QgsLayoutItemLabel::QgsLayoutItemLabel( QgsLayout *layout ) : QgsLayoutItem( layout ) { mDistanceArea.reset( new QgsDistanceArea() ); mHtmlUnitsToLayoutUnits = htmlUnitsToLayoutUnits(); //get default layout font from settings QgsSettings settings; QString defaultFontString = settings.value( QStringLiteral( "LayoutDesigner/defaultFont" ), QVariant(), QgsSettings::Gui ).toString(); if ( !defaultFontString.isEmpty() ) { mFont.setFamily( defaultFontString ); } //default to a 10 point font size mFont.setPointSizeF( 10 ); //default to no background setBackgroundEnabled( false ); //a label added while atlas preview is enabled needs to have the expression context set, //otherwise fields in the label aren't correctly evaluated until atlas preview feature changes (#9457) refreshExpressionContext(); mWebPage.reset( new QgsWebPage( this ) ); mWebPage->setIdentifier( tr( "Layout label item" ) ); mWebPage->setNetworkAccessManager( QgsNetworkAccessManager::instance() ); //This makes the background transparent. Found on http://blog.qt.digia.com/blog/2009/06/30/transparent-qwebview-or-qwebpage/ QPalette palette = mWebPage->palette(); palette.setBrush( QPalette::Base, Qt::transparent ); mWebPage->setPalette( palette ); mWebPage->mainFrame()->setZoomFactor( 10.0 ); mWebPage->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff ); mWebPage->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff ); connect( mWebPage.get(), &QWebPage::loadFinished, this, &QgsLayoutItemLabel::loadingHtmlFinished ); }
QgsLayoutItemHtml::QgsLayoutItemHtml( QgsLayout *layout ) : QgsLayoutMultiFrame( layout ) { mHtmlUnitsToLayoutUnits = htmlUnitsToLayoutUnits(); mWebPage = qgis::make_unique< QgsWebPage >(); mWebPage->setIdentifier( tr( "Layout HTML item" ) ); mWebPage->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff ); mWebPage->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff ); //This makes the background transparent. Found on http://blog.qt.digia.com/blog/2009/06/30/transparent-qwebview-or-qwebpage/ QPalette palette = mWebPage->palette(); palette.setBrush( QPalette::Base, Qt::transparent ); mWebPage->setPalette( palette ); mWebPage->setNetworkAccessManager( QgsNetworkAccessManager::instance() ); #if 0 //TODO if ( mLayout ) { connect( mLayout, &QgsComposition::itemRemoved, this, &QgsComposerMultiFrame::handleFrameRemoval ); } if ( mComposition && mComposition->atlasMode() == QgsComposition::PreviewAtlas ) { //a html item added while atlas preview is enabled needs to have the expression context set, //otherwise fields in the html aren't correctly evaluated until atlas preview feature changes (#9457) setExpressionContext( mComposition->atlasComposition().feature(), mComposition->atlasComposition().coverageLayer() ); } //connect to atlas feature changes //to update the expression context connect( &mComposition->atlasComposition(), &QgsAtlasComposition::featureChanged, this, &QgsLayoutItemHtml::refreshExpressionContext ); #endif mFetcher = new QgsNetworkContentFetcher(); }
double QgsLayoutItemHtml::findNearbyPageBreak( double yPos ) { if ( !mWebPage || mRenderedPage.isNull() || !mUseSmartBreaks ) { return yPos; } //convert yPos to pixels int idealPos = yPos * htmlUnitsToLayoutUnits(); //if ideal break pos is past end of page, there's nothing we need to do if ( idealPos >= mRenderedPage.height() ) { return yPos; } int maxSearchDistance = mMaxBreakDistance * htmlUnitsToLayoutUnits(); //loop through all lines just before ideal break location, up to max distance //of maxSearchDistance int changes = 0; QRgb currentColor; bool currentPixelTransparent = false; bool previousPixelTransparent = false; QRgb pixelColor; QList< QPair<int, int> > candidates; int minRow = std::max( idealPos - maxSearchDistance, 0 ); for ( int candidateRow = idealPos; candidateRow >= minRow; --candidateRow ) { changes = 0; currentColor = qRgba( 0, 0, 0, 0 ); //check all pixels in this line for ( int col = 0; col < mRenderedPage.width(); ++col ) { //count how many times the pixels change color in this row //eventually, we select a row to break at with the minimum number of color changes //since this is likely a line break, or gap between table cells, etc //but very unlikely to be midway through a text line or picture pixelColor = mRenderedPage.pixel( col, candidateRow ); currentPixelTransparent = qAlpha( pixelColor ) == 0; if ( pixelColor != currentColor && !( currentPixelTransparent && previousPixelTransparent ) ) { //color has changed currentColor = pixelColor; changes++; } previousPixelTransparent = currentPixelTransparent; } candidates.append( qMakePair( candidateRow, changes ) ); } //sort candidate rows by number of changes ascending, row number descending std::sort( candidates.begin(), candidates.end(), candidateSort ); //first candidate is now the largest row with smallest number of changes //OK, now take the mid point of the best candidate position //we do this so that the spacing between text lines is likely to be split in half //otherwise the html will be broken immediately above a line of text, which //looks a little messy int maxCandidateRow = candidates[0].first; int minCandidateRow = maxCandidateRow + 1; int minCandidateChanges = candidates[0].second; QList< QPair<int, int> >::iterator it; for ( it = candidates.begin(); it != candidates.end(); ++it ) { if ( ( *it ).second != minCandidateChanges || ( *it ).first != minCandidateRow - 1 ) { //no longer in a consecutive block of rows of minimum pixel color changes //so return the row mid-way through the block //first converting back to mm return ( minCandidateRow + ( maxCandidateRow - minCandidateRow ) / 2 ) / htmlUnitsToLayoutUnits(); } minCandidateRow = ( *it ).first; } //above loop didn't work for some reason //return first candidate converted to mm return candidates[0].first / htmlUnitsToLayoutUnits(); }