From 67f0cf443b12b24ae200193295abccb64bd7fbf9 Mon Sep 17 00:00:00 2001
From: Mark Watkins <jedimark@users.sourceforge.net>
Date: Fri, 18 Jan 2013 04:26:11 +1000
Subject: [PATCH] Implemented font texture caching

This seems to be quite a bit faster and solves the wavy line problems on mac.
I implemented a switch so this can be turned on/off in gGraphView::DrawTextQue()

change use_pixmap_cache to false to turn it off.

I'll remove the graph title and yaxis bits and put them back as this has the
same effect
---
 Graphs/gGraphView.cpp                      | 198 ++++++++++++++++-----
 Graphs/gGraphView.h                        |  21 ++-
 Graphs/gLineChart.cpp                      |   2 +-
 Graphs/gStatsLine.cpp                      |   2 +-
 Graphs/gXAxis.cpp                          |   2 +-
 Graphs/gYAxis.cpp                          |   2 +-
 SleepLib/calcs.cpp                         |  12 +-
 SleepLib/day.cpp                           |   2 +-
 SleepLib/loader_plugins/icon_loader.cpp    |  33 ++--
 SleepLib/loader_plugins/mseries_loader.cpp |  15 +-
 SleepLib/loader_plugins/resmed_loader.cpp  |  28 +--
 SleepLib/loader_plugins/zeo_loader.cpp     |   2 +-
 SleepLib/machine.cpp                       |   4 +-
 SleepLib/machine_loader.cpp                |   2 +-
 SleepyHeadQT.pro                           |  10 +-
 exportcsv.cpp                              |   8 +-
 main.cpp                                   |   9 +-
 mainwindow.cpp                             |  25 ++-
 oximetry.cpp                               |   2 +-
 qextserialport/posix_qextserialport.cpp    |   4 +-
 qextserialport/win_qextserialport.cpp      |   2 +-
 quazip/unzip.c                             |   2 +-
 quazip/zip.c                               |   4 +-
 version.h                                  |   2 +-
 24 files changed, 274 insertions(+), 119 deletions(-)

diff --git a/Graphs/gGraphView.cpp b/Graphs/gGraphView.cpp
index 02183d46..5a17a365 100644
--- a/Graphs/gGraphView.cpp
+++ b/Graphs/gGraphView.cpp
@@ -13,6 +13,7 @@
 #include <QDir>
 #include <QGLPixelBuffer>
 #include <QGLFramebufferObject>
+#include <QPixmapCache>
 #include "mainwindow.h"
 
 #include "Graphs/gYAxis.h"
@@ -22,7 +23,7 @@
 
 extern MainWindow *mainwin;
 
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
 #define USE_RENDERTEXT
 #include "OpenGL/glu.h"
 #else
@@ -1730,8 +1731,8 @@ void gGraph::DrawTextQue()
 // margin recalcs..
 void gGraph::resize(int width, int height)
 {
-    width=width;
-    height=height;
+    Q_UNUSED(width);
+    Q_UNUSED(height);
     //m_height=height;
     //m_width=width;
 }
@@ -1850,9 +1851,9 @@ Layer * gGraph::getLineChart()
 }
 
 // QTBUG-24710 pixmaps might not be freeing properly..
-QPixmap gGraphView::pbRenderPixmap(int w,int h)
+QImage gGraphView::pbRenderPixmap(int w,int h)
 {
-    QPixmap pm=QPixmap();
+    QImage pm=QImage();
     QGLFormat pbufferFormat = format();
     QGLPixelBuffer pbuffer(w,h,pbufferFormat,this);
 
@@ -1861,17 +1862,17 @@ QPixmap gGraphView::pbRenderPixmap(int w,int h)
        resizeGL(w,h);
        initializeGL();
        paintGL();
-       QImage image=pbuffer.toImage();
-       pm=QPixmap::fromImage(image);
+       pm=pbuffer.toImage();
+       //pm=QPixmap::fromImage(image);
        pbuffer.doneCurrent();
    }
    return pm;
 
 }
 
-QPixmap gGraphView::fboRenderPixmap(int w,int h)
+QImage gGraphView::fboRenderPixmap(int w,int h)
 {
-    QPixmap pm=QPixmap();
+    QImage pm=QImage();
 
     if (fbo_unsupported)
         return pm;
@@ -1897,7 +1898,7 @@ QPixmap gGraphView::fboRenderPixmap(int w,int h)
             fbo->release();
 
             // Copy just the section of the image (remember openGL draws from the bottom up)
-            pm=QPixmap::fromImage(fbo->toImage()).copy(0,max_fbo_height-h,w,h);
+            pm=fbo->toImage().copy(0,max_fbo_height-h,w,h);
             doneCurrent();
         }
     } else {
@@ -1957,14 +1958,15 @@ QPixmap gGraph::renderPixmap(int w, int h, bool printing)
     sg->setScaleY(1.0);
 
     //sg->makeCurrent();
-
+#ifndef Q_OS_MAC
     pm=sg->renderPixmap(w,h,false);
+#endif
     if (pm.isNull()) {
         // this one gives nags
-        pm=sg->fboRenderPixmap(w,h);
+        pm=QPixmap::fromImage(sg->fboRenderPixmap(w,h));
     } else if (pm.isNull()) { // not sure if this will work with printing
         qDebug() << "Had to use PixelBuffer for snapshots\n";
-        pm=sg->pbRenderPixmap(w,h);
+        pm=QPixmap::fromImage(sg->pbRenderPixmap(w,h));
     }
 
     //sg->doneCurrent();
@@ -2086,6 +2088,7 @@ gGraphView::gGraphView(QWidget *parent, gGraphView * shared) :
     m_button_down=m_graph_dragging=m_sizer_dragging=false;
     m_lastypos=m_lastxpos=0;
     m_horiz_travel=0;
+    pixmap_cache_size=0;
     this->setMouseTracking(true);
     m_emptytext=QObject::tr("No Data");
     InitGraphs();
@@ -2161,61 +2164,168 @@ gGraphView::~gGraphView()
     timer->stop();
     delete timer;
 }
