Index: GeoImageDock.cpp
===================================================================
--- GeoImageDock.cpp	(revision 10480)
+++ GeoImageDock.cpp	(working copy)
@@ -6,6 +6,8 @@
 
 #include <QtGui/QInputDialog>
 #include <QtGui/QMessageBox>
+#include <QtGui/QProgressDialog>
+#include <QtGui/QClipboard>
 
 
 GeoImageDock::GeoImageDock(MainWindow *aMain)
@@ -16,6 +18,17 @@
 	Image = new ImageView(this);
 	setWidget(Image);
 	setObjectName("geoImageDock");
+
+	setContextMenuPolicy(Qt::ActionsContextMenu);
+
+	QAction *remImages = new QAction("Remove Images", this);
+	QAction *toClipboard = new QAction("Copy filename to clipboard", this);
+
+	addAction(remImages);
+	addAction(toClipboard);
+
+	connect(remImages, SIGNAL(triggered()), this, SLOT(removeImages()));
+	connect(toClipboard, SIGNAL(triggered()), this, SLOT(toClipboard()));
 }
 
 GeoImageDock::~GeoImageDock(void)
@@ -32,19 +45,56 @@
 		curImage = ImageId;
 	}
 	else {
-		Image->setImage(QPair<QString, QPixmap>("", QPixmap()));
+		Image->setImage("");
 		curImage = -1;
 	}
 }
 
+void GeoImageDock::removeImages(void)
+{
+	MapLayer *theLayer = NULL;
+	MapFeature *feature;
+	TrackPoint *Pt;
+	int i;
+	unsigned int u;
 
+	for (i=0; i<activeLayers.size(); i++) {
+		theLayer = activeLayers.at(i);
+		for (u=0; u < theLayer->size(); u++) {
+			feature = theLayer->get(u);
+			if ((Pt = dynamic_cast<TrackPoint*>(feature))) {
+				Pt->setImageId(-1);
+				if (Pt->tagValue("Picture", "") == "GeoTagged")
+					new RemoveFeatureCommand(theLayer->getDocument(), Pt);
+			}
+		}
+	}
+	activeLayers.clear();
+
+	Images.clear();
+	curImage = -1;
+	Image->setImage("");
+
+	theView->invalidate(true, false);
+}
+	
+void GeoImageDock::toClipboard(void)
+{
+	if (curImage != -1) {
+		QClipboard *clipboard = QApplication::clipboard();
+
+		clipboard->setText(Images.at(curImage));
+	}
+}
+
 void GeoImageDock::loadImages(QStringList fileNames, MapDocument *theDocument, MapView *theView)
 {
 	QString file;
-	QPixmap img;
 	QDateTime time;
 	bool foundTime;
 
+	this->theView = theView;
+
 	Exiv2::Image::AutoPtr image;
 	Exiv2::ExifData *exifData;
 	Exiv2::ExifData::const_iterator i, end;
@@ -77,17 +127,20 @@
 			return;
 	}
 
-	CommandList * theList = new CommandList(tr("Loading Images"));
+	activeLayers.append(theLayer);
 
