////////////////////////////////////////////////////////////////////////////// // Calculate the size the remaining table needs // // Parameters // rect [out] - used space for display of table // // TODO // Redisplay of headers columns and rows not calculated. // ////////////////////////////////////////////////////////////////////////////// void CrossTab::CalculateTableSize(QRect& rect) { // Calculate columns { int width(1); CrossTabColumnIndex::iterator columnIt(m_columnIndex.begin()); for (int j=0 ; columnIt != m_columnIndex.end() ; ++j, ++columnIt) { // Keep header in mind Keep iteration in mind if ((m_rowHeaderEachPage && (j==0)) || ((j >= m_columnIndexStored))) { // Calculate new size and index width += columnIt.value().m_columnMaxWidth + m_cellLeftMargin + m_cellRightMargin; } } rect.setWidth(width); } // Calculate rows { int height(1); CrossTabRowIndex::iterator rowIt(m_rowIndex.begin()); for (int i=0 ; rowIt != m_rowIndex.end() ; ++i, ++rowIt) { // Keep header in mind Keep iteration in mind if ((m_columnHeaderEachPage && (i==0)) || (i >= m_rowIndexStored)) { // Calculate new size and index height += rowIt.value().m_rowMaxHeight + m_cellTopMargin + m_cellBottomMargin; } } rect.setHeight(height); } }
////////////////////////////////////////////////////////////////////////////// // draw ////////////////////////////////////////////////////////////////////////////// void CrossTab::Draw(QPainter & paint) { paint.save(); // Calculate the number of rows and columns that we can display int lastColumn(0); int lastRow(0); CalculateDisplayedRowsAndColumns(lastColumn, lastRow, m_rect); paint.drawRect(m_rect); QRect sampleRect(0,0,0,0); // Name itemRectangle QRect saveRect(0,0,0,0); int idRow=m_rowIndexStored; int idCol=m_columnIndexStored; // Start at the correct place CrossTabRowIndex::iterator rowIt(m_rowIndex.begin()); CrossTabColumnIndex::iterator columnIt(m_columnIndex.begin()); for (idRow = 0, rowIt = m_rowIndex.begin() ; ((idRow <= lastRow) && (rowIt != m_rowIndex.end())); ++idRow, ++rowIt) { // Should this row cell be displayed // Skip header column if not wanted if ( ((0 == idRow) && (0 != m_rowIndexStored) && !m_columnHeaderEachPage) || //Skip already displayed rows ((0 < idRow) && (idRow < m_rowIndexStored)) || //Skip rows that are not part of the already drawn table part (m_tableWrapDisplayAllColumnsFirst && (0 < idRow) && (idRow > m_rowIndexStoredLast) && (0 != m_columnIndexStored)) ) { continue; } for (idCol = 0, columnIt = m_columnIndex.begin() ; ((idCol <= lastColumn) && (columnIt != m_columnIndex.end())); ++idCol, ++columnIt) { // Should this column cell be displayed // Skip header row if not wanted if (((0 == idCol) && (0 != m_columnIndexStored) && !m_rowHeaderEachPage) || // Skip already displayed columns ((0 < idCol) && (idCol < m_columnIndexStored))) { continue; } // Get width of this column QString dataTekst (columnIt.key()); sampleRect.setWidth (columnIt.value().m_columnMaxWidth + m_cellLeftMargin + m_cellRightMargin); sampleRect.setHeight (rowIt.value().m_rowMaxHeight + m_cellTopMargin + m_cellBottomMargin); // Save rectangle saveRect = sampleRect; paint.setBackgroundMode(Qt::OpaqueMode); // Draw headers row if (idRow == 0) { paint.setBrush(QBrush(QColor(0, 0, 255, 127), Qt::SolidPattern)); } // Header column else if ((idRow != 0) && (idCol == 0)) { // Odd rows if ((idRow%2) != 0 ) { paint.setBrush(QBrush(QColor(0, 0, 255, 200), Qt::SolidPattern)); } // Even rows else { paint.setBrush(QBrush(QColor(90, 210, 255, 150), Qt::SolidPattern)); } } // Values else if ((idRow != 0) && (idCol != 0)) { // Odd rows if ((idRow%2) != 0 ) { paint.setBrush(QBrush(QColor(0, 0, 0, 0), Qt::SolidPattern)); } // Even rows else { paint.setBrush(QBrush(QColor(90, 210, 255, 127), Qt::SolidPattern)); } } // Draw rectangle paint.drawRect(sampleRect); paint.setBackgroundMode(Qt::TransparentMode); paint.setPen(Qt::SolidLine); // Skip margins: Adjust rectangle for data insertion sampleRect.setX(sampleRect.x() + m_cellLeftMargin); sampleRect.setY(sampleRect.y() + m_cellTopMargin); sampleRect.setWidth (columnIt.value().m_columnMaxWidth); sampleRect.setHeight (rowIt.value().m_rowMaxHeight); // get Font QFontMetrics fm(GetFont()); QRect dataRect; // Header if ((idRow == 0) && (idCol == 0)) { // Do nothing } // Headerrow else if ((idRow == 0) && (idCol != 0)) { dataRect = fm.boundingRect(sampleRect, m_hAlignMap["column"] | m_vAlignMap["column"], columnIt.key()); paint.drawText(dataRect, m_hAlignMap["column"] | m_vAlignMap["column"], columnIt.key()); } // Headercol else if ((idCol == 0) && (idRow != 0)) { dataRect = fm.boundingRect(sampleRect, m_hAlignMap["row"] | m_vAlignMap["row"], rowIt.key()); paint.drawText(dataRect, m_hAlignMap["row"] | m_vAlignMap["row"], rowIt.key()); } // Value else { dataRect = fm.boundingRect(sampleRect, m_hAlignMap["value"] | m_vAlignMap["value"], GetValue(columnIt.key(), rowIt.key())); paint.drawText(dataRect, m_hAlignMap["value"] | m_vAlignMap["value"], GetValue(columnIt.key(), rowIt.key())); } // Restore rectangle sampleRect = saveRect; sampleRect.setX(sampleRect.x() + sampleRect.width()); } // end for // Reset basic column id idCol = m_columnIndexStored; // Adjust item display rectangle sampleRect.setY(sampleRect.y()+sampleRect.height()); sampleRect.setX(0); } // Store indexes for iterative purpose m_rowIndexStored = lastRow + 1; m_columnIndexStored = lastColumn + 1; // Now that we are done return the paint device back to the state // it was when we started to mess with it paint.restore(); }
////////////////////////////////////////////////////////////////////////////// // Calculate the last index of column and row that can be displayed // // Parameters // lastColumn [out] - last column Id that can be displayed // lastRow [out] - last row Id that can be displayed // rect [in] - available space for display of table // [out] - used space for display of table // // TODO: Width and height initialised with 2 which is the border of the table. // There is no way to change the border/inner line of the table. // Thus assumed 1 pixel. ////////////////////////////////////////////////////////////////////////////// void CrossTab::CalculateDisplayedRowsAndColumns(int& lastColumn, int& lastRow, QRect& rect) { // Keep interation in mind lastColumn = m_columnIndexStored; lastRow = m_rowIndexStored; // Calculate columns { int width(1); bool filled(false); CrossTabColumnIndex::iterator columnIt(m_columnIndex.begin()); for (int j=0 ; !filled && (columnIt != m_columnIndex.end()); ++j, ++columnIt) { // Keep header in mind Keep iteration in mind if ((m_rowHeaderEachPage && (j==0)) || (j >= m_columnIndexStored)) { // Calculate new size and index width += columnIt.value().m_columnMaxWidth + m_cellLeftMargin + m_cellRightMargin; lastColumn = j; // Exceeding the size if (width > rect.width()) { // Revert and stop lastColumn = j-1; width -= (columnIt.value().m_columnMaxWidth + m_cellLeftMargin + m_cellRightMargin); filled = true; } } } rect.setWidth(width); } // Calculate rows { int height(1); bool filled(false); CrossTabRowIndex::iterator rowIt(m_rowIndex.begin()); for (int i=0 ; !filled && (rowIt != m_rowIndex.end()); ++i, ++rowIt) { // If the table was wrapped to a new page we should not print more rows // than the first part of the table if (m_tableWrapDisplayAllColumnsFirst && (i >= m_rowIndexStoredLast) && (0 != m_columnIndexStored)) { break; } // Keep header in mind Keep iteration in mind if ((m_columnHeaderEachPage && (i==0)) || (i >= m_rowIndexStored)) { // Calculate new size and index height += rowIt.value().m_rowMaxHeight + m_cellTopMargin + m_cellBottomMargin; lastRow = i; // Exceeding the size if (height > rect.height()) { // Revert and stop lastRow = i-1; height -= (rowIt.value().m_rowMaxHeight + m_cellTopMargin + m_cellBottomMargin); filled = true; } } } rect.setHeight(height); } }
void ByteArrayColumnViewPrivate::updateChanged() { Q_Q( ByteArrayColumnView ); const int xOffset = q->xOffset(); const PixelXRange Xs = PixelXRange::fromWidth( xOffset, q->visibleWidth() ); // do updates in offset column const LineRange changedOffsetLines = mTableRanges->changedOffsetLines(); if( !changedOffsetLines.isEmpty() ) q->updateColumn( *mOffsetColumn, changedOffsetLines ); // collect affected buffer columns QList<AbstractByteArrayColumnRenderer*> dirtyColumns; AbstractByteArrayColumnRenderer *column = mValueColumn; while( true ) { if( column->isVisible() && column->overlaps(Xs) ) { dirtyColumns.append( column ); column->prepareRendering( Xs ); } if( column == mCharColumn ) break; column = mCharColumn; } // any columns to paint? if( dirtyColumns.size() > 0 ) { // calculate affected lines/indizes const LinePositionRange fullPositions( 0, mTableLayout->noOfBytesPerLine()-1 ); CoordRange visibleRange( fullPositions, q->visibleLines() ); const int lineHeight = q->lineHeight(); CoordRange changedRange; // as there might be multiple selections on this line redo until no more is changed while( getNextChangedRange(&changedRange,visibleRange) ) { PixelY cy = q->yOffsetOfLine( changedRange.start().line() ); QListIterator<AbstractByteArrayColumnRenderer*> columnIt( dirtyColumns ); // only one line? if( changedRange.start().line() == changedRange.end().line() ) { const LinePositionRange changedPositions( changedRange.start().pos(), changedRange.end().pos() ); while( columnIt.hasNext() ) { const PixelXRange xPixels = columnIt.next()->xsOfLinePositionsInclSpaces( changedPositions ); q->viewport()->update( xPixels.start()-xOffset, cy, xPixels.width(), lineHeight ); } } // else { // first line const LinePositionRange firstChangedPositions( changedRange.start().pos(), fullPositions.end() ); while( columnIt.hasNext() ) { const PixelXRange XPixels = columnIt.next()->xsOfLinePositionsInclSpaces( firstChangedPositions ); q->viewport()->update( XPixels.start()-xOffset, cy, XPixels.width(), lineHeight ); } // at least one full line? for( int l = changedRange.start().line()+1; l < changedRange.end().line(); ++l ) { cy += lineHeight; columnIt.toFront(); while( columnIt.hasNext() ) { const PixelXRange XPixels = columnIt.next()->xsOfLinePositionsInclSpaces( fullPositions ); q->viewport()->update( XPixels.start()-xOffset, cy, XPixels.width(), lineHeight ); } } // last line cy += lineHeight; columnIt.toFront(); const LinePositionRange lastChangedPositions( fullPositions.start(), changedRange.end().pos() ); while( columnIt.hasNext() ) { const PixelXRange XPixels = columnIt.next()->xsOfLinePositionsInclSpaces( lastChangedPositions ); q->viewport()->update( XPixels.start()-xOffset, cy, XPixels.width(), lineHeight ); } } // continue the search at the overnext index visibleRange.setStart( changedRange.end()+1 ); //+2 ); TODO: currently bounding ranges are not merged if( !visibleRange.isValid() ) break; } } mTableRanges->resetChangedRanges(); }