File indexing completed on 2024-05-12 16:39:52

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(ERR_CANNOT_LOAD_OBJECT,
0252                                     xi18nc("@info", "Could not load Kexi Form Widgets plugin file <filename>%1</filename>.",
0253                                            pluginMetaData->fileName()));
0254             q->setErrorMessage(pluginMetaData, q->result().message());
0255             qWarning() << q->result().message();
0256             return 0;
0257         }
0258         WidgetFactory *widgetFactory = factory->create<WidgetFactory>(q);
0259         if (!widgetFactory) {
0260             q->m_result = KDbResult(ERR_CANNOT_LOAD_OBJECT,
0261                                     xi18nc("@info",
0262                                            "Could not open Kexi Form Widgets plugin <filename>%1</filename>.",
0263                                            pluginMetaData->fileName()));
0264             qWarning() << q->m_result.message();
0265             return 0;
0266         }
0267         widgetFactory->setLibrary(q);
0268         widgetFactory->setObjectName(pluginMetaData->id());
0269         widgetFactory->setAdvancedPropertiesVisible(showAdvancedProperties); //inherit this flag from the library
0270         m_factories.insert(pluginMetaData->id().toLatin1(), widgetFactory);
0271         return widgetFactory;
0272     }
0273 
0274     //! Loads widgets for factory @a f
0275     void loadFactoryWidgets(WidgetFactory *f) {
0276         QHash<QByteArray, WidgetInfo*> widgetsForFactory(f->classes());
0277         foreach (WidgetInfo *w, widgetsForFactory) {
0278             if (m_hiddenClasses.contains( w->className() ))
0279                 continue; //this class is hidden
0280             // check if we want to inherit a widget from a different factory
0281             if (!w->parentFactoryName().isEmpty() && !w->inheritedClassName().isEmpty()) {
0282                 WidgetFactory *parentFactory = m_factories.value(w->parentFactoryName().toLower());
0283                 if (!parentFactory) {
0284                     qWarning() << "class" << w->className() << ": no such parent factory" << w->parentFactoryName();
0285                     continue;
0286                 }
0287                 WidgetInfo* inheritedClass = parentFactory->widgetInfoForClassName(w->inheritedClassName());
0288                 if (!inheritedClass) {
0289                     qWarning() << "class" << w->inheritedClassName() << " - no such class to inherit in factory"
0290                         << w->parentFactoryName();
0291                     continue;
0292                 }
0293                 //ok: inherit properties:
0294                 w->setInheritedClass( inheritedClass );
0295                 if (w->iconName().isEmpty())
0296                     w->setIconName(inheritedClass->iconName());
0297                 //ok?
0298                 foreach(const QByteArray& alternateName, inheritedClass->alternateClassNames()) {
0299                     w->addAlternateClassName(
0300                         alternateName, inheritedClass->isOverriddenClassName(alternateName));
0301                 }
0302                 if (w->includeFileName().isEmpty())
0303                     w->setIncludeFileName(inheritedClass->includeFileName());
0304                 if (w->name().isEmpty())
0305                     w->setName(inheritedClass->name());
0306                 if (w->namePrefix().isEmpty())
0307                     w->setNamePrefix(nullptr, qPrintable(inheritedClass->namePrefix()));
0308                 if (w->description().isEmpty())
0309                     w->setDescription(inheritedClass->description());
0310             }
0311 
0312             QList<QByteArray> cnames( w->alternateClassNames() );
0313             cnames.prepend(w->className());
0314             foreach (const QByteArray &wname, cnames) {
0315                 WidgetInfo *widgetForClass = widgetsForFactory.value(wname);
0316                 if (!widgetForClass || (widgetForClass && !widgetForClass->isOverriddenClassName(wname))) {
0317                     //insert a widgetinfo, if:
0318                     //1) this class has no alternate class assigned yet, or
0319                     //2) this class has alternate class assigned but without 'override' flag
0320                     m_widgets.insert(wname, w);
0321                 }
0322             }
0323         }
0324     }
0325 
0326     WidgetLibrary *q;
0327     KexiGUIMessageHandler messageHandler;
0328     //! A map which associates a class name with a Widget class
0329     QHash<QString, KexiFormWidgetsPluginMetaData*> m_pluginsMetaData; //!< owner
0330     bool m_couldNotFindAnyFormWidgetPluginsErrorDisplayed;
0331     QSet<QString> m_supportedFactoryGroups;
0332     QHash<QByteArray, WidgetFactory*> m_factories; //!< owner
0333     QHash<QByteArray, WidgetInfo*> m_widgets; //!< owner
0334     QSet<QByteArray> m_advancedProperties;
0335     QSet<QByteArray> m_hiddenClasses;
0336     bool m_lookupDone;
0337     bool m_lookupResult;
0338     bool m_loadFactoriesDone;
0339     bool m_loadFactoriesResult;
0340 };
0341 }
0342 
0343 using namespace KFormDesigner;
0344 
0345 //-------------------------------------------
0346 
0347 WidgetLibrary::WidgetLibrary(QObject *parent, const QStringList& supportedFactoryGroups)
0348         : QObject(parent)
0349         , KDbResultable()
0350         , d(new Private(this, supportedFactoryGroups))
0351 {
0352 }
0353 
0354 WidgetLibrary::~WidgetLibrary()
0355 {
0356     delete d;
0357 }
0358 
0359 void WidgetLibrary::createWidgetActions(ActionGroup *group)
0360 {
0361     foreach (WidgetInfo *winfo, d->widgets()) {
0362         LibActionWidget *a = new LibActionWidget(group, winfo);
0363         connect(a, SIGNAL(toggled(QByteArray)), this, SIGNAL(widgetActionToggled(QByteArray)));
0364     }
0365 }
0366 
0367 void
0368 WidgetLibrary::addCustomWidgetActions(KActionCollection *col)
0369 {
0370     if (!col)
0371         return;
0372     foreach (WidgetFactory *factory, d->factories()) {
0373         factory->createCustomActions(col);
0374     }
0375 }
0376 
0377 QWidget* WidgetLibrary::createWidget(const QByteArray &classname, QWidget *parent,
0378                                      const char *name, Container *c,
0379                                      WidgetFactory::CreateWidgetOptions options)
0380 {
0381     WidgetInfo *wclass = d->widgets().value(classname);
0382     if (!wclass)
0383         return 0;
0384 
0385     QWidget *widget = wclass->factory()->createWidget(wclass->className(), parent, name, c, options);
0386     if (!widget) {
0387         //try to instantiate from inherited class
0388         if (wclass->inheritedClass())
0389             widget = wclass->inheritedClass()->factory()->createWidget(
0390                          wclass->className(), parent, name, c, options);
0391         if (!widget)
0392             return 0;
0393     }
0394     widget->setAcceptDrops(true);
0395     if (options & WidgetFactory::DesignViewMode) {
0396         FormWidgetInterface* fwiface = dynamic_cast<FormWidgetInterface*>(widget);
0397         if (fwiface)
0398             fwiface->setDesignMode(true);
0399     }
0400     emit widgetCreated(widget);
0401     return widget;
0402 }
0403 
0404 bool WidgetLibrary::createMenuActions(const QByteArray &c, QWidget *w, QMenu *menu,
0405                                       KFormDesigner::Container *container)
0406 {
0407     WidgetInfo *wclass = d->widgets().value(c);
0408     if (!wclass)
0409         return false;
0410 
0411     if (wclass->factory()->createMenuActions(c, w, menu, container)) {
0412         return true;
0413     }
0414     //try from inherited class
0415     if (wclass->inheritedClass()) {
0416         return wclass->inheritedClass()->factory()->createMenuActions(
0417                    wclass->className(), w, menu, container);
0418     }
0419     return false;
0420 }
0421 
0422 bool WidgetLibrary::startInlineEditing(const QByteArray &classname, QWidget *w,
0423                                        Container *container)
0424 {
0425     WidgetInfo *wclass = d->widgets().value(classname);
0426     if (!wclass)
0427         return false;
0428 
0429     FormWidgetInterface* fwiface = dynamic_cast<FormWidgetInterface*>(w);
0430     {
0431         KFormDesigner::WidgetFactory::InlineEditorCreationArguments args(classname, w, container);
0432         if (wclass->factory()->startInlineEditing(args)) {
0433             args.container->form()->createInlineEditor(args);
0434             if (fwiface)
0435                 fwiface->setEditingMode(true);
0436             return true;
0437         }
0438     }
0439     if (wclass->inheritedClass()) {
0440         //try from inherited class
0441         KFormDesigner::WidgetFactory::InlineEditorCreationArguments args(wclass->className(), w, container);
0442         if (wclass->inheritedClass()->factory()->startInlineEditing(args)) {
0443             args.container->form()->createInlineEditor(args);
0444             if (fwiface)
0445                 fwiface->setEditingMode(true);
0446             return true;
0447         }
0448     }
0449     return false;
0450 }
0451 
0452 bool WidgetLibrary::previewWidget(const QByteArray &classname, QWidget *widget, Container *container)
0453 {
0454     WidgetInfo *wclass = d->widgets().value(classname);
0455     if (!wclass)
0456         return false;
0457 
0458     FormWidgetInterface* fwiface = dynamic_cast<FormWidgetInterface*>(widget);
0459     if (fwiface)
0460         fwiface->setDesignMode(false);
0461     if (wclass->factory()->previewWidget(classname, widget, container))
0462         return true;
0463     //try from inherited class
0464     if (wclass->inheritedClass())
0465         return wclass->inheritedClass()->factory()->previewWidget(wclass->className(), widget, container);
0466     return false;
0467 }
0468 
0469 bool WidgetLibrary::clearWidgetContent(const QByteArray &classname, QWidget *w)
0470 {
0471     WidgetInfo *wclass = d->widgets().value(classname);
0472     if (!wclass)
0473         return false;
0474 
0475     if (wclass->factory()->clearWidgetContent(classname, w))
0476         return true;
0477     //try from inherited class
0478     if (wclass->inheritedClass())
0479         return wclass->inheritedClass()->factory()->clearWidgetContent(wclass->className(), w);
0480     return false;
0481 }
0482 
0483 QString WidgetLibrary::displayName(const QByteArray &classname)
0484 {
0485     WidgetInfo *wi = d->widgets().value(classname);
0486     if (wi)
0487         return wi->name();
0488 
0489     return classname;
0490 }
0491 
0492 QString WidgetLibrary::savingName(const QByteArray &classname)
0493 {
0494     WidgetInfo *wi = d->widgets().value(classname);
0495     if (wi && !wi->savingName().isEmpty())
0496         return wi->savingName();
0497 
0498     return classname;
0499 }
0500 
0501 QString WidgetLibrary::namePrefix(const QByteArray &classname)
0502 {
0503     WidgetInfo *wi = d->widgets().value(classname);
0504     if (wi)
0505         return wi->namePrefix();
0506 
0507     return classname;
0508 }
0509 
0510 QString WidgetLibrary::textForWidgetName(const QByteArray &name, const QByteArray &className)
0511 {
0512     WidgetInfo *widget = d->widgets().value(className);
0513     if (!widget)
0514         return QString();
0515 
0516     QString newName = name;
0517     newName.remove(widget->namePrefix());
0518     newName = widget->name() + (newName.isEmpty() ? QString() : (QLatin1String(" ") + newName));
0519     return newName;
0520 }
0521 
0522 QByteArray
0523 WidgetLibrary::classNameForAlternate(const QByteArray &classname)
0524 {
0525     if (d->widgets().value(classname))
0526         return classname;
0527 
0528     WidgetInfo *wi =  d->widgets().value(classname);
0529     if (wi) {
0530         return wi->className();
0531     }
0532 
0533     // widget not supported
0534     return "CustomWidget";
0535 }
0536 
0537 QString WidgetLibrary::includeFileName(const QByteArray &classname)
0538 {
0539     WidgetInfo *wi = d->widgets().value(classname);
0540     if (wi)
0541         return wi->includeFileName();
0542 
0543     return QString();
0544 }
0545 
0546 QString
0547 WidgetLibrary::iconName(const QByteArray &classname)
0548 {
0549     WidgetInfo *wi = d->widgets().value(classname);
0550     if (wi)
0551         return wi->iconName();
0552 
0553     return KexiIconName("unknown-widget");
0554 }
0555 
0556 bool
0557 WidgetLibrary::saveSpecialProperty(const QByteArray &classname,
0558     const QString &name, const QVariant &value, QWidget *w,
0559     QDomElement &parentNode, QDomDocument &parent)
0560 {
0561     WidgetInfo *wi = d->widgets().value(classname);
0562     if (!wi)
0563         return false;
0564 
0565     if (wi->factory()->saveSpecialProperty(classname, name, value, w, parentNode, parent))
0566         return true;
0567     //try from inherited class
0568     if (wi->inheritedClass())
0569         return wi->inheritedClass()->factory()->saveSpecialProperty(wi->className(), name, value, w, parentNode, parent);
0570     return false;
0571 }
0572 
0573 bool
0574 WidgetLibrary::readSpecialProperty(const QByteArray &classname,
0575     QDomElement &node, QWidget *w, ObjectTreeItem *item)
0576 {
0577     WidgetInfo *wi = d->widgets().value(classname);
0578     if (!wi)
0579         return false;
0580     if (wi->factory()->readSpecialProperty(classname, node, w, item))
0581         return true;
0582     //try from inherited class
0583     if (wi->inheritedClass())
0584         return wi->inheritedClass()->factory()->readSpecialProperty(wi->className(), node, w, item);
0585     return false;
0586 }
0587 
0588 void WidgetLibrary::setAdvancedPropertiesVisible(bool set)
0589 {
0590     d->showAdvancedProperties = set;
0591 }
0592 
0593 bool WidgetLibrary::advancedPropertiesVisible() const
0594 {
0595     return d->showAdvancedProperties;
0596 }
0597 
0598 bool
0599 WidgetLibrary::isPropertyVisible(const QByteArray &classname, QWidget *w,
0600                                  const QByteArray &property, bool multiple, bool isTopLevel)
0601 {
0602     if (isTopLevel) {
0603         // no focus policy for top-level form widget...
0604         if (!d->showAdvancedProperties && property == "focusPolicy")
0605             return false;
0606     }
0607 
0608     WidgetInfo *wi = d->widgets().value(classname);
0609     if (!wi)
0610         return false;
0611     if (!d->showAdvancedProperties && d->isAdvancedProperty(property)) {
0612         //this is advanced property, should we hide it?
0613         if (!wi->internalProperty("forceShowAdvancedProperty:" + property).toBool()
0614                 && (!wi->inheritedClass() || !wi->inheritedClass()->internalProperty("forceShowAdvancedProperty:" + property).toBool())) {
0615             return false; //hide it
0616         }
0617     }
0618 
0619     if (!wi->factory()->isPropertyVisible(classname, w, property, multiple, isTopLevel))
0620         return false;
0621     //try from inherited class
0622     if (wi->inheritedClass()
0623             && !wi->inheritedClass()->factory()->isPropertyVisible(wi->className(), w, property, multiple, isTopLevel))
0624         return false;
0625 
0626     return true;
0627 }
0628 
0629 QList<QByteArray> WidgetLibrary::autoSaveProperties(const QByteArray &classname)
0630 {
0631     WidgetInfo *wi = d->widgets().value(classname);
0632     if (!wi)
0633         return QList<QByteArray>();
0634     return wi->autoSaveProperties();
0635 }
0636 
0637 WidgetInfo*
0638 WidgetLibrary::widgetInfoForClassName(const char* classname)
0639 {
0640     return d->widgets().value(classname);
0641 }
0642 
0643 WidgetFactory*
0644 WidgetLibrary::factoryForClassName(const char* classname)
0645 {
0646     WidgetInfo *wi = widgetInfoForClassName(classname);
0647     return wi ? wi->factory() : 0;
0648 }
0649 
0650 QString WidgetLibrary::propertyDescForName(WidgetInfo *winfo, const QByteArray& propertyName)
0651 {
0652     if (!winfo || !winfo->factory())
0653         return QString();
0654     QString desc(winfo->factory()->propertyDescription(propertyName));
0655     if (!desc.isEmpty())
0656         return desc;
0657     if (winfo->parentFactoryName().isEmpty())
0658         return QString();
0659 
0660     //try in parent factory, if exists
0661     WidgetFactory *parentFactory = d->factories().value(winfo->parentFactoryName());
0662     if (!parentFactory)
0663         return QString();
0664 
0665     return parentFactory->propertyDescription(propertyName);
0666 }
0667 
0668 QString WidgetLibrary::propertyDescForValue(WidgetInfo *winfo, const QByteArray& name)
0669 {
0670     if (!winfo->factory())
0671         return QString();
0672     QString desc(winfo->factory()->valueDescription(name));
0673     if (!desc.isEmpty())
0674         return desc;
0675     if (winfo->parentFactoryName().isEmpty())
0676         return QString();
0677 
0678     //try in parent factory, if exists
0679     WidgetFactory *parentFactory = d->factories().value(winfo->parentFactoryName());
0680     if (!parentFactory)
0681         return QString();
0682 
0683     return parentFactory->valueDescription(name);
0684 }
0685 
0686 void WidgetLibrary::setPropertyOptions(KPropertySet& set, const WidgetInfo& winfo, QWidget* w)
0687 {
0688     if (!winfo.factory())
0689         return;
0690     winfo.factory()->setPropertyOptions(set, winfo, w);
0691     if (winfo.parentFactoryName().isEmpty())
0692         return;
0693     WidgetFactory *parentFactory = d->factories().value(winfo.parentFactoryName());
0694     if (!parentFactory)
0695         return;
0696     parentFactory->setPropertyOptions(set, winfo, w);
0697 }
0698 
0699 WidgetFactory* WidgetLibrary::factory(const char* factoryName) const
0700 {
0701     return d->factories().value(factoryName);
0702 }
0703 
0704 QVariant WidgetLibrary::internalProperty(const QByteArray& classname, const QByteArray& property)
0705 {
0706     WidgetInfo *wclass = d->widgets().value(classname);
0707     if (!wclass)
0708         return QString();
0709     QVariant value(wclass->internalProperty(property));
0710     if (value.isNull() && wclass->inheritedClass())
0711         return wclass->inheritedClass()->internalProperty(property);
0712     return value;
0713 }
0714 
0715 WidgetFactory::CreateWidgetOption WidgetLibrary::showOrientationSelectionPopup(
0716     const QByteArray &classname, QWidget* parent, const QPoint& pos)
0717 {
0718     WidgetInfo *wclass = d->widgets().value(classname);
0719     if (!wclass)
0720         return WidgetFactory::AnyOrientation;
0721 
0722     //get custom icons and strings
0723     QIcon iconHorizontal, iconVertical;
0724     QString iconName(wclass->internalProperty("orientationSelectionPopup:horizontalIcon").toString());
0725     if (iconName.isEmpty() && wclass->inheritedClass())
0726         iconName = wclass->inheritedClass()->internalProperty("orientationSelectionPopup:horizontalIcon").toString();
0727     if (!iconName.isEmpty())
0728         iconHorizontal = QIcon::fromTheme(iconName);
0729 
0730     iconName = wclass->internalProperty("orientationSelectionPopup:verticalIcon").toString();
0731     if (iconName.isEmpty() && wclass->inheritedClass())
0732         iconName = wclass->inheritedClass()->internalProperty("orientationSelectionPopup:verticalIcon").toString();
0733     if (!iconName.isEmpty())
0734         iconVertical = QIcon::fromTheme(iconName);
0735 
0736     QString textHorizontal = wclass->internalProperty("orientationSelectionPopup:horizontalText").toString();
0737     if (textHorizontal.isEmpty() && wclass->inheritedClass())
0738         iconName = wclass->inheritedClass()->internalProperty("orientationSelectionPopup:horizontalText").toString();
0739     if (textHorizontal.isEmpty()) //default
0740         textHorizontal = xi18nc("Insert Horizontal Widget", "Insert Horizontal");
0741 
0742     QString textVertical = wclass->internalProperty("orientationSelectionPopup:verticalText").toString();
0743     if (textVertical.isEmpty() && wclass->inheritedClass())
0744         iconName = wclass->inheritedClass()->internalProperty("orientationSelectionPopup:verticalText").toString();
0745     if (textVertical.isEmpty()) //default
0746         textVertical = xi18nc("Insert Vertical Widget", "Insert Vertical");
0747 
0748     QMenu popup(parent);
0749     popup.setObjectName("orientationSelectionPopup");
0750     popup.addSection(QIcon::fromTheme(wclass->iconName()), xi18n("Insert Widget: %1", wclass->name()));
0751     QAction* horizAction = popup.addAction(iconHorizontal, textHorizontal);
0752     QAction* vertAction = popup.addAction(iconVertical, textVertical);
0753     popup.addSeparator();
0754     popup.addAction(koIcon("dialog-cancel"), xi18n("Cancel"));
0755     QAction *a = popup.exec(pos);
0756     if (a == horizAction)
0757         return WidgetFactory::HorizontalOrientation;
0758     else if (a == vertAction)
0759         return WidgetFactory::VerticalOrientation;
0760 
0761     return WidgetFactory::AnyOrientation; //means "cancelled"
0762 }
0763 
0764 bool WidgetLibrary::propertySetShouldBeReloadedAfterPropertyChange(
0765     const QByteArray& classname, QWidget *w, const QByteArray& property)
0766 {
0767     WidgetInfo *winfo = widgetInfoForClassName(classname);
0768     if (!winfo)
0769         return false;
0770     return winfo->factory()->propertySetShouldBeReloadedAfterPropertyChange(classname, w, property);
0771 }
0772 
0773 ObjectTreeItem* WidgetLibrary::selectableItem(ObjectTreeItem* item)
0774 {
0775     //qDebug() << item->widget()->metaObject()->className();
0776     WidgetInfo *wi = d->widgets().value(item->widget()->metaObject()->className());
0777     if (!wi)
0778         return item;
0779     return wi->factory()->selectableItem(item);
0780 }
0781 
0782 
0783 void WidgetLibrary::setErrorMessage(KexiFormWidgetsPluginMetaData *pluginMetaData, const QString& errorMessage)
0784 {
0785     pluginMetaData->setErrorMessage(errorMessage);
0786 }