Skip to content
Permalink
Browse files

Add html annotations

  • Loading branch information
NathanW2 committed Sep 2, 2012
1 parent cbdafbc commit 7298e739082a14a0953df438c0f2bf51218317f4
@@ -30,6 +30,7 @@ SET(QGIS_APP_SRCS
qgsdecorationgriddialog.cpp
qgsembedlayerdialog.cpp
qgsformannotationdialog.cpp
qgshtmlannotationdialog.cpp
qgsdelattrdialog.cpp
qgsdisplayangle.cpp
qgsfieldcalculator.cpp
@@ -55,6 +56,7 @@ SET(QGIS_APP_SRCS
qgsmaptooledit.cpp
qgsmaptoolfeatureaction.cpp
qgsmaptoolformannotation.cpp
qgsmaptoolhtmlannotation.cpp
qgsmaptoolpinlabels.cpp
qgsmaptoolshowhidelabels.cpp
qgsmaptoolidentify.cpp
@@ -188,6 +190,7 @@ SET (QGIS_APP_MOC_HDRS
qgsfeatureaction.h
qgsfieldcalculator.h
qgsformannotationdialog.h
qgshtmlannotationdialog.h
qgsgraduatedsymboldialog.h
qgsidentifyresults.h
qgslabeldialog.h
@@ -124,6 +124,7 @@
#include "qgsexception.h"
#include "qgsfeature.h"
#include "qgsformannotationitem.h"
#include "qgshtmlannotationitem.h"
#include "qgsgenericprojectionselector.h"
#include "qgsgpsinformationwidget.h"
#include "qgslabelinggui.h"
@@ -217,6 +218,7 @@
#include "qgsmaptooldeletevertex.h"
#include "qgsmaptoolfeatureaction.h"
#include "qgsmaptoolformannotation.h"
#include "qgsmaptoolhtmlannotation.h"
#include "qgsmaptoolidentify.h"
#include "qgsmaptoolmeasureangle.h"
#include "qgsmaptoolmovefeature.h"
@@ -728,6 +730,7 @@ QgisApp::~QgisApp()
delete mMapTools.mMeasureAngle;
delete mMapTools.mTextAnnotation;
delete mMapTools.mFormAnnotation;
delete mMapTools.mHtmlAnnotation;
delete mMapTools.mAnnotation;
delete mMapTools.mAddFeature;
delete mMapTools.mMoveFeature;
@@ -931,6 +934,7 @@ void QgisApp::createActions()
connect( mActionDraw, SIGNAL( triggered() ), this, SLOT( refreshMapCanvas() ) );
connect( mActionTextAnnotation, SIGNAL( triggered() ), this, SLOT( addTextAnnotation() ) );
connect( mActionFormAnnotation, SIGNAL( triggered() ), this, SLOT( addFormAnnotation() ) );
connect( mActionHtmlAnnotation, SIGNAL( triggered() ), this, SLOT( addHtmlAnnotation() ) );
connect( mActionAnnotation, SIGNAL( triggered() ), this, SLOT( modifyAnnotation() ) );
connect( mActionLabeling, SIGNAL( triggered() ), this, SLOT( labeling() ) );

@@ -1354,6 +1358,7 @@ void QgisApp::createToolBars()
bt->setPopupMode( QToolButton::MenuButtonPopup );
bt->addAction( mActionTextAnnotation );
bt->addAction( mActionFormAnnotation );
bt->addAction( mActionHtmlAnnotation );
bt->addAction( mActionAnnotation );

QAction* defAnnotationAction = mActionTextAnnotation;
@@ -1362,6 +1367,7 @@ void QgisApp::createToolBars()
case 0: defAnnotationAction = mActionTextAnnotation; break;
case 1: defAnnotationAction = mActionFormAnnotation; break;
case 2: defAnnotationAction = mActionAnnotation; break;
case 3: defAnnotationAction = mActionHtmlAnnotation; break;
}
bt->setDefaultAction( defAnnotationAction );
QAction* annotationAction = mAttributesToolBar->addWidget( bt );
@@ -1665,6 +1671,7 @@ void QgisApp::setTheme( QString theThemeName )
mActionAddToOverview->setIcon( QgsApplication::getThemeIcon( "/mActionInOverview.png" ) );
mActionAnnotation->setIcon( QgsApplication::getThemeIcon( "/mActionAnnotation.png" ) );
mActionFormAnnotation->setIcon( QgsApplication::getThemeIcon( "/mActionFormAnnotation.png" ) );
mActionHtmlAnnotation->setIcon( QgsApplication::getThemeIcon( "/mActionFormAnnotation.png" ) );
mActionTextAnnotation->setIcon( QgsApplication::getThemeIcon( "/mActionTextAnnotation.png" ) );
mActionLabeling->setIcon( QgsApplication::getThemeIcon( "/mActionLabeling.png" ) );
mActionShowPinnedLabels->setIcon( QgsApplication::getThemeIcon( "/mActionShowPinnedLabels.svg" ) );
@@ -1793,6 +1800,8 @@ void QgisApp::createCanvasTools()
mMapTools.mTextAnnotation->setAction( mActionTextAnnotation );
mMapTools.mFormAnnotation = new QgsMapToolFormAnnotation( mMapCanvas );
mMapTools.mFormAnnotation->setAction( mActionFormAnnotation );
mMapTools.mHtmlAnnotation = new QgsMapToolHtmlAnnotation( mMapCanvas );
mMapTools.mHtmlAnnotation->setAction( mActionHtmlAnnotation );
mMapTools.mAnnotation = new QgsMapToolAnnotation( mMapCanvas );
mMapTools.mAnnotation->setAction( mActionAnnotation );
mMapTools.mAddFeature = new QgsMapToolAddFeature( mMapCanvas );
@@ -3904,6 +3913,11 @@ void QgisApp::addFormAnnotation()
mMapCanvas->setMapTool( mMapTools.mFormAnnotation );
}

void QgisApp::addHtmlAnnotation()
{
mMapCanvas->setMapTool( mMapTools.mHtmlAnnotation );
}

void QgisApp::addTextAnnotation()
{
mMapCanvas->setMapTool( mMapTools.mTextAnnotation );
@@ -4431,6 +4445,13 @@ bool QgisApp::loadAnnotationItemsFromProject( const QDomDocument& doc )
QgsFormAnnotationItem* newFormItem = new QgsFormAnnotationItem( mMapCanvas );
newFormItem->readXML( doc, formItemList.at( i ).toElement() );
}

QDomNodeList htmlItemList = doc.elementsByTagName( "HtmlAnnotationItem" );
for ( int i = 0; i < htmlItemList.size(); ++i )
{
QgsHtmlAnnotationItem* newHtmlItem = new QgsHtmlAnnotationItem( mMapCanvas );
newHtmlItem->readXML( doc, htmlItemList.at( i ).toElement() );
}
return true;
}

