File indexing completed on 2024-04-28 16:21:23

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003,2004 Ariya Hidayat <ariya@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 // Local
0022 #include "FunctionRepository.h"
0023 
0024 #include "SheetsDebug.h"
0025 #include "Function.h"
0026 #include "FunctionDescription.h"
0027 #include "FunctionModuleRegistry.h"
0028 
0029 #include <QDomElement>
0030 #include <QDomNode>
0031 #include <QFile>
0032 #include <QHash>
0033 
0034 #include <QGlobalStatic>
0035 #include <KLocalizedString>
0036 
0037 Q_GLOBAL_STATIC(Calligra::Sheets::FunctionRepository, s_instance)
0038 
0039 using namespace Calligra::Sheets;
0040 
0041 class Q_DECL_HIDDEN FunctionRepository::Private
0042 {
0043 public:
0044     QHash<QString, QSharedPointer<Function> > functions;
0045     QHash<QString, QSharedPointer<Function> > alternates;
0046     QHash<QString, FunctionDescription*> descriptions;
0047     QStringList groups;
0048     bool initialized;
0049 };
0050 
0051 FunctionRepository* FunctionRepository::self()
0052 {
0053     if (!s_instance.exists()) {
0054         *s_instance; // creates the global instance
0055 
0056         // register all existing functions
0057         FunctionModuleRegistry::instance()->registerFunctions();
0058 
0059 #ifndef NDEBUG
0060         debugSheetsUI << "functions registered:" << s_instance->d->functions.count()
0061                       << "descriptions loaded:" << s_instance->d->descriptions.count();
0062 
0063         // Verify, that every function has a description.
0064         QStringList missingDescriptions;
0065         typedef QHash<QString, QSharedPointer<Function> > Functions;
0066         Functions::ConstIterator end = s_instance->d->functions.constEnd();
0067         for (Functions::ConstIterator it = s_instance->d->functions.constBegin(); it != end; ++it) {
0068             if (!s_instance->d->descriptions.contains(it.key()))
0069                 missingDescriptions << it.key();
0070         }
0071         if (missingDescriptions.count() > 0) {
0072             debugSheetsUI << "No function descriptions found for:";
0073             foreach(const QString& missingDescription, missingDescriptions) {
0074                 debugSheetsUI << "\t" << missingDescription;
0075             }
0076         }
0077 #endif
0078     }
0079     return s_instance;
0080 }
0081 
0082 FunctionRepository::FunctionRepository()
0083         : d(new Private)
0084 {
0085     d->initialized = false;
0086 }
0087 
0088 FunctionRepository::~FunctionRepository()
0089 {
0090     qDeleteAll(d->descriptions);
0091     delete d;
0092 }
0093 
0094 void FunctionRepository::add(const QSharedPointer<Function>& function)
0095 {
0096     if (!function) return;
0097     d->functions.insert(function->name().toUpper(), function);
0098 
0099     if (!function->alternateName().isNull()) {
0100         d->alternates.insert(function->alternateName().toUpper(), function);
0101     }
0102 }
0103 
0104 void FunctionRepository::add(FunctionDescription *desc)
0105 {
0106     if (!desc) return;
0107     if (!d->functions.contains(desc->name())) return;
0108     d->descriptions.insert(desc->name(), desc);
0109 }
0110 
0111 void FunctionRepository::remove(const QSharedPointer<Function>& function)
0112 {
0113     const QString functionName = function->name().toUpper();
0114     delete d->descriptions.take(functionName);
0115     if (d->functions.contains(functionName)) {
0116         QSharedPointer<Function> function = d->functions.take(functionName);
0117         d->alternates.remove(function->alternateName().toUpper());
0118     }
0119 }
0120 
0121 QSharedPointer<Function> FunctionRepository::function(const QString& name)
0122 {
0123     const QString n = name.toUpper();
0124     QSharedPointer<Function> f = d->functions.value(n);
0125     return !f.isNull() ? f : d->alternates.value(n);
0126 }
0127 
0128 FunctionDescription *FunctionRepository::functionInfo(const QString& name)
0129 {
0130     return d->descriptions.value(name.toUpper());
0131 }
0132 
0133 // returns names of function in certain group
0134 QStringList FunctionRepository::functionNames(const QString& group)
0135 {
0136     QStringList lst;
0137 
0138     foreach(FunctionDescription* description, d->descriptions) {
0139         if (group.isNull() || (description->group() == group))
0140             lst.append(description->name());
0141     }
0142 
0143     lst.sort();
0144     return lst;
0145 }
0146 
0147 const QStringList& FunctionRepository::groups() const
0148 {
0149     return d->groups;
0150 }
0151 
0152 void FunctionRepository::addGroup(const QString& groupname)
0153 {
0154     d->groups.append(groupname);
0155     d->groups.sort();
0156 }
0157 
0158 void FunctionRepository::loadFunctionDescriptions(const QString& filename)
0159 {
0160     QFile file(filename);
0161     if (!file.open(QIODevice::ReadOnly))
0162         return;
0163 
0164     QDomDocument doc;
0165     doc.setContent(&file);
0166     file.close();
0167 
0168     QString group;
0169 
0170     QDomNode n = doc.documentElement().firstChild();
0171     for (; !n.isNull(); n = n.nextSibling()) {
0172         if (!n.isElement())
0173             continue;
0174         QDomElement e = n.toElement();
0175         if (e.tagName() == "Group") {
0176             group = i18n(e.namedItem("GroupName").toElement().text().toUtf8());
0177             addGroup(group);
0178 
0179             QDomNode n2 = e.firstChild();
0180             for (; !n2.isNull(); n2 = n2.nextSibling()) {
0181                 if (!n2.isElement())
0182                     continue;
0183                 QDomElement e2 = n2.toElement();
0184                 if (e2.tagName() == "Function") {
0185                     FunctionDescription* desc = new FunctionDescription(e2);
0186                     desc->setGroup(group);
0187                     if (d->functions.contains(desc->name()))
0188                         d->descriptions.insert(desc->name(), desc);
0189                     else {
0190                         debugSheetsUI << "Description for unknown function" << desc->name() << "found.";
0191                         delete desc;
0192                     }
0193                 }
0194             }
0195             group.clear();
0196         }
0197     }
0198 }