Skip to content

Commit 308b9d9

Browse files

File tree

6 files changed

+321
-0
lines changed

6 files changed

+321
-0
lines changed
 
886 Bytes
Loading

‎src/app/qgisapp.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
#include <QtGlobal>
6666
#include <QRegExp>
6767
#include <QRegExpValidator>
68+
#include <QTimer>
6869
//
6970
// Mac OS X Includes
7071
// Must include before GEOS 3 due to unqualified use of 'Point'
@@ -106,12 +107,14 @@
106107
#include "qgsmaplayerregistry.h"
107108
#include "qgsmapoverviewcanvas.h"
108109
#include "qgsmaprender.h"
110+
#include "qgsmaptip.h"
109111
#include "qgsmessageviewer.h"
110112
#include "qgsoptions.h"
111113
#include "qgspastetransformations.h"
112114
#include "qgspluginitem.h"
113115
#include "qgspluginmanager.h"
114116
#include "qgspluginregistry.h"
117+
#include "qgspoint.h"
115118
#include "qgsproject.h"
116119
#include "qgsprojectproperties.h"
117120
#include "qgsproviderregistry.h"
@@ -324,6 +327,7 @@ static void customSrsValidation_(QgsSpatialRefSys* srs)
324327
createCanvas();
325328
createOverview();
326329
createLegend();
330+
createMapTips();
327331

328332
mComposer = new QgsComposer(this); // Map composer
329333
mInternalClipboard = new QgsClipboard; // create clipboard
@@ -395,6 +399,8 @@ static void customSrsValidation_(QgsSpatialRefSys* srs)
395399
restoreWindowState();
396400

397401
mSplash->showMessage(tr("QGIS Ready!"), Qt::AlignHCenter | Qt::AlignBottom);
402+
403+
mMapTipsVisible = false;
398404
qApp->processEvents();
399405
} // QgisApp ctor
400406

@@ -792,6 +798,12 @@ void QgisApp::createActions()
792798
mActionEditPaste->setStatusTip(tr("Paste selected features"));
793799
connect(mActionEditPaste, SIGNAL(triggered()), this, SLOT(editPaste()));
794800
mActionEditPaste->setEnabled(false);
801+
802+
// maptips
803+
mActionMapTips = new QAction(QIcon(myIconPath+"/mActionMapTips.png"), tr("Map Tips"), this);
804+
mActionMapTips->setStatusTip(tr("Show information about a feature when the mouse is hovered over it"));
805+
connect ( mActionMapTips, SIGNAL ( triggered() ), this, SLOT ( toggleMapTips() ) );
806+
mActionMapTips->setCheckable(true);
795807

796808
#ifdef HAVE_PYTHON
797809
mActionShowPythonDialog = new QAction(tr("Python console"), this);
@@ -1036,6 +1048,7 @@ void QgisApp::createToolBars()
10361048
mAttributesToolBar->addAction(mActionOpenTable);
10371049
mAttributesToolBar->addAction(mActionMeasure);
10381050
mAttributesToolBar->addAction(mActionMeasureArea);
1051+
mAttributesToolBar->addAction(mActionMapTips);
10391052
mAttributesToolBar->addAction(mActionShowBookmarks);
10401053
mAttributesToolBar->addAction(mActionNewBookmark);
10411054
//
@@ -1365,6 +1378,18 @@ bool QgisApp::createDB()
13651378
return TRUE;
13661379
}
13671380

1381+
void QgisApp::createMapTips()
1382+
{
1383+
// Set up the timer for maptips. The timer is reset everytime the mouse is moved
1384+
mpMapTipsTimer = new QTimer ( mMapCanvas );
1385+
// connect the timer to the maptips slot
1386+
connect ( mpMapTipsTimer, SIGNAL ( timeout() ), this, SLOT ( showMapTip() ) );
1387+
// set the interval to 0.850 seconds - timer will be started next time the mouse moves
1388+
mpMapTipsTimer->setInterval ( 850 );
1389+
// Create the maptips object
1390+
mpMaptip = new QgsMapTip ();
1391+
}
1392+
13681393
// Update file menu with the current list of recently accessed projects
13691394
void QgisApp::updateRecentProjectPaths()
13701395
{
@@ -3402,6 +3427,7 @@ void QgisApp::attributeTable()
34023427
mMapLegend->legendLayerAttributeTable();
34033428
}
34043429

3430+
34053431
void QgisApp::deleteSelected()
34063432
{
34073433
QgsMapLayer *layer = mMapLegend->currentLayer();
@@ -3635,6 +3661,16 @@ void QgisApp::refreshMapCanvas()
36353661
mMapCanvas->refresh();
36363662
}
36373663

