Plasma
declarativewidget.cpp
Go to the documentation of this file.
00001 /* 00002 * Copyright 2010 Marco Martin <mart@kde.org> 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU Library General Public License as 00006 * published by the Free Software Foundation; either version 2, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details 00013 * 00014 * You should have received a copy of the GNU Library General Public 00015 * License along with this program; if not, write to the 00016 * Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "declarativewidget.h" 00021 00022 00023 #include <QtDeclarative/QDeclarativeComponent> 00024 #include <QtDeclarative/QDeclarativeItem> 00025 #include <QtDeclarative/QDeclarativeEngine> 00026 #include <QtDeclarative/QDeclarativeContext> 00027 #include <QScriptEngine> 00028 #include <QGraphicsLinearLayout> 00029 #include <QGraphicsScene> 00030 #include <QTimer> 00031 00032 #include <kdebug.h> 00033 #include <kdeclarative.h> 00034 #include <kglobal.h> 00035 #include <kstandarddirs.h> 00036 00037 #include "private/declarative/declarativenetworkaccessmanagerfactory_p.h" 00038 #include "private/dataenginebindings_p.h" 00039 00040 namespace Plasma 00041 { 00042 00043 class DeclarativeWidgetPrivate 00044 { 00045 public: 00046 DeclarativeWidgetPrivate(DeclarativeWidget *parent) 00047 : q(parent), 00048 engine(0), 00049 component(0), 00050 root(0), 00051 delay(false) 00052 { 00053 } 00054 00055 ~DeclarativeWidgetPrivate() 00056 { 00057 } 00058 00059 void errorPrint(); 00060 void execute(const QString &fileName); 00061 void finishExecute(); 00062 void scheduleExecutionEnd(); 00063 void minimumWidthChanged(); 00064 void minimumHeightChanged(); 00065 00066 00067 DeclarativeWidget *q; 00068 00069 QString qmlPath; 00070 QDeclarativeEngine* engine; 00071 QScriptEngine *scriptEngine; 00072 QDeclarativeComponent* component; 00073 QObject *root; 00074 bool delay : 1; 00075 }; 00076 00077 void DeclarativeWidgetPrivate::errorPrint() 00078 { 00079 QString errorStr = "Error loading QML file.\n"; 00080 if(component->isError()){ 00081 QList<QDeclarativeError> errors = component->errors(); 00082 foreach (const QDeclarativeError &error, errors) { 00083 errorStr += (error.line()>0?QString(QString::number(error.line()) + QLatin1String(": ")):QLatin1String("")) 00084 + error.description() + '\n'; 00085 } 00086 } 00087 kWarning() << component->url().toString() + '\n' + errorStr; 00088 } 00089 00090 void DeclarativeWidgetPrivate::execute(const QString &fileName) 00091 { 00092 if (fileName.isEmpty()) { 00093 kDebug() << "File name empty!"; 00094 return; 00095 } 00096 00097 component->loadUrl(fileName); 00098 00099 KDeclarative kdeclarative; 00100 kdeclarative.setDeclarativeEngine(engine); 00101 kdeclarative.initialize(); 00102 //binds things like kconfig and icons 00103 kdeclarative.setupBindings(); 00104 scriptEngine = kdeclarative.scriptEngine(); 00105 registerDataEngineMetaTypes(scriptEngine); 00106 00107 if (delay) { 00108 QTimer::singleShot(0, q, SLOT(scheduleExecutionEnd())); 00109 } else { 00110 scheduleExecutionEnd(); 00111 } 00112 } 00113 00114 void DeclarativeWidgetPrivate::scheduleExecutionEnd() 00115 { 00116 if (component->isReady() || component->isError()) { 00117 finishExecute(); 00118 } else { 00119 QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), q, SLOT(finishExecute())); 00120 } 00121 } 00122 00123 void DeclarativeWidgetPrivate::finishExecute() 00124 { 00125 if (component->isError()) { 00126 errorPrint(); 00127 } 00128 00129 root = component->create(); 00130 00131 if (!root) { 00132 errorPrint(); 00133 } 00134 00135 kDebug() << "Execution of QML done!"; 00136 QGraphicsWidget *widget = dynamic_cast<QGraphicsWidget*>(root); 00137 QGraphicsObject *object = dynamic_cast<QGraphicsObject *>(root); 00138 00139 00140 if (object) { 00141 static_cast<QGraphicsItem *>(object)->setParentItem(q); 00142 if (q->scene()) { 00143 q->scene()->addItem(object); 00144 } 00145 } 00146 00147 if (widget) { 00148 q->setPreferredSize(-1,-1); 00149 QGraphicsLinearLayout *lay = static_cast<QGraphicsLinearLayout *>(q->layout()); 00150 if (!lay) { 00151 lay = new QGraphicsLinearLayout(q); 00152 lay->setContentsMargins(0, 0, 0, 0); 00153 } 00154 lay->addItem(widget); 00155 } else { 00156 q->setLayout(0); 00157 qreal minimumWidth = 0; 00158 qreal minimumHeight = 0; 00159 if (object) { 00160 minimumWidth = object->property("minimumWidth").toReal(); 00161 minimumHeight = object->property("minimumHeight").toReal(); 00162 object->setProperty("width", q->size().width()); 00163 object->setProperty("height", q->size().height()); 00164 QObject::connect(object, SIGNAL(minimumWidthChanged()), q, SLOT(minimumWidthChanged())); 00165 QObject::connect(object, SIGNAL(minimumHeightChanged()), q, SLOT(minimumHeightChanged())); 00166 } 00167 00168 if (minimumWidth > 0 && minimumHeight > 0) { 00169 q->setMinimumSize(minimumWidth, minimumHeight); 00170 } else { 00171 q->setMinimumSize(-1, -1); 00172 } 00173 } 00174 emit q->finished(); 00175 } 00176 00177 void DeclarativeWidgetPrivate::minimumWidthChanged() 00178 { 00179 qreal minimumWidth = root->property("minimumWidth").toReal(); 00180 q->setMinimumWidth(minimumWidth); 00181 } 00182 00183 void DeclarativeWidgetPrivate::minimumHeightChanged() 00184 { 00185 qreal minimumHeight = root->property("minimumHeight").toReal(); 00186 q->setMinimumHeight(minimumHeight); 00187 } 00188 00189 DeclarativeWidget::DeclarativeWidget(QGraphicsWidget *parent) 00190 : QGraphicsWidget(parent), 00191 d(new DeclarativeWidgetPrivate(this)) 00192 { 00193 setFlag(QGraphicsItem::ItemHasNoContents); 00194 00195 d->engine = new QDeclarativeEngine(this); 00196 d->engine->setNetworkAccessManagerFactory(new DeclarativeNetworkAccessManagerFactory); 00197 foreach(const QString &importPath, KGlobal::dirs()->findDirs("module", "imports")) { 00198 d->engine->addImportPath(importPath); 00199 } 00200 00201 d->component = new QDeclarativeComponent(d->engine, this); 00202 } 00203 00204 DeclarativeWidget::~DeclarativeWidget() 00205 { 00206 QDeclarativeNetworkAccessManagerFactory *factory = d->engine->networkAccessManagerFactory(); 00207 d->engine->setNetworkAccessManagerFactory(0); 00208 delete factory; 00209 delete d; 00210 } 00211 00212 void DeclarativeWidget::setQmlPath(const QString &path) 00213 { 00214 d->qmlPath = path; 00215 d->execute(path); 00216 } 00217 00218 QString DeclarativeWidget::qmlPath() const 00219 { 00220 return d->qmlPath; 00221 } 00222 00223 void DeclarativeWidget::setInitializationDelayed(const bool delay) 00224 { 00225 d->delay = delay; 00226 } 00227 00228 bool DeclarativeWidget::isInitializationDelayed() const 00229 { 00230 return d->delay; 00231 } 00232 00233 QDeclarativeEngine* DeclarativeWidget::engine() 00234 { 00235 return d->engine; 00236 } 00237 00238 QScriptEngine *DeclarativeWidget::scriptEngine() const 00239 { 00240 return d->scriptEngine; 00241 } 00242 00243 QObject *DeclarativeWidget::rootObject() const 00244 { 00245 return d->root; 00246 } 00247 00248 QDeclarativeComponent *DeclarativeWidget::mainComponent() const 00249 { 00250 return d->component; 00251 } 00252 00253 void DeclarativeWidget::resizeEvent(QGraphicsSceneResizeEvent *event) 00254 { 00255 QGraphicsWidget::resizeEvent(event); 00256 00257 if (d->root) { 00258 d->root->setProperty("width", size().width()); 00259 d->root->setProperty("height", size().height()); 00260 } 00261 } 00262 00263 00264 } // namespace Plasma 00265 00266 #include <declarativewidget.moc> 00267
KDE 4.7 API Reference