File merkaartor-20091019_r144.diff of Package merkaartor

Index: clean.sh
===================================================================
--- clean.sh	(revision 0)
+++ clean.sh	(revision 144)
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+make distclean
+rm -rf binaries \
+       plugins/background/MYahooBackground/tmp \
+       plugins/qtstyle/skulpture22/tmp

Property changes on: clean.sh
___________________________________________________________________
Added: svn:executable
   + *

Index: build.sh
===================================================================
--- build.sh	(revision 0)
+++ build.sh	(revision 144)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+libdir=/usr/local/lib
+arch | grep -q x86_64 && libdir=/usr/local/lib64
+
+lrelease Merkaartor.pro
+qmake Merkaartor.pro PREFIX=/usr/local \
+                     NODEBUG=0 \
+                     GDAL=1 \
+                     GPSD=1 \
+                     GEOIMAGE=1 \
+                     LIBDIR=$libdir \
+                     FORCE_CUSTOM_STYLE=1
+make
+sudo make install

Property changes on: build.sh
___________________________________________________________________
Added: svn:executable
   + *

Index: src/MainWindow.h
===================================================================
--- src/MainWindow.h	(revision 107)
+++ src/MainWindow.h	(working copy)
@@ -160,6 +160,9 @@ class MainWindow : public QMainWindow, public Ui::
 		void move_triggered();
 		void add_triggered();
 		void reverse_triggered();
+		// signal forwarding
+		void continue_filtering(double, double, bool, bool, QPoint);
+		void update_delta(double londelta, double latdelta);
 
 	public:
 		MainWindowPrivate* p;
@@ -191,7 +194,12 @@ class MainWindow : public QMainWindow, public Ui::
 		void projectionTriggered(QAction* anAction);
 #endif
 		void styleTriggered(QAction* anAction);
-        void updateGpsPosition(float latitude, float longitude, QDateTime time, float altitude, float speed, float heading);
+        // set adjustposition to true for only updating the position marker, but not recording the trackpoint
+        void updateGpsPosition(float latitude, float longitude, QDateTime time, float altitude, float speed, float heading, 
+                               bool adjustposition);
+		// opens the trackfilter dialog
+		void GPSFilter(QString errmsg, double londelta, double latdelta, bool correctFutureTackpoints, 
+			       QPoint filterposition);
 		void applyStyles(QList<FeaturePainter>* thePainters);
 
 	public:
Index: src/GPS/trackfilterdialog.h
===================================================================
--- src/GPS/trackfilterdialog.h	(revision 0)
+++ src/GPS/trackfilterdialog.h	(revision 144)
@@ -0,0 +1,36 @@
+#ifndef TRACKFILTERDIALOG_H
+#define TRACKFILTERDIALOG_H
+
+#include <QDialog>
+
+#include "ui_trackfilterdialog.h"
+
+// trackfilter dialog window
+class TrackFilterDialog : public QDialog, public Ui::TrackFilterDialog
+{
+    Q_OBJECT
+
+private:
+    // for remembering previous deltas
+    double londelta, latdelta;
+
+public:
+    TrackFilterDialog(QWidget *parent = 0, double londelta = 0, double latdelta = 0, 
+                      bool correctFutureTackpoints = 0, QPoint *filterposition = NULL);
+
+signals:
+    // continue with updated position
+    void continue_filtering(double londelta, double latdelta, bool record, bool change_lon_lat_deltas, QPoint filterposition);
+    // show updated position with position marker on the map
+    void update_delta(double londelta,double latdelta);
+
+private slots:
+    // show updated position on the map when spinboxes/sliders are changed
+    void update();
+    // when pressing 'Use trackpoint' button
+    void accept();
+    // when pressing 'Discard trackpoint' button
+    void reject();
+};
+
+#endif
Index: src/GPS/trackfilterdialog.ui
===================================================================
--- src/GPS/trackfilterdialog.ui	(revision 0)
+++ src/GPS/trackfilterdialog.ui	(revision 144)
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>TrackFilterDialog</class>
+ <widget class="QDialog" name="TrackFilterDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>438</width>
+    <height>302</height>
+   </rect>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>438</width>
+    <height>302</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>TrackFilter</string>
+  </property>
+  <widget class="QGroupBox" name="groupBox">
+   <property name="geometry">
+    <rect>
+     <x>20</x>
+     <y>10</y>
+     <width>201</width>
+     <height>181</height>
+    </rect>
+   </property>
+   <property name="title">
+    <string>Correct Position (meter)</string>
+   </property>
+   <widget class="QSlider" name="lonhorizontalSlider">
+    <property name="geometry">
+     <rect>
+      <x>80</x>
+      <y>60</y>
+      <width>84</width>
+      <height>16</height>
+     </rect>
+    </property>
+    <property name="minimum">
+     <number>-500</number>
+    </property>
+    <property name="maximum">
+     <number>500</number>
+    </property>
+    <property name="singleStep">
+     <number>0</number>
+    </property>
+    <property name="orientation">
+     <enum>Qt::Horizontal</enum>
+    </property>
+   </widget>
+   <widget class="QSlider" name="latverticalSlider">
+    <property name="geometry">
+     <rect>
+      <x>30</x>
+      <y>30</y>
+      <width>16</width>
+      <height>84</height>
+     </rect>
+    </property>
+    <property name="minimum">
+     <number>-500</number>
+    </property>
+    <property name="maximum">
+     <number>500</number>
+    </property>
+    <property name="orientation">
+     <enum>Qt::Vertical</enum>
+    </property>
+   </widget>
+   <widget class="QSpinBox" name="latspinBox">
+    <property name="geometry">
+     <rect>
+      <x>10</x>
+      <y>140</y>
+      <width>55</width>
+      <height>23</height>
+     </rect>
+    </property>
+    <property name="minimum">
+     <number>-500</number>
+    </property>
+    <property name="maximum">
+     <number>500</number>
+    </property>
+   </widget>
+   <widget class="QSpinBox" name="lonspinBox">
+    <property name="geometry">
+     <rect>
+      <x>90</x>
+      <y>90</y>
+      <width>55</width>
+      <height>23</height>
+     </rect>
+    </property>
+    <property name="minimum">
+     <number>-500</number>
+    </property>
+    <property name="maximum">
+     <number>500</number>
+    </property>
+   </widget>
+  </widget>
+  <widget class="QWidget" name="layoutWidget">
+   <property name="geometry">
+    <rect>
+     <x>261</x>
+     <y>41</y>
+     <width>161</width>
+     <height>110</height>
+    </rect>
+   </property>
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <widget class="QPushButton" name="useTrackpointButton">
+      <property name="text">
+       <string>Use Trackpoint</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>38</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item>
+     <widget class="QPushButton" name="discardTrackpointButton">
+      <property name="text">
+       <string>Discard Trackpoint</string>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QCheckBox" name="correctFutureTrackpointscheckBox">
+   <property name="geometry">
+    <rect>
+     <x>30</x>
+     <y>210</y>
+     <width>321</width>
+     <height>22</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Use correction also for future Trackpoints</string>
+   </property>
+  </widget>
+  <widget class="QLabel" name="ErrorMessage">
+   <property name="geometry">
+    <rect>
+     <x>30</x>
+     <y>260</y>
+     <width>391</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>Error Message</string>
+   </property>
+  </widget>
+ </widget>
+ <tabstops>
+  <tabstop>latspinBox</tabstop>
+  <tabstop>latverticalSlider</tabstop>
+  <tabstop>lonspinBox</tabstop>
+  <tabstop>lonhorizontalSlider</tabstop>
+  <tabstop>useTrackpointButton</tabstop>
+  <tabstop>discardTrackpointButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>useTrackpointButton</sender>
+   <signal>clicked()</signal>
+   <receiver>TrackFilterDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>337</x>
+     <y>55</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>317</x>
+     <y>180</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>discardTrackpointButton</sender>
+   <signal>clicked()</signal>
+   <receiver>TrackFilterDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>311</x>
+     <y>139</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>336</x>
+     <y>180</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
Index: src/GPS/trackfilterdialog.cpp
===================================================================
--- src/GPS/trackfilterdialog.cpp	(revision 0)
+++ src/GPS/trackfilterdialog.cpp	(revision 144)
@@ -0,0 +1,88 @@
+#include <QtGui>
+
+#include "trackfilterdialog.h"
+
+TrackFilterDialog::TrackFilterDialog(QWidget *parent, double lon_delta, double lat_delta,
+                                     bool correctFutureTrackpoints, QPoint *filterposition)
+    : QDialog(parent)
+{
+    setupUi(this);
+
+    // move dialog window to initial or latest position
+    move(*filterposition);
+
+    // remember current deltas;
+    londelta=lon_delta;
+    latdelta=lat_delta;
+
+    // show current state, whether deltas were used not only for one trackpoint
+    correctFutureTrackpointscheckBox->setChecked(correctFutureTrackpoints);
+
+    // connect spinbox/slider for latitude
+    QObject::connect(latspinBox, SIGNAL(valueChanged(int)),
+                     latverticalSlider, SLOT(setValue(int)));
+    QObject::connect(latverticalSlider, SIGNAL(valueChanged(int)),
+                     latspinBox, SLOT(setValue(int)));
+
+    // show current delta for latitude in spinbox/slider
+    latspinBox->setValue((int)(latdelta*40000000/360));
+
+    // connect spinbox/slider for longitude in spinbox/slider
+    QObject::connect(lonspinBox, SIGNAL(valueChanged(int)),
+                     lonhorizontalSlider, SLOT(setValue(int)));
+    QObject::connect(lonhorizontalSlider, SIGNAL(valueChanged(int)),
+                     lonspinBox, SLOT(setValue(int)));
+
+    // show current delta for longitude
+    lonspinBox->setValue((int)(londelta*40000000/360));
+
+    // call update() if anything is changed in spinbox/slider for latitude/longitude
+    QObject::connect(latspinBox, SIGNAL(valueChanged(int)),
+                     this, SLOT(update()));
+    QObject::connect(lonspinBox, SIGNAL(valueChanged(int)),
+                     this, SLOT(update()));
+
+    // show current position with position marker on the map
+    update();
+}
+
+void TrackFilterDialog::update()
+{
+    // show updated position with position marker on the map
+    emit update_delta((lonspinBox->value() * 360.0 / 40000000) - londelta,
+		      (latspinBox->value() * 360.0 / 40000000) - latdelta);
+}
+
+void TrackFilterDialog::accept()
+{
+    // continue with updated deltas
+
+    //
+    // FIXME: Make sure that values for latspinBox/lonspinBox are the 
+    //        same next time if 'Use for future Trackpoints' checkbox
+    //        is set. Currently this is sometimes broken due to 
+    //        rounding errors and conversion issues between int and
+    //        double types. 
+    //
+    emit continue_filtering(lonspinBox->value() * 360.0 / 40000000,
+			    latspinBox->value() * 360.0 / 40000000,
+			    1, // record trackpoint
+			    correctFutureTrackpointscheckBox->isChecked(),
+			    pos() // dialog window position
+			    );
+    // close dialog window
+    done(0);
+}
+
+void TrackFilterDialog::reject()
+{
+    // continue with previous deltas
+    emit continue_filtering(londelta, 
+			    latdelta, 
+			    0, // do not record trackpoint
+			    correctFutureTrackpointscheckBox->isChecked(), 
+			    pos() // dialog window position
+			    );
+    // close dialog window
+    done(1);
+}
Index: src/GPS/qgpsdevice.h
===================================================================
--- src/GPS/qgpsdevice.h	(revision 107)
+++ src/GPS/qgpsdevice.h	(working copy)
@@ -25,6 +25,8 @@
 #include <QThread>
 #include <QDateTime>
 #include <QFile>