+
 void gGraphView::DrawTextQue()
 {
-    glPushAttrib(GL_COLOR_BUFFER_BIT);
+    const qint64 expire_after_ms=4000; // expire string pixmap after this many milliseconds
+    const bool use_pixmap_cache=true;
+    quint64 ti=0;
     int w,h;
+    QHash<QString,myPixmapCache*>::iterator it;
     QPainter painter;
+    if (use_pixmap_cache) {
+        // Current time in milliseconds since epoch.
+        ti=QDateTime::currentDateTime().toMSecsSinceEpoch();
+
+
+        // Expire any strings not used
+        QList<QString> expire;
+
+        for (it=pixmap_cache.begin();it!=pixmap_cache.end();it++) {
+            if ((*it)->last_used < (ti-expire_after_ms)) {
+                expire.push_back(it.key());
+            }
+        }
+        for (int i=0;i<expire.count();i++) {
+            const QString key=expire.at(i);
+            // unbind the texture
+            deleteTexture(pixmap_cache[key]->textureID);
+            QPixmap *pm=pixmap_cache[key]->pixmap;
+            pixmap_cache_size-=pm->width() * pm->height() * (pm->depth()/8);
+            // free the pixmap
+            delete pixmap_cache[key]->pixmap;
+
+            // free the myPixmapCache object
+            delete pixmap_cache[key];
+
+            // pull the dead record from the cache.
+            pixmap_cache.remove(expire.at(i));
+        }
+
+    } else {
+        glPushAttrib(GL_COLOR_BUFFER_BIT);
+
 #ifndef USE_RENDERTEXT
-    painter.begin(this);
+        painter.begin(this);
 #endif
+    }
     for (int i=0;i<m_textque_items;i++) {
         // GL Font drawing is ass in Qt.. :(
         TextQue & q=m_textque[i];
-#ifndef USE_RENDERTEXT
-        QBrush b(q.color);
-        painter.setBrush(b);
-        painter.setFont(*q.font);
-#endif
 
-        if (q.angle==0) {
-            qglColor(q.color);
+        if (use_pixmap_cache) {
+            // Generate the pixmap cache "key"
+            QString hstr=QString("%4:%5:%6").arg(q.text).arg(q.color.name()).arg(q.font->key());
 
-            // *********************************************************
-            // Holy crap this is slow
-            // The following line is responsible for 77% of drawing time
-            // *********************************************************
-#ifdef USE_RENDERTEXT
-            renderText(q.x,q.y,q.text,*q.font);
-#else
-            painter.drawText(q.x, q.y, q.text);
-#endif
+            QPixmap * pm=NULL;
+
+            //Random_note: test add to qmake for qt5 stuff DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x040900
+
+            it=pixmap_cache.find(hstr);
+            myPixmapCache *pc=NULL;
+            if (it!=pixmap_cache.end()) {
+                pc=(*it);
+
+            } else {
+                //This is much slower than other text rendering methods, but caching more than makes up for the speed decrease.
+                pc=new myPixmapCache;
+                // not found.. create the image and store it in a cache
+                pc->last_used=ti; // set the last_used value.
+
+                QFontMetrics fm(*q.font);
+                QRect rect=fm.boundingRect(q.text);
+                w=rect.width();
+                h=rect.height();
+                pm=new QPixmap(w+4,h+4);
+                pm->fill(Qt::transparent);
+
+                painter.begin(pm);
+
+                QBrush b(q.color);
+                painter.setBrush(b);
+                painter.setFont(*q.font);
+                painter.drawText(2,h,q.text);
+                painter.end();
+
+                pc->pixmap=pm;
+                pixmap_cache_size+=pm->width()*pm->height()*(pm->depth()/8);
+                pc->textureID=bindTexture(*pm);
+                pixmap_cache[hstr]=pc;
+
+            }
+
+            if (pc) {
+                pc->last_used=ti;
+                glEnable(GL_BLEND);
+                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+                glEnable(GL_TEXTURE_2D);
+                if (q.angle!=0) {
+                    glPushMatrix();
+                    glTranslatef(q.x-pc->pixmap->height()*2+4,q.y+pc->pixmap->width()/2+4, 0);
+                    glRotatef(-q.angle,0,0,1);
+                    drawTexture(QPoint(0,pc->pixmap->height()/2),pc->textureID);
+                    glPopMatrix();
+                    //glTranslatef(marginLeft()+4,originY+height/2+x/2, 0);
+                    //glRotatef(-90,0,0,1);
+                    //m_graphview->drawTexture(QPoint(0,y/2),titleImageTex);
+                } else {
+                    // TODO: setup for rotation if angle specified.
+                    drawTexture(QPoint(q.x,q.y-pc->pixmap->height()+4),pc->textureID);
+                }
+                glDisable(GL_TEXTURE_2D);
+                glDisable(GL_BLEND);
+            }
         } else {
-#ifdef USE_RENDERTEXT
-            painter.begin(this);
+
+#ifndef USE_RENDERTEXT
             QBrush b(q.color);
             painter.setBrush(b);
             painter.setFont(*q.font);
 #endif
-            w=painter.fontMetrics().width(q.text);
-            h=painter.fontMetrics().xHeight()+2;
 
-            painter.translate(q.x, q.y);
-            painter.rotate(-q.angle);
-            painter.drawText(floor(-w/2.0), floor(-h/2.0), q.text);
-            painter.rotate(+q.angle);
-            painter.translate(-q.x, -q.y);
+            if (q.angle==0) {
+                qglColor(q.color);
+                // *********************************************************
+                // Holy crap this is slow
+                // The following line is responsible for 77% of drawing time
+                // *********************************************************
+
 #ifdef USE_RENDERTEXT
-            painter.end();
+                renderText(q.x,q.y,q.text,*q.font);
+#else
+                painter.drawText(q.x, q.y, q.text);
 #endif
+            } else {
+#ifdef USE_RENDERTEXT
+                painter.begin(this);
+                QBrush b(q.color);
+                painter.setBrush(b);
+                painter.setFont(*q.font);
+#endif
+                w=painter.fontMetrics().width(q.text);
+                h=painter.fontMetrics().xHeight()+2;
+
+                painter.translate(q.x, q.y);
+                painter.rotate(-q.angle);
+                painter.drawText(floor(-w/2.0), floor(-h/2.0), q.text);
+                painter.rotate(+q.angle);
+                painter.translate(-q.x, -q.y);
+#ifdef USE_RENDERTEXT
+                painter.end();
+#endif
+           }
         }
         q.text.clear();
         //q.text.squeeze();
     }
+
+    if (!use_pixmap_cache) {
 #ifndef USE_RENDERTEXT
-    painter.end();
+        painter.end();
 #endif
-    glPopAttrib();
+        glPopAttrib();
+    }
     //qDebug() << "rendered" << m_textque_items << "text items";
     m_textque_items=0;
 }
@@ -2964,7 +3074,7 @@ void gGraphView::paintGL()
             v+=ring[i];
         }
         double fps=v/double(rs);
