mapcontrol.h 12.3 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
/*
*
* 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 <http://www.gnu.org/licenses/>.
*
* Contact e-mail: kaiwinter@gmx.de
* Program URL   : http://qmapcontrol.sourceforge.net/
*
*/

#ifndef MAPCONTROL_H
#define MAPCONTROL_H

#include <QtGui>

#include "layermanager.h"
#include "layer.h"
#include "mapadapter.h"
#include "geometry.h"
#include "imagemanager.h"

//! QMapControl namespace
namespace qmapcontrol
{
    class LayerManager;
    class MapAdapter;
    class Layer;

    //! The control element of the widget and also the widget itself
    /*!
     * This is the main widget.
     * To this control layers can be added.
     * A MapControl have to be instantiated with a QSize which sets the size the widget takes in a layout.
     * The given size is also the size, which is asured to be filled with map images.
     *
     * @author Kai Winter <kaiwinter@gmx.de>
     */
    class MapControl : public QWidget
    {
        Q_OBJECT

    public:
        //! Declares what actions the mouse move has on the map
        enum MouseMode
        {
            Panning, /*!< The map is moved */
            Dragging, /*!< A rectangular can be drawn */
            None, /*!< Mouse move events have no efect to the map */
        };

        //! The constructor of MapControl
        /*!
         * The MapControl is the widget which displays the maps.
         * The size describes the area, which gets filled with map data
         * When you give no MouseMode, the mouse is moving the map.
         * You can change the MouseMode on runtime, to e.g. Dragging, which lets the user drag a rectangular box.
         * After the dragging a signal with the size of the box is emitted.
         * The mousemode ´None´ can be used, to completely define the control of the map yourself.
         * @param size the size which the widget should fill with map data
         * @param mousemode the way mouseevents are handled
         */
        MapControl ( QSize size, MouseMode mousemode = Panning );

        ~MapControl();

        //! adds a layer
        /*!
         * If multiple layers are added, they are painted in the added order.
         * @param layer the layer which should be added
         */
        void addLayer ( Layer* layer );

        //! returns the layer with the given name
        /*!
         * @param  layername name of the wanted layer
         * @return the layer with the given name
         */
        Layer* layer ( const QString& layername ) const;

95 96 97
        //! The factor the offscreen image is larger than the current viewport
        float offscreenImageFactor();

pixhawk's avatar
pixhawk committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
        //! returns the names of all layers
        /*!
         * @return returns a QList with the names of all layers
         */
        QList<QString> layers() const;

        //! returns the number of existing layers
        /*!
         * @return returns the number of existing layers
         */
        int numberOfLayers() const;

        //! returns the coordinate of the center of the map
        /*!
         * @return returns the coordinate of the middle of the screen
         */
        QPointF	currentCoordinate() const;

        //! returns the current zoom level
        /*!
         * @return returns the current zoom level
         */
        int currentZoom() const;

        //! sets the middle of the map to the given coordinate
        /*!
         * @param  coordinate the coordinate which the view´s middle should be set to
         */
        void setView ( const QPointF& coordinate ) const;

        //! sets the view, so all coordinates are visible
        /*!
         * @param  coordinates the Coorinates which should be visible
         */
        void setView ( const QList<QPointF> coordinates ) const;

        //! sets the view and zooms in, so all coordinates are visible
        /*!
         * The code of setting the view to multiple coordinates is "brute force" and pretty slow.
         * Have to be reworked.
         * @param  coordinates the Coorinates which should be visible
         */
        void setViewAndZoomIn ( const QList<QPointF> coordinates ) const;

        //! sets the view to the given Point
        /*!
         *
         * @param point the geometric point the view should be set to
         */
        void setView ( const Point* point ) const;

        //! Keeps the center of the map on the Geometry, even when it moves
        /*!
         * To stop the following the method stopFollowing() have to be called
         * @param  geometry the Geometry which should stay centered.
         */
        void followGeometry ( const Geometry* geometry ) const;

        //TODO:
        // void followGeometry(const QList<Geometry*>) const;

        //! Stops the following of a Geometry
        /*!
         * if the view is set to follow a Geometry this method stops the trace.
         * See followGeometry().
         * @param geometry the Geometry which should not followed anymore
         */
        void stopFollowing ( Geometry* geometry );

        //! Smoothly moves the center of the view to the given Coordinate
        /*!
         * @param  coordinate the Coordinate which the center of the view should moved to
         */
        void moveTo	( QPointF coordinate );

        //! sets the Mouse Mode of the MapControl
        /*!
         * There are three MouseModes declard by an enum.
         * The MouesMode Dragging draws an rectangular in the map while the MouseButton is pressed.
         * When the Button is released a boxDragged() signal is emitted.
         *
         * The second MouseMode (the default) is Panning, which allows to drag the map around.
         * @param mousemode the MouseMode
         */
        void setMouseMode ( MouseMode mousemode );

        //! returns the current MouseMode
        /*!
         * For a explanation for the MouseModes see setMouseMode()
         * @return the current MouseMode
         */
        MapControl::MouseMode mouseMode();

        //int rotation;

        //! Enable persistent caching of map tiles
        /*!
         * Call this method to allow the QMapControl widget to save map tiles
         * persistent (also over application restarts).
         * Tiles are stored in the subdirectory "QMapControl.cache" within the
         * user's home directory. This can be changed by giving a path.
         * @param path the path to the cache directory
         */
        void enablePersistentCache ( const QDir& path=QDir::homePath() + "/QMapControl.cache" );