+#include <QStringList>
+#include <qpoint.h>
 
 class QString;
 class QMutex;
@@ -113,6 +115,13 @@ class QGPSDevice : public QThread
         float speed()           { return cur_speed;         }
         float variation()       { return cur_variation;     }
         float dillution()       { return cur_dillution;     }
+        // returns current deltas for latitude/longitude (used when showing current position) 
+        double latdelta()       { return cur_latdelta;      }
+        double londelta()       { return cur_londelta;      }
+        // returns current update deltas for latitude/longitude (used when showing current position)
+        // introduced for the temporary changes of deltas in trackfilter dialog
+        double updatelatdelta() { return update_latdelta;   } 
+        double updatelondelta() { return update_londelta;   } 
         
         CardinalDirection latCardinal()     { return cur_latCardinal;   }
         CardinalDirection longCardinal()    { return cur_longCardinal;  }
@@ -126,11 +135,15 @@ class QGPSDevice : public QThread
         int latDegrees();
         int latMinutes();
         int latSeconds();
+        // better precision required when used for NMEA
+        double latSecondsf();
         
         int longDegrees();
         int longMinutes();
         int longSeconds();
-        
+        // better precision required when used for NMEA
+        double longSecondsf();
+
     public slots:
             
         virtual void startDevice();
@@ -138,9 +151,13 @@ class QGPSDevice : public QThread
 
     signals:
     
-        void  updatePosition(float latitude, float longitude, QDateTime time, float altitude, float speed, float heading);
+        // set adjustposition to true for only updating the position marker, but not recording the trackpoint
+        void  updatePosition(float latitude, float longitude, QDateTime time, float altitude, float speed, float heading,
+                             bool adjustposition);
         void  updateStatus();
         void doStopDevice();
+        // trigger opening the trackfilter dialog
+        void gpsfilter(QString errmsg, double londelta, double latdelta, bool correctFutureTackpoints, QPoint filterposition);
 
         
     protected:
@@ -175,13 +192,34 @@ class QGPSDevice : public QThread
 
 		QDateTime cur_datetime;
 
+        // current/previous timestamp for calculating acceleration
+        double cur_timestamp;
+        double prev_timestamp;
+        // deltas and update deltas for showing position of trackpoint
+        double cur_latdelta;
+        double cur_londelta;
+        double update_latdelta;
+        double update_londelta;
         float cur_latitude;
         float cur_longitude;
         float cur_altitude;
         float cur_heading;
         float cur_speed;
+        // previous speed for calculating acceleration
+        float prev_speed;
+        // backup speed, so it can easily be restored if trackpoint is discarded
+        float tmp_speed;
         float cur_variation;
         float cur_dillution;
+
+        // flag being set when trackfilter dialog is opened/closed
+        bool filterdialogvisible;
+        // flag to set whether deltas are also to be used for future trackpoints
+        bool correctFutureTackpoints;
+        // position of dialog window
+        QPoint filterpos;
+        // buffer for trackpoints; used when filterdialog=true
+        QStringList linesbuffer;
         
         CardinalDirection cur_latCardinal;
         CardinalDirection cur_longCardinal;
@@ -196,6 +234,9 @@ class QGPSDevice : public QThread
         FixType cur_fixType;
         FixMode cur_fixMode;
         FixStatus cur_fixStatus;
+
+        // NMEA file to record trackpoints
+        QFile *LogFile;
         
         bool parseGGA(const char *ggaString = 0);
         bool parseGLL(const char *ggaString = 0);
@@ -278,11 +319,23 @@ class QGPSDDevice : public QGPSDevice
 	protected:
 		virtual void run();
 
+	public slots:
+		// continue filtering with updated deltas
+        	virtual void continueFiltering(double londelta, double latdelta, bool record, 
+					       bool change_lon_lat_deltas, QPoint filterposition);
+		// show updated position of trackpoint, but don't record it
+        	virtual void UpdateDelta(double londelta, double latdelta);
+
 	private:
 		void onLinkReady();
 		void onDataAvailable();
 		void onStop();
 
+		// write NMEA log
+		void writeLog();
+		// calculate checksum of NMEA sentence
+		int checksum(const char *buf);
+
 		void parse(const QString& s);
 		void parseO(const QString& s);
 		void parseY(const QString& s);
