Skip to content

Commit

Permalink
[FEATURE][composer] Data defined url for composer html items. Sponsor…
Browse files Browse the repository at this point in the history
…ed by City of Uster, Switzerland.
  • Loading branch information
nyalldawson committed Jul 21, 2014
1 parent 7e815ca commit 68e03cb
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 6 deletions.
5 changes: 5 additions & 0 deletions python/core/composer/qgscomposerhtml.sip
Expand Up @@ -152,4 +152,9 @@ class QgsComposerHtml: QgsComposerMultiFrame
* @see url
*/
void loadHtml();

void refreshExpressionContext();

virtual void refreshDataDefinedProperty( QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties );

};
5 changes: 5 additions & 0 deletions python/core/composer/qgscomposermultiframe.sip
Expand Up @@ -84,4 +84,9 @@ class QgsComposerMultiFrame: QgsComposerObject

signals:
void changed();

/**Emitted when the contents of the multi frame have changed and the frames
* must be redrawn.
*/
void contentsChanged();
};
45 changes: 45 additions & 0 deletions src/app/composer/qgscomposerhtmlwidget.cpp
Expand Up @@ -45,6 +45,15 @@ QgsComposerHtmlWidget::QgsComposerHtmlWidget( QgsComposerHtml* html, QgsComposer
if ( mHtml )
{
QObject::connect( mHtml, SIGNAL( changed() ), this, SLOT( setGuiElementValues() ) );

QgsAtlasComposition* atlas = atlasComposition();
if ( atlas )
{
// repopulate data defined buttons if atlas layer changes
connect( atlas, SIGNAL( coverageLayerChanged( QgsVectorLayer* ) ),
this, SLOT( populateDataDefinedButtons() ) );
connect( atlas, SIGNAL( toggled( bool ) ), this, SLOT( populateDataDefinedButtons() ) );
}
}

//embed widget for general options
Expand All @@ -54,6 +63,12 @@ QgsComposerHtmlWidget::QgsComposerHtmlWidget( QgsComposerHtml* html, QgsComposer
QgsComposerItemWidget* itemPropertiesWidget = new QgsComposerItemWidget( this, mFrame );
mainLayout->addWidget( itemPropertiesWidget );
}

//connections for data defined buttons
connect( mUrlDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedProperty( ) ) );
connect( mUrlDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedProperty( ) ) );
connect( mUrlDDBtn, SIGNAL( dataDefinedActivated( bool ) ), mUrlLineEdit, SLOT( setDisabled( bool ) ) );

}

QgsComposerHtmlWidget::QgsComposerHtmlWidget(): QgsComposerItemBaseWidget( 0, 0 )
Expand Down Expand Up @@ -358,5 +373,35 @@ void QgsComposerHtmlWidget::setGuiElementValues()
mRadioManualSource->setChecked( mHtml->contentMode() == QgsComposerHtml::ManualHtml );
mHtmlEditor->setEnabled( mHtml->contentMode() == QgsComposerHtml::ManualHtml );
mInsertExpressionButton->setEnabled( mHtml->contentMode() == QgsComposerHtml::ManualHtml );

populateDataDefinedButtons();

blockSignals( false );
}

QgsComposerItem::DataDefinedProperty QgsComposerHtmlWidget::ddPropertyForWidget( QgsDataDefinedButton *widget )
{
if ( widget == mUrlDDBtn )
{
return QgsComposerItem::SourceUrl;
}
return QgsComposerItem::NoProperty;
}

void QgsComposerHtmlWidget::populateDataDefinedButtons()
{
QgsVectorLayer* vl = atlasCoverageLayer();

//block signals from data defined buttons
mUrlDDBtn->blockSignals( true );

//initialise buttons to use atlas coverage layer
mUrlDDBtn->init( vl, mHtml->dataDefinedProperty( QgsComposerItem::SourceUrl ),
QgsDataDefinedButton::AnyType, tr( "url string" ) );

//initial state of controls - disable related controls when dd buttons are active
mUrlLineEdit->setEnabled( !mUrlDDBtn->isActive() );

//unblock signals from data defined buttons
mUrlDDBtn->blockSignals( false );
}
7 changes: 7 additions & 0 deletions src/app/composer/qgscomposerhtmlwidget.h
Expand Up @@ -47,6 +47,13 @@ class QgsComposerHtmlWidget: public QgsComposerItemBaseWidget, private Ui::QgsCo
/**Sets the GUI elements to the values of mHtmlItem*/
void setGuiElementValues();

protected:
QgsComposerItem::DataDefinedProperty ddPropertyForWidget( QgsDataDefinedButton *widget );

protected slots:
/**Initializes data defined buttons to current atlas coverage layer*/
void populateDataDefinedButtons();

private:
QgsComposerHtmlWidget();
void blockSignals( bool block );
Expand Down
3 changes: 3 additions & 0 deletions src/core/composer/qgscomposerframe.cpp
Expand Up @@ -21,6 +21,8 @@ QgsComposerFrame::QgsComposerFrame( QgsComposition* c, QgsComposerMultiFrame* mf
: QgsComposerItem( x, y, width, height, c )
, mMultiFrame( mf )
{
//repaint frame when multiframe content changes
connect( mf, SIGNAL( contentsChanged() ), this, SLOT( repaint() ) );
}

QgsComposerFrame::QgsComposerFrame()
Expand All @@ -41,6 +43,7 @@ bool QgsComposerFrame::writeXML( QDomElement& elem, QDomDocument & doc ) const
frameElem.setAttribute( "sectionWidth", QString::number( mSection.width() ) );
frameElem.setAttribute( "sectionHeight", QString::number( mSection.height() ) );
elem.appendChild( frameElem );

return _writeXML( frameElem, doc );
}

