Skip to content

Commit 68e03cb

Browse files
committed
[FEATURE][composer] Data defined url for composer html items. Sponsored by City of Uster, Switzerland.
1 parent 7e815ca commit 68e03cb

File tree

10 files changed

+132
-6
lines changed

10 files changed

+132
-6
lines changed

python/core/composer/qgscomposerhtml.sip

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,9 @@ class QgsComposerHtml: QgsComposerMultiFrame
152152
* @see url
153153
*/
154154
void loadHtml();
155+
156+
void refreshExpressionContext();
157+
158+
virtual void refreshDataDefinedProperty( QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties );
159+
155160
};

python/core/composer/qgscomposermultiframe.sip

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,9 @@ class QgsComposerMultiFrame: QgsComposerObject
8484

8585
signals:
8686
void changed();
87+
88+
/**Emitted when the contents of the multi frame have changed and the frames
89+
* must be redrawn.
90+
*/
91+
void contentsChanged();
8792
};

src/app/composer/qgscomposerhtmlwidget.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ QgsComposerHtmlWidget::QgsComposerHtmlWidget( QgsComposerHtml* html, QgsComposer
4545
if ( mHtml )
4646
{
4747
QObject::connect( mHtml, SIGNAL( changed() ), this, SLOT( setGuiElementValues() ) );
48+
49+
QgsAtlasComposition* atlas = atlasComposition();
50+
if ( atlas )
51+
{
52+
// repopulate data defined buttons if atlas layer changes
53+
connect( atlas, SIGNAL( coverageLayerChanged( QgsVectorLayer* ) ),
54+
this, SLOT( populateDataDefinedButtons() ) );
55+
connect( atlas, SIGNAL( toggled( bool ) ), this, SLOT( populateDataDefinedButtons() ) );
56+
}
4857
}
4958

5059
//embed widget for general options
@@ -54,6 +63,12 @@ QgsComposerHtmlWidget::QgsComposerHtmlWidget( QgsComposerHtml* html, QgsComposer
5463
QgsComposerItemWidget* itemPropertiesWidget = new QgsComposerItemWidget( this, mFrame );
5564
mainLayout->addWidget( itemPropertiesWidget );
5665
}
66+
67+
//connections for data defined buttons
68+
connect( mUrlDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedProperty( ) ) );
69+
connect( mUrlDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedProperty( ) ) );
70+
connect( mUrlDDBtn, SIGNAL( dataDefinedActivated( bool ) ), mUrlLineEdit, SLOT( setDisabled( bool ) ) );
71+
5772
}
5873

5974
QgsComposerHtmlWidget::QgsComposerHtmlWidget(): QgsComposerItemBaseWidget( 0, 0 )
@@ -358,5 +373,35 @@ void QgsComposerHtmlWidget::setGuiElementValues()
358373
mRadioManualSource->setChecked( mHtml->contentMode() == QgsComposerHtml::ManualHtml );
359374
mHtmlEditor->setEnabled( mHtml->contentMode() == QgsComposerHtml::ManualHtml );
360375
mInsertExpressionButton->setEnabled( mHtml->contentMode() == QgsComposerHtml::ManualHtml );
376+
377+
populateDataDefinedButtons();
378+
361379
blockSignals( false );
362380
}
381+
382+
QgsComposerItem::DataDefinedProperty QgsComposerHtmlWidget::ddPropertyForWidget( QgsDataDefinedButton *widget )
383+
{
384+
if ( widget == mUrlDDBtn )
385+
{
386+
return QgsComposerItem::SourceUrl;
387+
}
388+
return QgsComposerItem::NoProperty;
389+
}
390+
391+
void QgsComposerHtmlWidget::populateDataDefinedButtons()
392+
{
393+
QgsVectorLayer* vl = atlasCoverageLayer();
394+
395+
//block signals from data defined buttons
396+
mUrlDDBtn->blockSignals( true );
397+
398+
//initialise buttons to use atlas coverage layer
399+
mUrlDDBtn->init( vl, mHtml->dataDefinedProperty( QgsComposerItem::SourceUrl ),
400+
QgsDataDefinedButton::AnyType, tr( "url string" ) );
401+
402+
//initial state of controls - disable related controls when dd buttons are active
403+
mUrlLineEdit->setEnabled( !mUrlDDBtn->isActive() );
404+
405+
//unblock signals from data defined buttons
406+
mUrlDDBtn->blockSignals( false );
407+
}

