File indexing completed on 2024-05-19 12:54:39

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003 Lucijan Busch <lucijan@gmx.at>
0003    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
0004    Copyright (C) 2004-2015 Jarosław Staniek <staniek@kde.org>
0005 
0006    This library is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Library General Public
0008    License as published by the Free Software Foundation; either
0009    version 2 of the License, or (at your option) any later version.
0010 
0011    This library is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014    Library General Public License for more details.
0015 
0016    You should have received a copy of the GNU Library General Public License
0017    along with this library; see the file COPYING.LIB.  If not, write to
0018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020 */
0021 
0022 #include "widgetlibrary.h"
0023 #include <KexiIcon.h>
0024 #include "WidgetInfo.h"
0025 #include "widgetfactory.h"
0026 #include "libactionwidget.h"
0027 #include "container.h"
0028 #include "form.h"
0029 #include "formIO.h"
0030 #include "FormWidgetInterface.h"
0031 #include "objecttree.h"
0032 #include "KexiJsonTrader.h"
0033 #include "KexiFormWidgetsPluginMetaData.h"
0034 #include "KexiVersion.h"
0035 #include <core/kexiguimsghandler.h>
0036 #define KEXI_SKIP_SETUPBREEZEICONTHEME
0037 #define KEXI_SKIP_REGISTERRESOURCE
0038 #include <main/KexiRegisterResource_p.h>
0039 
0040 #include <KActionCollection>
0041 #include <KLocalizedString>
0042 
0043 #include <QDomDocument>
0044 #include <QMenu>
0045 #include <QDebug>
0046 
0047 namespace KFormDesigner
0048 {
0049 
0050 Q_GLOBAL_STATIC_WITH_ARGS(KexiJsonTrader, KexiFormWidgetsPluginTrader_instance, (KEXI_BASE_PATH "/forms/widgets"))
0051 
0052 //! @internal
0053 class Q_DECL_HIDDEN WidgetLibrary::Private
0054 {
0055 public:
0056     Private(WidgetLibrary *library, const QStringList& supportedFactoryGroups)
0057             : showAdvancedProperties(true)
0058             , q(library)
0059             , m_couldNotFindAnyFormWidgetPluginsErrorDisplayed(false)
0060             , m_supportedFactoryGroups(supportedFactoryGroups.toSet())
0061             , m_lookupDone(false)
0062             , m_lookupResult(false)
0063             , m_loadFactoriesDone(false)
0064     {
0065         q->setMessageHandler(&messageHandler);
0066         m_advancedProperties.insert("acceptDrops");
0067         m_advancedProperties.insert("accessibleDescription");
0068         m_advancedProperties.insert("accessibleName");
0069         m_advancedProperties.insert("autoMask");
0070         m_advancedProperties.insert("backgroundOrigin");
0071         m_advancedProperties.insert("backgroundMode");//this is rather useless
0072         m_advancedProperties.insert("baseSize");
0073         m_advancedProperties.insert("contextMenuEnabled");
0074         m_advancedProperties.insert("contextMenuPolicy");
0075         m_advancedProperties.insert("cursorPosition");
0076         m_advancedProperties.insert("cursorMoveStyle");
0077         m_advancedProperties.insert("dragEnabled");
0078         m_advancedProperties.insert("enableSqueezedText");
0079         m_advancedProperties.insert("layout");// too large risk to break things
0080         m_advancedProperties.insert("layoutDirection");
0081         m_advancedProperties.insert("locale");
0082         m_advancedProperties.insert("mouseTracking");
0083 /*! @todo: reenable */ m_advancedProperties.insert("palette");
0084         m_advancedProperties.insert("sizeAdjustPolicy"); //QAbstractScrollArea
0085         m_advancedProperties.insert("sizeIncrement");
0086         m_advancedProperties.insert("sizePolicy");
0087         m_advancedProperties.insert("statusTip");
0088         m_advancedProperties.insert("tabletTracking");
0089         m_advancedProperties.insert("toolTipDuration");
0090         m_advancedProperties.insert("trapEnterKeyEvent");
0091         m_advancedProperties.insert("windowModality");
0092         m_advancedProperties.insert("autoExclusive");
0093         // by providing this in propeditor
0094         m_advancedProperties.insert("minimumSize");
0095         m_advancedProperties.insert("maximumSize");
0096         m_advancedProperties.insert("clickMessage"); // for backward compatibility KEXI projects created with Qt < 4.7
0097         m_advancedProperties.insert("showClearButton"); // for backward compatibility KEXI projects created with Qt 4
0098 #ifndef KEXI_SHOW_UNFINISHED
0099 /*! @todo reenable */
0100         m_advancedProperties.insert("accel");
0101         m_advancedProperties.insert("icon");
0102         m_advancedProperties.insert("paletteBackgroundPixmap");
0103         m_advancedProperties.insert("pixmap");
0104         m_advancedProperties.insert("shortcut"); // renamed from "accel" in Qt 4
0105         m_advancedProperties.insert("windowIcon"); // renamed from "icon" in Qt 4
0106 #endif
0107     }
0108     ~Private() {
0109         qDeleteAll(m_factories);
0110         m_factories.clear();
0111         qDeleteAll(m_pluginsMetaData);
0112         m_pluginsMetaData.clear();
0113     }
0114 
0115     QHash<QByteArray, WidgetInfo*> widgets() {
0116         KDbMessageGuard mg(q);
0117         (void)loadFactories();
0118         return m_widgets;
0119     }
0120 
0121     QHash<QByteArray, WidgetFactory*> factories() {
0122         KDbMessageGuard mg(q);
0123         (void)loadFactories();
0124         return m_factories;
0125     }
0126 
0127     bool isAdvancedProperty(const QByteArray &property) const {
0128         return m_advancedProperties.contains(property);
0129     }
0130 
0131     bool showAdvancedProperties;
0132 
0133 private:
0134     //! Performs a form widget plugins lookup. @return true on success.
0135     //! @todo This method generates a few warnings, maybe we want to optionally display them somewhere (via the message handler)?
0136     bool lookup() {
0137         //! @todo Allow refreshing
0138         if (m_lookupDone) {
0139             return m_lookupResult;
0140         }
0141         m_lookupDone = true;
0142         m_lookupResult = false;
0143         q->clearResult();
0144 
0145         QStringList serviceTypes;
0146         serviceTypes << "Kexi/FormWidget";
0147         QList<QPluginLoader*> offers = KexiFormWidgetsPluginTrader_instance->query(serviceTypes);
0148         foreach(const QPluginLoader *loader, offers) {
0149             QScopedPointer<KexiFormWidgetsPluginMetaData> metaData(new KexiFormWidgetsPluginMetaData(*loader));
0150             if (metaData->id().isEmpty()) {
0151                 qWarning() << "No plugin ID specified for Kexi Form Widgets plugin"
0152                            << metaData->fileName() << "-- skipping!";
0153                 continue;
0154             }
0155             // check version
0156             const QString expectedVersion = KFormDesigner::version();
0157             if (metaData->version() != expectedVersion) {
0158                 qWarning() << "Kexi Form Widgets plugin" << metaData->id() << "has version"
0159                            << metaData->majorVersion() << "but required version is" << KFormDesigner::version()
0160                            << "-- skipping!";
0161                 continue;
0162             }
0163             // skip duplicates
0164             if (m_pluginsMetaData.contains(metaData->id())) {
0165                 qWarning() << "More than one Kexi Form Widgets plugin with ID"
0166                            << metaData->id() << metaData->fileName() << "-- skipping this one";
0167                 continue;
0168             }
0169             //qDebug() << "found factory:" << ptr->name();
0170 
0171             if (!metaData->group().isEmpty() && !m_supportedFactoryGroups.contains(metaData->group())) {
0172                 qDebug() << "Factory group" << metaData->group()
0173                          << "for Form Widgets plugin"
0174                          << metaData->id() << metaData->fileName()
0175                          << "is not supported -- skipping!";
0176                 continue;
0177             }
0178             if (!setupPrivateIconsResourceWithMessage(
0179                 QLatin1String(KEXI_BASE_PATH),
0180                 QString::fromLatin1("icons/%1_%2.rcc")
0181                     .arg(metaData->id()).arg(supportedIconTheme),
0182                 QtWarningMsg,
0183                 QString::fromLatin1(":/icons/%1").arg(metaData->id())))
0184             {
0185                 continue;
0186             }
0187 
0188             m_pluginsMetaData.insert(metaData->id(), metaData.data());
0189             metaData.take();
0190         }
0191         qDeleteAll(offers);
0192         offers.clear();
0193         if (m_pluginsMetaData.isEmpty()) {
0194             q->m_result = KDbResult(i18n("Could not find any form widget plugins."));
0195             m_couldNotFindAnyFormWidgetPluginsErrorDisplayed = true;
0196             return false;
0197         }
0198         m_lookupResult = true;
0199         return true;
0200     }
0201 
0202     //! Loads all factory plugins
0203     bool loadFactories() {
0204         if (m_loadFactoriesDone) {
0205             if (m_couldNotFindAnyFormWidgetPluginsErrorDisplayed) {
0206                 q->clearResult(); // show the warning only once
0207             }
0208             return m_loadFactoriesResult;
0209         }
0210         m_loadFactoriesDone = true;
0211         m_loadFactoriesResult = false;
0212         if (!lookup()) {
0213             return false;
0214         }
0215         foreach (KexiFormWidgetsPluginMetaData *pluginMetaData, m_pluginsMetaData) {
0216             WidgetFactory *factory = loadFactory(pluginMetaData);
0217             if (!factory) {
0218                 continue;
0219             }
0220             //collect information about classes to be hidden
0221             if (factory->hiddenClasses()) {
0222                 foreach (const QByteArray &c, *factory->hiddenClasses()) {
0223                     m_hiddenClasses.insert(c);
0224                 }
0225             }
0226         }
0227 
0228         //now we have factories instantiated: load widgets
0229         QList<WidgetFactory*> loadLater;
0230         foreach (WidgetFactory *factory, m_factories) {
0231             //ONE LEVEL, FLAT INHERITANCE, but works!
0232             //if this factory inherits from something, load its witgets later
0233     //! @todo improve
0234             if (factory->inheritsFactories())
0235                 loadLater.append(factory);
0236             else
0237                 loadFactoryWidgets(factory);
0238         }
0239         //load now the rest
0240         foreach (WidgetFactory* f, loadLater) {
0241             loadFactoryWidgets(f);
0242         }
0243         m_loadFactoriesResult = true;
0244         return true;
0245     }
0246 
0247     //! Loads of a single factory. @return true on success
0248     WidgetFactory *loadFactory(KexiFormWidgetsPluginMetaData *pluginMetaData) {
0249         KPluginFactory *factory = qobject_cast<KPluginFactory*>(pluginMetaData->instantiate());
0250         if (!factory) {
0251             q->m_result = KDbResult(
0252                 ERR_CANNOT_LOAD_OBJECT,
0253                 xi18nc("@info", "Could not load Form Widgets plugin file <filename>%1</filename> "
0254                                 "for <application>%2</application>.",
0255                        pluginMetaData->fileName(), QApplication::applicationDisplayName()));
0256             q->setErrorMessage(pluginMetaData, q->result().message());
0257             qWarning() << q->result().message();
0258             return 0;
0259         }
0260         WidgetFactory *widgetFactory = factory->create<WidgetFactory>(q);
0261         if (!widgetFactory) {
0262             q->m_result = KDbResult(
0263                 ERR_CANNOT_LOAD_OBJECT,
0264                 xi18nc("@info", "Could not open Form Widgets plugin <filename>%1</filename> for "
0265                                 "<application>%2</application>.",
0266                        pluginMetaData->fileName(), QApplication::applicationDisplayName()));
0267             qWarning() << q->m_result.message();
0268             return 0;
0269         }
0270         widgetFactory->setLibrary(q);
0271         widgetFactory->setObjectName(pluginMetaData->id());
0272         widgetFactory->setAdvancedPropertiesVisible(showAdvancedProperties); //inherit this flag from the library
0273         m_factories.insert(pluginMetaData->id().toLatin1(), widgetFactory);
0274         return widgetFactory;
0275     }
0276 
0277     //! Loads widgets for factory @a f
0278     void loadFactoryWidgets(WidgetFactory *f) {
0279         QHash<QByteArray, WidgetInfo*> widgetsForFactory(f->classes());
0280         foreach (WidgetInfo *w, widgetsForFactory) {
0281             if (m_hiddenClasses.contains( w->className() ))
0282                 continue; //this class is hidden
0283             // check if we want to inherit a widget from a different factory
0284             if (!w->parentFactoryName().isEmpty() && !w->inheritedClassName().isEmpty()) {
0285                 WidgetFactory *parentFactory = m_factories.value(w->parentFactoryName().toLower());
0286                 if (!parentFactory) {
0287                     qWarning() << "class" << w->className() << ": no such parent factory" << w->parentFactoryName();
0288                     continue;
0289                 }
0290                 WidgetInfo* inheritedClass = parentFactory->widgetInfoForClassName(w->inheritedClassName());
0291                 if (!inheritedClass) {
0292                     qWarning() << "class" << w->inheritedClassName() << "- no such class to inherit in factory"
0293                         << w->parentFactoryName();
0294                     continue;
0295                 }
0296                 //ok: inherit properties:
0297                 w->setInheritedClass( inheritedClass );
0298                 if (w->iconName().isEmpty())
0299                     w->setIconName(inheritedClass->iconName());
0300                 //ok?
0301                 foreach(const QByteArray& alternateName, inheritedClass->alternateClassNames()) {
0302                     w->addAlternateClassName(
0303                         alternateName, inheritedClass->isOverriddenClassName(alternateName));
0304                 }
0305                 if (w->includeFileName().isEmpty())
0306                     w->setIncludeFileName(inheritedClass->includeFileName());
0307                 if (w->name().isEmpty())
0308                     w->setName(inheritedClass->name());
0309                 if (w->namePrefix().isEmpty())
0310                     w->setNamePrefix(nullptr, qPrintable(inheritedClass->namePrefix()));
0311                 if (w->description().isEmpty())
0312                     w->setDescription(inheritedClass->description());
0313             }
0314 
0315             QList<QByteArray> cnames( w->alternateClassNames() );
0316             cnames.prepend(w->className());
0317             foreach (const QByteArray &wname, cnames) {
0318                 WidgetInfo *widgetForClass = widgetsForFactory.value(wname);
0319                 if (!widgetForClass || (widgetForClass && !widgetForClass->isOverriddenClassName(wname))) {
0320                     //insert a widgetinfo, if:
0321                     //1) this class has no alternate class assigned yet, or
0322                     //2) this class has alternate class assigned but without 'override' flag
0323                     m_widgets.insert(wname, w);
0324                 }
0325             }
0326         }
0327     }
0328 
0329     WidgetLibrary *q;
0330     KexiGUIMessageHandler messageHandler;
0331     //! A map which associates a class name with a Widget class
0332     QHash<QString, KexiFormWidgetsPluginMetaData*> m_pluginsMetaData; //!< owner
0333     bool m_couldNotFindAnyFormWidgetPluginsErrorDisplayed;
0334     QSet<QString> m_supportedFactoryGroups;
0335     QHash<QByteArray, WidgetFactory*> m_factories; //!< owner
0336     QHash<QByteArray, WidgetInfo*> m_widgets; //!< owner
0337     QSet<QByteArray> m_advancedProperties;
0338     QSet<QByteArray> m_hiddenClasses;
0339     bool m_lookupDone;
0340     bool m_lookupResult;
0341     bool m_loadFactoriesDone;
0342     bool m_loadFactoriesResult;
0343 };
0344 }
0345 
0346 using namespace KFormDesigner;
0347 
0348 //-------------------------------------------
0349 
0350 WidgetLibrary::WidgetLibrary(QObject *parent, const QStringList& supportedFactoryGroups)
0351         : QObject(parent)
0352         , KDbResultable()
0353         , d(new Private(this, supportedFactoryGroups))
0354 {
0355 }
0356 
0357 WidgetLibrary::~WidgetLibrary()
0358 {
0359     delete d;
0360 }
0361 
0362 void WidgetLibrary::createWidgetActions(ActionGroup *group)
0363 {
0364     foreach (WidgetInfo *winfo, d->widgets()) {
0365         LibActionWidget *a = new LibActionWidget(group, winfo);
0366         connect(a, SIGNAL(toggled(QByteArray)), this, SIGNAL(widgetActionToggled(QByteArray)));
0367     }
0368 }
0369 
0370 void
0371 WidgetLibrary::addCustomWidgetActions(KActionCollection *col)
0372 {
0373     if (!col)
0374         return;
0375     foreach (WidgetFactory *factory, d->factories()) {
0376         factory->createCustomActions(col);
0377     }
0378 }
0379 
0380 QWidget* WidgetLibrary::createWidget(const QByteArray &classname, QWidget *parent,
0381                                      const char *name, Container *c,
0382                                      WidgetFactory::CreateWidgetOptions options)
0383 {
0384     WidgetInfo *wclass = d->widgets().value(classname);
0385     if (!wclass)
0386         return 0;
0387 
0388     QWidget *widget = wclass->factory()->createWidget(wclass->className(), parent, name, c, options);
0389     if (!widget) {
0390         //try to instantiate from inherited class
0391         if (wclass->inheritedClass())
0392             widget = wclass->inheritedClass()->factory()->createWidget(
0393                          wclass->className(), parent, name, c, options);
0394         if (!widget)
0395             return 0;
0396     }
0397     widget->setAcceptDrops(true);
0398     if (options & WidgetFactory::DesignViewMode) {
0399         FormWidgetInterface* fwiface = dynamic_cast<FormWidgetInterface*>(widget);
0400         if (fwiface)
0401             fwiface->setDesignMode(true);
0402     }
0403     emit widgetCreated(widget);
0404     return widget;
0405 }
0406 
0407 bool WidgetLibrary::createMenuActions(const QByteArray &c, QWidget *w, QMenu *menu,
0408                                       KFormDesigner::Container *container)
0409 {
0410     WidgetInfo *wclass = d->widgets().value(c);
0411     if (!wclass)
0412         return false;
0413 
0414     if (wclass->factory()->createMenuActions(c, w, menu, container)) {
0415         return true;
0416     }
0417     //try from inherited class
0418     if (wclass->inheritedClass()) {
0419         return wclass->inheritedClass()->factory()->createMenuActions(
0420                    wclass->className(), w, menu, container);
0421     }
0422     return false;
0423 }
0424 
0425 bool WidgetLibrary::startInlineEditing(const QByteArray &classname, QWidget *w,
0426                                        Container *container)
0427 {
0428     WidgetInfo *wclass = d->widgets().value(classname);
0429     if (!wclass)
0430         return false;
0431 
0432     FormWidgetInterface* fwiface = dynamic_cast<FormWidgetInterface*>(w);
0433     {
0434         KFormDesigner::WidgetFactory::InlineEditorCreationArguments args(classname, w, container);
0435         if (wclass->factory()->startInlineEditing(args)) {
0436             args.container->form()->createInlineEditor(args);
0437             if (fwiface)
0438                 fwiface->setEditingMode(true);
0439             return true;
0440         }
0441     }
0442     if (wclass->inheritedClass()) {
0443         //try from inherited class
0444         KFormDesigner::WidgetFactory::InlineEditorCreationArguments args(wclass->className(), w, container);
0445         if (wclass->inheritedClass()->factory()->startInlineEditing(args)) {
0446             args.container->form()->createInlineEditor(args);
0447             if (fwiface)
0448                 fwiface->setEditingMode(true);
0449             return true;
0450         }
0451     }
0452     return false;
0453 }
0454 
0455 bool WidgetLibrary::previewWidget(const QByteArray &classname, QWidget *widget, Container *container)
0456 {
0457     WidgetInfo *wclass = d->widgets().value(classname);
0458     if (!wclass)
0459         return false;
0460 
0461     FormWidgetInterface* fwiface = dynamic_cast<FormWidgetInterface*>(widget);
0462     if (fwiface)
0463         fwiface->setDesignMode(false);
0464     if (wclass->factory()->previewWidget(classname, widget, container))
0465         return true;
0466     //try from inherited class
0467     if (wclass->inheritedClass())
0468         return wclass->inheritedClass()->factory()->previewWidget(wclass->className(), widget, container);
0469     return false;
0470 }
0471 
0472 bool WidgetLibrary::clearWidgetContent(const QByteArray &classname, QWidget *w)
0473 {
0474     WidgetInfo *wclass = d->widgets().value(classname);
0475     if (!wclass)
0476         return false;
0477 
0478     if (wclass->factory()->clearWidgetContent(classname, w))
0479         return true;
0480     //try from inherited class
0481     if (wclass->inheritedClass())
0482         return wclass->inheritedClass()->factory()->clearWidgetContent(wclass->className(), w);
0483     return false;
0484 }
0485 
0486 QString WidgetLibrary::displayName(const QByteArray &classname)
0487 {
0488     WidgetInfo *wi = d->widgets().value(classname);
0489     if (wi)
0490         return wi->name();
0491 
0492     return classname;
0493 }
0494 
0495 QString WidgetLibrary::savingName(const QByteArray &classname)
0496 {
0497     WidgetInfo *wi = d->widgets().value(classname);
0498     if (wi && !wi->savingName().isEmpty())
0499         return wi->savingName();
0500 
0501     return classname;
0502 }
0503 
0504 QString WidgetLibrary::namePrefix(const QByteArray &classname)
0505 {
0506     WidgetInfo *wi = d->widgets().value(classname);
0507     if (wi)
0508         return wi->namePrefix();
0509 
0510     return classname;
0511 }
0512 
0513 QString WidgetLibrary::textForWidgetName(const QByteArray &name, const QByteArray &className)
0514 {
0515     WidgetInfo *widget = d->widgets().value(className);
0516     if (!widget)
0517         return QString();
0518 
0519     QString newName = name;
0520     newName.remove(widget->namePrefix());
0521     newName = widget->name() + (newName.isEmpty() ? QString() : (QLatin1String(" ") + newName));
0522     return newName;
0523 }
0524 
0525 QByteArray
0526 WidgetLibrary::classNameForAlternate(const QByteArray &classname)
0527 {
0528     if (d->widgets().value(classname))
0529         return classname;
0530 
0531     WidgetInfo *wi =  d->widgets().value(classname);
0532     if (wi) {
0533         return wi->className();
0534     }
0535 
0536     // widget not supported
0537     return "CustomWidget";
0538 }
0539 
0540 QString WidgetLibrary::includeFileName(const QByteArray &classname)
0541 {
0542     WidgetInfo *wi = d->widgets().value(classname);
0543     if (wi)
0544         return wi->includeFileName();
0545 
0546     return QString();
0547 }
0548 
0549 QString
0550 WidgetLibrary::iconName(const QByteArray &classname)
0551 {
0552     WidgetInfo *wi = d->widgets().value(classname);
0553     if (wi)
0554         return wi->iconName();
0555 
0556     return KexiIconName("unknown-widget");
0557 }
0558 
0559 bool
0560 WidgetLibrary::saveSpecialProperty(const QByteArray &classname,
0561     const QString &name, const QVariant &value, QWidget *w,
0562     QDomElement &parentNode, QDomDocument &parent)
0563 {
0564     WidgetInfo *wi = d->widgets().value(classname);
0565     if (!wi)
0566         return false;
0567 
0568     if (wi->factory()->saveSpecialProperty(classname, name, value, w, parentNode, parent))
0569         return true;
0570     //try from inherited class
0571     if (wi->inheritedClass())
0572         return wi->inheritedClass()->factory()->saveSpecialProperty(wi->className(), name, value, w, parentNode, parent);
0573     return false;
0574 }
0575 
0576 bool
0577 WidgetLibrary::readSpecialProperty(const QByteArray &classname,
0578     QDomElement &node, QWidget *w, ObjectTreeItem *item)
0579 {
0580     WidgetInfo *wi = d->widgets().value(classname);
0581     if (!wi)
0582         return false;
0583     if (wi->factory()->readSpecialProperty(classname, node, w, item))
0584         return true;
0585     //try from inherited class
0586     if (wi->inheritedClass())
0587         return wi->inheritedClass()->factory()->readSpecialProperty(wi->className(), node, w, item);
0588     return false;
0589 }
0590 
0591 void WidgetLibrary::setAdvancedPropertiesVisible(bool set)
0592 {
0593     d->showAdvancedProperties = set;
0594 }
0595 
0596 bool WidgetLibrary::advancedPropertiesVisible() const
0597 {
0598     return d->showAdvancedProperties;
0599 }
0600 
0601 bool
0602 WidgetLibrary::isPropertyVisible(const QByteArray &classname, QWidget *w,
0603                                  const QByteArray &property, bool multiple, bool isTopLevel)
0604 {
0605     if (isTopLevel) {
0606         // no focus policy for top-level form widget...
0607         if (!d->showAdvancedProperties && property == "focusPolicy")
0608             return false;
0609     }
0610 
0611     WidgetInfo *wi = d->widgets().value(classname);
0612     if (!wi)
0613         return false;
0614     if (!d->showAdvancedProperties && d->isAdvancedProperty(property)) {
0615         //this is advanced property, should we hide it?
0616         if (!wi->internalProperty("forceShowAdvancedProperty:" + property).toBool()
0617                 && (!wi->inheritedClass() || !wi->inheritedClass()->internalProperty("forceShowAdvancedProperty:" + property).toBool())) {
0618             return false; //hide it
0619         }
0620     }
0621 
0622     if (!wi->factory()->isPropertyVisible(classname, w, property, multiple, isTopLevel))
0623         return false;
0624     //try from inherited class
0625     if (wi->inheritedClass()
0626             && !wi->inheritedClass()->factory()->isPropertyVisible(wi->className(), w, property, multiple, isTopLevel))
0627         return false;
0628 
0629     return true;
0630 }
0631 
0632 QList<QByteArray> WidgetLibrary::autoSaveProperties(const QByteArray &classname)
0633 {
0634     WidgetInfo *wi = d->widgets().value(classname);
0635     if (!wi)
0636         return QList<QByteArray>();
0637     return wi->autoSaveProperties();
0638 }
0639 
0640 WidgetInfo*
0641 WidgetLibrary::widgetInfoForClassName(const char* classname)
0642 {
0643     return d->widgets().value(classname);
0644 }
0645 
0646 WidgetFactory*
0647 WidgetLibrary::factoryForClassName(const char* classname)
0648 {
0649     WidgetInfo *wi = widgetInfoForClassName(classname);
0650     return wi ? wi->factory() : 0;
0651 }
0652 
0653 QString WidgetLibrary::propertyDescForName(WidgetInfo *winfo, const QByteArray& propertyName)
0654 {
0655     if (!winfo || !winfo->factory())
0656         return QString();
0657     QString desc(winfo->factory()->propertyDescription(propertyName));
0658     if (!desc.isEmpty())
0659         return desc;
0660     if (winfo->parentFactoryName().isEmpty())
0661         return QString();
0662 
0663     //try in parent factory, if exists
0664     WidgetFactory *parentFactory = d->factories().value(winfo->parentFactoryName());
0665     if (!parentFactory)
0666         return QString();
0667 
0668     return parentFactory->propertyDescription(propertyName);
0669 }
0670 
0671 QString WidgetLibrary::propertyDescForValue(WidgetInfo *winfo, const QByteArray& name)
0672 {
0673     if (!winfo->factory())
0674         return QString();
0675     QString desc(winfo->factory()->valueDescription(name));
0676     if (!desc.isEmpty())
0677         return desc;
0678     if (winfo->parentFactoryName().isEmpty())
0679         return QString();
0680 
0681     //try in parent factory, if exists
0682     WidgetFactory *parentFactory = d->factories().value(winfo->parentFactoryName());
0683     if (!parentFactory)
0684         return QString();
0685 
0686     return parentFactory->valueDescription(name);
0687 }
0688 
0689 void WidgetLibrary::setPropertyOptions(KPropertySet& set, const WidgetInfo& winfo, QWidget* w)
0690 {
0691     if (!winfo.factory())
0692         return;
0693     winfo.factory()->setPropertyOptions(set, winfo, w);
0694     if (winfo.parentFactoryName().isEmpty())
0695         return;
0696     WidgetFactory *parentFactory = d->factories().value(winfo.parentFactoryName());
0697     if (!parentFactory)
0698         return;
0699     parentFactory->setPropertyOptions(set, winfo, w);
0700 }
0701 
0702 WidgetFactory* WidgetLibrary::factory(const char* factoryName) const
0703 {
0704     return d->factories().value(factoryName);
0705 }
0706 
0707 QVariant WidgetLibrary::internalProperty(const QByteArray& classname, const QByteArray& property)
0708 {
0709     WidgetInfo *wclass = d->widgets().value(classname);
0710     if (!wclass)
0711         return QString();
0712     QVariant value(wclass->internalProperty(property));
0713     if (value.isNull() && wclass->inheritedClass())
0714         return wclass->inheritedClass()->internalProperty(property);
0715     return value;
0716 }
0717 
0718 WidgetFactory::CreateWidgetOption WidgetLibrary::showOrientationSelectionPopup(
0719     const QByteArray &classname, QWidget* parent, const QPoint& pos)
0720 {
0721     WidgetInfo *wclass = d->widgets().value(classname);
0722     if (!wclass)
0723         return WidgetFactory::AnyOrientation;
0724 
0725     //get custom icons and strings
0726     QIcon iconHorizontal, iconVertical;
0727     QString iconName(wclass->internalProperty("orientationSelectionPopup:horizontalIcon").toString());
0728     if (iconName.isEmpty() && wclass->inheritedClass())
0729         iconName = wclass->inheritedClass()->internalProperty("orientationSelectionPopup:horizontalIcon").toString();
0730     if (!iconName.isEmpty())
0731         iconHorizontal = QIcon::fromTheme(iconName);
0732 
0733     iconName = wclass->internalProperty("orientationSelectionPopup:verticalIcon").toString();
0734     if (iconName.isEmpty() && wclass->inheritedClass())
0735         iconName = wclass->inheritedClass()->internalProperty("orientationSelectionPopup:verticalIcon").toString();
0736     if (!iconName.isEmpty())
0737         iconVertical = QIcon::fromTheme(iconName);
0738 
0739     QString textHorizontal = wclass->internalProperty("orientationSelectionPopup:horizontalText").toString();
0740     if (textHorizontal.isEmpty() && wclass->inheritedClass())
0741         iconName = wclass->inheritedClass()->internalProperty("orientationSelectionPopup:horizontalText").toString();
0742     if (textHorizontal.isEmpty()) //default
0743         textHorizontal = xi18nc("Insert Horizontal Widget", "Insert Horizontal");
0744 
0745     QString textVertical = wclass->internalProperty("orientationSelectionPopup:verticalText").toString();
0746     if (textVertical.isEmpty() && wclass->inheritedClass())
0747         iconName = wclass->inheritedClass()->internalProperty("orientationSelectionPopup:verticalText").toString();
0748     if (textVertical.isEmpty()) //default
0749         textVertical = xi18nc("Insert Vertical Widget", "Insert Vertical");
0750 
0751     QMenu popup(parent);
0752     popup.setObjectName("orientationSelectionPopup");
0753     popup.addSection(QIcon::fromTheme(wclass->iconName()), xi18n("Insert Widget: %1", wclass->name()));
0754     QAction* horizAction = popup.addAction(iconHorizontal, textHorizontal);
0755     QAction* vertAction = popup.addAction(iconVertical, textVertical);
0756     popup.addSeparator();
0757     popup.addAction(koIcon("dialog-cancel"), xi18n("Cancel"));
0758     QAction *a = popup.exec(pos);
0759     if (a == horizAction)
0760         return WidgetFactory::HorizontalOrientation;
0761     else if (a == vertAction)
0762         return WidgetFactory::VerticalOrientation;
0763 
0764     return WidgetFactory::AnyOrientation; //means "cancelled"
0765 }
0766 
0767 bool WidgetLibrary::propertySetShouldBeReloadedAfterPropertyChange(
0768     const QByteArray& classname, QWidget *w, const QByteArray& property)
0769 {
0770     WidgetInfo *winfo = widgetInfoForClassName(classname);
0771     if (!winfo)
0772         return false;
0773     return winfo->factory()->propertySetShouldBeReloadedAfterPropertyChange(classname, w, property);
0774 }
0775 
0776 ObjectTreeItem* WidgetLibrary::selectableItem(ObjectTreeItem* item)
0777 {
0778     //qDebug() << item->widget()->metaObject()->className();
0779     WidgetInfo *wi = d->widgets().value(item->widget()->metaObject()->className());
0780     if (!wi)
0781         return item;
0782     return wi->factory()->selectableItem(item);
0783 }
0784 
0785 
0786 void WidgetLibrary::setErrorMessage(KexiFormWidgetsPluginMetaData *pluginMetaData, const QString& errorMessage)
0787 {
0788     pluginMetaData->setErrorMessage(errorMessage);
0789 }