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 }