void QgsComposerAttributeTableV2::atlasLayerChanged( QgsVectorLayer *layer ) { if ( mSource != QgsComposerAttributeTableV2::AtlasFeature || layer == mCurrentAtlasLayer ) { //nothing to do return; } //atlas feature mode, atlas layer changed, so we need to reset columns if ( mCurrentAtlasLayer ) { //disconnect from previous layer disconnect( mCurrentAtlasLayer, SIGNAL( layerModified() ), this, SLOT( refreshAttributes() ) ); } mCurrentAtlasLayer = layer; //rebuild column list to match all columns from layer resetColumns(); refreshAttributes(); //listen for modifications to layer and refresh table when they occur connect( layer, SIGNAL( layerModified() ), this, SLOT( refreshAttributes() ) ); }
void QgsComposerAttributeTable::setDisplayAttributes( const QSet<int>& attr, bool refresh ) { if ( !mVectorLayer ) { return; } //rebuild columns list, taking only attributes with index in supplied QSet qDeleteAll( mColumns ); mColumns.clear(); const QgsFields& fields = mVectorLayer->fields(); if ( !attr.empty() ) { QSet<int>::const_iterator attIt = attr.constBegin(); for ( ; attIt != attr.constEnd(); ++attIt ) { int attrIdx = ( *attIt ); if ( !fields.exists( attrIdx ) ) { continue; } QString currentAlias = mVectorLayer->attributeDisplayName( attrIdx ); QgsComposerTableColumn* col = new QgsComposerTableColumn; col->setAttribute( fields[attrIdx].name() ); col->setHeading( currentAlias ); mColumns.append( col ); } } else { //resetting, so add all attributes to columns for ( int idx = 0; idx < fields.count(); ++idx ) { QString currentAlias = mVectorLayer->attributeDisplayName( idx ); QgsComposerTableColumn* col = new QgsComposerTableColumn; col->setAttribute( fields[idx].name() ); col->setHeading( currentAlias ); mColumns.append( col ); } } if ( refresh ) { refreshAttributes(); } }
QgsComposerAttributeTableV2::QgsComposerAttributeTableV2( QgsComposition *composition, bool createUndoCommands ) : QgsComposerTableV2( composition, createUndoCommands ) , mSource( LayerAttributes ) , mCurrentAtlasLayer( nullptr ) , mComposerMap( nullptr ) , mMaximumNumberOfFeatures( 30 ) , mShowUniqueRowsOnly( false ) , mShowOnlyVisibleFeatures( false ) , mFilterToAtlasIntersection( false ) , mFilterFeatures( false ) , mFeatureFilter( QLatin1String( "" ) ) { //set first vector layer from layer registry as default one QMap<QString, QgsMapLayer *> layerMap = mComposition->project()->mapLayers(); QMap<QString, QgsMapLayer *>::const_iterator mapIt = layerMap.constBegin(); for ( ; mapIt != layerMap.constEnd(); ++mapIt ) { QgsVectorLayer *vl = dynamic_cast<QgsVectorLayer *>( mapIt.value() ); if ( vl ) { mVectorLayer.setLayer( vl ); break; } } if ( mVectorLayer ) { resetColumns(); //listen for modifications to layer and refresh table when they occur connect( mVectorLayer.get(), &QgsVectorLayer::layerModified, this, &QgsComposerTableV2::refreshAttributes ); } if ( mComposition ) { connect( mComposition->project(), static_cast < void ( QgsProject::* )( const QString & ) >( &QgsProject::layerWillBeRemoved ), this, &QgsComposerAttributeTableV2::removeLayer ); //refresh table attributes when composition is refreshed connect( mComposition, &QgsComposition::refreshItemsTriggered, this, &QgsComposerTableV2::refreshAttributes ); //connect to atlas feature changes to update table rows connect( &mComposition->atlasComposition(), &QgsAtlasComposition::featureChanged, this, &QgsComposerTableV2::refreshAttributes ); //atlas coverage layer change = regenerate columns connect( &mComposition->atlasComposition(), &QgsAtlasComposition::coverageLayerChanged, this, &QgsComposerAttributeTableV2::atlasLayerChanged ); } refreshAttributes(); }
bool SproutDevice::changeMode(std::string value) { bool success = false; std::string result; if( value.compare("AutoDetect") == 0 ) { //result = serialController->queryDevice("OPMODE?", rs232QuerySleep_ms); //string::size_type equalPos = result.find_first_of("="); //std::string newMode = result.substr(equalPos + 1); ////Convert to expected capitalization of attribute name //std::transform(newMode.begin(), newMode.end(), newMode.begin(), ::tolower); //std::string::iterator stopIter = newMode.begin(); //stopIter++; //std::transform(newMode.begin(), stopIter, newMode.begin(), ::toupper); // ////if(newMode.at(newMode.size() - 1) == '\b') //newMode = newMode.substr(0, newMode.size() - 1); //for(unsigned i = 0; i < newMode.size(); i++) //{ // std::cout << "{" << (char)newMode.at(i) << "}" << std::endl; //} //std::cout << "Equal? " << ((newMode.compare("Off")==0) ? "Yes" : "No") << std::endl; success = true; refreshAttributes(); // success = setAttribute("Mode", getMode()); } else { result = serialController->queryDevice("OPMODE=" + value, rs232QuerySleep_ms); string::size_type zeroPos = result.find_first_of("0"); //sprout returns 0 on success string::size_type twoPos = result.find_first_of("2"); //and 2 on failure // cout << "mode change response: " << result << std::endl; success = (zeroPos != std::string::npos && twoPos == std::string::npos); } return success; }
void QgsComposerAttributeTable::setSceneRect( const QRectF& rectangle ) { double titleHeight = 2 * mGridStrokeWidth + 2 * mLineTextDistance + fontAscentMillimeters( mHeaderFont ); double attributeHeight = mGridStrokeWidth + 2 * mLineTextDistance + fontAscentMillimeters( mContentFont ); if (( rectangle.height() - titleHeight ) > 0 ) { mMaximumNumberOfFeatures = ( rectangle.height() - titleHeight ) / attributeHeight; } else { mMaximumNumberOfFeatures = 0; } QgsComposerItem::setSceneRect( rectangle ); //refresh table attributes, since number of features has likely changed refreshAttributes(); emit maximumNumberOfFeaturesChanged( mMaximumNumberOfFeatures ); }
void QgsComposerAttributeTableV2::setComposerMap( const QgsComposerMap *map ) { if ( map == mComposerMap ) { //no change return; } if ( mComposerMap ) { //disconnect from previous map disconnect( mComposerMap, &QgsComposerMap::extentChanged, this, &QgsComposerTableV2::refreshAttributes ); } mComposerMap = map; if ( mComposerMap ) { //listen out for extent changes in linked map connect( mComposerMap, &QgsComposerMap::extentChanged, this, &QgsComposerTableV2::refreshAttributes ); } refreshAttributes(); emit changed(); }
QgsComposerAttributeTable::QgsComposerAttributeTable( QgsComposition* composition ) : QgsComposerTable( composition ) , mVectorLayer( nullptr ) , mComposerMap( nullptr ) , mMaximumNumberOfFeatures( 5 ) , mShowOnlyVisibleFeatures( false ) , mFilterFeatures( false ) , mFeatureFilter( "" ) { //set first vector layer from layer registry as default one QMap<QString, QgsMapLayer*> layerMap = QgsMapLayerRegistry::instance()->mapLayers(); QMap<QString, QgsMapLayer*>::const_iterator mapIt = layerMap.constBegin(); for ( ; mapIt != layerMap.constEnd(); ++mapIt ) { QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( mapIt.value() ); if ( vl ) { mVectorLayer = vl; break; } } if ( mVectorLayer ) { resetColumns(); } connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( removeLayer( const QString& ) ) ); if ( mComposition ) { //refresh table attributes when composition is refreshed connect( mComposition, SIGNAL( refreshItemsTriggered() ), this, SLOT( refreshAttributes() ) ); //connect to atlas feature changes to update table rows connect( &mComposition->atlasComposition(), SIGNAL( featureChanged( QgsFeature* ) ), this, SLOT( refreshAttributes() ) ); } }
bool QgsComposerAttributeTable::readXML( const QDomElement& itemElem, const QDomDocument& doc ) { if ( itemElem.isNull() ) { return false; } mShowOnlyVisibleFeatures = itemElem.attribute( "showOnlyVisibleFeatures", "1" ).toInt(); mFilterFeatures = itemElem.attribute( "filterFeatures", "false" ) == "true" ? true : false; mFeatureFilter = itemElem.attribute( "featureFilter", "" ); //composer map int composerMapId = itemElem.attribute( "composerMap", "-1" ).toInt(); if ( composerMapId == -1 ) { mComposerMap = 0; } if ( composition() ) { mComposerMap = composition()->getComposerMapById( composerMapId ); } else { mComposerMap = 0; } if ( mComposerMap ) { //if we have found a valid map item, listen out to extent changes on it and refresh the table QObject::connect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( refreshAttributes() ) ); } //vector layer QString layerId = itemElem.attribute( "vectorLayer", "not_existing" ); if ( layerId == "not_existing" ) { mVectorLayer = 0; } else { QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerId ); if ( ml ) { mVectorLayer = dynamic_cast<QgsVectorLayer*>( ml ); if ( mVectorLayer ) { //if we have found a valid vector layer, listen for modifications on it and refresh the table QObject::connect( mVectorLayer, SIGNAL( layerModified() ), this, SLOT( refreshAttributes() ) ); } } } //restore display attribute map mDisplayAttributes.clear(); QDomNodeList displayAttributeList = itemElem.elementsByTagName( "displayAttributes" ); if ( displayAttributeList.size() > 0 ) { QDomElement displayAttributesElem = displayAttributeList.at( 0 ).toElement(); QDomNodeList attributeEntryList = displayAttributesElem.elementsByTagName( "attributeEntry" ); for ( int i = 0; i < attributeEntryList.size(); ++i ) { QDomElement attributeEntryElem = attributeEntryList.at( i ).toElement(); int index = attributeEntryElem.attribute( "index", "-1" ).toInt(); if ( index != -1 ) { mDisplayAttributes.insert( index ); } } } //restore alias map mFieldAliasMap.clear(); QDomNodeList aliasMapNodeList = itemElem.elementsByTagName( "attributeAliasMap" ); if ( aliasMapNodeList.size() > 0 ) { QDomElement attributeAliasMapElem = aliasMapNodeList.at( 0 ).toElement(); QDomNodeList aliasMepEntryList = attributeAliasMapElem.elementsByTagName( "aliasEntry" ); for ( int i = 0; i < aliasMepEntryList.size(); ++i ) { QDomElement aliasEntryElem = aliasMepEntryList.at( i ).toElement(); int key = aliasEntryElem.attribute( "key", "-1" ).toInt(); QString value = aliasEntryElem.attribute( "value", "" ); mFieldAliasMap.insert( key, value ); } } //restore sort columns mSortInformation.clear(); QDomElement sortColumnsElem = itemElem.firstChildElement( "sortColumns" ); if ( !sortColumnsElem.isNull() ) { QDomNodeList columns = sortColumnsElem.elementsByTagName( "column" ); for ( int i = 0; i < columns.size(); ++i ) { QDomElement columnElem = columns.at( i ).toElement(); int attribute = columnElem.attribute( "index" ).toInt(); bool ascending = columnElem.attribute( "ascending" ) == "true" ? true : false; mSortInformation.push_back( qMakePair( attribute, ascending ) ); } } bool success = tableReadXML( itemElem, doc ); //must be done here because tableReadXML->setSceneRect changes mMaximumNumberOfFeatures mMaximumNumberOfFeatures = itemElem.attribute( "maxFeatures", "5" ).toInt(); refreshAttributes(); emit itemChanged(); return success; }
void QgsComposerTableV2::render( QPainter *p, const QRectF &renderExtent, const int frameIndex ) { if ( !p ) { return; } bool emptyTable = mTableContents.length() == 0; if ( emptyTable && mEmptyTableMode == QgsComposerTableV2::HideTable ) { //empty table set to hide table mode, so don't draw anything return; } //calculate which rows to show in this frame QPair< int, int > rowsToShow = rowRange( renderExtent, frameIndex ); if ( mComposition->plotStyle() == QgsComposition::Print || mComposition->plotStyle() == QgsComposition::Postscript ) { //exporting composition, so force an attribute refresh //we do this in case vector layer has changed via an external source (eg, another database user) refreshAttributes(); } p->save(); //antialiasing on p->setRenderHint( QPainter::Antialiasing, true ); p->setPen( Qt::SolidLine ); //now draw the text double currentX = ( mShowGrid ? mGridStrokeWidth : 0 ); double currentY; QList<QgsComposerTableColumn*>::const_iterator columnIt = mColumns.constBegin(); int col = 0; double cellHeaderHeight = QgsComposerUtils::fontAscentMM( mHeaderFont ) + 2 * mCellMargin; double cellBodyHeight = QgsComposerUtils::fontAscentMM( mContentFont ) + 2 * mCellMargin; QRectF cell; //calculate whether a header is required bool drawHeader = (( mHeaderMode == QgsComposerTableV2::FirstFrame && frameIndex < 1 ) || ( mHeaderMode == QgsComposerTableV2::AllFrames ) ); //calculate whether drawing table contents is required bool drawContents = !( emptyTable && mEmptyTableMode == QgsComposerTableV2::ShowMessage ); for ( ; columnIt != mColumns.constEnd(); ++columnIt ) { currentY = ( mShowGrid ? mGridStrokeWidth : 0 ); currentX += mCellMargin; Qt::TextFlag textFlag = ( Qt::TextFlag )0; if (( *columnIt )->width() <= 0 ) { //automatic column width, so we use the Qt::TextDontClip flag when drawing contents, as this works nicer for italicised text //which may slightly exceed the calculated width //if column size was manually set then we do apply text clipping, to avoid painting text outside of columns width textFlag = Qt::TextDontClip; } if ( drawHeader ) { //draw the header cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], cellHeaderHeight ); //calculate alignment of header Qt::AlignmentFlag headerAlign = Qt::AlignLeft; switch ( mHeaderHAlignment ) { case FollowColumn: headerAlign = ( *columnIt )->hAlignment(); break; case HeaderLeft: headerAlign = Qt::AlignLeft; break; case HeaderCenter: headerAlign = Qt::AlignHCenter; break; case HeaderRight: headerAlign = Qt::AlignRight; break; } QgsComposerUtils::drawText( p, cell, ( *columnIt )->heading(), mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, textFlag ); currentY += cellHeaderHeight; currentY += ( mShowGrid ? mGridStrokeWidth : 0 ); } if ( drawContents ) { //draw the attribute values for ( int row = rowsToShow.first; row < rowsToShow.second; ++row ) { cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], cellBodyHeight ); QVariant cellContents = mTableContents.at( row ).at( col ); QString str = cellContents.toString(); QgsComposerUtils::drawText( p, cell, str, mContentFont, mContentFontColor, ( *columnIt )->hAlignment(), Qt::AlignVCenter, textFlag ); currentY += cellBodyHeight; currentY += ( mShowGrid ? mGridStrokeWidth : 0 ); } } currentX += mMaxColumnWidthMap[ col ]; currentX += mCellMargin; currentX += ( mShowGrid ? mGridStrokeWidth : 0 ); col++; } //and the borders if ( mShowGrid ) { int numberRowsToDraw = rowsToShow.second - rowsToShow.first; if ( mEmptyTableMode == QgsComposerTableV2::DrawEmptyCells ) { numberRowsToDraw = rowsVisible( frameIndex ); } bool mergeCells = false; if ( emptyTable && mEmptyTableMode == QgsComposerTableV2::ShowMessage ) { //draw a merged row for the empty table message numberRowsToDraw++; mergeCells = true; } QPen gridPen; gridPen.setWidthF( mGridStrokeWidth ); gridPen.setColor( mGridColor ); gridPen.setJoinStyle( Qt::MiterJoin ); p->setPen( gridPen ); drawHorizontalGridLines( p, numberRowsToDraw, drawHeader ); drawVerticalGridLines( p, mMaxColumnWidthMap, numberRowsToDraw, drawHeader, mergeCells ); } //special case - no records and table is set to ShowMessage mode if ( emptyTable && mEmptyTableMode == QgsComposerTableV2::ShowMessage ) { double messageX = ( mShowGrid ? mGridStrokeWidth : 0 ) + mCellMargin; double messageY = ( mShowGrid ? mGridStrokeWidth : 0 ) + ( drawHeader ? cellHeaderHeight + ( mShowGrid ? mGridStrokeWidth : 0 ) : 0 ); cell = QRectF( messageX, messageY, mTableSize.width() - messageX, cellBodyHeight ); QgsComposerUtils::drawText( p, cell, mEmptyTableMessage, mContentFont, mContentFontColor, Qt::AlignHCenter, Qt::AlignVCenter, ( Qt::TextFlag )0 ); } p->restore(); }
void QgsLayoutTable::render( QgsLayoutItemRenderContext &context, const QRectF &, const int frameIndex ) { bool emptyTable = mTableContents.length() == 0; if ( emptyTable && mEmptyTableMode == QgsLayoutTable::HideTable ) { //empty table set to hide table mode, so don't draw anything return; } if ( !mLayout->renderContext().isPreviewRender() ) { //exporting composition, so force an attribute refresh //we do this in case vector layer has changed via an external source (e.g., another database user) refreshAttributes(); } //calculate which rows to show in this frame QPair< int, int > rowsToShow = rowRange( frameIndex ); double gridSizeX = mShowGrid && mVerticalGrid ? mGridStrokeWidth : 0; double gridSizeY = mShowGrid && mHorizontalGrid ? mGridStrokeWidth : 0; double cellHeaderHeight = QgsLayoutUtils::fontAscentMM( mHeaderFont ) + 2 * mCellMargin; double cellBodyHeight = QgsLayoutUtils::fontAscentMM( mContentFont ) + 2 * mCellMargin; QRectF cell; //calculate whether a header is required bool drawHeader = ( ( mHeaderMode == QgsLayoutTable::FirstFrame && frameIndex < 1 ) || ( mHeaderMode == QgsLayoutTable::AllFrames ) ); //calculate whether drawing table contents is required bool drawContents = !( emptyTable && mEmptyTableMode == QgsLayoutTable::ShowMessage ); int numberRowsToDraw = rowsToShow.second - rowsToShow.first; int numberEmptyRows = 0; if ( drawContents && mShowEmptyRows ) { numberRowsToDraw = rowsVisible( frameIndex, rowsToShow.first, true ); numberEmptyRows = numberRowsToDraw - rowsToShow.second + rowsToShow.first; } bool mergeCells = false; if ( emptyTable && mEmptyTableMode == QgsLayoutTable::ShowMessage ) { //draw a merged row for the empty table message numberRowsToDraw++; rowsToShow.second++; mergeCells = true; } QPainter *p = context.renderContext().painter(); p->save(); // painter is scaled to dots, so scale back to layout units p->scale( context.renderContext().scaleFactor(), context.renderContext().scaleFactor() ); //draw the text p->setPen( Qt::SolidLine ); double currentX = gridSizeX; double currentY = gridSizeY; if ( drawHeader ) { //draw the headers int col = 0; for ( const QgsLayoutTableColumn *column : qgis::as_const( mColumns ) ) { //draw background p->save(); p->setPen( Qt::NoPen ); p->setBrush( backgroundColor( -1, col ) ); p->drawRect( QRectF( currentX, currentY, mMaxColumnWidthMap[col] + 2 * mCellMargin, cellHeaderHeight ) ); p->restore(); currentX += mCellMargin; Qt::TextFlag textFlag = static_cast< Qt::TextFlag >( 0 ); if ( column->width() <= 0 ) { //automatic column width, so we use the Qt::TextDontClip flag when drawing contents, as this works nicer for italicised text //which may slightly exceed the calculated width //if column size was manually set then we do apply text clipping, to avoid painting text outside of columns width textFlag = Qt::TextDontClip; } cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], cellHeaderHeight ); //calculate alignment of header Qt::AlignmentFlag headerAlign = Qt::AlignLeft; switch ( mHeaderHAlignment ) { case FollowColumn: headerAlign = column->hAlignment(); break; case HeaderLeft: headerAlign = Qt::AlignLeft; break; case HeaderCenter: headerAlign = Qt::AlignHCenter; break; case HeaderRight: headerAlign = Qt::AlignRight; break; } QgsLayoutUtils::drawText( p, cell, column->heading(), mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, textFlag ); currentX += mMaxColumnWidthMap[ col ]; currentX += mCellMargin; currentX += gridSizeX; col++; } currentY += cellHeaderHeight; currentY += gridSizeY; } //now draw the body cells int rowsDrawn = 0; if ( drawContents ) { //draw the attribute values for ( int row = rowsToShow.first; row < rowsToShow.second; ++row ) { rowsDrawn++; currentX = gridSizeX; int col = 0; //calculate row height double rowHeight = mMaxRowHeightMap[row + 1] + 2 * mCellMargin; for ( const QgsLayoutTableColumn *column : qgis::as_const( mColumns ) ) { //draw background p->save(); p->setPen( Qt::NoPen ); p->setBrush( backgroundColor( row, col ) ); p->drawRect( QRectF( currentX, currentY, mMaxColumnWidthMap[col] + 2 * mCellMargin, rowHeight ) ); p->restore(); // currentY = gridSize; currentX += mCellMargin; QVariant cellContents = mTableContents.at( row ).at( col ); QString str = cellContents.toString(); Qt::TextFlag textFlag = static_cast< Qt::TextFlag >( 0 ); if ( column->width() <= 0 && mWrapBehavior == TruncateText ) { //automatic column width, so we use the Qt::TextDontClip flag when drawing contents, as this works nicer for italicised text //which may slightly exceed the calculated width //if column size was manually set then we do apply text clipping, to avoid painting text outside of columns width textFlag = Qt::TextDontClip; } else if ( textRequiresWrapping( str, column->width(), mContentFont ) ) { str = wrappedText( str, column->width(), mContentFont ); } cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], rowHeight ); QgsLayoutUtils::drawText( p, cell, str, mContentFont, mContentFontColor, column->hAlignment(), column->vAlignment(), textFlag ); currentX += mMaxColumnWidthMap[ col ]; currentX += mCellMargin; currentX += gridSizeX; col++; } currentY += rowHeight; currentY += gridSizeY; } } if ( numberRowsToDraw > rowsDrawn ) { p->save(); p->setPen( Qt::NoPen ); //draw background of empty rows for ( int row = rowsDrawn; row < numberRowsToDraw; ++row ) { currentX = gridSizeX; int col = 0; if ( mergeCells ) { p->setBrush( backgroundColor( row + 10000, 0 ) ); p->drawRect( QRectF( gridSizeX, currentY, mTableSize.width() - 2 * gridSizeX, cellBodyHeight ) ); } else { for ( QgsLayoutTableColumn *column : qgis::as_const( mColumns ) ) { Q_UNUSED( column ); //draw background //we use a bit of a hack here - since we don't want these extra blank rows to match the firstrow/lastrow rule, add 10000 to row number p->setBrush( backgroundColor( row + 10000, col ) ); p->drawRect( QRectF( currentX, currentY, mMaxColumnWidthMap[col] + 2 * mCellMargin, cellBodyHeight ) ); // currentY = gridSize; currentX += mMaxColumnWidthMap[ col ] + 2 * mCellMargin; currentX += gridSizeX; col++; } } currentY += cellBodyHeight + gridSizeY; } p->restore(); } //and the borders if ( mShowGrid ) { QPen gridPen; gridPen.setWidthF( mGridStrokeWidth ); gridPen.setColor( mGridColor ); gridPen.setJoinStyle( Qt::MiterJoin ); p->setPen( gridPen ); if ( mHorizontalGrid ) { drawHorizontalGridLines( p, rowsToShow.first, rowsToShow.second + numberEmptyRows, drawHeader ); } if ( mVerticalGrid ) { drawVerticalGridLines( p, mMaxColumnWidthMap, rowsToShow.first, rowsToShow.second + numberEmptyRows, drawHeader, mergeCells ); } } //special case - no records and table is set to ShowMessage mode if ( emptyTable && mEmptyTableMode == QgsLayoutTable::ShowMessage ) { double messageX = gridSizeX + mCellMargin; double messageY = gridSizeY + ( drawHeader ? cellHeaderHeight + gridSizeY : 0 ); cell = QRectF( messageX, messageY, mTableSize.width() - messageX, cellBodyHeight ); QgsLayoutUtils::drawText( p, cell, mEmptyTableMessage, mContentFont, mContentFontColor, Qt::AlignHCenter, Qt::AlignVCenter, static_cast< Qt::TextFlag >( 0 ) ); } p->restore(); }
void QgsLayoutTable::refresh() { QgsLayoutMultiFrame::refresh(); refreshAttributes(); }
void QgsComposerAttributeTable::setFieldAliasMap( const QMap<int, QString>& map ) { restoreFieldAliasMap( map ); refreshAttributes(); }
bool QgsComposerAttributeTableV2::readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames ) { if ( itemElem.isNull() ) { return false; } //read general table properties if ( !QgsComposerTableV2::readXML( itemElem, doc, ignoreFrames ) ) { return false; } QgsVectorLayer* prevLayer = sourceLayer(); if ( prevLayer ) { //disconnect from previous layer disconnect( prevLayer, SIGNAL( layerModified() ), this, SLOT( refreshAttributes() ) ); } mSource = QgsComposerAttributeTableV2::ContentSource( itemElem.attribute( "source", "0" ).toInt() ); mRelationId = itemElem.attribute( "relationId", "" ); if ( mSource == QgsComposerAttributeTableV2::AtlasFeature ) { mCurrentAtlasLayer = mComposition->atlasComposition().coverageLayer(); } mShowUniqueRowsOnly = itemElem.attribute( "showUniqueRowsOnly", "0" ).toInt(); mShowOnlyVisibleFeatures = itemElem.attribute( "showOnlyVisibleFeatures", "1" ).toInt(); mFilterToAtlasIntersection = itemElem.attribute( "filterToAtlasIntersection", "0" ).toInt(); mFilterFeatures = itemElem.attribute( "filterFeatures", "false" ) == "true" ? true : false; mFeatureFilter = itemElem.attribute( "featureFilter", "" ); mMaximumNumberOfFeatures = itemElem.attribute( "maxFeatures", "5" ).toInt(); //composer map int composerMapId = itemElem.attribute( "composerMap", "-1" ).toInt(); if ( composerMapId == -1 ) { mComposerMap = 0; } if ( composition() ) { mComposerMap = composition()->getComposerMapById( composerMapId ); } else { mComposerMap = 0; } if ( mComposerMap ) { //if we have found a valid map item, listen out to extent changes on it and refresh the table connect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( refreshAttributes() ) ); } //vector layer QString layerId = itemElem.attribute( "vectorLayer", "not_existing" ); if ( layerId == "not_existing" ) { mVectorLayer = 0; } else { QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerId ); if ( ml ) { mVectorLayer = dynamic_cast<QgsVectorLayer*>( ml ); } } //connect to new layer connect( sourceLayer(), SIGNAL( layerModified() ), this, SLOT( refreshAttributes() ) ); refreshAttributes(); emit changed(); return true; }
bool QgsComposerAttributeTable::readXML( const QDomElement& itemElem, const QDomDocument& doc ) { if ( itemElem.isNull() ) { return false; } //read general table properties if ( !tableReadXML( itemElem, doc ) ) { return false; } mShowOnlyVisibleFeatures = itemElem.attribute( "showOnlyVisibleFeatures", "1" ).toInt(); mFilterFeatures = itemElem.attribute( "filterFeatures", "false" ) == "true" ? true : false; mFeatureFilter = itemElem.attribute( "featureFilter", "" ); //composer map int composerMapId = itemElem.attribute( "composerMap", "-1" ).toInt(); if ( composerMapId == -1 ) { mComposerMap = 0; } if ( composition() ) { mComposerMap = composition()->getComposerMapById( composerMapId ); } else { mComposerMap = 0; } if ( mComposerMap ) { //if we have found a valid map item, listen out to extent changes on it and refresh the table QObject::connect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( refreshAttributes() ) ); } //vector layer QString layerId = itemElem.attribute( "vectorLayer", "not_existing" ); if ( layerId == "not_existing" ) { mVectorLayer = 0; } else { QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerId ); if ( ml ) { mVectorLayer = dynamic_cast<QgsVectorLayer*>( ml ); if ( mVectorLayer ) { //if we have found a valid vector layer, listen for modifications on it and refresh the table QObject::connect( mVectorLayer, SIGNAL( layerModified() ), this, SLOT( refreshAttributes() ) ); } } } //restore display attribute map. This is required to upgrade pre 2.4 projects. QSet<int> displayAttributes; QDomNodeList displayAttributeList = itemElem.elementsByTagName( "displayAttributes" ); if ( displayAttributeList.size() > 0 ) { QDomElement displayAttributesElem = displayAttributeList.at( 0 ).toElement(); QDomNodeList attributeEntryList = displayAttributesElem.elementsByTagName( "attributeEntry" ); for ( int i = 0; i < attributeEntryList.size(); ++i ) { QDomElement attributeEntryElem = attributeEntryList.at( i ).toElement(); int index = attributeEntryElem.attribute( "index", "-1" ).toInt(); if ( index != -1 ) { displayAttributes.insert( index ); } } setDisplayAttributes( displayAttributes, false ); } //restore alias map. This is required to upgrade pre 2.4 projects. QMap<int, QString> fieldAliasMap; QDomNodeList aliasMapNodeList = itemElem.elementsByTagName( "attributeAliasMap" ); if ( aliasMapNodeList.size() > 0 ) { QDomElement attributeAliasMapElem = aliasMapNodeList.at( 0 ).toElement(); QDomNodeList aliasMepEntryList = attributeAliasMapElem.elementsByTagName( "aliasEntry" ); for ( int i = 0; i < aliasMepEntryList.size(); ++i ) { QDomElement aliasEntryElem = aliasMepEntryList.at( i ).toElement(); int key = aliasEntryElem.attribute( "key", "-1" ).toInt(); QString value = aliasEntryElem.attribute( "value", "" ); fieldAliasMap.insert( key, value ); } restoreFieldAliasMap( fieldAliasMap ); } //restore sort columns. This is required to upgrade pre 2.4 projects. QDomElement sortColumnsElem = itemElem.firstChildElement( "sortColumns" ); if ( !sortColumnsElem.isNull() && mVectorLayer ) { QDomNodeList columns = sortColumnsElem.elementsByTagName( "column" ); const QgsFields& fields = mVectorLayer->pendingFields(); for ( int i = 0; i < columns.size(); ++i ) { QDomElement columnElem = columns.at( i ).toElement(); int attribute = columnElem.attribute( "index" ).toInt(); Qt::SortOrder order = columnElem.attribute( "ascending" ) == "true" ? Qt::AscendingOrder : Qt::DescendingOrder; //find corresponding column QList<QgsComposerTableColumn*>::iterator columnIt = mColumns.begin(); for ( ; columnIt != mColumns.end(); ++columnIt ) { if (( *columnIt )->attribute() == fields[attribute].name() ) { ( *columnIt )->setSortByRank( i + 1 ); ( *columnIt )->setSortOrder( order ); break; } } } } //must be done here because tableReadXML->setSceneRect changes mMaximumNumberOfFeatures mMaximumNumberOfFeatures = itemElem.attribute( "maxFeatures", "5" ).toInt(); refreshAttributes(); emit itemChanged(); return true; }
void QgsComposerTable::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget ) { Q_UNUSED( itemStyle ); Q_UNUSED( pWidget ); if ( !painter ) { return; } if ( mComposition->plotStyle() == QgsComposition::Print || mComposition->plotStyle() == QgsComposition::Postscript ) { //exporting composition, so force an attribute refresh //we do this in case vector layer has changed via an external source (eg, another database user) refreshAttributes(); } drawBackground( painter ); painter->save(); //antialiasing on painter->setRenderHint( QPainter::Antialiasing, true ); painter->setPen( Qt::SolidLine ); //now draw the text double currentX = mGridStrokeWidth; double currentY; QList<QgsComposerTableColumn*>::const_iterator columnIt = mColumns.constBegin(); int col = 0; double cellHeaderHeight = fontAscentMillimeters( mHeaderFont ) + 2 * mLineTextDistance; double cellBodyHeight = fontAscentMillimeters( mContentFont ) + 2 * mLineTextDistance; QRectF cell; for ( ; columnIt != mColumns.constEnd(); ++columnIt ) { currentY = mGridStrokeWidth; currentX += mLineTextDistance; cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], cellHeaderHeight ); //calculate alignment of header Qt::AlignmentFlag headerAlign = Qt::AlignLeft; switch ( mHeaderHAlignment ) { case FollowColumn: headerAlign = ( *columnIt )->hAlignment(); break; case HeaderLeft: headerAlign = Qt::AlignLeft; break; case HeaderCenter: headerAlign = Qt::AlignHCenter; break; case HeaderRight: headerAlign = Qt::AlignRight; break; } drawText( painter, cell, ( *columnIt )->heading(), mHeaderFont, headerAlign, Qt::AlignVCenter, Qt::TextDontClip ); currentY += cellHeaderHeight; currentY += mGridStrokeWidth; //draw the attribute values QList<QgsAttributeMap>::const_iterator attIt = mAttributeMaps.begin(); for ( ; attIt != mAttributeMaps.end(); ++attIt ) { cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], cellBodyHeight ); const QgsAttributeMap ¤tAttributeMap = *attIt; QString str = currentAttributeMap[ col ].toString(); drawText( painter, cell, str, mContentFont, ( *columnIt )->hAlignment(), Qt::AlignVCenter, Qt::TextDontClip ); currentY += cellBodyHeight; currentY += mGridStrokeWidth; } currentX += mMaxColumnWidthMap[ col ]; currentX += mLineTextDistance; currentX += mGridStrokeWidth; col++; } //and the borders if ( mShowGrid ) { QPen gridPen; gridPen.setWidthF( mGridStrokeWidth ); gridPen.setColor( mGridColor ); gridPen.setJoinStyle( Qt::MiterJoin ); painter->setPen( gridPen ); drawHorizontalGridLines( painter, mAttributeMaps.size() ); drawVerticalGridLines( painter, mMaxColumnWidthMap ); } painter->restore(); //draw frame and selection boxes if necessary drawFrame( painter ); if ( isSelected() ) { drawSelectionBoxes( painter ); } }
void QgsComposerTableV2::render( QPainter *p, const QRectF &, const int frameIndex ) { if ( !p ) { return; } bool emptyTable = mTableContents.length() == 0; if ( emptyTable && mEmptyTableMode == QgsComposerTableV2::HideTable ) { //empty table set to hide table mode, so don't draw anything return; } if ( mComposition->plotStyle() == QgsComposition::Print || mComposition->plotStyle() == QgsComposition::Postscript ) { //exporting composition, so force an attribute refresh //we do this in case vector layer has changed via an external source (eg, another database user) refreshAttributes(); } //calculate which rows to show in this frame QPair< int, int > rowsToShow = rowRange( frameIndex ); double gridSize = mShowGrid ? mGridStrokeWidth : 0; double cellHeaderHeight = QgsComposerUtils::fontAscentMM( mHeaderFont ) + 2 * mCellMargin; double cellBodyHeight = QgsComposerUtils::fontAscentMM( mContentFont ) + 2 * mCellMargin; QRectF cell; //calculate whether a header is required bool drawHeader = (( mHeaderMode == QgsComposerTableV2::FirstFrame && frameIndex < 1 ) || ( mHeaderMode == QgsComposerTableV2::AllFrames ) ); //calculate whether drawing table contents is required bool drawContents = !( emptyTable && mEmptyTableMode == QgsComposerTableV2::ShowMessage ); int numberRowsToDraw = rowsToShow.second - rowsToShow.first; int numberEmptyRows = 0; if ( drawContents && mShowEmptyRows ) { numberRowsToDraw = rowsVisible( frameIndex, rowsToShow.first, true ); numberEmptyRows = numberRowsToDraw - rowsToShow.second + rowsToShow.first; } bool mergeCells = false; if ( emptyTable && mEmptyTableMode == QgsComposerTableV2::ShowMessage ) { //draw a merged row for the empty table message numberRowsToDraw++; rowsToShow.second++; mergeCells = true; } p->save(); //antialiasing on p->setRenderHint( QPainter::Antialiasing, true ); //draw the text p->setPen( Qt::SolidLine ); double currentX = gridSize; double currentY = gridSize; if ( drawHeader ) { //draw the headers int col = 0; Q_FOREACH ( const QgsComposerTableColumn* column, mColumns ) { //draw background p->save(); p->setPen( Qt::NoPen ); p->setBrush( backgroundColor( -1, col ) ); p->drawRect( QRectF( currentX, currentY, mMaxColumnWidthMap[col] + 2 * mCellMargin, cellHeaderHeight ) ); p->restore(); currentX += mCellMargin; Qt::TextFlag textFlag = static_cast< Qt::TextFlag >( 0 ); if ( column->width() <= 0 ) { //automatic column width, so we use the Qt::TextDontClip flag when drawing contents, as this works nicer for italicised text //which may slightly exceed the calculated width //if column size was manually set then we do apply text clipping, to avoid painting text outside of columns width textFlag = Qt::TextDontClip; } cell = QRectF( currentX, currentY, mMaxColumnWidthMap[col], cellHeaderHeight ); //calculate alignment of header Qt::AlignmentFlag headerAlign = Qt::AlignLeft; switch ( mHeaderHAlignment ) { case FollowColumn: headerAlign = column->hAlignment(); break; case HeaderLeft: headerAlign = Qt::AlignLeft; break; case HeaderCenter: headerAlign = Qt::AlignHCenter; break; case HeaderRight: headerAlign = Qt::AlignRight; break; } QgsComposerUtils::drawText( p, cell, column->heading(), mHeaderFont, mHeaderFontColor, headerAlign, Qt::AlignVCenter, textFlag ); currentX += mMaxColumnWidthMap[ col ]; currentX += mCellMargin; currentX += gridSize; col++; } currentY += cellHeaderHeight; currentY += gridSize; }
void QgsComposerTextTableV2::setContents( const QList<QStringList>& contents ) { mRowText = contents; refreshAttributes(); }
void QgsComposerTextTableV2::addRow( const QStringList& row ) { mRowText.append( row ); refreshAttributes(); }