src/app/composer/qgscomposerhtmlwidget.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ class QgsComposerHtmlWidget: public QgsComposerItemBaseWidget, private Ui::QgsCo
4747
/**Sets the GUI elements to the values of mHtmlItem*/
4848
void setGuiElementValues();
4949

50+
protected:
51+
QgsComposerItem::DataDefinedProperty ddPropertyForWidget( QgsDataDefinedButton *widget );
52+
53+
protected slots:
54+
/**Initializes data defined buttons to current atlas coverage layer*/
55+
void populateDataDefinedButtons();
56+
5057
private:
5158
QgsComposerHtmlWidget();
5259
void blockSignals( bool block );

src/core/composer/qgscomposerframe.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ QgsComposerFrame::QgsComposerFrame( QgsComposition* c, QgsComposerMultiFrame* mf
2121
: QgsComposerItem( x, y, width, height, c )
2222
, mMultiFrame( mf )
2323
{
24+
//repaint frame when multiframe content changes
25+
connect( mf, SIGNAL( contentsChanged() ), this, SLOT( repaint() ) );
2426
}
2527

2628
QgsComposerFrame::QgsComposerFrame()
@@ -41,6 +43,7 @@ bool QgsComposerFrame::writeXML( QDomElement& elem, QDomDocument & doc ) const
4143
frameElem.setAttribute( "sectionWidth", QString::number( mSection.width() ) );
4244
frameElem.setAttribute( "sectionHeight", QString::number( mSection.height() ) );
4345
elem.appendChild( frameElem );
46+
4447
return _writeXML( frameElem, doc );
4548
}
4649

src/core/composer/qgscomposerhtml.cpp

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "qgsnetworkaccessmanager.h"
2121
#include "qgsmessagelog.h"
2222
#include "qgsexpression.h"
23+
#include "qgslogger.h"
2324

2425
#include <QCoreApplication>
2526
#include <QPainter>
@@ -47,9 +48,11 @@ QgsComposerHtml::QgsComposerHtml( QgsComposition* c, bool createUndoCommands ):
4748
if ( mComposition )
4849
{
4950
QObject::connect( mComposition, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( handleFrameRemoval( QgsComposerItem* ) ) );
50-
connect( mComposition, SIGNAL( refreshItemsTriggered() ), this, SLOT( loadHtml() ) );
5151
}
5252

53+
// data defined strings
54+
mDataDefinedNames.insert( QgsComposerObject::SourceUrl, QString( "dataDefinedSourceUrl" ) );
55+
5356
if ( mComposition && mComposition->atlasMode() == QgsComposition::PreviewAtlas )
5457
{
5558
//a html item added while atlas preview is enabled needs to have the expression context set,
@@ -152,12 +155,13 @@ QString QgsComposerHtml::fetchHtml( QUrl url )
152155

153156
QByteArray array = reply->readAll();
154157
reply->deleteLater();
155-
return QString( array );
158+
mFetchedHtml = QString( array );
159+
return mFetchedHtml;
156160
}
157161