Index: src/GPS/GPS.pri
===================================================================
--- src/GPS/GPS.pri	(revision 107)
+++ src/GPS/GPS.pri	(working copy)
@@ -1,16 +1,19 @@
 
 FORMS += \
-           qgpsmainwindowui.ui 
+           qgpsmainwindowui.ui \
+           trackfilterdialog.ui
 
 HEADERS += qgps.h \
            qgpssatellitetracker.h \
            qgpsdevice.h \
-	   SatelliteStrengthView.h
+	   SatelliteStrengthView.h \
+           trackfilterdialog.h
 
 SOURCES += qgps.cpp \
            qgpssatellitetracker.cpp \
            qgpsdevice.cpp \
-	   SatelliteStrengthView.cpp
+	   SatelliteStrengthView.cpp \
+           trackfilterdialog.cpp
 
 DEFINES += USE_GPS
 
Index: src/GPS/qgpsdevice.cpp
===================================================================
--- src/GPS/qgpsdevice.cpp	(revision 107)
+++ src/GPS/qgpsdevice.cpp	(working copy)
@@ -36,6 +36,13 @@
 
 #include "Preferences/MerkaartorPreferences.h"
 
+// filter limits are currently hard-coded
+#define MAXSPEED 25
+#define MINACCEL -10
+#define MAXACCEL 4
+/*  about HDOP=6.66 */
+#define MAXDILLUTION 100
+
 /* GPSSLOTFORWARDER */
 
 GPSSlotForwarder::GPSSlotForwarder(QGPSDevice* aTarget)
@@ -76,11 +83,30 @@ QGPSDevice::QGPSDevice()
 {
     mutex = new QMutex(QMutex::Recursive);
 
+    // initialize new members
+    cur_timestamp = 0;
+    prev_timestamp = 0;
+    // trackfilter not active
+    filterdialogvisible = 0;
+    // no deltas required
+    cur_latdelta = 0;
+    cur_londelta = 0;
+    update_latdelta = 0;
+    update_londelta = 0;
+    // nothing to correct
+    correctFutureTackpoints = 0;
+    // show trackfilter dialog at the top left corner of the screen
+    // when being opened
+    filterpos.setX(0);
+    filterpos.setY(0);
+
     setLatitude(0);
     setLongitude(0);
     setAltitude(0);
     setHeading(0);
     setSpeed(0);
+    // assume a previous speed of 0
+    prev_speed = 0;
     setVariation(0);
 
 	setFixMode(QGPSDevice::FixAuto);
@@ -112,6 +138,13 @@ int QGPSDevice::latSeconds()
 	double s = (m * 60) - int(m * 60);
 	return int(s * 60);
 }
+// NMEA needs a better precision
+double QGPSDevice::latSecondsf()
+{
+        double m = fabs(latitude()) - latDegrees();
+        double s = (m * 60) - int(m * 60);
+        return s * 60;
+}
 int QGPSDevice::longDegrees()    { return (int) (fabs(longitude()));													}
 int QGPSDevice::longMinutes()
 {
@@ -124,6 +157,13 @@ int QGPSDevice::longSeconds()
 	double s = (m * 60) - int(m * 60);
 	return int(s * 60);
 }
+// NMEA needs a better precision
+double QGPSDevice::longSecondsf()
+{
+        double m = fabs(longitude()) - longDegrees();
+        double s = (m * 60) - int(m * 60);
+        return (s * 60);
+}
 
 bool QGPSDevice::isActiveSat(int prn)
 {
@@ -767,7 +807,8 @@ void QGPSComDevice::parse(const QByteArray& buffer
         //strcpy(nmeastr_rmc, bufferString);
         if (parseRMC(bufferString.data()))
 			if (fixStatus() == QGPSDevice::StatusActive && (fixType() == QGPSDevice::Fix3D || fixType() == QGPSDevice::FixUnavailable))
-				emit updatePosition(latitude(), longitude(), dateTime(), altitude(), speed(), heading());
+				// adjustposition=false
+				emit updatePosition(latitude(), longitude(), dateTime(), altitude(), speed(), heading(), 0);
 	}
 	emit updateStatus();
 }
@@ -890,7 +931,8 @@ void QGPSFileDevice::onDataAvailable()
                 //strcpy(nmeastr_rmc, bufferString);
                 if (parseRMC(bufferString))
 					if (fixStatus() == QGPSDevice::StatusActive && (fixType() == QGPSDevice::Fix3D || fixType() == QGPSDevice::FixUnavailable))
-						emit updatePosition(latitude(), longitude(), dateTime(), altitude(), speed(), heading());
+						// adjustpostion=false
+						emit updatePosition(latitude(), longitude(), dateTime(), altitude(), speed(), heading(), 0);
            }
 
             mutex->unlock();
@@ -907,13 +949,34 @@ QGPSDDevice::QGPSDDevice(const QString& device)
 	setDevice(device);
 }
 