3664+
void QgisApp::toggleMapTips()
3665+
{
3666+
mMapTipsVisible = !mMapTipsVisible;
3667+
// if off, stop the timer
3668+
if ( !mMapTipsVisible )
3669+
{
3670+
mpMapTipsTimer->stop();
3671+
}
3672+
}
3673+
36383674
void QgisApp::toggleEditing()
36393675
{
36403676
if(mMapCanvas && mMapCanvas->isDrawing())
@@ -3663,8 +3699,26 @@ void QgisApp::showMouseCoordinate(QgsPoint & p)
36633699
{
36643700
mCoordsLabel->setMinimumWidth(mCoordsLabel->width());
36653701
}
3702+
3703+
if ( mMapTipsVisible )
3704+
{
3705+
// store the point, we need it for when the maptips timer fires
3706+
mLastMapPosition = p;
3707+
3708+
// we use this slot to control the timer for maptips since it is fired each time
3709+
// the mouse moves.
3710+
if ( mMapCanvas->underMouse() )
3711+
{
3712+
// Clear the maptip (this is done conditionally)
3713+
mpMaptip->clear ( mMapCanvas );
3714+
// don't start the timer if the mouse is not over the map canvas
3715+
mpMapTipsTimer->start();
3716+
QgsDebugMsg("Started maptips timer");
3717+
}
3718+
}
36663719
}
36673720

3721+
36683722
void QgisApp::showScale(double theScale)
36693723
{
36703724
if (theScale >= 1.0)
@@ -4685,6 +4739,50 @@ void QgisApp::showStatusMessage(QString theMessage)
46854739
statusBar()->message(theMessage);
46864740
}
46874741

4742+
void QgisApp::showMapTip()
4743+
4744+
{
4745+
/* Show the maptip using tooltip */
4746+
// Stop the timer while we look for a maptip
4747+
mpMapTipsTimer->stop();
4748+
4749+
// Only show tooltip if the mouse is over the canvas
4750+
if ( mMapCanvas->underMouse() )
4751+
{
4752+
QPoint myPointerPos = mMapCanvas->mouseLastXY();
4753+
4754+
// Following is debug stuff
4755+
QgsDebugMsg ( "Mouse IS over canvas" );
4756+
QgsDebugMsg ( "Maptips timer fired:" );
4757+
QgsDebugMsg ( mLastMapPosition.stringRep() );
4758+
QgsDebugMsg ( "Pixel coordinates of mouse position:" );
4759+
QgsDebugMsg ( QString::number ( myPointerPos.x() ) + "," + QString::number ( myPointerPos.y() ) );
4760+
// end debug stuff
4761+
4762+
// Make sure there is an active layer before proceeding
4763+
4764+
QgsMapLayer* mypLayer = mMapCanvas->currentLayer();
4765+
if ( mypLayer )
4766+
{
4767+
QgsDebugMsg("Current layer for maptip display is: " + mypLayer->source());
4768+
// only process vector layers
4769+
if ( mypLayer->type() == QgsMapLayer::VECTOR )
4770+
{
4771+
4772+
4773+
// Show the maptip if the maptips button is depressed
4774+
if(mMapTipsVisible)
4775+
{
4776+
mpMaptip->showMapTip ( mypLayer, mLastMapPosition, myPointerPos, mMapCanvas );
4777+
}
4778+
}
4779+
}
4780+
else
4781+
{
4782+
QgsDebugMsg ( "Maptips require an active layer" );
4783+
}
4784+
}
4785+
}
46884786
void QgisApp::projectPropertiesProjections()
46894787
{
46904788
// Driver to display the project props dialog and switch to the

‎src/app/qgisapp.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class QgsHelpViewer;
4343
class QgsLegend;
4444
class QgsMapCanvas;
4545
class QgsMapLayer;
46+
class QgsMapTip;
4647
class QgsMapTool;
4748
class QgsPoint;
4849
class QgsProviderRegistry;
@@ -57,6 +58,7 @@ class QgsRect;
5758
#include <QAbstractSocket>
5859

5960
#include "qgsconfig.h"
61+
#include <qgspoint.h>
6062

6163
/*! \class QgisApp
6264
* \brief Main window for the Qgis application
@@ -379,6 +381,12 @@ public slots:
379381
//! Shows a warning when an old project file is read.
380382
void warnOlderProjectVersion(QString);
381383

384+
//! Toggle map tips on/off
385+
void toggleMapTips();
386+
387+
//! Show the map tip
388+
void showMapTip();
389+
382390
signals:
383391
/** emitted when a key is pressed and we want non widget sublasses to be able
384392
to pick up on this (e.g. maplayer) */
@@ -450,6 +458,7 @@ public slots:
450458
void createOverview();
451459
void createCanvas();
452460
bool createDB();
461+
void createMapTips();
453462
//toolbars ----------------------------------------
454463
QToolBar *mFileToolBar;
455464
QToolBar *mLayerToolBar;
@@ -509,6 +518,7 @@ public slots:
509518
QAction *mActionZoomLast;
510519
QAction *mActionZoomToLayer;
511520
QAction *mActionIdentify;
521+
QAction *mActionMapTips;
512522
QAction *mActionSelect;
513523
QAction *mActionOpenTable;
514524
QAction *mActionMeasure;
@@ -638,6 +648,21 @@ public slots:
638648
*/
639649
QString mRasterFileFilter;
640650

651+
/** Timer for map tips
652+
*/
653+
QTimer *mpMapTipsTimer;
654+
655+
/** Point of last mouse position in map coordinates (used with MapTips)
656+
*/
657+
QgsPoint mLastMapPosition;
658+
659+
/* Maptip object
660+
*/
661+
QgsMapTip * mpMaptip;
662+
663+
// Flag to indicate if maptips are on or off
664+
bool mMapTipsVisible;
665+
641666
#ifdef HAVE_PYTHON
642667
QgsPythonDialog* mPythonConsole;
643668
#endif

‎src/gui/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ qgsprojectionselector.cpp
2121
qgsquickprint.cpp
2222
qgsrubberband.cpp
2323
qgsvertexmarker.cpp
24+
qgsmaptip.cpp
2425
)
2526