+	QProgressDialog progress(tr("Loading Images ..."), tr("Abort loading"), 0, fileNames.size());
+	progress.setWindowModality(Qt::WindowModal);
+	progress.show();
+
 	bool ok;
 	int offset = -1;
 
 	foreach(file, fileNames) {
-		if (!img.load(file))
-			WARNING("Image broken", "Cannot open image %1.");
+		progress.setValue(fileNames.indexOf(file));
 
-		if (img.isNull())
-			continue;
+		if (!QFile::exists(file))
+			WARNING("No such file", "Can't find image %1.");
 
     	image = Exiv2::ImageFactory::open(file.toAscii().constData());
 		if (image.get() == 0)
@@ -103,6 +156,7 @@
 		QString latS((*exifData)["Exif.GPSInfo.GPSLatitude"].toString().c_str());
 		QString lonS((*exifData)["Exif.GPSInfo.GPSLongitude"].toString().c_str());
 		QString timeStamp((*exifData)["Exif.Image.DateTime"].toString().c_str());
+		if (timeStamp.isEmpty()) timeStamp = QString((*exifData)["Exif.Photo.DateTimeOriginal"].toString().c_str());
 
 		if (!latS.isEmpty() && !lonS.isEmpty()) {
 			double lat = 0.0, lon = 0.0, *cur;
@@ -129,60 +183,64 @@
 			TrackPoint *Pt = new TrackPoint( Coord( angToInt(lat), angToInt(lon)));
 			Pt->setTag("Picture", "GeoTagged"); // Is this the nicest way to avoid the "?"-Image for this trackpoint?
 			Pt->setImageId(Images.size());
-			Images.append(QPair<QString, QPixmap>(file, img));
-			theList->add(new AddFeatureCommand(theLayer, Pt, false));
+			Images.append(file);
+			new AddFeatureCommand(theLayer, Pt, false);
 		} else if (!timeStamp.isEmpty()) {
 	
 			if (offset == -1) { // ask the user to specify an offset for the images
 				offset = QInputDialog::getInteger( NULL, tr("Set an offset"),
-				 tr("Specify an offset\n(positive values will position the\nimages more to the end of the track):"),
-				 0, 0, (int) ((unsigned int)-1 / 2), 1, &ok);
+				 tr("Specify an offset in seconds.\n(positive values will position the\nimages more to the end of the track):"),
+				 0, -(int) ((unsigned int)-1 /2), (int) ((unsigned int)-1 / 2), 1, &ok);
 				if (!ok) return;
 			}
 
 			time = QDateTime::fromString(timeStamp, "yyyy:MM:dd hh:mm:ss").addSecs(offset);
 
-			MapFeature *feature = NULL, *bestFeature = NULL;
-			TrackPoint *Pt;
-			unsigned int secondsTo = (unsigned int)-1, a;
+			MapFeature *feature = NULL;
+			TrackPoint *Pt, *bestPt = NULL;
+			int secondsTo = (unsigned int)-1 / 2, a;
 			unsigned int u;
 
-			for (u=0; u<theLayer->size(); feature = theLayer->get(u++)) {
-				if (!feature) { qDebug() << "is this a bug???"; continue; } // TODO
+			for (u=0; u<theLayer->size(); u++) {
+				feature = theLayer->get(u);
 				if ((Pt = dynamic_cast<TrackPoint*>(feature))) {
-					a = time.secsTo(Pt->time());
-					if (a < secondsTo) {
+					a = time.secsTo(Pt->time().toLocalTime());
+					if (abs(a) < abs(secondsTo)) {
 						secondsTo = a;
-						bestFeature = feature;
+						bestPt = Pt;
 					}
 				}
 			}
 
-			if (!bestFeature)
+			if (!bestPt)
 				WARNING("No TrackPoints", "No TrackPoints found for image %1");
 
-			if (secondsTo >= 15)
-				if ( QMessageBox::question(NULL, tr("Wrong image?"),
+			if (secondsTo >= 15) {
+				int button = QMessageBox::question(NULL, tr("Wrong image?"),
 				 tr("Image \"%1\" was taken %2 seconds before the next trackpoint was recorded.\n" \
-				 "Do you still want to use it?").arg(file).arg(secondsTo), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes)
+				 "Do you still want to use it?").arg(file).arg(abs(secondsTo)), QMessageBox::Yes | QMessageBox::No | QMessageBox::Abort, QMessageBox::No );
+				if (button == QMessageBox::Abort)
+					return;
+				if (button == QMessageBox::No)
 					continue;
+			}
 
-			if (!(Pt = dynamic_cast<TrackPoint*>(bestFeature)))
-				WARNING("Bug?", "Can't access TrackPoint!\n(%1)");
+			bestPt->setImageId(Images.size());
+			Images.append(file);
 
-			Pt->setImageId(Images.size());
-			Images.append(QPair<QString, QPixmap>(file, img));
-
 		} else
 			WARNING("No geo informations", "Image %1 is not a geotagged image.");
+
+		if (progress.wasCanceled()) {
+			theView->invalidate(true, false);
+			return;
+		}
+		qApp->processEvents();
 	}
 
+	progress.setValue(fileNames.size());
+
 	theView->invalidate(true, false);
-	if (theList->size()) {
-		theDocument->addHistory(theList);
-	}
-	else
-		delete theList;
 
 }
 
@@ -206,10 +264,13 @@
 {
 }
 
-void ImageView::setImage(QPair<QString, QPixmap> img)
+void ImageView::setImage(QString filename)
 {
-	name = img.first;
-	image = img.second;
+	name = filename;
+	if (!name.isEmpty())
+		image.load(name);
+	else
+		image = QPixmap();
 	area = QRect(QPoint(0, 0), image.size());
 	resizeEvent(NULL);
 	update();
@@ -239,14 +300,18 @@
 	else rect.setHeight((int)((double)rect.width() * aspect));
 }
 