        //! Sets the proxy for HTTP connections
        /*!
         * This method sets the proxy for HTTP connections.
         * This is not provided by the current Qtopia version!
         * @param host the proxy´s hostname or ip
         * @param port the proxy´s port
         */
        void setProxy ( QString host, int port );

        //! Displays the scale within the widget
        /*!
         *
         * @param show true if the scale should be displayed
         */
        void showScale ( bool show );

220 221 222 223 224 225 226 227

        //! Displays the Lat and Lon within the widget
        /*!
         *
         * @param show true if Lat and Lon should be displayed
         */
        void showCoord ( bool show );

228 229 230 231 232 233 234
        //! Set the pen for overlay text
        /*!
         *
         * @param pen The new QPen
         */
        void setPen(QPen pen);

pixhawk's avatar
pixhawk committed
235 236 237 238 239 240 241 242 243
    private:
        LayerManager* layermanager;
        QPoint screen_middle; // middle of the widget (half size)

        QPoint pre_click_px; // used for scrolling (MouseMode Panning)
        QPoint current_mouse_pos; // used for scrolling and dragging (MouseMode Panning/Dragging)

        QSize size; // size of the widget

244 245 246 247
        QPointF currentWorldCoordinate; // updated by mouseMove

        QList<double> distanceList;

pixhawk's avatar
pixhawk committed
248 249 250
        bool mousepressed;
        MouseMode mymousemode;
        bool scaleVisible;
251
        bool cursorPosVisible;
252
        QPen mapPen;
pixhawk's avatar
pixhawk committed
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270

        bool m_loadingFlag;

        QMutex moveMutex; // used for method moveTo()
        QPointF target; // used for method moveTo()
        int steps; // used for method moveTo()

        QPointF clickToWorldCoordinate ( QPoint click );
        MapControl& operator= ( const MapControl& rhs );
        MapControl ( const MapControl& old );

    protected:
        void paintEvent ( QPaintEvent* evnt );
        void mousePressEvent ( QMouseEvent* evnt );
        void mouseReleaseEvent ( QMouseEvent* evnt );
        void mouseMoveEvent ( QMouseEvent* evnt );

    signals:
271
        void mouseEvent(const QMouseEvent* evnt);
pixhawk's avatar
pixhawk committed
272 273 274 275 276 277 278 279 280 281 282

        //! Emitted AFTER a MouseEvent occured
        /*!
         * This signals allows to receive click events within the MapWidget together with the world coordinate.
         * It is emitted on MousePressEvents and MouseReleaseEvents.
         * The kind of the event can be obtained by checking the events type.
         * @param  evnt the QMouseEvent that occured
         * @param  coordinate the corresponding world coordinate
         */
        void mouseEventCoordinate ( const QMouseEvent* evnt, const QPointF coordinate );

283 284 285 286 287 288 289 290 291
        //! Emitted on mouse move generating
        /*!
         * This signals allows to receive the mouse position in the world coordinate.
         * It is emitted on mouseMoveEvents.
         * setMouseTracking must be set programatically to have this method work.
         * @param  coordinate the corresponding world coordinate
         */
        void mouseMoveCoordinateEvent(const QPointF coordinate);

pixhawk's avatar
pixhawk committed
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
        //! Emitted, after a Rectangular is dragged.
        /*!
         * It is possible to select a rectangular area in the map, if the MouseMode is set to Dragging.
         * The coordinates are in world coordinates
         * @param  QRectF the dragged Rect
         */
        void boxDragged ( const QRectF );

        //! This signal is emitted, when a Geometry is clicked
        /*!
         * @param geometry The clicked Geometry object
         * @param coord_px  The coordinate in pixel coordinates
         */
        void geometryClicked ( Geometry* geometry, QPoint coord_px );

        //! This signal is emitted, after the view have changed
        /*!
         * @param coordinate The current coordinate
         * @param zoom The current zoom
         */
        void viewChanged ( const QPointF &coordinate, int zoom );

    public slots:
        //! zooms in one step
        void zoomIn();

        //! zooms out one step
        void zoomOut();

        //! sets the given zoomlevel
        /*!
         * @param zoomlevel the zoomlevel
         */
        void setZoom ( int zoomlevel );

        //! scrolls the view to the left
        void scrollLeft ( int pixel=10 );

        //! scrolls the view to the right
        void scrollRight ( int pixel=10 );

        //! scrolls the view up
        void scrollUp ( int pixel=10 );

        //! scrolls the view down
        void scrollDown ( int pixel=10 );

        //! scrolls the view by the given point
        void scroll ( const QPoint scroll );

        //! updates the map for the given rect
        /*!
         * @param rect the area which should be repainted
         */
        void updateRequest ( QRect rect );

348 349
        void drawGeometries();

pixhawk's avatar
pixhawk committed
350 351 352 353 354 355 356 357 358 359 360 361
        //! updates the hole map by creating a new offscreen image
        /*!
         *
         */
        void updateRequestNew();

        //! Resizes the map to the given size
        /*!
         * @param newSize The new size
         */
        void resize(const QSize newSize);

362 363 364 365 366 367
        //! Open a popup to save the current offscreen image to disk
        void openImageSaveDialog();

        //! Sets the factor the offscreen image should be larger than the visible area */
        void setOffscreenImageFactor(double factor);

pixhawk's avatar
pixhawk committed
368 369 370 371 372 373 374
    private slots:
        void tick();
        void loadingFinished();
        void positionChanged ( Geometry* geom );
    };
}
#endif