2627
SET(QGIS_GUI_MOC_HDRS

‎src/gui/qgsmaptip.cpp

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/***************************************************************************
2+
qgsmaptips.cpp - Query a layer and show a maptip on the canvas
3+
---------------------
4+
begin : October 2007
5+
copyright : (C) 2007 by Gary Sherman
6+
email : sherman @ mrcc dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
// QGIS includes
16+
#include <qgsmapcanvas.h>
17+
#include <qgsmaplayer.h>
18+
#include <qgsvectordataprovider.h>
19+
#include <qgsfield.h>
20+
21+
// Qt includes
22+
#include <QPoint>
23+
#include <QToolTip>
24+
#include <QSettings>
25+
26+
#include "qgsmaptip.h"
27+
28+
QgsMapTip::QgsMapTip ()
29+
{
30+
// init the visible flag
31+
mMapTipVisible = false;
32+
}
33+
34+
QgsMapTip::~QgsMapTip()
35+
{
36+
37+
}
38+
39+
void QgsMapTip::showMapTip ( QgsMapLayer * thepLayer,
40+
QgsPoint & theMapPosition,
41+
QPoint & thePixelPosition,
42+
QgsMapCanvas *thepMapCanvas )
43+
{
44+
// Do the search using the active layer and the preferred label
45+
// field for the layer. The label field must be defined in the layer configuration
46+
// file/database. The code required to do this is similar to identify, except
47+
// we only want the first qualifying feature and we will only display the
48+
// field defined as the label field in the layer configuration file/database.
49+
//
50+
// TODO: Define the label (display) field for each map layer in the map configuration file/database
51+
52+
// Show the maptip on the canvas
53+
QString myTipText = fetchFeature ( thepLayer, theMapPosition, thepMapCanvas );
54+
if ( myTipText.length() > 0 )
55+
{
56+
mMapTipVisible = true;
57+
QToolTip::showText ( thepMapCanvas->mapToGlobal ( thePixelPosition ), myTipText, thepMapCanvas );
58+
// store the point so we can use it to clear the maptip later
59+
mLastPosition = thePixelPosition;
60+
}
61+
else
62+
{
63+
mMapTipVisible = false;
64+
}
65+
66+
}
67+
68+
void QgsMapTip::clear ( QgsMapCanvas *mpMapCanvas )
69+
{
70+
if ( mMapTipVisible )
71+
{
72+
// set the maptip to blank
73+
QToolTip::showText ( mpMapCanvas->mapToGlobal ( mLastPosition ), "", mpMapCanvas );
74+
// reset the visible flag
75+
mMapTipVisible = false;
76+
}
77+
}
78+
79+
QString QgsMapTip::fetchFeature ( QgsMapLayer *layer, QgsPoint & mapPosition, QgsMapCanvas *mpMapCanvas )
80+
{
81+
// Default return value
82+
QString maptipText = "";
83+
// Protection just in case we get passed a null layer
84+
if(layer)
85+
{
86+
// Get the setting for the search radius from user preferences, if it exists
87+
QSettings settings;
88+
double identifyValue = settings.value ( "/Map/identifyRadius", QGis::DEFAULT_IDENTIFY_RADIUS ).toDouble();
89+
90+
// create the search rectangle
91+
double searchRadius = mpMapCanvas->extent().width() * ( identifyValue / 100.0 );
92+
QgsRect r;
93+
r.setXmin ( mapPosition.x() - searchRadius );
94+
r.setXmax ( mapPosition.x() + searchRadius );
95+
r.setYmin ( mapPosition.y() - searchRadius );
96+
r.setYmax ( mapPosition.y() + searchRadius );
97+
98+
// Get the data provider
99+
QgsVectorDataProvider* dataProvider = dynamic_cast<QgsVectorLayer*> ( layer )->getDataProvider();
100+
// Fetch the attribute list for the layer
101+
QgsAttributeList allAttributes = dataProvider->allAttributesList();
102+
// Select all attributes within the search radius
103+
dataProvider->select ( allAttributes, r, true, true );
104+
// Feature to hold the results of the fetch
105+
QgsFeature feature;
106+
// Get the field list for the layer
107+
const QgsFieldMap& fields = dataProvider->fields();
108+
// Get the label (display) field for the layer
109+
QString fieldIndex = dynamic_cast<QgsVectorLayer*> ( layer )->displayField();
110+
if ( dataProvider->getNextFeature ( feature ) )
111+
{
112+
// if we get a feature, pull out the display field and set the maptip text to its value
113+
QgsAttributeMap attributes = feature.attributeMap();
114+
for ( QgsAttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); ++it )
115+
{
116+
117+
if ( fields[it.key() ].name() == fieldIndex )
118+
{
119+
maptipText = it->toString();
120+
121+
}
122+
123+
}
124+
}
125+
}
126+
// return the map tip
127+
return maptipText;
128+
}
129+

‎src/gui/qgsmaptip.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/***************************************************************************
2+
qgsmaptip.h - Query a layer and show a maptip on the canvas
3+
---------------------
4+
begin : October 2007
5+
copyright : (C) 2007 by Gary Sherman
6+
email : sherman @ mrcc dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
#ifndef _QGSMAPTIP_H_
16+
#define _QGSMAPTIP_H_
17+
18+
class QgsMapLayer;
19+
class QgsMapCanvas;
20+
class QPoint;
21+
class QString;
22+
23+
24+
/** \ingroup gui
25+
* A maptip is a class to display a tip on a map canvas
26+
* when a mouse is hovered over a feature.
27+
*/
28+
class QgsMapTip
29+
{
30+
public:
31+
/** Default constructor
32+
*/
33+
QgsMapTip ();
34+
/** Destructor
35+
*/
36+
virtual ~QgsMapTip ();
37+
/** Show a maptip at a given point on the map canvas
38+
* @param QgsMapLayer thepLayer - a qgis vector map layer pointer that will
39+
* be used to provide the attribute data for the map tip.
40+
* @param QgsPoint theMapPosition - a reference to the position of the cursor
41+
* in map coordinatess.
42+
* @param QgsPoint thePixelPosition - a reference to the position of the cursor
43+
* in pixel coordinates.
44+
* @param QgsMapCanvas thepMapCanvas - a map canvas on which the tip is drawn
45+
*/
46+
void showMapTip ( QgsMapLayer * thepLayer,
47+
QgsPoint & theMapPosition,
48+
QPoint & thePixelPosition,
49+
QgsMapCanvas *mpMapCanvas );
50+
/** Clear the current maptip if it exists
51+
* @param QgsMapCanvas mpMapCanvas - the canvas from which the tip should
52+
* be cleared.
53+
*/
54+
void clear ( QgsMapCanvas *mpMapCanvas );
55+
private:
56+
// Fetch the feature to use for the maptip text. Only the first feature in the
57+
// search radius is used
58+
QString fetchFeature ( QgsMapLayer * thepLayer,
59+
QgsPoint & theMapPosition,
60+
QgsMapCanvas *thepMapCanvas );
61+
// Flag to indicate if a maptip is currently being displayed
62+
bool mMapTipVisible;
63+
// Last point on the map canvas when the maptip timer fired. This point is in widget pixel
64+
// coordinates
65+
QPoint mLastPosition;
66+
67+
};
68+
#endif // _QGSMAPTIP_H_

0 commit comments

Comments
 (0)
Please sign in to comment.