diff options
author | Martin Wache <martin@debian.lan> | 2010-11-20 13:07:12 +0100 |
---|---|---|
committer | Martin Wache <martin@debian.lan> | 2010-11-20 13:07:12 +0100 |
commit | 350ebad826ece189072d19b2dc9224ffc8e4aced (patch) | |
tree | 6e0f68a954579f77cefe41c70d5cbe368f5cfcd0 | |
parent | ff37e7006cea3b14bb108c68d60a97fe15074369 (diff) | |
download | vdr-plugin-live-350ebad826ece189072d19b2dc9224ffc8e4aced.tar.gz vdr-plugin-live-350ebad826ece189072d19b2dc9224ffc8e4aced.tar.bz2 |
- some fixes and improvements to multischedule
-rw-r--r-- | css/styles.css | 70 | ||||
-rw-r--r-- | pages/menu.ecpp | 1 | ||||
-rw-r--r-- | pages/multischedule.ecpp | 231 | ||||
-rw-r--r-- | tools.cpp | 1 |
4 files changed, 243 insertions, 60 deletions
diff --git a/css/styles.css b/css/styles.css index 4fd23b1..35b2119 100644 --- a/css/styles.css +++ b/css/styles.css @@ -867,6 +867,76 @@ table.listing a { font-weight: bold; } +/* ################################## + # table schedule + # (this is used for the MultiSchedule) + ################################## +*/ + +table.mschedule { + padding: 0px; + margin: 0px; +} + +table.mschedule tr { + height: 12px; +} + +table.mschedule tr td.event { + background: transparent url(img/bg_line.png) bottom repeat-x; + border-bottom: 1px solid #C0C1DA; +} + +table.mschedule tr.odd td.time { + background-color: #D0D0ff; +} + +table.mschedule tr.even td.time { + background-color: #ffffff; +} + +table.mschedule tr.current_row td.time { + background-color: #ffB0B0; +} + +table.mschedule tr td.leftcol { + padding-left: 7px; + padding-right: 5px; +} + +table.mschedule div.content1 { + min-width: 20em; + max-width: 30em; +} + +table.mschedule div.tools1 { + float: right; +} + +table.mschedule div.start { + float: left; +} + +table.mschedule tr td div.title { + padding: 3px; + clear: both; +} + +table.mschedule tr td div.short { + clear: both; + overflow: hidden; +} + +table.mschedule tr td div.description { + overflow: hidden; + clear: both; +} + +table.mschedule a { + color: black; + font-weight: bold; +} + /* ############################## # Blue Background Thingy diff --git a/pages/menu.ecpp b/pages/menu.ecpp index dbcb862..5721e42 100644 --- a/pages/menu.ecpp +++ b/pages/menu.ecpp @@ -86,6 +86,7 @@ if (!component.empty()) { <div> <!-- inner --> <& menu.component current=("whats_on") &> <& menu.component current=("schedule") &> + <& menu.component current=("multischedule") &> <& menu.component current=("timers") &> <%cpp> if (LiveFeatures< features::epgsearch >().Recent()) { diff --git a/pages/multischedule.ecpp b/pages/multischedule.ecpp index ab97d9b..3d207ec 100644 --- a/pages/multischedule.ecpp +++ b/pages/multischedule.ecpp @@ -18,17 +18,19 @@ struct SchedEntry { string title; string short_description; string description; + string description_trunc; string start; string end; string day; string epgid; + bool truncated; int start_row; int row_count; }; </%pre> <%args> - int channel = -1; + int channel = 1; </%args> <%session scope="global"> bool logged_in(false); @@ -39,33 +41,10 @@ bool logged_in(false); <%include>page_init.eh</%include> <%cpp> if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); -</%cpp> -<%cpp> - pageTitle = trVDR("Schedule"); - - cSchedulesLock schedulesLock; - cSchedules const* schedules = cSchedules::Schedules( schedulesLock ); - - ReadLock channelsLock( Channels ); - if ( !channelsLock ) - throw HtmlError( tr("Couldn't aquire access to channels, please try again later.") ); - - // cChannel* Channel; (see %request above) - if ( channel > 0 ) { - Channel = Channels.GetByNumber( channel ); - } - else { - if (cDevice::CurrentChannel()) { - Channel = Channels.GetByNumber(cDevice::CurrentChannel()); - } - else { - Channel = Channels.Get( Channels.GetNextNormal( -1 ) ); - } - } - if ( Channel == 0 ) - throw HtmlError( tr("Couldn't find channel or no channels available. Maybe you mistyped your request?") ); - - cSchedule const* Schedule = schedules->GetSchedule( Channel ); +pageTitle = trVDR("Schedule"); + Channel = Channels.GetByNumber( channel ); + if (!Channel) + throw HtmlError( tr("Error didn't find the channel") ); </%cpp> <& pageelems.doc_type &> <html> @@ -76,32 +55,64 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); </head> <body> <& pageelems.logo &> - <& menu active=("multischedule") component=("schedule.channel_selection") &> + <& menu active=("multischedule") component=("multischedule.channel_selection") &> <div class="inhalt"> <%cpp> - if ( Schedule == 0 ) { -</%cpp> - <$ tr("No schedules available for this channel") $>. -<%cpp> - } - else { + + cSchedulesLock schedulesLock; + cSchedules const* schedules = cSchedules::Schedules( schedulesLock ); + + ReadLock channelsLock( Channels ); + if ( !channelsLock ) + throw HtmlError( tr("Couldn't aquire access to channels, please try again later.") ); +{ time_t now = time(NULL) - ::Setup.EPGLinger * 60; time_t sched_start = 3600 * (now / 3600); // start at a full hour // tChannelID channel_id(Channel->GetChannelID()); // int evntNr = 0; -#define MAX_CHANNELS 5 +#define MAX_CHANNELS 3 #define MAX_EVENTS 200 -#define MINUTES_PER_ROW 6 +#define MINUTES_PER_ROW 5 +#define CHARACTERS_PER_ROW 30 SchedEntry table[MAX_CHANNELS][MAX_EVENTS]; + int chan = 0; + int count[ MAX_CHANNELS ]; + string channel_names[ MAX_CHANNELS]; + for ( chan = 0; chan<MAX_CHANNELS; chan++) + { int prev_row = -1; - int count = 0; - for (const cEvent *Event = Schedule->Events()->First(); Event && count < MAX_EVENTS; + count[ chan ] = 0; + + Channel = Channels.GetByNumber( channel+chan ); + if ( ! Channel ) + continue; + if ( Channel->GroupSep() || Channel->Name() == '\0' ) + continue; + channel_names[ chan ] = Channel->Name(); + + cSchedule const* Schedule = schedules->GetSchedule( Channel ); + if ( ! Schedule ) + continue; + for (const cEvent *Event = Schedule->Events()->First(); Event && count[chan] < MAX_EVENTS; Event = Schedule->Events()->Next(Event)) { if (Event->EndTime() <= sched_start ) continue; EpgInfoPtr epgEvent = EpgEvents::CreateEpgInfo(Channel, Event); - SchedEntry &en=table[0][count]; + if ( prev_row < 0 && Event->StartTime() > sched_start + MINUTES_PER_ROW ) + { + // insert dummy event at start + SchedEntry &en=table[chan][count[chan]]; + int event_start_row = (Event->StartTime() - sched_start) / 60 / MINUTES_PER_ROW; + en.start_row = 0; + en.row_count = event_start_row; + // no title and no start time = dummy event + en.title = ""; + en.start = ""; + prev_row = en.start_row + en.row_count; + count[chan]++; + } + SchedEntry &en=table[chan][count[chan]]; en.title = epgEvent->Title(); en.short_description = epgEvent->ShortDescr(); @@ -113,31 +124,71 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); // string strEventID = lexical_cast<string>(Event->EventID(); en.start_row = prev_row > 0 ? prev_row : 0; - prev_row = en.start_row; int end_time = Schedule->Events()->Next(Event) ? Schedule->Events()->Next(Event)->StartTime() : Event->EndTime(); int next_event_start_row = (end_time - sched_start) / 60 / MINUTES_PER_ROW; en.row_count = next_event_start_row - en.start_row; - if ( en.row_count < 2 ) - en.row_count = 2; + if ( en.row_count < 1 ) + en.row_count = 1; prev_row = en.start_row + en.row_count; - count++; - }; + + // truncate description if too long + en.truncated=false; + en.description_trunc=StringWordTruncate( en.description, + CHARACTERS_PER_ROW*(en.row_count-2), + en.truncated ); + + + + count[chan]++; + }; + } </%cpp> - <table class="listing" cellspacing="0" cellpadding="0"> + <table class="mschedule" cellspacing="0" cellpadding="0"> <%cpp> time_t sched_end = sched_start + 60 * 60 * 12; // 12 hr int sched_end_row = ( sched_end - sched_start ) / 60 / MINUTES_PER_ROW; - int cur_event = 0; - for (int row = 0 ; row < sched_end_row; row++ ) + int cur_event[ MAX_CHANNELS ]; + for (int i=0;i<MAX_CHANNELS;i++) + cur_event[i]=0; +</%cpp> + <tr class=" topaligned "> + <td > <div class="boxheader"> <div><div><$ tr("Time") $></div></div> </div></td> + <td class="time spacer"> </td> +<%cpp> + for ( int channel = 0; channel< MAX_CHANNELS ; channel++) + { +</%cpp> + <td> <div class="boxheader"> <div> <div><$ channel_names[channel] $> </div></div> </div></td> + <td class="time spacer"> </td> +<%cpp> + } +</%cpp> + </tr> +<%cpp> + bool odd=true; + for (int row = 0 ; row < sched_end_row; row++ ) { + int minutes= ( (sched_start + row * 60 * MINUTES_PER_ROW ) % 3600 ) / 60; + string row_class; + if ( minutes == 0 ) + { + // full hour, swap odd/even + odd = !odd; + }; + if ( (sched_start + row * 60 * MINUTES_PER_ROW ) <= now && + (sched_start + (row+1) * 60 * MINUTES_PER_ROW ) > now ) + { + row_class +=" current_row "; + } + row_class += odd ? " odd " : " even "; </%cpp> - <tr class=" topaligned "> - <td> + <tr class=" <$ row_class $>"> + <td class=" time leftcol "> <%cpp> - if ( (sched_start + row * 60 * MINUTES_PER_ROW ) % 3600 == 0 ) + if ( minutes == 0 ) { </%cpp> <$ FormatDateTime( tr("%I:%M %p"), sched_start + row * 60 * MINUTES_PER_ROW ) $> @@ -148,20 +199,80 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); </%cpp> <%cpp> - } + } </%cpp> </td> <%cpp> - if ( table[0][cur_event].start_row == row ) - { - SchedEntry &en=table[0][cur_event]; - bool truncated = false; + for ( int channel = 0; channel< MAX_CHANNELS ; channel++) + { + // output spacer column </%cpp> - <td class="topaligned leftcol rightcol" rowspan="<$ en.row_count $>"> - <div class="more withmargin"><a <& tooltip.hint text=(StringEscapeAndBreak(StringWordTruncate(en.description, 300, truncated)) + "<br />" + tr("Click to view details.")) &>><span class="title"><$ en.title $></span><br /><span class="short"><$ en.short_description.empty() ? " " : en.short_description $></span></a><$ en.start + "-" + en.end $></div></td> + <td class = " time spacer " > </td> <%cpp> - cur_event++; - } + if ( table[channel][cur_event[channel]].start_row != row ) + // no new event in this channel, skip it + continue; + + SchedEntry &en=table[channel][cur_event[channel]]; + if (en.title.empty() && en.start.empty() ) + { + // empty dummy event +</%cpp> + <td class="event topaligned leftcol rightcol" rowspan="<$ en.row_count $>"> + </td> +<%cpp> + cur_event[channel]++; + continue; + + } + // output an event cell +</%cpp> + <td class="event topaligned leftcol rightcol" rowspan="<$ en.row_count $>"> + <div class=" content1 " > + <div class=" tools1 " > + <& pageelems.event_timer epgid=(en.epgid) &> +<%cpp> + if (LiveFeatures<features::epgsearch>().Recent() ) { +</%cpp> + <a href="searchresults.html?searchplain=<$ StringUrlEncode(en.title) $>"><img src="<$ LiveSetup().GetThemedLink("img", "search.png") $>" alt="" <& tooltip.hint text=(tr("Search for repeats.")) &>></img></a> +<%cpp> + } else { + </%cpp><img src="img/transparent.png" width="16" height="16"><%cpp> + } +</%cpp> + <& pageelems.imdb_info_href title=(en.title) &> + </div><div class= "start withmargin"><$ en.start $></div> + <div class="title withmargin"><a <& tooltip.hint text=(StringEscapeAndBreak(tr("Click to view details."))) &><& tooltip.display domId=en.epgid &>><$ en.title $></a></div> +<%cpp> + if ( en.row_count>2 && !en.short_description.empty() ) + { +</%cpp> + <div class="short withmargin"><$ en.short_description.empty() ? " " : en.short_description $></div> +<%cpp> + } + if ( en.row_count>3 && ! en.description_trunc.empty() ) + { +</%cpp> + <div class="description withmargin"><$en.description_trunc$>... +<%cpp> + if ( en.truncated ) + { +</%cpp> + <a <& tooltip.hint text=(StringEscapeAndBreak(tr("Click to view details."))) &><& tooltip.display domId=en.epgid &>> <$ tr("more") $></a> +<%cpp> + } +</%cpp> + </div></div> +<%cpp> + + } +</%cpp> + </div> + </td> +<%cpp> + // move to next event for this channel + cur_event[channel]++; + } </%cpp> </tr> <%cpp> @@ -114,6 +114,7 @@ namespace vdrlive { { if (input.length() <= maxLen) { + truncated = false; return input; } truncated = true; |