tools/designer/src/lib/shared/qsimpleresource.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Designer of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qsimpleresource_p.h"
       
    43 #include "widgetfactory_p.h"
       
    44 #include "widgetdatabase_p.h"
       
    45 
       
    46 #include <formscriptrunner_p.h>
       
    47 #include <properties_p.h>
       
    48 #include <ui4_p.h>
       
    49 
       
    50 #include <QtDesigner/QDesignerFormEditorInterface>
       
    51 #include <QtDesigner/QDesignerLanguageExtension>
       
    52 #include <script_p.h>
       
    53 #include <QtDesigner/QExtensionManager>
       
    54 #include <QtDesigner/QDesignerCustomWidgetInterface>
       
    55 #include <QtDesigner/extrainfo.h>
       
    56 
       
    57 #include <QtGui/QIcon>
       
    58 #include <QtGui/QWidget>
       
    59 #include <QtGui/QAction>
       
    60 #include <QtCore/QDebug>
       
    61 #include <QtCore/QCoreApplication>
       
    62 
       
    63 
       
    64 QT_BEGIN_NAMESPACE
       
    65 
       
    66 namespace {
       
    67     typedef QList<DomWidgetData*> DomWidgetDataList;
       
    68     typedef QList<DomProperty*> DomPropertyList;
       
    69     typedef QList<QDesignerCustomWidgetInterface *> CustomWidgetInterfaces;
       
    70 }
       
    71 
       
    72 namespace qdesigner_internal {
       
    73 
       
    74 bool QSimpleResource::m_warningsEnabled = true;
       
    75 
       
    76 QSimpleResource::QSimpleResource(QDesignerFormEditorInterface *core) :
       
    77     QAbstractFormBuilder(),
       
    78     m_core(core)
       
    79 {
       
    80     QString workingDirectory = QDir::homePath();
       
    81     workingDirectory +=  QDir::separator();
       
    82     workingDirectory +=  QLatin1String(".designer");
       
    83     setWorkingDirectory(QDir(workingDirectory));
       
    84 #ifndef QT_FORMBUILDER_NO_SCRIPT
       
    85     // Disable scripting in the editors.
       
    86     formScriptRunner()-> setOptions(QFormScriptRunner::DisableScripts);
       
    87 #endif
       
    88 }
       
    89 
       
    90 QSimpleResource::~QSimpleResource()
       
    91 {
       
    92 
       
    93 }
       
    94 
       
    95 QBrush QSimpleResource::setupBrush(DomBrush *brush)
       
    96 {
       
    97     return QAbstractFormBuilder::setupBrush(brush);
       
    98 }
       
    99 
       
   100 DomBrush *QSimpleResource::saveBrush(const QBrush &brush)
       
   101 {
       
   102     return QAbstractFormBuilder::saveBrush(brush);
       
   103 }
       
   104 
       
   105 QIcon QSimpleResource::nameToIcon(const QString &filePath, const QString &qrcPath)
       
   106 {
       
   107     Q_UNUSED(filePath)
       
   108     Q_UNUSED(qrcPath)
       
   109     qWarning() << "QSimpleResource::nameToIcon() is obsoleted";
       
   110     return QIcon();
       
   111 }
       
   112 
       
   113 QString QSimpleResource::iconToFilePath(const QIcon &pm) const
       
   114 {
       
   115     Q_UNUSED(pm)
       
   116     qWarning() << "QSimpleResource::iconToFilePath() is obsoleted";
       
   117     return QString();
       
   118 }
       
   119 
       
   120 QString QSimpleResource::iconToQrcPath(const QIcon &pm) const
       
   121 {
       
   122     Q_UNUSED(pm)
       
   123     qWarning() << "QSimpleResource::iconToQrcPath() is obsoleted";
       
   124     return QString();
       
   125 }
       
   126 
       
   127 QPixmap QSimpleResource::nameToPixmap(const QString &filePath, const QString &qrcPath)
       
   128 {
       
   129     Q_UNUSED(filePath)
       
   130     Q_UNUSED(qrcPath)
       
   131     qWarning() << "QSimpleResource::nameToPixmap() is obsoleted";
       
   132     return QPixmap();
       
   133 }
       
   134 
       
   135 QString QSimpleResource::pixmapToFilePath(const QPixmap &pm) const
       
   136 {
       
   137     Q_UNUSED(pm)
       
   138     qWarning() << "QSimpleResource::pixmapToFilePath() is obsoleted";
       
   139     return QString();
       
   140 }
       
   141 
       
   142 QString QSimpleResource::pixmapToQrcPath(const QPixmap &pm) const
       
   143 {
       
   144     Q_UNUSED(pm)
       
   145     qWarning() << "QSimpleResource::pixmapToQrcPath() is obsoleted";
       
   146     return QString();
       
   147 }
       
   148 
       
   149 DomScript *QSimpleResource::createScript(const QString &script, ScriptSource source)
       
   150 {
       
   151     if (script.isEmpty())
       
   152         return 0;
       
   153     DomScript *domScript = new DomScript();
       
   154     switch (source) {
       
   155     case ScriptExtension:
       
   156         domScript->setAttributeSource(QLatin1String("extension"));
       
   157         break;
       
   158     case ScriptDesigner:
       
   159         domScript->setAttributeSource(QLatin1String("designer"));
       
   160         break;
       
   161     case ScriptCustomWidgetPlugin:
       
   162         domScript->setAttributeSource(QLatin1String("customwidgetplugin"));
       
   163         break;
       
   164     }
       
   165     domScript->setAttributeLanguage(QLatin1String("Qt Script"));
       
   166     domScript->setText(script);
       
   167     return domScript;
       
   168 }
       
   169 
       
   170 // Add a script to a list of DomScripts unless empty
       
   171 void QSimpleResource::addScript(const QString &script, ScriptSource source, DomScripts &domScripts)
       
   172 {
       
   173     if (DomScript *domScript = createScript(script, source)) {
       
   174         domScripts += domScript;
       
   175     }
       
   176 }
       
   177 
       
   178 void QSimpleResource::addExtensionDataToDOM(QAbstractFormBuilder *afb,
       
   179                                             QDesignerFormEditorInterface *core,
       
   180                                             DomWidget *ui_widget, QWidget *widget)
       
   181 {
       
   182     QExtensionManager *emgr = core->extensionManager();
       
   183     if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(emgr, widget)) {
       
   184         extra->saveWidgetExtraInfo(ui_widget);
       
   185     }
       
   186     if (QDesignerScriptExtension *scriptExt = qt_extension<QDesignerScriptExtension*>(emgr, widget)) {
       
   187         // Add internal state
       
   188         const QVariantMap data = scriptExt->data();
       
   189         if (!data.empty()) {
       
   190             // Convert the map to a DomState.
       
   191             // We pass on the widget for property introspection. Thus, non-designable properties
       
   192             // that have to be converted using QMetaObject (enums and the like) will work.
       
   193             DomPropertyList properties;
       
   194             const QVariantMap::const_iterator vcend = data.constEnd();
       
   195             for (QVariantMap::const_iterator it = data.constBegin(); it != vcend; ++it) {
       
   196                 if (DomProperty *prop = variantToDomProperty(afb, widget->metaObject(), it.key(), it.value()))
       
   197                     properties += prop;
       
   198             }
       
   199             if (!properties.empty()) {
       
   200                 DomWidgetData *domData = new DomWidgetData;
       
   201                 domData->setElementProperty(properties);
       
   202                 DomWidgetDataList domDataList;
       
   203                  domDataList += domData;
       
   204                 ui_widget->setElementWidgetData(domDataList);
       
   205             }
       
   206 
       
   207         }
       
   208         // Add script
       
   209         const QString script = scriptExt->script();
       
   210         if (!script.isEmpty()) {
       
   211             DomScripts domScripts = ui_widget->elementScript();
       
   212             addScript(script, ScriptExtension, domScripts);
       
   213             ui_widget->setElementScript(domScripts);
       
   214         }
       
   215     }
       
   216 }
       
   217 
       
   218 void QSimpleResource::applyExtensionDataFromDOM(QAbstractFormBuilder *afb,
       
   219                                                 QDesignerFormEditorInterface *core,
       
   220                                                 DomWidget *ui_widget, QWidget *widget, bool applyState)
       
   221 {
       
   222     QExtensionManager *emgr = core->extensionManager();
       
   223     if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(emgr, widget)) {
       
   224         extra->loadWidgetExtraInfo(ui_widget);
       
   225     }
       
   226     if (applyState) {
       
   227         if (QDesignerScriptExtension *scriptExt = qt_extension<QDesignerScriptExtension*>(emgr, widget)) {
       
   228             // Apply the state.
       
   229             // We pass on the widget for property introspection. Thus, non-designable properties
       
   230             // that have to be converted using QMetaObject (enums and the like) will work.
       
   231             QVariantMap data;
       
   232             DomWidgetDataList domDataList = ui_widget->elementWidgetData();
       
   233             if (!domDataList.empty()) {
       
   234                 foreach (const DomWidgetData *domData, domDataList) {
       
   235                     const DomPropertyList properties = domData->elementProperty();
       
   236                     foreach(const DomProperty *prop, properties) {
       
   237                         const QVariant vprop = domPropertyToVariant(afb, widget->metaObject(), prop);
       
   238                         if (vprop.type() != QVariant::Invalid)
       
   239                             data.insert(prop->attributeName(), vprop);
       
   240                     }
       
   241                 }
       
   242             }
       
   243             scriptExt->setData(data);
       
   244         }
       
   245     }
       
   246 }
       
   247 
       
   248 QString QSimpleResource::customWidgetScript(QDesignerFormEditorInterface *core, QObject *object)
       
   249 {
       
   250     return customWidgetScript(core, qdesigner_internal::WidgetFactory::classNameOf(core, object));
       
   251 }
       
   252 
       
   253 bool QSimpleResource::hasCustomWidgetScript(QDesignerFormEditorInterface *, QObject *)
       
   254 {
       
   255     return false;
       
   256 }
       
   257 
       
   258 QString QSimpleResource::customWidgetScript(QDesignerFormEditorInterface *, const QString &)
       
   259 {
       
   260     return QString();
       
   261 }
       
   262 
       
   263 bool QSimpleResource::setWarningsEnabled(bool warningsEnabled)
       
   264 {
       
   265     const bool rc = m_warningsEnabled;
       
   266     m_warningsEnabled = warningsEnabled;
       
   267     return rc;
       
   268 }
       
   269 
       
   270 bool QSimpleResource::warningsEnabled()
       
   271 {
       
   272     return m_warningsEnabled;
       
   273 }
       
   274 
       
   275 // Custom widgets handling helpers
       
   276 
       
   277 // Add unique fake slots and signals to lists
       
   278 bool QSimpleResource::addFakeMethods(const DomSlots *domSlots, QStringList &fakeSlots, QStringList &fakeSignals)
       
   279 {
       
   280     if (!domSlots)
       
   281         return false;
       
   282 
       
   283     bool rc = false;
       
   284     foreach (const QString &fakeSlot, domSlots->elementSlot())
       
   285         if (fakeSlots.indexOf(fakeSlot) == -1) {
       
   286             fakeSlots += fakeSlot;
       
   287             rc = true;
       
   288         }
       
   289 
       
   290     foreach (const QString &fakeSignal, domSlots->elementSignal())
       
   291         if (fakeSignals.indexOf(fakeSignal) == -1) {
       
   292             fakeSignals += fakeSignal;
       
   293             rc = true;
       
   294         }
       
   295     return rc;
       
   296 }
       
   297 
       
   298 void QSimpleResource::addFakeMethodsToWidgetDataBase(const DomCustomWidget *domCustomWidget, WidgetDataBaseItem *item)
       
   299 {
       
   300     const DomSlots *domSlots = domCustomWidget->elementSlots();
       
   301     if (!domSlots)
       
   302         return;
       
   303 
       
   304     // Merge in new slots, signals
       
   305     QStringList fakeSlots = item->fakeSlots();
       
   306     QStringList fakeSignals = item->fakeSignals();
       
   307     if (addFakeMethods(domSlots, fakeSlots, fakeSignals)) {
       
   308         item->setFakeSlots(fakeSlots);
       
   309         item->setFakeSignals(fakeSignals);
       
   310     }
       
   311 }
       
   312 
       
   313 // Perform one iteration of adding the custom widgets to the database,
       
   314 // looking up the base class and inheriting its data.
       
   315 // Remove the succeeded custom widgets from the list.
       
   316 // Classes whose base class could not be found are left in the list.
       
   317 
       
   318 void QSimpleResource::addCustomWidgetsToWidgetDatabase(const QDesignerFormEditorInterface *core,
       
   319                                                        QList<DomCustomWidget*>& custom_widget_list)
       
   320 {
       
   321     QDesignerWidgetDataBaseInterface *db = core->widgetDataBase();
       
   322     for (int i=0; i < custom_widget_list.size(); ) {
       
   323         bool classInserted = false;
       
   324         DomCustomWidget *custom_widget = custom_widget_list[i];
       
   325         const QString customClassName = custom_widget->elementClass();
       
   326         const QString base_class = custom_widget->elementExtends();
       
   327         QString includeFile;
       
   328         IncludeType includeType = IncludeLocal;
       
   329         if (const DomHeader *header = custom_widget->elementHeader()) {
       
   330             includeFile = header->text();
       
   331             if (header->hasAttributeLocation() && header->attributeLocation() == QLatin1String("global"))
       
   332                 includeType = IncludeGlobal;
       
   333         }
       
   334         const bool domIsContainer = custom_widget->elementContainer();
       
   335         // Append a new item
       
   336         if (base_class.isEmpty()) {
       
   337             WidgetDataBaseItem *item = new WidgetDataBaseItem(customClassName);
       
   338             item->setPromoted(false);
       
   339             item->setGroup(QCoreApplication::translate("Designer", "Custom Widgets"));
       
   340             item->setIncludeFile(buildIncludeFile(includeFile, includeType));
       
   341             item->setContainer(domIsContainer);
       
   342             item->setCustom(true);
       
   343             addFakeMethodsToWidgetDataBase(custom_widget, item);
       
   344             db->append(item);
       
   345             custom_widget_list.removeAt(i);
       
   346             classInserted = true;
       
   347         } else {
       
   348             // Create a new entry cloned from base class. Note that this will ignore existing
       
   349             // classes, eg, plugin custom widgets.
       
   350             QDesignerWidgetDataBaseItemInterface *item =
       
   351                 appendDerived(db, customClassName, QCoreApplication::translate("Designer", "Promoted Widgets"),
       
   352                               base_class,
       
   353                               buildIncludeFile(includeFile, includeType),
       
   354                               true,true);
       
   355             // Ok, base class found.
       
   356             if (item) {
       
   357                 // Hack to accommodate for old UI-files in which "container" is not set properly:
       
   358                 // Apply "container" from DOM only if true (else, eg classes from QFrame might not accept
       
   359                 // dropping child widgets on them as container=false). This also allows for
       
   360                 // QWidget-derived stacked pages.
       
   361                 if (domIsContainer)
       
   362                     item->setContainer(domIsContainer);
       
   363 
       
   364                 addFakeMethodsToWidgetDataBase(custom_widget, static_cast<WidgetDataBaseItem*>(item));
       
   365                 custom_widget_list.removeAt(i);
       
   366                 classInserted = true;
       
   367             }
       
   368         }
       
   369         // Skip failed item.
       
   370         if (!classInserted)
       
   371             i++;
       
   372     }
       
   373 
       
   374 }
       
   375 
       
   376 void QSimpleResource::handleDomCustomWidgets(const QDesignerFormEditorInterface *core,
       
   377                                              const DomCustomWidgets *dom_custom_widgets)
       
   378 {
       
   379     if (dom_custom_widgets == 0)
       
   380         return;
       
   381     QList<DomCustomWidget*> custom_widget_list = dom_custom_widgets->elementCustomWidget();
       
   382     // Attempt to insert each item derived from its base class.
       
   383     // This should at most require two iterations in the event that the classes are out of order
       
   384     // (derived first, max depth: promoted custom plugin = 2)
       
   385     for (int iteration = 0;  iteration < 2;  iteration++) {
       
   386         addCustomWidgetsToWidgetDatabase(core, custom_widget_list);
       
   387         if (custom_widget_list.empty())
       
   388             return;
       
   389     }
       
   390     // Oops, there are classes left whose base class could not be found.
       
   391     // Default them to QWidget with warnings.
       
   392     const QString fallBackBaseClass = QLatin1String("QWidget");
       
   393     for (int i=0; i < custom_widget_list.size(); i++ ) {
       
   394         DomCustomWidget *custom_widget = custom_widget_list[i];
       
   395         const QString customClassName = custom_widget->elementClass();
       
   396         const QString base_class = custom_widget->elementExtends();
       
   397         qDebug() << "** WARNING The base class " << base_class << " of the custom widget class " << customClassName
       
   398             << " could not be found. Defaulting to " << fallBackBaseClass << '.';
       
   399         custom_widget->setElementExtends(fallBackBaseClass);
       
   400     }
       
   401     // One more pass.
       
   402     addCustomWidgetsToWidgetDatabase(core, custom_widget_list);
       
   403 }
       
   404 
       
   405 // ------------ FormBuilderClipboard
       
   406 
       
   407 FormBuilderClipboard::FormBuilderClipboard(QWidget *w)
       
   408 {
       
   409     m_widgets += w;
       
   410 }
       
   411 
       
   412 bool FormBuilderClipboard::empty() const
       
   413 {
       
   414     return m_widgets.empty() && m_actions.empty();
       
   415 }
       
   416 }
       
   417 
       
   418 QT_END_NAMESPACE