@@ -7945,6 +7966,8 @@ void QgisApp::toolButtonActionTriggered( QAction *action )
settings.setValue( "/UI/annotationTool", 1 );
else if ( action == mActionAnnotation )
settings.setValue( "/UI/annotationTool", 2 );
else if ( action == mActionHtmlAnnotation )
settings.setValue( "/UI/annotationTool", 3 );

bt->setDefaultAction( action );
}
@@ -816,6 +816,7 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
//annotations
void addFormAnnotation();
void addTextAnnotation();
void addHtmlAnnotation();
void modifyAnnotation();

//! shows label settings dialog (for labeling-ng)
@@ -1084,6 +1085,7 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
QgsMapTool* mRotatePointSymbolsTool;
QgsMapTool* mAnnotation;
QgsMapTool* mFormAnnotation;
QgsMapTool* mHtmlAnnotation;
QgsMapTool* mTextAnnotation;
QgsMapTool* mPinLabels;
QgsMapTool* mShowHideLabels;
@@ -0,0 +1,90 @@
/***************************************************************************
QgsHTMLAnnotationDialog.cpp
---------------------
begin : March 2010
copyright : (C) 2010 by Marco Hugentobler
email : marco dot hugentobler at sourcepole dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgshtmlannotationdialog.h"
#include "qgsannotationwidget.h"
#include "qgsvectorlayer.h"
#include <QFileDialog>
#include <QFileInfo>
#include <QGraphicsScene>

QgsHtmlAnnotationDialog::QgsHtmlAnnotationDialog( QgsHtmlAnnotationItem* item, QWidget * parent, Qt::WindowFlags f )
: QDialog( parent, f ), mItem( item ), mEmbeddedWidget( 0 )
{
setupUi( this );
mEmbeddedWidget = new QgsAnnotationWidget( mItem );
mEmbeddedWidget->show();
mStackedWidget->addWidget( mEmbeddedWidget );
mStackedWidget->setCurrentWidget( mEmbeddedWidget );

if ( item )
{
mFileLineEdit->setText( item->htmlPage() );
}

QObject::connect( mButtonBox, SIGNAL( accepted() ), this, SLOT( applySettingsToItem() ) );
QPushButton* deleteButton = new QPushButton( tr( "Delete" ) );
QObject::connect( deleteButton, SIGNAL( clicked() ), this, SLOT( deleteItem() ) );
mButtonBox->addButton( deleteButton, QDialogButtonBox::RejectRole );
}

QgsHtmlAnnotationDialog::~QgsHtmlAnnotationDialog()
{

}

void QgsHtmlAnnotationDialog::applySettingsToItem()
{
//apply settings from embedded item widget
if ( mEmbeddedWidget )
{
mEmbeddedWidget->apply();
}

if ( mItem )
{
mItem->setHTMLPage( mFileLineEdit->text() );
QgsVectorLayer* layer = mItem->vectorLayer();
if ( layer )
{
//set last used annotation form as default for the layer
//layer->setAnnotationForm( mFileLineEdit->text() );
}
mItem->update();
}
}

void QgsHtmlAnnotationDialog::on_mBrowseToolButton_clicked()
{
QString directory;
QFileInfo fi( mFileLineEdit->text() );
if ( fi.exists() )
{
directory = fi.absolutePath();
}
QString filename = QFileDialog::getOpenFileName( 0, tr( "html" ), directory, "*.html" );
mFileLineEdit->setText( filename );
}

void QgsHtmlAnnotationDialog::deleteItem()
{
QGraphicsScene* scene = mItem->scene();
if ( scene )
{
scene->removeItem( mItem );
}
delete mItem;
mItem = 0;
}

@@ -0,0 +1,40 @@
/***************************************************************************
qgsformannotationdialog.h
---------------------
begin : March 2010
copyright : (C) 2010 by Marco Hugentobler
email : marco dot hugentobler at sourcepole dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QgsHTMLAnnotationDialog_H
#define QgsHTMLAnnotationDialog_H

#include "ui_qgsformannotationdialogbase.h"
#include "qgshtmlannotationitem.h"

class QgsAnnotationWidget;

class QgsHtmlAnnotationDialog: public QDialog, private Ui::QgsFormAnnotationDialogBase
{
Q_OBJECT
public:
QgsHtmlAnnotationDialog( QgsHtmlAnnotationItem* item, QWidget * parent = 0, Qt::WindowFlags f = 0 );
~QgsHtmlAnnotationDialog();

private:
QgsHtmlAnnotationItem* mItem;
QgsAnnotationWidget* mEmbeddedWidget;

private slots:
void applySettingsToItem();
void on_mBrowseToolButton_clicked();
void deleteItem();
};

#endif // QgsHTMLAnnotationDialog_H
@@ -18,6 +18,8 @@
#include "qgsmaptoolannotation.h"
#include "qgsformannotationdialog.h"
#include "qgsformannotationitem.h"
#include "qgshtmlannotationitem.h"
#include "qgshtmlannotationdialog.h"
#include "qgslogger.h"
#include "qgsmapcanvas.h"
#include "qgstextannotationdialog.h"
@@ -60,6 +62,12 @@ QDialog* QgsMapToolAnnotation::createItemEditor( QgsAnnotationItem *item )
return new QgsFormAnnotationDialog( fItem );
}

QgsHtmlAnnotationItem* hItem = dynamic_cast<QgsHtmlAnnotationItem*>( item );
if ( hItem )
{
return new QgsHtmlAnnotationDialog( hItem );
}

return 0;
}

@@ -0,0 +1,53 @@
/***************************************************************************
qgsmaptoolformannotation.cpp
-------------------------------
begin : February 9, 2010
copyright : (C) 2010 by Marco Hugentobler
email : marco dot hugentobler at hugis dot net
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsmaptoolhtmlannotation.h"
#include "qgshtmlannotationitem.h"
#include "qgsmapcanvas.h"
#include "qgsvectorlayer.h"
#include <QMouseEvent>

QgsMapToolHtmlAnnotation::QgsMapToolHtmlAnnotation( QgsMapCanvas* canvas ): QgsMapToolAnnotation( canvas )
{

}

QgsMapToolHtmlAnnotation::~QgsMapToolHtmlAnnotation()
{

}

QgsAnnotationItem* QgsMapToolHtmlAnnotation::createItem( QMouseEvent* e )
{
//try to associate the current vector layer and a feature to the form item
QgsVectorLayer* currentVectorLayer = 0;
if ( mCanvas )
{
QgsMapLayer* mLayer = mCanvas->currentLayer();
if ( mLayer )
{
currentVectorLayer = dynamic_cast<QgsVectorLayer*>( mLayer );
}
}

QgsHtmlAnnotationItem* formItem = new QgsHtmlAnnotationItem( mCanvas, currentVectorLayer );
formItem->setMapPosition( toMapCoordinates( e->pos() ) );
formItem->setSelected( true );
formItem->setFrameSize( QSizeF( 200, 100 ) );
return formItem;
}

@@ -0,0 +1,33 @@
/***************************************************************************
QgsMapToolHtmlAnnotation.h
-----------------------------
begin : February 9, 2010
copyright : (C) 2010 by Marco Hugentobler
email : marco dot hugentobler at hugis dot net
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSMAPTOOLHTMLANNOTATION_H
#define QGSMAPTOOLHTMLANNOTATION_H

#include "qgsmaptoolannotation.h"

class QgsMapToolHtmlAnnotation: public QgsMapToolAnnotation
{
public:
QgsMapToolHtmlAnnotation( QgsMapCanvas* canvas );
~QgsMapToolHtmlAnnotation();

protected:
QgsAnnotationItem* createItem( QMouseEvent* e );
};

#endif // QgsMapToolHtmlAnnotation_H
@@ -59,6 +59,7 @@ qgsencodingfiledialog.cpp
qgsfiledropedit.cpp
qgsfieldvalidator.cpp
qgsformannotationitem.cpp
qgshtmlannotationitem.cpp
qgsgenericprojectionselector.cpp
qgsmanageconnectionsdialog.cpp
qgsmapcanvas.cpp
@@ -156,6 +157,7 @@ qgisinterface.h
qgsencodingfiledialog.h
qgsfieldvalidator.h
qgsformannotationitem.h
qgshtmlannotationitem.h
qgsgenericprojectionselector.h
qgsmanageconnectionsdialog.h
qgsmapcanvas.h

5 comments on commit 7298e73

@AndrewM-

This comment has been minimized.

Copy link

@AndrewM- AndrewM- replied Jul 25, 2013

As of the master 26 July 2013, I found the html annotation worked but did not update the field data used in expressions so show the data for the current feature record. Data for the first record in the table was being shown no matter which feature was clicked. The same html code works correctly for html tips. The test code was:

<b>[% "PhotoName" %]</b>
<img src='[% "URL" %]' height='200' width='300'/>

where URL is the file address for an image such as "c:\photos\img1.jpg". I have tried the using double quotes and single quotes to ensure that it is not just an issue with how quotes are used.

I am applying the html by double clicking an existing blank annotation and importing a html file each time I add an annotation. Is this how the tools is meant to be used, or is there some place that I should be putting the html before starting to use the tool?

@AndrewM-

This comment has been minimized.

Copy link

@AndrewM- AndrewM- replied Jul 25, 2013

I have read the source code and can't quite figure it out but it appears that a single feature ID is used to look up the DOM and get attributes. In my photographic data, which is geotagged using a time-based track log from a Garmin GPS, is it common for photos to be stacked on top of each other. Even if this was not the case, I often stand in one spot and take photos upstream, downstream and across the stream. Handling of multiple features at the same point is likely to be an issue. The only solution I can think of would be to have a preview in the dialog that has forwards and backwards butttons to allow the user to choose which of the coincident records to display.

@NathanW2

This comment has been minimized.

Copy link
Member Author

@NathanW2 NathanW2 replied Jul 26, 2013

Yes currently it's a limitation of the tool. I doesn't support stacked features well or at all.

This should be opened as a bug on hub.qgis.org

@AndrewM-

This comment has been minimized.

Copy link

@AndrewM- AndrewM- replied Jul 28, 2013

@timlinux

This comment has been minimized.

Copy link
Member

@timlinux timlinux replied Jul 28, 2013

Hi

@AndrewM- QtCreator is the defacto IDE for Qt related development and works great for QGIS. You can debug etc nicely with it (in partiular under linux).

Tim

Please sign in to comment.
You can’t perform that action at this time.