--- /dev/null
+#!/bin/sh
+dch --no-auto-nmu -i -m
--- /dev/null
+weightgraph (1.0.0) unstable; urgency=low
+
+ * Initial Release.
+
+ -- Visa Putkinen <visa.putkinen@iki.fi> Mon, 21 Feb 2011 20:21:04 +0200
--- /dev/null
+Source: weightgraph
+Section: user/utilities
+Priority: optional
+Maintainer: Visa Putkinen <visa.putkinen@iki.fi>
+Build-Depends: debhelper (>= 5), libqt4-dev
+Standards-Version: 3.7.3
+Homepage: <insert the upstream URL, if relevant>
+
+Package: weightgraph
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Keep track of your weight.
+ Use weightgraph to record your daily weights. It will plot a nice graph of the
+ weights to help you keep up your weight control motivation.
+XSBC-Bugtracker: mailto:visa.putkinen@iki.fi
+XSBC-Maemo-Display-Name: WeightGraph
+XB-Maemo-Icon-26:
+ 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
--- /dev/null
+Upstream Author(s):
+
+ Visa Putkinen <visa.putkinen@iki.fi>
+
+Copyright:
+
+ <Copyright (C) 2011 Visa Putkinen>
+
+License:
+
+ This package 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 package 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 package; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+On Debian systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
+
+The Debian packaging is (C) 2011, Visa Putkinen <visa@nana> and
+is licensed under the GPL, see above.
--- /dev/null
+#!/bin/sh
+# postinst script for weightgraph
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <postinst> `configure' <most-recently-configured-version>
+# * <old-postinst> `abort-upgrade' <new version>
+# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+# <new-version>
+# * <postinst> `abort-remove'
+# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+# <failed-install-package> <version> `removing'
+# <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ configure)
+ gtk-update-icon-cache -f /usr/share/icons/hicolor
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
--- /dev/null
+#!/usr/bin/make -f
+APPNAME = weightgraph
+
+# Use hardware floating point
+ifneq (,$(findstring vfp,$(DEB_BUILD_OPTIONS)))
+CFLAGS += -mfpu=vfp -mfloat-abi=softfp
+endif
+
+builddir:
+ mkdir -p builddir
+
+builddir/Makefile: builddir
+ cd builddir && qmake-qt4 PREFIX=/usr ../$(APPNAME).pro
+
+build: build-stamp
+
+build-stamp: builddir/Makefile
+ dh_testdir
+ # compile commands go here
+ cd builddir && $(MAKE) -j4
+ touch $@
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp
+ # cleanup commands go here
+ rm -rf builddir
+ dh_clean
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+ # install commands go here
+ cd builddir && $(MAKE) INSTALL_ROOT=$(CURDIR)/debian/$(APPNAME) install
+
+# Build arch-independent files here
+binary-indep: build install
+#We have nothing to do by default
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installdocs
+ dh_installexamples
+ dh_installman
+ dh_link
+# dh_strip --dbg-package=appname-dbg
+ dh_compress
+ dh_fixperms
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
--- /dev/null
+#include "editwindow.h"
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QMessageBox>
+#include <QLabel>
+#ifdef Q_WS_MAEMO_5
+#include <QMaemo5DatePickSelector>
+#endif
+extern WeightDataModel *wdm;
+
+EditWindow::EditWindow(QWidget *parent) :
+ QMainWindow(parent)
+{
+#ifdef Q_WS_MAEMO_5
+ setAttribute(Qt::WA_Maemo5StackedWindow);
+#endif
+
+ setWindowTitle("WeightGraph");
+
+ QWidget *centralContainer = new QWidget(parent);
+ QHBoxLayout *horiz = new QHBoxLayout(centralContainer);
+
+ weightView.setModel(wdm);
+ weightView.setMinimumWidth(540);
+ horiz->addWidget(&weightView);
+
+ QWidget *rightContainer = new QWidget(centralContainer);
+ QVBoxLayout *right = new QVBoxLayout(rightContainer);
+
+ addButton.setText("Add");
+ addButton.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ connect(&addButton, SIGNAL(clicked()), this, SLOT(addWeight()));
+ right->addWidget(&addButton);
+
+ removeButton.setText("Remove");
+ removeButton.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ connect(&removeButton, SIGNAL(clicked()), this, SLOT(removeSelected()));
+ right->addWidget(&removeButton);
+
+ editButton.setText("Edit");
+ editButton.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ connect(&editButton, SIGNAL(clicked()), this, SLOT(editSelected()));
+ right->addWidget(&editButton);
+
+ horiz->addWidget(rightContainer);
+
+ setCentralWidget(centralContainer);
+
+ connect(weightView.selectionModel(),
+ SIGNAL(selectionChanged(const QItemSelection &,const QItemSelection &)),
+ this, SLOT(updateButtons()));
+ updateButtons();
+
+}
+AddWeightDialog::AddWeightDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ setModal(true);
+ QGridLayout *layout = new QGridLayout(this);
+
+ QLabel *dateLabel = new QLabel("Date:", this);
+ //dateLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Maximum);
+ layout->addWidget(dateLabel, 0, 0);
+
+#ifdef Q_WS_MAEMO_5
+ date = new QMaemo5ValueButton(this);
+ QMaemo5DatePickSelector *picker = new QMaemo5DatePickSelector(this);
+ picker->setCurrentDate(QDate::currentDate());
+ date->setPickSelector(picker);
+#else
+ date = new QDateEdit(this);
+ date->setDate(QDate::currentDate());
+ date->setDisplayFormat("yyyy-MM-dd");
+#endif
+ layout->addWidget(date, 1, 0);
+
+ QLabel *weightLabel = new QLabel("Weight:", this);
+ //weightLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Maximum);
+ layout->addWidget(weightLabel, 0, 1);
+
+ weight = new WeightSpinBox(this);
+ layout->addWidget(weight, 1, 1);
+
+ QPushButton *cancelButton = new QPushButton("Cancel", this);
+ connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
+ layout->addWidget(cancelButton, 2, 0);
+
+ QPushButton *addButton = new QPushButton("Add", this);
+ connect(addButton, SIGNAL(clicked()), this, SLOT(accept()));
+ layout->addWidget(addButton, 2, 1);
+}
+WeightDataModel::DateWeight AddWeightDialog::getDateWeight()
+{
+ WeightDataModel::DateWeight ret;
+#ifdef Q_WS_MAEMO_5
+ ret.date = dynamic_cast<QMaemo5DatePickSelector*>(date->pickSelector())->currentDate();
+#else
+ ret.date = date->date();
+#endif
+ ret.weight = weight->value();
+ return ret;
+}
+
+void EditWindow::updateButtons()
+{
+ if (weightView.selectionModel()->selection().indexes().size() == 1) {
+ removeButton.setEnabled(true);
+ editButton.setEnabled(true);
+ }
+ else {
+ removeButton.setEnabled(false);
+ editButton.setEnabled(false);
+ }
+}
+
+extern WeightDataModel *wdm;
+void EditWindow::addWeight()
+{
+ AddWeightDialog d;
+ int code = d.exec();
+ if (code == QDialog::Accepted) {
+ WeightDataModel::DateWeight dw = d.getDateWeight();
+ if (wdm->dateExists(dw.date)) {
+ QMessageBox::warning(this, "Duplicate", "A weight for this date already exists.\n"
+ "Only one weight per date allowed.");
+ return;
+ }
+ wdm->setWeightForDate(dw);
+ }
+}
+
+void EditWindow::removeSelected()
+{
+ int answer =
+ QMessageBox::question(this, "Remove?", "Really remove selected entry?",
+ QMessageBox::No, QMessageBox::Yes);
+ if (answer == QMessageBox::Yes) {
+ QModelIndexList indexes = weightView.selectionModel()->selection().indexes();
+ foreach(QModelIndex i, indexes)
+ wdm->removeRows(i.row(), 1);
+ }
+}
+
+void EditWindow::editSelected()
+{
+ QModelIndexList indexes = weightView.selectionModel()->selection().indexes();
+ if (indexes.size() == 1)
+ weightView.edit(wdm->index(indexes.first().row(), 1));
+}
--- /dev/null
+#ifndef EDITWINDOW_H
+#define EDITWINDOW_H
+
+#include <QMainWindow>
+#include <QPushButton>
+#include <QDateEdit>
+#ifdef Q_WS_MAEMO_5
+#include <QMaemo5ValueButton>
+#endif
+#include <QGridLayout>
+#include <QDialog>
+#include "weightview.h"
+#include "weightdata.h"
+
+class EditWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ explicit EditWindow(QWidget *parent = 0);
+public slots:
+ void updateButtons();
+ void addWeight();
+ void removeSelected();
+ void editSelected();
+private:
+ WeightView weightView;
+ QPushButton addButton, removeButton, editButton;
+};
+
+class AddWeightDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ AddWeightDialog(QWidget *parent=0);
+ WeightDataModel::DateWeight getDateWeight();
+
+private:
+#ifdef Q_WS_MAEMO_5
+ QMaemo5ValueButton *date;
+#else
+ QDateEdit *date;
+#endif
+ WeightSpinBox *weight;
+};
+
+
+#endif // EDITWINDOW_H
--- /dev/null
+[Desktop Entry]
+Encoding=UTF-8
+Version=1.0
+Type=Application
+Name=WeightGraph
+Exec=/usr/bin/weightgraph
+Icon=weightgraph
+X-Window-Icon=weightgraph
+X-Window-Icon-Dimmed=weightgraph
+Categories=Utility
--- /dev/null
+#include <QtGui/QApplication>
+#include <QDir>
+#include <QMainWindow>
+#include <QMessageBox>
+#include "mainwindow.h"
+#include "weightdata.h"
+#include "settings.h"
+#include "settingswindow.h"
+
+//For debugging
+#include "weightgraphview.h"
+
+//Global pointer to the weight data
+WeightDataModel *wdm;
+Settings *settings;
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setApplicationName("WeightGraph");
+ QCoreApplication::setOrganizationDomain("vpu.me");
+ QApplication a(argc, argv);
+ QDir dir(Settings::datadir());
+ try {
+ if(!dir.exists())
+ dir.mkpath(Settings::datadir());
+ } catch(...) {
+ QMainWindow w2;
+ w2.show();
+ QMessageBox::critical(&w2, "Critical error",
+ "Critical error while creating directory \""+Settings::datadir()+"\"");
+ return 1;
+ }
+ QString datafilename = Settings::datafile();
+ try {
+ wdm = new WeightDataModel(datafilename, &a);
+ }
+ catch(QString error) {
+ QMainWindow w2;
+ w2.show();
+ QMessageBox::critical(&w2, "Critical error",
+ "Critical error while opening weight data file:\""+error+"\"");
+ return 1;
+ }
+
+ MainWindow w;
+#if defined(Q_WS_S60)
+ w.showMaximized();
+#else
+ w.show();
+#endif
+
+ return a.exec();
+}
--- /dev/null
+//#include "ui_mainwindow.h"
+#include "mainwindow.h"
+#include "weightdata.h"
+#include "weightstatsview.h"
+#include "weightgraphview.h"
+#include <QtGui/QX11Info>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+extern WeightDataModel *wdm;
+
+MainWindow::MainWindow(QWidget *parent) :
+ QMainWindow(parent)
+{
+#ifdef Q_WS_MAEMO_5
+ setAttribute(Qt::WA_Maemo5StackedWindow);
+#endif
+
+ setWindowTitle("WeightGraph");
+
+ QWidget *central = new QWidget(this);
+ QHBoxLayout *topLayout = new QHBoxLayout(central);
+
+ // vv LEFT SIDE BEGINS vv
+ QWidget *leftContainer = new QWidget(central);
+ QVBoxLayout *leftLayout = new QVBoxLayout(leftContainer);
+ leftLayout->setSpacing(1);
+ leftLayout->setMargin(1);
+
+ // vvv LEFT TOP BEGINS vvv
+ //QGroupBox * leftTopContainer = new QGroupBox("Today's weight?", leftContainer);
+ QFrame *leftTopContainer = new QFrame(leftContainer);
+ leftTopContainer->setFrameShadow(QFrame::Sunken);
+ leftTopContainer->setFrameStyle(QFrame::StyledPanel);
+ leftTopContainer->setLineWidth(2);
+ leftTopContainer->setMidLineWidth(2);
+ QGridLayout *leftTopLayout = new QGridLayout(leftTopContainer);
+
+ QLabel *todayLabel = new QLabel("Today's weight?", leftContainer);
+ leftTopLayout->addWidget(todayLabel, 0, 0);
+
+ weight = new WeightSpinBox(leftTopContainer);
+ if(wdm->size() > 0)
+ weight->setValue(wdm->getWeights().last().weight);
+ leftTopLayout->addWidget(weight, 1, 0);
+
+ QPushButton *setButton = new QPushButton("Set", leftTopContainer);
+ connect(setButton, SIGNAL(clicked()), this, SLOT(setTodaysWeight()));
+ leftTopLayout->addWidget(setButton, 2, 0);
+
+ leftLayout->addWidget(leftTopContainer);
+ // ^^^ LEFT TOP ENDS ^^^
+
+// QWidget *vspacer0 = new QWidget(leftContainer);
+// vspacer0->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
+// leftLayout->addWidget(vspacer0);
+
+ WeightStatsView *stats = new WeightStatsView(wdm, this);
+ leftLayout->addWidget(stats);
+
+// QWidget *vspacer = new QWidget(leftContainer);
+// vspacer->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
+// leftLayout->addWidget(vspacer);
+
+ ew = new EditWindow(this);
+ QPushButton *listButton = new QPushButton("List / edit", leftContainer);
+ connect(listButton, SIGNAL(clicked()), ew, SLOT(show()));
+ leftLayout->addWidget(listButton);
+
+ topLayout->addWidget(leftContainer);
+ // ^^ LEFT SIDE ENDS ^^
+
+ smallGraph = new WeightGraphView(wdm, "Small", central);
+ bigGraph = new WeightGraphView(wdm, "Big", this);
+#ifdef Q_WS_MAEMO_5
+ bigGraph->setAttribute(Qt::WA_Maemo5StackedWindow);
+ bigGraph->grabZoomKeys(Settings::grabZoomKeys());
+#endif
+ bigGraph->setWindowFlags(bigGraph->windowFlags() | Qt::Window);
+ connect(smallGraph, SIGNAL(clicked()), bigGraph, SLOT(show()));
+ topLayout->addWidget(smallGraph);
+
+ this->setCentralWidget(central);
+
+
+ aboutDialog = new QMessageBox(QMessageBox::NoIcon, "About WeightGraph",
+ "Copyright (C) 2011 Visa Putkinen. Licence: GPLv2",
+ QMessageBox::Close, this);
+ aboutDialog->setIconPixmap(QPixmap(":/img/icon48"));
+ aboutDialog->setInformativeText("Usage: enter your weight every day using "
+ "the main screen's \"Today's weight?\" box "
+ "or the List / edit window. You may enter "
+ "at most one weight per day."
+ "\n\n"
+ "A graph of the weights will be drawn when "
+ "two or more weights are entered. Tap the "
+ "graph to open a larger graph view. Use the "
+ "external zoom buttons to adjust the shown "
+ "time period."
+ "\n\n"
+ "The weights are stored in human readable (and "
+ "writeable) form in "
+ "MyDocs/WeightGraph/weightdata.txt");
+
+
+ //Important: SettingsWindow must be created after all graph
+ //views are created or settings won't show all graphs
+ settingsWindow = new SettingsWindow(this);
+ menuBar()->addAction(tr("Settings"), settingsWindow, SLOT(show()));
+ menuBar()->addAction(tr("About"), aboutDialog, SLOT(exec()));
+
+ grabZoomKeys(Settings::grabZoomKeys());
+
+ connect(Settings::self(), SIGNAL(settingChanged()), this, SLOT(update()));
+}
+
+void MainWindow::setTodaysWeight()
+{
+ wdm->setWeightForDate(QDate::currentDate(), weight->value());
+}
+
+void MainWindow::keyPressEvent(QKeyEvent* event)
+{
+ //qDebug() << "Main window: key pressed: " << event->key();
+ switch (event->key()) {
+ case Qt::Key_F7:
+ smallGraph->decPeriod();
+ event->accept();
+ break;
+
+ case Qt::Key_F8:
+ smallGraph->incPeriod();
+ event->accept();
+ break;
+ }
+ QWidget::keyPressEvent(event);
+}
+void MainWindow::grabZoomKeys(bool grab)
+{
+ if (!winId()) {
+ qWarning("Can't grab keys unless we have a window id");
+ return;
+ }
+
+ 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!");
+ return;
+ }
+
+
+ XChangeProperty (QX11Info::display(),
+ winId(),
+ atom,
+ XA_INTEGER,
+ 32,
+ PropModeReplace,
+ reinterpret_cast<unsigned char *>(&val),
+ 1);
+
+ //qDebug() << "Main window grabbed zoom keys: " << winId();
+}
--- /dev/null
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QtGui>
+#include "editwindow.h"
+#include "weightspinbox.h"
+#include "weightgraphview.h"
+#include "settingswindow.h"
+
+namespace Ui {
+ class MainWindow;
+}
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = 0);
+public slots:
+ void grabZoomKeys(bool grab);
+private slots:
+ void setTodaysWeight();
+ void update() {
+ grabZoomKeys(Settings::grabZoomKeys());
+ QWidget::update();
+ }
+protected:
+ void keyPressEvent(QKeyEvent* event);
+private:
+ //Ui::MainWindow *ui;
+ WeightSpinBox *weight;
+ EditWindow *ew;
+ WeightGraphView *smallGraph;
+ WeightGraphView *bigGraph;
+ SettingsWindow *settingsWindow;
+ QMessageBox *aboutDialog;
+};
+
+#endif // MAINWINDOW_H
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>MainWindow</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <widget class="QWidget" name="horizontalLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>741</width>
+ <height>461</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="todayLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Today:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDoubleSpinBox" name="todayWeight">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::UpDownArrows</enum>
+ </property>
+ <property name="specialValueText">
+ <string>kg</string>
+ </property>
+ <property name="decimals">
+ <number>1</number>
+ </property>
+ <property name="minimum">
+ <double>30.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>1000.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.100000000000000</double>
+ </property>
+ <property name="value">
+ <double>70.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="kgLabel">
+ <property name="text">
+ <string>Kg</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>TextLabel1</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>TextLabel2</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="autoFillBackground">
+ <bool>true</bool>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::Box</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="res.qrc">:/img/graph.jpg</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources>
+ <include location="res.qrc"/>
+ </resources>
+ <connections/>
+</ui>
--- /dev/null
+#!/bin/sh
+
+MAD=/opt/NokiaQtSDK/Maemo/4.6.2/bin/mad
+APPNAME=weightgraph
+VERSION=`head -1 debian/changelog | cut -d'(' -f 2 | cut -d')' -f 1`
+DIR=/tmp/$APPNAME-$VERSION
+rm -rf $DIR
+cp -r . $DIR
+cd $DIR
+$MAD dpkg-buildpackage
+$MAD dpkg-buildpackage -sa -S
--- /dev/null
+<RCC>
+ <qresource prefix="/img">
+ <file alias="icon48">maemofiles/48/weightgraph.png</file>
+ </qresource>
+</RCC>
--- /dev/null
+#include "settings.h"
+#include <QDir>
+
+Settings *Settings::singleton = new Settings();
+QSettings Settings::s(Settings::settingsfile(), QSettings::IniFormat);
+const QString Settings::weightUnitKey = "WeightUnit";
+const QString Settings::goalWeightMinKey = "GoalWeightMin";
+const QString Settings::goalWeightMaxKey = "GoalWeightMax";
+const QString Settings::grabZoomKeysKey = "GrabZoomKeys";
+const QString Settings::graphSettingsGroupSuffix = "Graph";
+const QString Settings::goalWeightEnabledKey = "GoalWeightEnabled";
+const QString Settings::weightIntervalModeKey = "WeightIntervalMode";
+const QString Settings::weightIntervalMinKey = "WeightIntervalMin";
+const QString Settings::weightIntervalMaxKey = "WeightIntervalMax";
+const QString Settings::defaultTimeIntervalKey = "DefaultTimeInterval";
+
+QString Settings::weightUnit()
+{
+ if(!s.contains(weightUnitKey))
+ setWeightUnit("kg");
+ return s.value(weightUnitKey).toString();
+}
+void Settings::setWeightUnit(QString wu)
+{
+ s.setValue(weightUnitKey, wu);
+}
+void Settings::setWeightUnitAndSync(QString wu)
+{
+ setWeightUnit(wu);
+ sync();
+}
+
+double Settings::goalWeightMin()
+{
+ if(!s.contains(goalWeightMinKey))
+ setGoalWeightMin(0.0);
+ return s.value(goalWeightMinKey).toDouble();
+}
+void Settings::setGoalWeightMin(double min)
+{
+ s.setValue(goalWeightMinKey, min);
+}
+void Settings::setGoalWeightMinAndSync(double min)
+{
+ setGoalWeightMin(min);
+ sync();
+}
+
+double Settings::goalWeightMax()
+{
+ if(!s.contains(goalWeightMaxKey))
+ setGoalWeightMax(0.0);
+ return s.value(goalWeightMaxKey).toDouble();
+}
+void Settings::setGoalWeightMax(double max)
+{
+ s.setValue(goalWeightMaxKey, max);
+}
+void Settings::setGoalWeightMaxAndSync(double max)
+{
+ setGoalWeightMax(max);
+ sync();
+}
+
+bool Settings::grabZoomKeys()
+{
+ if(!s.contains(grabZoomKeysKey))
+ setGrabZoomKeys(true);
+ return s.value(grabZoomKeysKey).toBool();
+}
+void Settings::setGrabZoomKeys(bool grab)
+{
+ s.setValue(grabZoomKeysKey, grab);
+}
+void Settings::setGrabZoomKeysAndSync(bool grab)
+{
+ setGrabZoomKeys(grab);
+ sync();
+}
+
+GraphSettings Settings::graphSettings(const QString &graphId)
+{
+ GraphSettings ret;
+ bool changed = false;
+ s.beginGroup(graphId+graphSettingsGroupSuffix);
+
+ if (!s.contains(goalWeightEnabledKey)) {
+ s.setValue(goalWeightEnabledKey, false);
+ changed = true;
+ }
+ ret.goalWeightEnabled = s.value(goalWeightEnabledKey).toBool();
+
+ if (!s.contains(weightIntervalModeKey)) {
+ s.setValue(weightIntervalModeKey, (int)GraphSettings::AutomaticWithoutGoalWeight);
+ changed = true;
+ }
+ ret.weightIntervalMode =
+ (GraphSettings::WeightIntervalMode)s.value(weightIntervalModeKey).toInt();
+
+ if (!s.contains(weightIntervalMinKey)) {
+ s.setValue(weightIntervalMinKey, 0.0);
+ changed = true;
+ }
+ ret.weightIntervalMin = s.value(weightIntervalMinKey).toDouble();
+
+ if (!s.contains(weightIntervalMaxKey)) {
+ s.setValue(weightIntervalMaxKey, 0.0);
+ changed = true;
+ }
+ ret.weightIntervalMax = s.value(weightIntervalMaxKey).toDouble();
+
+ if (!s.contains(defaultTimeIntervalKey)) {
+ s.setValue(defaultTimeIntervalKey, 0);
+ changed = true;
+ }
+ ret.defaultTimeInterval = s.value(defaultTimeIntervalKey).toInt();
+
+ s.endGroup();
+ if (changed)
+ sync();
+ return ret;
+}
+void Settings::setGraphSettings(const QString &graphId, GraphSettings &gs)
+{
+ s.beginGroup(graphId+graphSettingsGroupSuffix);
+ s.setValue(goalWeightEnabledKey, gs.goalWeightEnabled);
+ s.setValue(weightIntervalModeKey, (int)gs.weightIntervalMode);
+ s.setValue(weightIntervalMinKey, gs.weightIntervalMin);
+ s.setValue(weightIntervalMaxKey, gs.weightIntervalMax);
+ s.setValue(defaultTimeIntervalKey, gs.defaultTimeInterval);
+ s.endGroup();
+}
+void Settings::setGraphSettingsAndSync(const QString &graphId,
+ GraphSettings &gs)
+{
+ setGraphSettings(graphId, gs);
+ sync();
+}
+
+QStringList Settings::graphIds()
+{
+ QStringList tmp = s.childGroups();
+ tmp = tmp.filter(QRegExp("^\\w+Graph$"));
+ return tmp.replaceInStrings(QRegExp("^(\\w+)Graph$"), "\\1");
+}
+void Settings::sync()
+{
+ s.sync();
+ emit singleton->settingChanged();
+}
+
+QString Settings::datadir()
+{
+#ifdef Q_WS_MAEMO_5
+ return QDir::home().path()+"/MyDocs/WeightGraph";
+#else
+ return QDir::home().path()+"/.weightgraph";
+#endif
+}
+QString Settings::datafile()
+{
+ return datadir()+"/weightdata.txt";
+}
+QString Settings::settingsfile()
+{
+ return datadir()+"/config.ini";
+}
--- /dev/null
+#ifndef SETTINGS_H
+#define SETTINGS_H
+
+#include <QSettings>
+
+struct GraphSettings
+{
+ enum WeightIntervalMode {
+ AutomaticWithGoalWeight,
+ AutomaticWithoutGoalWeight,
+ Manual
+ };
+ bool goalWeightEnabled;
+ WeightIntervalMode weightIntervalMode;
+ double weightIntervalMin;
+ double weightIntervalMax;
+ int defaultTimeInterval;
+};
+
+class Settings : public QObject
+{
+ Q_OBJECT
+public:
+ static Settings *self() { return singleton; }
+ static QString weightUnit();
+ static double goalWeightMin();
+ static double goalWeightMax();
+ static bool grabZoomKeys();
+ static GraphSettings graphSettings(const QString &graphId);
+ static QStringList graphIds();
+
+ static QString datadir();
+ static QString datafile();
+ static QString settingsfile();
+public slots:
+ static void setWeightUnit(QString wu);
+ static void setWeightUnitAndSync(QString wu);
+ static void setGoalWeightMin(double min);
+ static void setGoalWeightMinAndSync(double min);
+ static void setGoalWeightMax(double max);
+ static void setGoalWeightMaxAndSync(double max);
+ static void setGrabZoomKeys(bool grab);
+ static void setGrabZoomKeysAndSync(bool grab);
+ static void setGraphSettings(const QString &graphId, GraphSettings &gs);
+ static void setGraphSettingsAndSync(const QString &graphId,
+ GraphSettings &gs);
+ static void sync();
+signals:;
+ //settingChanged is emitted when sync() is called.
+ void settingChanged();
+private:
+ Settings() : QObject(0) {}
+ static Settings *singleton;
+ static QSettings s;
+ static const QString weightUnitKey;
+ static const QString goalWeightMinKey;
+ static const QString goalWeightMaxKey;
+ static const QString grabZoomKeysKey;
+ static const QString graphSettingsGroupSuffix;
+ static const QString goalWeightEnabledKey;
+ static const QString weightIntervalModeKey;
+ static const QString weightIntervalMinKey;
+ static const QString weightIntervalMaxKey;
+ static const QString defaultTimeIntervalKey;
+};
+#endif // SETTINGS_H
--- /dev/null
+#include "settingswindow.h"
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QGridLayout>
+#include <QLabel>
+#include <QStringListModel>
+#include <QPushButton>
+
+//for debugging
+#include <iostream>
+#include <QDebug>
+
+static QStringList timeIntervalStrings() {
+ QStringList timeIntervals;
+ timeIntervals.append("1 week");
+ timeIntervals.append("1 month");
+ timeIntervals.append("3 months");
+ timeIntervals.append("6 months");
+ timeIntervals.append("1 year");
+ timeIntervals.append("all");
+ return timeIntervals;
+}
+static int timeIntervalToIndex(int days) {
+ switch(days) {
+ case 0: return 5;
+ case 7: return 0;
+ case 30: return 1;
+ case 90: return 2;
+ case 180: return 3;
+ case 365: return 4;
+ default: Q_ASSERT(0 && "unknown time interval");
+ }
+ return 0; //unreachable
+}
+static int indexToTimeInterval(int index) {
+ switch(index) {
+ case 5: return 0;
+ case 0: return 7;
+ case 1: return 30;
+ case 2: return 90;
+ case 3: return 180;
+ case 4: return 365;
+ default: Q_ASSERT(0 && "unknown time interval index");
+ }
+ return 0; //unreachable
+}
+
+SettingsWindow::SettingsWindow(QWidget *parent) :
+ QMainWindow(parent)
+{
+#ifdef Q_WS_MAEMO_5
+ setAttribute(Qt::WA_Maemo5StackedWindow);
+#endif
+
+ setWindowTitle("WeightGraph");
+
+ QWidget *rootContainer = new QWidget(this);
+ QVBoxLayout *rootLayout = new QVBoxLayout(rootContainer);
+
+ QWidget *topContainer = new QWidget(rootContainer);
+ QGridLayout *topLayout = new QGridLayout(topContainer);
+
+ QStringList units; units.append("kg"); units.append("lb");
+ QStringListModel *weightUnitModel = new QStringListModel(units, topContainer);
+#ifdef Q_WS_MAEMO_5
+ weightUnit = new QMaemo5ValueButton("Unit", topContainer);
+ weightUnit->setValueLayout(QMaemo5ValueButton::ValueUnderTextCentered);
+ QMaemo5ListPickSelector *weightUnitSelector = new QMaemo5ListPickSelector(topContainer);
+ weightUnitSelector->setModel(weightUnitModel);
+ weightUnitSelector->setCurrentIndex(Settings::weightUnit() == "kg" ? 0 : 1);
+ weightUnit->setPickSelector(weightUnitSelector);
+ connect(weightUnit->pickSelector(), SIGNAL(selected(QString)),
+ Settings::self(), SLOT(setWeightUnitAndSync(QString)));
+#else
+ weightUnit = new QComboBox(topContainer);
+ weightUnit->setModel(weightUnitModel);
+#endif
+
+ topLayout->addWidget(weightUnit, 0, 0);
+
+// QWidget *spacer = new QWidget(topContainer);
+// spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
+// topLayout->addWidget(spacer);
+
+ QFrame *goalFrame = new QFrame(topContainer);
+ goalFrame->setFrameShadow(QFrame::Sunken);
+ goalFrame->setFrameStyle(QFrame::StyledPanel);
+ goalFrame->setLineWidth(2);
+ goalFrame->setMidLineWidth(2);
+ QHBoxLayout *goalLayout = new QHBoxLayout(goalFrame);
+
+ goalLayout->addWidget(new QLabel("Goal weight:", topContainer));
+
+ goalMin = new WeightSpinBox(topContainer);
+ goalMin->setValue(Settings::goalWeightMin());
+ goalLayout->addWidget(goalMin);
+
+ goalLayout->addWidget(new QLabel("-", topContainer));
+
+ goalMax = new WeightSpinBox(topContainer);
+ goalMax->setValue(Settings::goalWeightMax());
+ goalLayout->addWidget(goalMax);
+ topLayout->addWidget(goalFrame, 0, 1);
+
+ grabZoomKeys = new QPushButton("Use zoom/volume keys to zoom", rootContainer);
+ grabZoomKeys->setCheckable(true);
+ grabZoomKeys->setChecked(Settings::grabZoomKeys());
+ topLayout->addWidget(grabZoomKeys, 1, 0, 1, 2);
+
+ rootLayout->addWidget(topContainer);
+
+ QTabWidget *tabWidget = new QTabWidget(rootContainer);
+
+ graphSettingsList = new QList<GraphSettingsWidget*>();
+
+ QStringList graphIds; graphIds.append("Small"); graphIds.append("Big");
+ foreach(QString id, graphIds) {
+ GraphSettingsWidget *gsw = new GraphSettingsWidget(id, tabWidget);
+ graphSettingsList->append(gsw);
+ tabWidget->addTab(gsw, id+" graph");
+ }
+
+ rootLayout->addWidget(tabWidget);
+
+ setCentralWidget(rootContainer);
+}
+
+void SettingsWindow::closeEvent(QCloseEvent *event)
+{
+ //Note: Weight unit not saved as it is saved on change.
+ Settings::setGoalWeightMin(goalMin->value());
+ Settings::setGoalWeightMax(goalMax->value());
+ Settings::setGrabZoomKeys(grabZoomKeys->isChecked());
+ foreach(GraphSettingsWidget *gsw, *graphSettingsList) {
+ GraphSettings gs;
+ gs.goalWeightEnabled = gsw->goalWeightEnabled;
+#ifdef Q_WS_MAEMO_5
+ QMaemo5ListPickSelector *picker =
+ dynamic_cast<QMaemo5ListPickSelector*>(gsw->weightIntervalMode->pickSelector());
+ gs.weightIntervalMode = (GraphSettings::WeightIntervalMode)picker->currentIndex();
+#else
+ gs.weightIntervalMode =
+ (GraphSettings::WeightIntervalMode)gsw->weightIntervalMode->currentIndex();
+#endif
+ gs.weightIntervalMin = gsw->weightIntervalMin->value();
+ gs.weightIntervalMax = gsw->weightIntervalMax->value();
+#ifdef Q_WS_MAEMO_5
+ QMaemo5ListPickSelector *picker2 =
+ dynamic_cast<QMaemo5ListPickSelector*>(gsw->defaultTimeInterval->pickSelector());
+ gs.defaultTimeInterval = indexToTimeInterval(picker2->currentIndex());
+#else
+ gs.defaultTimeInterval
+ = indexToTimeInterval(gsw->defaultTimeInterval->currentIndex());
+#endif
+ Settings::setGraphSettingsAndSync(gsw->graphId, gs);
+ }
+ QMainWindow::closeEvent(event);
+}
+
+GraphSettingsWidget::GraphSettingsWidget(QString graphId, QWidget *parent) :
+ QWidget(parent), graphId(graphId) {
+ QWidget *rootContainer = new QWidget(this);
+ QGridLayout *rootLayout = new QGridLayout(rootContainer);
+
+ QWidget *topSpacer = new QWidget(rootContainer);
+ topSpacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ rootLayout->addWidget(topSpacer, 0, 0);
+
+ GraphSettings gs = Settings::graphSettings(graphId);
+
+ goalWeightEnabled = new QPushButton("Show goal weight", rootContainer);
+ goalWeightEnabled->setCheckable(true);
+ goalWeightEnabled->setChecked(gs.goalWeightEnabled);
+ rootLayout->addWidget(goalWeightEnabled, 1, 0);
+
+ QStringListModel *timeIntervalModel =
+ new QStringListModel(timeIntervalStrings(), rootContainer);
+#ifdef Q_WS_MAEMO_5
+ defaultTimeInterval= new QMaemo5ValueButton("Time interval", rootContainer);
+ defaultTimeInterval->setValueLayout(QMaemo5ValueButton::ValueUnderTextCentered);
+ QMaemo5ListPickSelector *timeIntervalSelector =
+ new QMaemo5ListPickSelector(rootContainer);
+ timeIntervalSelector->setModel(timeIntervalModel);
+ timeIntervalSelector->setCurrentIndex(timeIntervalToIndex(gs.defaultTimeInterval));
+ defaultTimeInterval->setPickSelector(timeIntervalSelector);
+#else
+ defaultTimeInterval = new QComboBox(rootContainer);
+ defaultTimeInterval->setModel(timeIntervalModel);
+ defaultTimeInterval->setCurrentIndex(timeIntervalToIndex(gs.defaultTimeInterval));
+#endif
+ rootLayout->addWidget(defaultTimeInterval, 2, 0);
+
+// QWidget *spacer = new QWidget(rootContainer);
+// spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
+// rootLayout->addWidget(spacer, 0, 1, 2, 1);
+
+ QFrame *weightFrame = new QFrame(rootContainer);
+ weightFrame->setFrameShadow(QFrame::Sunken);
+ weightFrame->setFrameStyle(QFrame::StyledPanel);
+ weightFrame->setLineWidth(2);
+ weightFrame->setMidLineWidth(2);
+ QGridLayout *weightLayout = new QGridLayout(weightFrame);
+
+ QStringList weightIntervalModes;
+ weightIntervalModes.append("Auto with goal weight");
+ weightIntervalModes.append("Auto without goal weight");
+ weightIntervalModes.append("Manual");
+ QStringListModel *weightIntervalModeModel =
+ new QStringListModel(weightIntervalModes, rootContainer);
+#ifdef Q_WS_MAEMO_5
+ weightIntervalMode = new QMaemo5ValueButton("Weight interval mode", rootContainer);
+ weightIntervalMode->setValueLayout(QMaemo5ValueButton::ValueUnderTextCentered);
+ QMaemo5ListPickSelector *weightIntervalModeSelector =
+ new QMaemo5ListPickSelector(rootContainer);
+ weightIntervalModeSelector->setModel(weightIntervalModeModel);
+ weightIntervalModeSelector->setCurrentIndex((int)gs.weightIntervalMode);
+ weightIntervalMode->setPickSelector(weightIntervalModeSelector);
+ connect(weightIntervalMode->pickSelector(), SIGNAL(selected(QString)),
+ this, SLOT(weightIntervalModeChanged(QString)));
+#else
+ weightIntervalMode = new QComboBox(rootContainer);
+ weightIntervalMode->setModel(weightIntervalModeModel);
+#endif
+ weightLayout->addWidget(weightIntervalMode, 0, 0, 1, 3);
+
+
+ weightIntervalMin = new WeightSpinBox(rootContainer);
+ weightIntervalMin->setEnabled(gs.weightIntervalMode == GraphSettings::Manual);
+ weightIntervalMin->setValue(gs.weightIntervalMin);
+ weightLayout->addWidget(weightIntervalMin, 1, 0);
+
+ weightLayout->addWidget(new QLabel("-", rootContainer), 1, 1);
+
+ weightIntervalMax = new WeightSpinBox(rootContainer);
+ weightIntervalMax->setEnabled(gs.weightIntervalMode == GraphSettings::Manual);
+ weightIntervalMax->setValue(gs.weightIntervalMax);
+ weightLayout->addWidget(weightIntervalMax, 1, 2);
+
+ rootLayout->addWidget(weightFrame, 1, 1, 2, 1);
+
+ QWidget *bottomSpacer = new QWidget(rootContainer);
+ bottomSpacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ rootLayout->addWidget(bottomSpacer, 4, 0);
+
+}
+void GraphSettingsWidget::weightIntervalModeChanged(QString mode) {
+ bool isManual = mode == "Manual";
+ weightIntervalMin->setEnabled(isManual);
+ weightIntervalMax->setEnabled(isManual);
+}
+
--- /dev/null
+#ifndef SETTINGSWINDOW_H
+#define SETTINGSWINDOW_H
+
+#include <QMainWindow>
+#include <QTabWidget>
+#include <QPushButton>
+#include <QList>
+#ifdef Q_WS_MAEMO_5
+# include <QtMaemo5>
+#else
+# include <QComboBox>
+#endif
+#include "weightspinbox.h"
+
+class GraphSettingsWidget;
+
+class SettingsWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ explicit SettingsWindow(QWidget *parent = 0);
+protected:
+ void closeEvent(QCloseEvent *);
+signals:
+
+public slots:
+private:
+#ifdef Q_WS_MAEMO_5
+ QMaemo5ValueButton *weightUnit;
+#else
+ QComboBox *weightUnit;
+#endif
+ WeightSpinBox *goalMin;
+ WeightSpinBox *goalMax;
+ QPushButton *grabZoomKeys;
+ QList<GraphSettingsWidget*> *graphSettingsList;
+};
+
+class GraphSettingsWidget : public QWidget {
+ Q_OBJECT
+public:
+ GraphSettingsWidget(QString graphId, QWidget *parent);
+private slots:
+ void weightIntervalModeChanged(QString mode);
+public:
+ QString graphId;
+ QPushButton *goalWeightEnabled;
+#ifdef Q_WS_MAEMO_5
+ QMaemo5ValueButton *weightIntervalMode;
+ QMaemo5ValueButton *defaultTimeInterval;
+#else
+ QComboBox *weightIntervalMode;
+ QComboBox *defaultTimeInterval;
+#endif
+
+ WeightSpinBox *weightIntervalMin;
+ WeightSpinBox *weightIntervalMax;
+};
+
+#endif // SETTINGSWINDOW_H
--- /dev/null
+#include "weightdata.h"
+#include "settings.h"
+#include <QTextStream>
+#include <QStringList>
+#include <QtAlgorithms>
+#include <assert.h>
+#include <limits>
+
+#include <QDebug>
+
+WeightDataModel::WeightDataModel(QString &datafilename, QObject *parent) :
+ QAbstractTableModel(parent), datafile(datafilename)
+{
+ clear();
+ readFromDisk();
+}
+
+void WeightDataModel::clear()
+{
+ weights.clear();
+}
+
+Qt::ItemFlags WeightDataModel::flags(const QModelIndex &index) const
+{
+ if(!index.isValid())
+ return Qt::ItemIsEnabled;
+ switch(index.column()) {
+ case 0: return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ case 1: return Qt::ItemIsEnabled | Qt::ItemIsEditable;
+ default: return Qt::NoItemFlags;
+ }
+}
+
+QVariant WeightDataModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || index.row() >= rowCount(QModelIndex())
+ || index.column() >= columnCount(QModelIndex()))
+ return QVariant();
+
+ if (role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::SizeHintRole)
+ return QVariant();
+
+ if (role == Qt::SizeHintRole) {
+ if (index.column() == 0)
+ return QSize(230,70);
+ else
+ return QSize(280,70);
+ }
+
+ if (index.column() == 0) {
+ return weights.at(index.row()).date.toString(Qt::ISODate);
+ }
+ else {
+ if (role == Qt::DisplayRole)
+ return QString("%1 %2").arg(weights.at(index.row()).weight,5,'f',1)
+ .arg(Settings::weightUnit());
+ else
+ return weights.at(index.row()).weight;
+ }
+
+ return QVariant();
+}
+
+bool WeightDataModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (!index.isValid() || role != Qt::EditRole)
+ return false;
+ switch (index.column()) {
+ case 0:
+ weights[index.row()].date = value.toDate();
+ break;
+ case 1: {
+ double weight = value.toDouble();
+ weights[index.row()].weight = weight;
+ break;
+ }
+ default: return false;
+ }
+
+ emit(dataChanged(index, index));
+
+ writeToDisk();
+ return true;
+}
+
+bool WeightDataModel::setDataForRow(int row, const DateWeight &dw)
+{
+ if (row < 0 || row >= weights.size())
+ return false;
+
+ weights[row] = dw;
+ QModelIndex a = index(row, 0);
+ QModelIndex b = index(row, 1);
+
+ emit(dataChanged(a, b));
+ writeToDisk();
+ return true;
+}
+// Sets data for a date. Adds a new row for the date if it doesn't exist.
+void WeightDataModel::setWeightForDate(const QDate &date, double weight)
+{
+ int row = rowOfDate(date);
+ if (row == -1) {
+ row = rowForNewDate(date);
+ insertRows(row, 1);
+ }
+ DateWeight dw = {date, weight};
+ setDataForRow(row, dw);
+}
+
+void WeightDataModel::setWeightForDate(const WeightDataModel::DateWeight &dw)
+{
+ setWeightForDate(dw.date, dw.weight);
+}
+
+QVariant WeightDataModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ if (orientation == Qt::Horizontal) {
+ return section == 0 ? tr("Date") : tr("Weight");
+ }
+ else {
+ return QString("%1").arg(section);
+ }
+}
+
+// Insert count "empty" rows starting from row.
+// DOESN'T WRITE DATA BACK TO DISK to allow inserter
+// to modify the row, then write it.
+bool WeightDataModel::insertRows(int row, int count, const QModelIndex &/*parent*/)
+{
+ beginInsertRows(QModelIndex(), row, row+count-1);
+ DateWeight empty;
+ //empty.date.setDate(2000,1,1);
+ empty.weight = 0.0;
+ while(count--)
+ weights.insert(row, empty);
+ endInsertRows();
+ return true;
+}
+
+bool WeightDataModel::removeRows(int row, int count, const QModelIndex &/*parent*/)
+{
+ beginRemoveRows(QModelIndex(), row, row+count-1);
+ while(count--)
+ weights.removeAt(row);
+ endRemoveRows();
+ writeToDisk();
+ return true;
+}
+
+//Returns the row of the date or -1 if it doesn't exist.
+int WeightDataModel::rowOfDate(const QDate &date) const
+{
+ for(int i=0; i<weights.size(); i++)
+ if (weights[i].date == date)
+ return i;
+ return -1;
+}
+
+bool WeightDataModel::dateExists(const QDate &date) const
+{
+ return rowOfDate(date) != -1;
+}
+
+int WeightDataModel::rowForNewDate(const QDate &date) const
+{
+ if (weights.size() == 0)
+ return 0;
+ if (date < weights.first().date)
+ return 0;
+ for(int i=1; i<weights.size(); i++) {
+ if (weights.at(i-1).date < date
+ && weights.at(i).date > date)
+ return i;
+ }
+ if (date > weights.last().date)
+ return weights.size();
+ assert(0 && "UNREACHABLE");
+ return -1;
+}
+
+void WeightDataModel::writeToDisk()
+{
+ if (QFile::exists(datafile.fileName())) {
+ QFile::copy(datafile.fileName(), datafile.fileName()+".bak");
+ }
+ if (datafile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ QTextStream stream(&datafile);
+ foreach(DateWeight w, weights)
+ stream << w.date.toString(Qt::ISODate) << ';' << w.weight << "\n";
+ datafile.close();
+ }
+}
+
+void WeightDataModel::readFromDisk()
+{
+ if (!datafile.exists()) {
+ clear();
+ return;
+ }
+ if (datafile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ clear();
+ QTextStream stream(&datafile);
+ QString line = stream.readLine();
+ while (!line.isNull()) {
+ QStringList parts = line.split(';');
+ DateWeight w;
+ w.date = QDate::fromString(parts[0], Qt::ISODate);
+ if (!w.date.isValid()) {
+ throw(QString("Invalid date in file: '%1'").arg(parts[0]));
+ }
+ bool ok;
+ w.weight = parts[1].toDouble(&ok);
+ if(!ok) {
+ throw(QString("Invalid weight in file: '%1'").arg(parts[1]));
+ }
+ weights.push_back(w);
+ line = stream.readLine();
+ }
+ datafile.close();
+ qSort(weights);
+ }
+ else {
+ clear();
+ throw(QString("Could not read file '%1'").arg(datafile.fileName()));
+ return;
+ }
+}
--- /dev/null
+#ifndef WEIGHTDATA_H
+#define WEIGHTDATA_H
+
+#include <QAbstractTableModel>
+#include <QDate>
+#include <QList>
+#include <QFile>
+#include <QDoubleSpinBox>
+#include <QItemEditorCreatorBase>
+
+//For debugging:
+#include <iostream>
+
+// A table model with 2 columns: Date | Weight
+class WeightDataModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ struct DateWeight
+ {
+ QDate date;
+ double weight;
+ bool operator<(const DateWeight &o) const { return date < o.date; }
+ };
+ typedef QList<DateWeight> WeightList;
+ WeightDataModel(QString &datafile, QObject *parent = 0);
+ int rowCount(const QModelIndex &/**/) const { return weights.size(); }
+ int columnCount(const QModelIndex &/**/) const { return 2; }
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role);
+ bool setDataForRow(int row, const DateWeight &dw);
+ void setWeightForDate(const QDate &date, double weight);
+ void setWeightForDate(const DateWeight &dw);
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ int rowOfDate(const QDate &date) const;
+ bool dateExists(const QDate &date) const;
+ int rowForNewDate(const QDate &date) const;
+ void clear();
+
+ int size() const { return weights.size(); }
+ const WeightList &getWeights() const { return weights; }
+private:
+ void writeToDisk();
+ void readFromDisk();
+
+private:
+ WeightList weights;
+ QFile datafile;
+};
+
+typedef WeightDataModel::DateWeight DW;
+
+#endif // WEIGHTDATA_H
--- /dev/null
+#-------------------------------------------------
+#
+# Project created by QtCreator 2011-01-16T18:23:01
+#
+#-------------------------------------------------
+
+QT += core gui maemo5
+
+TARGET = weightgraph
+TEMPLATE = app
+
+
+SOURCES += main.cpp\
+ mainwindow.cpp \
+ weightdata.cpp \
+ editwindow.cpp \
+ weightstatsview.cpp \
+ weightgraphview.cpp \
+ settings.cpp \
+ settingswindow.cpp
+
+HEADERS += mainwindow.h \
+ weightdata.h \
+ editwindow.h \
+ weightview.h \
+ weightspinbox.h \
+ weightstatsview.h \
+ weightgraphview.h \
+ settings.h \
+ settingswindow.h
+
+FORMS += mainwindow.ui
+
+CONFIG += mobility console
+MOBILITY =
+
+RESOURCES += \
+ res.qrc
+
+unix {
+ INSTALLS += target desktop icon64
+ target.path = /usr/bin
+ desktop.path = /usr/share/applications/hildon
+ desktop.files += maemofiles/weightgraph.desktop
+# icon48.path = /usr/share/icons/hicolor/48x48/apps
+# icon48.files += maemofiles/48/weightgraph.png
+# icon64.path = /usr/share/icons/hicolor/64x64/apps
+ icon64.path = /usr/share/icons
+ icon64.files += maemofiles/64/weightgraph.png
+# iconscalable.path = /usr/share/icons/hicolor/scalable/apps
+# iconscalable.files += maemofiles/64/weightgraph.png
+}
+
+symbian {
+ TARGET.UID3 = 0xecc772d7
+ # TARGET.CAPABILITY +=
+ TARGET.EPOCSTACKSIZE = 0x14000
+ TARGET.EPOCHEAPSIZE = 0x020000 0x800000
+}
--- /dev/null
+<!DOCTYPE QtCreatorProject>
+<qtcreator>
+ <data>
+ <variable>ProjectExplorer.Project.ActiveTarget</variable>
+ <value type="int">0</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.EditorSettings</variable>
+ <valuemap type="QVariantMap">
+ <value key="EditorConfiguration.Codec" type="QByteArray">System</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Target.0</variable>
+ <valuemap type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Maemo</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Target.MaemoDeviceTarget</value>
+ <value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value>
+ <value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">qmake</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
+ <valuelist key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QVariantList"/>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.2" type="QVariantMap">
+ <value key="Packaging Enabled" type="bool">true</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MaemoPackageCreationStep</value>
+ <valuelist key="Qt4ProjectManager.BuildStep.MaemoPackage.LocalFiles" type="QVariantList"/>
+ <value key="Qt4ProjectManager.BuildStep.MaemoPackage.Modified" type="bool">false</value>
+ <value key="Qt4ProjectManager.BuildStep.MaemoPackage.RemoteExe" type="QString"></value>
+ <valuelist key="Qt4ProjectManager.BuildStep.MaemoPackage.RemoteFiles" type="QVariantList"/>
+ <value key="Version Number" type="QString">1.0.0</value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">3</value>
+ <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList">
+ <value type="QString">clean</value>
+ </valuelist>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Debug</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/visa/koodaus/maemo/WeightGraph-build-maemo</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">3</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">9</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.1" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">qmake</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
+ <valuelist key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QVariantList"/>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.2" type="QVariantMap">
+ <value key="Packaging Enabled" type="bool">true</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MaemoPackageCreationStep</value>
+ <valuelist key="Qt4ProjectManager.BuildStep.MaemoPackage.LocalFiles" type="QVariantList"/>
+ <value key="Qt4ProjectManager.BuildStep.MaemoPackage.Modified" type="bool">false</value>
+ <value key="Qt4ProjectManager.BuildStep.MaemoPackage.RemoteExe" type="QString"></value>
+ <valuelist key="Qt4ProjectManager.BuildStep.MaemoPackage.RemoteFiles" type="QVariantList"/>
+ <value key="Version Number" type="QString">0.0.1</value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">3</value>
+ <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList">
+ <value type="QString">clean</value>
+ </valuelist>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Release</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/visa/koodaus/maemo/WeightGraph-build-maemo</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">3</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">9</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">2</value>
+ <valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
+ <value key=".ProFile" type="QString">WeightGraph.pro</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">New Maemo Run Configuration</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MaemoRunConfiguration</value>
+ <valuelist key="Qt4ProjectManager.MaemoRunConfiguration.Arguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.MaemoRunConfiguration.DeviceId" type="qulonglong">3</value>
+ <valuelist key="Qt4ProjectManager.MaemoRunConfiguration.LastDeployedFiles" type="QVariantList">
+ <value type="QString">/home/visa/koodaus/maemo/WeightGraph-build-maemo/weightgraph_0.0.1_armel.deb</value>
+ <value type="QString">192.168.2.15</value>
+ <value type="QString">/home/visa/koodaus/maemo/WeightGraph-build-simulator/weightgraph_0.0.1_armel.deb</value>
+ <value type="QString">/media/puhveli/visa/koodaus/maemo/WeightGraph-build-desktop/weightgraph_0.0.1_armel.deb</value>
+ <value type="QString">/home/visa/koodaus/maemo/WeightGraph-build-maemo/weightgraph_1.0.0_armel.deb</value>
+ <value type="QString">192.168.0.9</value>
+ <value type="QString">/home/visa/koodaus/maemo/WeightGraph-build-maemo/weightgraph_0.0.1_armel.deb</value>
+ </valuelist>
+ <valuelist key="Qt4ProjectManager.MaemoRunConfiguration.LastDeployedHosts" type="QVariantList">
+ <value type="QString">192.168.2.15</value>
+ <value type="QString">/home/visa/koodaus/maemo/WeightGraph-build-maemo/weightgraph_0.0.1_armel.deb</value>
+ <value type="QString">192.168.0.9</value>
+ <value type="QString">192.168.0.9</value>
+ <value type="QString">192.168.0.9</value>
+ <value type="QString">/home/visa/koodaus/maemo/WeightGraph-build-maemo/weightgraph_0.0.1_armel.deb</value>
+ <value type="QString">192.168.0.9</value>
+ </valuelist>
+ <valuelist key="Qt4ProjectManager.MaemoRunConfiguration.LastDeployedRemotePaths" type="QVariantList">
+ <value type="QString">/home/user/weightgraph_0.0.1_armel.deb</value>
+ <value type="QString">/home/user/weightgraph_0.0.1_armel.deb</value>
+ <value type="QString">/home/user/weightgraph_0.0.1_armel.deb</value>
+ <value type="QString">/home/user/weightgraph_0.0.1_armel.deb</value>
+ <value type="QString">/home/user/weightgraph_1.0.0_armel.deb</value>
+ <value type="QString">/home/user/weightgraph_0.0.1_armel.deb</value>
+ <value type="QString">/home/user/weightgraph_0.0.1_armel.deb</value>
+ </valuelist>
+ <valuelist key="Qt4ProjectManager.MaemoRunConfiguration.LastDeployedTimes" type="QVariantList">
+ <value type="QDateTime">2011-01-23T23:49:03</value>
+ <value type="QDateTime">2011-01-20T00:24:31</value>
+ <value type="QDateTime">2011-01-28T21:31:27</value>
+ <value type="QDateTime">2011-01-28T20:41:50</value>
+ <value type="QDateTime">2011-02-23T03:19:59</value>
+ <value type="QDateTime">2011-02-22T01:10:11</value>
+ <value type="QDateTime">2011-02-03T03:44:22</value>
+ </valuelist>
+ </valuemap>
+ <value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Target.1</variable>
+ <valuemap type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Qt Simulator</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Target.QtSimulatorTarget</value>
+ <value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value>
+ <value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">qmake</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
+ <valuelist key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QVariantList"/>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">2</value>
+ <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList">
+ <value type="QString">clean</value>
+ </valuelist>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Debug</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/visa/koodaus/maemo/WeightGraph-build-simulator</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.1" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">qmake</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
+ <valuelist key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QVariantList"/>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">2</value>
+ <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList">
+ <value type="QString">clean</value>
+ </valuelist>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Release</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/visa/koodaus/maemo/WeightGraph-build-simulator</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">2</value>
+ <valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">weightgraph</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value>
+ <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">weightgraph.pro</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserSetName" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserSetWorkingDirectory" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Target.2</variable>
+ <valuemap type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Desktop</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Target.DesktopTarget</value>
+ <value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value>
+ <value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">qmake</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
+ <valuelist key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QVariantList"/>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">2</value>
+ <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList">
+ <value type="QString">clean</value>
+ </valuelist>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Debug</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/media/puhveli/visa/koodaus/maemo/WeightGraph-build-desktop</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">8</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">1</value>
+ <valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">weightgraph</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value>
+ <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">weightgraph.pro</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserSetName" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserSetWorkingDirectory" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.TargetCount</variable>
+ <value type="int">3</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+ <value type="int">4</value>
+ </data>
+</qtcreator>
--- /dev/null
+#include "weightgraphview.h"
+#include "settings.h"
+#include <QPainter>
+#include <QDebug>
+#include <QTimer>
+#include <cmath>
+#include <QtGui/QX11Info>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+WeightGraphView::WeightGraphView(WeightDataModel *wdm,
+ const QString &id, QWidget *parent) :
+ QWidget(parent), id(id), wdm(wdm),
+ period(Settings::graphSettings(id).defaultTimeInterval)
+{
+ setWindowTitle("WeightGraph");
+
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ connect(wdm, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ this, SLOT(update()));
+ connect(wdm, SIGNAL(rowsInserted(const QModelIndex&,int,int)),
+ this, SLOT(update()));
+ connect(wdm, SIGNAL(rowsRemoved(const QModelIndex&,int,int)),
+ this, SLOT(update()));
+ connect(Settings::self(), SIGNAL(settingChanged()),
+ this, SLOT(update()));
+}
+
+void WeightGraphView::mousePressEvent(QMouseEvent *)
+{
+ emit clicked();
+}
+
+QSize WeightGraphView::sizeHint() const
+{
+ return QSize(300, 400);
+}
+
+void WeightGraphView::keyPressEvent(QKeyEvent* event)
+{
+ //qDebug() << "Key pressed: " << event->key();
+ switch (event->key()) {
+ case Qt::Key_F7:
+ decPeriod();
+ event->accept();
+ break;
+
+ case Qt::Key_F8:
+ incPeriod();
+ event->accept();
+ break;
+ }
+ 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)
+#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;
+}
+
+void WeightGraphView::paintEvent(QPaintEvent *)
+{
+ QPainter painter(this);
+ painter.setRenderHint(QPainter::Antialiasing);
+
+ GraphSettings gs = Settings::graphSettings(id);
+ const QList<DW> &allWeights = wdm->getWeights();
+
+ double min, max;
+ QList<DW> weights;
+ const DW *beforeFirst = NULL;
+ if (allWeights.size() < 2) {
+ min = 0;
+ max = 100;
+ }
+ else {
+ bool firstFound = false;
+ min = 1e30;
+ max = -1e30;
+ const QDate &l = allWeights.last().date;
+ for(int i=0; i < allWeights.size(); i++) {
+ if (period == 0 || firstFound || allWeights[i].date.daysTo(l) <= period) {
+ weights.append(allWeights[i]);
+ if (allWeights[i].weight < min)
+ min = allWeights[i].weight;
+ if (allWeights[i].weight > max)
+ max = allWeights[i].weight;
+ firstFound = true;
+ }
+ if (!firstFound)
+ beforeFirst = &allWeights[i];
+ }
+ }
+
+ if (gs.weightIntervalMode == GraphSettings::AutomaticWithGoalWeight
+ && gs.goalWeightEnabled) {
+ min = qMin(min, Settings::goalWeightMin());
+ max = qMax(max, Settings::goalWeightMax());
+ }
+ else if(gs.weightIntervalMode == GraphSettings::Manual) {
+ if (gs.weightIntervalMax > gs.weightIntervalMin) {
+ min = gs.weightIntervalMin;
+ max = gs.weightIntervalMax;
+ }
+ }
+ // else default is min and max of actual data
+
+ double margin = (max - min)*0.03;
+ double minW = min - margin;
+ double maxW = max + margin;
+ double weightInterval = maxW-minW;
+ if (maxW-minW < 0.1) {
+ minW = min-0.003;
+ maxW = max+0.003;
+ weightInterval = maxW - minW;
+ }
+ QDate f, l;
+ int days;
+ if (weights.size() < 2) {
+ l = QDate::currentDate();
+ f = l.addDays(-7);
+ days = 7;
+ }
+ else if (period==0) {
+ f = weights.first().date;
+ l = weights.last().date;
+ days = f.daysTo(l);
+ } else {
+ l = weights.last().date;
+ f = l.addDays(-period);
+ days = period;
+ }
+
+ // Interpolate to fill gap in left part of the graph
+ if (weights.first().date != f && beforeFirst != NULL) {
+ DW dw;
+ dw.date = f;
+ dw.weight = (weights.first().weight - beforeFirst->weight)
+ /beforeFirst->date.daysTo(weights.first().date)
+ *beforeFirst->date.daysTo(f)
+ +beforeFirst->weight;
+ weights.prepend(dw);
+ }
+
+ painter.setWindow(-50, 0, width()+85, height()+25);
+
+ if (gs.goalWeightEnabled
+ && ((Settings::goalWeightMin() > minW && Settings::goalWeightMin() < maxW)
+ ||(Settings::goalWeightMax() > minW && Settings::goalWeightMax() < maxW))) {
+ QPen oldPen = painter.pen();
+ QBrush oldBrush = painter.brush();
+ 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.setClipping(false);
+ painter.setPen(oldPen);
+ painter.setBrush(oldBrush);
+ }
+
+ // Y-axis
+ QFont font = painter.font();
+ font.setPixelSize(16);
+ painter.setFont(font);
+ painter.drawLine(QPointF(0.0,0.0), QPointF(0,height()));
+ double mult = weightIntervalToMult(weightInterval);
+ 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)));
+ 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.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);
+ }
+ }
+
+ // X-axis
+ font.setPixelSize(13);
+ painter.setFont(font);
+ double endOfLastDate = -1e6;
+ mult = days/30+1;
+ painter.drawLine(QPointF(0.0,height()), QPointF(width(),height()));
+ for(int day=0; day <= days; day+=mult) {
+ 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) {
+ tickLen = 5.0;
+ painter.drawText(QPointF(D_X(day)-textSize.width()/2,
+ W_Y(minW)+18), text);
+ endOfLastDate = D_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));
+ }
+
+ // The weight data
+ QPolygonF linepoints;
+ foreach(DW dw, weights) {
+ linepoints << DW_POINT(dw);
+ }
+ painter.drawPolyline(linepoints);
+
+}
+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
+ //graph to actually show up, then call update.
+ QTimer *tmp = new QTimer(this);
+ tmp->setSingleShot(true);
+ tmp->setInterval(500);
+ connect(tmp, SIGNAL(timeout()), this, SLOT(update()));
+ tmp->start();
+}
+
+void WeightGraphView::grabZoomKeys(bool grab)
+{
+ if (!winId()) {
+ qWarning("Can't grab keys unless we have a window id");
+ return;
+ }
+
+ 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!");
+ return;
+ }
+
+
+ XChangeProperty (QX11Info::display(),
+ winId(),
+ atom,
+ XA_INTEGER,
+ 32,
+ PropModeReplace,
+ reinterpret_cast<unsigned char *>(&val),
+ 1);
+
+ //qDebug() << "Grabbed for winId " << winId();
+}
--- /dev/null
+#ifndef WEIGHTGRAPHVIEW_H
+#define WEIGHTGRAPHVIEW_H
+
+#include <QWidget>
+#include <QKeyEvent>
+#include "weightdata.h"
+#include "settings.h"
+
+class WeightGraphView : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit WeightGraphView(WeightDataModel *wdm, const QString &id, QWidget *parent = 0);
+ QSize sizeHint() const;
+signals:
+ void clicked();
+public slots:
+ void paintEvent(QPaintEvent *);
+ void show();
+ void update() {
+ grabZoomKeys(Settings::grabZoomKeys());
+ QWidget::update();
+ }
+
+ void grabZoomKeys(bool grab);
+ void incPeriod() {
+ if (period == 0)
+ period = wdm->getWeights().first().date.daysTo(wdm->getWeights().last().date) + 1;
+ else
+ period++;
+ update();
+ }
+ void decPeriod() {
+ if (period == 0)
+ period = wdm->getWeights().first().date.daysTo(wdm->getWeights().last().date) - 1;
+ else
+ period = qMax(1, period-1);
+ update();
+ }
+ void setPeriod(int period) { this->period = period; update(); }
+protected:
+ void mousePressEvent(QMouseEvent *);
+ void keyPressEvent(QKeyEvent* event);
+private:
+ QString id;
+ WeightDataModel *wdm;
+ int period;
+};
+
+#endif // WEIGHTGRAPHVIEW_H
--- /dev/null
+#ifndef WEIGHTSPINBOX_H
+#define WEIGHTSPINBOX_H
+
+#include <QDoubleSpinBox>
+#include "settings.h"
+
+class WeightSpinBox : public QDoubleSpinBox
+{
+ Q_OBJECT
+public:
+ WeightSpinBox(QWidget *parent=0) : QDoubleSpinBox(parent)
+ {
+ setDecimals(1);
+ setSingleStep(0.1);
+ setMinimum(10.0);
+ setMaximum(999.9);
+ setValue(60.0);
+ updateWeightUnit();
+ connect(Settings::self(), SIGNAL(settingChanged()),
+ this, SLOT(updateWeightUnit()));
+ }
+private slots:
+ void updateWeightUnit() {
+ setSuffix(" "+Settings::weightUnit());
+ }
+};
+
+#endif // WEIGHTSPINBOX_H
--- /dev/null
+#include "weightstatsview.h"
+#include "settings.h"
+#include <QVBoxLayout>
+#include <QGroupBox>
+
+#include <QDebug>
+
+WeightStatsView::WeightStatsView(WeightDataModel *wdm, QWidget *parent) :
+ QWidget(parent), wdm(wdm)
+{
+ connect(wdm, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ this, SLOT(updateStats()));
+ connect(wdm, SIGNAL(rowsInserted(const QModelIndex&,int,int)),
+ this, SLOT(updateStats()));
+ connect(wdm, SIGNAL(rowsRemoved(const QModelIndex&,int,int)),
+ this, SLOT(updateStats()));
+ connect(Settings::self(), SIGNAL(settingChanged()),
+ this, SLOT(updateStats()));
+
+ QVBoxLayout *lo = new QVBoxLayout(this);
+
+ last = new QLabel(this);
+ lo->addWidget(last);
+
+ change = new QLabel(this);
+ lo->addWidget(change);
+
+ updateStats();
+}
+
+QString dateString(QDate date)
+{
+ int days = date.daysTo(QDate::currentDate());
+ if (days < 0)
+ return date.toString(Qt::ISODate);
+ else if (days == 0)
+ return "Today";
+ else if (days == 1)
+ return "Yesterday";
+ else if (days < 7)
+ return date.toString("dddd");
+ else
+ return date.toString(Qt::ISODate);
+}
+
+QString dateIntervalString(int days)
+{
+ if (days < 30)
+ return QString("%1 days").arg(days);
+ else if (days < 360)
+ return QString("%1m %2d").arg(days/30).arg(days%30);
+ else if (days < 365)
+ return QString("1y 0m");
+ else
+ return QString("%1y %2m").arg(days/365).arg((days%365)/30);
+}
+
+void WeightStatsView::updateStats()
+{
+ if (wdm->size() == 0) {
+ last->setText("Last: No data");
+ change->setText("Change: No data");
+ return;
+ }
+ QString unit = Settings::weightUnit();
+ const DW &f = wdm->getWeights().first();
+ const DW &l = wdm->getWeights().last();
+ last->setText(tr("Last: %1 %2\n (%3)")
+ .arg(l.weight,0,'f',1)
+ .arg(unit)
+ .arg(dateString(l.date)));
+ change->setText(tr("Change: %1 %2\n"
+ " (in %3)")
+ .arg(l.weight-f.weight,0,'f',1)
+ .arg(unit)
+ .arg(dateIntervalString(f.date.daysTo(l.date))));
+}
--- /dev/null
+#ifndef WEIGHTSTATSVIEW_H
+#define WEIGHTSTATSVIEW_H
+
+#include <QWidget>
+#include <QLabel>
+#include "weightdata.h"
+
+class WeightStatsView : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit WeightStatsView(WeightDataModel *wdm, QWidget *parent = 0);
+
+
+signals:
+
+public slots:
+ void updateStats();
+private:
+ WeightDataModel *wdm;
+ QLabel *last;
+ QLabel *change;
+};
+
+#endif // WEIGHTSTATSVIEW_H
--- /dev/null
+#ifndef WEIGHTVIEW_H
+#define WEIGHTVIEW_H
+
+#include <QTableView>
+#include <QStyledItemDelegate>
+#include <QItemEditorCreatorBase>
+#include <QDoubleSpinBox>
+#include <QItemEditorFactory>
+#include <QFont>
+#include <QHeaderView>
+#include "weightspinbox.h"
+
+class WeightView : public QTableView
+{
+ Q_OBJECT
+public:
+ explicit WeightView(QWidget *parent = 0) :
+ QTableView(parent)
+ {
+ QItemEditorFactory *editorFactory = new QItemEditorFactory;
+ editorFactory->registerEditor(QVariant::Double, new WeightView::WeightEditCreator);
+ delegate.setItemEditorFactory(editorFactory);
+ setItemDelegate(&delegate);
+ setSelectionMode(QAbstractItemView::SingleSelection);
+ this->verticalHeader()->hide();
+ this->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
+ this->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
+ QFont f;
+ f.setPointSize(28);
+ setFont(f);
+ }
+
+ class WeightEditCreator : public QItemEditorCreatorBase
+ {
+ public:
+ WeightEditCreator() : QItemEditorCreatorBase() { }
+ virtual QWidget *createWidget(QWidget *parent) const
+ {
+ return new WeightSpinBox(parent);
+ }
+ virtual QByteArray valuePropertyName() const { return "value"; }
+ };
+ private:
+ QStyledItemDelegate delegate;
+};
+
+#endif // WEIGHTVIEW_H
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
-WeightGraph is a Maemo 5 utility that helps you keep track of your weight. It
+<h1>WeightGraph</h1>
+<p>WeightGraph is a Maemo 5 utility that helps you keep track of your weight. It
lets you record weight measurements daily and as the name suggests, it plots a
nice curve based on the weight data. WeightGraph is designed to be simple and
-easy to use.
+easy to use.</p>
</body>
</html>