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 }