[vlc-commits] Qt: rework EPG
Francois Cartegnie
git at videolan.org
Fri Dec 16 14:43:12 CET 2016
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed Dec 14 19:45:01 2016 +0100| [ab494fd208e74112324254a2f78970c81d7744db] | committer: Francois Cartegnie
Qt: rework EPG
Less loops and simplified structs/updates
Also now redisplays recorded epg.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=ab494fd208e74112324254a2f78970c81d7744db
---
modules/gui/qt/Makefile.am | 2 +
modules/gui/qt/components/epg/EPGChannels.cpp | 18 +-
modules/gui/qt/components/epg/EPGChannels.hpp | 7 +-
modules/gui/qt/components/epg/EPGItem.cpp | 35 +--
modules/gui/qt/components/epg/EPGItem.hpp | 16 +-
modules/gui/qt/components/epg/EPGProgram.cpp | 135 ++++++++++++
modules/gui/qt/components/epg/EPGProgram.hpp | 65 ++++++
modules/gui/qt/components/epg/EPGRuler.cpp | 24 +-
modules/gui/qt/components/epg/EPGRuler.hpp | 3 +-
modules/gui/qt/components/epg/EPGView.cpp | 302 +++++++-------------------
modules/gui/qt/components/epg/EPGView.hpp | 32 ++-
modules/gui/qt/components/epg/EPGWidget.cpp | 28 +--
12 files changed, 355 insertions(+), 312 deletions(-)
diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index 799b193..bf3d98b 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -83,6 +83,7 @@ libqt_plugin_la_SOURCES = \
components/controller_widget.cpp components/controller_widget.hpp \
components/epg/EPGChannels.cpp components/epg/EPGChannels.hpp \
components/epg/EPGItem.cpp components/epg/EPGItem.hpp \
+ components/epg/EPGProgram.cpp components/epg/EPGProgram.hpp \
components/epg/EPGRuler.cpp components/epg/EPGRuler.hpp \
components/epg/EPGView.cpp components/epg/EPGView.hpp \
components/epg/EPGWidget.cpp components/epg/EPGWidget.hpp \
@@ -180,6 +181,7 @@ nodist_libqt_plugin_la_SOURCES = \
components/controller.moc.cpp \
components/controller_widget.moc.cpp \
components/epg/EPGChannels.moc.cpp \
+ components/epg/EPGProgram.moc.cpp \
components/epg/EPGRuler.moc.cpp \
components/epg/EPGView.moc.cpp \
components/epg/EPGWidget.moc.cpp \
diff --git a/modules/gui/qt/components/epg/EPGChannels.cpp b/modules/gui/qt/components/epg/EPGChannels.cpp
index 1266a29..bb12729 100644
--- a/modules/gui/qt/components/epg/EPGChannels.cpp
+++ b/modules/gui/qt/components/epg/EPGChannels.cpp
@@ -25,11 +25,13 @@
#include <vlc_epg.h>
#include "EPGChannels.hpp"
+#include "EPGProgram.hpp"
#include "EPGView.hpp"
#include <QPainter>
#include <QFont>
#include <QPaintEvent>
+#include <QtAlgorithms>
EPGChannels::EPGChannels( QWidget *parent, EPGView *m_epgView )
: QWidget( parent ), m_epgView( m_epgView ), m_offset( 0 )
@@ -43,19 +45,20 @@ void EPGChannels::setOffset( int offset )
update();
}
-void EPGChannels::addChannel( QString channelName )
+void EPGChannels::addProgram( const EPGProgram *program )
{
- if ( !channelList.contains( channelName ) )
+ if ( !programsList.contains( program ) )
{
- channelList << channelName;
- channelList.sort();
+ programsList << program;
+ qSort(programsList.begin(), programsList.end(), EPGProgram::lessThan);
update();
}
}
-void EPGChannels::removeChannel( QString channelName )
+void EPGChannels::reset()
{
- if ( channelList.removeOne( channelName ) ) update();
+ programsList.clear();
+ update();
}
void EPGChannels::paintEvent( QPaintEvent *event )
@@ -68,8 +71,9 @@ void EPGChannels::paintEvent( QPaintEvent *event )
p.drawLine( 0, 0, width() - 1, 0 );
unsigned int i=0;
- foreach( QString text, channelList )
+ foreach( const EPGProgram *program, programsList )
{
+ QString text = program->getName();
/* try to remove the " [Program xxx]" end */
int i_idx_channel = text.lastIndexOf(" [");
if (i_idx_channel > 0)
diff --git a/modules/gui/qt/components/epg/EPGChannels.hpp b/modules/gui/qt/components/epg/EPGChannels.hpp
index a0143d8..b4fee69 100644
--- a/modules/gui/qt/components/epg/EPGChannels.hpp
+++ b/modules/gui/qt/components/epg/EPGChannels.hpp
@@ -28,6 +28,7 @@
#include <QWidget>
class EPGView;
+class EPGProgram;
class EPGChannels : public QWidget
{
@@ -37,8 +38,8 @@ public:
public slots:
void setOffset( int offset );
- void addChannel( QString );
- void removeChannel( QString );
+ void addProgram( const EPGProgram * );
+ void reset();
protected:
void paintEvent( QPaintEvent *event ) Q_DECL_OVERRIDE;
@@ -46,7 +47,7 @@ protected:
private:
EPGView *m_epgView;
int m_offset;
- QStringList channelList;
+ QList<const EPGProgram *> programsList;
};
#endif // EPGCHANNELS_HPP
diff --git a/modules/gui/qt/components/epg/EPGItem.cpp b/modules/gui/qt/components/epg/EPGItem.cpp
index 3d83928..2ba01e0 100644
--- a/modules/gui/qt/components/epg/EPGItem.cpp
+++ b/modules/gui/qt/components/epg/EPGItem.cpp
@@ -35,11 +35,13 @@
#include "qt.hpp"
-EPGItem::EPGItem( const vlc_epg_event_t *data, EPGView *view )
- : m_view( view )
+EPGItem::EPGItem( const vlc_epg_event_t *data, EPGView *view, const EPGProgram *prog )
+ : QGraphicsItem()
{
+ m_view = view;
+ program = prog;
+ m_id = data->i_id;
setData( data );
- m_current = false;
m_boundingRect.setHeight( TRACKS_HEIGHT );
setFlags( QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
setAcceptHoverEvents( true );
@@ -67,8 +69,8 @@ void EPGItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *option,
QLinearGradient gradient( mapped.topLeft(), mapped.bottomLeft() );
- bool b_simultaneous = playsAt( m_view->baseTime() );
- if ( m_current || b_simultaneous )
+ bool b_simultaneous = m_view->liveTime().isValid() && playsAt( m_view->liveTime() );
+ if ( program->getCurrent() == this || b_simultaneous )
gradientColor.setRgb( 244, 125, 0 , b_simultaneous ? 192 : 255 );
else
gradientColor.setRgb( 201, 217, 242 );
@@ -139,15 +141,14 @@ QDateTime EPGItem::end() const
return QDateTime( m_start ).addSecs( m_duration );
}
-int EPGItem::duration() const
+uint32_t EPGItem::duration() const
{
return m_duration;
}
-void EPGItem::setRow( unsigned int i_row_ )
+uint16_t EPGItem::eventID() const
{
- i_row = i_row_;
- updatePos();
+ return m_id;
}
bool EPGItem::setData( const vlc_epg_event_t *data )
@@ -171,16 +172,12 @@ bool EPGItem::setData( const vlc_epg_event_t *data )
setDuration( data->i_duration );
setRating( data->i_rating );
update();
+ updatePos();
return true;
}
return false;
}
-void EPGItem::setCurrent( bool b_current )
-{
- m_current = b_current;
-}
-
bool EPGItem::endsBefore( const QDateTime &ref ) const
{
return m_start.addSecs( m_duration ) < ref;
@@ -191,7 +188,7 @@ bool EPGItem::playsAt( const QDateTime & ref ) const
return (m_start <= ref) && !endsBefore( ref );
}
-void EPGItem::setDuration( int duration )
+void EPGItem::setDuration( uint32_t duration )
{
m_duration = duration;
m_boundingRect.setWidth( duration );
@@ -215,8 +212,12 @@ QString EPGItem::description() const
void EPGItem::updatePos()
{
- int x = m_view->startTime().secsTo( m_start );
- setPos( x, i_row * TRACKS_HEIGHT );
+ QDateTime overallmin = m_view->startTime();
+ if( overallmin.isValid() )
+ {
+ int x = m_view->startTime().secsTo( m_start );
+ setPos( x, program->getPosition() * TRACKS_HEIGHT );
+ }
}
void EPGItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * event )
diff --git a/modules/gui/qt/components/epg/EPGItem.hpp b/modules/gui/qt/components/epg/EPGItem.hpp
index 938ecdc..92d0c8c 100644
--- a/modules/gui/qt/components/epg/EPGItem.hpp
+++ b/modules/gui/qt/components/epg/EPGItem.hpp
@@ -33,11 +33,12 @@
class QPainter;
class QString;
class EPGView;
+class EPGProgram;
class EPGItem : public QGraphicsItem
{
public:
- EPGItem( const vlc_epg_event_t *data, EPGView *view );
+ EPGItem( const vlc_epg_event_t *data, EPGView *view, const EPGProgram * );
QRectF boundingRect() const Q_DECL_OVERRIDE;
void paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0 ) Q_DECL_OVERRIDE;
@@ -45,14 +46,13 @@ public:
const QDateTime& start() const;
QDateTime end() const;
- int duration() const;
+ uint32_t duration() const;
+ uint16_t eventID() const;
const QString& name() const { return m_name; }
QString description() const;
int rating() const { return m_rating; }
bool setData( const vlc_epg_event_t * );
- void setRow( unsigned int );
- void setCurrent( bool );
- void setDuration( int duration );
+ void setDuration( uint32_t duration );
void setRating( uint8_t i_rating );
void updatePos();
bool endsBefore( const QDateTime & ) const;
@@ -64,16 +64,16 @@ protected:
void hoverLeaveEvent ( QGraphicsSceneHoverEvent * ) Q_DECL_OVERRIDE;
private:
+ const EPGProgram *program;
EPGView *m_view;
QRectF m_boundingRect;
- unsigned int i_row;
QDateTime m_start;
- int m_duration;
+ uint32_t m_duration;
+ uint16_t m_id;
QString m_name;
QString m_description;
QString m_shortDescription;
- bool m_current;
uint8_t m_rating;
};
diff --git a/modules/gui/qt/components/epg/EPGProgram.cpp b/modules/gui/qt/components/epg/EPGProgram.cpp
new file mode 100644
index 0000000..3309cc0
--- /dev/null
+++ b/modules/gui/qt/components/epg/EPGProgram.cpp
@@ -0,0 +1,135 @@
+/*****************************************************************************
+ * EPGProgram.cpp:
+ ****************************************************************************
+ * Copyright © 2016 VideoLAN Authors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#include "EPGProgram.hpp"
+#include "EPGItem.hpp"
+#include "EPGView.hpp"
+
+#include <QtAlgorithms>
+
+EPGProgram::EPGProgram( EPGView *view_, const vlc_epg_t *p_epg ) : QObject( view_ )
+{
+ name = QString(p_epg->psz_name);
+ id = p_epg->i_id;
+ sourceid = p_epg->i_source_id;
+ view = view_;
+ pos = 0;
+ current = NULL;
+}
+
+EPGProgram::~EPGProgram()
+{
+ qDeleteAll(eventsbyid);
+ eventsbytime.clear();
+}
+
+bool EPGProgram::lessThan( const EPGProgram *a, const EPGProgram *b )
+{
+ return a->pos < b->pos;
+}
+
+size_t EPGProgram::getPosition() const
+{
+ return pos;
+}
+
+const EPGItem * EPGProgram::getCurrent() const
+{
+ return current;
+}
+
+const QString & EPGProgram::getName() const
+{
+ return name;
+}
+
+void EPGProgram::setPosition( size_t i )
+{
+ pos = i;
+}
+
+void EPGProgram::pruneEvents( const QDateTime &date )
+{
+ QMap<QDateTime, const EPGItem *>::iterator it = eventsbytime.begin();
+ for( ; it != eventsbytime.end(); )
+ {
+ const EPGItem *item = *it;
+ if( item->endsBefore( date ) ) /* Expired item ? */
+ {
+ EPGItem *modifiableitem = eventsbyid.take( item->eventID() );
+ view->scene()->removeItem( modifiableitem );
+ delete modifiableitem;
+ it = eventsbytime.erase( it );
+ }
+ else break;
+ }
+}
+
+void EPGProgram::updateEventPos()
+{
+ foreach( EPGItem *item, eventsbyid )
+ item->updatePos();
+}
+
+void EPGProgram::updateEvents( const vlc_epg_event_t * const * pp_events, size_t i_events,
+ const vlc_epg_event_t *p_current, QDateTime *mindate )
+{
+ for( size_t i=0; i<i_events; i++ )
+ {
+ const vlc_epg_event_t *p_event = pp_events[i];
+ QDateTime eventStart = QDateTime::fromTime_t( p_event->i_start );
+ if( !mindate->isValid() || eventStart < *mindate )
+ *mindate = eventStart;
+
+ EPGItem *epgItem = NULL;
+ QHash<uint32_t, EPGItem *>::iterator it = eventsbyid.find( p_event->i_id );
+ if ( it != eventsbyid.end() )
+ {
+ epgItem = *it;
+
+ /* Update our existing programs */
+ if( eventStart != epgItem->start() )
+ {
+ eventsbytime.remove( epgItem->start() );
+ eventsbytime.insert( eventStart, epgItem );
+ }
+
+ epgItem->setData( p_event ); /* updates our entry */
+ }
+ else if( !eventsbytime.contains( eventStart ) /* !Inconsistency */ )
+ {
+ /* Insert a new program entry */
+ epgItem = new EPGItem( p_event, view, this );
+
+ /* Effectively insert our new program */
+ eventsbyid.insert( p_event->i_id, epgItem );
+ eventsbytime.insert( eventStart, epgItem );
+
+ view->scene()->addItem( epgItem );
+
+ /* First Insert, needs to focus by default then */
+ if( !view->hasFocus() )
+ view->focusItem( epgItem );
+ }
+
+ if( p_current == p_event )
+ current = epgItem;
+ }
+}
+
diff --git a/modules/gui/qt/components/epg/EPGProgram.hpp b/modules/gui/qt/components/epg/EPGProgram.hpp
new file mode 100644
index 0000000..9e7aa1d
--- /dev/null
+++ b/modules/gui/qt/components/epg/EPGProgram.hpp
@@ -0,0 +1,65 @@
+/*****************************************************************************
+ * EPGProgram.hpp:
+ ****************************************************************************
+ * Copyright © 2016 VideoLAN Authors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifndef EPGPROGRAM_HPP
+#define EPGPROGRAM_HPP
+
+#include "qt.hpp"
+
+#include <vlc_epg.h>
+#include <QObject>
+#include <QMap>
+#include <QHash>
+#include <QDateTime>
+
+class EPGView;
+class EPGItem;
+
+class EPGProgram : public QObject
+{
+ Q_OBJECT
+
+ public:
+ EPGProgram( EPGView *, const vlc_epg_t * );
+ virtual ~EPGProgram();
+
+ void pruneEvents( const QDateTime & );
+ void updateEvents( const vlc_epg_event_t * const *, size_t, const vlc_epg_event_t *,
+ QDateTime * );
+ void updateEventPos();
+ size_t getPosition() const;
+ void setPosition( size_t );
+ const EPGItem * getCurrent() const;
+ const QString & getName() const;
+ static bool lessThan( const EPGProgram *, const EPGProgram * );
+
+ QHash<uint32_t, EPGItem *> eventsbyid;
+ QMap<QDateTime, const EPGItem *> eventsbytime;
+
+ private:
+ const EPGItem *current;
+ EPGView *view;
+ size_t pos;
+
+ QString name;
+ uint32_t id;
+ uint16_t sourceid;
+};
+
+#endif // EPGPROGRAM_HPP
diff --git a/modules/gui/qt/components/epg/EPGRuler.cpp b/modules/gui/qt/components/epg/EPGRuler.cpp
index bd7ccac..46a87cc 100644
--- a/modules/gui/qt/components/epg/EPGRuler.cpp
+++ b/modules/gui/qt/components/epg/EPGRuler.cpp
@@ -47,15 +47,17 @@ void EPGRuler::setScale( double scale )
update();
}
-void EPGRuler::setStartTime( const QDateTime& startTime )
+void EPGRuler::setRange( const QDateTime& startTime, const QDateTime& endTime )
{
- m_startTime = startTime;
- update();
-}
-
-void EPGRuler::setDuration( int duration )
-{
- m_duration = duration;
+ if( !startTime.isValid() || !endTime.isValid() )
+ {
+ m_startTime = QDateTime();
+ }
+ else
+ {
+ m_startTime = startTime;
+ m_duration = startTime.secsTo( endTime );
+ }
update();
}
@@ -73,6 +75,12 @@ void EPGRuler::paintEvent( QPaintEvent *event )
const int spacing = m_scale * 3600;
QPainter p( this );
+ if( !m_startTime.isValid() )
+ {
+ QWidget::paintEvent( event );
+ return;
+ }
+
QDateTime localStartTime;
localStartTime = m_startTime.addSecs( m_offset / m_scale );
diff --git a/modules/gui/qt/components/epg/EPGRuler.hpp b/modules/gui/qt/components/epg/EPGRuler.hpp
index ddd7873..1a8021b 100644
--- a/modules/gui/qt/components/epg/EPGRuler.hpp
+++ b/modules/gui/qt/components/epg/EPGRuler.hpp
@@ -39,8 +39,7 @@ public:
public slots:
void setScale( double scale );
- void setStartTime( const QDateTime& startTime );
- void setDuration( int duration );
+ void setRange( const QDateTime&, const QDateTime& );
void setOffset( int offset );
protected:
diff --git a/modules/gui/qt/components/epg/EPGView.cpp b/modules/gui/qt/components/epg/EPGView.cpp
index 5835e01..ea5b3ac 100644
--- a/modules/gui/qt/components/epg/EPGView.cpp
+++ b/modules/gui/qt/components/epg/EPGView.cpp
@@ -40,6 +40,12 @@ void EPGGraphicsScene::drawBackground( QPainter *painter, const QRectF &rect)
{
EPGView *epgView = qobject_cast<EPGView *>(parent());
+ if( !epgView->startTime().isValid() )
+ {
+ QGraphicsScene::drawBackground( painter, rect );
+ return;
+ }
+
/* day change */
QDateTime rectstarttime = epgView->startTime().addSecs( rect.left() );
QDateTime nextdaylimit = QDateTime( rectstarttime.date() );
@@ -63,9 +69,12 @@ void EPGGraphicsScene::drawBackground( QPainter *painter, const QRectF &rect)
painter->drawLine( QLineF( rect.left(), y, rect.right(), y ) );
/* current hour line */
- int x = epgView->startTime().secsTo( epgView->baseTime() );
- painter->setPen( QPen( QColor( 255, 192, 192 ) ) );
- painter->drawLine( QLineF( x, rect.top(), x, rect.bottom() ) );
+ if( epgView->liveTime().isValid() )
+ {
+ int x = epgView->startTime().secsTo( epgView->liveTime() );
+ painter->setPen( QPen( QColor( 255, 192, 192 ) ) );
+ painter->drawLine( QLineF( x, rect.top(), x, rect.bottom() ) );
+ }
}
EPGView::EPGView( QWidget *parent ) : QGraphicsView( parent )
@@ -74,7 +83,8 @@ EPGView::EPGView( QWidget *parent ) : QGraphicsView( parent )
setFrameStyle( QFrame::Box );
setAlignment( Qt::AlignLeft | Qt::AlignTop );
- m_startTime = QDateTime::currentDateTime();
+ m_startTime = QDateTime();
+ m_maxTime = m_startTime;
EPGGraphicsScene *EPGscene = new EPGGraphicsScene( this );
@@ -89,276 +99,114 @@ void EPGView::setScale( double scaleFactor )
setMatrix( matrix );
}
-void EPGView::updateStartTime()
-{
- mutex.lock();
- foreach( EPGEventByTimeQMap *epgItemByTime, epgitemsByChannel.values() )
- {
- foreach( EPGItem *epgItem, epgItemByTime->values() )
- {
- epgItem->updatePos();
- }
- }
- mutex.unlock();
-}
-
-void EPGView::updateChannels()
-{
- /* Make sure our items goes to the correct row */
- unsigned int channelIndex = 0;
- mutex.lock();
- foreach( EPGEventByTimeQMap *epgItemByTime, epgitemsByChannel.values() )
- {
- foreach( EPGItem *epgItem, epgItemByTime->values() )
- epgItem->setRow( channelIndex );
- channelIndex++;
- }
- mutex.unlock();
-}
-
const QDateTime& EPGView::startTime() const
{
return m_startTime;
}
-const QDateTime& EPGView::baseTime() const
+QDateTime EPGView::liveTime() const
{
- return m_baseTime;
+ if( m_startTime.isValid() && m_maxTime.isValid() )
+ {
+ QDateTime now = QDateTime::currentDateTime();
+ if( now >= m_startTime && now <= m_maxTime )
+ return now;
+ }
+ return QDateTime();
}
bool EPGView::hasValidData() const
{
- return !epgitemsByChannel.isEmpty();
+ return !programs.isEmpty();
}
-bool EPGView::addEPGEvents( vlc_epg_event_t **pp_events, size_t i_events,
- QString channelName, const vlc_epg_event_t *p_current )
+bool EPGView::updateEPG( const vlc_epg_t * const *pp_epg, size_t i_epg )
{
- /* Init our nested map if required */
- EPGEventByTimeQMap *epgItemByTime;
- EPGItem *epgItem;
- bool b_refresh_channels = false;
-
- if( i_events < 1 )
- return false;
+ m_updtMinTime = QDateTime();
- mutex.lock();
- /* First check and create channel if missing */
- if ( !epgitemsByChannel.contains( channelName ) )
+ for ( size_t i = 0; i < i_epg; ++i )
{
- epgItemByTime = new EPGEventByTimeQMap();
- epgitemsByChannel.insert( channelName, epgItemByTime );
- emit channelAdded( channelName );
- b_refresh_channels = true;
- } else {
- epgItemByTime = epgitemsByChannel.value( channelName );
- }
+ const vlc_epg_t *p_epg = pp_epg[i];
- QDateTime rangeStart = QDateTime::fromTime_t( pp_events[0]->i_start );
- QDateTime rangeEnd = QDateTime::fromTime_t( pp_events[i_events - 1]->i_start );
- rangeEnd.addSecs( pp_events[i_events - 1]->i_duration );
+ EPGProgram *program;
- EPGEventByTimeQMap::iterator itRangeBegin =
- epgItemByTime->lowerBound( rangeStart );
- EPGEventByTimeQMap::iterator itRangeEnd =
- epgItemByTime->upperBound( rangeEnd );
-
- EPGEventByTimeQMap::iterator it = itRangeBegin;
- for( size_t i=0; i<i_events; i++ )
- {
- const vlc_epg_event_t *p_event = pp_events[i];
-
- for( ; it != itRangeEnd; ++it )
+ QHash<uint16_t, EPGProgram*>::iterator it = programs.find( p_epg->i_source_id );
+ if( it != programs.end() )
{
- EPGItem *epgItem = *it;
- QDateTime eventStart = QDateTime::fromTime_t( p_event->i_start );
- if( epgItem->start() < eventStart )
- {
- if( it != itRangeBegin ||
- epgItem->start().addSecs( epgItem->duration() ) > eventStart )
- delete *it++;
- }
- else if( epgItem->start() > eventStart )
- {
- break;
- }
+ program = *it;
}
- }
-
- mutex.unlock();
-
-
- bool b_added = false;
- for( size_t i=0; i<i_events; i++ )
- {
- const vlc_epg_event_t *p_event = pp_events[i];
-
- QDateTime eventStart = QDateTime::fromTime_t( p_event->i_start );
- if ( eventStart.addSecs( p_event->i_duration ) < m_baseTime )
- continue; /* EPG feed sent expired item */
- if ( eventStart < m_startTime )
- {
- m_startTime = eventStart;
- emit startTimeChanged( m_startTime );
- }
-
- mutex.lock();
-
- if ( epgItemByTime->contains( eventStart ) )
+ else
{
- /* Update our existing programs */
- epgItem = epgItemByTime->value( eventStart );
- epgItem->setCurrent( ( p_event == p_current ) );
- epgItem->setData( p_event ); /* updates our entry */
- } else {
- /* Insert a new program entry */
- epgItem = new EPGItem( p_event, this );
- /* Effectively insert our new program */
- epgItem->setCurrent( ( p_event == p_current ) );
- epgItemByTime->insert( eventStart, epgItem );
- scene()->addItem( epgItem );
- /* update only our row (without calling the updatechannels()) */
- epgItem->setRow( epgitemsByChannel.keys().indexOf( channelName ) );
-
- /* First Insert, needs to focus by default then */
- if ( epgitemsByChannel.keys().count() == 1 &&
- epgItemByTime->count() == 1 )
- focusItem( epgItem );
- b_added = true;
+ program = new EPGProgram( this, p_epg );
+ program->setPosition( programs.count() );
+ programs.insert( p_epg->i_source_id, program );
+ emit programAdded( program );
}
-
- mutex.unlock();
+ program->updateEvents( p_epg->pp_event, p_epg->i_event, p_epg->p_current, &m_updtMinTime );
}
+ if( !m_startTime.isValid() )
+ m_startTime = m_updtMinTime;
- /* Update rows on each item */
- if ( b_refresh_channels ) updateChannels();
-
- return b_added;
-}
-
-void EPGView::removeEPGEvent( vlc_epg_event_t *eventdata, QString channelName )
-{
- EPGEventByTimeQMap *epgItemByTime;
- QDateTime eventStart = QDateTime::fromTime_t( eventdata->i_start );
- EPGItem *epgItem;
- bool b_update_channels = false;
-
- mutex.lock();
- if ( epgitemsByChannel.contains( channelName ) )
- {
- epgItemByTime = epgitemsByChannel.value( channelName );
-
- if ( epgItemByTime->contains( eventStart ) )
- { /* delete our EPGItem */
- epgItem = epgItemByTime->value( eventStart );
- epgItemByTime->remove( eventStart );
- scene()->removeItem( epgItem );
- delete epgItem;
- }
-
- if ( epgItemByTime->keys().isEmpty() )
- { /* Now unused channel */
- epgitemsByChannel.remove( channelName );
- delete epgItemByTime;
- emit channelRemoved( channelName );
- b_update_channels = true;
- }
- }
- mutex.unlock();
-
- if ( b_update_channels ) updateChannels();
+ return true;
}
void EPGView::reset()
{
/* clean our items storage and remove them from the scene */
- EPGEventByTimeQMap *epgItemByTime;
- EPGItem *epgItem;
- mutex.lock();
- foreach( const QString &channelName, epgitemsByChannel.keys() )
- {
- epgItemByTime = epgitemsByChannel[ channelName ];
- foreach( const QDateTime &key, epgItemByTime->keys() )
- {
- epgItem = epgItemByTime->value( key );
- scene()->removeItem( epgItem );
- epgItemByTime->remove( key );
- delete epgItem;
- }
- epgitemsByChannel.remove( channelName );
- delete epgItemByTime;
- emit channelRemoved( channelName ); /* notify others */
- }
- mutex.unlock();
+ qDeleteAll(programs.values());
+ programs.clear();
+ m_startTime = m_maxTime = QDateTime();
}
-void EPGView::cleanup()
+void EPGView::walkItems( bool b_cleanup )
{
- /* remove expired items and clear their current flag */
- EPGEventByTimeQMap *epgItemByTime;
- EPGItem *epgItem;
- m_baseTime = QDateTime::currentDateTime();
- QDateTime lowestTime = m_baseTime;
- bool b_timechanged = false;
- bool b_update_channels = false;
-
- mutex.lock();
- foreach( const QString &channelName, epgitemsByChannel.keys() )
+ m_updtMinTime = m_startTime;
+ QDateTime maxTime;
+ bool b_rangechanged = false;
+
+ foreach( EPGProgram *program, programs )
{
- epgItemByTime = epgitemsByChannel[ channelName ];
- foreach( const QDateTime &key, epgItemByTime->keys() )
+ /* remove expired items and clear their current flag */
+ if( b_cleanup && m_updtMinTime.isValid() )
+ program->pruneEvents( m_updtMinTime );
+
+ if( !program->eventsbytime.isEmpty() )
{
- epgItem = epgItemByTime->value( key );
- if ( epgItem->endsBefore( baseTime() ) ) /* Expired item ? */
+ const EPGItem *last = program->eventsbytime.last();
+ if( !maxTime.isValid() ||
+ last->start().addSecs( last->duration() ) > maxTime )
{
- scene()->removeItem( epgItem );
- epgItemByTime->remove( key );
- delete epgItem;
- } else {
- epgItem->setCurrent( false ); /* if stream doesn't update */
- if ( lowestTime > epgItem->start() )
- {
- lowestTime = epgItem->start(); /* update our reference */
- b_timechanged = true;
- }
+ maxTime = last->start().addSecs( last->duration() );
}
}
-
- if ( epgItemByTime->keys().isEmpty() )
- { /* Now unused channel */
- epgitemsByChannel.remove( channelName );
- delete epgItemByTime;
- emit channelRemoved( channelName );
- b_update_channels = true;
- }
}
- mutex.unlock();
- if ( b_timechanged )
+ if( m_startTime.isValid() && m_startTime != m_updtMinTime )
+ b_rangechanged = m_updtMinTime.isValid();
+
+ if( maxTime.isValid() && m_maxTime != maxTime )
+ b_rangechanged |= m_updtMinTime.isValid();
+
+ m_startTime = m_updtMinTime;
+ m_maxTime = maxTime;
+
+ if ( b_rangechanged )
{
- m_startTime = lowestTime;
- emit startTimeChanged( m_startTime );
+ foreach( EPGProgram *program, programs )
+ program->updateEventPos();
+ emit rangeChanged( m_startTime, m_maxTime );
}
-
- if ( b_update_channels ) updateChannels();
}
-EPGView::~EPGView()
+void EPGView::cleanup()
{
- reset();
+ walkItems( true );
}
-void EPGView::updateDuration()
+EPGView::~EPGView()
{
- QDateTime maxItemTime;
- mutex.lock();
- foreach( EPGEventByTimeQMap *epgItemByTime, epgitemsByChannel.values() )
- foreach( EPGItem *epgItem, epgItemByTime->values() )
- if ( epgItem->end() > maxItemTime ) maxItemTime = epgItem->end();
- mutex.unlock();
- m_duration = m_startTime.secsTo( maxItemTime );
- emit durationChanged( m_duration );
+ reset();
}
void EPGView::focusItem( EPGItem *epgItem )
diff --git a/modules/gui/qt/components/epg/EPGView.hpp b/modules/gui/qt/components/epg/EPGView.hpp
index c74413c..114e973 100644
--- a/modules/gui/qt/components/epg/EPGView.hpp
+++ b/modules/gui/qt/components/epg/EPGView.hpp
@@ -26,22 +26,20 @@
#include "qt.hpp"
+#include "EPGProgram.hpp"
+
#include <vlc_epg.h>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QList>
-#include <QMap>
-#include <QMutex>
+#include <QHash>
#include <QDateTime>
class EPGItem;
#define TRACKS_HEIGHT 60
-typedef QMap<QDateTime, EPGItem *> EPGEventByTimeQMap;
-typedef QMap<QString, EPGEventByTimeQMap* > EPGTimeMapByChannelQMap;
-
class EPGGraphicsScene : public QGraphicsScene
{
Q_OBJECT
@@ -61,36 +59,32 @@ public:
void setScale( double scaleFactor );
- void updateStartTime();
const QDateTime& startTime() const;
- const QDateTime& baseTime() const;
+ QDateTime liveTime() const;
- bool addEPGEvents( vlc_epg_event_t **, size_t, QString, const vlc_epg_event_t * );
- void removeEPGEvent( vlc_epg_event_t*, QString );
- void updateDuration();
+ bool updateEPG( const vlc_epg_t * const *, size_t );
void reset();
void cleanup();
bool hasValidData() const;
signals:
- void startTimeChanged( const QDateTime& startTime );
- void durationChanged( int seconds );
+ void rangeChanged( const QDateTime&, const QDateTime& );
void itemFocused( EPGItem * );
- void channelAdded( QString );
- void channelRemoved( QString );
-protected:
+ void programAdded( const EPGProgram * );
+protected:
+ void walkItems( bool );
QDateTime m_startTime;
- QDateTime m_baseTime;
+ QDateTime m_maxTime;
+ QDateTime m_updtMinTime; /* >= startTime before pruning */
int m_scaleFactor;
int m_duration;
public slots:
void focusItem( EPGItem * );
+
private:
- EPGTimeMapByChannelQMap epgitemsByChannel;
- void updateChannels();
- QMutex mutex;
+ QHash<uint16_t, EPGProgram*> programs;
};
#endif // EPGVIEW_H
diff --git a/modules/gui/qt/components/epg/EPGWidget.cpp b/modules/gui/qt/components/epg/EPGWidget.cpp
index ec113b4..bf9cb49 100644
--- a/modules/gui/qt/components/epg/EPGWidget.cpp
+++ b/modules/gui/qt/components/epg/EPGWidget.cpp
@@ -69,25 +69,22 @@ EPGWidget::EPGWidget( QWidget *parent ) : QWidget( parent )
layout->addWidget( rootWidget );
setLayout( layout );
- CONNECT( m_epgView, startTimeChanged(QDateTime),
- m_rulerWidget, setStartTime(QDateTime) );
- CONNECT( m_epgView, durationChanged(int),
- m_rulerWidget, setDuration(int) );
+ CONNECT( m_epgView, rangeChanged(const QDateTime &, const QDateTime &),
+ m_rulerWidget, setRange(const QDateTime &, const QDateTime &) );
+
CONNECT( m_epgView->horizontalScrollBar(), valueChanged(int),
m_rulerWidget, setOffset(int) );
CONNECT( m_epgView->verticalScrollBar(), valueChanged(int),
m_channelsWidget, setOffset(int) );
connect( m_epgView, SIGNAL( itemFocused(EPGItem*)),
this, SIGNAL(itemSelectionChanged(EPGItem*)) );
- CONNECT( m_epgView, channelAdded(QString), m_channelsWidget, addChannel(QString) );
- CONNECT( m_epgView, channelRemoved(QString), m_channelsWidget, removeChannel(QString) );
+ CONNECT( m_epgView, programAdded(const EPGProgram *), m_channelsWidget, addProgram(const EPGProgram *) );
}
void EPGWidget::reset()
{
+ m_channelsWidget->reset();
m_epgView->reset();
- m_epgView->updateDuration();
- m_epgView->updateStartTime();
}
void EPGWidget::setZoom( int level )
@@ -106,26 +103,15 @@ void EPGWidget::updateEPG( input_item_t *p_input_item )
i_event_source_type = p_input_item->i_type;
b_input_type_known = true;
- m_epgView->cleanup(); /* expire items and flags */
/* Fixme: input could have dissapeared */
vlc_mutex_lock( & p_input_item->lock );
-
- for ( int i = 0; i < p_input_item->i_epg; ++i )
- {
- vlc_epg_t *p_epg = p_input_item->pp_epg[i];
- /* Read current epg events from libvlc and try to insert them */
- m_epgView->addEPGEvents( p_epg->pp_event, p_epg->i_event,
- qfu( p_epg->psz_name ),
- p_epg->p_current );
- }
+ m_epgView->updateEPG( p_input_item->pp_epg, p_input_item->i_epg );
vlc_mutex_unlock( & p_input_item->lock );
/* toggle our widget view */
rootWidget->setCurrentIndex(
m_epgView->hasValidData() ? EPGVIEW_WIDGET : NOEPG_WIDGET );
- // Update the global duration and start time.
- m_epgView->updateDuration();
- m_epgView->updateStartTime();
+ m_epgView->cleanup();
}
More information about the vlc-commits
mailing list