diff --git a/Jamulus.pro b/Jamulus.pro index dbd4b49b..b0df1a78 100755 --- a/Jamulus.pro +++ b/Jamulus.pro @@ -158,6 +158,7 @@ HEADERS += src/audiomixerboard.h \ src/connectdlg.h \ src/global.h \ src/clientdlg.h \ + src/historygraph.h \ src/serverdlg.h \ src/multicolorled.h \ src/multicolorledbar.h \ @@ -168,6 +169,7 @@ HEADERS += src/audiomixerboard.h \ src/settings.h \ src/socket.h \ src/soundbase.h \ + src/svghistorygraph.h \ src/testbench.h \ src/util.h \ src/analyzerconsole.h \ @@ -266,6 +268,7 @@ SOURCES += src/audiomixerboard.cpp \ src/settings.cpp \ src/socket.cpp \ src/soundbase.cpp \ + src/svghistorygraph.cpp \ src/util.cpp \ src/analyzerconsole.cpp \ src/recorder/jamrecorder.cpp \ diff --git a/src/historygraph.h b/src/historygraph.h new file mode 100755 index 00000000..cf8e5caf --- /dev/null +++ b/src/historygraph.h @@ -0,0 +1,90 @@ +#ifndef HISTORYGRAPH_H +#define HISTORYGRAPH_H + +#include +#include +#include +#include +#include +#include +#include +#include "global.h" +#include "util.h" + +/* Definitions ****************************************************************/ +// number of history items to store +#define NUM_ITEMS_HISTORY 600 + +/* Classes ********************************************************************/ +class CHistoryGraph : public QObject +{ + Q_OBJECT + +public: + enum EHistoryItemType + { + HIT_LOCAL_CONNECTION, + HIT_REMOTE_CONNECTION, + HIT_SERVER_STOP + }; + + CHistoryGraph(); + void Start ( const QString& sNewFileName ); + void Add ( const QDateTime& newDateTime, const EHistoryItemType curType ); + void Add ( const QDateTime& newDateTime, const QHostAddress ClientInetAddr ); + void Update(); + +protected: + struct SHistoryData + { + QDateTime DateTime; + EHistoryItemType Type; + }; + void DrawFrame ( const int iNewNumTicksX ); + void AddMarker ( const SHistoryData& curHistoryData ); + void Save ( const QString sFileName ); + + QString sFileName; + + bool bDoHistory; + CFIFO vHistoryDataFifo; + + QRect PlotCanvasRect; + + int iNumTicksX; + int iYAxisStart; + int iYAxisEnd; + int iNumTicksY; + int iGridFrameOffset; + int iGridWidthWeekend; + int iTextOffsetToGrid; + int iXAxisTextHeight; + int iMarkerSizeNewCon; + int iMarkerSizeServSt; + + QFont AxisFont; + int iTextOffsetX; + + QColor PlotBackgroundColor; + QColor PlotFrameColor; + QColor PlotGridColor; + QColor PlotTextColor; + QColor PlotMarkerNewColor; + QColor PlotMarkerNewLocalColor; + QColor PlotMarkerStopColor; + + QImage PlotPixmap; + + double dXSpace; + int iYSpace; + + QDate curDate; + QRect PlotGridFrame; + QTimer TimerDailyUpdate; + +public slots: + void OnTimerDailyUpdate() { Update(); } +}; + + +#endif // HISTORYGRAPH_H diff --git a/src/main.cpp b/src/main.cpp index 91fea668..b043f29b 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -415,8 +415,7 @@ int main ( int argc, char** argv ) // Application object if ( !bUseGUI && !strHistoryFileName.isEmpty() ) { - tsConsole << "Qt5 requires a windowing system to paint a JPEG image; disabling history graph" << endl; - strHistoryFileName = ""; + tsConsole << "Qt5 requires a windowing system to paint a JPEG image; image will use SVG" << endl; } QCoreApplication* pApp = bUseGUI ? new QApplication ( argc, argv ) diff --git a/src/serverlogging.cpp b/src/serverlogging.cpp index 8876c099..0567cebe 100755 --- a/src/serverlogging.cpp +++ b/src/serverlogging.cpp @@ -333,7 +333,14 @@ void CServerLogging::Start ( const QString& strLoggingFileName ) void CServerLogging::EnableHistory ( const QString& strHistoryFileName ) { - HistoryGraph.Start ( strHistoryFileName ); + if ( strHistoryFileName.right(4).compare(".svg", Qt::CaseInsensitive) == 0 ) + { + SvgHistoryGraph.Start ( strHistoryFileName ); + } + else + { + HistoryGraph.Start ( strHistoryFileName ); + } } void CServerLogging::AddNewConnection ( const QHostAddress& ClientInetAddr ) @@ -342,14 +349,13 @@ void CServerLogging::AddNewConnection ( const QHostAddress& ClientInetAddr ) const QString strLogStr = CurTimeDatetoLogString() + ", " + ClientInetAddr.toString() + ", connected"; -#ifndef _WIN32 - QTextStream tsConsoleStream ( stdout ); + QTextStream& tsConsoleStream = *( ( new ConsoleWriterFactory() )->get() ); tsConsoleStream << strLogStr << endl; // on console -#endif *this << strLogStr; // in log file // add element to history HistoryGraph.Add ( QDateTime::currentDateTime(), ClientInetAddr ); + SvgHistoryGraph.Add ( QDateTime::currentDateTime(), ClientInetAddr ); } void CServerLogging::AddServerStopped() @@ -357,17 +363,16 @@ void CServerLogging::AddServerStopped() const QString strLogStr = CurTimeDatetoLogString() + ",, server stopped " "-------------------------------------"; -#ifndef _WIN32 - QTextStream tsConsoleStream ( stdout ); + QTextStream& tsConsoleStream = *( ( new ConsoleWriterFactory() )->get() ); tsConsoleStream << strLogStr << endl; // on console -#endif *this << strLogStr; // in log file // add element to history and update on server stop - HistoryGraph.Add ( QDateTime::currentDateTime(), - CHistoryGraph::HIT_SERVER_STOP ); + HistoryGraph.Add ( QDateTime::currentDateTime(), CHistoryGraph::HIT_SERVER_STOP ); + SvgHistoryGraph.Add ( QDateTime::currentDateTime(), CHistoryGraph::HIT_SERVER_STOP ); HistoryGraph.Update(); + SvgHistoryGraph.Update(); } void CServerLogging::operator<< ( const QString& sNewStr ) @@ -420,8 +425,8 @@ void CServerLogging::ParseLogFile ( const QString& strFileName ) if ( strAddress.isEmpty() ) { // server stop - HistoryGraph.Add ( curDateTime, - CHistoryGraph::HIT_SERVER_STOP ); + HistoryGraph.Add ( curDateTime, CHistoryGraph::HIT_SERVER_STOP ); + SvgHistoryGraph.Add ( curDateTime, CHistoryGraph::HIT_SERVER_STOP ); } else { @@ -432,13 +437,15 @@ void CServerLogging::ParseLogFile ( const QString& strFileName ) { // new client connection HistoryGraph.Add ( curDateTime, curAddress ); + SvgHistoryGraph.Add ( curDateTime, curAddress ); } } } } } - HistoryGraph.Update(); + HistoryGraph.Update(); + SvgHistoryGraph.Update(); } QString CServerLogging::CurTimeDatetoLogString() diff --git a/src/serverlogging.h b/src/serverlogging.h index fc281ae6..4fcb6d5b 100755 --- a/src/serverlogging.h +++ b/src/serverlogging.h @@ -22,11 +22,9 @@ * \******************************************************************************/ -#if !defined ( SERVERLOGGING_HOIHOKIH83JH8_3_43445KJIUHF1912__INCLUDED_ ) -#define SERVERLOGGING_HOIHOKIH83JH8_3_43445KJIUHF1912__INCLUDED_ +#ifndef SERVERLOGGING_H +#define SERVERLOGGING_H -#include -#include #include #include #include @@ -35,84 +33,10 @@ #include "global.h" #include "util.h" - -/* Definitions ****************************************************************/ -// number of history items to store -#define NUM_ITEMS_HISTORY 600 - +#include "historygraph.h" +#include "svghistorygraph.h" /* Classes ********************************************************************/ -class CHistoryGraph : public QObject -{ - Q_OBJECT - -public: - enum EHistoryItemType - { - HIT_LOCAL_CONNECTION, - HIT_REMOTE_CONNECTION, - HIT_SERVER_STOP - }; - - CHistoryGraph(); - void Start ( const QString& sNewFileName ); - void Add ( const QDateTime& newDateTime, const EHistoryItemType curType ); - void Add ( const QDateTime& newDateTime, const QHostAddress ClientInetAddr ); - void Update(); - -protected: - struct SHistoryData - { - QDateTime DateTime; - EHistoryItemType Type; - }; - void DrawFrame ( const int iNewNumTicksX ); - void AddMarker ( const SHistoryData& curHistoryData ); - void Save ( const QString sFileName ); - - QString sFileName; - - bool bDoHistory; - CFIFO vHistoryDataFifo; - - QRect PlotCanvasRect; - - int iNumTicksX; - int iYAxisStart; - int iYAxisEnd; - int iNumTicksY; - int iGridFrameOffset; - int iGridWidthWeekend; - int iTextOffsetToGrid; - int iXAxisTextHeight; - int iMarkerSizeNewCon; - int iMarkerSizeServSt; - - QFont AxisFont; - int iTextOffsetX; - - QColor PlotBackgroundColor; - QColor PlotFrameColor; - QColor PlotGridColor; - QColor PlotTextColor; - QColor PlotMarkerNewColor; - QColor PlotMarkerNewLocalColor; - QColor PlotMarkerStopColor; - - QImage PlotPixmap; - - double dXSpace; - int iYSpace; - - QDate curDate; - QRect PlotGridFrame; - QTimer TimerDailyUpdate; - -public slots: - void OnTimerDailyUpdate() { Update(); } -}; - - class CServerLogging { public: @@ -122,6 +46,7 @@ public: void Start ( const QString& strLoggingFileName ); void EnableHistory ( const QString& strHistoryFileName ); + void EnableSVGHistory ( const QString& strHistoryFileName ); void AddNewConnection ( const QHostAddress& ClientInetAddr ); void AddServerStopped(); void ParseLogFile ( const QString& strFileName ); @@ -131,8 +56,9 @@ protected: QString CurTimeDatetoLogString(); CHistoryGraph HistoryGraph; + CSvgHistoryGraph SvgHistoryGraph; bool bDoLogging; QFile File; }; -#endif /* !defined ( SERVERLOGGING_HOIHOKIH83JH8_3_43445KJIUHF1912__INCLUDED_ ) */ +#endif // SERVERLOGGING_H diff --git a/src/svghistorygraph.cpp b/src/svghistorygraph.cpp new file mode 100755 index 00000000..78176b26 --- /dev/null +++ b/src/svghistorygraph.cpp @@ -0,0 +1,340 @@ +#include "svghistorygraph.h" + +CSvgHistoryGraph::CSvgHistoryGraph() : + sFileName ( "" ), + bDoHistory ( false ), + vHistoryDataFifo ( NUM_ITEMS_HISTORY ), + plotCanvasRectX ( 0 ), + plotCanvasRectY ( 0 ), + plotCanvasRectWidth ( 600 ), + plotCanvasRectHeight ( 450 ), + numDays ( 0 ), + iYAxisStart ( 0 ), + iYAxisEnd ( 24 ), + iNumTicksY ( 5 ), + iGridFrameOffset ( 10 ), + iGridWidthWeekend ( 3 ), // should be an odd value + iTextOffsetToGrid ( 3 ), + iXAxisTextHeight ( 22 ), + iMarkerSizeNewCon ( 11 ), + iMarkerSizeServSt ( 8 ), + axisFontFamily ( "sans-serif" ), + axisFontWeight ( "80" ), + axisFontSize ( 10 ), + iTextOffsetX ( 18 ), + plotGridFrameX ( plotCanvasRectX + iGridFrameOffset ), + plotGridFrameY ( plotCanvasRectY + iGridFrameOffset ), + plotGridFrameWidth ( plotCanvasRectWidth - 2 * iGridFrameOffset ), + plotGridFrameHeight ( plotCanvasRectHeight - 2 * iGridFrameOffset - iXAxisTextHeight ), + plotGridFrameRight ( plotGridFrameX + plotGridFrameWidth ), + plotGridFrameBottom ( plotGridFrameY + plotGridFrameHeight ), + PlotBackgroundColor ( "white" ), // background + PlotFrameColor ( "black" ), // frame + PlotGridColor ( "gray" ), // grid + PlotTextColor ( "black" ), // text + PlotMarkerNewColor ( "darkCyan" ), // marker for new connection + PlotMarkerNewLocalColor ( "blue" ), // marker for new local connection + PlotMarkerStopColor ( "red" ) // marker for server stop +{ + + // set SVG veiwBox to correct size to ensure correct scaling + svgRootAttributes.append("viewBox", + QString("%1, %2, %3, %4") + .arg(plotCanvasRectX) + .arg(plotCanvasRectY) + .arg(plotCanvasRectWidth) + .arg(plotCanvasRectHeight) + ); + + svgRootAttributes.append("xmlns", "http://www.w3.org/2000/svg"); + svgRootAttributes.append("xmlns:xlink", "http://www.w3.org/1999/xlink"); + + // generate plot grid frame rectangle + gridFrameAttributes.append("stroke", QString("%1").arg(PlotFrameColor)); + gridFrameAttributes.append("stroke-width", QString("%1").arg(1)); + gridFrameAttributes.append("style", QString("fill: none;")); + + textAttributes.append("stroke", QString("%1").arg(PlotTextColor)); + textAttributes.append("font-family", axisFontFamily); + textAttributes.append("font-weight", axisFontWeight); + textAttributes.append("font-size", QString("%1").arg(axisFontSize)); + + gridAttributes.append("stroke", QString("%1").arg(PlotGridColor)); + gridAttributes.append("stroke-width", QString("%1").arg(1)); + + gridWeekendAttributes.append("stroke", QString("%1").arg(PlotGridColor)); + gridWeekendAttributes.append("stroke-width", QString("%1").arg(iGridWidthWeekend)); + + // Connections ------------------------------------------------------------- + QObject::connect ( &TimerDailyUpdate, SIGNAL ( timeout() ), + this, SLOT ( OnTimerDailyUpdate() ) ); + +} + +void CSvgHistoryGraph::Start ( const QString& sNewFileName ) +{ + if ( !sNewFileName.isEmpty() ) + { + // save file name + sFileName = sNewFileName; + + // set enable flag + bDoHistory = true; + + // enable timer (update once a day) + TimerDailyUpdate.start ( 3600000 * 24 ); + + // initial update (empty graph) + Update(); + } +} + +void CSvgHistoryGraph::DrawFrame( QXmlStreamWriter &svgStreamWriter, const unsigned int _numDays ) +{ + unsigned int i; + + // store number of x-axis ticks (number of days we want to draw + // the history for + numDays = _numDays; + + // Create actual plot region (grid frame) ---------------------------------- + rect(svgStreamWriter, plotGridFrameX, plotGridFrameY, plotGridFrameWidth, plotGridFrameHeight, gridFrameAttributes); + + // calculate step for x-axis ticks so that we get the desired number of + // ticks -> 5 ticks + +// TODO the following equation does not work as expected but results are acceptable + + // we want to have "floor ( numDays / 5 )" which is the same as + // "numDays / 5" since "numDays" is an integer variable + const unsigned int iXAxisTickStep = numDays / 5 + 1; + + // grid (ticks) for x-axis + dayXSpace = static_cast ( plotCanvasRectWidth / ( numDays + 1 ) ); + for ( i = 0; i < numDays; i++ ) + { + unsigned int iBottomExtraTickLen = 0; + const unsigned int iCurX = plotGridFrameX + static_cast ( dayXSpace * ( i + 1 ) ); + const QDate curXAxisDate = curDate.addDays ( i - numDays + 1 ); + + // text (print only every "iXAxisTickStep" tick) + if ( !( i % iXAxisTickStep ) ) + { + text(svgStreamWriter, static_cast(std::max(0, static_cast(iCurX - iTextOffsetX))), plotGridFrameBottom + iXAxisTextHeight + iTextOffsetToGrid, curXAxisDate.toString ( "dd.MM." ), textAttributes); + + iBottomExtraTickLen = 5; + } + + // regular grid + line(svgStreamWriter, iCurX, 1 + plotGridFrameY, iCurX, plotGridFrameBottom + iBottomExtraTickLen, gridAttributes); + + // different grid width for weekends (overwrite regular grid) + if ( ( curXAxisDate.dayOfWeek() == 6 ) || // check for Saturday + ( curXAxisDate.dayOfWeek() == 7 ) ) // check for Sunday + { + const unsigned int iGridWidthWeekendHalf = iGridWidthWeekend / 2; + + line(svgStreamWriter, iCurX, 1 + plotGridFrameY + iGridWidthWeekendHalf, iCurX, plotGridFrameBottom - iGridWidthWeekendHalf, gridWeekendAttributes); + } + } + + // grid (ticks) for y-axis, draw iNumTicksY - 2 grid lines and + // iNumTicksY - 1 text labels (the lowest grid line is the grid frame) + iYSpace = plotGridFrameHeight / ( iNumTicksY - 1 ); + for ( i = 0; i < ( iNumTicksY - 1 ); i++ ) + { + const unsigned int iCurY = plotGridFrameY + iYSpace * ( i + 1 ); + + // text + text(svgStreamWriter, plotGridFrameX + iTextOffsetToGrid, iCurY - iTextOffsetToGrid, + QString ( "%1:00" ).arg ( ( iYAxisEnd - iYAxisStart ) / ( iNumTicksY - 1 ) * ( ( iNumTicksY - 2 ) - i ) ), + textAttributes ); + + // grid (do not overwrite frame) + if ( i < ( iNumTicksY - 2 ) ) + { + line(svgStreamWriter, plotGridFrameX, iCurY, plotGridFrameRight, iCurY, gridAttributes); + } + } +} + +void CSvgHistoryGraph::AddMarker ( QXmlStreamWriter &svgStreamWriter, const SHistoryData& curHistoryData ) +{ + // calculate x-axis offset (difference of days compared to + // current date) + const unsigned int iXAxisOffs = static_cast( curDate.daysTo ( curHistoryData.DateTime.date() ) ); + + // check range, if out of range, do not plot anything + if ( -iXAxisOffs > ( numDays - 1 ) ) + { + return; + } + + // calculate y-axis offset (consider hours and minutes) + const double dYAxisOffs = 24 - curHistoryData.DateTime.time().hour() - + static_cast ( curHistoryData.DateTime.time().minute() ) / 60; + + // calculate the actual point in the graph (in pixels) + unsigned int curPointX = plotGridFrameX + static_cast ( dayXSpace * ( numDays + iXAxisOffs ) ); + unsigned int curPointY = plotGridFrameY + static_cast ( static_cast ( plotGridFrameHeight ) / ( iYAxisEnd - iYAxisStart ) * dYAxisOffs ); + unsigned int wh = 0; + QXmlStreamAttributes curPointAttibutes; + curPointAttibutes.append("stroke", "0"); + + // we use different markers for new connection and server stop items + switch ( curHistoryData.Type ) + { + case CHistoryGraph::EHistoryItemType::HIT_SERVER_STOP: + curPointAttibutes.append("fill", PlotMarkerStopColor); + wh = iMarkerSizeServSt; + break; + + case CHistoryGraph::EHistoryItemType::HIT_LOCAL_CONNECTION: + curPointAttibutes.append("fill", PlotMarkerNewLocalColor); + wh = iMarkerSizeNewCon; + break; + + case CHistoryGraph::EHistoryItemType::HIT_REMOTE_CONNECTION: + curPointAttibutes.append("fill", PlotMarkerNewColor); + wh = iMarkerSizeNewCon; + break; + } + rect(svgStreamWriter, curPointX, curPointY, wh, wh, curPointAttibutes); +} + +void CSvgHistoryGraph::Save ( const QString sFileName, const QString& svgImage ) +{ + QFile outf (sFileName); + if (!outf.open(QFile::WriteOnly)) { + throw std::runtime_error( (sFileName + " could not be written. Aborting.").toStdString() ); + } + QTextStream out(&outf); + + out << svgImage << endl; +} + +void CSvgHistoryGraph::Add ( const QDateTime& newDateTime, + const QHostAddress ClientInetAddr ) +{ + if ( bDoHistory ) + { + // add element to history, distinguish between a local connection + // and a remote connection + if ( ( ClientInetAddr == QHostAddress ( "127.0.0.1" ) ) || + ( ClientInetAddr.toString().left ( 7 ).compare ( "192.168" ) == 0 ) ) + { + // local connection + Add ( newDateTime, CHistoryGraph::HIT_LOCAL_CONNECTION ); + } + else + { + // remote connection + Add ( newDateTime, CHistoryGraph::HIT_REMOTE_CONNECTION ); + } + } +} + +void CSvgHistoryGraph::Add ( const QDateTime& newDateTime, + const CHistoryGraph::EHistoryItemType curType ) +{ + if ( bDoHistory ) + { + // create and add new element in FIFO + SHistoryData curHistoryData; + curHistoryData.DateTime = newDateTime; + curHistoryData.Type = curType; + + vHistoryDataFifo.Add ( curHistoryData ); + } +} + +void CSvgHistoryGraph::Update() +{ + if ( bDoHistory ) + { + + int i; + + // store current date for reference + curDate = QDate::currentDate(); + + // get oldest date in history + QDate oldestDate = curDate.addDays ( 1 ); // one day in the future + const int iNumItemsForHistory = vHistoryDataFifo.Size(); + for ( i = 0; i < iNumItemsForHistory; i++ ) + { + // only use valid dates + if ( vHistoryDataFifo[i].DateTime.date().isValid() ) + { + if ( vHistoryDataFifo[i].DateTime.date() < oldestDate ) + { + oldestDate = vHistoryDataFifo[i].DateTime.date(); + } + } + } + + const unsigned int iNumDaysInHistory = static_cast( -curDate.daysTo ( oldestDate ) + 1 ); + + // create SVG document + QString svgImage; + QXmlStreamWriter svgStreamWriter( &svgImage ); + svgStreamWriter.setAutoFormatting(true); + svgStreamWriter.writeStartDocument(); + svgStreamWriter.writeStartElement("svg"); + svgStreamWriter.writeAttributes(svgRootAttributes); + + // draw frame of the graph + DrawFrame ( svgStreamWriter, iNumDaysInHistory ); + + // add markers + for ( i = 0; i < iNumItemsForHistory; i++ ) + { + // only use valid dates + if ( vHistoryDataFifo[i].DateTime.date().isValid() ) + { + AddMarker ( svgStreamWriter, vHistoryDataFifo[i] ); + } + } + + svgStreamWriter.writeEndDocument(); + + // save graph as picture in file + Save ( sFileName, svgImage ); + } +} + +void CSvgHistoryGraph::rect ( QXmlStreamWriter &svgStreamWriter, const unsigned int x, const unsigned int y, const unsigned width, const unsigned height, const QXmlStreamAttributes &attrs ) +{ + svgStreamWriter.writeEmptyElement("rect"); + svgStreamWriter.writeAttribute("x", QString("%1").arg(x)); + svgStreamWriter.writeAttribute("y", QString("%1").arg(y)); + svgStreamWriter.writeAttribute("width", QString("%1").arg(width)); + svgStreamWriter.writeAttribute("height", QString("%1").arg(height)); + if (attrs.size() > 0) { + svgStreamWriter.writeAttributes(attrs); + } +} + +void CSvgHistoryGraph::line ( QXmlStreamWriter &svgStreamWriter, const unsigned int x1, const unsigned int y1, const unsigned int x2, const unsigned int y2, const QXmlStreamAttributes &attrs ) +{ + svgStreamWriter.writeEmptyElement("line"); + svgStreamWriter.writeAttribute("x1", QString("%1").arg(x1)); + svgStreamWriter.writeAttribute("y1", QString("%1").arg(y1)); + svgStreamWriter.writeAttribute("x2", QString("%1").arg(x2)); + svgStreamWriter.writeAttribute("y2", QString("%1").arg(y2)); + if (attrs.size() > 0) { + svgStreamWriter.writeAttributes(attrs); + } +} + +void CSvgHistoryGraph::text ( QXmlStreamWriter &svgStreamWriter, const unsigned int x, const unsigned int y, const QString &value, const QXmlStreamAttributes &attrs ) +{ + svgStreamWriter.writeStartElement("text"); + svgStreamWriter.writeAttribute("x", QString("%1").arg(x)); + svgStreamWriter.writeAttribute("y", QString("%1").arg(y)); + if (attrs.size() > 0) { + svgStreamWriter.writeAttributes(attrs); + } + svgStreamWriter.writeCharacters( value ); + svgStreamWriter.writeEndElement(); +} diff --git a/src/svghistorygraph.h b/src/svghistorygraph.h new file mode 100755 index 00000000..7124e440 --- /dev/null +++ b/src/svghistorygraph.h @@ -0,0 +1,97 @@ +#ifndef SVGHISTORYGRAPH_H +#define SVGHISTORYGRAPH_H + +#include "historygraph.h" +#include +#include + +/* Definitions ****************************************************************/ +// number of history items to store +#ifndef NUM_ITEMS_HISTORY +#define NUM_ITEMS_HISTORY 600 +#endif + +/* Classes ********************************************************************/ +class CSvgHistoryGraph : public QObject +{ + Q_OBJECT + +public: + CSvgHistoryGraph(); + void Start ( const QString& sNewFileName ); + void Add ( const QDateTime& newDateTime, const CHistoryGraph::EHistoryItemType curType ); + void Add ( const QDateTime& newDateTime, const QHostAddress ClientInetAddr ); + void Update(); + +private: + struct SHistoryData + { + QDateTime DateTime; + CHistoryGraph::EHistoryItemType Type; + }; + void DrawFrame ( QXmlStreamWriter &svgStreamWriter, const unsigned int numDays ); + void AddMarker ( QXmlStreamWriter &svgStreamWriter, const SHistoryData& curHistoryData ); + void Save ( const QString sFileName, const QString& svgImage ); + + void rect ( QXmlStreamWriter &svgStreamWriter, const unsigned int x, const unsigned int y, const unsigned width, const unsigned height, const QXmlStreamAttributes &attrs = QXmlStreamAttributes() ); + void line ( QXmlStreamWriter &svgStreamWriter, const unsigned int x1, const unsigned int y1, const unsigned int x2, const unsigned int y2, const QXmlStreamAttributes &attrs = QXmlStreamAttributes() ); + void text ( QXmlStreamWriter &svgStreamWriter, const unsigned int x, const unsigned int y, const QString &value, const QXmlStreamAttributes &attrs = QXmlStreamAttributes() ); + + QString sFileName; + + bool bDoHistory; + CFIFO vHistoryDataFifo; + + const unsigned int plotCanvasRectX; + const unsigned int plotCanvasRectY; + const unsigned int plotCanvasRectWidth; + const unsigned int plotCanvasRectHeight; + + unsigned int numDays; + + const unsigned int iYAxisStart; + const unsigned int iYAxisEnd; + const unsigned int iNumTicksY; + const unsigned int iGridFrameOffset; + const unsigned int iGridWidthWeekend; + const unsigned int iTextOffsetToGrid; + const unsigned int iXAxisTextHeight; + const unsigned int iMarkerSizeNewCon; + const unsigned int iMarkerSizeServSt; + const QString axisFontFamily; + const QString axisFontWeight; + const unsigned int axisFontSize; + const unsigned int iTextOffsetX; + + const unsigned int plotGridFrameX; + const unsigned int plotGridFrameY; + const unsigned int plotGridFrameWidth; + const unsigned int plotGridFrameHeight; + const unsigned int plotGridFrameRight; + const unsigned int plotGridFrameBottom; + + QString PlotBackgroundColor; + QString PlotFrameColor; + QString PlotGridColor; + QString PlotTextColor; + QString PlotMarkerNewColor; + QString PlotMarkerNewLocalColor; + QString PlotMarkerStopColor; + + double dayXSpace; + unsigned int iYSpace; + + QDate curDate; + QXmlStreamAttributes svgRootAttributes; + QXmlStreamAttributes gridFrameAttributes; + QXmlStreamAttributes textAttributes; + QXmlStreamAttributes gridAttributes; + QXmlStreamAttributes gridWeekendAttributes; + QTimer TimerDailyUpdate; + +public slots: + void OnTimerDailyUpdate() { Update(); } + +}; + +#endif // SVGHISTORYGRAPH_H