Refactoring
[weightgraph] / weightgraph / weightgraphview.cpp
index 4e0d65f..5d91c7b 100644 (file)
@@ -1,9 +1,10 @@
 #include "weightgraphview.h"
 #include "settings.h"
-#include <QPainter>
+#include <cmath>
+#include <limits>
 #include <QDebug>
+#include <QPainter>
 #include <QTimer>
-#include <cmath>
 #include <QtGui/QX11Info>
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
@@ -39,7 +40,6 @@ QSize WeightGraphView::sizeHint() const
 
 void WeightGraphView::keyPressEvent(QKeyEvent* event)
 {
-  //qDebug() << "Key pressed: " << event->key();
   switch (event->key()) {
   case Qt::Key_F7:
       decPeriod();
@@ -54,32 +54,39 @@ void WeightGraphView::keyPressEvent(QKeyEvent* event)
   QWidget::keyPressEvent(event);
 }
 
-// Macros to transform dates and weights to paintdevice coords
-#define D_X(d) ((d)*qreal(width())/days)
-#define DW_X(dw) D_X(f.daysTo((dw).date))
-#define W_Y(w) (height()*(maxW-(w))/weightInterval)
-#define DW_Y(dw) W_Y((dw).weight)
+// X-coordinate of QDate / DateWeigth
+#define DATE_X(d) ((d)*qreal(width())/days)
+#define DW_X(dw) DATE_X(f.daysTo((dw).date))
+
+// Y-coordinate of Weight / DateWeight
+#define WEIGHT_Y(w) (height()*(maxW-(w))/weightInterval)
+#define DW_Y(dw) WEIGHT_Y((dw).weight)
+
+// Coordinate point of DateWeight
 #define DW_POINT(dw) QPointF(DW_X(dw), DW_Y(dw))
 
-inline double weightIntervalToMult(double wi)
-{
-  if (wi <= 0.2) return 0.01;
-  else if (wi <= 0.5) return 0.025;
-  else if (wi <= 1.0) return 0.05;
-  else if (wi <= 2.0) return 0.1;
-  else if (wi <= 5.0) return 0.25;
-  else if (wi <= 10.0) return 0.5;
-  else if (wi <= 20.0) return 1.0;
-  else if (wi <= 50.0) return 2.5;
-  else if (wi <= 100.0) return 5.0;
-  else if (wi <= 200.0) return 10.0;
-  else if (wi <= 500.0) return 25.0;
-  else if (wi <= 1000.0) return 50.0;
-  else return 100.0;
+namespace {
+  inline double weightIntervalToMult(double wi)
+  {
+    if (wi <= 0.2) return 0.01;
+    else if (wi <= 0.5) return 0.025;
+    else if (wi <= 1.0) return 0.05;
+    else if (wi <= 2.0) return 0.1;
+    else if (wi <= 5.0) return 0.25;
+    else if (wi <= 10.0) return 0.5;
+    else if (wi <= 20.0) return 1.0;
+    else if (wi <= 50.0) return 2.5;
+    else if (wi <= 100.0) return 5.0;
+    else if (wi <= 200.0) return 10.0;
+    else if (wi <= 500.0) return 25.0;
+    else if (wi <= 1000.0) return 50.0;
+    else return 100.0;
+  }
 }
 
 void WeightGraphView::paintEvent(QPaintEvent *)
 {
+  // TODO: split this monster function!
   QPainter painter(this);
   painter.setRenderHint(QPainter::Antialiasing);
 
@@ -95,8 +102,8 @@ void WeightGraphView::paintEvent(QPaintEvent *)
   }
   else {
     bool firstFound = false;
-    min = 1e30;
-    max = -1e30;
+    min = std::numeric_limits<double>::max();
+    max = std::numeric_limits<double>::min();
     const QDate &l = allWeights.last().date;
     for(int i=0; i < allWeights.size(); i++) {
       if (period == 0 || firstFound || allWeights[i].date.daysTo(l) <= period) {
@@ -172,8 +179,8 @@ void WeightGraphView::paintEvent(QPaintEvent *)
     painter.setPen(Qt::NoPen);
     painter.setBrush(QColor(0,255,0,100));
     painter.setClipRect(QRectF(0,0,width(),height()));
-    painter.drawRect(QRectF(QPointF(0, W_Y(Settings::goalWeightMax())),
-                            QPointF(width(), W_Y(Settings::goalWeightMin()))));
+    painter.drawRect(QRectF(QPointF(0, WEIGHT_Y(Settings::goalWeightMax())),
+                            QPointF(width(), WEIGHT_Y(Settings::goalWeightMin()))));
     painter.setClipping(false);
     painter.setPen(oldPen);
     painter.setBrush(oldBrush);
@@ -188,15 +195,15 @@ void WeightGraphView::paintEvent(QPaintEvent *)
   int count = 0;
   for(double w=ceil(minW/mult)*mult; w < maxW; w += mult, count++) {
     double len = count%5==0 ? 7.0 : 4.0;
-    painter.drawLine(QPointF(-len,W_Y(w)),QPointF(len,W_Y(w)));
+    painter.drawLine(QPointF(-len,WEIGHT_Y(w)),QPointF(len,WEIGHT_Y(w)));
     if (count%5 == 0) {
       QPen p = painter.pen();
       painter.setPen(QColor(50,50,50));
-      painter.drawLine(QPointF(len,W_Y(w)),QPointF(width(),W_Y(w)));
+      painter.drawLine(QPointF(len,WEIGHT_Y(w)),QPointF(width(),WEIGHT_Y(w)));
       painter.setPen(p);
       QString text = tr("%1").arg(double(w),0,'f', mult <= 0.25 ? 2 : 1);
       QSize textSize = painter.fontMetrics().size(0, text);
-      painter.drawText(QPointF(-len-3-textSize.width(), W_Y(w)+6), text);
+      painter.drawText(QPointF(-len-3-textSize.width(), WEIGHT_Y(w)+6), text);
     }
   }
 
@@ -210,16 +217,16 @@ void WeightGraphView::paintEvent(QPaintEvent *)
     QString text = f.addDays(day).toString(Qt::ISODate);
     QSize textSize = painter.fontMetrics().size(0, text);
     double tickLen;
-    if (D_X(day)-textSize.width()/2 > endOfLastDate + 10) {
+    if (DATE_X(day)-textSize.width()/2 > endOfLastDate + 10) {
       tickLen = 5.0;
-      painter.drawText(QPointF(D_X(day)-textSize.width()/2,
-                               W_Y(minW)+18), text);
-      endOfLastDate = D_X(day)+textSize.width()/2;
+      painter.drawText(QPointF(DATE_X(day)-textSize.width()/2,
+                               WEIGHT_Y(minW)+18), text);
+      endOfLastDate = DATE_X(day)+textSize.width()/2;
     }
     else
       tickLen = 3.0;
-    painter.drawLine(QPointF(D_X(day), W_Y(minW)-tickLen),
-                     QPointF(D_X(day), W_Y(minW)+tickLen));
+    painter.drawLine(QPointF(DATE_X(day), WEIGHT_Y(minW)-tickLen),
+                     QPointF(DATE_X(day), WEIGHT_Y(minW)+tickLen));
   }
 
   // The weight data
@@ -233,8 +240,8 @@ void WeightGraphView::paintEvent(QPaintEvent *)
 void WeightGraphView::show()
 {
   QWidget::show();
-  grabZoomKeys(Settings::grabZoomKeys()); //Need to be regrabbed somewhy
-  //Work around a bug: hidden graphs don't update. Must wait for the
+  grabZoomKeysForWindow(winId(), Settings::grabZoomKeys()); //Need to be regrabbed somewhy
+  //Work around a bug: hidden graphs don't update - must wait for the
   //graph to actually show up, then call update.
   QTimer *tmp = new QTimer(this);
   tmp->setSingleShot(true);
@@ -243,9 +250,17 @@ void WeightGraphView::show()
   tmp->start();
 }
 
-void WeightGraphView::grabZoomKeys(bool grab)
+void WeightGraphView::update() {
+  grabZoomKeysForWindow(winId(), Settings::grabZoomKeys());
+  QWidget::update();
+}
+
+void WeightGraphView::grabZoomKeys(bool grab) {
+  WeightGraphView::grabZoomKeysForWindow(winId(), grab);
+}
+void WeightGraphView::grabZoomKeysForWindow(WId winId, bool grab)
 {
-  if (!winId()) {
+  if (!winId) {
     qWarning("Can't grab keys unless we have a window id");
     return;
   }
@@ -253,20 +268,34 @@ void WeightGraphView::grabZoomKeys(bool grab)
   unsigned long val = (grab) ? 1 : 0;
   Atom atom = XInternAtom(QX11Info::display(), "_HILDON_ZOOM_KEY_ATOM", False);
   if (!atom) {
-    qWarning("Unable to obtain _HILDON_ZOOM_KEY_ATOM. This example will only work "
-             "on a Maemo 5 device!");
+    qWarning("Unable to obtain _HILDON_ZOOM_KEY_ATOM. Is this Maemo 5?");
     return;
   }
 
+  XChangeProperty (QX11Info::display(), winId, atom, XA_INTEGER, 32,
+                   PropModeReplace, reinterpret_cast<unsigned char *>(&val), 1);
+}
 
-  XChangeProperty (QX11Info::display(),
-                   winId(),
-                   atom,
-                   XA_INTEGER,
-                   32,
-                   PropModeReplace,
-                   reinterpret_cast<unsigned char *>(&val),
-                   1);
+namespace {
+  int getNumberOfDaysBetweenFirstAndLastEntry(WeightDataModel *wdm) {
+    QDate first = wdm->getWeights().first().date;
+    QDate last = wdm->getWeights().last().date;
+    return first.daysTo(last);
+  }
+}
 
-  //qDebug() << "Grabbed for winId " << winId();
+#define PERIOD_CHANGE_FACTOR 0.05
+void WeightGraphView::incPeriod() {
+  if (period == 0)
+    period = getNumberOfDaysBetweenFirstAndLastEntry(wdm) + 1;
+  else
+    period += qMax(1, int(period*PERIOD_CHANGE_FACTOR));
+  update();
+}
+void WeightGraphView::decPeriod() {
+  if (period == 0)
+    period = getNumberOfDaysBetweenFirstAndLastEntry(wdm) - 1;
+  else
+    period = qMax(2, qMin(period-1, int(period*(1-PERIOD_CHANGE_FACTOR))));
+  update();
 }