158162
void QgsComposerHtml::loadHtml()
159163
{
160-
if ( !mWebPage || ( mContentMode == QgsComposerHtml::Url && mUrl.isEmpty() ) )
164+
if ( !mWebPage )
161165
{
162166
return;
163167
}
@@ -167,7 +171,29 @@ void QgsComposerHtml::loadHtml()
167171
{
168172
case QgsComposerHtml::Url:
169173
{
170-
loadedHtml = fetchHtml( mUrl );
174+
175+
QString currentUrl = mUrl.toString();
176+
177+
//data defined url set?
178+
QVariant exprVal;
179+
if ( dataDefinedEvaluate( QgsComposerObject::SourceUrl, exprVal ) )
180+
{
181+
currentUrl = exprVal.toString().trimmed();;
182+
QgsDebugMsg( QString( "exprVal Source Url:%1" ).arg( currentUrl ) );
183+
}
184+
if ( currentUrl.isEmpty() )
185+
{
186+
return;
187+
}
188+
if ( currentUrl != mLastFetchedUrl )
189+
{
190+
loadedHtml = fetchHtml( QUrl( currentUrl ) );
191+
mLastFetchedUrl = currentUrl;
192+
}
193+
else
194+
{
195+
loadedHtml = mFetchedHtml;
196+
}
171197
break;
172198
}
173199
case QgsComposerHtml::ManualHtml:
@@ -183,7 +209,7 @@ void QgsComposerHtml::loadHtml()
183209

184210
mLoaded = false;
185211
//set html, using the specified url as base if in Url mode
186-
mWebPage->mainFrame()->setHtml( loadedHtml, mContentMode == QgsComposerHtml::Url ? QUrl( mUrl ) : QUrl() );
212+
mWebPage->mainFrame()->setHtml( loadedHtml, mContentMode == QgsComposerHtml::Url ? QUrl( mLastFetchedUrl ) : QUrl() );
187213

188214
while ( !mLoaded )
189215
{
@@ -214,6 +240,8 @@ void QgsComposerHtml::loadHtml()
214240

215241
recalculateFrameSizes();
216242
emit changed();
243+
//trigger a repaint
244+
emit contentsChanged();
217245
}
218246

219247
void QgsComposerHtml::frameLoaded( bool ok )
@@ -455,3 +483,13 @@ void QgsComposerHtml::refreshExpressionContext()
455483
setExpressionContext( feature, vl );
456484
loadHtml();
457485
}
486+
487+
void QgsComposerHtml::refreshDataDefinedProperty( QgsComposerObject::DataDefinedProperty property )
488+
{
489+
//updates data defined properties and redraws item to match
490+
if ( property == QgsComposerObject::SourceUrl || property == QgsComposerObject::AllProperties )
491+
{
492+
loadHtml();
493+
}
494+
QgsComposerObject::refreshDataDefinedProperty( property );
495+
}

src/core/composer/qgscomposerhtml.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame
178178

179179
void refreshExpressionContext();
180180

181+
virtual void refreshDataDefinedProperty( QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties );
182+
181183
private slots:
182184
void frameLoaded( bool ok = true );
183185

@@ -186,6 +188,8 @@ class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame
186188
QUrl mUrl;
187189
QWebPage* mWebPage;
188190
QString mHtml;
191+
QString mFetchedHtml;
192+
QString mLastFetchedUrl;
189193
bool mLoaded;
190194
QSizeF mSize; //total size in mm
191195
double mHtmlUnitsToMM;

src/core/composer/qgscomposermultiframe.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ class CORE_EXPORT QgsComposerMultiFrame: public QgsComposerObject
122122

123123
signals:
124124
void changed();
125+
126+
/**Emitted when the contents of the multi frame have changed and the frames
127+
* must be redrawn.
128+
*/
129+
void contentsChanged();
125130
};
126131

127132
#endif // QGSCOMPOSERMULTIFRAME_H

src/core/composer/qgscomposerobject.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ class CORE_EXPORT QgsComposerObject: public QObject
6565
MapXMax, /*< map extent x maximum */
6666
MapYMax, /*< map extent y maximum */
6767
//composer picture
68-
PictureSource /*< picture source url */
68+
PictureSource, /*< picture source url */
69+
//html item
70+
SourceUrl /*< html source utl */
6971
};
7072

7173
/** Specifies whether the value returned by a function should be the original, user

src/ui/qgscomposerhtmlwidgetbase.ui

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@
9292
</property>
9393
</widget>
9494
</item>
95+
<item>
96+
<widget class="QgsDataDefinedButton" name="mUrlDDBtn">
97+
<property name="text">
98+
<string>...</string>
99+
</property>
100+
</widget>
101+
</item>
95102
</layout>
96103
</item>
97104
<item row="2" column="0" colspan="2">
@@ -220,6 +227,11 @@
220227
<header>qgscollapsiblegroupbox.h</header>
221228
<container>1</container>
222229
</customwidget>
230+
<customwidget>
231+
<class>QgsDataDefinedButton</class>
232+
<extends>QToolButton</extends>
233+
<header>qgsdatadefinedbutton.h</header>
234+
</customwidget>
223235
</customwidgets>
224236
<resources/>
225237
<connections/>

0 commit comments

Comments
 (0)