-void ImageView::mouseDoubleClickEvent(QMouseEvent * e)
+void ImageView::mouseDoubleClickEvent(QMouseEvent * /* e */)
 {
-	if (e->button() & Qt::LeftButton) zoom((int)(0.0652 * image.width()));
+	if (QApplication::keyboardModifiers() == Qt::ControlModifier)
+		zoom((int)(-0.0625 * image.width())); // zoom in 16 steps
+	else
+		zoom((int)(0.0625 * image.width())); // zoom in 16 steps
 }
 
 void ImageView::mousePressEvent(QMouseEvent * e)
 {
-	if (e->button() & Qt::RightButton) zoom((int)(-0.0652 * image.width()));
+	if (e->button() & Qt::RightButton)
+		QWidget::mousePressEvent(e);
 	else mousePos = e->pos();
 }
 	
@@ -261,13 +326,26 @@
 
 void ImageView::wheelEvent(QWheelEvent *e)
 {
-	zoom((int)((double)e->delta() / 8.0 / 360.0 * (double)image.width()));
+	zoom((int)((double)e->delta() / 8.0 / 360.0 * (double)image.width())); // one wheel rotation are 16 steps
 }
 
 void ImageView::zoom(int level)
 {
+	if (name.isEmpty())
+		return;
+
 	QPoint zoomValue(level, (int)((double)level * aspect));
+
+	// this while loop reduces the zoom level to not get a negative width/height for area
+	// we have to check both width and height because of integer rounding
+	while (area.width() <= zoomValue.x() * 2 || area.height() <= zoomValue.y() * 2 ||
+	 (level < 0 && (area.width() < -2 * zoomValue.x() || area.height() < -2 * zoomValue.y()) )) {
+		if (zoomValue == QPoint(1, 1))
+			return;
+		zoomValue /= 2;
+	}
 	area = QRect(area.topLeft() + zoomValue, area.bottomRight() - zoomValue);
+
 	if (level > 0 ) {
 		QPoint cursor = mapFromGlobal(QCursor::pos());
 		area.translate((int)(((double)cursor.x() - (double)rect.width() / 2.0) / (double)rect.width() * (double)zoomValue.x() * 2),
Index: GeoImageDock.h
===================================================================
--- GeoImageDock.h	(revision 10480)
+++ GeoImageDock.h	(working copy)
@@ -14,14 +14,18 @@
 #define WARNING(title, message) { \
 	if (warning(tr(title), tr(message).arg(file))) \
 		continue; \
-	else \
-		 return; }
+	else { \
+		theView->invalidate(true, false); \
+		return; \
+	} \
+}
 
 class ImageView;
 
 class GeoImageDock : public QDockWidget
 {
 	Q_OBJECT
+
 public:
 	GeoImageDock(MainWindow *aMain);
 	~GeoImageDock(void);
@@ -29,15 +33,19 @@
 	void loadImages(QStringList fileNames, MapDocument *theDocument, MapView *theView);
 	void setImage(int ImageId);
 
-protected:
-	//void resizeEvent(QResizeEvent *e);
+private slots:
+	void removeImages(void);
+	void toClipboard(void);
 
 private:
-	QList<QPair<QString, QPixmap> > Images;
+	QStringList Images;
 	int curImage;
 
 	ImageView *Image;
 
+	QList<MapLayer*> activeLayers;
+	MapView *theView;
+
 	bool warning(QString title, QString message);
 };
 
@@ -47,7 +55,7 @@
 	ImageView(QWidget *parent);
 	~ImageView();
 
-	void setImage(QPair<QString, QPixmap> img);
+	void setImage(QString filename);
 
 protected:
 	void paintEvent(QPaintEvent *e);
Index: Map/ImportGPX.cpp
===================================================================
--- Map/ImportGPX.cpp	(revision 10480)
+++ Map/ImportGPX.cpp	(working copy)
@@ -48,6 +48,7 @@
 			if (!Value.isEmpty())
 			{
 				QDateTime dt(QDateTime::fromString(Value.left(19),"yyyy-MM-ddTHH:mm:ss"));
+				dt.setTimeSpec(Qt::UTC);
 				Pt->setTime(dt);
 			}
 		}