Expand Down
48 changes: 43 additions & 5 deletions src/core/composer/qgscomposerhtml.cpp
Expand Up @@ -20,6 +20,7 @@
#include "qgsnetworkaccessmanager.h"
#include "qgsmessagelog.h"
#include "qgsexpression.h"
#include "qgslogger.h"

#include <QCoreApplication>
#include <QPainter>
Expand Down Expand Up @@ -47,9 +48,11 @@ QgsComposerHtml::QgsComposerHtml( QgsComposition* c, bool createUndoCommands ):
if ( mComposition )
{
QObject::connect( mComposition, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( handleFrameRemoval( QgsComposerItem* ) ) );
connect( mComposition, SIGNAL( refreshItemsTriggered() ), this, SLOT( loadHtml() ) );
}

// data defined strings
mDataDefinedNames.insert( QgsComposerObject::SourceUrl, QString( "dataDefinedSourceUrl" ) );

if ( mComposition && mComposition->atlasMode() == QgsComposition::PreviewAtlas )
{
//a html item added while atlas preview is enabled needs to have the expression context set,
Expand Down Expand Up @@ -152,12 +155,13 @@ QString QgsComposerHtml::fetchHtml( QUrl url )

QByteArray array = reply->readAll();
reply->deleteLater();
return QString( array );
mFetchedHtml = QString( array );
return mFetchedHtml;
}

void QgsComposerHtml::loadHtml()
{
if ( !mWebPage || ( mContentMode == QgsComposerHtml::Url && mUrl.isEmpty() ) )
if ( !mWebPage )
{
return;
}
Expand All @@ -167,7 +171,29 @@ void QgsComposerHtml::loadHtml()
{
case QgsComposerHtml::Url:
{
loadedHtml = fetchHtml( mUrl );

QString currentUrl = mUrl.toString();

//data defined url set?
QVariant exprVal;
if ( dataDefinedEvaluate( QgsComposerObject::SourceUrl, exprVal ) )
{
currentUrl = exprVal.toString().trimmed();;
QgsDebugMsg( QString( "exprVal Source Url:%1" ).arg( currentUrl ) );
}
if ( currentUrl.isEmpty() )
{
return;
}
if ( currentUrl != mLastFetchedUrl )
{
loadedHtml = fetchHtml( QUrl( currentUrl ) );
mLastFetchedUrl = currentUrl;
}
else
{
loadedHtml = mFetchedHtml;
}
break;
}
case QgsComposerHtml::ManualHtml:
Expand All @@ -183,7 +209,7 @@ void QgsComposerHtml::loadHtml()

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

while ( !mLoaded )
{
Expand Down Expand Up @@ -214,6 +240,8 @@ void QgsComposerHtml::loadHtml()

recalculateFrameSizes();
emit changed();
//trigger a repaint
emit contentsChanged();
}

void QgsComposerHtml::frameLoaded( bool ok )
Expand Down Expand Up @@ -455,3 +483,13 @@ void QgsComposerHtml::refreshExpressionContext()
setExpressionContext( feature, vl );
loadHtml();
}

void QgsComposerHtml::refreshDataDefinedProperty( QgsComposerObject::DataDefinedProperty property )
{
//updates data defined properties and redraws item to match
if ( property == QgsComposerObject::SourceUrl || property == QgsComposerObject::AllProperties )
{
loadHtml();
}
QgsComposerObject::refreshDataDefinedProperty( property );
}
4 changes: 4 additions & 0 deletions src/core/composer/qgscomposerhtml.h
Expand Up @@ -178,6 +178,8 @@ class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame

void refreshExpressionContext();

virtual void refreshDataDefinedProperty( QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties );

private slots:
void frameLoaded( bool ok = true );

Expand All @@ -186,6 +188,8 @@ class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame
QUrl mUrl;
QWebPage* mWebPage;
QString mHtml;
QString mFetchedHtml;
QString mLastFetchedUrl;
bool mLoaded;
QSizeF mSize; //total size in mm
double mHtmlUnitsToMM;
Expand Down
5 changes: 5 additions & 0 deletions src/core/composer/qgscomposermultiframe.h
Expand Up @@ -122,6 +122,11 @@ class CORE_EXPORT QgsComposerMultiFrame: public QgsComposerObject

signals:
void changed();

/**Emitted when the contents of the multi frame have changed and the frames
* must be redrawn.
*/
void contentsChanged();
};

#endif // QGSCOMPOSERMULTIFRAME_H
4 changes: 3 additions & 1 deletion src/core/composer/qgscomposerobject.h
Expand Up @@ -65,7 +65,9 @@ class CORE_EXPORT QgsComposerObject: public QObject
MapXMax, /*< map extent x maximum */
MapYMax, /*< map extent y maximum */
//composer picture
PictureSource /*< picture source url */
PictureSource, /*< picture source url */
//html item
SourceUrl /*< html source utl */
};

/** Specifies whether the value returned by a function should be the original, user
Expand Down
12 changes: 12 additions & 0 deletions src/ui/qgscomposerhtmlwidgetbase.ui
Expand Up @@ -92,6 +92,13 @@
</property>
</widget>
</item>
<item>
<widget class="QgsDataDefinedButton" name="mUrlDDBtn">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0" colspan="2">
Expand Down Expand Up @@ -220,6 +227,11 @@
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsDataDefinedButton</class>
<extends>QToolButton</extends>
<header>qgsdatadefinedbutton.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
Expand Down

0 comments on commit 68e03cb

Please sign in to comment.