File indexing completed on 2025-01-12 13:05:56

0001 
0002 /* This file is part of the KDE project
0003    Copyright (C) 2001 Graham Short <grahshrt@netscape.net>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #include <qproimport.h>
0022 
0023 #include <sstream>
0024 
0025 #include <kdebug.h>
0026 #include <kmessagebox.h>
0027 #include <kpluginfactory.h>
0028 #include <KoFilterChain.h>
0029 
0030 #include <sheets/part/Doc.h>
0031 #include <sheets/Sheet.h>
0032 #include <sheets/Cell.h>
0033 #include <sheets/Value.h>
0034 #include <sheets/Map.h>
0035 #include <sheets/LoadingInfo.h>
0036 
0037 #include <qproformula.h>
0038 #include <qpro/stream.h>
0039 #include <qpro/record_factory.h>
0040 #include <QFile>
0041 #include <QByteArray>
0042 
0043 using namespace Calligra::Sheets;
0044 
0045 K_PLUGIN_FACTORY_WITH_JSON(QPROImportFactory, "calligra_filter_qpro2sheets.json",
0046                            registerPlugin<QpImport>();)
0047 
0048 // ---------------------------------------------------------------
0049 
0050 QpTableList::QpTableList()
0051 {
0052     for (int lIdx = 0; lIdx < cNameCnt; ++lIdx) {
0053         cTable[lIdx] = 0;
0054     }
0055 }
0056 
0057 QpTableList::~QpTableList()
0058 {
0059     // don't delete the list of tables
0060 }
0061 
0062 
0063 void
0064 QpTableList::table(unsigned pIdx, Sheet* pTable)
0065 {
0066     if (pIdx < cNameCnt) {
0067         cTable[pIdx] = pTable;
0068     }
0069 }
0070 
0071 Sheet*
0072 QpTableList::table(unsigned pIdx)
0073 {
0074     return (pIdx < cNameCnt ? cTable[pIdx] : 0);
0075 }
0076 
0077 
0078 // ---------------------------------------------------------------
0079 
0080 QpImport::QpImport(QObject* parent, const QVariantList&)
0081         : KoFilter(parent)
0082 {
0083 }
0084 
0085 void
0086 QpImport::InitTableName(int pIdx, QString& pResult)
0087 {
0088     if (pIdx < 26) {
0089         pResult = (char)('A' + pIdx);
0090     } else {
0091         pResult = (char)('A' - 1 + pIdx / 26);
0092         pResult += (char)('A' + pIdx % 26);
0093     }
0094 }
0095 
0096 KoFilter::ConversionStatus QpImport::convert(const QByteArray& from, const QByteArray& to)
0097 {
0098     bool bSuccess = true;
0099 
0100     KoDocument* document = m_chain->outputDocument();
0101     if (!document)
0102         return KoFilter::StupidError;
0103 
0104     kDebug(30523) << "here we go..." << document->metaObject()->className();
0105 
0106     if (!::qobject_cast<const Calligra::Sheets::Doc *>(document)) {   // it's safer that way :)
0107         kWarning(30501) << "document isn't a Calligra::Sheets::Doc but a " << document->metaObject()->className();
0108         return KoFilter::NotImplemented;
0109     }
0110     if (from != "application/x-quattropro" || to != "application/x-kspread") {
0111         kWarning(30501) << "Invalid mimetypes " << from << " " << to;
0112         return KoFilter::NotImplemented;
0113     }
0114 
0115     kDebug(30523) << "...still here...";
0116 
0117     // No need for a dynamic cast here, since we use Qt's moc magic
0118     Doc *ksdoc = (Doc*)document;
0119 
0120     if (ksdoc->mimeType() != "application/x-ole-storage") {
0121         kWarning(30501) << "Invalid document mimetype " << ksdoc->mimeType();
0122         return KoFilter::NotImplemented;
0123     }
0124 
0125     QpIStream lIn(QFile::encodeName(m_chain->inputFile()));
0126 
0127     if (!lIn) {
0128         KMessageBox::sorry(0L, i18n("QPRO filter cannot open input file - please report."));
0129         return KoFilter::FileNotFound;
0130     }
0131 
0132     Sheet *table = 0;
0133 
0134     QString field;
0135     int value = 0;
0136     emit sigProgress(value);
0137 
0138     QpRecFactory            lFactory(lIn);
0139     QpTableList             lTableNames;
0140     QP_UINT8                lPageIdx = 0;
0141 
0142     QpRec*                  lRec = 0;
0143     QpRecBop*               lRecBop = 0;
0144     QpRecIntegerCell*       lRecInt = 0;
0145     QpRecFloatingPointCell* lRecFloat = 0;
0146     QpRecFormulaCell*       lRecFormula = 0;
0147     QpRecLabelCell*         lRecLabel = 0;
0148     QpRecPageName*          lRecPageName = 0;
0149 
0150     do {
0151         field.clear();
0152         lRec  = lFactory.nextRecord();
0153 
0154         switch (lRec->type()) {
0155         case QpBop:
0156             lRecBop = (QpRecBop*)lRec;
0157             lPageIdx = lRecBop->pageIndex();
0158 
0159             // find out if we know about this table already, if not create it
0160             table = lTableNames.table(lPageIdx);
0161 
0162             if (table == 0) {
0163                 table = ksdoc->map()->addNewSheet();
0164                 // set up a default name for the table
0165                 table->setSheetName(lTableNames.name(lPageIdx)
0166                                     , true
0167                                    );
0168                 lTableNames.table(lPageIdx, table);
0169             }
0170             break;
0171 
0172         case QpIntegerCell:
0173             lRecInt = (QpRecIntegerCell*)lRec;
0174             field.setNum(lRecInt->integer());
0175 //cout << "Setting R " << lRecInt->row()+1 << ", C " << ((unsigned)lRecInt->column()) << endl;
0176             if (table)
0177                 setText(table, lRecInt->row() + 1, ((unsigned)lRecInt->column()) + 1, field, false);
0178             break;
0179 
0180         case QpFormulaCell:
0181             lRecFormula = (QpRecFormulaCell*)lRec;
0182             {
0183                 QuattroPro::Formula lAnswer(*lRecFormula, lTableNames);
0184 
0185                 char*     lFormula = lAnswer.formula();
0186 
0187                 field = lFormula;
0188 
0189                 delete [] lFormula;
0190             }
0191 
0192             // check for referenced tables that haven't been created yet
0193             for (unsigned lIdx = 0; lIdx < lTableNames.cNameCnt; ++lIdx) {
0194                 if (lTableNames.allocated(lIdx) && (lTableNames.table(lIdx) == 0)) {
0195                     // we're about to reference a table that hasn't been created yet.
0196                     // setText gets upset about this, so create a blank table
0197 
0198                     Sheet* lNewTable = ksdoc->map()->addNewSheet();
0199 
0200                     // set up a default name for the table
0201                     lNewTable->setSheetName(lTableNames.name(lIdx)
0202                                             , true
0203                                            );
0204                     lTableNames.table(lIdx, lNewTable);
0205                 }
0206             }
0207 
0208             if (table)
0209                 setText(table, lRecFormula->row() + 1, lRecFormula->column() + 1, field, false);
0210             break;
0211 
0212         case QpFloatingPointCell:
0213             lRecFloat = (QpRecFloatingPointCell*)lRec;
0214             field.setNum(lRecFloat->value());
0215             if (table)
0216                 setText(table, lRecFloat->row() + 1, lRecFloat->column() + 1, field, false);
0217             break;
0218 
0219         case QpLabelCell:
0220             lRecLabel = (QpRecLabelCell*)lRec;
0221             field = "'";
0222             field += lRecLabel->label();
0223             if (table)
0224                 setText(table, lRecLabel->row() + 1, lRecLabel->column() + 1, field, false);
0225             break;
0226 
0227         case QpPageName:
0228             lRecPageName = (QpRecPageName*)lRec;
0229 
0230             if (lTableNames.allocated(lPageIdx) && lTableNames.table(lPageIdx)) {
0231                 lTableNames.table(lPageIdx)->setSheetName(lRecPageName->pageName()
0232 //                                                     , true
0233                                                          );
0234                 lTableNames.name(lPageIdx, lRecPageName->pageName());
0235             }
0236             break;
0237 
0238         case QpPassword:
0239             KMessageBox::sorry(0L, i18n("Unable to open password protected files.\n"
0240                                         "The password algorithm has not been published")
0241                               );
0242             delete lRec;
0243             return KoFilter::NotImplemented;
0244         }
0245 
0246         delete lRec;
0247         lRec = 0;
0248     } while (lIn);
0249 
0250     ksdoc->map()->loadingInfo()->setInitialActiveSheet(table);
0251 
0252     emit sigProgress(100);
0253     if (bSuccess)
0254         return KoFilter::OK;
0255     else
0256         return KoFilter::StupidError;
0257 }
0258 
0259 void QpImport::setText(Sheet* sheet, int _row, int _column, const QString& _text, bool asString)
0260 {
0261     Cell cell(sheet, _column, _row);
0262     if (asString) {
0263         cell.setUserInput(_text);
0264         cell.setValue(Value(_text));
0265     } else {
0266         cell.parseUserInput(_text);
0267     }
0268 }
0269 
0270 #include <qproimport.moc>