+// open NMEA logfile
 bool QGPSDDevice::openDevice()
 {
+	if (M_PREFS->getGpsSaveLog()) {
+		QString fn = "log-" + QDateTime::currentDateTime().toString(Qt::ISODate) + ".nmea";
+		fn.replace(':', '-');
+		LogFile = new QFile(M_PREFS->getGpsLogDir() + "/"+fn);
+		if (!LogFile->open(QIODevice::WriteOnly)) {
+			QMessageBox::critical(NULL, tr("GPS log error"),
+					      tr("Unable to create GPS log file: %1.").arg(M_PREFS->getGpsLogDir() + "/"+fn), 
+					      QMessageBox::Ok);
+			delete LogFile;
+			LogFile = NULL;
+		}
+	}
+
 	return true;
 }
 
+// close NMEA logfile
 bool QGPSDDevice::closeDevice()
 {
+	if (LogFile && LogFile->isOpen()) {
+		LogFile->close();
+		delete LogFile;
+	}
+	LogFile = NULL;
+
 	return true;
 }
 
@@ -933,6 +996,8 @@ void QGPSDDevice::run()
 	connect(Server,SIGNAL(readyRead()),&Forward,SLOT(onDataAvailable()));
 	connect(this,SIGNAL(doStopDevice()),&Forward,SLOT(onStop()));
 	exec();
+	// close NMEA logfile
+	closeDevice();
 }
 
 void QGPSDDevice::onDataAvailable()
