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

0001 /* This file is part of the KDE project
0002    Copyright (C) 1998-2002 The KSpread Team <calligra-devel@kde.org>
0003    Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com>
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; only
0008    version 2 of the License.
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 // built-in information functions
0022 
0023 #include "InformationModule.h"
0024 
0025 #include <CalligraVersionWrapper.h>
0026 #ifdef Q_OS_WIN
0027 #include <windows.h>
0028 #else
0029 #include <sys/utsname.h>
0030 #endif
0031 
0032 #include <QDir>
0033 #include <KLocalizedString>
0034 
0035 #include "SheetsDebug.h"
0036 #include "CalculationSettings.h"
0037 #include "Function.h"
0038 #include "FunctionModuleRegistry.h"
0039 #include "ValueCalc.h"
0040 #include "ValueConverter.h"
0041 #include "Map.h"
0042 #include "Sheet.h"
0043 #include "Region.h"
0044 #include "Cell.h"
0045 #include "Formula.h"
0046 #include "CellStorage.h"
0047 
0048 #include <KoDocument.h>
0049 #include <KoPart.h>
0050 #include <KoApplication.h>
0051 
0052 using namespace Calligra::Sheets;
0053 
0054 // prototypes (sorted alphabetically)
0055 Value func_errortype(valVector args, ValueCalc *calc, FuncExtra *);
0056 Value func_filename(valVector args, ValueCalc *calc, FuncExtra *);
0057 Value func_formula(valVector args, ValueCalc *calc, FuncExtra *);
0058 Value func_info(valVector args, ValueCalc *calc, FuncExtra *);
0059 Value func_isblank(valVector args, ValueCalc *calc, FuncExtra *);
0060 Value func_isdate(valVector args, ValueCalc *calc, FuncExtra *);
0061 Value func_iserr(valVector args, ValueCalc *calc, FuncExtra *);
0062 Value func_iserror(valVector args, ValueCalc *calc, FuncExtra *);
0063 Value func_iseven(valVector args, ValueCalc *calc, FuncExtra *);
0064 Value func_isformula(valVector args, ValueCalc *calc, FuncExtra *);
0065 Value func_islogical(valVector args, ValueCalc *calc, FuncExtra *);
0066 Value func_isna(valVector args, ValueCalc *calc, FuncExtra *);
0067 Value func_isnottext(valVector args, ValueCalc *calc, FuncExtra *);
0068 Value func_isnum(valVector args, ValueCalc *calc, FuncExtra *);
0069 Value func_isodd(valVector args, ValueCalc *calc, FuncExtra *);
0070 Value func_isref(valVector args, ValueCalc *calc, FuncExtra *);
0071 Value func_istext(valVector args, ValueCalc *calc, FuncExtra *);
0072 Value func_istime(valVector args, ValueCalc *calc, FuncExtra *);
0073 Value func_n(valVector args, ValueCalc *calc, FuncExtra *);
0074 Value func_na(valVector args, ValueCalc *calc, FuncExtra *);
0075 Value func_type(valVector args, ValueCalc *calc, FuncExtra *);
0076 Value func_version(valVector args, ValueCalc *calc, FuncExtra *);
0077 
0078 CALLIGRA_SHEETS_EXPORT_FUNCTION_MODULE("kspreadinformationmodule.json", InformationModule)
0079 
0080 
0081 InformationModule::InformationModule(QObject* parent, const QVariantList&)
0082         : FunctionModule(parent)
0083 {
0084     Function *f;
0085 
0086     f = new Function("ERRORTYPE", func_errortype);
0087     add(f);
0088     f = new Function("FILENAME", func_filename);
0089     f->setParamCount(0);
0090     add(f);
0091     f = new Function("FORMULA", func_formula);
0092     f->setParamCount(1);
0093     f->setNeedsExtra(true);
0094     add(f);
0095     f = new Function("INFO", func_info);
0096     add(f);
0097     f = new Function("ISBLANK", func_isblank);
0098     add(f);
0099     f = new Function("ISDATE", func_isdate);
0100     add(f);
0101     f = new Function("ISERR", func_iserr);
0102     add(f);
0103     f = new Function("ISERROR", func_iserror);
0104     add(f);
0105     f = new Function("ISEVEN", func_iseven);
0106     f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETISEVEN");
0107     add(f);
0108     f = new Function("ISFORMULA", func_isformula);
0109     f->setNeedsExtra(true);
0110     add(f);
0111     f = new Function("ISLOGICAL", func_islogical);
0112     add(f);
0113     f = new Function("ISNA", func_isna);
0114     add(f);
0115     f = new Function("ISNONTEXT", func_isnottext);
0116     add(f);
0117     f = new Function("ISNOTTEXT", func_isnottext);
0118     add(f);
0119     f = new Function("ISNUM", func_isnum);
0120     add(f);
0121     f = new Function("ISNUMBER", func_isnum);
0122     add(f);
0123     f = new Function("ISODD", func_isodd);
0124     f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETISODD");
0125     add(f);
0126     f = new Function("ISREF", func_isref);
0127     f->setNeedsExtra(true);
0128     f->setAcceptArray();
0129     add(f);
0130     f = new Function("ISTEXT", func_istext);
0131     add(f);
0132     f = new Function("ISTIME", func_istime);
0133     add(f);
0134     f = new Function("N", func_n);
0135     add(f);
0136     f = new Function("NA", func_na);
0137     f->setParamCount(0);
0138     add(f);
0139     f = new Function("TYPE", func_type);
0140     f->setAcceptArray();
0141     add(f);
0142 }
0143 
0144 QString InformationModule::descriptionFileName() const
0145 {
0146     return QString("information.xml");
0147 }
0148 
0149 // Function: ERROR.TYPE
0150 Value func_errortype(valVector args, ValueCalc *, FuncExtra *)
0151 {
0152     if (! args[0].isError()) {
0153         // its an error if the argument isn't an error...
0154         return Value::errorVALUE();
0155     }
0156 
0157     if (args[0] == Value::errorNULL()) {
0158         return Value(1);
0159     } else if (args[0] == Value::errorDIV0()) {
0160         return Value(2);
0161     } else if (args[0] == Value::errorVALUE()) {
0162         return Value(3);
0163     } else if (args[0] == Value::errorREF()) {
0164         return Value(4);
0165     } else if (args[0] == Value::errorNAME()) {
0166         return Value(5);
0167     } else if (args[0] == Value::errorNUM()) {
0168         return Value(6);
0169     } else if (args[0] == Value::errorNA()) {
0170         return Value(7);
0171     } else if (args[0] == Value::errorCIRCLE()) {
0172         // non-standard error type
0173         return Value(101);
0174     } else if (args[0] == Value::errorDEPEND()) {
0175         // non-standard error type
0176         return Value(102);
0177     } else if (args[0] == Value::errorPARSE()) {
0178         // non-standard error type
0179         return Value(103);
0180     } else {
0181         // something I didn't think of...
0182         debugSheets << "Unexpected error type";
0183         return Value(0);
0184     }
0185 }
0186 // Function: INFO
0187 Value func_info(valVector args, ValueCalc *calc, FuncExtra *)
0188 {
0189     QString type = calc->conv()->asString(args[0]).asString().toLower();
0190 
0191     if (type == "directory")
0192         return Value(QDir::currentPath());
0193 
0194     if (type == "release")
0195         return Value(CalligraVersionWrapper::versionString());
0196 
0197     if (type == "numfile") {
0198         KoApplication *app = qobject_cast<KoApplication*>(qApp);
0199         if(! app) {
0200            return Value(0);
0201         } else {
0202 
0203             QSet<QString> nameList;
0204             QList<KoPart*> parts = app->partList();
0205             foreach(KoPart* part, parts) {
0206                 nameList.insert(part->document()->objectName());
0207             }
0208             return Value(nameList.size());
0209         }
0210     }
0211 
0212     if (type == "recalc") {
0213         QString result;
0214         if (!calc->settings()->isAutoCalculationEnabled())
0215             result = i18n("Manual");
0216         else
0217             result = i18n("Automatic");
0218         return Value(result);
0219     }
0220 
0221     if (type == "memavail")
0222         // not supported
0223         return Value::errorVALUE();
0224     if (type == "memused")
0225         // not supported
0226         return Value::errorVALUE();
0227     if (type == "origin")
0228         // not supported
0229         return Value::errorVALUE();
0230 
0231     if (type == "system") {
0232 #ifndef Q_OS_WIN
0233         struct utsname name;
0234         if (uname(&name) >= 0)
0235             return Value(QString(name.sysname));
0236 #else
0237         return Value(QString("Windows"));
0238 #endif
0239     }
0240 
0241     if (type == "totmem")
0242         // not supported
0243         return Value::errorVALUE();
0244 
0245     if (type == "osversion") {
0246 #ifndef Q_OS_WIN
0247         struct utsname name;
0248         if (uname(&name) >= 0) {
0249             QString os = QString("%1 %2 (%3)").arg(name.sysname).
0250                          arg(name.release).arg(name.machine);
0251             return Value(os);
0252         }
0253 #else
0254         OSVERSIONINFO versionInfo;
0255         SYSTEM_INFO sysInfo;
0256         QString architecture;
0257         
0258         versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
0259         
0260         GetVersionEx(&versionInfo);
0261         GetSystemInfo(&sysInfo);
0262         
0263         switch(sysInfo.wProcessorArchitecture) {
0264         case PROCESSOR_ARCHITECTURE_AMD64:
0265             architecture = QString("x86_64");
0266             break;
0267         case PROCESSOR_ARCHITECTURE_IA64:
0268             architecture = QString("ia64");
0269             break;
0270         case PROCESSOR_ARCHITECTURE_INTEL:
0271             architecture = QString("x86");
0272             break;
0273         default:
0274             architecture = QString("unknown");
0275         }
0276         
0277         QString os = QString("Windows %1.%2 (%3)").arg(versionInfo.dwMajorVersion).arg(versionInfo.dwMinorVersion).arg(architecture);
0278         
0279         return Value(os);
0280 #endif
0281     }
0282 
0283     return Value::errorVALUE();
0284 }
0285 
0286 // Function: ISBLANK
0287 Value func_isblank(valVector args, ValueCalc *, FuncExtra *)
0288 {
0289     return Value(args[0].isEmpty());
0290 }
0291 
0292 // Function: ISLOGICAL
0293 Value func_islogical(valVector args, ValueCalc *, FuncExtra *)
0294 {
0295     return Value(args[0].isBoolean());
0296 }
0297 
0298 // Function: ISTEXT
0299 Value func_istext(valVector args, ValueCalc *, FuncExtra *)
0300 {
0301     return Value(args[0].isString());
0302 }
0303 
0304 // Function: ISREF
0305 Value func_isref(valVector args, ValueCalc * /*calc*/, FuncExtra *e)
0306 {
0307     if (args[0].isError()) return args[0];  // errors pass through
0308     // no reference ?
0309     if ((e == 0) || (e->ranges[0].col1 == -1) || (e->ranges[0].row1 == -1))
0310         return Value(false);
0311     // if we are here, it is a reference (cell/range)
0312     return Value(true);
0313 }
0314 
0315 // Function: ISNOTTEXT
0316 Value func_isnottext(valVector args, ValueCalc *, FuncExtra *)
0317 {
0318     return Value(args[0].isString() ? false : true);
0319 }
0320 
0321 // Function: ISNUM
0322 Value func_isnum(valVector args, ValueCalc *, FuncExtra *)
0323 {
0324     return Value(args[0].isNumber());
0325 }
0326 
0327 // Function: ISTIME
0328 Value func_istime(valVector args, ValueCalc *, FuncExtra *)
0329 {
0330     return Value((args[0].format() == Value::fmt_Time)
0331                  || (args[0].format() == Value::fmt_DateTime));
0332 }
0333 
0334 // Function: ISDATE
0335 Value func_isdate(valVector args, ValueCalc *, FuncExtra *)
0336 {
0337     return Value((args[0].format() == Value::fmt_Date)
0338                  || (args[0].format() == Value::fmt_DateTime));
0339 }
0340 
0341 // Function: ISODD
0342 Value func_isodd(valVector args, ValueCalc *calc, FuncExtra *)
0343 {
0344     return Value(calc->isEven(args[0]) ? false : true);
0345 }
0346 
0347 // Function: ISEVEN
0348 Value func_iseven(valVector args, ValueCalc *calc, FuncExtra *)
0349 {
0350     if (args[0].isError())
0351         return args[0];
0352     return Value(calc->isEven(args[0]));
0353 }
0354 
0355 // Function: ISFORMULA
0356 Value func_isformula(valVector /*args*/, ValueCalc */*calc*/, FuncExtra *e)
0357 {
0358     const Calligra::Sheets::Region &region = e->regions[0];
0359     QPoint p = region.firstRange().topLeft();
0360     CellStorage *s = region.firstSheet()->cellStorage();
0361     Formula formula = s->formula(p.x(), p.y());
0362     return Value(formula.isValid());
0363 }
0364 
0365 // Function: ISERR
0366 Value func_iserr(valVector args, ValueCalc *, FuncExtra *)
0367 {
0368     return Value((args[0].isError() &&
0369                   (args[0].errorMessage() != Value::errorNA().errorMessage())));
0370 }
0371 
0372 // Function: ISERROR
0373 Value func_iserror(valVector args, ValueCalc *, FuncExtra *)
0374 {
0375     return Value(args[0].isError());
0376 }
0377 
0378 // Function: ISNA
0379 Value func_isna(valVector args, ValueCalc *, FuncExtra *)
0380 {
0381     return Value((args[0].isError() &&
0382                   (args[0].errorMessage() == Value::errorNA().errorMessage())));
0383 }
0384 
0385 // Function: TYPE
0386 Value func_type(valVector args, ValueCalc *, FuncExtra *)
0387 {
0388     // Returns 1 for numbers, 2 for text, 4 for boolean, 16 for error,
0389     // 64 for arrays
0390     if (args[0].isArray())
0391         return Value(64);
0392     if (args[0].isNumber())
0393         return Value(1);
0394     if (args[0].isString())
0395         return Value(2);
0396     if (args[0].isBoolean())
0397         return Value(4);
0398     if (args[0].isError())
0399         return Value(16);
0400 
0401     // something else ?
0402     return Value(0);
0403 }
0404 
0405 Value func_filename(valVector, ValueCalc *calc, FuncExtra *)
0406 {
0407     return Value(calc->settings()->fileName());
0408 }
0409 
0410 Value func_formula(valVector, ValueCalc *, FuncExtra *e)
0411 {
0412     if(e->ranges[0].col1 < 1 || e->ranges[0].row1 < 1)
0413         return Value::errorVALUE();
0414     const Calligra::Sheets::Cell c(e->sheet, e->ranges[0].col1, e->ranges[0].row1);
0415     if (c.isNull())
0416         return Value::errorVALUE();
0417     if (!c.isFormula())
0418         return Value::errorNA();
0419     return Value(c.formula().expression());
0420 }
0421 
0422 // Function: N
0423 Value func_n(valVector args, ValueCalc *calc, FuncExtra *)
0424 {
0425     return calc->conv()->asFloat(args[0]);
0426 }
0427 
0428 // Function: NA
0429 Value func_na(valVector, ValueCalc *, FuncExtra *)
0430 {
0431     return Value::errorNA();
0432 }
0433 
0434 #include "information.moc"