-        ss="Debug Mode "+QString::number(ms,'f',1)+"ms ("+QString::number(fps,'f',1)+"fps) "+QString::number(lines_drawn_this_frame,'f',0)+" lines "+QString::number(quads_drawn_this_frame,'f',0)+" quads";
+        ss="Debug Mode "+QString::number(ms,'f',1)+"ms ("+QString::number(fps,'f',1)+"fps) "+QString::number(lines_drawn_this_frame,'f',0)+" lines "+QString::number(quads_drawn_this_frame,'f',0)+" quads "+QString::number(pixmap_cache.count(),'f',0)+" strings";
         int w,h;
         GetTextExtent(ss,w,h);
         QColor col=Qt::white;
diff --git a/Graphs/gGraphView.h b/Graphs/gGraphView.h
index 34fd32bd..68aeedb1 100644
--- a/Graphs/gGraphView.h
+++ b/Graphs/gGraphView.h
@@ -794,6 +794,18 @@ protected slots:
     void Timeout();
 };
 
+/*! \struct myPixmapCache
+    \brief My version of Pixmap cache with texture binding support
+
+ */
+struct myPixmapCache
+{
+    quint64 last_used;
+    QPixmap *pixmap;
+    GLuint textureID;
+};
+
+
 /*! \class gGraphView
     \brief Main OpenGL Graph Area, derived from QGLWidget
 
@@ -964,10 +976,10 @@ public:
     void trashGraphs();
 
     //! \brief Use a QGLFrameBufferObject to render to a pixmap
-    QPixmap fboRenderPixmap(int w,int h);
+    QImage fboRenderPixmap(int w,int h);
 
     //! \brief Use a QGLPixelBuffer to render to a pixmap
-    QPixmap pbRenderPixmap(int w,int h);
+    QImage pbRenderPixmap(int w,int h);
 
 protected:
     //! \brief Set up the OpenGL basics for the QGLWidget underneath
@@ -1080,6 +1092,11 @@ protected:
 
     QTime m_animationStarted;
 
+    // turn this into a struct later..
+    QHash<QString,myPixmapCache *> pixmap_cache;
+    qint32 pixmap_cache_size;
+
+
     //QVector<GLuint> texid;
 signals:
 
diff --git a/Graphs/gLineChart.cpp b/Graphs/gLineChart.cpp
index e5486fa0..1634c992 100644
--- a/Graphs/gLineChart.cpp
+++ b/Graphs/gLineChart.cpp
@@ -520,7 +520,7 @@ void gLineChart::paint(gGraph & w,int left, int top, int width, int height)
                         gs <<= 1;
                     if (gs > j) {
                         qDebug() << "Would overflow line points.. increase default VertexBuffer size in gLineChart";
-                        siz=j >> square_plot ? 2 : 1;
+                        siz=(j >> square_plot) ? 2 : 1;
                         done=true; // end after this partial draw..
                     }
 
diff --git a/Graphs/gStatsLine.cpp b/Graphs/gStatsLine.cpp
index 65c9e9b8..955e40a5 100644
--- a/Graphs/gStatsLine.cpp
+++ b/Graphs/gStatsLine.cpp
@@ -10,7 +10,7 @@ void gStatsLine::paint(gGraph & w, int left, int top, int width, int height)
 {
     if (!m_visible) return;
     //if (m_empty) return;
-    height=height;
+    Q_UNUSED(height);
 
     int z=(width+gYAxis::Margin)/5;
     int p=left-gYAxis::Margin;
diff --git a/Graphs/gXAxis.cpp b/Graphs/gXAxis.cpp
index 1ea9bef0..45e274ca 100644
--- a/Graphs/gXAxis.cpp
+++ b/Graphs/gXAxis.cpp
@@ -165,7 +165,7 @@ void gXAxis::paint(gGraph & w,int left,int top, int width, int height)
         if (py<start_px) continue;
         lines->add(py,top,py,mintop);
     }
-    static QString dow[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
+    //static QString dow[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
 
     int ms,m,h,s,d;
     qint64 j;
diff --git a/Graphs/gYAxis.cpp b/Graphs/gYAxis.cpp
index 6d88b05d..b83d2254 100644
--- a/Graphs/gYAxis.cpp
+++ b/Graphs/gYAxis.cpp
@@ -224,7 +224,7 @@ void gYAxis::paint(gGraph & w,int left,int top, int width, int height)
             if (x>labelW) labelW=x;
             h=(height-2)-ty;
             h+=yh;
-#ifndef Q_WS_MAC
+#ifndef Q_OS_MAC
             // stupid pixel alignment rubbish, I really should be using floats..
             h+=1;
 #endif
diff --git a/SleepLib/calcs.cpp b/SleepLib/calcs.cpp
index 70fb0b92..bf01aeb6 100644
--- a/SleepLib/calcs.cpp
+++ b/SleepLib/calcs.cpp
@@ -568,7 +568,7 @@ void FlowParser::flagEvents()
 
     double start=m_flow->first();
    // double sps=1000.0/m_rate;
-    double st,mt,et, dur;
+    double st,et, dur; //mt
     qint64 len;
 
     bool allowDuplicates=PROFILE.cpap->userEventDuplicates();
@@ -1042,7 +1042,7 @@ void zMaskProfile::scanPressure(Session * session)
     Pressure.clear();
 
     int prescnt=0;
-    EventStoreType pressure;
+    //EventStoreType pressure;
     if (session->eventlist.contains(CPAP_Pressure)) {
         prescnt=session->count(CPAP_Pressure);
         Pressure.reserve(prescnt);
@@ -1071,11 +1071,11 @@ void zMaskProfile::scanLeakList(EventList * el)
     EventStoreType * dptr=el->rawData();
     EventStoreType * eptr=dptr+count;
     quint32 * tptr=el->rawTime();
-    EventDataType gain=el->gain();
+    //EventDataType gain=el->gain();
 
     EventStoreType pressure,leak;
 
-    EventDataType fleak;
+    //EventDataType fleak;
     QMap<EventStoreType, EventDataType>::iterator pmin;
     qint64 ti;
     bool found;
@@ -1117,7 +1117,7 @@ void zMaskProfile::scanLeakList(EventList * el)
 //                }
 //            }
         } else {
-            int i=5;
+            //int i=5;
         }
     }
 
@@ -1163,7 +1163,7 @@ void zMaskProfile::updatePressureMin()
         nthi=floor(nth);
 
         sum1=0,sum2=0;
-        w1,w2=0;
+        w1=0,w2=0;
 
         EventDataType v1=0,v2;
 
diff --git a/SleepLib/day.cpp b/SleepLib/day.cpp
index df83a214..4b2706de 100644
--- a/SleepLib/day.cpp
+++ b/SleepLib/day.cpp
@@ -196,7 +196,7 @@ EventDataType Day::percentile(ChannelID code,EventDataType percentile)
 
         int value;
         qint64 weight;
-        qint64 tval;
+        //qint64 tval;
         if (timeweight) {
             for (QHash<EventStoreType, quint32>::iterator i=tei.value().begin();i!=tei.value().end();i++) {
                 value=i.key();
diff --git a/SleepLib/loader_plugins/icon_loader.cpp b/SleepLib/loader_plugins/icon_loader.cpp
index 752c105b..d0784522 100644
--- a/SleepLib/loader_plugins/icon_loader.cpp
+++ b/SleepLib/loader_plugins/icon_loader.cpp
@@ -170,7 +170,7 @@ int FPIconLoader::OpenMachine(Machine *mach, QString & path, Profile * profile)
     for (int i=0;i<flw.size();i++) {
         OpenFLW(mach,flw[i],profile);
     }
-    SessionID zz,sid,st;
+    SessionID zz,sid;//,st;
     float hours,dur,mins;
 
     qDebug() << "Last 20 Sessions";
@@ -205,7 +205,7 @@ int FPIconLoader::OpenMachine(Machine *mach, QString & path, Profile * profile)
     QList<FPWaveChunk> chunks;
     for (QMap<int,QDate>::iterator dit=FLWDate.begin();dit!=FLWDate.end();dit++) {
         int k=dit.key();
-        QDate date=dit.value();
+        //QDate date=dit.value();
 //        QList<Session *> values = SessDate.values(date);
         for (int j=0;j<FLWTS[k].size();j++) {
 
@@ -247,11 +247,13 @@ int FPIconLoader::OpenMachine(Machine *mach, QString & path, Profile * profile)
 
 bool FPIconLoader::OpenFLW(Machine * mach,QString filename, Profile * profile)
 {
+    Q_UNUSED(mach);
+    Q_UNUSED(profile);
     QByteArray data;
     quint16 t1;
     quint32 ts;
     double ti;
-    qint8 b;
+    //qint8 b;
     EventList * flow=NULL, * pressure=NULL, *leak=NULL;
     QDateTime datetime;
     quint8 a1,a2;
@@ -397,7 +399,7 @@ bool FPIconLoader::OpenFLW(Machine * mach,QString filename, Profile * profile)
                 break;
             if (!((p2[0]==0xff) && (p2[1]==0xff))) {
                 if (count>0) {
-                    int i=5;
+                    //int i=5;
                 }
                 do {
                     while ((*p++ != 0xff) && (p < endbuf)) {
@@ -421,10 +423,10 @@ bool FPIconLoader::OpenFLW(Machine * mach,QString filename, Profile * profile)
 
             count++;
 
-            if (pr<0) {
-                quint16 z3=pr;
-                int i=5;
-            }
+            //if (pr<0) {
+                //quint16 z3=pr;
+               // int i=5;
+            //}
 
             if (leak) {
                 leak->AddEvent(ti,lkaj);
@@ -436,10 +438,10 @@ bool FPIconLoader::OpenFLW(Machine * mach,QString filename, Profile * profile)
             if (flow) {
                 qint16 tmp;
                 unsigned char * bb=(unsigned char *)buf;
-                char c;
-                if (len>50) {
-                    int i=5;
-                }
+                //char c;
+                //if (len>50) {
+                    //int i=5;
+                //}
 
                 EventDataType val;
                 for (int i=0;i<len;i++) {
@@ -536,7 +538,7 @@ bool FPIconLoader::OpenSummary(Machine * mach,QString filename, Profile * profil
     in.setVersion(QDataStream::Qt_4_6);
     in.setByteOrder(QDataStream::LittleEndian);
 
-    quint16 t1,t2;
+    quint16 t1;//,t2;
     quint32 ts;
     //QByteArray line;
     unsigned char a1,a2, a3,a4, a5, p1, p2,  p3, p4, p5, j1, j2, j3 ,j4,j5,j6,j7, x1, x2;
@@ -642,6 +644,9 @@ bool FPIconLoader::OpenSummary(Machine * mach,QString filename, Profile * profil
 
 bool FPIconLoader::OpenDetail(Machine * mach, QString filename, Profile * profile)
 {
+    Q_UNUSED(mach);
+    Q_UNUSED(profile);
+
     qDebug() << filename;
     QByteArray header;
     QFile file(filename);
@@ -664,7 +669,7 @@ bool FPIconLoader::OpenDetail(Machine * mach, QString filename, Profile * profil
 
     QByteArray index;
     index=file.read(0x800);
-    long size=index.size(),pos=0;
+    //long size=index.size(),pos=0;
     QDataStream in(index);
 
     in.setVersion(QDataStream::Qt_4_6);
diff --git a/SleepLib/loader_plugins/mseries_loader.cpp b/SleepLib/loader_plugins/mseries_loader.cpp
index 9d91898e..524a1067 100644
--- a/SleepLib/loader_plugins/mseries_loader.cpp
+++ b/SleepLib/loader_plugins/mseries_loader.cpp
@@ -117,6 +117,7 @@ blockLayoutOffsets   {
 
 int MSeriesLoader::Open(QString & path,Profile *profile)
 {
+    Q_UNUSED(profile);
     // Until a smartcard reader is written, this is not an auto-scanner.. it just opens a block file..
 
     QFile file(path);
@@ -138,13 +139,13 @@ int MSeriesLoader::Open(QString & path,Profile *profile)
     if (magic!=0x5249) { // "RI" Respironics Magic number
         return 0;
     }
-    quint8 cardtype=cardinfo[2];
-    quint8 cardver=cardinfo[3];
+    //quint8 cardtype=cardinfo[2];
+    //quint8 cardver=cardinfo[3];
 
     quint16 user_offset=(cardinfo[4] << 8) | cardinfo[5];
-    quint16 rx_offset=(cardinfo[8] << 8) | cardinfo[9];
+    //quint16 rx_offset=(cardinfo[8] << 8) | cardinfo[9];
     quint16 control_offset=(cardinfo[12] << 8) | cardinfo[13];
-    quint16 data_offset=(cardinfo[16] << 8) | cardinfo[17];
+    //quint16 data_offset=(cardinfo[16] << 8) | cardinfo[17];
 
 
     const char * userinfo=block.data()+user_offset;
@@ -164,7 +165,7 @@ int MSeriesLoader::Open(QString & path,Profile *profile)
         qDebug() << "MSeries UserInfo block checksum failure" << path;
     }
 
-    const unsigned char * rxblock=(unsigned char *)block.data()+rx_offset;
+    //const unsigned char * rxblock=(unsigned char *)block.data()+rx_offset;
 
     unsigned char * controlblock=(unsigned char *)block.data()+control_offset;
     quint16 count=controlblock[0] << 8 | controlblock[1]; // number of control blocks
@@ -262,7 +263,7 @@ int MSeriesLoader::Open(QString & path,Profile *profile)
                 u1=cb[0];
                 cb++;
 
-                if ((cb[0]==0xfe)) {
+                if (cb[0]==0xfe) {
                     u1=cb[0] << 8 | cb[1]; // fe 0a, followed by timestamp
                     cb+=2;
                     break; // start on the next timestamp
@@ -308,7 +309,7 @@ int MSeriesLoader::Open(QString & path,Profile *profile)
     } while (cb < endcard && !done);
 
     done=false;
-    bool first=true;
+    //bool first=true;
     quint8 exch;
     cnt=0;
     do {
diff --git a/SleepLib/loader_plugins/resmed_loader.cpp b/SleepLib/loader_plugins/resmed_loader.cpp
index e8f41d62..1eb8157e 100644
--- a/SleepLib/loader_plugins/resmed_loader.cpp
+++ b/SleepLib/loader_plugins/resmed_loader.cpp
@@ -91,12 +91,12 @@ bool EDFParser::Parse()
     bool ok;
     QString temp,temp2;
 
-    version=QString::fromAscii(header.version,8).toLong(&ok);
+    version=QString::fromLatin1(header.version,8).toLong(&ok);
     if (!ok)
         return false;
 
-    //patientident=QString::fromAscii(header.patientident,80);
-    recordingident=QString::fromAscii(header.recordingident,80); // Serial number is in here..
+    //patientident=QString::fromLatin1(header.patientident,80);
+    recordingident=QString::fromLatin1(header.recordingident,80); // Serial number is in here..
     int snp=recordingident.indexOf("SRN=");
     serialnumber.clear();
     /*char * idx=index(header.recordingident,'=');
@@ -112,7 +112,7 @@ bool EDFParser::Parse()
             break;
         serialnumber+=recordingident[i];
     }
-    QDateTime startDate=QDateTime::fromString(QString::fromAscii(header.datetime,16),"dd.MM.yyHH.mm.ss");
+    QDateTime startDate=QDateTime::fromString(QString::fromLatin1(header.datetime,16),"dd.MM.yyHH.mm.ss");
     //startDate.toTimeSpec(Qt::UTC);
     QDate d2=startDate.date();
     if (d2.year()<2000) {
@@ -128,18 +128,18 @@ bool EDFParser::Parse()
 
     //qDebug() << startDate.toString("yyyy-MM-dd HH:mm:ss");
 
-    num_header_bytes=QString::fromAscii(header.num_header_bytes,8).toLong(&ok);
+    num_header_bytes=QString::fromLatin1(header.num_header_bytes,8).toLong(&ok);
     if (!ok)
         return false;
-    //reserved44=QString::fromAscii(header.reserved,44);
-    num_data_records=QString::fromAscii(header.num_data_records,8).toLong(&ok);
+    //reserved44=QString::fromLatin1(header.reserved,44);
+    num_data_records=QString::fromLatin1(header.num_data_records,8).toLong(&ok);
     if (!ok)
         return false;
 
-    dur_data_record=QString::fromAscii(header.dur_data_records,8).toDouble(&ok)*1000.0;
+    dur_data_record=QString::fromLatin1(header.dur_data_records,8).toDouble(&ok)*1000.0;
     if (!ok)
         return false;
-    num_signals=QString::fromAscii(header.num_signals,4).toLong(&ok);
+    num_signals=QString::fromLatin1(header.num_signals,4).toLong(&ok);
     if (!ok)
         return false;
 
@@ -218,7 +218,7 @@ bool EDFParser::Open(QString name)
         datasize=filesize-EDFHeaderSize;
         if (datasize<0) return false;
         qDebug() << "Size of" << name << "uncompressed=" << filesize;
-        gzFile f=gzopen(name.toAscii(),"rb");
+        gzFile f=gzopen(name.toLatin1(),"rb");
         if (!f) {
             qDebug() << "EDFParser::Open() Couldn't open file" << name;
             return false;
@@ -478,9 +478,9 @@ int ResmedLoader::Open(QString & path,Profile *profile)
 
     QHash<qint16,QList<time_t> > daystarttimes;
     QHash<qint16,QList<time_t> > dayendtimes;
-    qint16 on,off;
-    qint16 o1[10],o2[10];
-    time_t st,et;
+    //qint16 on,off;
+    //qint16 o1[10],o2[10];
+    //time_t st,et;
     time_t time=stredf.startdate/1000L; // == 12pm on first day
 //    for (int i=0;i<days;i++) {
 //        EDFSignal *maskon=stredf.lookup["Mask On"];
@@ -636,7 +636,7 @@ int ResmedLoader::Open(QString & path,Profile *profile)
     /////////////////////////////////////////////////////////////////////////////
     // Scan over file list and knock out of dayused list
     /////////////////////////////////////////////////////////////////////////////
-    int dn;
+    //int dn;
 //    for (QMap<SessionID,QStringList>::iterator si=sessfiles.begin();si!=sessfiles.end();si++) {
 //        sessionid=si.key();
 
diff --git a/SleepLib/loader_plugins/zeo_loader.cpp b/SleepLib/loader_plugins/zeo_loader.cpp
index ee0569d4..a93a1ce2 100644
--- a/SleepLib/loader_plugins/zeo_loader.cpp
+++ b/SleepLib/loader_plugins/zeo_loader.cpp
@@ -133,7 +133,7 @@ int ZEOLoader::OpenFile(QString filename)
     QDateTime start_of_night, end_of_night, rise_time;
     SessionID sid;
 
-    const qint64 WindowSize=30000;
+    //const qint64 WindowSize=30000;
     qint64 st,tt;
     int stage;
 
diff --git a/SleepLib/machine.cpp b/SleepLib/machine.cpp
index fbef30ac..2ea401ac 100644
--- a/SleepLib/machine.cpp
+++ b/SleepLib/machine.cpp
@@ -109,7 +109,7 @@ QDate Machine::AddSession(Session *s,Profile *p)
 
     sessionlist[s->session()]=s; // To make sure it get's saved later even if it's not wanted.
 
-    int drift=PROFILE.cpap->clockDrift();
+    //int drift=PROFILE.cpap->clockDrift();
 
     QDateTime d2=QDateTime::fromTime_t(s->first()/1000);
 
@@ -162,7 +162,7 @@ QDate Machine::AddSession(Session *s,Profile *p)
     dit=day.find(date);
     if (dit==day.end()) {
         //QString dstr=date.toString("yyyyMMdd");
-        //qDebug("Adding Profile Day %s",dstr.toAscii().data());
+        //qDebug("Adding Profile Day %s",dstr.toLatin1().data());
         dd=new Day(this);
         day[date]=dd;
         // Add this Day record to profile
diff --git a/SleepLib/machine_loader.cpp b/SleepLib/machine_loader.cpp
index 4c9a533b..10142d81 100644
--- a/SleepLib/machine_loader.cpp
+++ b/SleepLib/machine_loader.cpp
@@ -70,7 +70,7 @@ bool MachineLoader::compressFile(QString inpath, QString outpath)
         return false;
     }
     f.close();
-    gzFile gz=gzopen(outpath.toAscii(),"wb");
+    gzFile gz=gzopen(outpath.toLatin1(),"wb");
     //gzbuffer(gz,65536*2);
     if (!gz) {
         qDebug() << "compressFile() Couldn't open" << outpath <<"for writing";
diff --git a/SleepyHeadQT.pro b/SleepyHeadQT.pro
index c3f63c38..ea929b84 100644
--- a/SleepyHeadQT.pro
+++ b/SleepyHeadQT.pro
@@ -4,7 +4,15 @@
 #
 #-------------------------------------------------
 
-QT += core gui webkit opengl network xml
+QT += core gui opengl network xml
+
+contains(QT_MAJOR_VERSION,5) {
+    QT += webkitwidgets
+}
+
+!contains(QT_MAJOR_VERSION,5) {
+    QT += webkit
+}
 
 CONFIG += rtti
 
diff --git a/exportcsv.cpp b/exportcsv.cpp
index 12fa4d4b..e8d1d7b9 100644
--- a/exportcsv.cpp
+++ b/exportcsv.cpp
@@ -193,7 +193,7 @@ void ExportCSV::on_exportButton_clicked()
             header+=sep+schema::channel[p90list[i]].label()+tr(" %1%").arg(percent,0,'f',0);
     }
     header+=newline;
-    file.write(header.toAscii());
+    file.write(header.toLatin1());
     QDate date=ui->startDate->date();
     Daily *daily=mainwin->getDaily();
     QDate daily_date=daily->getDate();
@@ -230,7 +230,7 @@ void ExportCSV::on_exportButton_clicked()
                 for (int i=0;i<p90list.size();i++)
                     data+=sep+QString::number(day->p90(p90list.at(i)));
                 data+=newline;
-                file.write(data.toAscii());
+                file.write(data.toLatin1());
 
             } else if (ui->rb1_Sessions->isChecked()) {
                 for (int i=0;i<day->size();i++) {
@@ -258,7 +258,7 @@ void ExportCSV::on_exportButton_clicked()
                     for (int j=0;j<p90list.size();j++)
                         data+=sep+QString::number(day->p90(p90list.at(j)));
                     data+=newline;
-                    file.write(data.toAscii());
+                    file.write(data.toLatin1());
                 }
             } else if (ui->rb1_details->isChecked()) {
                 QList<ChannelID> all=countlist;
@@ -280,7 +280,7 @@ void ExportCSV::on_exportButton_clicked()
                                     data+=sep+schema::channel[key].name();
                                     data+=sep+QString::number(ev->data(q),'f',2);
                                     data+=newline;
-                                    file.write(data.toAscii());
+                                    file.write(data.toLatin1());
                                 }
                             }
                         }
diff --git a/main.cpp b/main.cpp
index 4f706937..f4fc643e 100644
--- a/main.cpp
+++ b/main.cpp
@@ -115,7 +115,10 @@ int main(int argc, char *argv[])
 #ifdef Q_WS_X11
     XInitThreads();
 #endif
+
+#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
     QGL::setPreferredPaintEngine(QPaintEngine::OpenGL);
+#endif
 
     bool force_login_screen=false;
     QApplication a(argc, argv);
@@ -248,8 +251,12 @@ int main(int argc, char *argv[])
                                 PREF["Fonts_Application_Italic"].toBool()));
 
     qDebug() << "Selected" << QApplication::font().family();
-    qInstallMsgHandler(MyOutputHandler);
 
+//#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
+//    qInstallMessageHandler(MyOutputHandler);
+//#else
+    qInstallMsgHandler(MyOutputHandler);
+//#endif
     MainWindow w;
     mainwin=&w;
 
diff --git a/mainwindow.cpp b/mainwindow.cpp
index eb15ac3e..8ae3f993 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -86,7 +86,7 @@ MainWindow::MainWindow(QWidget *parent) :
     //ui->tabWidget->setCurrentIndex(1);
 
     // Disable Screenshot on Mac Platform,as it doesn't work, and the system provides this functionality anyway.
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
     ui->action_Screenshot->setVisible(false);
 #endif
 
@@ -121,7 +121,7 @@ MainWindow::MainWindow(QWidget *parent) :
         ui->logText->hide();
     }
 
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
     PROFILE.appearance->setAntiAliasing(false);
 #endif
     ui->action_Link_Graph_Groups->setChecked(PROFILE.general->linkGroups());
@@ -233,7 +233,7 @@ void MainWindow::Notify(QString s,QString title,int ms)
 
 void MainWindow::Startup()
 {
-    qDebug() << PREF["AppName"].toString().toAscii()+" v"+VersionString.toAscii() << "built with Qt"<< QT_VERSION_STR << "on" << __DATE__ << __TIME__;
+    qDebug() << PREF["AppName"].toString().toLatin1()+" v"+VersionString.toLatin1() << "built with Qt"<< QT_VERSION_STR << "on" << __DATE__ << __TIME__;
     qstatus->setText(tr("Loading Data"));
     qprogress->show();
     //qstatusbar->showMessage(tr("Loading Data"),0);
@@ -316,7 +316,7 @@ void MainWindow::on_action_Import_Data_triggered()
         w.setFileMode(QFileDialog::Directory);
         w.setOption(QFileDialog::ShowDirsOnly, true);
 
-#if defined(Q_WS_MAC) && (QT_VERSION_CHECK(4,8,0) > QT_VERSION)
+#if defined(Q_OS_MAC) && (QT_VERSION_CHECK(4,8,0) > QT_VERSION)
         // Fix for tetragon, 10.6 barfs up Qt's custom dialog
         w.setOption(QFileDialog::DontUseNativeDialog,true);
 #else
@@ -1443,7 +1443,7 @@ void MainWindow::on_overviewButton_clicked()
 
 void MainWindow::on_webView_loadFinished(bool arg1)
 {
-    arg1=arg1;
+    Q_UNUSED(arg1);
     qprogress->hide();
     if (first_load) {
         QTimer::singleShot(0,this,SLOT(Startup()));
@@ -1567,7 +1567,7 @@ void MainWindow::on_action_Screenshot_triggered()
 }
 void MainWindow::DelayedScreenshot()
 {
-//#ifdef Q_WS_MAC
+//#ifdef Q_OS_MAC
 //    CGImageRef windowImage = CGWindowListCreateImage(imageBounds, singleWindowListOptions, windowID, imageOptions);
 //    originalPixmap = new QPixmap(QPixmap::fromMacCGImageRef(windowImage));
 
@@ -1740,7 +1740,7 @@ void MainWindow::PrintReport(gGraphView *gv,QString name, QDate date)
     printer->setNumCopies(1);
     printer->setPageMargins(10,10,10,10,QPrinter::Millimeter);
     QPrintDialog dialog(printer);
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
     // QTBUG-17913
     QApplication::processEvents();
 #endif
@@ -2164,14 +2164,21 @@ void MainWindow::PrintReport(gGraphView *gv,QString name, QDate date)
         //painter.beginNativePainting();
         //g->showTitle(false);
         int hhh=full_graph_height-normal_height;
-        QPixmap pm=g->renderPixmap(virt_width,hhh,1);//fscale);
+        QPixmap pm2=g->renderPixmap(virt_width,hhh,1);
+        QImage pm=pm2.toImage();//fscale);
+        pm2.detach();
         //g->showTitle(true);
         //painter.endNativePainting();
         g->m_marginbottom=tmb;
         PROFILE.appearance->setAntiAliasing(aa_setting);
 
+
         if (!pm.isNull()) {
-            painter.drawPixmap(0,top,virt_width,full_graph_height-normal_height,pm);
+            painter.drawImage(0,top,pm);;
+
+
+
+            //painter.drawImage(0,top,virt_width,full_graph_height-normal_height,pm);
         }
         top+=full_graph_height;
 
diff --git a/oximetry.cpp b/oximetry.cpp
index 4f8bff6c..15319845 100644
--- a/oximetry.cpp
+++ b/oximetry.cpp
@@ -939,7 +939,7 @@ void Oximetry::on_RefreshPortsButton_clicked()
     bool current_found=false;
 
     // Windows build mixes these up
-#if defined(Q_WS_WIN32) || defined(Q_WS_MAC)
+#if defined(Q_WS_WIN32) || defined(Q_OS_MAC)
 #define qesPORTNAME portName
 #else
 #define qesPORTNAME physName
diff --git a/qextserialport/posix_qextserialport.cpp b/qextserialport/posix_qextserialport.cpp
index c7f923cd..1f5be897 100644
--- a/qextserialport/posix_qextserialport.cpp
+++ b/qextserialport/posix_qextserialport.cpp
@@ -680,9 +680,9 @@ bool QextSerialPort::open(OpenMode mode)
     if (mode == QIODevice::NotOpen)
         return isOpen();
     if (!isOpen()) {
-        qDebug() << "trying to open file" << port.toAscii();
+        qDebug() << "trying to open file" << port.toLatin1();
         //note: linux 2.6.21 seems to ignore O_NDELAY flag
-        if ((fd = ::open(port.toAscii() ,O_RDWR | O_NOCTTY | O_NDELAY)) != -1) {
+        if ((fd = ::open(port.toLatin1() ,O_RDWR | O_NOCTTY | O_NDELAY)) != -1) {
             qDebug("file opened succesfully");
 
             setOpenMode(mode);              // Flag the port as opened
diff --git a/qextserialport/win_qextserialport.cpp b/qextserialport/win_qextserialport.cpp
index af1cdb60..13a064da 100644
--- a/qextserialport/win_qextserialport.cpp
+++ b/qextserialport/win_qextserialport.cpp
@@ -53,7 +53,7 @@ bool QextSerialPort::open(OpenMode mode) {
         return isOpen();
     if (!isOpen()) {
         /*open the port*/