@@ -954,15 +1019,27 @@ void QGPSDDevice::onDataAvailable()
 
 void QGPSDDevice::parse(const QString& s)
 {
-	qDebug() << "parsing " << s.toUtf8().data() << "*";
-	QStringList Args(s.split(',',QString::SkipEmptyParts));
-	for (int i=0; i<Args.count(); ++i)
-	{
-		QString Left(Args[i].left(2));
-		if (Left == "O=")
+	// write trackpoint data to buffer
+	linesbuffer << s;
+	// look at buffer
+	while (!linesbuffer.isEmpty()) {
+	    // read buffer and parse data if trackfilter dialog is not open; 
+	    // otherwise return immediately
+	    if (!filterdialogvisible) {
+		QString first=linesbuffer.first();
+		linesbuffer.removeFirst();
+		qDebug() << "parsing " << first.toUtf8().data() << "*";
+		QStringList Args(first.split(',',QString::SkipEmptyParts));
+		for (int i=0; i<Args.count(); ++i) {
+		    QString Left(Args[i].left(2));
+		    if (Left == "O=")
 			parseO(Args[i].right(Args[i].length()-2));
-		if (Left == "Y=")
+		    if (Left == "Y=")
 			parseY(Args[i].right(Args[i].length()-2));
+		}
+	    } else {
+	    	return;
+	    }
 	}
 }
 
@@ -990,40 +1067,286 @@ void QGPSDDevice::parseY(const QString& s)
 
 void QGPSDDevice::parseO(const QString& s)
 {
+	double timestamp;
+
 	if (s.isEmpty()) return;
 	setFixType(FixInvalid);
+	setFixStatus(StatusVoid); // by Travers Carter <tcarter@noggin.com.au>
 	if (s[0] == '?') return;
 	QStringList Args(s.split(' ',QString::SkipEmptyParts));
 	if (Args.count() < 5) return;
 	setFixType(Fix2D);
+	setFixStatus(StatusActive); // by Travers Carter <tcarter@noggin.com.au>
 	setLatitude(Args[3].toDouble());
 	setLongitude(Args[4].toDouble());
+
+	// Update the timestamp (by Travers Carter <tcarter@noggin.com.au>)
+	cur_datetime = QDateTime::fromTime_t(Args[1].toDouble()).toUTC();
+
+	// make sure we update prev_timestamp and prev_speed, which
+        // are later being used by acceleration filter, only when
+	// timestamp of trackpoint data changes
+	timestamp = Args[1].toDouble();
+	if (cur_timestamp) {
+		if (timestamp - cur_timestamp > 0) {
+			printf("*** timestamp changed ***\n");
+			prev_timestamp = cur_timestamp;
+			prev_speed = speed();
+		}
+	} else {
+		prev_timestamp = timestamp;
+	}
+
+	cur_timestamp = timestamp;
+
+	// Debug output
+	printf("timestamp:      %f\n", timestamp);
+	printf("prev_timestamp: %f\n", prev_timestamp);
+	printf("cur_timestamp:  %f\n", cur_timestamp);
+
 	double Alt = 0;
 	if (Args.count() > 5)
 		Alt = Args[5].toDouble();
 	double Speed = 0;
 	if (Args.count() > 9)
-		Speed = Args[9].toDouble();
+		Speed = Args[9].toDouble() / 1000 * 3600; // Convert from metres/sec to km/h
+							  // (by Travers Carter <tcarter@noggin.com.au>)
 	double Heading = 0;
 	if (Args.count() > 7)
 		Heading = Args[7].toDouble();
-	emit updatePosition(Args[3].toDouble(),
-		Args[4].toDouble(),
-		QDateTime::currentDateTime(),
-		Alt, Speed, Heading);
+	
+	// Update the fix type (by Travers Carter <tcarter@noggin.com.au>)
+	if (Args.count() > 14) {
+		if (Args[14] == "1") {
+			setFixType(FixUnavailable);
+		} else if (Args[14] == "3") {
+			setFixType(Fix3D);
+		}
+	}
+
+	// Dillution filter
+        double Dillution = 0;
+        if (Args.count() > 6) {
+		Dillution = Args[6].toDouble();
+		printf("Dillution: %f\n", Dillution);
+		if (Dillution > MAXDILLUTION) {
+			qDebug() << "dillution :" << Dillution << " m > " 
+ 			         << MAXDILLUTION << "--> dropping trackpoint";
+			setHeading(Heading);
+			setAltitude(Alt);
+			setSpeed(Speed);
+			emit updateStatus();
+			QString errmsg;
+			errmsg=QString("Horizontal error estimate too high (%1m > %2m)")
+				.arg(Dillution).arg(MAXDILLUTION);
+			// trigger opening the trackfilter dialog
+			emit gpsfilter(errmsg, cur_londelta, cur_latdelta, correctFutureTackpoints, filterpos);
+			// flag it as openend, so trackpoint data is buffered
+			filterdialogvisible=1;
+			return;
+		}
+	}
+	setDillution(Dillution);
+
+	printf("prev_speed: %f m/s\n",prev_speed/3.6);
+	printf("cur_speed: %f m/s\n", Speed/3.6);
+
+	// Speed/acceleration filters (higher priority for speed filter) 
+	if (Speed > MAXSPEED) {
+	    qDebug() << "speed :" << Speed << " km/h > " << MAXSPEED << "--> dropping trackpoint";
+	    setHeading(Heading);
+	    setAltitude(Alt);
+	    setSpeed(Speed);
+	    emit updateStatus();
+	    QString errmsg;
+	    errmsg=QString("Speed too high (%1km/h > %2km/h)").arg(Speed).arg(MAXSPEED);
+	    // trigger opening the trackfilter dialog
+	    emit gpsfilter(errmsg, cur_londelta, cur_latdelta, correctFutureTackpoints, filterpos);
+	    // flag it as openend, so trackpoint data is buffered
+	    filterdialogvisible=1;
+	    return;
+	} else if ((cur_timestamp - prev_timestamp) > 0) {
+		float accel = (Speed - prev_speed)/
+			       (3.6 * (cur_timestamp - prev_timestamp));
+		printf("accel: %f m/(s*s)\n", accel);
+		if (accel > MAXACCEL || accel < MINACCEL ) {
+			qDebug() << "accel: " << accel << " m/(s*s) not in" 
+				 << "[" << MINACCEL << "..." << MAXACCEL
+				 << "] --> dropping trackpoint";
+			setHeading(Heading);
+			setAltitude(Alt);
+			setSpeed(Speed);
+			emit updateStatus();
+			QString errmsg;
+			errmsg=QString("Acceleration (%1m/(s*s)) not in limits [%2m/(s*s)...%3m/(s*s)]")
+				.arg(accel).arg(MINACCEL).arg(MAXACCEL);
+			// trigger opening the trackfilter dialog
+			emit gpsfilter(errmsg, cur_latdelta, cur_londelta, correctFutureTackpoints, filterpos);
+			// flag it as openend, so trackpoint data is buffered
+			filterdialogvisible=1;
+			return;
+		}
+	}
+
+	emit updatePosition(Args[3].toDouble()+cur_latdelta,
+			    Args[4].toDouble()+cur_londelta,
+			    cur_datetime, // by Travers Carter <tcarter@noggin.com.au>
+			    Alt, Speed, Heading, 0);
 	setHeading(Heading);
 	setAltitude(Alt);
 	setSpeed(Speed);
 	emit updateStatus();
-
+	setLatitude(latitude() + latdelta());
+	setLongitude(longitude() + londelta());
+	// write recorded trackpoint to NMEA logfile
+	writeLog();
 }
 
 void QGPSDDevice::onLinkReady()
 {
 	if (!Server) return;
 	Server->write("w+");
-	Server->write("j=1");
+	// clear all fix data at the start of each poll cycle; we don't want
+        // to use the dillution from previous trackpoints for our filter!
+	Server->write("j=0");
 }
+
+void QGPSDDevice::continueFiltering(double londelta, double latdelta, bool record, bool change_lon_lat_deltas, QPoint filterposition)
+{
+	// remember trackfilter dialog window position
+	filterpos.setX(filterposition.x());
+	filterpos.setY(filterposition.y());
+	// no longer use any update deltas for show current trackpoint position
+	update_latdelta = 0;
+	update_londelta = 0;
+	if (change_lon_lat_deltas) {
+	    // save new deltas
+	    cur_latdelta=latdelta;
+	    cur_londelta=londelta;
+	    // remember state for next run
+	    correctFutureTackpoints = 1;
+	} else {
+	    // reset deltas
+	    cur_latdelta = 0;
+	    cur_londelta = 0;
+	    // remember state for next run
+	    correctFutureTackpoints = 0;
+	}
+	if (record) {
+		// show updated position on map
+		emit updatePosition(latitude()+latdelta,
+				    longitude()+londelta,
+				    dateTime(),
+				    altitude(), speed(), heading(), 0);
+		emit updateStatus();
+
+		// update latitude/longitude of trackpoint
+		setLatitude(latitude() + cur_latdelta);
+		setLongitude(longitude() + cur_londelta);
+		// write trackpoint to NMEA logfile
+		writeLog();
+	} else {
+		// restore backup speed since trackpoint has been discarded
+		setSpeed(tmp_speed);
+	}
+	// trackpoint data no longer needs to be buffered
+	filterdialogvisible=0;
+}
+
+void QGPSDDevice::UpdateDelta(double londelta, double latdelta)
+{
+	// new update deltas
+	update_latdelta = latdelta;
+	update_londelta = londelta;
+
+	// only show updated position (adjustposition=true)
+	emit updatePosition(latitude(),
+                            longitude(),
+                            dateTime(),
+                            altitude(), speed(), heading(), 1);
+}
+
+// calculates checksum for NMEA sentence
+int QGPSDDevice::checksum(const char * buf) {
+	int x = 0;
+	const char *p;
+
+	for (p=buf; *p; p++) {
+		x ^= *p;
+	}
+	
+	return x;
+}
+
+// write GPRMC/GPGGA NMEA sentences for each trackpoint data
+void QGPSDDevice::writeLog()
+{
+	char buf[80];
+	char cksum[3];
+	char date[7];
+	char time[11];
+	char *lc_numeric_locale;
+
+	QByteArray line="";
+	if (LogFile) {
+		QString qdate=cur_datetime.toString("ddMMyy");
+		QString qtime=cur_datetime.toString("hhmmss.zzz");
+		strcpy(date,qdate.toUtf8());
+		strcpy(time,qtime.toUtf8());
+		// backup current LC_NUMERIC locale
+		lc_numeric_locale=setlocale(LC_NUMERIC, NULL);
+		// make sure to use "decimal point" as radix character for speed value
+		setlocale(LC_NUMERIC, "C");
+		snprintf(buf, sizeof(buf), "GPRMC,%s,A,%.2i%.2i.%.4i,%s,%.3i%.2i.%.4i,%s,%f,,%s,,",
+			 time,
+			 latDegrees(), 
+			 latMinutes(), 
+			 (int)(latSecondsf()*10000/60),
+			 (latitude() > 0) ? "N" : "S", 
+			 longDegrees(),
+			 longMinutes(),
+			 (int)(longSecondsf()*10000/60),
+			 (longitude() > 0) ? "E" : "W", 
+			 speed()/1.852,
+			 date);
+		// restore previous LC_NUMERIC locale
+		setlocale(LC_NUMERIC, lc_numeric_locale);
+		snprintf(cksum, sizeof(cksum),"%.2X", checksum(buf));
+	        line.append("$");
+		line.append(buf);
+		line.append("*");
+		line.append(cksum);
+		line.append("\n");
+		// finally
+		LogFile->write(line);
+		// backup current LC_NUMERIC locale
+		lc_numeric_locale=setlocale(LC_NUMERIC, NULL);
+		// make sure to use "decimal point" as radix character for speed value
+		setlocale(LC_NUMERIC, "C");
+		snprintf(buf, sizeof(buf), "GPGGA,%s,%.2i%.2i.%.4i,%s,%.3i%.2i.%.4i,%s,1,,,%.2f,M,0.0,M,,",
+			 time,
+			 latDegrees(),
+			 latMinutes(),
+			 (int)(latSecondsf()*10000/60),
+			 (longitude() > 0) ? "N" : "S",
+			 longDegrees(),
+			 longMinutes(),
+			 (int)(longSecondsf()*10000/60),
+			 (latitude() > 0) ? "E" : "W",
+			 altitude());
+		// restore previous LC_NUMERIC locale
+		setlocale(LC_NUMERIC, lc_numeric_locale);
+		snprintf(cksum, sizeof(cksum),"%.2X", checksum(buf));
+		line = "";
+		line.append("$");
+		line.append(buf);
+		line.append("*");
+		line.append(cksum);
+		line.append("\n");
+		// finally
+		LogFile->write(line);
+       }
+}
 #endif
 
 #ifdef Q_OS_SYMBIAN
@@ -1079,9 +1402,10 @@ void QGPSS60Device::onLocationChanged(double latit
 	setLongitude(longitude);
 	setAltitude(altitude);
 	setSpeed(speed);
-	
+
+	// adjustposition=false	
 	emit updatePosition(latitude, longitude, QDateTime::currentDateTime(),
-			altitude, speed, cur_heading);
+			altitude, speed, cur_heading, 0);
 }
 
 void QGPSS60Device::onStatusChanged(XQLocation::DeviceStatus)
