From 2f01e7a558be65186900e278d6ffc91bbe3cc7f8 Mon Sep 17 00:00:00 2001 From: Francois Cartegnie <fcvlcdev@free.fr> Date: Wed, 22 Feb 2012 22:04:56 +0100 Subject: [PATCH] Qt: info_panels: Add bitrate graph --- modules/gui/qt4/Modules.am | 3 + modules/gui/qt4/components/info_panels.cpp | 26 ++- modules/gui/qt4/components/info_panels.hpp | 5 + modules/gui/qt4/components/info_widgets.cpp | 180 ++++++++++++++++++++ modules/gui/qt4/components/info_widgets.hpp | 52 ++++++ po/POTFILES.in | 2 + 6 files changed, 263 insertions(+), 5 deletions(-) create mode 100644 modules/gui/qt4/components/info_widgets.cpp create mode 100644 modules/gui/qt4/components/info_widgets.hpp diff --git a/modules/gui/qt4/Modules.am b/modules/gui/qt4/Modules.am index 457d314c85a3..30f1f59d7743 100644 --- a/modules/gui/qt4/Modules.am +++ b/modules/gui/qt4/Modules.am @@ -47,6 +47,7 @@ nodist_SOURCES_qt4 = \ dialogs/extensions.moc.cpp \ components/extended_panels.moc.cpp \ components/info_panels.moc.cpp \ + components/info_widgets.moc.cpp \ components/preferences_widgets.moc.cpp \ components/complete_preferences.moc.cpp \ components/simple_preferences.moc.cpp \ @@ -305,6 +306,7 @@ SOURCES_qt4 = qt4.cpp \ dialogs/extensions.cpp \ components/extended_panels.cpp \ components/info_panels.cpp \ + components/info_widgets.cpp \ components/preferences_widgets.cpp \ components/complete_preferences.cpp \ components/simple_preferences.cpp \ @@ -380,6 +382,7 @@ noinst_HEADERS = \ dialogs/extensions.hpp \ components/extended_panels.hpp \ components/info_panels.hpp \ + components/info_widgets.hpp \ components/preferences_widgets.hpp \ components/complete_preferences.hpp \ components/simple_preferences.hpp \ diff --git a/modules/gui/qt4/components/info_panels.cpp b/modules/gui/qt4/components/info_panels.cpp index 0b051d4baed4..2f93d8e4a77d 100644 --- a/modules/gui/qt4/components/info_panels.cpp +++ b/modules/gui/qt4/components/info_panels.cpp @@ -33,6 +33,7 @@ #include "qt4.hpp" #include "components/info_panels.hpp" #include "components/interface_widgets.hpp" +#include "info_widgets.hpp" #include <assert.h> #include <vlc_url.h> @@ -491,7 +492,7 @@ void InfoPanel::saveCodecsInfo() */ InputStatsPanel::InputStatsPanel( QWidget *parent ): QWidget( parent ) { - QGridLayout *layout = new QGridLayout(this); + QVBoxLayout *layout = new QVBoxLayout(this); QLabel *topLabel = new QLabel( qtr( "Current" " media / stream " "statistics") ); @@ -526,6 +527,8 @@ InputStatsPanel::InputStatsPanel( QWidget *parent ): QWidget( parent ) "0", input , "KiB" ); CREATE_AND_ADD_TO_CAT( input_bitrate_stat, qtr("Input bitrate"), "0", input, "kb/s" ); + input_bitrate_graph = new QTreeWidgetItem(); + input_bitrate_stat->addChild( input_bitrate_graph ); CREATE_AND_ADD_TO_CAT( demuxed_stat, qtr("Demuxed data size"), "0", input, "KiB") ; CREATE_AND_ADD_TO_CAT( stream_bitrate_stat, qtr("Content bitrate"), "0", input, "kb/s" ); @@ -565,7 +568,19 @@ InputStatsPanel::InputStatsPanel( QWidget *parent ): QWidget( parent ) StatsTree->resizeColumnToContents( 0 ); StatsTree->setColumnWidth( 1 , 200 ); - layout->addWidget(StatsTree, 1, 0 ); + layout->addWidget(StatsTree, 4, 0 ); + + statsView = new VLCStatsView( this ); + statsView->setFrameStyle( QFrame::NoFrame ); + statsView->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ); + input_bitrate_graph->setSizeHint( 1, QSize(0, 100) ); + StatsTree->setItemWidget( input_bitrate_graph, 1, statsView ); +} + +void InputStatsPanel::hideEvent( QHideEvent * event ) +{ + statsView->reset(); + QWidget::hideEvent( event ); } /** @@ -584,12 +599,14 @@ void InputStatsPanel::update( input_item_t *p_item ) { QString str; widget->setText( 1 , str.sprintf( format, ## calc ) ); } UPDATE_INT( read_media_stat, (p_item->p_stats->i_read_bytes / 1024 ) ); - UPDATE_FLOAT( input_bitrate_stat, "%6.0f", (float)(p_item->p_stats->f_input_bitrate * 8000 )); + UPDATE_FLOAT( input_bitrate_stat, "%6.0f", (float)(p_item->p_stats->f_input_bitrate * 8000 )); UPDATE_INT( demuxed_stat, (p_item->p_stats->i_demux_read_bytes / 1024 ) ); - UPDATE_FLOAT( stream_bitrate_stat, "%6.0f", (float)(p_item->p_stats->f_demux_bitrate * 8000 )); + UPDATE_FLOAT( stream_bitrate_stat, "%6.0f", (float)(p_item->p_stats->f_demux_bitrate * 8000 )); UPDATE_INT( corrupted_stat, p_item->p_stats->i_demux_corrupted ); UPDATE_INT( discontinuity_stat, p_item->p_stats->i_demux_discontinuity ); + statsView->addValue( p_item->p_stats->f_input_bitrate * 8000 ); + /* Video */ UPDATE_INT( vdecoded_stat, p_item->p_stats->i_decoded_video ); UPDATE_INT( vdisplayed_stat, p_item->p_stats->i_displayed_pictures ); @@ -614,4 +631,3 @@ void InputStatsPanel::update( input_item_t *p_item ) void InputStatsPanel::clear() { } - diff --git a/modules/gui/qt4/components/info_panels.hpp b/modules/gui/qt4/components/info_panels.hpp index ce30edfd66b8..c0b9ce1be7fe 100644 --- a/modules/gui/qt4/components/info_panels.hpp +++ b/modules/gui/qt4/components/info_panels.hpp @@ -51,6 +51,7 @@ class QLineEdit; class CoverArtLabel; class QTextEdit; class QLabel; +class VLCStatsView; class MetaPanel: public QWidget { @@ -116,11 +117,14 @@ class InputStatsPanel: public QWidget Q_OBJECT public: InputStatsPanel( QWidget * ); +protected: + virtual void hideEvent( QHideEvent * ); private: QTreeWidget *StatsTree; QTreeWidgetItem *input; QTreeWidgetItem *read_media_stat; QTreeWidgetItem *input_bitrate_stat; + QTreeWidgetItem *input_bitrate_graph; QTreeWidgetItem *demuxed_stat; QTreeWidgetItem *stream_bitrate_stat; QTreeWidgetItem *corrupted_stat; @@ -142,6 +146,7 @@ private: QTreeWidgetItem *aplayed_stat; QTreeWidgetItem *alost_stat; + VLCStatsView *statsView; public slots: void update( input_item_t * ); void clear(); diff --git a/modules/gui/qt4/components/info_widgets.cpp b/modules/gui/qt4/components/info_widgets.cpp new file mode 100644 index 000000000000..f7bbbff08847 --- /dev/null +++ b/modules/gui/qt4/components/info_widgets.cpp @@ -0,0 +1,180 @@ +/***************************************************************************** + * info_widgets.cpp : Widgets for info panels + **************************************************************************** + * Copyright (C) 2013 the VideoLAN team + * + * 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 "qt4.hpp" +#include "info_widgets.hpp" + +#include <QGridLayout> +#include <QLabel> +#include <QGraphicsView> +#include <QGraphicsScene> +#include <QPolygonF> +#include <QGraphicsPolygonItem> +#include <QGraphicsLineItem> +#include <QVectorIterator> + +#define STATS_LENGTH 10 +#define ADD_LABEL(row, color, text) \ +label = new QLabel( QString( "<font color=\"%1\">%2</font>" ) \ + .arg( color.name() ) \ + .arg( text ) \ + ); \ +layout->addWidget( label, row, 0, 1, 1, 0 ); + +VLCStatsView::VLCStatsView( QWidget *parent ) : QGraphicsView( parent ) +{ + QColor history(0, 0, 0, 255), + total(237, 109, 0, 160), + content(109, 237, 0, 160); + + scale( 1.0, -1.0 ); /* invert our Y axis */ + setOptimizationFlags( QGraphicsView::DontAdjustForAntialiasing ); + setAlignment( Qt::AlignLeft ); + setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); + setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); + viewScene = new QGraphicsScene( this ); + historyShape = viewScene->addPolygon( QPolygonF(), QPen(Qt::NoPen), + QBrush(history) ); + totalbitrateShape = viewScene->addPolygon( QPolygonF(), QPen(Qt::NoPen), + QBrush(total) ); + setScene( viewScene ); + reset(); + + QPen linepen( Qt::DotLine ); + linepen.setBrush( QBrush( QColor( 33, 33, 33 ) ) ); + for ( int i=0; i<3; i++ ) + rulers[i] = viewScene->addLine( QLineF(), linepen ); +} +#undef ADD_LABEL + +void VLCStatsView::reset() +{ + historymergepointer = 0; + blocksize = 4; + valuesaccumulator = 0; + valuesaccumulatorcount = 0; + historyShape->setPolygon( QPolygonF() ); + totalbitrateShape->setPolygon( QPolygonF() ); +} + +void VLCStatsView::addValue( float value ) +{ + value /= 1000; + + QPolygonF shape = totalbitrateShape->polygon(); + if ( shape.count() > ( STATS_LENGTH + 2 ) ) /* keep only STATS_LENGTH samples */ + { + shape.remove( 1 ); + for(int i=1; i<( STATS_LENGTH + 2 ); i++) + ( (QPointF &) shape.at(i) ).setX( i - 1 ); /*move back values*/ + } + + int count = shape.count(); + if ( count == 0 ) + { + shape << QPointF( 0, 0 ); /* begin and close shape */ + shape << QPointF( count, 0 ); + } + + shape.insert( shape.end() - 1, QPointF( count, value ) ); + ( (QPointF &) shape.last() ).setX( count ); + totalbitrateShape->setPolygon( shape ); + + addHistoryValue( value ); + + QRectF maxsizes = scene()->itemsBoundingRect(); + maxsizes.setRight( STATS_LENGTH ); + fitInView( maxsizes ); /* fix viewport */ + drawRulers( maxsizes ); +} + +void VLCStatsView::drawRulers( const QRectF &maxsizes ) +{ + float height = maxsizes.height() * 1000; + int texp = 0; + while( height > 1.0 ) { height /= 10; texp++; } + height = 1.0; + while( texp-- ) height *= 10; + for ( int i=0; i<3; i++ ) + { + float y = ( height / 5 ) * ( i + 1 ) / 1000; + rulers[i]->setLine( QLineF( 0, y, STATS_LENGTH, y ) ); + } +} + +void VLCStatsView::addHistoryValue( float value ) +{ + /* We keep a full history by creating virtual blocks for inserts, growing + by power of 2 when no more space is available. At this time, we also + free space by agregating the oldest values 2 by 2. + Each shown value finally being a mean of blocksize samples. + */ + bool doinsert = false; + int next_blocksize = blocksize; + QPolygonF shape = historyShape->polygon(); + int count = shape.count(); + if ( count == 0 ) + { + shape << QPointF( 0, 0 ); /* begin and close shape */ + shape << QPointF( count, 0 ); + } + + valuesaccumulator += ( value / blocksize ); + valuesaccumulatorcount++; + + if ( valuesaccumulatorcount == blocksize ) + { + valuesaccumulator = 0; + valuesaccumulatorcount = 0; + doinsert = true; + } + + if ( doinsert ) + { + if ( count > ( STATS_LENGTH + 2 ) ) + { + float y = 0; + y += ((QPointF &) shape.at( historymergepointer + 1 )).y(); + y += ((QPointF &) shape.at( historymergepointer + 2 )).y(); + y /= 2; + + /* merge */ + shape.remove( historymergepointer + 2 ); + ( (QPointF &) shape.at( historymergepointer + 1 ) ).setY( y ); + for(int i=historymergepointer +1; i<( STATS_LENGTH + 2 ); i++) + ( (QPointF &) shape.at(i) ).setX( i - 1 ); /*move back values*/ + historymergepointer++; + if ( historymergepointer > ( STATS_LENGTH - 1 ) ) + { + historymergepointer = 0; + next_blocksize = ( blocksize << 1 ); + } + } + + shape.insert( shape.end() - 1, QPointF( count, value ) ); + ( (QPointF &) shape.last() ).setX( count ); + } + else + ( (QPointF &) shape.last() ).setX( count - 1 ); + + historyShape->setPolygon( shape ); + + blocksize = next_blocksize; +} diff --git a/modules/gui/qt4/components/info_widgets.hpp b/modules/gui/qt4/components/info_widgets.hpp new file mode 100644 index 000000000000..0a1b22b25eb0 --- /dev/null +++ b/modules/gui/qt4/components/info_widgets.hpp @@ -0,0 +1,52 @@ +/***************************************************************************** + * info_widgets.hpp : Widgets for info panels + **************************************************************************** + * Copyright (C) 2013 the VideoLAN team + * + * 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 INFO_WIDGETS_HPP +#define INFO_WIDGETS_HPP + +#include <QGraphicsView> + +class QGraphicsView; +class QGraphicsScene; +class QGraphicsPolygonItem; +class QGraphicsLineItem; + +class VLCStatsView: public QGraphicsView +{ + Q_OBJECT + +public: + VLCStatsView( QWidget * ); + void addValue( float ); + void reset(); + +private: + void addHistoryValue( float ); + void drawRulers( const QRectF & ); + QGraphicsScene *viewScene; + QGraphicsPolygonItem *totalbitrateShape; + QGraphicsPolygonItem *historyShape; + QGraphicsLineItem *rulers[3]; + unsigned int historymergepointer; + unsigned int blocksize; + float valuesaccumulator; + unsigned int valuesaccumulatorcount; +}; + +#endif // INFO_WIDGETS_HPP diff --git a/po/POTFILES.in b/po/POTFILES.in index cd1a3c7332f1..4ece099b8ad4 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -605,6 +605,8 @@ modules/gui/qt4/components/extended_panels.cpp modules/gui/qt4/components/extended_panels.hpp modules/gui/qt4/components/info_panels.cpp modules/gui/qt4/components/info_panels.hpp +modules/gui/qt4/components/info_widgets.cpp +modules/gui/qt4/components/info_widgets.hpp modules/gui/qt4/components/interface_widgets.cpp modules/gui/qt4/components/interface_widgets.hpp modules/gui/qt4/components/open_panels.cpp -- GitLab