You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2944 lines
106 KiB
2944 lines
106 KiB
/*
|
|
Copyright (C) 2001, S.R.Haque (srhaque@iee.org).
|
|
This file is part of the KDE project
|
|
Copyright (C) 2005 Thomas Zander <zander@kde.org>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
DESCRIPTION
|
|
|
|
This file implements KWord tables.
|
|
*/
|
|
|
|
// ### TODO : multi page tables
|
|
|
|
#include "KWTableFrameSet.h"
|
|
#include "KWDocument.h"
|
|
#include "KWAnchor.h"
|
|
#include "KWCanvas.h"
|
|
#include "KWCommand.h"
|
|
#include "KWViewMode.h"
|
|
#include "KWView.h"
|
|
#include "KWordFrameSetIface.h"
|
|
#include "KWordTableFrameSetIface.h"
|
|
#include "KWFrameList.h"
|
|
#include "KWPageManager.h"
|
|
#include "KWPage.h"
|
|
#include "KWOasisSaver.h"
|
|
|
|
#include <KoOasisContext.h>
|
|
#include <KoXmlWriter.h>
|
|
#include <KoDom.h>
|
|
#include <KoXmlNS.h>
|
|
#include <KoTextObject.h> // for customItemChar !
|
|
#include <KoTextParag.h>
|
|
|
|
#include <tdemessagebox.h>
|
|
#include <kdebug.h>
|
|
#include <tdelocale.h>
|
|
#include <dcopobject.h>
|
|
#include <tqapplication.h>
|
|
#include <tqpopupmenu.h>
|
|
#include <tqclipboard.h>
|
|
|
|
|
|
KWTableFrameSet::KWTableFrameSet( KWDocument *doc, const TQString & name ) :
|
|
KWFrameSet( doc )
|
|
{
|
|
m_rows = m_cols = m_nr_cells = 0;
|
|
m_name = TQString();
|
|
m_active = true;
|
|
m_frames.setAutoDelete(false);
|
|
if ( name.isEmpty() )
|
|
m_name = doc->generateFramesetName( i18n( "Table %1" ) );
|
|
else
|
|
m_name = name;
|
|
}
|
|
|
|
KWTableFrameSet::~KWTableFrameSet()
|
|
{
|
|
m_doc = 0L;
|
|
}
|
|
|
|
KWordFrameSetIface* KWTableFrameSet::dcopObject()
|
|
{
|
|
if ( !m_dcop )
|
|
m_dcop = new KWordTableFrameSetIface( this );
|
|
|
|
return m_dcop;
|
|
}
|
|
|
|
|
|
KWFrameSetEdit * KWTableFrameSet::createFrameSetEdit( KWCanvas * canvas )
|
|
{
|
|
return new KWTableFrameSetEdit( this, canvas );
|
|
}
|
|
|
|
void KWTableFrameSet::updateFrames( int flags )
|
|
{
|
|
for(TableIter c(this); c; ++c)
|
|
c.current()->updateFrames( flags );
|
|
if ( isFloating() ) {
|
|
KWAnchor * anchor = findAnchor( 0 );
|
|
if ( anchor )
|
|
anchor->resize();
|
|
}
|
|
|
|
KWFrameSet::updateFrames( flags );
|
|
}
|
|
|
|
void KWTableFrameSet::moveFloatingFrame( int /*frameNum TODO */, const KoPoint &position )
|
|
{
|
|
// TODO multi-page case
|
|
|
|
double dx = position.x() - m_colPositions[0];
|
|
double dy = position.y() - m_rowPositions[0];
|
|
|
|
KWTableFrameSet::Cell *daCell = cell(0,0);
|
|
Q_ASSERT(daCell);
|
|
if (! daCell) return; //hack to work around https://bugs.kde.org/show_bug.cgi?id=67216
|
|
int oldPageNumber = daCell->frame(0)->pageNumber();
|
|
// TODO multi-page case
|
|
|
|
moveBy( dx, dy );
|
|
|
|
if ( dx || dy ) {
|
|
updateFrames();
|
|
cell(0,0)->frame(0)->frameStack()->updateAfterMove( oldPageNumber );
|
|
}
|
|
}
|
|
|
|
KoSize KWTableFrameSet::floatingFrameSize( int /*frameNum*/ )
|
|
{
|
|
return boundingRect().size();
|
|
}
|
|
|
|
KCommand * KWTableFrameSet::anchoredObjectCreateCommand( int /*frameNum*/ )
|
|
{
|
|
return new KWCreateTableCommand( i18n("Create Table"), this );
|
|
}
|
|
|
|
KCommand * KWTableFrameSet::anchoredObjectDeleteCommand( int /*frameNum*/ )
|
|
{
|
|
return new KWDeleteTableCommand( i18n("Delete Table"), this );
|
|
}
|
|
|
|
KWAnchor * KWTableFrameSet::createAnchor( KoTextDocument *txt, int frameNum )
|
|
{
|
|
//kdDebug(32004) << "KWTableFrameSet::createAnchor" << endl;
|
|
return new KWAnchor( txt, this, frameNum );
|
|
}
|
|
|
|
void KWTableFrameSet::createAnchors( KoTextParag * parag, int index, bool placeHolderExists /*= false */ /*only used when loading*/,
|
|
bool repaint )
|
|
{
|
|
//kdDebug(32004) << "KWTableFrameSet::createAnchors" << endl;
|
|
// TODO make one rect per page, and create one anchor per page
|
|
// Anchor this frame, after the previous one
|
|
KWAnchor * anchor = createAnchor( m_anchorTextFs->textDocument(), 0 );
|
|
if ( !placeHolderExists )
|
|
parag->insert( index, KoTextObject::customItemChar() );
|
|
parag->setCustomItem( index, anchor, 0 );
|
|
kdDebug(32004) << "KWTableFrameSet::createAnchors setting anchor" << endl;
|
|
parag->setChanged( true );
|
|
if ( repaint )
|
|
emit repaintChanged( m_anchorTextFs );
|
|
}
|
|
|
|
void KWTableFrameSet::deleteAnchors()
|
|
{
|
|
KWAnchor * anchor = findAnchor( 0 );
|
|
kdDebug(32004) << "KWTableFrameSet::deleteAnchors anchor=" << anchor << endl;
|
|
deleteAnchor( anchor );
|
|
}
|
|
|
|
|
|
void KWTableFrameSet::addCell( Cell* daCell ) // called add but also used to 'update'
|
|
{
|
|
m_rows = kMax( daCell->rowAfter(), m_rows );
|
|
m_cols = kMax( daCell->columnAfter(), m_cols );
|
|
|
|
if ( m_rowArray.size() < daCell->rowAfter() )
|
|
m_rowArray.resize( daCell->rowAfter() );
|
|
for ( uint row = daCell->firstRow() ;row < daCell->rowAfter(); ++row )
|
|
{
|
|
if ( !m_rowArray[ row ] )
|
|
m_rowArray.insert( row, new Row );
|
|
m_rowArray[ row ]->addCell( daCell );
|
|
}
|
|
}
|
|
|
|
void KWTableFrameSet::removeCell( Cell* daCell )
|
|
{
|
|
for ( uint row = daCell->firstRow() ; row < daCell->rowAfter(); ++row )
|
|
m_rowArray[ row ]->removeCell( daCell );
|
|
}
|
|
|
|
void KWTableFrameSet::insertRowVector(uint index, Row *r)
|
|
{
|
|
if(m_rowArray.size() < m_rowArray.count() + 1)
|
|
m_rowArray.resize(m_rowArray.count() + 1);
|
|
|
|
for(uint i = m_rowArray.count(); i > index; i--)
|
|
m_rowArray.insert(i, m_rowArray[i-1]);
|
|
|
|
m_rowArray.insert(index, r);
|
|
}
|
|
|
|
/*
|
|
* Inserts a new (empty) element into each row vector.
|
|
* Elements in a row vector after index are moved back.
|
|
*/
|
|
void KWTableFrameSet::insertEmptyColumn(uint index)
|
|
{
|
|
for(uint i = 0; i < m_rowArray.count(); ++i) {
|
|
Row *r = m_rowArray[i];
|
|
if(r->m_cellArray.size() < m_cols + 1)
|
|
r->m_cellArray.resize(m_cols + 1);
|
|
for(int j = m_cols - 1; j >= (int)index; --j)
|
|
r->m_cellArray.insert(j + 1, r->m_cellArray[j]);
|
|
r->m_cellArray.insert(index, 0);
|
|
}
|
|
}
|
|
|
|
KWTableFrameSet::Row*
|
|
KWTableFrameSet::removeRowVector(uint index)
|
|
{
|
|
Q_ASSERT(index < m_rowArray.count() );
|
|
Row *ret = m_rowArray.at(index);
|
|
Row *r;
|
|
for(uint i = index; i < m_rowArray.size() - 1; ++i){
|
|
r = m_rowArray.at(i+1);
|
|
m_rowArray.remove(i+1);
|
|
m_rowArray.insert(i,r);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
KoRect KWTableFrameSet::boundingRect() {
|
|
KoRect outerRect(m_colPositions[0], // left
|
|
m_rowPositions[0], // top
|
|
m_colPositions.last()-m_colPositions[0], // width
|
|
m_rowPositions.last()-m_rowPositions[0]);// height
|
|
|
|
// Add 1 'pixel' (at current zoom level) like KWFrame::outerKoRect(),
|
|
// to avoid that the bottom line disappears due to rounding problems
|
|
// (i.e. that it doesn't fit in the calculated paragraph height in pixels,
|
|
// which depends on the paragraph's Y position)
|
|
// Better have one pixel too much (caret looks too big by one pixel)
|
|
// than one missing (bottom line of cell not painted)
|
|
outerRect.rRight() += m_doc->zoomItX( 1 ) / m_doc->zoomedResolutionX();
|
|
outerRect.rBottom() += m_doc->zoomItY( 1 ) / m_doc->zoomedResolutionY();
|
|
|
|
return outerRect;
|
|
|
|
}
|
|
|
|
double KWTableFrameSet::topWithoutBorder()
|
|
{
|
|
double top = 0.0;
|
|
for (uint i = 0; i < getColumns(); i++)
|
|
{
|
|
KWTableFrameSet::Cell *daCell = cell( 0, i );
|
|
top = kMax( top, m_rowPositions[0] + daCell->topBorder() );
|
|
}
|
|
return top;
|
|
}
|
|
|
|
|
|
double KWTableFrameSet::leftWithoutBorder()
|
|
{
|
|
double left = 0.0;
|
|
for (uint i=0; i < getRows(); i++)
|
|
{
|
|
KWTableFrameSet::Cell *daCell = cell( i, 0 );
|
|
left = kMax( left, m_colPositions[0] + daCell->leftBorder() );
|
|
}
|
|
return left;
|
|
}
|
|
|
|
/* returns the cell that occupies row, col. */
|
|
KWTableFrameSet::Cell *KWTableFrameSet::cell( unsigned int row, unsigned int col ) const
|
|
{
|
|
if ( row < m_rowArray.size() && col < m_rowArray[row]->size() ) {
|
|
Cell* cell = (*m_rowArray[row])[col];
|
|
if ( cell )
|
|
return cell;
|
|
}
|
|
// kdWarning() << name() << " cell " << row << "," << col << " => returning 0!" << kdBacktrace( 3 ) << endl;
|
|
//#ifndef NDEBUG
|
|
// validate();
|
|
// printArrayDebug();
|
|
//#endif
|
|
return 0L;
|
|
}
|
|
|
|
KWTableFrameSet::Cell *KWTableFrameSet::cellByPos( double x, double y ) const
|
|
{
|
|
KWFrame *f = frameAtPos(x,y);
|
|
if(f) return static_cast<KWTableFrameSet::Cell *> (f->frameSet());
|
|
return 0L;
|
|
}
|
|
|
|
void KWTableFrameSet::recalcCols(unsigned int col,unsigned int row) {
|
|
if(col >= getColumns())
|
|
col = getColumns()-1;
|
|
if(row >= getRows())
|
|
row = getRows()-1;
|
|
Cell *activeCell = cell(row,col);
|
|
Q_ASSERT( activeCell );
|
|
if ( !activeCell )
|
|
return;
|
|
double difference = 0;
|
|
|
|
if(activeCell->frame(0)->left() - activeCell->leftBorder() != m_colPositions[activeCell->firstColumn()]) {
|
|
// left border moved.
|
|
col = activeCell->firstRow();
|
|
difference = 0-(activeCell->frame(0)->left() - activeCell->leftBorder() - m_colPositions[activeCell->firstColumn()]);
|
|
}
|
|
|
|
if(activeCell->frame(0)->right() - activeCell->rightBorder() !=
|
|
m_colPositions[activeCell->lastColumn()]) { // right border moved
|
|
|
|
col = activeCell->columnAfter();
|
|
double difference2 = activeCell->frame(0)->right() + activeCell->rightBorder() - m_colPositions[activeCell->columnAfter()];
|
|
|
|
double moved=difference2+difference;
|
|
if(moved > -0.01 && moved < 0.01) { // we were simply moved.
|
|
col=0;
|
|
difference = difference2;
|
|
} else if(difference2!=0)
|
|
difference = difference2;
|
|
}
|
|
|
|
m_redrawFromCol=getColumns(); // possible reposition col starting with this one, done in recalcRows
|
|
if(difference!=0) {
|
|
double last=col==0?0:m_colPositions[col-1];
|
|
for(unsigned int i=col; i < m_colPositions.count(); i++) {
|
|
double &colPos = m_colPositions[i];
|
|
colPos = colPos + difference;
|
|
if(colPos-last < s_minFrameWidth) { // Never make it smaller then allowed!
|
|
difference += s_minFrameWidth - colPos;
|
|
colPos = s_minFrameWidth + last;
|
|
}
|
|
last=colPos;
|
|
}
|
|
m_redrawFromCol=col;
|
|
if(col>0) m_redrawFromCol--;
|
|
//if(activeCell) activeCell->frame(0)->setMinimumFrameHeight(0);
|
|
}
|
|
updateFrames();
|
|
//kdDebug(32004) << "end KWTableFrameSet::recalcCols" << endl;
|
|
}
|
|
|
|
|
|
// Step through the whole table and recalculate the position and size
|
|
// of each cell.
|
|
|
|
void KWTableFrameSet::recalcRows(unsigned int col, unsigned int row) {
|
|
kdDebug(32004) << name() << " KWTableFrameSet::recalcRows ("<< col <<"," << row << ")" << endl;
|
|
//for(unsigned int i=0; i < m_rowPositions.count() ; i++) kdDebug(32004) << "row: " << i << " = " << m_rowPositions[i] << endl;
|
|
|
|
Cell *activeCell = cell(row,col);
|
|
Q_ASSERT( activeCell );
|
|
if ( !activeCell ) // #122807
|
|
return;
|
|
double difference = 0;
|
|
|
|
if(activeCell->frame(0)->height() != activeCell->frame(0)->minimumFrameHeight() &&
|
|
activeCell->type() == FT_TEXT) {
|
|
// when the amount of text changed and the frame has to be rescaled we are also called.
|
|
// lets check the minimum size for all the cells in this row.
|
|
|
|
// Take a square of table cells which depend on each others height. It is always the full
|
|
// width of the table and the height is determined by joined cells, the minimum is one row.
|
|
double minHeightOtherCols=0; // The minimum height which the whole square of table cells can take
|
|
double minHeightActiveRow=0; // The minimum height our cell can get because of cells in his row
|
|
double minHeightMyCol=0; // The minimum height our column can get in the whole square
|
|
unsigned int rowSpan = activeCell->rowSpan();
|
|
unsigned int startRow = activeCell->firstRow();
|
|
for (uint colCount = 0; colCount < getColumns(); ++colCount )
|
|
{
|
|
// for each column
|
|
unsigned int rowCount=startRow;
|
|
double thisColHeight=0; // the total height of this column
|
|
double thisColActiveRow=0; // the total height of all cells in this col, completely in the
|
|
// row of the activeCell
|
|
do { // for each row (under startRow)
|
|
Cell *thisCell=cell(rowCount,colCount);
|
|
if ( !thisCell )
|
|
break; // ###
|
|
if(thisCell->firstRow() < startRow) { // above -> set startRow and restart
|
|
rowSpan += startRow - thisCell->firstRow();
|
|
startRow = thisCell->firstRow();
|
|
break;
|
|
}
|
|
if(thisCell->rowAfter() > startRow + rowSpan) {
|
|
rowSpan = thisCell->rowAfter() - startRow;
|
|
break;
|
|
}
|
|
|
|
thisColHeight+=thisCell->frame(0)->minimumFrameHeight();
|
|
thisColHeight+=thisCell->topBorder();
|
|
thisColHeight+=thisCell->bottomBorder();
|
|
|
|
if(thisCell->firstRow() >= activeCell->firstRow() && thisCell->rowAfter() <= activeCell->rowAfter())
|
|
thisColActiveRow+=thisCell->frame(0)->minimumFrameHeight();
|
|
|
|
rowCount += thisCell->rowSpan();
|
|
} while (rowCount < rowSpan+startRow);
|
|
|
|
if(colCount >= activeCell->firstColumn() &&
|
|
colCount < activeCell->columnAfter() )
|
|
minHeightMyCol = thisColHeight;
|
|
else {
|
|
minHeightOtherCols = kMax(minHeightOtherCols, thisColHeight);
|
|
minHeightActiveRow = kMax(minHeightActiveRow, thisColActiveRow);
|
|
}
|
|
} // for each column
|
|
|
|
bool bottomRow = (startRow+rowSpan == activeCell->rowAfter());
|
|
if(!bottomRow) {
|
|
Cell *bottomCell=cell(startRow+rowSpan-1, activeCell->firstColumn());
|
|
bottomCell->frame(0)->setHeight(bottomCell->frame(0)->minimumFrameHeight() +
|
|
minHeightOtherCols - minHeightMyCol);
|
|
// ### RECURSE ###
|
|
recalcRows(bottomCell->firstColumn(), bottomCell->firstRow());
|
|
}
|
|
if(activeCell->frame(0)->minimumFrameHeight() > activeCell->frame(0)->height()) { // wants to grow
|
|
activeCell->frame(0)->setHeight(activeCell->frame(0)->minimumFrameHeight());
|
|
//kdDebug(32004) << activeCell->name() << " grew to its minheight: " << activeCell->frame(0)->minimumFrameHeight() << endl;
|
|
} else { // wants to shrink
|
|
double newHeight=kMax(activeCell->frame(0)->minimumFrameHeight(),minHeightActiveRow);
|
|
if(bottomRow) // I'm a strech cell
|
|
newHeight=kMax(newHeight, minHeightOtherCols - (minHeightMyCol - activeCell->frame(0)->minimumFrameHeight()));
|
|
activeCell->frame(0)->setHeight(newHeight);
|
|
//kdDebug(32004) << activeCell->name() << " shrunk to: " << newHeight << endl;
|
|
}
|
|
}
|
|
|
|
if(activeCell->frame(0)->top() - activeCell->topBorder() != getPositionOfRow(activeCell->firstRow())) {
|
|
// top moved.
|
|
row = activeCell->firstRow();
|
|
difference = 0 - (activeCell->frame(0)->top() - activeCell->topBorder() - getPositionOfRow(row));
|
|
}
|
|
|
|
|
|
if(activeCell->frame(0)->bottom() + activeCell->bottomBorder() !=
|
|
getPositionOfRow(activeCell->rowAfter())) { // bottom moved
|
|
|
|
row = activeCell->rowAfter();
|
|
double difference2 = activeCell->frame(0)->bottom() + activeCell->bottomBorder() - getPositionOfRow(row);
|
|
double moved=difference2+difference;
|
|
if(moved > -0.01 && moved < 0.01) { // we were simply moved.
|
|
row=0;
|
|
difference = difference2;
|
|
} else if( difference2!=0)
|
|
difference = difference2;
|
|
}
|
|
|
|
unsigned int fromRow = m_rows; // possible reposition rows starting with this one, default to no repositioning
|
|
unsigned int untilRow=0; // possible reposition rows ending with this one
|
|
if( TQABS( difference ) > 1E-10 ) { // means "difference != 0.0"
|
|
TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
|
|
TQValueList<double>::iterator j = m_rowPositions.begin();
|
|
double last=0.0;
|
|
int lineNumber=-1;
|
|
while(j != m_rowPositions.end()) {
|
|
lineNumber++;
|
|
if(pageBound!=m_pageBoundaries.end()) {
|
|
if((int)*pageBound == lineNumber) { // next page
|
|
if(lineNumber >= (int)row) { // then delete line j
|
|
TQValueList<double>::iterator nextJ = j;
|
|
++nextJ;
|
|
difference -= *(nextJ)-*(j);
|
|
kdDebug(32004) << "Deleting line with old pos: " << *j << endl;
|
|
j=m_rowPositions.remove(j);
|
|
j--;
|
|
TQValueList<unsigned int>::iterator tmp = pageBound;
|
|
++pageBound;
|
|
m_pageBoundaries.remove(tmp);
|
|
j++;
|
|
continue;
|
|
}
|
|
++pageBound;
|
|
lineNumber--;
|
|
}
|
|
}
|
|
if(lineNumber >= (int)row) { // below changed row
|
|
if(*(j)-last < s_minFrameHeight) // Never make it smaller then allowed!
|
|
difference += s_minFrameHeight - *(j) + last;
|
|
last=*(j);
|
|
kdDebug(32004) << "moving " << *(j) << " by " << difference << "; to " << (*j) + difference << endl;
|
|
(*j) += difference; // move line.
|
|
}
|
|
j++;
|
|
}
|
|
fromRow=row;
|
|
if(row>0) fromRow--;
|
|
} else {
|
|
row=0;
|
|
}
|
|
#if 0
|
|
{ TQValueList<unsigned int>::iterator pb = m_pageBoundaries.begin();
|
|
unsigned int i=0;
|
|
double last=0;
|
|
do {
|
|
double cur=m_rowPositions[i];
|
|
if(pb!=m_pageBoundaries.end() && *(pb)==i) {
|
|
kdDebug(32004) << "line: " << i << ": " << cur << " *" << (last>cur?" (ALERT)":"") << endl;
|
|
++pb;
|
|
} else
|
|
kdDebug(32004) << "line: " << i << ": " << cur << (last>cur?" (ALERT)":"") << endl;
|
|
last=cur;
|
|
i++;
|
|
} while( i<m_rowPositions.count());
|
|
}
|
|
#endif
|
|
#if 0 // def SUPPORT_MULTI_PAGE_TABLES
|
|
|
|
//double pageHeight = m_doc->ptPaperHeight() - m_doc->ptBottomBorder() - m_doc->ptTopBorder();
|
|
unsigned int pageNumber=cell(0,0)->frame(0)->pageNumber() +1;
|
|
unsigned int lineNumber=1;
|
|
TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
|
|
TQValueList<double>::iterator j = m_rowPositions.begin();
|
|
|
|
double diff=0.0;
|
|
double pageBottom = pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder();
|
|
// kdDebug(32004) << "pageBottom; " << pageBottom << endl;
|
|
while(++j!=m_rowPositions.end()) { // stuff for multipage tables.
|
|
if(pageBound!=m_pageBoundaries.end() && *pageBound == lineNumber ) {
|
|
if(*j > pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder() ) { // next page marker exists, and is accurate...
|
|
pageNumber++;
|
|
pageBottom = pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder();
|
|
// kdDebug(32004) << "pageBottom; " << pageBottom << endl;
|
|
untilRow=kMax(untilRow, *pageBound);
|
|
pageBound++;
|
|
}
|
|
}
|
|
|
|
//kdDebug() << "checking; " << lineNumber << ", " << (*j) << endl;
|
|
if((*j) + diff > pageBottom) { // a row falls off the page.
|
|
//kdDebug(32004) << "row falls off of page"<< endl;
|
|
untilRow = m_rows;
|
|
bool hugeRow = false;
|
|
unsigned int breakRow = lineNumber-1;
|
|
// find out of no cells are spanning multiple rows meaning we have to break higher.
|
|
#if 0
|
|
// ### TODO: I did not get a chance do debug this yet! TZ.
|
|
for(int i=0; i < getColumns() ; i++) {
|
|
kdDebug() << "i: " << i<< endl;
|
|
Cell *c= cell(breakRow, i);
|
|
kdDebug() << "c: " << c->firstRow() << "," << c->m_col << " w: " << c->columnSpan() << ", h: " << c->rowSpan() << endl;
|
|
if(c->firstRow() < breakRow) {
|
|
breakRow = c->firstRow();
|
|
i=-1;
|
|
}
|
|
}
|
|
kdDebug() << "breakRow: " << breakRow<< endl;
|
|
fromRow=kMin(fromRow, breakRow);
|
|
if(breakRow < lineNumber+1) {
|
|
for(unsigned int i=lineNumber+1; i > breakRow;i--)
|
|
kdDebug() << "j--";
|
|
for(unsigned int i=lineNumber+1; i > breakRow;i--)
|
|
--j;
|
|
lineNumber=breakRow+1;
|
|
}
|
|
|
|
// find out if the next row (the new one on the page) does not contain cells higher then page.
|
|
for(unsigned int i=0; i < getColumns() ; i++) {
|
|
if(cell(breakRow+1,i) && cell(breakRow+1,i)->frame(0)->height() > pageHeight)
|
|
hugeRow=true;
|
|
}
|
|
//if((*pageBound) != breakRow) { // I think that this has to be that way
|
|
// voeg top in in rowPositions
|
|
#endif
|
|
|
|
double topOfPage = m_doc->ptPaperHeight() * pageNumber + m_doc->ptTopBorder();
|
|
|
|
TQValueList<double>::iterator tmp = m_rowPositions.at(breakRow);
|
|
diff += topOfPage - (*tmp); // diff between bottom of last row on page and top of new page
|
|
//kdDebug() << "diff += " << topOfPage << " - " << (*tmp) << ". diff += " << topOfPage - (*tmp) <<" ="<< diff << endl;
|
|
lineNumber++;
|
|
m_rowPositions.insert(j, topOfPage);
|
|
|
|
// insert new pageBound. It points to last LINE on previous page
|
|
pageBound = m_pageBoundaries.insert(pageBound, breakRow);
|
|
//kdDebug(32004) << "inserting new pageBound: " << breakRow << " at " << m_rowPositions[breakRow] << endl;
|
|
pageBound++;
|
|
if(!hugeRow) {
|
|
// add header-rij toe. (en zet bool) TODO
|
|
//j++;
|
|
//lineNumber++;
|
|
// m_hasTmpHeaders = true;
|
|
}
|
|
pageNumber++;
|
|
pageBottom = pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder();
|
|
//kdDebug(32004) << " pageBottom: " << pageBottom << " pageNumber=" << pageNumber << endl;
|
|
if((int)pageNumber > m_doc->numPages()) {
|
|
int num = m_doc->appendPage();
|
|
kdDebug(32004) << "Have appended page: " << num << " (one page mode!)" << endl;
|
|
m_doc->afterInsertPage( num );
|
|
}
|
|
}
|
|
//if(diff > 0) kdDebug(32004) << " adding " << diff << ", line " << lineNumber << " " << *(j) <<" -> " << *(j)+diff << endl;
|
|
if(diff > 0)
|
|
(*j) = (*j) + diff;
|
|
lineNumber++;
|
|
|
|
#if 0 // def SUPPORT_MULTI_PAGE_TABLES
|
|
// Note: produces much ouput!
|
|
int i = 1; // DEBUG
|
|
for ( TQValueList<double>::iterator itDebug = m_rowPositions.begin(); itDebug != m_rowPositions.end(); ++itDebug, ++i )
|
|
{
|
|
kdDebug(32004) << "m_rowPosition[" << i << "]= " << (*itDebug) << endl;
|
|
}
|
|
#endif
|
|
|
|
}
|
|
#endif
|
|
#if 0
|
|
{ TQValueList<unsigned int>::iterator pb = m_pageBoundaries.begin();
|
|
unsigned int i=0;
|
|
double last=0;
|
|
do {
|
|
double cur=m_rowPositions[i];
|
|
if(pb!=m_pageBoundaries.end() && *(pb)==i) {
|
|
kdDebug(32004) << "line: " << i << ": " << cur << " *" << (last>cur?" (ALERT)":"") << endl;
|
|
++pb;
|
|
} else
|
|
kdDebug(32004) << "line: " << i << ": " << cur << (last>cur?" (ALERT)":"") << endl;
|
|
last=cur;
|
|
i++;
|
|
} while( i<m_rowPositions.count());
|
|
}
|
|
#endif
|
|
//for (unsigned int i=0; i < getRows(); kdDebug(32004)<<" pos of row["<<i<<"] = "<<getPositionOfRow(i)<<"/"<<getPositionOfRow(i,true)<<endl,i++);
|
|
//kdDebug () << "Repositioning from row : " << fromRow << " until: " << untilRow << endl;
|
|
//kdDebug () << "Repositioning from col > " << redrawFromCol << endl;
|
|
// do positioning.
|
|
//Cell *cell;
|
|
//bool setMinFrameSize= activeCell->frame(0)->isSelected();
|
|
|
|
#if 0 // def SUPPORT_MULTI_PAGE_TABLES
|
|
for(TableIter cell(this); cell; ++cell) {
|
|
if((cell->rowAfter() > fromRow && cell->firstRow() < untilRow) || cell->columnAfter() > m_redrawFromCol)
|
|
position(cell, (cell==activeCell && cell->frame(0)->isSelected()));
|
|
}
|
|
m_redrawFromCol = getColumns();
|
|
|
|
// check if any rowPosition entries are unused
|
|
|
|
// first create a hash of all row entries
|
|
TQMap<unsigned int,int> rows; // rownr, count
|
|
unsigned int top=m_rowPositions.count() - m_pageBoundaries.count()-1;
|
|
for(unsigned int i=0; i < top; rows[i++]=0);
|
|
|
|
// fill hash with data
|
|
for(TableIter i(this); i; ++i) {
|
|
rows[i->firstRow()] += 1;
|
|
}
|
|
// check if some entries have stayed unused.
|
|
unsigned int counter=top;
|
|
int adjustment=m_pageBoundaries.count()-1;
|
|
|
|
do {
|
|
counter--;
|
|
if(adjustment >= 0 && counter == m_pageBoundaries[adjustment])
|
|
adjustment--;
|
|
if(rows[counter]==0) {
|
|
kdDebug() << k_funcinfo << "no rows at counter=" << counter << " -> erasing" << endl;
|
|
m_rows--;
|
|
m_rowPositions.erase(m_rowPositions.at(counter+(adjustment>0?adjustment:0)));
|
|
for (TableIter cell(this); cell; ++cell) {
|
|
if(cell->firstRow() < counter && cell->rowAfter() > counter)
|
|
cell->setRowSpan(cell->rowSpan()-1);
|
|
if(cell->firstRow() > counter)
|
|
cell->setFirstRow(cell->firstRow()-1);
|
|
}
|
|
|
|
if(adjustment >= -1) {
|
|
pageBound = m_pageBoundaries.at(adjustment+1);
|
|
while(pageBound!=m_pageBoundaries.end()) {
|
|
(*pageBound)= (*pageBound)-1;
|
|
pageBound++;
|
|
}
|
|
}
|
|
}
|
|
} while(counter!=0);
|
|
#endif
|
|
|
|
|
|
m_redrawFromCol = 0;
|
|
for (TableIter cell(this); cell; ++cell) {
|
|
if((cell->rowAfter() > fromRow && cell->firstRow() < untilRow)
|
|
|| cell->columnAfter() > m_redrawFromCol)
|
|
position(cell);
|
|
}
|
|
m_redrawFromCol = getColumns();
|
|
kdDebug(32004) << name() << " KWTableFrameSet::recalcRows done" << endl;
|
|
updateFrames();
|
|
}
|
|
|
|
int KWTableFrameSet::columnEdgeAt( double x ) const
|
|
{
|
|
// We compare x with the middle of columns (left+right/2),
|
|
// to find which column x is closest to.
|
|
// m_colPositions is sorted, so we can remember the last column we looked at.
|
|
double lastMiddlePos = 0;
|
|
for ( uint i = 0; i < m_colPositions.count() - 1; i++ ) {
|
|
double middlePos = ( m_colPositions[i] + m_colPositions[i+1] ) / 2;
|
|
Q_ASSERT( lastMiddlePos < middlePos );
|
|
if ( x > lastMiddlePos && x <= middlePos )
|
|
return i;
|
|
lastMiddlePos = middlePos;
|
|
}
|
|
return m_colPositions.count() - 1;
|
|
}
|
|
|
|
int KWTableFrameSet::rowEdgeAt( double y ) const
|
|
{
|
|
double lastMiddlePos = 0;
|
|
for ( uint i = 0; i < m_rowPositions.count() - 1; i++ ) {
|
|
double middlePos = ( m_rowPositions[i] + m_rowPositions[i+1] ) / 2;
|
|
Q_ASSERT( lastMiddlePos < middlePos );
|
|
if ( y > lastMiddlePos && y <= middlePos )
|
|
return i;
|
|
lastMiddlePos = middlePos;
|
|
}
|
|
return m_rowPositions.count() - 1;
|
|
}
|
|
|
|
double KWTableFrameSet::columnSize( unsigned int col )
|
|
{
|
|
return m_colPositions[ col ];
|
|
}
|
|
|
|
double KWTableFrameSet::rowSize( unsigned int row )
|
|
{
|
|
return m_rowPositions[ row ];
|
|
}
|
|
|
|
void KWTableFrameSet::resizeColumn( unsigned int col, double x )
|
|
{
|
|
kdDebug() << k_funcinfo << col << "," << x << endl;
|
|
if ((col != 0) && (x - m_colPositions[ col-1 ] < s_minFrameWidth))
|
|
m_colPositions[ col ] = m_colPositions[ col-1 ] + s_minFrameWidth;
|
|
else
|
|
if ((col != getColumns()) && (m_colPositions[ col + 1 ] - x < s_minFrameWidth))
|
|
m_colPositions[col] = m_colPositions[ col + 1 ] - s_minFrameWidth;
|
|
else
|
|
m_colPositions[ col ] = x;
|
|
|
|
// move all cells right of 'col'
|
|
for (TableIter cell(this); cell; ++cell) {
|
|
if ( cell->columnAfter() >= col ) {
|
|
position(cell);
|
|
}
|
|
}
|
|
recalcCols( col-1, 0 );
|
|
}
|
|
|
|
void KWTableFrameSet::resizeRow( unsigned int row, double y )
|
|
{
|
|
kdDebug() << k_funcinfo << row << "," << y << endl;
|
|
double difference = m_rowPositions[row];
|
|
if ((row != 0) && (y - m_rowPositions[ row-1 ] < s_minFrameHeight))
|
|
m_rowPositions[ row ] = m_rowPositions[ row-1 ] + s_minFrameHeight;
|
|
else
|
|
if ((row != getRows()) && (m_rowPositions[ row + 1 ] - y < s_minFrameHeight))
|
|
m_rowPositions[row] = m_rowPositions[ row + 1 ] - s_minFrameHeight;
|
|
else
|
|
m_rowPositions[ row ] = y;
|
|
difference = m_rowPositions[row] - difference;
|
|
|
|
//move all rows under 'row'
|
|
if (row != 0)
|
|
for (unsigned int i=row+1; i<= getRows(); i++)
|
|
m_rowPositions[i] = m_rowPositions[i] + difference;
|
|
|
|
// move all cells under 'row'
|
|
for (TableIter cell(this); cell; ++cell) {
|
|
if ( cell->rowAfter() >= row ) {
|
|
position(cell);
|
|
}
|
|
}
|
|
recalcRows( 0, row-1 );
|
|
}
|
|
|
|
void KWTableFrameSet::resizeWidth( double width ) {
|
|
Q_ASSERT(width != 0);
|
|
Q_ASSERT(boundingRect().width() != 0);
|
|
kdDebug() << "bounding width before resize " << boundingRect().width() << endl;
|
|
double growth = width / boundingRect().width();
|
|
|
|
// since we move all the columns, we also move the 1st one,
|
|
// depending where it is on the page.
|
|
// just compensate by substracting that offset.
|
|
double moveOffset = m_colPositions[0] * growth - m_colPositions[0];
|
|
|
|
for (uint i=0; i<m_colPositions.count(); i++) {
|
|
m_colPositions[i] = m_colPositions[i] * growth - moveOffset;
|
|
}
|
|
finalize();
|
|
kdDebug() << "bounding width after resize" << boundingRect().width() << endl;
|
|
Q_ASSERT(boundingRect().width() - width < 0.01);
|
|
}
|
|
|
|
void KWTableFrameSet::setBoundingRect( KoRect rect, CellSize widthMode, CellSize heightMode ) {
|
|
// Column positions..
|
|
m_colPositions.clear();
|
|
unsigned int cols=0;
|
|
for (TableIter c(this); c; ++c)
|
|
cols = kMax(cols, c.current()->columnAfter());
|
|
double colWidth = rect.width() / cols;
|
|
if ( widthMode == TblAuto ) {
|
|
KWPage *page = pageManager()->page(rect);
|
|
rect.setLeft( page->leftMargin() );
|
|
colWidth = (page->width() - page->leftMargin() - page->rightMargin()) / cols;
|
|
}
|
|
|
|
for(unsigned int i=0; i <= cols;i++) {
|
|
m_colPositions.append(rect.x() + colWidth * i);
|
|
}
|
|
|
|
// Row positions..
|
|
m_rowPositions.clear();
|
|
m_pageBoundaries.clear();
|
|
double rowHeight = 0;
|
|
if( heightMode != TblAuto )
|
|
rowHeight = rect.height() / m_rows;
|
|
rowHeight=kMax(rowHeight, 22.0); // m_doc->getDefaultParagLayout()->getFormat().ptFontSize()) // TODO use table style font-size
|
|
|
|
for(unsigned int i=0; i <= m_rows;i++) {
|
|
m_rowPositions.append(rect.y() + rowHeight * i);
|
|
}
|
|
|
|
double oneMm = MM_TO_POINT( 1.0 );
|
|
for (TableIter cell(this); cell; ++cell) {
|
|
KWFrame *frame = cell->frame(0);
|
|
frame->setPaddingLeft( oneMm );
|
|
frame->setPaddingRight( oneMm );
|
|
frame->setPaddingTop( oneMm );
|
|
frame->setPaddingBottom( oneMm );
|
|
frame->setNewFrameBehavior( KWFrame::NoFollowup );
|
|
position(cell, true);
|
|
}
|
|
}
|
|
|
|
void KWTableFrameSet::position( Cell *theCell, bool setMinFrameHeight ) {
|
|
if(!theCell->frame(0)) { // sanity check.
|
|
kdDebug(32004) << "errorous table cell!! row:" << theCell->firstRow()
|
|
<< ", col: " << theCell->firstColumn() << endl;
|
|
return;
|
|
}
|
|
double x = *m_colPositions.at(theCell->firstColumn());
|
|
double y = getPositionOfRow(theCell->firstRow());
|
|
double width = (*m_colPositions.at(theCell->columnAfter())) - x;
|
|
double height = getPositionOfRow(theCell->lastRow(), true) - y;
|
|
|
|
#if 0
|
|
if(theCell->m_col==0) {
|
|
kdDebug(32004) << "row " << theCell->firstRow() << " has top: "
|
|
<< y << ", and bottom: " << y + height << endl;
|
|
}
|
|
#endif
|
|
|
|
// Now take the border sizes and make the cell smaller so it still fits inside the grid.
|
|
KWFrame *theFrame = theCell->frame(0);
|
|
x+=theCell->leftBorder();
|
|
width-=theCell->leftBorder();
|
|
width-=theCell->rightBorder();
|
|
y+=theCell->topBorder();
|
|
height-=theCell->topBorder();
|
|
height-=theCell->bottomBorder();
|
|
|
|
theFrame->setRect( x,y,width,height);
|
|
if( setMinFrameHeight )
|
|
theFrame->setMinimumFrameHeight(height);
|
|
|
|
if(!theCell->isVisible())
|
|
theCell->setVisible(true);
|
|
}
|
|
|
|
double KWTableFrameSet::getPositionOfRow( unsigned int row, bool bottom ) {
|
|
unsigned int adjustment=0;
|
|
TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
|
|
while(pageBound != m_pageBoundaries.end() && (*pageBound) <= row + adjustment) {
|
|
adjustment++;
|
|
pageBound++;
|
|
}
|
|
if(m_rowPositions.count() < row+adjustment+(bottom?1:0)) // Requested row does not exist.
|
|
return 0;
|
|
return m_rowPositions[row+adjustment+(bottom?1:0)];
|
|
}
|
|
|
|
void KWTableFrameSet::moveBy( double dx, double dy ) {
|
|
bool redraw=false;
|
|
kdDebug(32004) << "KWTableFrameSet(" << name() << ")::moveBy(" << dx<<","<<dy<<")\n";
|
|
//for(unsigned int i=0; i < m_rowPositions.count() ; kdDebug(32004) << "row " << i << ": " << m_rowPositions[i++] << endl);
|
|
if(!(dy > -0.001 && dy < 0.001)) {
|
|
redraw=true;
|
|
TQValueList<double>::iterator row = m_rowPositions.begin();
|
|
while(row != m_rowPositions.end()) {
|
|
(*row)= (*row)+dy;
|
|
row++;
|
|
}
|
|
}
|
|
if(!(dx > -0.001 && dx < 0.001)) {
|
|
redraw=true;
|
|
TQValueList<double>::iterator col = m_colPositions.begin();
|
|
while(col != m_colPositions.end()) {
|
|
(*col)= (*col)+dx;
|
|
col++;
|
|
}
|
|
}
|
|
|
|
if(redraw) {
|
|
for(TableIter cell(this);cell;++cell)
|
|
position(cell);
|
|
}
|
|
}
|
|
|
|
/* Delete all cells that are completely in this row. */
|
|
void KWTableFrameSet::deleteRow( unsigned int row, RemovedRow &rr, bool _recalc)
|
|
{
|
|
Q_ASSERT(row < m_rowArray.size());
|
|
const unsigned int rowspan=1;
|
|
|
|
double height= getPositionOfRow(row+rowspan-1,true) - getPositionOfRow(row);
|
|
TQValueList<double>::iterator tmp = m_rowPositions.at(row+rowspan);
|
|
tmp=m_rowPositions.erase(tmp);
|
|
while(tmp!=m_rowPositions.end()) {
|
|
(*tmp)= (*tmp)-height;
|
|
tmp++;
|
|
}
|
|
|
|
rr.m_index = row;
|
|
rr.m_rowHeight = height;
|
|
rr.m_row = m_rowArray[row];
|
|
|
|
// move/delete cells.
|
|
for ( TableIter cell(this); cell; ++cell ) {
|
|
if ( row >= cell->firstRow() && row < cell->rowAfter()) { // cell is indeed in row
|
|
if(cell->rowSpan() == 1) { // cell is wholly contained within row
|
|
m_frames.remove( cell->frame(0) );
|
|
} else { // make cell span rowspan less rows
|
|
cell->setRowSpan(cell->rowSpan()-rowspan);
|
|
position(cell);
|
|
}
|
|
|
|
} else if ( cell->firstRow() > row ) {
|
|
// move cell up
|
|
cell->setFirstRow( cell->firstRow() - rowspan );
|
|
position(cell);
|
|
}
|
|
}
|
|
|
|
removeRowVector(row);
|
|
m_rows -= rowspan;
|
|
m_rowArray.resize( m_rows );
|
|
validate();
|
|
|
|
if ( _recalc )
|
|
recalcRows( 0, row-1 );
|
|
}
|
|
|
|
void KWTableFrameSet::reInsertRow(RemovedRow &rr)
|
|
{
|
|
uint row = rr.index();
|
|
Row *r = rr.row();
|
|
uint rlen = r->count();
|
|
|
|
// adjust cell positions & sizes
|
|
for(MarkedIterator cell(this); cell; ++cell) {
|
|
|
|
if ( cell->firstRow() < row && cell->lastRow() >= row ){ // cell is indeed in row
|
|
cell->setRowSpan(cell->rowSpan() + 1);
|
|
}
|
|
else if(r->m_cellArray[cell->firstColumn()] == cell.current()) {
|
|
cell->setRowSpan(cell->rowSpan() + 1);
|
|
}
|
|
else if ( cell->firstRow() >= row ) {
|
|
// move cell down
|
|
cell->setFirstRow( cell->firstRow() + 1);
|
|
}
|
|
}
|
|
|
|
// put back m_frames that were removed
|
|
for(uint i = 0; i < rlen; i++){
|
|
if( m_frames.findRef((*r)[i]->frame(0)) == -1 )
|
|
m_frames.append( (*r)[i]->frame(0) );
|
|
}
|
|
|
|
// adjust row positions (ignores page boundaries!)a
|
|
if(row == m_rows) { //reinserting at bottom of table
|
|
double d = m_rowPositions.last() + rr.height();
|
|
m_rowPositions.append(d);
|
|
}
|
|
else {
|
|
TQValueList<double>::iterator top = m_rowPositions.at(row);
|
|
TQValueList<double>::iterator i = m_rowPositions.at(row+1);
|
|
i = m_rowPositions.insert(i, *top + rr.height());
|
|
i++;
|
|
for(; i != m_rowPositions.end(); ++i) {
|
|
*i = *i+ rr.height();
|
|
}
|
|
}
|
|
|
|
// reinsert row into array
|
|
m_rows++;
|
|
insertRowVector(rr.index(), rr.takeRow());
|
|
|
|
// don't actually have to visit all the cells, this could be optimised
|
|
for(TableIter i(this); i ; ++i)
|
|
position(i.current());
|
|
|
|
validate();
|
|
}
|
|
|
|
void KWTableFrameSet::insertNewRow( uint idx, bool recalc, bool _removeable)
|
|
{
|
|
|
|
(void) _removeable; // unused parameter
|
|
unsigned int copyFromRow = idx==0?0:idx-1;
|
|
if(idx==0)
|
|
copyFromRow=1;
|
|
Row *copyRow = m_rowArray[copyFromRow];
|
|
|
|
uint new_rows = m_rows + 1;
|
|
// What height to use for the new row
|
|
double height = getPositionOfRow(copyFromRow,true) - getPositionOfRow(copyFromRow);
|
|
|
|
// Calculate offset in TQValueList because of page breaks.
|
|
unsigned int adjustment=0;
|
|
unsigned int untilRow=m_rows;
|
|
TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
|
|
while(pageBound != m_pageBoundaries.end() && (*pageBound) <= idx) {
|
|
// Find out how many pages we already had.
|
|
adjustment++;
|
|
pageBound++;
|
|
}
|
|
|
|
// Move all rows down from newRow to bottom of page
|
|
TQValueList<double>::iterator tmp = m_rowPositions.at(idx);
|
|
double newPos = *tmp + height;
|
|
tmp++;
|
|
m_rowPositions.insert(tmp, newPos);
|
|
for(unsigned int i=idx+adjustment+2; i < m_rowPositions.count(); i++) {
|
|
double &rowPos = m_rowPositions[i];
|
|
kdDebug(32004) << "adjusting " << rowPos << " -> " << rowPos + height << endl;
|
|
rowPos = rowPos + height;
|
|
if(*pageBound == i) {
|
|
untilRow= *pageBound;
|
|
break; // stop at pageBreak.
|
|
}
|
|
}
|
|
|
|
for ( MarkedIterator cells(this); cells; ++cells) {
|
|
if ( cells->firstRow() >= idx ) { // move all cells beneath the new row.
|
|
cells->setFirstRow(cells->firstRow()+1);
|
|
}
|
|
}
|
|
|
|
insertRowVector(idx, new Row);
|
|
|
|
unsigned int i = 0;
|
|
while(i < getColumns()) {
|
|
|
|
if(idx != 0 && (idx != m_rows)) {
|
|
Cell *c = cell(idx - 1, i);
|
|
if( c == cell(idx + 1, i) ) {
|
|
m_rowArray[idx]->addCell(c);
|
|
c->setRowSpan(c->rowSpan() + 1);
|
|
i += c->columnSpan();
|
|
continue; // don't need to make a new cell
|
|
}
|
|
}
|
|
|
|
KWFrame *theFrame = new KWFrame(copyRow->m_cellArray[i]->frame(0));
|
|
Cell *newCell=new Cell( this, idx, i, TQString() );
|
|
newCell->setColumnSpan( cell(copyFromRow,i)->columnSpan() );
|
|
addCell(newCell);
|
|
newCell->addFrame( theFrame, false );
|
|
position(newCell);
|
|
i += newCell->columnSpan();
|
|
}
|
|
|
|
// Position all changed cells.
|
|
|
|
m_rows = new_rows;
|
|
validate();
|
|
if ( recalc )
|
|
finalize();
|
|
}
|
|
|
|
void KWTableFrameSet::deleteColumn(uint col, RemovedColumn &rc)
|
|
{
|
|
// keep these values in case we have to put it back
|
|
if(!rc.m_initialized) {
|
|
rc.m_index = col;
|
|
rc.m_width = m_colPositions[col+1] - m_colPositions[col];
|
|
}
|
|
|
|
// move the colomn positions
|
|
TQValueList<double>::iterator tmp = m_colPositions.at(col+1);
|
|
tmp = m_colPositions.erase(tmp);
|
|
while(tmp != m_colPositions.end()) {
|
|
(*tmp) = (*tmp) - rc.m_width;
|
|
tmp++;
|
|
}
|
|
|
|
// remove cells that are wholy in this column,
|
|
// otherwise reduce rowspan. pointers to all cells
|
|
// are kept in the RemovedColumn
|
|
CheckedIter iter(this);
|
|
for(uint i = 0; i < m_rows; ++i) {
|
|
Cell *daCell = cell(i, col);
|
|
|
|
if(!rc.m_initialized) {
|
|
rc.m_column.append(daCell);
|
|
rc.m_removed.append(daCell->columnSpan() == 1);
|
|
}
|
|
|
|
if(daCell->columnSpan() == 1) { // lets remove it
|
|
if(daCell->firstRow() == i) {
|
|
m_frames.remove( daCell->frame(0) );
|
|
m_nr_cells--;
|
|
}
|
|
m_rowArray[i]->m_cellArray.insert(col, 0);
|
|
}
|
|
else { // make cell span 1 less column
|
|
if(daCell->firstRow() == i) {
|
|
daCell->setColumnSpan( daCell->columnSpan() - 1 );
|
|
position(daCell);
|
|
}
|
|
}
|
|
}
|
|
|
|
// adjust cells in a later column
|
|
for(; iter; ++iter) {
|
|
if (iter->firstColumn() > col ) {
|
|
iter->setFirstColumn( iter->firstColumn() - 1);
|
|
position(iter.current());
|
|
}
|
|
}
|
|
|
|
// move pointers in 2d array back one column to occupy
|
|
// removed column
|
|
for(uint i = 0; i < m_rows; i++) {
|
|
for(uint j = col + 1; j < m_cols; j++)
|
|
m_rowArray[i]->m_cellArray.insert(j-1, m_rowArray[i]->m_cellArray[j]);
|
|
}
|
|
m_cols--;
|
|
rc.m_initialized = true;
|
|
|
|
validate();
|
|
recalcCols( col, 0 );
|
|
recalcRows( col, 0 );
|
|
}
|
|
|
|
void KWTableFrameSet::reInsertColumn(RemovedColumn &rc)
|
|
{
|
|
TQValueList<double>::iterator tmp = m_colPositions.at(rc.m_index);
|
|
|
|
tmp = m_colPositions.insert(tmp, *tmp);
|
|
tmp++;
|
|
while(tmp != m_colPositions.end()) {
|
|
(*tmp) = (*tmp) + rc.m_width;
|
|
tmp++;
|
|
}
|
|
|
|
// if a cell starts after the column we are inserting, it
|
|
// must be moved to the right, except if it is going to
|
|
// occury the reinserted column also.
|
|
for ( MarkedIterator cells(this); cells ; ++cells ) {
|
|
if ( cells->firstColumn() >= rc.m_index &&
|
|
(rc.m_column.at(cells->firstRow()) != cells.current())) {
|
|
|
|
cells->setFirstColumn(cells->firstColumn() + 1);
|
|
}
|
|
}
|
|
insertEmptyColumn(rc.m_index);
|
|
m_cols++;
|
|
|
|
for(uint i = 0; i < m_rows; ++i) {
|
|
bool removed = rc.m_removed[i];
|
|
Cell *daCell = rc.m_column.at(i);
|
|
if(i == daCell->firstRow()) {
|
|
if(removed) {
|
|
daCell->setColumnSpan(1);
|
|
m_frames.append(daCell->frame(0));
|
|
m_nr_cells++;
|
|
}
|
|
else {
|
|
daCell->setColumnSpan(daCell->columnSpan() + 1);
|
|
}
|
|
addCell(daCell);
|
|
}
|
|
}
|
|
|
|
validate();
|
|
finalize();
|
|
}
|
|
|
|
void KWTableFrameSet::insertNewColumn( uint idx, double width)
|
|
{
|
|
TQValueList<double>::iterator tmp = m_colPositions.at(idx);
|
|
|
|
tmp = m_colPositions.insert(tmp, *tmp);
|
|
tmp++;
|
|
while(tmp!=m_colPositions.end()) {
|
|
(*tmp)= (*tmp)+width;
|
|
tmp++;
|
|
}
|
|
|
|
for ( MarkedIterator cells(this); cells ; ++cells ) {
|
|
if ( cells->firstColumn() >= idx) { // move all cells right of the new col.
|
|
cells->setFirstColumn(cells->firstColumn() + 1);
|
|
}
|
|
}
|
|
insertEmptyColumn(idx);
|
|
m_cols++;
|
|
uint copyCol = (idx == 0) ? 1 : idx - 1 ;
|
|
|
|
// make the new cells
|
|
// note that the loop counter is mucked with in the loop!
|
|
for( unsigned int i = 0; i < getRows(); i++ ) {
|
|
|
|
// can't break a cell in half, so if there is the same cell
|
|
// on both sides of inserted column, it occupies the new
|
|
// column as well
|
|
if(idx != 0 && (idx != m_cols -1)) {
|
|
Cell *c = cell(i, idx - 1);
|
|
if( c == cell(i, idx + 1) ) {
|
|
// m_rowArray[i]->m_cellArray.insert(idx, c);
|
|
c->setColumnSpan(c->columnSpan() + 1);
|
|
addCell(c);
|
|
i += c->rowSpan() - 1;
|
|
continue; // don't need to make a new cell
|
|
}
|
|
}
|
|
|
|
Cell *newCell = new Cell( this, i, idx, TQString() );
|
|
KWFrame *theFrame = new KWFrame(cell(i, copyCol)->frame(0));
|
|
newCell->addFrame( theFrame, false );
|
|
position(newCell);
|
|
m_nr_cells++;
|
|
}
|
|
validate();
|
|
finalize();
|
|
}
|
|
|
|
void KWTableFrameSet::ungroup()
|
|
{
|
|
// m_cells.setAutoDelete( false );
|
|
// m_cells.clear();
|
|
m_nr_cells = 0;
|
|
|
|
m_active = false;
|
|
}
|
|
|
|
void KWTableFrameSet::group()
|
|
{
|
|
// m_cells.setAutoDelete( true );
|
|
// m_cells.clear();
|
|
|
|
m_nr_cells = 0;
|
|
m_active = true;
|
|
}
|
|
|
|
KCommand *KWTableFrameSet::joinCells(unsigned int colBegin,unsigned int rowBegin, unsigned int colEnd,unsigned int rowEnd) {
|
|
Cell *firstCell = cell(rowBegin, colBegin);
|
|
// if just one cell selected for joining; exit.
|
|
if(rowBegin == rowEnd && colBegin == colEnd || cell(rowBegin,colBegin) == cell(rowEnd,colEnd))
|
|
return 0L;
|
|
TQPtrList<KWFrameSet> listFrameSet;
|
|
TQPtrList<KWFrame> listCopyFrame;
|
|
|
|
// do the actual merge.
|
|
for(unsigned int i=colBegin; i<=colEnd;i++) {
|
|
for(unsigned int j=rowBegin; j<=rowEnd;j++) {
|
|
Cell *daCell = cell(j,i);
|
|
if(daCell && daCell!=firstCell) {
|
|
listFrameSet.append(daCell);
|
|
KWFrame* frame = daCell->frame(0);
|
|
Q_ASSERT(frame);
|
|
if(! frame) continue; // see bug #132642
|
|
listCopyFrame.append(frame->getCopy());
|
|
daCell->deleteFrame(frame);
|
|
}
|
|
}
|
|
}
|
|
|
|
Q_ASSERT(firstCell);
|
|
// update firstcell properties to reflect the merge
|
|
firstCell->setColumnSpan(colEnd-colBegin+1);
|
|
firstCell->setRowSpan(rowEnd-rowBegin+1);
|
|
addCell(firstCell);
|
|
position(firstCell);
|
|
validate();
|
|
|
|
m_doc->updateAllFrames(); // TODO: only fs->updateFrames() & m_doc->updateFramesOnTopOrBelow(pageNum)
|
|
m_doc->repaintAllViews();
|
|
return new KWJoinCellCommand( i18n("Join Cells"), this,colBegin,rowBegin, colEnd,rowEnd,listFrameSet,listCopyFrame);
|
|
}
|
|
|
|
KCommand *KWTableFrameSet::splitCell(unsigned int intoRows, unsigned int intoCols, unsigned int col, unsigned int row, TQPtrList<KWFrameSet> listFrameSet, TQPtrList<KWFrame>listFrame) {
|
|
if(intoRows < 1 || intoCols < 1)
|
|
return 0L;
|
|
|
|
kdDebug(32004) << "KWTableFrameSet::splitCell" << endl;
|
|
Cell *daCell=cell(row,col);
|
|
int rowsDiff = intoRows - daCell->rowSpan();
|
|
int colsDiff = ((int) intoCols) - daCell->columnSpan();
|
|
|
|
if(rowsDiff >0) {
|
|
unsigned int adjustment=0;
|
|
TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
|
|
while(pageBound != m_pageBoundaries.end() && (*pageBound) <= row) {
|
|
adjustment++;
|
|
pageBound++;
|
|
}
|
|
double height = (m_rowPositions[row+adjustment+1] - m_rowPositions[row+adjustment])/intoRows;
|
|
|
|
TQValueList<double>::iterator iRow = m_rowPositions.at(adjustment+row);
|
|
for (int i=0; i < rowsDiff; i++) {
|
|
double newPos = *iRow + height;
|
|
iRow++;
|
|
iRow=m_rowPositions.insert(iRow, newPos);
|
|
}
|
|
|
|
// insert more rows into m_rowArray
|
|
for(int i = 0; i < rowsDiff; ++i) {
|
|
insertRowVector(row+i+1, new Row);
|
|
m_rows++;
|
|
}
|
|
|
|
// m_rows += rowsDiff;
|
|
//for(unsigned int i=0; i < m_rowPositions.count() ; ++i)
|
|
// kdDebug(32004) << "row " << i << ": " << m_rowPositions[i] << endl);
|
|
}
|
|
if(colsDiff >0) {
|
|
double width = (m_colPositions[col+1] - m_colPositions[col])/intoCols;
|
|
|
|
TQValueList<double>::iterator iCol = m_colPositions.at(col);
|
|
for (int i=0; i < colsDiff; i++) {
|
|
double newPos = *iCol + width;
|
|
iCol++;
|
|
iCol=m_colPositions.insert(iCol, newPos);
|
|
}
|
|
|
|
for(int i = 0; i < colsDiff; i++) {
|
|
insertEmptyColumn(col+i+1);
|
|
m_cols++;
|
|
}
|
|
//for(unsigned int i=0; i < m_colPositions.count(); ++i)
|
|
// kdDebug(32004) << "col " << i << ": " << m_colPositions[i] << endl);
|
|
//m_cols += colsDiff;
|
|
}
|
|
|
|
// adjust cellspan and rowspan on other cells.
|
|
for (CheckedIter i(this); i ; ++i) {
|
|
if(daCell == i) continue;
|
|
|
|
if(rowsDiff>0) {
|
|
if(row >= i->firstRow()&& row < i->firstRow()+ i->rowSpan())
|
|
i->setRowSpan(i->rowSpan() + rowsDiff);
|
|
if(i->firstRow() > row) {
|
|
i->setFirstRow(i->firstRow() + rowsDiff);
|
|
// theCell->frame(0)->setTop(theCell->frame(0)->top()+extraHeight);
|
|
}
|
|
}
|
|
if(colsDiff>0) {
|
|
if(col >= i->firstColumn() && col < i->columnAfter())
|
|
i->setColumnSpan(i->columnSpan() + colsDiff);
|
|
if(i->firstColumn() > col)
|
|
i->setFirstColumn(i->firstColumn() + colsDiff);
|
|
}
|
|
/*if(extraHeight != 0 && theCell->firstRow()== row) {
|
|
theCell->frame(0)->setHeight(theCell->frame(0)->height()+extraHeight);
|
|
} */
|
|
if ( rowsDiff > 0 || colsDiff > 0 ) // something changed?
|
|
addCell( i ); // update arrays
|
|
}
|
|
|
|
int i=0;
|
|
KWFrame *firstFrame = daCell->frame(0);
|
|
// create new cells
|
|
for (unsigned int y = 0; y < intoRows; y++) {
|
|
for (unsigned int x = 0; x < intoCols; x++){
|
|
if(x==0 && y==0)
|
|
continue; // the orig cell takes this spot.
|
|
|
|
Cell *lastFrameSet=0L;
|
|
|
|
if(listFrameSet.isEmpty())
|
|
lastFrameSet = new Cell( this, y + row, x + col );
|
|
else
|
|
lastFrameSet = static_cast<KWTableFrameSet::Cell*> (listFrameSet.at(i));
|
|
lastFrameSet->setGroupManager(this);
|
|
|
|
KWFrame *theFrame=0L;
|
|
if(listFrame.isEmpty())
|
|
{
|
|
theFrame=firstFrame->getCopy();
|
|
theFrame->setRunAround( KWFrame::RA_NO );
|
|
theFrame->setFrameBehavior(KWFrame::AutoExtendFrame);
|
|
theFrame->setNewFrameBehavior(KWFrame::NoFollowup);
|
|
lastFrameSet->addFrame( theFrame,false );
|
|
}
|
|
else
|
|
lastFrameSet->addFrame( listFrame.at(i)->getCopy(),false );
|
|
i++;
|
|
|
|
// if the orig cell spans more rows/cols than it is split into, make first col/row wider.
|
|
if(rowsDiff <0 && y==0)
|
|
lastFrameSet->setRowSpan(lastFrameSet->rowSpan() - rowsDiff);
|
|
if(colsDiff <0 && x==0)
|
|
lastFrameSet->setColumnSpan(lastFrameSet->columnSpan() - colsDiff);
|
|
|
|
addCell( lastFrameSet );
|
|
position(lastFrameSet);
|
|
}
|
|
}
|
|
|
|
// set new row and col-span. Use intermediate ints otherwise we get strange results as the
|
|
// intermediate result could be negative (which goes wrong with unsigned ints)
|
|
int r = (daCell->rowSpan() +1) - intoRows;
|
|
if(r < 1) r=1;
|
|
daCell->setRowSpan(r);
|
|
|
|
int c = (daCell->columnSpan() + 1) - intoCols;
|
|
if(c < 1) c=1;
|
|
daCell->setColumnSpan(c);
|
|
|
|
position(daCell);
|
|
addCell(daCell);
|
|
validate();
|
|
|
|
finalize();
|
|
|
|
return new KWSplitCellCommand(i18n("Split Cells"),this,col,row,intoCols, intoRows);
|
|
}
|
|
|
|
void KWTableFrameSet::viewFormatting( TQPainter &/*painter*/, int )
|
|
{
|
|
}
|
|
|
|
void KWTableFrameSet::validate()
|
|
{
|
|
for(CheckedIter cells(this); cells; ++cells) {
|
|
if(cells->columnSpan() == 0 || cells->rowSpan() == 0) {
|
|
kdDebug(32004) << " KWTableFrameSet::validate(): zero dimension" << endl;
|
|
kdDebug(32004) << cells->firstRow() << " " << cells->firstColumn() << " " << cells->rowSpan()
|
|
<< " " << cells->columnSpan() << endl;
|
|
}
|
|
|
|
for(uint i = cells->firstRow(); i < cells->rowAfter(); ++i) {
|
|
|
|
for(uint j = cells->firstColumn(); j < cells->columnAfter(); ++j) {
|
|
if( cell(i,j) != cells.current() ) {
|
|
|
|
TQString str = TQString("| 0x%1 ").arg( (unsigned long)cells.current(), 0, 16 );
|
|
kdDebug(32004) << " KWTableFrameSet::validate() failed " << endl;
|
|
kdDebug(32004) << "at row: "<< i << " col: "<< j << " cell: "<< str << endl;
|
|
kdDebug(32004) << cells->firstRow() << " " << cells->firstColumn() << " " << cells->rowSpan()
|
|
<< " " << cells->columnSpan() << endl;
|
|
//printArrayDebug();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void KWTableFrameSet::createEmptyRegion( const TQRect & crect, TQRegion & emptyRegion, KWViewMode *viewMode )
|
|
{
|
|
// Avoid iterating over all cells if we are out of view
|
|
if ( !viewMode->normalToView( m_doc->zoomRect( boundingRect() ) ).intersects( crect ) )
|
|
return;
|
|
|
|
TQRect outerRect( viewMode->normalToView( m_doc->zoomRect( boundingRect() )));
|
|
outerRect &= crect;
|
|
if ( !outerRect.isEmpty() )
|
|
emptyRegion = emptyRegion.subtract( outerRect );
|
|
|
|
TQPtrListIterator<KWFrame> frameIt = frameIterator();
|
|
for ( ; frameIt.current(); ++frameIt )
|
|
{
|
|
TQRect outerRect( viewMode->normalToView( frameIt.current()->outerRect(viewMode) ) );
|
|
//kdDebug(32004) << "KWTableFrameSet::createEmptyRegion outerRect=" << DEBUGRECT( outerRect )
|
|
// << " crect=" << DEBUGRECT( crect ) << endl;
|
|
outerRect &= crect;
|
|
if ( !outerRect.isEmpty() )
|
|
emptyRegion = emptyRegion.subtract( outerRect );
|
|
}
|
|
}
|
|
|
|
void KWTableFrameSet::drawBorders( TQPainter& painter, const TQRect &crect, KWViewMode *viewMode ) {
|
|
|
|
/* Draw the borders on top of the lines stores in the m_rowPositions and m_colPositions arrays.
|
|
* check the relevant cells for borders and thus line thickness.
|
|
* We move the outer lines (on row==0 and col==0 plus on col=getColumns() etc) a bit so they will stay
|
|
* inside the boundary of the table!
|
|
*/
|
|
painter.save();
|
|
TQPen previewLinePen( TQApplication::palette().color( TQPalette::Active, TQColorGroup::Mid ) );
|
|
TQColor defaultBorderColor = KoTextFormat::defaultTextColor( &painter );
|
|
const int minborder = 1;
|
|
bool drawPreviewLines = viewMode && viewMode->drawFrameBorders();
|
|
|
|
// *** draw horizontal lines *** //
|
|
unsigned int row=0;
|
|
TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
|
|
for (unsigned int i=0 ; i < m_rowPositions.count() ; i++) {
|
|
//kdDebug(32004) << "Horizontal line code. i: " << i << endl;
|
|
bool bottom=false;
|
|
if( (pageBound!=m_pageBoundaries.end() && (*pageBound) == row)
|
|
|| i == m_rowPositions.count()-1)
|
|
bottom=true; // at end of page or end of table draw bottom border of cell.
|
|
|
|
const KoBorder *border=0;
|
|
double startPos =0;
|
|
for(unsigned int col=0; col <= getColumns();) {
|
|
//kdDebug(32004) << "bottom=" << bottom << " row=" << row << " col=" << col << endl;
|
|
Cell *daCell = col < getColumns() ? cell(bottom?row-1:row, col) : 0;
|
|
//if(daCell) kdDebug(32004) << "cell (" << daCell->firstRow()<< "," << daCell->firstColumn() << ")" << endl;
|
|
//else kdDebug(32004) << "cell: " << daCell << endl;
|
|
|
|
if(daCell && daCell->firstRow() != (bottom?row-1:row))
|
|
daCell=0;
|
|
|
|
if(startPos!=0 && (!daCell || col == getColumns() || (
|
|
bottom && daCell->frame(0)->bottomBorder()!=*border ||
|
|
!bottom && daCell->frame(0)->topBorder()!=*border
|
|
))) {
|
|
if(border->width() > 0 || drawPreviewLines) {
|
|
double y = m_rowPositions[i];
|
|
if(row==0)
|
|
y+=border->width() / 2; // move slightly down.
|
|
else if (row == getRows())
|
|
y-=border->width() / 2; // move slightly up.
|
|
int ypix = m_doc->zoomItY(y);
|
|
double offset=0.0;
|
|
if(border->width() > 0 && col!=getColumns()) { // offset border when not at right most cell.
|
|
if(daCell) offset=daCell->leftBorder();
|
|
if ( row > 0 ) {
|
|
Cell *c = cell(row-1, col);
|
|
if(c) offset=kMax(offset, c->leftBorder());
|
|
}
|
|
}
|
|
double x = m_colPositions[col] + offset;
|
|
TQPoint topLeft = viewMode->normalToView(TQPoint(m_doc->zoomItX(startPos), ypix));
|
|
TQPoint bottomRight = viewMode->normalToView(TQPoint(m_doc->zoomItX(x), ypix));
|
|
TQRect line = TQRect(topLeft, bottomRight);
|
|
if(crect.intersects( line )) {
|
|
//if(border->width() <= 0) kdDebug(32004) << "preview line" << endl;
|
|
if(border->width() <= 0)
|
|
painter.setPen( previewLinePen );
|
|
else {
|
|
int borderWidth = KoBorder::zoomWidthY( border->width(), m_doc, minborder );
|
|
painter.setPen( KoBorder::borderPen( *border, borderWidth, defaultBorderColor ) );
|
|
}
|
|
//kdDebug(32004) << "Paint: painter.drawHorizontalLine(" << line.left() << "," << line.top() << "," << line.right() << "," << line.bottom() << ")\n";
|
|
painter.drawLine( line.left(), line.top(), line.right(), line.bottom());
|
|
}
|
|
}
|
|
// reset startPos
|
|
startPos = 0;
|
|
}
|
|
if(daCell && startPos==0) {
|
|
if(bottom)
|
|
border=&(daCell->frame(0)->bottomBorder());
|
|
else
|
|
border=&(daCell->frame(0)->topBorder());
|
|
|
|
if(col==0) // left most cell
|
|
startPos = m_colPositions[col];
|
|
else {
|
|
double offset=0.0;
|
|
if(border->width() > 0) { // move line to the left a bit to compensate for the left border
|
|
if(daCell) offset=daCell->leftBorder();
|
|
if ( row > 0 ) {
|
|
Cell *c = cell(row-1, col);
|
|
if(c) offset=kMax(offset, c->leftBorder());
|
|
}
|
|
}
|
|
startPos = m_colPositions[col] - offset;
|
|
}
|
|
}
|
|
col += daCell ? daCell->columnSpan() : 1;
|
|
}
|
|
if(pageBound!=m_pageBoundaries.end() && (*pageBound) == row)
|
|
pageBound++;
|
|
else
|
|
row++;
|
|
}
|
|
|
|
// *** draw vertical lines *** //
|
|
for (unsigned int col=0 ; col < m_colPositions.count(); col++) {
|
|
//kdDebug(32004) << "Vertical line code. col: " << col << endl;
|
|
bool right = false;
|
|
if(col == m_colPositions.count()-1)
|
|
right = true; // draw right border of cell.
|
|
int cellColumn = right?col-1:col; // the column we'll be looking for in the loop below
|
|
Q_ASSERT( cellColumn >= 0 );
|
|
|
|
const KoBorder *border = 0;
|
|
int startRow = -1;
|
|
for(unsigned int row=0; row <= getRows();) {
|
|
//kdDebug(32004) << "row=" << row << " cellColumn=" << cellColumn << endl;
|
|
Cell *daCell = row < getRows() ? cell(row, cellColumn) : 0;
|
|
|
|
//kdDebug(32004) << "Drawing vert. Line for cell row: " << row << " col: " << cellColumn << endl;
|
|
if(daCell && daCell->firstColumn() != (uint)cellColumn)
|
|
daCell=0;
|
|
|
|
#if 0
|
|
kdDebug() << "Condition: startRow:" << (startRow!=-1) << endl;
|
|
if ( startRow != -1 ) {
|
|
Q_ASSERT( border );
|
|
kdDebug() << "Other conditions: cell:" << !daCell << endl;
|
|
kdDebug() << " or last row:" << ( row == ( int )getRows() ) << endl;
|
|
if ( daCell )
|
|
kdDebug() << "Different border:" <<
|
|
( ( right && daCell->frame(0)->rightBorder() != *border) ||
|
|
( !right && daCell->frame(0)->leftBorder() != *border) )
|
|
<< endl;
|
|
}
|
|
#endif
|
|
|
|
// be sure that the right border of the table is drawn even for joined cells
|
|
if ( !daCell && startRow == -1 && cellColumn == ((int)m_colPositions.count()-2 ) && right )
|
|
{
|
|
// find the joined cell
|
|
int col = cellColumn;
|
|
while ( !daCell && col>0 )
|
|
{
|
|
col--;
|
|
daCell = cell(row, col);
|
|
}
|
|
if ( daCell && daCell->isJoinedCell() && ( (int)daCell->columnSpan() + col -1 ) == cellColumn )
|
|
{
|
|
border = &(daCell->frame(0)->rightBorder());
|
|
startRow = row;
|
|
}
|
|
else
|
|
daCell = 0;
|
|
}
|
|
|
|
// Draw when something changed (different kind of border) or we're at the end
|
|
// This code could be rewritten in a more TQRT-like way
|
|
// (iterate and compare with next, instead of the startRow/cell/border hack...)
|
|
if(startRow != -1 &&
|
|
(!daCell || row == getRows() ||
|
|
( right && daCell->frame(0)->rightBorder() != *border) ||
|
|
( !right && daCell->frame(0)->leftBorder() != *border) )
|
|
) {
|
|
if(border->width() > 0 || drawPreviewLines) {
|
|
double x = m_colPositions[col];
|
|
if(col==0) {
|
|
x+=border->width() / 2;
|
|
} else if(col==getColumns()) {
|
|
x-=border->width() / 2;
|
|
}
|
|
int xpix = m_doc->zoomItX(x);
|
|
TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
|
|
unsigned int topRow=startRow;
|
|
//kdDebug(32004) << "Drawing from topRow=" << topRow << endl;
|
|
do { // draw minimum of one line per page.
|
|
while( pageBound != m_pageBoundaries.end() && *(pageBound) < topRow )
|
|
pageBound++;
|
|
|
|
unsigned int bottomRow;
|
|
if(pageBound == m_pageBoundaries.end())
|
|
bottomRow = m_rowPositions.count()-1;
|
|
else
|
|
bottomRow = *(pageBound++);
|
|
|
|
//kdDebug(32004) << "from: " << topRow << " to: " << kMin((uint)row, bottomRow) << endl;
|
|
//kdDebug(32004) << "from: " << m_rowPositions[topRow] << " to: " << m_rowPositions[kMin((uint)row, bottomRow)] << endl;
|
|
double offset=0.0;
|
|
if(border->width() > 0) {
|
|
//kdDebug(32004) << "looking at topRow=" << topRow << " col=" << col << endl;
|
|
Cell *c=cell(topRow,col);
|
|
if(c) offset=c->topBorder();
|
|
if ( col > 0 ) {
|
|
c=cell(topRow,col-1);
|
|
if(c) offset=kMax(offset,c->topBorder());
|
|
}
|
|
if(topRow==0) offset=0.0;
|
|
}
|
|
double top=m_rowPositions[topRow]-offset;
|
|
|
|
unsigned int toRow=kMin((uint)row,bottomRow);
|
|
offset=0.0;
|
|
if(border->width() > 0 && toRow!=bottomRow) {
|
|
if(daCell) offset=daCell->topBorder();
|
|
Cell *c=cell(toRow,col-1);
|
|
if(c) offset=kMax(offset,c->topBorder());
|
|
}
|
|
double bottom=m_rowPositions[toRow] + offset;
|
|
|
|
TQPoint topLeft = viewMode->normalToView(TQPoint(xpix, m_doc->zoomItY(top)));
|
|
TQPoint bottomRight = viewMode->normalToView(TQPoint(xpix, m_doc->zoomItY(bottom)));
|
|
TQRect line = TQRect(topLeft, bottomRight);
|
|
if(crect.intersects( line )) {
|
|
if(border->width() <= 0)
|
|
painter.setPen( previewLinePen );
|
|
else {
|
|
int borderWidth = KoBorder::zoomWidthX( border->width(), m_doc, minborder );
|
|
painter.setPen(KoBorder::borderPen( *border, borderWidth, defaultBorderColor ));
|
|
}
|
|
//kdDebug(32004) << "drawBorders(): painter.drawVerticalLine(" << line.left() << "," << line.top() << "," << line.right() << "," << line.bottom() << ")\n";
|
|
painter.drawLine( line.left(), line.top(), line.right(), line.bottom());
|
|
}
|
|
|
|
topRow=bottomRow+1;
|
|
} while(topRow < (uint)row && topRow != m_rowPositions.count());
|
|
} // end "if border to be drawn"
|
|
|
|
// reset startRow
|
|
startRow = -1;
|
|
}
|
|
|
|
if(daCell && startRow == -1) {
|
|
startRow = row;
|
|
if(right)
|
|
border = &(daCell->frame(0)->rightBorder());
|
|
else
|
|
border = &(daCell->frame(0)->leftBorder());
|
|
//kdDebug(32004) << "startRow set to " << row << endl;
|
|
}
|
|
row += daCell ? daCell->rowSpan() : 1;
|
|
//kdDebug(32004) << "End of loop, row=" << row << endl;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
if(drawPreviewLines) {
|
|
TQPen minsizeLinePen( red );
|
|
painter.setPen( minsizeLinePen );
|
|
for ( unsigned int i = 0; i < m_cells.count(); i++ ) {
|
|
Cell *daCell = m_cells.at( i );
|
|
double y = daCell->frame(0)->top() + daCell->frame(0)->minimumFrameHeight() + 1.5;
|
|
if(y >= daCell->frame(0)->bottom()) continue;
|
|
int ypix=m_doc->zoomItY(y);
|
|
TQPoint topLeft = viewMode->normalToView(TQPoint(m_doc->zoomItX(daCell->frame(0)->left()), ypix));
|
|
TQPoint bottomRight = viewMode->normalToView(TQPoint(m_doc->zoomItX(daCell->frame(0)->right()), ypix));
|
|
TQRect line = TQRect(topLeft, bottomRight);
|
|
if(crect.intersects( line )) {
|
|
painter.drawLine( line.left(), line.top(), line.right(), line.bottom());
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
painter.restore();
|
|
}
|
|
|
|
void KWTableFrameSet::drawContents( TQPainter * painter, const TQRect & crect,
|
|
const TQColorGroup & cg, bool onlyChanged, bool resetChanged,
|
|
KWFrameSetEdit * edit, KWViewMode * viewMode,
|
|
KWFrameViewManager *fvm )
|
|
{
|
|
for (TableIter cells(this) ; cells ; ++cells)
|
|
{
|
|
if (edit)
|
|
{
|
|
KWTableFrameSetEdit * tableEdit = static_cast<KWTableFrameSetEdit *>(edit);
|
|
if ( tableEdit->currentCell() && ((Cell*) cells) == tableEdit->currentCell()->frameSet() )
|
|
{
|
|
cells->drawContents( painter, crect, cg, onlyChanged, resetChanged, tableEdit->currentCell(), viewMode, fvm );
|
|
continue;
|
|
}
|
|
}
|
|
cells->drawContents( painter, crect, cg, onlyChanged, resetChanged, 0L, viewMode, fvm );
|
|
}
|
|
drawBorders( *painter, crect, viewMode );
|
|
//kdDebug(32004) << "drawContents()" << endl;
|
|
}
|
|
|
|
// Called by KWAnchor for inline tables
|
|
// TODO: for non-inline ones we need a text-box around us...
|
|
// Well, even for inline-as-char ones.... Currently being debated with OASIS.
|
|
void KWTableFrameSet::saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool ) const
|
|
{
|
|
writer.startElement( "table:table" );
|
|
writer.addAttribute( "table:name", name() );
|
|
KoGenStyle tableStyle( KWDocument::STYLE_TABLE, "table" );
|
|
tableStyle.addProperty( "table:align", "margins" );
|
|
tableStyle.addPropertyPt( "style:width", m_colPositions.last()-m_colPositions[0] );
|
|
const TQString tableStyleName = context.mainStyles().lookup( tableStyle, "table" );
|
|
writer.addAttribute( "table:style-name", tableStyleName );
|
|
|
|
// ### to minimize the XML, we could use table:number-columns-repeated here
|
|
// when a number of consecutive columns have the exact same style.
|
|
for ( uint colNr = 0; colNr < getColumns(); ++colNr )
|
|
{
|
|
writer.startElement( "table:table-column" );
|
|
KoGenStyle columnStyle( KWDocument::STYLE_TABLE_COLUMN, "table-column" );
|
|
columnStyle.addPropertyPt( "style:column-width", m_colPositions[colNr+1] - m_colPositions[colNr] );
|
|
const TQString colStyleName = context.mainStyles().lookup( columnStyle, "col" );
|
|
writer.addAttribute( "table:style-name", colStyleName );
|
|
writer.endElement(); // table:table-column
|
|
}
|
|
|
|
// TODO table-header-rows once supported
|
|
|
|
for ( uint row = 0; row < getRows(); ++row )
|
|
{
|
|
writer.startElement( "table:table-row" );
|
|
|
|
KoGenStyle rowStyle( KWDocument::STYLE_TABLE_ROW, "table-row" );
|
|
rowStyle.addPropertyPt( "table:row-height", m_rowPositions[row+1] - m_rowPositions[row] );
|
|
// TODO is min-row-height or use-optimal-row-height necessary?
|
|
const TQString rowStyleName = context.mainStyles().lookup( rowStyle, "row" );
|
|
writer.addAttribute( "table:style-name", rowStyleName );
|
|
|
|
for ( uint col = 0; col < getColumns(); ++col )
|
|
{
|
|
Cell* daCell = cell(row, col);
|
|
Q_ASSERT( daCell );
|
|
if ( !daCell )
|
|
continue;
|
|
|
|
if ( daCell->isFirstGridPosnFast( row, col ) )
|
|
{
|
|
writer.startElement( "table:table-cell" );
|
|
|
|
// Style: background, border, padding.
|
|
KoGenStyle cellStyle( KWDocument::STYLE_TABLE_CELL_AUTO, "table-cell" );
|
|
daCell->frame( 0 )->saveBorderProperties( cellStyle );
|
|
const TQString colStyleName = context.mainStyles().lookup( cellStyle, "cell" );
|
|
writer.addAttribute( "table:style-name", colStyleName );
|
|
|
|
// Attributes
|
|
if ( daCell->columnSpan() > 1 )
|
|
writer.addAttribute( "table:number-columns-spanned", daCell->columnSpan() );
|
|
if ( daCell->rowSpan() > 1 )
|
|
writer.addAttribute( "table:number-row-spanned", daCell->rowSpan() );
|
|
|
|
// Content
|
|
daCell->saveOasisContent( writer, context );
|
|
|
|
writer.endElement(); // table:table-cell
|
|
}
|
|
else
|
|
{
|
|
// Empty element for the covered cell
|
|
writer.startElement( "table:covered-table-cell" );
|
|
writer.endElement();
|
|
}
|
|
}
|
|
writer.endElement(); // table:table-row
|
|
}
|
|
|
|
writer.endElement(); // table:table
|
|
}
|
|
|
|
void KWTableFrameSet::loadOasis( const TQDomElement& tableTag, KoOasisContext& context )
|
|
{
|
|
// Left position of each column. The last one defined is the right position of the last cell/column.
|
|
TQMemArray<double> columnLefts(4);
|
|
uint maxColumns = columnLefts.size() - 1;
|
|
|
|
uint col = 0;
|
|
columnLefts[0] = 0.0; // Initialize left of first cell
|
|
TQDomElement elem;
|
|
forEachElement( elem, tableTag )
|
|
{
|
|
if ( elem.localName() == "table-column" && elem.namespaceURI() == KoXmlNS::table )
|
|
{
|
|
uint repeat = elem.attributeNS( KoXmlNS::table, "number-columns-repeated", "1").toUInt(); // Default 1 time
|
|
if (!repeat)
|
|
repeat=1; // At least one column defined!
|
|
KoStyleStack& styleStack = context.styleStack();
|
|
styleStack.setTypeProperties( "table-column" );
|
|
styleStack.save();
|
|
context.fillStyleStack( elem, KoXmlNS::table, "style-name", "table-column" );
|
|
|
|
TQString strWidth = styleStack.attributeNS( KoXmlNS::style, "column-width" );
|
|
double width = KoUnit::parseValue( strWidth );
|
|
|
|
if ( width < 1.0 ) // Something is wrong with the width
|
|
{
|
|
kdWarning(32004) << "Table column width ridiculous, assuming 1 inch!" << endl;
|
|
width = 72.0;
|
|
}
|
|
else
|
|
kdDebug(32004) << "- style width " << width << endl;
|
|
|
|
for ( uint j = 0; j < repeat; ++j )
|
|
{
|
|
++col;
|
|
if ( col >= maxColumns )
|
|
{
|
|
// We need more columns
|
|
maxColumns += 4;
|
|
columnLefts.resize( maxColumns+1, TQGArray::SpeedOptim );
|
|
}
|
|
columnLefts[col] = width + columnLefts[col-1];
|
|
kdDebug(32004) << "Cell column " << col-1 << " left " << columnLefts[col-1] << " right " << columnLefts[col] << endl;
|
|
}
|
|
styleStack.restore();
|
|
}
|
|
}
|
|
|
|
uint row = 0;
|
|
uint column = 0;
|
|
parseInsideOfTable( tableTag, context, columnLefts, row, column, 0 );
|
|
}
|
|
|
|
void KWTableFrameSet::parseInsideOfTable( const TQDomElement& parent, KoOasisContext& context,
|
|
const TQMemArray<double> & columnLefts, uint& row, uint& column,
|
|
double currentRowHeight )
|
|
{
|
|
kdDebug(32004) << "parseInsideOfTable" << endl;
|
|
KoStyleStack& styleStack = context.styleStack();
|
|
|
|
TQDomElement e;
|
|
forEachElement( e, parent )
|
|
{
|
|
const TQString localName = e.localName();
|
|
const TQString ns = e.namespaceURI();
|
|
if ( ns != KoXmlNS::table ) {
|
|
kdWarning(32004) << "Skipping element " << e.tagName() << " (in parseInsideOfTable)" << endl;
|
|
continue;
|
|
}
|
|
|
|
styleStack.save();
|
|
if ( localName == "table-cell" )
|
|
{
|
|
loadOasisCell( e, context, columnLefts, row, column, currentRowHeight );
|
|
++column;
|
|
}
|
|
else if ( localName == "covered-table-cell" )
|
|
{
|
|
++column;
|
|
}
|
|
else if ( localName == "table-row" )
|
|
{
|
|
context.fillStyleStack( e, KoXmlNS::table, "style-name", "table-row" );
|
|
context.styleStack().setTypeProperties( "table-row" );
|
|
|
|
// Load row height in case it was set - note that it might not be set (e.g. OOo)
|
|
double rowHeight = styleStack.attributeNS( KoXmlNS::table, "row-height" ).toDouble();
|
|
column = 0;
|
|
parseInsideOfTable( e, context, columnLefts, row, column, rowHeight );
|
|
++row;
|
|
}
|
|
else if ( localName == "table-header-rows" ) // ###TODO
|
|
{
|
|
// TODO: do we need to fillStyleStack?
|
|
parseInsideOfTable( e, context, columnLefts, row, column, currentRowHeight );
|
|
}
|
|
else if ( localName == "table-column" )
|
|
{
|
|
// Already treated in loadOasis, we do not need to do anything here!
|
|
}
|
|
// TODO sub-table [ add to stack and expand at end of table loading ]
|
|
else
|
|
{
|
|
kdWarning(32004) << "Skipping element " << localName << " (in parseInsideOfTable)" << endl;
|
|
}
|
|
|
|
styleStack.restore();
|
|
}
|
|
}
|
|
|
|
void KWTableFrameSet::loadOasisCell( const TQDomElement& element, KoOasisContext& context,
|
|
const TQMemArray<double> & columnLefts, uint row, uint column,
|
|
double currentRowHeight )
|
|
{
|
|
//kdDebug(32004) << k_funcinfo << element.localName() << " " << row << "," << column << endl;
|
|
|
|
KoStyleStack& styleStack = context.styleStack();
|
|
uint rowSpan = element.attributeNS( KoXmlNS::table, "number-rows-spanned", TQString() ).toUInt();
|
|
if ( rowSpan == 0 )
|
|
rowSpan = 1;
|
|
uint colSpan = element.attributeNS( KoXmlNS::table, "number-columns-spanned", TQString() ).toUInt();
|
|
if ( colSpan == 0 )
|
|
colSpan = 1;
|
|
|
|
// m_rowPositions / m_colPositions could be TQMemArrays, or TQValueVectors...
|
|
while(m_rowPositions.count() <= row + rowSpan + m_pageBoundaries.count()) {
|
|
m_rowPositions.append(0);
|
|
}
|
|
while(m_colPositions.count() <= column + colSpan) {
|
|
m_colPositions.append(0);
|
|
}
|
|
|
|
Cell *daCell = new Cell( this, row, column, TQString() /*unused*/ );
|
|
|
|
daCell->setRowSpan( rowSpan );
|
|
daCell->setColumnSpan( colSpan );
|
|
addCell( daCell ); // rowSpan/colSpan have changed -> update array
|
|
|
|
double width = columnLefts[ TQMIN( column+colSpan, columnLefts.size()-1 ) ] - columnLefts[column];
|
|
double height = currentRowHeight > 0 ? currentRowHeight : 20;
|
|
KWFrame* frame = new KWFrame( daCell, columnLefts[column], 0, width, height );
|
|
if ( currentRowHeight > 0 )
|
|
frame->setMinimumFrameHeight( height ); // ensure that text formatting won't resize it down
|
|
frame->setRunAround( KWFrame::RA_NO );
|
|
frame->setFrameBehavior( KWFrame::AutoExtendFrame );
|
|
frame->setNewFrameBehavior( KWFrame::NoFollowup );
|
|
daCell->addFrame( frame, false );
|
|
|
|
context.fillStyleStack( element, KoXmlNS::table, "style-name", "table-cell" );
|
|
styleStack.setTypeProperties( "table-cell" );
|
|
|
|
daCell->frame( 0 )->loadBorderProperties( styleStack );
|
|
|
|
daCell->loadOasisContent( element, context );
|
|
afterLoadingCell( daCell );
|
|
}
|
|
|
|
// Old XML
|
|
TQDomElement KWTableFrameSet::save( TQDomElement &parentElem, bool saveFrames ) {
|
|
// When saving to a file, we don't have anything specific to the frameset to save.
|
|
// Save the cells only.
|
|
for (TableIter cells(this) ; cells ; ++cells)
|
|
cells->save(parentElem, saveFrames);
|
|
return TQDomElement(); // No englobing element for tables...
|
|
}
|
|
|
|
// Old XML
|
|
TQDomElement KWTableFrameSet::toXML( TQDomElement &parentElem, bool saveFrames )
|
|
{
|
|
TQDomElement framesetElem = parentElem.ownerDocument().createElement( "FRAMESET" );
|
|
parentElem.appendChild( framesetElem );
|
|
KWFrameSet::saveCommon( framesetElem, false ); // Save the frameset attributes
|
|
// Save the cells
|
|
save( framesetElem, saveFrames );
|
|
return framesetElem;
|
|
}
|
|
|
|
// Old XML
|
|
void KWTableFrameSet::fromXML( TQDomElement &framesetElem, bool loadFrames, bool useNames )
|
|
{
|
|
KWFrameSet::load( framesetElem, false ); // Load the frameset attributes
|
|
// Load the cells
|
|
TQDomElement cellElem = framesetElem.firstChild().toElement();
|
|
for ( ; !cellElem.isNull() ; cellElem = cellElem.nextSibling().toElement() )
|
|
{
|
|
if ( cellElem.tagName() == "FRAMESET" )
|
|
loadCell( cellElem, loadFrames, useNames );
|
|
}
|
|
}
|
|
|
|
// Old XML
|
|
KWTableFrameSet::Cell* KWTableFrameSet::loadCell( TQDomElement &framesetElem, bool loadFrames, bool useNames )
|
|
{
|
|
int _row = KWDocument::getAttribute( framesetElem, "row", 0 );
|
|
if(_row <0) _row =0;
|
|
unsigned int row=_row;
|
|
int _col = KWDocument::getAttribute( framesetElem, "col", 0 );
|
|
if(_col <0) _col =0;
|
|
int _rows = KWDocument::getAttribute( framesetElem, "rows", 1 );
|
|
if(_rows <0) _rows = 1;
|
|
int _cols = KWDocument::getAttribute( framesetElem, "cols", 1 );
|
|
if(_cols <0) _cols = 1;
|
|
|
|
// m_rowPositions / m_colPositions could be TQMemArrays, or TQValueVectors...
|
|
while(m_rowPositions.count() <= static_cast<unsigned int>(row + _rows + m_pageBoundaries.count())) {
|
|
m_rowPositions.append(0);
|
|
}
|
|
while(m_colPositions.count() <= static_cast<unsigned int>(_col + _cols)) {
|
|
m_colPositions.append(0);
|
|
}
|
|
|
|
Cell *daCell = new Cell( this, row, _col, TQString() /*unused*/ );
|
|
TQString autoName = daCell->name();
|
|
//kdDebug(32004) << "KWTableFrameSet::loadCell autoName=" << autoName << endl;
|
|
daCell->load( framesetElem, loadFrames );
|
|
daCell->setRowSpan(_rows);
|
|
daCell->setColumnSpan(_cols);
|
|
addCell( daCell ); // rowSpan/colSpan have changed -> update array
|
|
afterLoadingCell( daCell );
|
|
if ( !useNames )
|
|
daCell->setName( autoName );
|
|
return daCell;
|
|
}
|
|
|
|
// Shared between old xml and oasis
|
|
void KWTableFrameSet::afterLoadingCell( Cell* daCell )
|
|
{
|
|
uint row = daCell->firstRow();
|
|
uint col = daCell->firstColumn();
|
|
uint rowSpan = daCell->rowSpan();
|
|
uint colSpan = daCell->columnSpan();
|
|
if(m_pageBoundaries.count() > 0) {
|
|
unsigned int adjustment=0;
|
|
TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
|
|
while(pageBound != m_pageBoundaries.end() && (*pageBound) <= row + adjustment) {
|
|
adjustment++;
|
|
pageBound++;
|
|
}
|
|
row+=adjustment;
|
|
}
|
|
|
|
kdDebug(32004) << "loading cell (" << row << "," << col << ")\n";
|
|
if(daCell->frame(0)) {
|
|
daCell->frame(0)->setMinimumFrameHeight(daCell->frame(0)->height()); // TODO run the formatter over the text here
|
|
TQValueList<double>::iterator tmp = m_colPositions.at(col);
|
|
if(*tmp == 0) (*tmp) = daCell->frame(0)->left();
|
|
else (*tmp) = (daCell->frame(0)->left() + *tmp) / 2;
|
|
|
|
tmp = m_colPositions.at(col+colSpan);
|
|
if(*tmp == 0) (*tmp) = daCell->frame(0)->right();
|
|
else (*tmp) = (daCell->frame(0)->right() + *tmp) / 2;
|
|
|
|
tmp = m_rowPositions.at(row);
|
|
if(*tmp == 0)
|
|
(*tmp) = daCell->frame(0)->top();
|
|
else {
|
|
if (static_cast<int>(*tmp/m_doc->pageLayout().ptHeight) < static_cast<int>(daCell->frame(0)->top()/m_doc->pageLayout().ptHeight)) {
|
|
kdDebug(32004) << "This cell is on a new page" << endl;
|
|
TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
|
|
while(pageBound != m_pageBoundaries.end() && (*pageBound) < row) ++pageBound;
|
|
if(*pageBound!=row) {
|
|
m_pageBoundaries.insert(pageBound,row++);
|
|
++tmp;
|
|
m_rowPositions.insert(tmp,daCell->frame(0)->top());
|
|
}
|
|
} else
|
|
(*tmp) = (daCell->frame(0)->top() + *tmp) / 2;
|
|
}
|
|
|
|
tmp = m_rowPositions.at( row + rowSpan );
|
|
if(*tmp == 0)
|
|
(*tmp) = daCell->frame(0)->bottom();
|
|
else { // untested...
|
|
if (static_cast<int>(*tmp/m_doc->pageLayout().ptHeight) > static_cast<int>(daCell->frame(0)->top()/m_doc->pageLayout().ptHeight)) {
|
|
kdDebug(32004) << "next cell is on a new page" << endl;
|
|
TQValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
|
|
while(pageBound != m_pageBoundaries.end() && (*pageBound) < row) ++pageBound;
|
|
if(*pageBound!=row) {
|
|
m_pageBoundaries.insert(pageBound,row++);
|
|
m_rowPositions.insert(tmp,daCell->frame(0)->bottom());
|
|
}
|
|
} else
|
|
(*tmp) = (daCell->frame(0)->bottom() + *tmp) / 2;
|
|
}
|
|
}
|
|
|
|
if ( m_rowPositions.count() != m_rows + 1 ) {
|
|
kdDebug() << name() << " loadCell: m_rowPositions=" << m_rowPositions.count() << " m_rows= " << m_rows << endl;
|
|
}
|
|
}
|
|
|
|
int KWTableFrameSet::paragraphs()
|
|
{
|
|
int paragraphs = 0;
|
|
for (TableIter cells(this) ; cells ; ++cells)
|
|
paragraphs += cells->paragraphs();
|
|
return paragraphs;
|
|
}
|
|
|
|
int KWTableFrameSet::paragraphsSelected()
|
|
{
|
|
int paragraphs = 0;
|
|
for (TableIter cells(this) ; cells ; ++cells)
|
|
paragraphs += cells->paragraphsSelected();
|
|
return paragraphs;
|
|
}
|
|
|
|
bool KWTableFrameSet::statistics( TQProgressDialog *progress, ulong & charsWithSpace, ulong & charsWithoutSpace, ulong & words,
|
|
ulong & sentences, ulong & syllables, ulong & lines, bool selected )
|
|
{
|
|
for (TableIter cells(this) ; cells ; ++cells)
|
|
if( ! cells->statistics( progress, charsWithSpace, charsWithoutSpace, words, sentences, syllables, lines, selected ) )
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void KWTableFrameSet::finalize( ) {
|
|
kdDebug(32004) << "KWTableFrameSet::finalize" << endl;
|
|
|
|
for (TableIter cells(this) ; cells ; ++cells)
|
|
{
|
|
position( cells );
|
|
cells->finalize();
|
|
}
|
|
|
|
recalcCols(0, 0);
|
|
recalcRows(0, 0);
|
|
KWFrameSet::finalize();
|
|
}
|
|
|
|
void KWTableFrameSet::layout()
|
|
{
|
|
for (TableIter cells(this) ; cells ; ++cells)
|
|
cells->layout();
|
|
}
|
|
|
|
void KWTableFrameSet::invalidate()
|
|
{
|
|
for (TableIter cells(this) ; cells ; ++cells)
|
|
cells->invalidate();
|
|
}
|
|
|
|
void KWTableFrameSet::setVisible( bool v )
|
|
{
|
|
for (TableIter cells(this) ; cells ; ++cells)
|
|
cells->setVisible( v );
|
|
|
|
KWFrameSet::setVisible( v );
|
|
}
|
|
|
|
bool KWTableFrameSet::canRemovePage( int num ) {
|
|
/* This one is a lot simpler then the one it overrides, we simply don't have
|
|
to check if the frame contains something, the simple existence of a frame
|
|
is enough
|
|
*/
|
|
TQPtrListIterator<KWFrame> frameIt( frameIterator() );
|
|
for ( ; frameIt.current(); ++frameIt ) {
|
|
if ( frameIt.current()->pageNumber() == num ) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void KWTableFrameSet::addTextFrameSets( TQPtrList<KWTextFrameSet> & lst, bool onlyReadWrite )
|
|
{
|
|
for (TableIter cells(this) ; cells ; ++cells)
|
|
if (!cells->textObject()->protectContent() || onlyReadWrite )
|
|
lst.append(cells);
|
|
}
|
|
|
|
KWTextFrameSet* KWTableFrameSet::nextTextObject( KWFrameSet *obj )
|
|
{
|
|
bool found = false;
|
|
KWTableFrameSet::Cell *tmp = dynamic_cast<KWTableFrameSet::Cell *>(obj);
|
|
|
|
// make sure we have this cell
|
|
if ( tmp ) {
|
|
for(TableIter i(this); i; ++i) {
|
|
if(i.current() == tmp) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
TableIter iter(this);
|
|
if(found)
|
|
iter.goToCell(tmp);
|
|
|
|
for(; iter; ++iter) {
|
|
KWTextFrameSet *newFrm = iter->nextTextObject( obj );
|
|
if(newFrm && newFrm->textObject()->needSpellCheck())
|
|
return newFrm;
|
|
}
|
|
|
|
return 0L;
|
|
}
|
|
|
|
void KWTableFrameSet::setZOrder()
|
|
{
|
|
for( TableIter cells(this) ; cells ; ++cells ) {
|
|
cells->setZOrder();
|
|
}
|
|
|
|
}
|
|
|
|
// TODO provide toPlainText() (reimplemented from KWFrameSet)
|
|
|
|
TQByteArray KWTableFrameSet::convertTableToText() // should be const, but TableIter doesn't allow it
|
|
{
|
|
KWOasisSaver oasisSaver( m_doc );
|
|
for (TableIter cells(this); cells; ++cells)
|
|
{
|
|
cells->textObject()->saveOasisContent( oasisSaver.bodyWriter(), oasisSaver.savingContext() );
|
|
}
|
|
if ( !oasisSaver.finish() )
|
|
return TQByteArray();
|
|
return oasisSaver.data();
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
void KWTableFrameSet::printDebug( KWFrame * theFrame )
|
|
{
|
|
KWTableFrameSet::Cell *daCell = dynamic_cast<KWTableFrameSet::Cell *>( theFrame->frameSet() );
|
|
Q_ASSERT( daCell );
|
|
if ( daCell ) {
|
|
kdDebug(32004) << " | |- row :" << daCell->firstRow() << endl;
|
|
kdDebug(32004) << " | |- col :" << daCell->firstColumn() << endl;
|
|
kdDebug(32004) << " | |- rows:" << daCell->rowSpan() << endl;
|
|
kdDebug(32004) << " | +- cols:" << daCell->columnSpan() << endl;
|
|
}
|
|
}
|
|
|
|
void KWTableFrameSet::printArrayDebug() {
|
|
kdDebug(32004) << " | Row/Cell arrays" << endl;
|
|
Q_ASSERT( m_rows == m_rowArray.size() );
|
|
for ( unsigned int row = 0; row < m_rows; ++row ) {
|
|
TQString str = TQString( " | Row %1: " ).arg( row );
|
|
for ( unsigned int col = 0; col < getColumns(); ++col )
|
|
str += TQString("| 0x%1 ").arg( (unsigned long)(*m_rowArray[row])[col], 0, 16 );
|
|
kdDebug(32004) << str<< " |" << endl;
|
|
}
|
|
}
|
|
|
|
void KWTableFrameSet::printDebug() {
|
|
kdDebug(32004) << " | Table size (" << m_rows << "x" << getColumns() << ")" << endl;
|
|
kdDebug(32004) << " | col " << 0 << ": " << m_colPositions[0] << endl;
|
|
for(unsigned int i=1;i<m_colPositions.count(); ++i)
|
|
kdDebug(32004) << " | | " << i << ": " << m_colPositions[i] << endl;
|
|
kdDebug(32004) << " | row " << 0 << ": " << m_rowPositions[0] << endl;
|
|
for(unsigned int i=1;i<m_rowPositions.count(); ++i)
|
|
kdDebug(32004) << " | | " << i << ": " << m_rowPositions[i] << endl;
|
|
|
|
printArrayDebug();
|
|
KWFrameSet::printDebug();
|
|
}
|
|
|
|
#endif
|
|
|
|
// ===
|
|
|
|
KWTableFrameSet::Cell::Cell( KWTableFrameSet *table, unsigned int row, unsigned int col, const TQString &/*name*/ ) :
|
|
KWTextFrameSet( table->m_doc,
|
|
// Generate frameset name from table_name+row+col
|
|
i18n("Hello dear translator :), 1 is the table name, 2 and 3 are row and column", "%1 Cell %2,%3")
|
|
.arg( table->name() ).arg(row).arg(col) )
|
|
{
|
|
m_row = row;
|
|
m_col = col;
|
|
m_rows = 1;
|
|
m_cols = 1;
|
|
m_isJoinedCell = false;
|
|
setGroupManager( table );
|
|
table->addCell( this );
|
|
}
|
|
|
|
KWTableFrameSet::Cell::Cell( KWTableFrameSet *table, const Cell &original ) :
|
|
KWTextFrameSet( table->m_doc, original.m_name+'_' )
|
|
{
|
|
m_row = original.m_row;
|
|
m_col = original.m_col;
|
|
m_rows = original.m_rows;
|
|
m_cols = original.m_cols;
|
|
m_isJoinedCell = original.m_isJoinedCell;
|
|
setGroupManager( table );
|
|
table->addCell( this );
|
|
}
|
|
|
|
KWTableFrameSet::Cell::~Cell()
|
|
{
|
|
}
|
|
|
|
bool KWTableFrameSet::Cell::isAboveOrLeftOf( unsigned row, unsigned col ) const
|
|
{
|
|
return ( m_row < row ) || ( ( m_row == row ) && ( m_col < col ) );
|
|
}
|
|
|
|
bool KWTableFrameSet::Cell::containsCell( unsigned row, unsigned col ) const
|
|
{
|
|
return ( m_row <= row &&
|
|
m_col <= col &&
|
|
rowAfter() > row &&
|
|
columnAfter() > col );
|
|
}
|
|
|
|
void KWTableFrameSet::Cell::addFrame(KWFrame *_frame, bool recalc) {
|
|
if(groupmanager())
|
|
groupmanager()->addFrame(_frame, recalc);
|
|
KWTextFrameSet::addFrame(_frame, recalc);
|
|
}
|
|
|
|
void KWTableFrameSet::Cell::frameDeleted( KWFrame* frm, bool recalc )
|
|
{
|
|
if(groupmanager())
|
|
groupmanager()->deleteFrame( frm, false, recalc );
|
|
}
|
|
|
|
double KWTableFrameSet::Cell::leftBorder() {
|
|
double b = frame(0)->leftBorder().width();
|
|
if(b==0.0)
|
|
return 0.0;
|
|
if(m_col==0) // left most cell
|
|
return b;
|
|
return (b / 2);
|
|
}
|
|
|
|
double KWTableFrameSet::Cell::rightBorder() {
|
|
double b=frame(0)->rightBorder().width();
|
|
if(b==0.0)
|
|
return 0.0;
|
|
if(m_col+m_cols==m_groupmanager->getColumns()) // right most cell
|
|
return b;
|
|
return (b / 2);
|
|
}
|
|
|
|
double KWTableFrameSet::Cell::topBorder() {
|
|
double b = frame(0)->topBorder().width();
|
|
if(b==0.0)
|
|
return 0.0;
|
|
if(m_row==0) // top most cell
|
|
return b;
|
|
return (b / 2);
|
|
}
|
|
|
|
double KWTableFrameSet::Cell::bottomBorder() {
|
|
double b = frame(0)->bottomBorder().width();
|
|
if(b==0.0)
|
|
return 0.0;
|
|
if(rowAfter() == m_groupmanager->m_rows) // bottom most cell
|
|
return b;
|
|
return (b / 2);
|
|
}
|
|
|
|
void KWTableFrameSet::Cell::setLeftBorder(KoBorder newBorder) {
|
|
KWFrame *f = frame(0);
|
|
double diff = f->leftBorder().width() - newBorder.width();
|
|
f->setLeftBorder(newBorder);
|
|
|
|
if((diff > 0.01 || diff < -0.01) && m_col!=0) {
|
|
diff = diff / 2; // if not outer edge only use halve
|
|
m_groupmanager->cell(m_row, m_col-1)->setRightBorder(newBorder);
|
|
}
|
|
f->setLeft(f->left() - diff);
|
|
}
|
|
|
|
void KWTableFrameSet::Cell::setRightBorder(KoBorder newBorder) {
|
|
KWFrame *f = frame(0);
|
|
double diff = f->rightBorder().width() - newBorder.width();
|
|
f->setRightBorder(newBorder);
|
|
|
|
if((diff > 0.01 || diff < -0.01) && m_col+m_cols!=m_groupmanager->getColumns()) {
|
|
diff = diff / 2; // if not outer edge only use halve
|
|
m_groupmanager->cell(m_row, m_col+1)->setLeftBorder(newBorder);
|
|
}
|
|
f->setRight(f->right() + diff);
|
|
}
|
|
|
|
void KWTableFrameSet::Cell::setTopBorder(KoBorder newBorder) {
|
|
KWFrame *f = frame(0);
|
|
double diff = f->topBorder().width() - newBorder.width();
|
|
f->setTopBorder(newBorder);
|
|
|
|
if((diff > 0.01 || diff < -0.01) && m_row!=0) {
|
|
diff = diff / 2; // if not outer edge only use halve
|
|
m_groupmanager->cell(m_row-1, m_col)->setBottomBorder(newBorder);
|
|
}
|
|
f->setTop(f->top() - diff);
|
|
}
|
|
|
|
void KWTableFrameSet::Cell::setBottomBorder(KoBorder newBorder) {
|
|
KWFrame *f = frame(0);
|
|
double diff = f->bottomBorder().width() - newBorder.width();
|
|
f->setBottomBorder(newBorder);
|
|
|
|
if((diff > 0.01 || diff < -0.01) && rowAfter() != m_groupmanager->m_rows) {
|
|
diff = diff / 2; // if not outer edge only use halve
|
|
m_groupmanager->cell(m_row+1, m_col)->setTopBorder(newBorder);
|
|
}
|
|
f->setBottom(f->bottom() + diff);
|
|
}
|
|
|
|
void KWTableFrameSet::Cell::setZOrder()
|
|
{
|
|
TQPtrListIterator<KWFrame> frameIt = frameIterator();
|
|
for ( ; frameIt.current(); ++frameIt )
|
|
{
|
|
(*frameIt)->setZOrder( kWordDocument()->maxZOrder( (*frameIt)->pageNumber() ) + 1 );
|
|
}
|
|
}
|
|
|
|
void KWTableFrameSet::Cell::drawContents( TQPainter * painter, const TQRect & crect,
|
|
const TQColorGroup & cg, bool onlyChanged, bool resetChanged,
|
|
KWFrameSetEdit * edit, KWViewMode * viewMode, KWFrameViewManager *fvm )
|
|
{
|
|
bool printing = painter->device()->devType() == TQInternal::Printer;
|
|
bool drawPreviewLines = viewMode && viewMode->drawFrameBorders();
|
|
TQRect cellRect = crect;
|
|
if(!printing && drawPreviewLines) {
|
|
// Make sure the clipping is changed so the preview lines (frame borders) are not overwritten.
|
|
TQRect zoomedRect( m_doc->zoomRect(*frame(0)) );
|
|
TQRect innerFrameRect( viewMode->normalToView( zoomedRect ) );
|
|
innerFrameRect.addCoords(1, 1, -1, -1); // move and shrink
|
|
cellRect = innerFrameRect.intersect(crect);
|
|
}
|
|
KWTextFrameSet::drawContents(painter, cellRect, cg, onlyChanged, resetChanged, edit, viewMode, fvm);
|
|
}
|
|
|
|
KWTableFrameSetEdit::~KWTableFrameSetEdit()
|
|
{
|
|
if ( m_currentCell )
|
|
m_currentCell->terminate();
|
|
delete m_currentCell;
|
|
}
|
|
|
|
void KWTableFrameSetEdit::mousePressEvent( TQMouseEvent * e, const TQPoint & nPoint, const KoPoint & dPoint )
|
|
{
|
|
setCurrentCell( dPoint );
|
|
if ( m_currentCell )
|
|
m_currentCell->mousePressEvent( e, nPoint, dPoint );
|
|
}
|
|
|
|
void KWTableFrameSetEdit::setCurrentCell( const KoPoint & dPoint )
|
|
{
|
|
KWFrameSet *fs = tableFrameSet()->cellByPos( dPoint.x(), dPoint.y() );
|
|
KWTextFrameSet *textframeSet = dynamic_cast<KWTextFrameSet *>(fs);
|
|
|
|
if ( textframeSet&& textframeSet->protectContent() && !tableFrameSet()->kWordDocument()->cursorInProtectedArea())
|
|
return;
|
|
|
|
if ( fs && ( !m_currentCell || fs != m_currentCell->frameSet() ) )
|
|
setCurrentCell( fs );
|
|
}
|
|
|
|
void KWTableFrameSetEdit::setCurrentCell( KWFrameSet * fs, bool eraseSelection )
|
|
{
|
|
bool oldProtectContent = false;
|
|
KWTextFrameSet *textframeSet=0L;
|
|
if ( m_currentCell )
|
|
textframeSet = dynamic_cast<KWTextFrameSet *>(m_currentCell->frameSet());
|
|
if ( textframeSet )
|
|
oldProtectContent = textframeSet->protectContent();
|
|
|
|
if ( m_currentCell )
|
|
{
|
|
m_currentCell->terminate(eraseSelection);
|
|
delete m_currentCell;
|
|
}
|
|
m_currentCell = fs->createFrameSetEdit( m_canvas );
|
|
textframeSet = dynamic_cast<KWTextFrameSet *>(m_currentCell->frameSet());
|
|
if ( textframeSet )
|
|
{
|
|
if ( oldProtectContent != textframeSet->protectContent())
|
|
{
|
|
m_canvas->kWordDocument()->updateTextFrameSetEdit();
|
|
}
|
|
}
|
|
|
|
|
|
m_currentFrame = fs->frame( 0 );
|
|
KWTextFrameSetEdit *textframeSetEdit = dynamic_cast<KWTextFrameSetEdit *>(m_currentCell);
|
|
if ( textframeSetEdit )
|
|
{
|
|
textframeSetEdit->ensureCursorVisible();
|
|
//refresh koruler
|
|
m_canvas->gui()->getView()->slotUpdateRuler();
|
|
}
|
|
}
|
|
|
|
KWFrameSetEdit* KWTableFrameSetEdit::currentTextEdit()
|
|
{
|
|
return m_currentCell;
|
|
}
|
|
|
|
|
|
void KWTableFrameSetEdit::keyPressEvent( TQKeyEvent * e )
|
|
{
|
|
// This method handles the up/left/down/right navigation keys in tables
|
|
if ( !m_currentCell )
|
|
return;
|
|
KWTableFrameSet::Cell *cell = static_cast<KWTableFrameSet::Cell *>(m_currentCell->frameSet());
|
|
KWTextFrameSet *textframeSet = dynamic_cast<KWTextFrameSet *>(m_currentCell->frameSet());
|
|
bool moveToOtherCell = true;
|
|
if(textframeSet)
|
|
{
|
|
// don't move to an adjacent cell when we are selecting text
|
|
KoTextDocument * textdoc = textframeSet->textDocument();
|
|
if(textdoc->hasSelection( KoTextDocument::Standard ))
|
|
moveToOtherCell=false;
|
|
}
|
|
KWTableFrameSet::Cell *fs = 0L;
|
|
|
|
bool tab=false; // No tab key pressed
|
|
if(moveToOtherCell)
|
|
{
|
|
switch( e->key() ) {
|
|
case TQt::Key_Up:
|
|
{
|
|
if(!(static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor()->parag()->prev())
|
|
{
|
|
KWTableFrameSet* tableFrame=tableFrameSet();
|
|
int row = cell->firstRow() - 1;
|
|
int col = cell->firstColumn();
|
|
if (row < 0) { // Wrap at top of table
|
|
col--; // Goes to column on the left
|
|
row = tableFrame->getRows() - 1;
|
|
}
|
|
if (col < 0) { // It was the first column
|
|
// Maybe exit the table instead?
|
|
col = tableFrame->getColumns() - 1;
|
|
row = tableFrame->getRows() - 1;
|
|
}
|
|
fs=tableFrame->cell(row,col);
|
|
// Not needed. cell gives us the right one already
|
|
//if (fs && fs->firstRow() != static_cast<unsigned int>(row)) { // Merged cell
|
|
// fs=tableFrame->cell( row - fs->rowSpan() + 1, col );
|
|
//}
|
|
}
|
|
}
|
|
break;
|
|
case TQt::Key_Down:
|
|
{
|
|
if(!(static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor()->parag()->next())
|
|
{
|
|
KWTableFrameSet* tableFrame=tableFrameSet();
|
|
unsigned int row = cell->rowAfter();
|
|
unsigned int col = cell->firstColumn();
|
|
if(row >= tableFrame->getRows()) { // Wrap at bottom of table
|
|
row=0;
|
|
col++; // Go to next column
|
|
}
|
|
if(col >= tableFrame->getColumns()) { // It was the last one
|
|
// Maybe exit the table instead?
|
|
col=0;
|
|
row=0;
|
|
}
|
|
fs=tableFrame->cell(row,col);
|
|
Q_ASSERT( fs );
|
|
Q_ASSERT( fs->firstRow() == row ); // We can't end up in the middle of a merged cell here.
|
|
}
|
|
}
|
|
break;
|
|
case TQt::Key_Backtab:
|
|
tab=true;
|
|
if (e->state() & TQt::ControlButton)
|
|
break; // Break if tab was pressed with Control (in *any* key combination)
|
|
// Do not break
|
|
case TQt::Key_Left:
|
|
{
|
|
KoTextCursor *cur = (static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor();
|
|
if ( tab || (!cur->parag()->prev()&&cur->index()==0) )
|
|
{
|
|
KWTableFrameSet* tableFrame=tableFrameSet();
|
|
int row=cell->firstRow();
|
|
int col=cell->firstColumn() - 1;
|
|
if(col < 0) { // Wrap at first column
|
|
col = (int)tableFrame->getColumns()-1;
|
|
row--; // Go up
|
|
}
|
|
if(row < 0) { // It was the first row
|
|
// Maybe exit the table instead?
|
|
col = (int)tableFrame->getColumns()-1;
|
|
row = (int)tableFrame->getRows()-1;
|
|
}
|
|
fs=tableFrame->cell(row,col);
|
|
// Not needed. cell gives us the right one already
|
|
//if(fs && (int)fs->m_col != col) { // Merged cell
|
|
// fs=tableFrame->cell( row, col - fs->columnSpan() + 1 );
|
|
//}
|
|
}
|
|
}
|
|
break;
|
|
case TQt::Key_Tab:
|
|
tab=true;
|
|
if (e->state() & TQt::ControlButton)
|
|
break; // Break if tab was pressed with Control (in *any* key combination)
|
|
// Do not break
|
|
case TQt::Key_Right:
|
|
{
|
|
KoTextCursor *cur = (static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor();
|
|
if( tab || (!cur->parag()->next()&&cur->index()==cur->parag()->string()->length()-1) )
|
|
{
|
|
KWTableFrameSet* tableFrame=tableFrameSet();
|
|
unsigned int row = cell->firstRow();
|
|
unsigned int col = cell->columnAfter();
|
|
if(col >= tableFrame->getColumns()) { // Wrap after last column
|
|
col = 0;
|
|
row++; // Go down one row
|
|
}
|
|
if(row >= tableFrame->getRows()) { // It was the last row
|
|
// Maybe exit the table instead?
|
|
col = 0;
|
|
row = 0;
|
|
}
|
|
fs=tableFrame->cell(row,col);
|
|
Q_ASSERT( fs );
|
|
Q_ASSERT( fs->firstRow() == row ); // We can't end up in the middle of a merged cell here.
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if ( fs )
|
|
{
|
|
//don't switch to a protected cell protected when cursor in protected areas was disabled.
|
|
if ( fs->textObject()->protectContent() && !tableFrameSet()->kWordDocument()->cursorInProtectedArea())
|
|
return;
|
|
setCurrentCell( fs );
|
|
}
|
|
else if ( textframeSet )
|
|
{
|
|
if ( !textframeSet->textObject()->protectContent() )
|
|
{
|
|
if (tab && (e->state() & TQt::ControlButton) )
|
|
{
|
|
TQKeyEvent event(TQEvent::KeyPress, TQt::Key_Tab, 9, 0, TQChar(9));
|
|
m_currentCell->keyPressEvent( &event );
|
|
}
|
|
else
|
|
m_currentCell->keyPressEvent( e );
|
|
}
|
|
else if(e->text().length() > 0)
|
|
KMessageBox::information(0L, i18n("Read-only content cannot be changed. No modifications will be accepted."));
|
|
}
|
|
}
|
|
|
|
void KWTableFrameSetEdit::keyReleaseEvent( TQKeyEvent * e )
|
|
{
|
|
if ( m_currentCell )
|
|
m_currentCell->keyReleaseEvent( e );
|
|
}
|
|
|
|
void KWTableFrameSetEdit::imStartEvent( TQIMEvent* e )
|
|
{
|
|
if ( m_currentCell )
|
|
m_currentCell->imStartEvent( e );
|
|
}
|
|
|
|
void KWTableFrameSetEdit::imComposeEvent( TQIMEvent* e )
|
|
{
|
|
if ( m_currentCell )
|
|
m_currentCell->imComposeEvent( e );
|
|
}
|
|
|
|
void KWTableFrameSetEdit::imEndEvent( TQIMEvent* e )
|
|
{
|
|
if ( m_currentCell )
|
|
m_currentCell->imEndEvent( e );
|
|
}
|
|
|
|
void KWTableFrameSetEdit::dragMoveEvent( TQDragMoveEvent * e, const TQPoint &n, const KoPoint &d )
|
|
{
|
|
kdDebug(32004)<<"m_currentCell :"<<m_currentCell<<endl;
|
|
if ( m_currentCell )
|
|
{
|
|
KWFrameSet *fs = tableFrameSet()->cellByPos( d.x(), d.y() );
|
|
kdDebug(32004)<<"fs :"<<fs <<endl;
|
|
if(fs && fs != m_currentCell->frameSet())
|
|
setCurrentCell(fs, false);
|
|
if(m_currentCell)
|
|
m_currentCell->dragMoveEvent( e, n, d );
|
|
}
|
|
else
|
|
{
|
|
setCurrentCell( d );
|
|
kdDebug(32004)<<"after m_currentCell :"<<m_currentCell<<endl;
|
|
if(m_currentCell)
|
|
m_currentCell->dragMoveEvent( e, n, d );
|
|
}
|
|
}
|
|
|
|
void KWTableFrameSet::Row::addCell( Cell *cell )
|
|
{
|
|
if ( m_cellArray.size() < cell->columnAfter())
|
|
m_cellArray.resize( cell->columnAfter() );
|
|
for ( uint col = cell->firstColumn() ; col < cell->columnAfter(); ++col )
|
|
m_cellArray.insert( col, cell );
|
|
}
|
|
|
|
void KWTableFrameSet::Row::removeCell( Cell* cell )
|
|
{
|
|
for ( uint col = cell->firstColumn() ; col < cell->columnAfter(); ++col )
|
|
m_cellArray.remove( col );
|
|
}
|
|
|
|
template<>
|
|
KWTableFrameSet::Cell*
|
|
KWTableFrameSet::TableIterator<KWTableFrameSet::VISIT_CELL>::operator++()
|
|
{
|
|
if(!m_cell) return 0;
|
|
|
|
Cell *ret = m_cell;
|
|
|
|
do{
|
|
// check for end of row first
|
|
if(m_table->cell(m_row,m_col)->lastColumn() >= m_limit[RIGHT] ) {
|
|
// now check for end of column
|
|
if (m_row >= m_limit[LOW]){
|
|
// at end of traversal
|
|
m_cell = 0;
|
|
break;
|
|
}
|
|
else {
|
|
// goto first grid position in next row
|
|
m_row += 1;
|
|
m_col = m_limit[LEFT];
|
|
}
|
|
}
|
|
else {
|
|
// goto next cell in row
|
|
m_col = m_table->cell(m_row, m_col)->columnAfter();
|
|
}
|
|
|
|
m_cell = m_table->cell(m_row,m_col);
|
|
} while( m_cell && !m_cell->isFirstGridPosnFast(m_row,m_col) );
|
|
|
|
return ret;
|
|
}
|
|
|
|
template<>
|
|
KWTableFrameSet::Cell*
|
|
KWTableFrameSet::TableIterator<KWTableFrameSet::VISIT_GRID>::operator++()
|
|
{
|
|
if(!m_cell) return 0;
|
|
|
|
Cell *ret = m_cell;
|
|
// check for end of row
|
|
if(m_col == m_limit[RIGHT]) {
|
|
if(m_row == m_limit[LOW]) { // end of traversal
|
|
m_row = 0;
|
|
m_col = 0;
|
|
m_cell = 0;
|
|
}
|
|
else { // go to next row
|
|
m_row += 1;
|
|
m_col = m_limit[LEFT];
|
|
m_cell = m_table->cell(m_row, m_col);
|
|
}
|
|
}
|
|
else { // move to next cell in row
|
|
m_col += 1;
|
|
m_cell = m_table->cell(m_row, m_col);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
KWTableFrameSet::MarkedIterator::MarkedIterator(KWTableFrameSet *table) :
|
|
GridIter(table)
|
|
{
|
|
// clear all the cell marks
|
|
for(GridIter cell(table); cell; ++cell)
|
|
cell->clearMark();
|
|
|
|
if ( current() ) {
|
|
// kdDebug() << "MarkedIterator: visit: "
|
|
// << TQString("| 0x%1 ").arg((unsigned long)current(), 0, 16) << endl;
|
|
current()->setMark();
|
|
}
|
|
}
|
|
|
|
KWTableFrameSet::Cell *
|
|
KWTableFrameSet::MarkedIterator::operator++()
|
|
{
|
|
Cell *ret = GridIter::operator++();
|
|
|
|
while ( current() && current()->marked() ) {
|
|
GridIter::operator++();
|
|
}
|
|
if ( current() ) {
|
|
// kdDebug() << "MarkedIterator: visit: "
|
|
// << TQString("| 0x%1 ").arg((unsigned long)current(), 0, 16) << endl;
|
|
current()->setMark();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template<>
|
|
KWTableFrameSet::TableIterator<KWTableFrameSet::CHECKED>::TableIterator(KWTableFrameSet *table):
|
|
m_table(table)
|
|
{
|
|
Q_ASSERT(m_table);
|
|
set_limits(0, (int)m_table->getColumns() - 1, 0, (int)m_table->getRows() - 1);
|
|
|
|
Cell *c = 0;
|
|
for(uint i = m_limit[HIGH]; i <= m_limit[LOW]; ++i)
|
|
for(uint j = m_limit[LEFT]; j <= m_limit[RIGHT]; ++j) {
|
|
|
|
c = m_table->cell(i,j);
|
|
if(c) c->clearMark();
|
|
}
|
|
toFirstCell();
|
|
}
|
|
|
|
template<>
|
|
KWTableFrameSet::Cell*
|
|
KWTableFrameSet::TableIterator<KWTableFrameSet::CHECKED>::operator++ ()
|
|
{
|
|
|
|
Cell *ret = m_cell;
|
|
if(!ret) return 0;
|
|
|
|
ret->setMark();
|
|
m_cell = 0;
|
|
uint i = m_row; uint j = m_col;
|
|
|
|
for(; i <= m_limit[LOW]; ++i) {
|
|
|
|
for(j = 0; j <= m_limit[RIGHT]; ++j) {
|
|
m_cell = m_table->cell(i,j);
|
|
if( m_cell && !m_cell->marked() ){
|
|
m_row = i; m_col = j;
|
|
goto out;
|
|
}
|
|
else if(i == m_limit[LOW] && j == m_limit[RIGHT]){
|
|
m_cell = 0;
|
|
goto out;
|
|
}
|
|
}
|
|
}
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
template<>
|
|
KWTableFrameSet::Cell*
|
|
KWTableFrameSet::TableIterator<KWTableFrameSet::CHECKED>::toFirstCell ()
|
|
{
|
|
m_cell = 0;
|
|
for(uint i = m_limit[HIGH]; i <= m_limit[LOW]; ++i)
|
|
for(uint j = m_limit[LEFT]; j <= m_limit[RIGHT]; ++j) {
|
|
m_cell = m_table->cell(i,j);
|
|
if(m_cell) {
|
|
m_row = i; m_col = j;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
out:
|
|
return m_cell;
|
|
}
|
|
|
|
RemovedRow::RemovedRow() :
|
|
m_row(0), m_index(0), m_rowHeight(0.0)
|
|
{
|
|
|
|
}
|
|
|
|
RemovedRow::~RemovedRow()
|
|
{
|
|
// free cells as well ???
|
|
delete m_row;
|
|
}
|
|
|
|
KWTableFrameSet::Row *RemovedRow::takeRow()
|
|
{
|
|
Q_ASSERT(m_row);
|
|
KWTableFrameSet::Row *ret = m_row;
|
|
m_row = 0;
|
|
return ret;
|
|
}
|
|
|
|
RemovedColumn::RemovedColumn()
|
|
: m_column(), m_removed(), m_index(0), m_width(0), m_initialized(false){ }
|
|
|
|
|
|
#include "KWTableFrameSet.moc"
|