Index: src/MapView.cpp
===================================================================
--- src/MapView.cpp	(revision 107)
+++ src/MapView.cpp	(working copy)
@@ -260,7 +260,13 @@ void MapView::drawGPS(QPainter & P)
 {
 	if (Main->gps()->getGpsDevice()) {
 		if (Main->gps()->getGpsDevice()->fixStatus() == QGPSDevice::StatusActive) {
-			Coord vp(angToInt(Main->gps()->getGpsDevice()->latitude()), angToInt(Main->gps()->getGpsDevice()->longitude()));
+			// consider current and updated deltas for latitude/longitude
+			Coord vp(angToInt(Main->gps()->getGpsDevice()->latitude()
+                                         +Main->gps()->getGpsDevice()->latdelta()
+                                         +Main->gps()->getGpsDevice()->updatelatdelta()),
+				 angToInt(Main->gps()->getGpsDevice()->longitude()
+                                         +Main->gps()->getGpsDevice()->londelta()
+                                         +Main->gps()->getGpsDevice()->updatelondelta()));
 			QPointF g = p->theTransform.map(projection().project(vp));
 			QPixmap pm = getPixmapFromFile(":/Gps/Gps_Marker.svg", 32);
 			P.drawPixmap(g - QPoint(16, 16), pm);
Index: src/MainWindow.cpp
===================================================================
--- src/MainWindow.cpp	(revision 107)
+++ src/MainWindow.cpp	(working copy)
@@ -72,6 +72,7 @@
 
 #include "qgps.h"
 #include "qgpsdevice.h"
+#include "trackfilterdialog.h"
 
 #include <QtCore/QDir>
 #include <QtCore/QFileInfo>
@@ -2480,8 +2481,16 @@ void MainWindow::on_gpsConnectAction_triggered()
 	QGPSS60Device* aGps = new QGPSS60Device();
 #endif
 	if (aGps->openDevice()) {
-		connect(aGps, SIGNAL(updatePosition(float, float, QDateTime, float, float, float)), 
-			this, SLOT(updateGpsPosition(float, float, QDateTime, float, float, float)));
+		// new: bool adjustposition
+		connect(aGps, SIGNAL(updatePosition(float, float, QDateTime, float, float, float, bool)), 
+			this, SLOT(updateGpsPosition(float, float, QDateTime, float, float, float, bool)));
+		// run GPSFilter, i.e. open trackfilter dialog when gpsfilter signal received
+		connect(aGps, SIGNAL(gpsfilter(QString, double, double, bool, QPoint)), 
+			this, SLOT(GPSFilter(QString, double, double, bool, QPoint)));
+		// forward continue_filtering signal
+		connect(this, SIGNAL(continue_filtering(double, double, bool, bool, QPoint)), 
+			aGps, SLOT(continueFiltering(double, double, bool, bool, QPoint)));
+		connect(this, SIGNAL(update_delta(double, double)), aGps, SLOT(UpdateDelta(double, double)));
 
 		gpsConnectAction->setEnabled(false);
 		gpsReplayAction->setEnabled(false);
@@ -2510,8 +2519,9 @@ void MainWindow::on_gpsReplayAction_triggered()
 
 	QGPSFileDevice* aGps = new QGPSFileDevice(fileName);
 	if (aGps->openDevice()) {
-		connect(aGps, SIGNAL(updatePosition(float, float, QDateTime, float, float, float)), 
-			this, SLOT(updateGpsPosition(float, float, QDateTime, float, float, float)));
+		// new: bool adjustposition
+		connect(aGps, SIGNAL(updatePosition(float, float, QDateTime, float, float, float, bool)), 
+			this, SLOT(updateGpsPosition(float, float, QDateTime, float, float, float, bool)));
 
 		gpsConnectAction->setEnabled(false);
 		gpsReplayAction->setEnabled(false);
@@ -2535,13 +2545,15 @@ void MainWindow::on_gpsDisconnectAction_triggered(
 	gpsRecordAction->setChecked(false);
 	gpsPauseAction->setChecked(false);
 
-	disconnect(theGPS->getGpsDevice(), SIGNAL(updatePosition(float, float, QDateTime, float, float, float)), 
-		this, SLOT(updateGpsPosition(float, float, QDateTime, float, float, float)));
+	// new: bool adjustposition
+	disconnect(theGPS->getGpsDevice(), SIGNAL(updatePosition(float, float, QDateTime, float, float, float, bool)), 
+		this, SLOT(updateGpsPosition(float, float, QDateTime, float, float, float, bool)));
 	theGPS->stopGps();
 	theGPS->resetGpsStatus();
 }
 
-void MainWindow::updateGpsPosition(float latitude, float longitude, QDateTime time, float altitude, float speed, float heading)
+void MainWindow::updateGpsPosition(float latitude, float longitude, QDateTime time, float altitude, float speed, float heading,
+				   bool adjustposition)
 {
 	Q_UNUSED(heading)
 	if (theGPS->getGpsDevice()) {
@@ -2555,7 +2567,9 @@ void MainWindow::on_gpsDisconnectAction_triggered(
 			}
 		}
 
-		if (gpsRecordAction->isChecked() && !gpsPauseAction->isChecked()) {
+		// do not record trackpoint if adjustposition is set (used by trackfilter dialog)
+		if (gpsRecordAction->isChecked() && !gpsPauseAction->isChecked()
+		    && !adjustposition) {
 			TrackPoint* pt = new TrackPoint(gpsCoord);
 			pt->setTime(time);
 			pt->setElevation(altitude);
@@ -2614,6 +2628,20 @@ void MainWindow::on_gpsPauseAction_triggered()
 	}
 }
 
+void MainWindow::GPSFilter(QString errmsg, double londelta, double latdelta, bool correctFutureTackpoints, QPoint filterposition)
+{
+	// open trackfilter dialog
+	TrackFilterDialog *dialog = new TrackFilterDialog(this, londelta, latdelta, correctFutureTackpoints, &filterposition);
+	// forward signals
+	connect(dialog,SIGNAL(continue_filtering(double, double, bool, bool, QPoint)),
+	        this,SIGNAL(continue_filtering(double, double, bool, bool, QPoint)));
+	connect(dialog, SIGNAL(update_delta(double, double)), this, SIGNAL(update_delta(double, double)));
+	dialog->ErrorMessage->setText(errmsg);
+	dialog->show();
+
+	return;
+}
+
 void MainWindow::on_toolTemplatesSaveAction_triggered()
 {
 	QString f = QFileDialog::getSaveFileName(this, tr("Save Tag Templates"), "", tr("Merkaartor tag templates (*.mat)"));
openSUSE Build Service is sponsored by