/* * * This file is part of QMapControl, * an open-source cross-platform map widget * * Copyright (C) 2007 - 2008 Kai Winter * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with QMapControl. If not, see . * * Contact e-mail: kaiwinter@gmx.de * Program URL : http://qmapcontrol.sourceforge.net/ * */ #include "layermanager.h" namespace qmapcontrol { LayerManager::LayerManager(MapControl* mapcontrol, QSize size) :mapcontrol(mapcontrol), scroll(QPoint(0,0)), size(size), whilenewscroll(QPoint(0,0)) { // genauer berechnen? offSize = size *2; composedOffscreenImage = QPixmap(offSize); composedOffscreenImage2 = QPixmap(offSize); zoomImage = QPixmap(size); zoomImage.fill(Qt::white); screenmiddle = QPoint(size.width()/2, size.height()/2); } LayerManager::~LayerManager() { mylayers.clear(); } QPointF LayerManager::currentCoordinate() const { return mapmiddle; } QPixmap LayerManager::getImage() const { return composedOffscreenImage; } Layer* LayerManager::layer() const { Q_ASSERT_X(mylayers.size()>0, "LayerManager::getLayer()", "No layers were added!"); return mylayers.first(); } Layer* LayerManager::layer(const QString& layername) const { QListIterator layerit(mylayers); while (layerit.hasNext()) { Layer* l = layerit.next(); if (l->layername() == layername) return l; } return 0; } QList LayerManager::layers() const { QList keys; QListIterator layerit(mylayers); while (layerit.hasNext()) { keys.append(layerit.next()->layername()); } return keys; } void LayerManager::scrollView(const QPoint& point) { scroll += point; zoomImageScroll+=point; mapmiddle_px += point; mapmiddle = layer()->mapadapter()->displayToCoordinate(mapmiddle_px); if (!checkOffscreen()) { newOffscreenImage(); } else { moveWidgets(); } } void LayerManager::moveWidgets() { QListIterator it(mylayers); while (it.hasNext()) { it.next()->moveWidgets(mapmiddle_px); } } void LayerManager::setView(const QPointF& coordinate) { mapmiddle_px = layer()->mapadapter()->coordinateToDisplay(coordinate); mapmiddle = coordinate; //TODO: muss wegen moveTo() raus if (!checkOffscreen()) { newOffscreenImage(); } else { //TODO: // verschiebung ausrechnen // oder immer neues offscreenimage newOffscreenImage(); } } void LayerManager::setView(QList coordinates) { setMiddle(coordinates); // mapcontrol->update(); } void LayerManager::setViewAndZoomIn(const QList coordinates) { while (containsAll(coordinates)) { setMiddle(coordinates); zoomIn(); } if (!containsAll(coordinates)) { zoomOut(); } mapcontrol->update(); } void LayerManager::setMiddle(QList coordinates) { int sum_x = 0; int sum_y = 0; for (int i=0; imapadapter()->coordinateToDisplay(coordinates.at(i)); sum_x += p.x(); sum_y += p.y(); } QPointF middle = layer()->mapadapter()->displayToCoordinate(QPoint(sum_x/coordinates.size(), sum_y/coordinates.size())); // middle in px rechnen! setView(middle); } bool LayerManager::containsAll(QList coordinates) const { QRectF bb = getViewport(); bool containsall = true; for (int i=0; imapadapter()->displayToCoordinate(upperLeft); QPointF lrCoord = layer()->mapadapter()->displayToCoordinate(lowerRight); QRectF coordinateBB = QRectF(ulCoord, QSizeF( (lrCoord-ulCoord).x(), (lrCoord-ulCoord).y())); return coordinateBB; } void LayerManager::addLayer(Layer* layer) { mylayers.append(layer); layer->setSize(size); connect(layer, SIGNAL(updateRequest(QRectF)), this, SLOT(updateRequest(QRectF))); connect(layer, SIGNAL(updateRequest()), this, SLOT(updateRequest())); if (mylayers.size()==1) { setView(QPointF(0,0)); } } void LayerManager::newOffscreenImage(bool clearImage, bool showZoomImage) { // qDebug() << "LayerManager::newOffscreenImage()"; whilenewscroll = mapmiddle_px; if (clearImage) { composedOffscreenImage2.fill(Qt::white); } QPainter painter(&composedOffscreenImage2); if (showZoomImage) { painter.drawPixmap(screenmiddle.x()-zoomImageScroll.x(), screenmiddle.y()-zoomImageScroll.y(),zoomImage); } //only draw basemaps for (int i=0; iisVisible()) { if (l->layertype() == Layer::MapLayer) { l->drawYourImage(&painter, whilenewscroll); } } } composedOffscreenImage = composedOffscreenImage2; scroll = mapmiddle_px-whilenewscroll; mapcontrol->update(); } void LayerManager::zoomIn() { QCoreApplication::processEvents(); ImageManager::instance()->abortLoading(); // layer rendern abbrechen? zoomImageScroll = QPoint(0,0); zoomImage.fill(Qt::white); QPixmap tmpImg = composedOffscreenImage.copy(screenmiddle.x()+scroll.x(),screenmiddle.y()+scroll.y(), size.width(), size.height()); QPainter painter(&zoomImage); painter.translate(screenmiddle); painter.scale(2, 2); painter.translate(-screenmiddle); painter.drawPixmap(0,0,tmpImg); QListIterator it(mylayers); //TODO: remove hack, that mapadapters wont get set zoom multiple times QList doneadapters; while (it.hasNext()) { Layer* l = it.next(); if (!doneadapters.contains(l->mapadapter())) { l->zoomIn(); doneadapters.append(l->mapadapter()); } } mapmiddle_px = layer()->mapadapter()->coordinateToDisplay(mapmiddle); whilenewscroll = mapmiddle_px; newOffscreenImage(); } bool LayerManager::checkOffscreen() const { // calculate offscreenImage dimension (px) QPoint upperLeft = mapmiddle_px - screenmiddle; QPoint lowerRight = mapmiddle_px + screenmiddle; QRect viewport = QRect(upperLeft, lowerRight); QRect testRect = layer()->offscreenViewport(); if (!testRect.contains(viewport)) { return false; } return true; } void LayerManager::zoomOut() { QCoreApplication::processEvents(); ImageManager::instance()->abortLoading(); zoomImageScroll = QPoint(0,0); zoomImage.fill(Qt::white); QPixmap tmpImg = composedOffscreenImage.copy(screenmiddle.x()+scroll.x(),screenmiddle.y()+scroll.y(), size.width(), size.height()); QPainter painter(&zoomImage); painter.translate(screenmiddle); painter.scale(0.500001,0.500001); painter.translate(-screenmiddle); painter.drawPixmap(0,0,tmpImg); painter.translate(screenmiddle); painter.scale(2,2); painter.translate(-screenmiddle); QListIterator it(mylayers); //TODO: remove hack, that mapadapters wont get set zoom multiple times QList doneadapters; while (it.hasNext()) { Layer* l = it.next(); if (!doneadapters.contains(l->mapadapter())) { l->zoomOut(); doneadapters.append(l->mapadapter()); } } mapmiddle_px = layer()->mapadapter()->coordinateToDisplay(mapmiddle); whilenewscroll = mapmiddle_px; newOffscreenImage(); } void LayerManager::setZoom(int zoomlevel) { int current_zoom; if (layer()->mapadapter()->minZoom() < layer()->mapadapter()->maxZoom()) { current_zoom = layer()->mapadapter()->currentZoom(); } else { current_zoom = layer()->mapadapter()->minZoom() - layer()->mapadapter()->currentZoom(); } if (zoomlevel < current_zoom) { for (int i=current_zoom; i>zoomlevel; i--) { zoomOut(); } } else { for (int i=current_zoom; iisVisible()) { l->mouseEvent(evnt, mapmiddle_px); } } // QListIterator it(mylayers); // while (it.hasNext()) // { // qDebug() << it.next(); // Layer* l = it.next(); // if (l->isVisible()) // { // l->mouseEvent(evnt, mapmiddle_px); // } // } } void LayerManager::updateRequest(QRectF rect) { const QPoint topleft = mapmiddle_px - screenmiddle; QPointF c = rect.topLeft(); if (getViewport().contains(c) || getViewport().contains(rect.bottomRight())) { // QPoint point = getLayer()->getMapAdapter()->coordinateToDisplay(c); // QPoint finalpoint = point-topleft; // QRect rect_px = QRect(int(finalpoint.x()-(rect.width()-1)/2), int(finalpoint.y()-(rect.height()-1)/2), // int(rect.width()+1), int(rect.height()+1)); // // mapcontrol->updateRequest(rect_px); mapcontrol->update(); // newOffscreenImage(); } } void LayerManager::updateRequest() { newOffscreenImage(); } void LayerManager::forceRedraw() { newOffscreenImage(); } void LayerManager::removeZoomImage() { zoomImage.fill(Qt::white); forceRedraw(); } void LayerManager::drawGeoms(QPainter* painter) { QListIterator it(mylayers); while (it.hasNext()) { Layer* l = it.next(); if (l->layertype() == Layer::GeometryLayer && l->isVisible()) { l->drawYourGeometries(painter, mapmiddle_px, layer()->offscreenViewport()); } } } void LayerManager::drawImage(QPainter* painter) { painter->drawPixmap(-scroll.x()-screenmiddle.x(), -scroll.y()-screenmiddle.y(), composedOffscreenImage); } int LayerManager::currentZoom() const { return layer()->mapadapter()->currentZoom(); } void LayerManager::resize(QSize newSize) { size = newSize; offSize = newSize *2; composedOffscreenImage = QPixmap(offSize); composedOffscreenImage2 = QPixmap(offSize); zoomImage = QPixmap(newSize); zoomImage.fill(Qt::white); screenmiddle = QPoint(newSize.width()/2, newSize.height()/2); QListIterator it(mylayers); while (it.hasNext()) { Layer* l = it.next(); l->setSize(newSize); } newOffscreenImage(); } }