|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 2005-2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program 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 General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <tqstringlist.h>
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
#include "kspread_cell.h"
|
|
|
|
#include "kspread_doc.h"
|
|
|
|
#include "kspread_global.h"
|
|
|
|
#include "kspread_map.h"
|
|
|
|
#include "kspread_sheet.h"
|
|
|
|
#include "kspread_util.h"
|
|
|
|
#include "kspread_view.h"
|
|
|
|
|
|
|
|
#include "region.h"
|
|
|
|
|
|
|
|
namespace KSpread
|
|
|
|
{
|
|
|
|
|
|
|
|
class Region::Private
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Private()
|
|
|
|
{
|
|
|
|
view = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
View* view;
|
|
|
|
TQValueList<Element*> cells;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
class Region
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
Region::Region()
|
|
|
|
{
|
|
|
|
d = new Private();
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Region(View* view, const TQString& string, Sheet* sheet)
|
|
|
|
{
|
|
|
|
d = new Private();
|
|
|
|
d->view = view;
|
|
|
|
|
|
|
|
if (string.isEmpty())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
TQStringList substrings = TQStringList::split(';', string);
|
|
|
|
TQStringList::ConstIterator end = substrings.constEnd();
|
|
|
|
for (TQStringList::ConstIterator it = substrings.constBegin(); it != end; ++it)
|
|
|
|
{
|
|
|
|
TQString sRegion = *it;
|
|
|
|
if (!sheet)
|
|
|
|
{
|
|
|
|
sheet = filterSheetName(sRegion);
|
|
|
|
}
|
|
|
|
|
|
|
|
int delimiterPos = sRegion.find(':');
|
|
|
|
if (delimiterPos > -1)
|
|
|
|
{
|
|
|
|
// range
|
|
|
|
Point ul(sRegion.left(delimiterPos));
|
|
|
|
Point lr(sRegion.mid(delimiterPos + 1));
|
|
|
|
|
|
|
|
if (ul.isValid() && lr.isValid())
|
|
|
|
{
|
|
|
|
Range* range = createRange(sRegion);
|
|
|
|
range->setSheet(sheet);
|
|
|
|
d->cells.append(range);
|
|
|
|
}
|
|
|
|
else if (ul.isValid())
|
|
|
|
{
|
|
|
|
Point* point = createPoint(sRegion.left(delimiterPos));
|
|
|
|
point->setSheet(sheet);
|
|
|
|
d->cells.append(point);
|
|
|
|
}
|
|
|
|
else // lr.isValid()
|
|
|
|
{
|
|
|
|
Point* point = createPoint(sRegion.right(delimiterPos + 1));
|
|
|
|
point->setSheet(sheet);
|
|
|
|
d->cells.append(point);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// single cell
|
|
|
|
Point* point = createPoint(sRegion);
|
|
|
|
point->setSheet(sheet);
|
|
|
|
d->cells.append(point);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Region(const TQRect& rect, Sheet* sheet)
|
|
|
|
{
|
|
|
|
d = new Private();
|
|
|
|
|
|
|
|
if (rect.isNull())
|
|
|
|
{
|
|
|
|
kdError(36001) << "Region::Region(const TQRect&): TQRect is empty!" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
add(rect, sheet);
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Region(const TQPoint& point, Sheet* sheet)
|
|
|
|
{
|
|
|
|
d = new Private();
|
|
|
|
|
|
|
|
if (point.isNull())
|
|
|
|
{
|
|
|
|
kdError(36001) << "Region::Region(const TQPoint&): TQPoint is empty!" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
add(point, sheet);
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Region(const Region& list)
|
|
|
|
{
|
|
|
|
d = new Private();
|
|
|
|
d->view = list.d->view;
|
|
|
|
|
|
|
|
ConstIterator end(list.d->cells.constEnd());
|
|
|
|
for (ConstIterator it = list.d->cells.constBegin(); it != end; ++it)
|
|
|
|
{
|
|
|
|
Element *element = *it;
|
|
|
|
if (element->type() == Element::Point)
|
|
|
|
{
|
|
|
|
Point* point = static_cast<Point*>(element);
|
|
|
|
d->cells.append(createPoint(*point));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Range* range = static_cast<Range*>(element);
|
|
|
|
d->cells.append(createRange(*range));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Region(int x, int y, Sheet* sheet)
|
|
|
|
{
|
|
|
|
d = new Private();
|
|
|
|
|
|
|
|
if (x<1 || y<1)
|
|
|
|
{
|
|
|
|
kdError(36001) << "Region::Region(int x, int y): Coordinates are invalid!" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
add(TQPoint(x,y), sheet);
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Region(int x, int y, int width, int height, Sheet* sheet)
|
|
|
|
{
|
|
|
|
d = new Private();
|
|
|
|
|
|
|
|
if (x<1 || y<1 || width<1 || height<1)
|
|
|
|
{
|
|
|
|
kdError(36001) << "Region::Region(int x, int y, int width, int height): Dimensions are invalid!" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
add(TQRect(x,y,width,height), sheet);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Region::~Region()
|
|
|
|
{
|
|
|
|
d->cells.clear();
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
View* Region::view() const
|
|
|
|
{
|
|
|
|
Q_ASSERT(d->view);
|
|
|
|
return d->view;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Region::setView(View* view)
|
|
|
|
{
|
|
|
|
d->view = view;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::isValid() const
|
|
|
|
{
|
|
|
|
ConstIterator end = d->cells.constEnd();
|
|
|
|
for (ConstIterator it = d->cells.constBegin(); it != end; ++it)
|
|
|
|
{
|
|
|
|
if (!(*it)->isValid())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::isSingular() const
|
|
|
|
{
|
|
|
|
if (d->cells.isEmpty() || d->cells.count() > 1 || (*d->cells.constBegin())->type() != Element::Point)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::isContiguous() const
|
|
|
|
{
|
|
|
|
if (d->cells.count() != 1 || !isValid())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Region::name(Sheet* originSheet) const
|
|
|
|
{
|
|
|
|
TQStringList names;
|
|
|
|
ConstIterator endOfList(d->cells.constEnd());
|
|
|
|
for (ConstIterator it = d->cells.constBegin(); it != endOfList; ++it)
|
|
|
|
{
|
|
|
|
Element *element = *it;
|
|
|
|
names += element->name(originSheet);
|
|
|
|
}
|
|
|
|
return names.isEmpty() ? "" : names.join(";");
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Element* Region::add(const TQPoint& point, Sheet* sheet)
|
|
|
|
{
|
|
|
|
// kdDebug() << k_funcinfo << endl;
|
|
|
|
if (point.x() < 1 || point.y() < 1)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
Iterator it = insert(d->cells.end(), point, sheet, false);
|
|
|
|
return (it == d->cells.end()) ? 0 : *it;
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Element* Region::add(const TQRect& range, Sheet* sheet)
|
|
|
|
{
|
|
|
|
if (range.normalize().width() == 0 || range.normalize().height() == 0)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (range.size() == TQSize(1,1))
|
|
|
|
{
|
|
|
|
return add(range.topLeft(), sheet);
|
|
|
|
}
|
|
|
|
Iterator it = insert(d->cells.end(), range, sheet, false);
|
|
|
|
return (it == d->cells.end()) ? 0 : *it;
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Element* Region::add(const Region& region)
|
|
|
|
{
|
|
|
|
ConstIterator endOfList(region.d->cells.constEnd());
|
|
|
|
for (ConstIterator it = region.d->cells.constBegin(); it != endOfList; ++it)
|
|
|
|
{
|
|
|
|
add((*it)->rect(), (*it)->sheet());
|
|
|
|
}
|
|
|
|
return d->cells.isEmpty() ? 0 : d->cells.last();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Region::sub(const TQPoint& point)
|
|
|
|
{
|
|
|
|
// TODO Stefan: Improve!
|
|
|
|
Iterator endOfList(d->cells.end());
|
|
|
|
for (Iterator it = d->cells.begin(); it != endOfList; ++it)
|
|
|
|
{
|
|
|
|
Element *element = *it;
|
|
|
|
if (element->rect() == TQRect(point,point))
|
|
|
|
{
|
|
|
|
delete element;
|
|
|
|
d->cells.remove(element);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Region::sub(const TQRect& range)
|
|
|
|
{
|
|
|
|
// TODO Stefan: Improve!
|
|
|
|
Iterator endOfList(d->cells.end());
|
|
|
|
for (Iterator it = d->cells.begin(); it != endOfList; ++it)
|
|
|
|
{
|
|
|
|
Element *element = *it;
|
|
|
|
if (element->rect().normalize() == range.normalize())
|
|
|
|
{
|
|
|
|
delete element;
|
|
|
|
d->cells.remove(element);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Region::sub(const Region& region)
|
|
|
|
{
|
|
|
|
ConstIterator endOfList(region.constEnd());
|
|
|
|
for (ConstIterator it = region.constBegin(); it != endOfList; ++it)
|
|
|
|
{
|
|
|
|
Element *element = *it;
|
|
|
|
if (element->type() == Element::Point)
|
|
|
|
{
|
|
|
|
Point* point = static_cast<Point*>(element);
|
|
|
|
sub(point->pos());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sub(element->rect());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Element* Region::eor(const TQPoint& point, Sheet* sheet)
|
|
|
|
{
|
|
|
|
bool containsPoint = false;
|
|
|
|
|
|
|
|
Iterator it = cells().begin();
|
|
|
|
Iterator endOfList = cells().end();
|
|
|
|
while (it != endOfList)
|
|
|
|
{
|
|
|
|
if (!(*it)->contains(point))
|
|
|
|
{
|
|
|
|
++it;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
containsPoint = true;
|
|
|
|
int x = point.x();
|
|
|
|
int y = point.y();
|
|
|
|
TQRect fullRange = (*it)->rect().normalize();
|
|
|
|
delete *it;
|
|
|
|
it = cells().remove(it);
|
|
|
|
|
|
|
|
// top range
|
|
|
|
int left = fullRange.left();
|
|
|
|
int top = fullRange.top();
|
|
|
|
int width = fullRange.width();
|
|
|
|
int height = y - top;
|
|
|
|
if (height > 0)
|
|
|
|
{
|
|
|
|
insert(it, TQRect(left, top, width, height), sheet);
|
|
|
|
}
|
|
|
|
// left range
|
|
|
|
left = fullRange.left();
|
|
|
|
top = y;
|
|
|
|
width = TQMAX(0, x - left);
|
|
|
|
height = 1;
|
|
|
|
if (width > 0)
|
|
|
|
{
|
|
|
|
insert(it, TQRect(left, top, width, height), sheet);
|
|
|
|
}
|
|
|
|
// right range
|
|
|
|
left = TQMIN(x+1, fullRange.right());
|
|
|
|
top = y;
|
|
|
|
width = TQMAX(0, fullRange.right() - x);
|
|
|
|
height = 1;
|
|
|
|
if (width > 0)
|
|
|
|
{
|
|
|
|
insert(it, TQRect(left, top, width, height), sheet);
|
|
|
|
}
|
|
|
|
// bottom range
|
|
|
|
left = fullRange.left();
|
|
|
|
top = y+1;
|
|
|
|
width = fullRange.width();
|
|
|
|
height = TQMAX(0, fullRange.bottom() - y);
|
|
|
|
if (height > 0)
|
|
|
|
{
|
|
|
|
insert(it, TQRect(left, top, width, height), sheet);
|
|
|
|
}
|
|
|
|
return *it;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!containsPoint)
|
|
|
|
{
|
|
|
|
return add(point, sheet);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Iterator Region::insert(Region::Iterator pos, const TQPoint& point, Sheet* sheet, bool multi)
|
|
|
|
{
|
|
|
|
if (point.x() < 1 || point.y() < 1)
|
|
|
|
{
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool containsPoint = false;
|
|
|
|
// bool adjacentPoint = false;
|
|
|
|
// TQRect neighbour;
|
|
|
|
|
|
|
|
// we don't have to check for occurences?
|
|
|
|
if (multi)
|
|
|
|
{
|
|
|
|
Point* rpoint = createPoint(point);
|
|
|
|
rpoint->setSheet(sheet);
|
|
|
|
return d->cells.insert(pos, rpoint);
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstIterator endOfList(d->cells.constEnd());
|
|
|
|
for (ConstIterator it = d->cells.constBegin(); it != endOfList; ++it)
|
|
|
|
{
|
|
|
|
Element *element = *it;
|
|
|
|
if (sheet && sheet != element->sheet())
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (element->contains(point))
|
|
|
|
{
|
|
|
|
containsPoint = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* else
|
|
|
|
{
|
|
|
|
neighbour = element->rect().normalize();
|
|
|
|
neighbour.setTopLeft(neighbour.topLeft() - TQPoint(1,1));
|
|
|
|
neighbour.setBottomRight(neighbour.bottomRight() + TQPoint(1,1));
|
|
|
|
if (neighbour.contains(point))
|
|
|
|
{
|
|
|
|
adjacentPoint = true; // TODO Stefan: Implement!
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
if ( !containsPoint )
|
|
|
|
{
|
|
|
|
Point* rpoint = createPoint(point);
|
|
|
|
rpoint->setSheet(sheet);
|
|
|
|
return d->cells.insert(pos, rpoint);
|
|
|
|
}
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Iterator Region::insert(Region::Iterator pos, const TQRect& range, Sheet* sheet, bool multi)
|
|
|
|
{
|
|
|
|
if (range.size() == TQSize(1,1))
|
|
|
|
{
|
|
|
|
return insert(pos, range.topLeft(), sheet);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (multi)
|
|
|
|
{
|
|
|
|
Range* rrange = createRange(range);
|
|
|
|
rrange->setSheet(sheet);
|
|
|
|
return d->cells.insert(pos, rrange);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool containsRange = false;
|
|
|
|
|
|
|
|
Iterator it( d->cells.begin() );
|
|
|
|
Iterator endOfList( d->cells.end() );
|
|
|
|
while ( it != endOfList )
|
|
|
|
{
|
|
|
|
if (sheet && sheet != (*it)->sheet())
|
|
|
|
{
|
|
|
|
++it;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ((*it)->contains(range))
|
|
|
|
{
|
|
|
|
containsRange = true;
|
|
|
|
}
|
|
|
|
else if (range.contains((*it)->rect()))
|
|
|
|
{
|
|
|
|
delete *it;
|
|
|
|
it = d->cells.remove(it);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
if ( !containsRange )
|
|
|
|
{
|
|
|
|
Range* rrange = createRange(range);
|
|
|
|
rrange->setSheet(sheet);
|
|
|
|
return d->cells.insert(pos, rrange);
|
|
|
|
}
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::isColumnAffected(uint col) const
|
|
|
|
{
|
|
|
|
ConstIterator endOfList(d->cells.constEnd());
|
|
|
|
for (ConstIterator it = d->cells.constBegin(); it != endOfList; ++it)
|
|
|
|
{
|
|
|
|
Element *element = *it;
|
|
|
|
TQRect normalizedRegion = element->rect().normalize();
|
|
|
|
if ((int)col >= normalizedRegion.left() && (int)col <= normalizedRegion.right())
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::isRowAffected(uint row) const
|
|
|
|
{
|
|
|
|
ConstIterator endOfList(d->cells.constEnd());
|
|
|
|
for (ConstIterator it = d->cells.constBegin(); it != endOfList; ++it)
|
|
|
|
{
|
|
|
|
Element *element = *it;
|
|
|
|
TQRect normalizedRegion = element->rect().normalize();
|
|
|
|
if ((int)row >= normalizedRegion.top() && (int)row <= normalizedRegion.bottom())
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::isColumnSelected(uint col) const
|
|
|
|
{
|
|
|
|
ConstIterator endOfList(d->cells.constEnd());
|
|
|
|
for (ConstIterator it = d->cells.constBegin(); it != endOfList; ++it)
|
|
|
|
{
|
|
|
|
Element *element = *it;
|
|
|
|
TQRect region = element->rect().normalize();
|
|
|
|
if ((col == 0 || ((int)col >= region.left() && (int)col <= region.right())) &&
|
|
|
|
region.top() == 1 && region.bottom() == KS_rowMax)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::isRowSelected(uint row) const
|
|
|
|
{
|
|
|
|
ConstIterator endOfList(d->cells.constEnd());
|
|
|
|
for (ConstIterator it = d->cells.constBegin(); it != endOfList; ++it)
|
|
|
|
{
|
|
|
|
Element *element = *it;
|
|
|
|
TQRect region = element->rect().normalize();
|
|
|
|
if ((row == 0 || ((int)row >= region.top() && (int)row <= region.bottom())) &&
|
|
|
|
region.left() == 1 && region.right() == KS_colMax)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::isColumnOrRowSelected() const
|
|
|
|
{
|
|
|
|
ConstIterator endOfList(d->cells.constEnd());
|
|
|
|
for (ConstIterator it = d->cells.constBegin(); it != endOfList; ++it)
|
|
|
|
{
|
|
|
|
Element *element = *it;
|
|
|
|
TQRect region = element->rect().normalize();
|
|
|
|
if ((region.top() == 1 && region.bottom() == KS_rowMax) ||
|
|
|
|
(region.left() == 1 && region.right() == KS_colMax))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::contains(const TQPoint& point, Sheet* sheet) const
|
|
|
|
{
|
|
|
|
if (d->cells.isEmpty())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ConstIterator endOfList(d->cells.constEnd());
|
|
|
|
for (ConstIterator it = d->cells.constBegin(); it != endOfList; ++it)
|
|
|
|
{
|
|
|
|
Element *element = *it;
|
|
|
|
if (element->contains(point))
|
|
|
|
{
|
|
|
|
if (sheet && element->sheet() != sheet)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::isEmpty() const
|
|
|
|
{
|
|
|
|
return d->cells.isEmpty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Region::clear()
|
|
|
|
{
|
|
|
|
Iterator end(d->cells.end());
|
|
|
|
for (Iterator it = d->cells.begin(); it != end; it = d->cells.remove(it))
|
|
|
|
{
|
|
|
|
delete *it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQRect Region::boundingRect() const
|
|
|
|
{
|
|
|
|
int left = KS_colMax;
|
|
|
|
int right = 1;
|
|
|
|
int top = KS_rowMax;
|
|
|
|
int bottom = 1;
|
|
|
|
Region::ConstIterator endOfList = cells().constEnd();
|
|
|
|
for (Region::ConstIterator it = cells().constBegin(); it != endOfList; ++it)
|
|
|
|
{
|
|
|
|
TQRect range = (*it)->rect().normalize();
|
|
|
|
if (range.left() < left)
|
|
|
|
{
|
|
|
|
left = range.left();
|
|
|
|
}
|
|
|
|
if (range.right() > right)
|
|
|
|
{
|
|
|
|
right = range.right();
|
|
|
|
}
|
|
|
|
if (range.top() < top)
|
|
|
|
{
|
|
|
|
top = range.top();
|
|
|
|
}
|
|
|
|
if (range.bottom() > bottom)
|
|
|
|
{
|
|
|
|
bottom = range.bottom();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TQRect(left, top, right-left+1, bottom-top+1);
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::ConstIterator Region::constBegin() const
|
|
|
|
{
|
|
|
|
return d->cells.constBegin();
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::ConstIterator Region::constEnd() const
|
|
|
|
{
|
|
|
|
return d->cells.constEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQValueList<Region::Element*>& Region::cells() const
|
|
|
|
{
|
|
|
|
return d->cells;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::operator==(const Region& other) const
|
|
|
|
{
|
|
|
|
ConstIterator endOfList(d->cells.constEnd());
|
|
|
|
ConstIterator endOfOtherList(other.d->cells.constEnd());
|
|
|
|
ConstIterator it = d->cells.constBegin();
|
|
|
|
ConstIterator it2 = other.d->cells.constBegin();
|
|
|
|
while (it != endOfList && it2 != endOfOtherList)
|
|
|
|
{
|
|
|
|
if ((*it++)->rect() != (*it2++)->rect())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Region::operator=(const Region& other)
|
|
|
|
{
|
|
|
|
d->view = other.d->view;
|
|
|
|
clear();
|
|
|
|
ConstIterator end(other.d->cells.constEnd());
|
|
|
|
for (ConstIterator it = other.d->cells.constBegin(); it != end; ++it)
|
|
|
|
{
|
|
|
|
Element *element = *it;
|
|
|
|
if (element->type() == Element::Point)
|
|
|
|
{
|
|
|
|
Point* point = static_cast<Point*>(element);
|
|
|
|
d->cells.append(createPoint(*point));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Range* range = static_cast<Range*>(element);
|
|
|
|
d->cells.append(createRange(*range));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Sheet* Region::filterSheetName(TQString& sRegion)
|
|
|
|
{
|
|
|
|
Sheet* sheet = 0;
|
|
|
|
int delimiterPos = sRegion.find( '!' );
|
|
|
|
if (delimiterPos > -1)
|
|
|
|
{
|
|
|
|
TQString sheetName = sRegion.left(delimiterPos);
|
|
|
|
// remove the '!'
|
|
|
|
sRegion = sRegion.right(sRegion.length() - delimiterPos - 1);
|
|
|
|
sheet = d->view->doc()->map()->findSheet(sheetName);
|
|
|
|
if (!sheet)
|
|
|
|
{
|
|
|
|
kdDebug() << "Sheet " << sheetName << " not found. Using active sheet!" << endl;
|
|
|
|
sheet = d->view->activeSheet();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return sheet;
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Point* Region::createPoint(const TQPoint& point) const
|
|
|
|
{
|
|
|
|
return new Point(point);
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Point* Region::createPoint(const TQString& string) const
|
|
|
|
{
|
|
|
|
return new Point(string);
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Point* Region::createPoint(const Point& point) const
|
|
|
|
{
|
|
|
|
return new Point(point);
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Range* Region::createRange(const TQRect& rect) const
|
|
|
|
{
|
|
|
|
return new Range(rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Range* Region::createRange(const TQString& string) const
|
|
|
|
{
|
|
|
|
return new Range(string);
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Range* Region::createRange(const Range& range) const
|
|
|
|
{
|
|
|
|
return new Range(range);
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
class Element
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
Region::Element::Element()
|
|
|
|
: m_sheet(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Element::~Element()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
class Point
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
Region::Point::Point(const TQPoint& point)
|
|
|
|
: Region::Element(),
|
|
|
|
m_point(point)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Point::Point(const TQString& sCell)
|
|
|
|
: Region::Element(),
|
|
|
|
m_point()
|
|
|
|
{
|
|
|
|
uint length = sCell.length();
|
|
|
|
|
|
|
|
if (length == 0)
|
|
|
|
{
|
|
|
|
kdDebug(36001) << "Region::Point::init: length = 0" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString string = sCell;//Region::filterSheetName(sCell);
|
|
|
|
|
|
|
|
uint p = 0;
|
|
|
|
|
|
|
|
// Fixed ?
|
|
|
|
if (string[0] == '$')
|
|
|
|
{
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Malformed ?
|
|
|
|
if (p == length)
|
|
|
|
{
|
|
|
|
kdDebug(36001) << "Region::Point::init: no point after '$' (string: '" << string.mid(p) << "'" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (string[p] < 'A' || string[p] > 'Z')
|
|
|
|
{
|
|
|
|
if (string[p] < 'a' || string[p] > 'z')
|
|
|
|
{
|
|
|
|
kdDebug(36001) << "Region::Point::init: wrong first character in point (string: '" << string.mid(p) << "'" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//default is error
|
|
|
|
int x = -1;
|
|
|
|
//search for the first character != text
|
|
|
|
int result = string.find( TQRegExp("[^A-Za-z]+"), p );
|
|
|
|
|
|
|
|
//get the colomn number for the character between actual position and the first non text charakter
|
|
|
|
if ( result != -1 )
|
|
|
|
{
|
|
|
|
x = util_decodeColumnLabelText( string.mid( p, result - p ) ); // x is defined now
|
|
|
|
}
|
|
|
|
else // If there isn't any, then this is not a point -> return
|
|
|
|
{
|
|
|
|
kdDebug(36001) << "Region::Point::init: no number in string (string: '" << string.mid( p, result ) << "'" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
p = result;
|
|
|
|
|
|
|
|
//limit is KS_colMax
|
|
|
|
if ( x > KS_colMax )
|
|
|
|
{
|
|
|
|
kdDebug(36001) << "Region::Point::init: column value too high (col: " << x << ")" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Malformed ?
|
|
|
|
if (p == length)
|
|
|
|
{
|
|
|
|
kdDebug(36001) << "Region::Point::init: p==length after cols" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (string[p] == '$')
|
|
|
|
{
|
|
|
|
p++;
|
|
|
|
// Malformed ?
|
|
|
|
if ( p == length )
|
|
|
|
{
|
|
|
|
kdDebug(36001) << "Region::Point::init: p==length after $ of row" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint p2 = p;
|
|
|
|
while ( p < length )
|
|
|
|
{
|
|
|
|
if (!TQChar(string[p++]).isDigit())
|
|
|
|
{
|
|
|
|
kdDebug(36001) << "Region::Point::init: no number" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ok;
|
|
|
|
int y = string.mid( p2, p-p2 ).toInt( &ok );
|
|
|
|
if ( !ok )
|
|
|
|
{
|
|
|
|
kdDebug(36001) << "Region::Point::init: Invalid number (string: '" << string.mid( p2, p-p2 ) << "'" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ( y > KS_rowMax )
|
|
|
|
{
|
|
|
|
kdDebug(36001) << "Region::Point::init: row value too high (row: " << y << ")" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ( y <= 0 )
|
|
|
|
{
|
|
|
|
kdDebug(36001) << "Region::Point::init: y <= 0" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_point = TQPoint(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Point::~Point()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Region::Point::name(Sheet* originSheet) const
|
|
|
|
{
|
|
|
|
TQString name = "";
|
|
|
|
if (m_sheet && m_sheet != originSheet)
|
|
|
|
{
|
|
|
|
name = m_sheet->sheetName() + "!";
|
|
|
|
}
|
|
|
|
return name + Cell::name(m_point.x(), m_point.y());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::Point::contains(const TQPoint& point) const
|
|
|
|
{
|
|
|
|
return (m_point == point);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::Point::contains(const TQRect& range) const
|
|
|
|
{
|
|
|
|
return (range.width() == 1) && (range.height() == 1) && (range.topLeft() == m_point);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
class Range
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
Region::Range::Range(const TQRect& rect)
|
|
|
|
: Region::Element(),
|
|
|
|
m_range(rect)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Range::Range(const TQString& sRange)
|
|
|
|
: Region::Element(),
|
|
|
|
m_range()
|
|
|
|
{
|
|
|
|
int delimiterPos = sRange.find(':');
|
|
|
|
if (delimiterPos == -1)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Region::filterSheetName(sRange);
|
|
|
|
|
|
|
|
Region::Point ul(sRange.left(delimiterPos));
|
|
|
|
Region::Point lr(sRange.mid(delimiterPos + 1));
|
|
|
|
|
|
|
|
if (!ul.isValid() || !lr.isValid())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_range = TQRect(ul.pos(), lr.pos());
|
|
|
|
}
|
|
|
|
|
|
|
|
Region::Range::~Range()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Region::Range::name(Sheet* originSheet) const
|
|
|
|
{
|
|
|
|
TQString name = "";
|
|
|
|
if (m_sheet && m_sheet != originSheet)
|
|
|
|
{
|
|
|
|
name = m_sheet->sheetName() + "!";
|
|
|
|
}
|
|
|
|
return name + Cell::name(m_range.left(), m_range.top()) + ":" +
|
|
|
|
Cell::name(m_range.right(), m_range.bottom() );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::Range::contains(const TQPoint& point) const
|
|
|
|
{
|
|
|
|
return m_range.normalize().contains(point);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Region::Range::contains(const TQRect& range) const
|
|
|
|
{
|
|
|
|
return m_range.normalize().contains(range.normalize());
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace KSpread
|