File indexing completed on 2024-05-12 16:35:36

0001 /* This file is part of the KDE project
0002 
0003    Copyright 2006 Fredrik Edemar <f_edemar@linux.se>
0004    Copyright 2003 Lukas Tinkl <lukas@kde.org>
0005    Copyright 2000, 2002-2003 Laurent Montel <montel@kde.org>
0006    Copyright 2001-2003 Philipp Mueller <philipp.mueller@gmx.de>
0007    Copyright 2003 Joseph Wenninger <jowenn@kde.org>
0008    Copyright 2002 Ariya Hidayat <ariya@kde.org>
0009    Copyright 2002 Harri Porten <porten@kde.org>
0010    Copyright 2002 John Dailey <dailey@vt.edu>
0011    Copyright 2001 Simon Hausmann <hausmann@kde.org>
0012    Copyright 2000 Werner Trobin <trobin@kde.org>
0013    Copyright 1999 Torben Weis <weis@kde.org>
0014 
0015    This library is free software; you can redistribute it and/or
0016    modify it under the terms of the GNU Library General Public
0017    License as published by the Free Software Foundation; either
0018    version 2 of the License, or (at your option) any later version.
0019 
0020    This library is distributed in the hope that it will be useful,
0021    but WITHOUT ANY WARRANTY; without even the implied warranty of
0022    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0023    Library General Public License for more details.
0024 
0025    You should have received a copy of the GNU Library General Public License
0026    along with this library; see the file COPYING.LIB.  If not, write to
0027    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0028    Boston, MA 02110-1301, USA.
0029 */
0030 
0031 // Local
0032 #include "SheetAdaptor.h"
0033 
0034 #include "SheetsDebug.h"
0035 #include "Damages.h"
0036 #include "Map.h"
0037 #include "PrintSettings.h"
0038 #include "Sheet.h"
0039 #include "SheetPrint.h"
0040 #include "Region.h"
0041 #include "ValueConverter.h"
0042 
0043 // commands
0044 #include "commands/DataManipulators.h"
0045 #include "commands/RowColumnManipulators.h"
0046 
0047 #include <KoUnit.h>
0048 
0049 using namespace Calligra::Sheets;
0050 
0051 SheetAdaptor::SheetAdaptor(Sheet* t)
0052         : QDBusAbstractAdaptor(t)
0053 {
0054     setAutoRelaySignals(false);
0055     m_sheet = t;
0056     connect(m_sheet->map(), SIGNAL(damagesFlushed(QList<Damage*>)),
0057             this, SLOT(handleDamages(QList<Damage*>)));
0058 }
0059 
0060 SheetAdaptor::~SheetAdaptor()
0061 {
0062 }
0063 
0064 QString SheetAdaptor::cellName(int x, int y)
0065 {
0066     /* sebsauer 20061206: commented out cause if someone starts to believe that
0067     counting starts by 0,0 then they may very surprised why the first col/row
0068     got returned twice. That happened to me and I was believing that's a Calligra Sheets
0069     bug too :-(
0070     // if someone calls us with either x or y 0 they _most_ most likely don't
0071     // know that the cell counting starts with 1 (Simon)
0072     // P.S.: I made that mistake for weeks and already started looking for the
0073     // "bug" in Calligra Sheets ;-)
0074     if ( x == 0 ) x = 1;
0075     if ( y == 0 ) y = 1;
0076     */
0077     return Cell::name(x, y);
0078 }
0079 
0080 int SheetAdaptor::cellRow(const QString& cellname)
0081 {
0082     return cellLocation(cellname).x();
0083 }
0084 
0085 int SheetAdaptor::cellColumn(const QString& cellname)
0086 {
0087     return cellLocation(cellname).y();
0088 }
0089 
0090 QPoint SheetAdaptor::cellLocation(const QString& cellname)
0091 {
0092     const Region region(cellname, m_sheet->map(), m_sheet);
0093     if (region.firstRange().isNull())
0094         return QPoint();
0095     return region.firstRange().topLeft();
0096 }
0097 
0098 QString SheetAdaptor::text(int x, int y)
0099 {
0100     Cell cell = Cell(m_sheet, x, y);
0101     return cell.userInput();
0102 }
0103 
0104 QString SheetAdaptor::text(const QString& cellname)
0105 {
0106     const QPoint location = cellLocation(cellname);
0107     return text(location.x(), location.y());
0108 }
0109 
0110 bool SheetAdaptor::setText(int x, int y, const QString& text, bool parse)
0111 {
0112     //FIXME: there is some problem with asString parameter, when it's set
0113     //to true Calligra Sheets says: ASSERT: "f" in Dependencies.cpp (621)
0114     //kspread: Cell at row 6, col 1 marked as formula, but formula is NULL
0115 
0116     Calligra::Sheets::DataManipulator *dm = new Calligra::Sheets::DataManipulator();
0117     dm->setSheet(m_sheet);
0118     dm->setValue(Value(text));
0119     dm->setParsing(parse);
0120     dm->add(QPoint(x, y));
0121     return dm->execute();
0122 }
0123 
0124 bool SheetAdaptor::setText(const QString& cellname, const QString& text, bool parse)
0125 {
0126     const QPoint location = cellLocation(cellname);
0127     return setText(location.x(), location.y(), text, parse);
0128 }
0129 
0130 QVariant valueToVariant(const Calligra::Sheets::Value& value, Sheet* sheet)
0131 {
0132     //Should we use following value-format enums here?
0133     //fmt_None, fmt_Boolean, fmt_Number, fmt_Percent, fmt_Money, fmt_DateTime, fmt_Date, fmt_Time, fmt_String
0134     switch (value.type()) {
0135     case Calligra::Sheets::Value::Empty:
0136         return QVariant();
0137     case Calligra::Sheets::Value::Boolean:
0138         return QVariant(value.asBoolean());
0139     case Calligra::Sheets::Value::Integer:
0140         return static_cast<qint64>(value.asInteger());
0141     case Calligra::Sheets::Value::Float:
0142         return (double) numToDouble(value.asFloat());
0143     case Calligra::Sheets::Value::Complex:
0144         return sheet->map()->converter()->asString(value).asString();
0145     case Calligra::Sheets::Value::String:
0146         return value.asString();
0147     case Calligra::Sheets::Value::Array: {
0148         QVariantList colarray;
0149         for (uint j = 0; j < value.rows(); j++) {
0150             QVariantList rowarray;
0151             for (uint i = 0; i < value.columns(); i++) {
0152                 Calligra::Sheets::Value v = value.element(i, j);
0153                 rowarray.append(valueToVariant(v, sheet));
0154             }
0155             colarray.append(rowarray);
0156         }
0157         return colarray;
0158     }
0159     break;
0160     case Calligra::Sheets::Value::CellRange:
0161         //FIXME: not yet used
0162         return QVariant();
0163     case Calligra::Sheets::Value::Error:
0164         return QVariant();
0165     }
0166     return QVariant();
0167 }
0168 
0169 QVariant SheetAdaptor::value(int x, int y)
0170 {
0171     Cell cell = Cell(m_sheet, x, y);
0172     return valueToVariant(cell.value(), m_sheet);
0173 }
0174 
0175 QVariant SheetAdaptor::value(const QString& cellname)
0176 {
0177     const QPoint location = cellLocation(cellname);
0178     return value(location.x(), location.y());
0179 }
0180 
0181 bool SheetAdaptor::setValue(int x, int y, const QVariant& value)
0182 {
0183     Cell cell = Cell(m_sheet, x, y);
0184     if (! cell) return false;
0185     Calligra::Sheets::Value v = cell.value();
0186     switch (value.type()) {
0187     case QVariant::Bool: v = Value(value.toBool()); break;
0188     case QVariant::ULongLong: v = Value(value.toLongLong()); break;
0189     case QVariant::Int: v = Value(value.toInt()); break;
0190     case QVariant::Double: v = Value(value.toDouble()); break;
0191     case QVariant::String: v = Value(value.toString()); break;
0192         //case QVariant::Date: v = Value( value.toDate() ); break;
0193         //case QVariant::Time: v = Value( value.toTime() ); break;
0194         //case QVariant::DateTime: v = Value( value.toDateTime() ); break;
0195     default: return false;
0196     }
0197     return true;
0198 }
0199 
0200 bool SheetAdaptor::setValue(const QString& cellname, const QVariant& value)
0201 {
0202     const QPoint location = cellLocation(cellname);
0203     return setValue(location.x(), location.y(), value);
0204 }
0205 
0206 #if 0
0207 QString SheetAdaptor::column(int _col)
0208 {
0209     //First col number = 1
0210     if (_col < 1)
0211         return QString();
0212     return "";//m_sheet->nonDefaultColumnFormat( _col )->getName/*objectName*/();/*dcopObject()->objId()*/
0213 
0214 }
0215 
0216 QString SheetAdaptor::row(int _row)
0217 {
0218     //First row number = 1
0219     if (_row < 1)
0220         return QString();
0221     return "";//m_sheet->nonDefaultRowFormat( _row )->/*dcopObject()->*/getName/*objectName*/();
0222 }
0223 #endif
0224 
0225 QString SheetAdaptor::sheetName() const
0226 {
0227     return m_sheet->sheetName();
0228 }
0229 
0230 bool SheetAdaptor::setSheetName(const QString & name)
0231 {
0232     return m_sheet->setSheetName(name);
0233 }
0234 
0235 int SheetAdaptor::lastColumn() const
0236 {
0237     return m_sheet->usedArea().width();
0238 }
0239 
0240 int SheetAdaptor::lastRow() const
0241 {
0242     return m_sheet->usedArea().height();
0243 }
0244 
0245 // bool SheetAdaptor::processDynamic( const DCOPCString& fun, const QByteArray&/*data*/,
0246 //                                         DCOPCString& replyType, QByteArray &replyData )
0247 // {
0248 //     debugSheets <<"Calling '" << fun.data() << '\'';
0249 //     // Does the name follow the pattern "foobar()" ?
0250 //     uint len = fun.length();
0251 //     if ( len < 3 )
0252 //         return false;
0253 //
0254 //     if ( fun[ len - 1 ] != ')' || fun[ len - 2 ] != '(' )
0255 //         return false;
0256 //
0257 //     // Is the function name a valid cell like "B5" ?
0258 //     Point p( fun.left( len - 2 ).data() );
0259 //     if ( !p.isValid() )
0260 //         return false;
0261 //
0262 //     DCOPCString str = objId() + '/' + fun.left( len - 2 );
0263 //
0264 //     replyType = "DCOPRef";
0265 //     QDataStream out( &replyData,QIODevice::WriteOnly );
0266 //     out.setVersion(QDataStream::Qt_3_1);
0267 //     out << DCOPRef( kapp->dcopClient()->appId(), str );
0268 //     return true;
0269 // }
0270 
0271 void SheetAdaptor::insertColumn(int col, int nbCol)
0272 {
0273     InsertDeleteColumnManipulator* manipulator = new InsertDeleteColumnManipulator();
0274     manipulator->setSheet(m_sheet);
0275     manipulator->add(Region(QRect(col, 1, nbCol, 1)));
0276     manipulator->execute();
0277 }
0278 
0279 void SheetAdaptor::insertRow(int row, int nbRow)
0280 {
0281     InsertDeleteRowManipulator* manipulator = new InsertDeleteRowManipulator();
0282     manipulator->setSheet(m_sheet);
0283     manipulator->add(Region(QRect(1, row, 1, nbRow)));
0284     manipulator->execute();
0285 }
0286 
0287 void SheetAdaptor::removeColumn(int col, int nbCol)
0288 {
0289     InsertDeleteColumnManipulator* manipulator = new InsertDeleteColumnManipulator();
0290     manipulator->setSheet(m_sheet);
0291     manipulator->setReverse(true);
0292     manipulator->add(Region(QRect(col, 1, nbCol, 1)));
0293     manipulator->execute();
0294 }
0295 
0296 void SheetAdaptor::removeRow(int row, int nbRow)
0297 {
0298     InsertDeleteRowManipulator* manipulator = new InsertDeleteRowManipulator();
0299     manipulator->setSheet(m_sheet);
0300     manipulator->setReverse(true);
0301     manipulator->add(Region(QRect(1, row, 1, nbRow)));
0302     manipulator->execute();
0303 }
0304 
0305 bool SheetAdaptor::isHidden() const
0306 {
0307     return m_sheet->isHidden();
0308 }
0309 
0310 void SheetAdaptor::setHidden(bool hidden)
0311 {
0312     m_sheet->setHidden(hidden);
0313 }
0314 
0315 #if 0
0316 bool SheetAdaptor::showGrid() const
0317 {
0318     return m_sheet->getShowGrid();
0319 }
0320 
0321 bool SheetAdaptor::showFormula() const
0322 {
0323     return m_sheet->getShowFormula();
0324 }
0325 
0326 bool SheetAdaptor::lcMode() const
0327 {
0328     return m_sheet->getLcMode();
0329 }
0330 
0331 bool SheetAdaptor::autoCalc() const
0332 {
0333     return m_sheet->isAutoCalculationEnabled();
0334 }
0335 
0336 bool SheetAdaptor::showColumnNumber() const
0337 {
0338     return m_sheet->getShowColumnNumber();
0339 }
0340 
0341 bool SheetAdaptor::hideZero() const
0342 {
0343     return m_sheet->getHideZero();
0344 }
0345 
0346 bool SheetAdaptor::firstLetterUpper() const
0347 {
0348     return m_sheet->getFirstLetterUpper();
0349 }
0350 
0351 void SheetAdaptor::setShowPageOutline(bool b)
0352 {
0353     m_sheet->setShowPageOutline(b);
0354     m_sheet->doc()->updateBorderButton();
0355 }
0356 #endif
0357 
0358 float SheetAdaptor::paperHeight()const
0359 {
0360     return m_sheet->print()->settings()->pageLayout().height;
0361 }
0362 
0363 void SheetAdaptor::setPrinterHeight(float height)
0364 {
0365     KoPageLayout pageLayout = m_sheet->print()->settings()->pageLayout();
0366     pageLayout.format = KoPageFormat::CustomSize;
0367     pageLayout.height = MM_TO_POINT(height);
0368     m_sheet->print()->settings()->setPageLayout(pageLayout);
0369 }
0370 
0371 float SheetAdaptor::paperWidth()const
0372 {
0373     return m_sheet->print()->settings()->pageLayout().width;
0374 }
0375 
0376 void SheetAdaptor::setPaperWidth(float width)
0377 {
0378     KoPageLayout pageLayout = m_sheet->print()->settings()->pageLayout();
0379     pageLayout.format = KoPageFormat::CustomSize;
0380     pageLayout.width = MM_TO_POINT(width);
0381     m_sheet->print()->settings()->setPageLayout(pageLayout);
0382 }
0383 
0384 float SheetAdaptor::paperLeftBorder()const
0385 {
0386     return m_sheet->print()->settings()->pageLayout().leftMargin;
0387 }
0388 
0389 float SheetAdaptor::paperRightBorder()const
0390 {
0391     return m_sheet->print()->settings()->pageLayout().rightMargin;
0392 }
0393 
0394 float SheetAdaptor::paperTopBorder()const
0395 {
0396     return m_sheet->print()->settings()->pageLayout().topMargin;
0397 }
0398 
0399 float SheetAdaptor::paperBottomBorder()const
0400 {
0401     return m_sheet->print()->settings()->pageLayout().bottomMargin;
0402 }
0403 
0404 QString SheetAdaptor::paperFormat() const
0405 {
0406     return m_sheet->printSettings()->paperFormatString();
0407 }
0408 
0409 QString SheetAdaptor::paperOrientation() const
0410 {
0411     return m_sheet->printSettings()->orientationString();
0412 }
0413 
0414 void SheetAdaptor::setPaperLayout(float leftBorder, float topBorder,
0415                                   float rightBorder, float bottomBoder,
0416                                   const QString& format, const QString& orientation)
0417 {
0418     KoPageLayout pageLayout;
0419     pageLayout.format = KoPageFormat::formatFromString(format);
0420     pageLayout.orientation = (orientation  == "Portrait")
0421                              ? KoPageFormat::Portrait : KoPageFormat::Landscape;
0422     pageLayout.leftMargin   = leftBorder;
0423     pageLayout.rightMargin  = rightBorder;
0424     pageLayout.topMargin    = topBorder;
0425     pageLayout.bottomMargin = bottomBoder;
0426     m_sheet->print()->settings()->setPageLayout(pageLayout);
0427 }
0428 
0429 #if 0
0430 QString SheetAdaptor::printHeadLeft()const
0431 {
0432     return m_sheet->print()->headLeft();
0433 }
0434 
0435 QString SheetAdaptor::printHeadMid()const
0436 {
0437     return m_sheet->print()->headMid();
0438 }
0439 
0440 QString SheetAdaptor::printHeadRight()const
0441 {
0442     return m_sheet->print()->headRight();
0443 }
0444 
0445 QString SheetAdaptor::printFootLeft()const
0446 {
0447     return m_sheet->print()->footLeft();
0448 }
0449 
0450 QString SheetAdaptor::printFootMid()const
0451 {
0452     return m_sheet->print()->footMid();
0453 }
0454 
0455 QString SheetAdaptor::printFootRight()const
0456 {
0457     return m_sheet->print()->footRight();
0458 }
0459 
0460 void SheetAdaptor::setPrintHeaderLeft(const QString & text)
0461 {
0462     m_sheet->print()->setHeadFootLine(text,       headMid(), headRight(),
0463                                       footLeft(), footMid(), footRight());
0464 }
0465 
0466 void SheetAdaptor::setPrintHeaderMiddle(const QString & text)
0467 {
0468     m_sheet->print()->setHeadFootLine(headLeft(), text,      headRight(),
0469                                       footLeft(), footMid(), footRight());
0470 
0471 }
0472 
0473 void SheetAdaptor::setPrintHeaderRight(const QString & text)
0474 {
0475     m_sheet->print()->setHeadFootLine(headLeft(), headMid(), text,
0476                                       footLeft(), footMid(), footRight());
0477 }
0478 
0479 void SheetAdaptor::setPrintFooterLeft(const QString & text)
0480 {
0481     m_sheet->print()->setHeadFootLine(headLeft(), headMid(), headRight(),
0482                                       text,       footMid(), footRight());
0483 }
0484 
0485 void SheetAdaptor::setPrintFooterMiddle(const QString & text)
0486 {
0487     m_sheet->print()->setHeadFootLine(headLeft(), headMid(), headRight(),
0488                                       footLeft(), text,      footRight());
0489 }
0490 
0491 void SheetAdaptor::setPrintFooterRight(const QString & text)
0492 {
0493     m_sheet->print()->setHeadFootLine(headLeft(), headMid(), headRight(),
0494                                       footLeft(), footMid(), text);
0495 }
0496 #endif
0497 
0498 bool SheetAdaptor::checkPassword(const QByteArray& passwd) const
0499 {
0500     return m_sheet->checkPassword(passwd);
0501 }
0502 
0503 bool SheetAdaptor::isProtected() const
0504 {
0505     return m_sheet->isProtected();
0506 }
0507 
0508 void SheetAdaptor::setProtected(const QByteArray& passwd)
0509 {
0510     m_sheet->setProtected(passwd);
0511 }
0512 
0513 void SheetAdaptor::handleDamages(const QList<Damage*>& damages)
0514 {
0515     const QList<Damage*>::ConstIterator end(damages.end());
0516     for (QList<Damage*>::ConstIterator it = damages.begin(); it != end; ++it) {
0517         const Damage *const damage = *it;
0518         if (!damage) {
0519             continue;
0520         }
0521         if (damage->type() == Damage::Sheet) {
0522             const SheetDamage *const sheetDamage = static_cast<const SheetDamage *>(damage);
0523             // Only process the sheet this adaptor works for.
0524             if (sheetDamage->sheet() != m_sheet) {
0525                 continue;
0526             }
0527             debugSheetsDamage << *sheetDamage;
0528             const SheetDamage::Changes changes = sheetDamage->changes();
0529             if (changes & SheetDamage::Name) {
0530                 emit nameChanged();
0531             }
0532             if (changes & SheetDamage::Shown) {
0533                 emit showChanged();
0534             }
0535             if (changes & SheetDamage::Hidden) {
0536                 emit hideChanged();
0537             }
0538             continue;
0539         }
0540     }
0541 }