-        Win_Handle=CreateFileA(port.toAscii(), GENERIC_READ|GENERIC_WRITE,
+        Win_Handle=CreateFileA(port.toLatin1(), GENERIC_READ|GENERIC_WRITE,
                               0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL);
         if (Win_Handle!=INVALID_HANDLE_VALUE) {
             QIODevice::open(mode);
diff --git a/quazip/unzip.c b/quazip/unzip.c
index 4ab1bd3f..bbec7647 100644
--- a/quazip/unzip.c
+++ b/quazip/unzip.c
@@ -1245,7 +1245,7 @@ extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
         return UNZ_PARAMERROR;
 
 
-    if ((pfile_in_zip_read_info->read_buffer == NULL))
+    if (pfile_in_zip_read_info->read_buffer == NULL)
         return UNZ_END_OF_LIST_OF_FILE;
     if (len==0)
         return 0;
diff --git a/quazip/zip.c b/quazip/zip.c
index 248d4849..9bc6ae15 100644
--- a/quazip/zip.c
+++ b/quazip/zip.c
@@ -776,9 +776,9 @@ extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
     zi->ci.flag = 0;
     if ((level==8) || (level==9))
       zi->ci.flag |= 2;
-    if ((level==2))
+    if (level==2)
       zi->ci.flag |= 4;
-    if ((level==1))
+    if (level==1)
       zi->ci.flag |= 6;
     if (password != NULL)
     {
diff --git a/version.h b/version.h
index fc3d109d..1b648ebb 100644
--- a/version.h
+++ b/version.h
@@ -13,7 +13,7 @@ const QString FullVersionString=QString().sprintf("%i.%i.%i-%i",major_version,mi
 
 const QString ReleaseStatus="beta";
 
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
     const QString PlatformString="MacOSX";
 #elif defined(Q_WS_WIN32)
     const QString PlatformString="Win32";