00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <kdebug.h>
00022
00023 #include <qmetaobject.h>
00024 #include <qdom.h>
00025 #include <qfile.h>
00026 #include <qtextstream.h>
00027 #include <qcursor.h>
00028 #include <qbuffer.h>
00029 #include <qimage.h>
00030 #include <qlayout.h>
00031 #include <qobjectlist.h>
00032 #include <qdatetime.h>
00033 #include <qlabel.h>
00034 #include <qpainter.h>
00035
00036 #include <kfiledialog.h>
00037 #include <klocale.h>
00038 #include <kcommand.h>
00039 #include <kaccelmanager.h>
00040
00041 #include "form.h"
00042 #include "container.h"
00043 #include "objecttree.h"
00044 #include "formmanager.h"
00045 #include "widgetlibrary.h"
00046 #include "spring.h"
00047 #include "pixmapcollection.h"
00048 #include "events.h"
00049 #include "utils.h"
00050 #include "kexiflowlayout.h"
00051 #include "widgetwithsubpropertiesinterface.h"
00052 #include "formIO.h"
00053
00055 CustomWidget::CustomWidget(const QCString &className, QWidget *parent, const char *name)
00056 : QWidget(parent, name), m_className(className)
00057 {
00058 setBackgroundMode(Qt::PaletteDark);
00059 }
00060
00061 CustomWidget::~CustomWidget()
00062 {
00063 }
00064
00065 void
00066 CustomWidget::paintEvent(QPaintEvent *)
00067 {
00068 QPainter p(this);
00069 p.setPen(palette().active().text());
00070 QRect r(rect());
00071 r.setX(r.x()+2);
00072 p.drawText(r, Qt::AlignTop, m_className);
00073 }
00074
00075 using namespace KFormDesigner;
00076
00077 QDict<QLabel> *FormIO::m_buddies = 0;
00078 ObjectTreeItem *FormIO::m_currentItem = 0;
00079 Form *FormIO::m_currentForm = 0;
00080 bool FormIO::m_savePixmapsInline = false;
00081
00082
00083
00084 KFORMEDITOR_EXPORT uint KFormDesigner::version()
00085 {
00086 return KFORMDESIGNER_VERSION;
00087 }
00088
00092
00093 FormIO::FormIO()
00094 {
00095 }
00096
00097 FormIO::~FormIO()
00098 {
00099 }
00100
00101 bool
00102 FormIO::saveFormToFile(Form *form, const QString &filename)
00103 {
00104 QString m_filename;
00105 if(!form->filename().isNull() && filename.isNull())
00106 m_filename = form->filename();
00107
00108 if(filename.isNull())
00109 {
00110 m_filename = KFileDialog::getSaveFileName(QString::null, i18n("*.ui|Qt Designer UI Files"));
00111 if(m_filename.isNull())
00112 return false;
00113 }
00114 else
00115 m_filename = filename;
00116 form->setFilename(m_filename);
00117
00118 QDomDocument domDoc;
00119 if (!saveFormToDom(form, domDoc))
00120 return false;
00121
00122 QFile file(m_filename);
00123 if (!file.open(IO_WriteOnly))
00124 return false;
00125
00126 QTextStream stream(&file);
00127 stream << domDoc.toString(3) << endl;
00128 file.close();
00129
00130 return true;
00131 }
00132
00133 bool
00134 FormIO::saveFormToByteArray(Form *form, QByteArray &dest)
00135 {
00136 QDomDocument domDoc;
00137 if (!saveFormToDom(form, domDoc))
00138 return false;
00139 dest = domDoc.toCString();
00140 return true;
00141 }
00142
00143 bool
00144 FormIO::saveFormToString(Form *form, QString &dest, int indent)
00145 {
00146 QDomDocument domDoc;
00147 if (!saveFormToDom(form, domDoc))
00148 return false;
00149 dest = domDoc.toString(indent);
00150 return true;
00151 }
00152
00153 bool
00154 FormIO::saveFormToDom(Form *form, QDomDocument &domDoc)
00155 {
00156 m_currentForm = form;
00157
00158 domDoc = QDomDocument("UI");
00159 QDomElement uiElement = domDoc.createElement("UI");
00160 domDoc.appendChild(uiElement);
00161 uiElement.setAttribute("version", "3.1");
00162 uiElement.setAttribute("stdsetdef", 1);
00163
00164
00165 form->headerProperties()->insert("version", QString::number(form->formatVersion()));
00166
00167 QDomElement headerPropertiesEl = domDoc.createElement("kfd:customHeader");
00168 for (QMapConstIterator<QCString,QString> it=form->headerProperties()->constBegin(); it!=form->headerProperties()->constEnd(); ++it) {
00169 headerPropertiesEl.setAttribute(it.key(), it.data());
00170 }
00171 uiElement.appendChild(headerPropertiesEl);
00172
00174 QDomElement inlinePix = domDoc.createElement("pixmapinproject");
00175 uiElement.appendChild(inlinePix);
00176
00177
00178 QDomElement baseClass = domDoc.createElement("class");
00179 uiElement.appendChild(baseClass);
00180 QDomText baseClassV = domDoc.createTextNode("QWidget");
00181 baseClass.appendChild(baseClassV);
00182
00183
00184 saveWidget(form->objectTree(), uiElement, domDoc);
00185
00186
00187 QDomElement layoutDefaults = domDoc.createElement("layoutDefaults");
00188 layoutDefaults.setAttribute("spacing", QString::number(form->defaultSpacing()));
00189 layoutDefaults.setAttribute("margin", QString::number(form->defaultMargin()));
00190 uiElement.appendChild(layoutDefaults);
00191
00193 if(form->autoTabStops())
00194 form->autoAssignTabStops();
00195 QDomElement tabStops = domDoc.createElement("tabstops");
00196 uiElement.appendChild(tabStops);
00197 for(ObjectTreeListIterator it( form->tabStopsIterator() ); it.current(); ++it)
00198 {
00199 QDomElement tabstop = domDoc.createElement("tabstop");
00200 tabStops.appendChild(tabstop);
00201 QDomText tabStopText = domDoc.createTextNode(it.current()->name());
00202 tabstop.appendChild(tabStopText);
00203 }
00204
00205
00206 form->pixmapCollection()->save(uiElement);
00207
00208 form->connectionBuffer()->save(uiElement);
00209
00210 form->commandHistory()->documentSaved();
00211
00212 m_currentForm = 0;
00213 m_currentItem = 0;
00214
00215
00216 return true;
00217 }
00218
00219 bool
00220 FormIO::loadFormFromByteArray(Form *form, QWidget *container, QByteArray &src, bool preview)
00221 {
00222 QString errMsg;
00223 int errLine;
00224 int errCol;
00225
00226 QDomDocument inBuf;
00227 bool parsed = inBuf.setContent(src, false, &errMsg, &errLine, &errCol);
00228
00229 if(!parsed)
00230 {
00231 kdDebug() << "WidgetWatcher::load(): " << errMsg << endl;
00232 kdDebug() << "WidgetWatcher::load(): line: " << errLine << " col: " << errCol << endl;
00233 return false;
00234 }
00235
00236 if (!loadFormFromDom(form, container, inBuf))
00237 return false;
00238 if(preview)
00239 form->setDesignMode(false);
00240 return true;
00241 }
00242
00243 bool
00244 FormIO::loadFormFromString(Form *form, QWidget *container, QString &src, bool preview)
00245 {
00246 QString errMsg;
00247 int errLine;
00248 int errCol;
00249
00250 #ifdef KEXI_DEBUG_GUI
00251 form->m_recentlyLoadedUICode = src;
00252 #endif
00253
00254 QDomDocument inBuf;
00255 bool parsed = inBuf.setContent(src, false, &errMsg, &errLine, &errCol);
00256
00257 if(!parsed)
00258 {
00259 kdDebug() << "WidgetWatcher::load(): " << errMsg << endl;
00260 kdDebug() << "WidgetWatcher::load(): line: " << errLine << " col: " << errCol << endl;
00261 return false;
00262 }
00263
00264 if (!loadFormFromDom(form, container, inBuf))
00265 return false;
00266 if(preview)
00267 form->setDesignMode(false);
00268 return true;
00269 }
00270
00271 bool
00272 FormIO::loadFormFromFile(Form *form, QWidget *container, const QString &filename)
00273 {
00274 QString errMsg;
00275 int errLine;
00276 int errCol;
00277 QString m_filename;
00278
00279 if(filename.isNull())
00280 {
00281 m_filename = KFileDialog::getOpenFileName(QString::null, i18n("*.ui|Qt Designer UI Files"));
00282 if(m_filename.isNull())
00283 return false;
00284 }
00285 else
00286 m_filename = filename;
00287
00288 QFile file(m_filename);
00289 if(!file.open(IO_ReadOnly))
00290 {
00291 kdDebug() << "Cannot open the file " << filename << endl;
00292 return false;
00293 }
00294 QTextStream stream(&file);
00295 QString text = stream.read();
00296
00297 QDomDocument inBuf;
00298 bool parsed = inBuf.setContent(text, false, &errMsg, &errLine, &errCol);
00299
00300 if(!parsed)
00301 {
00302 kdDebug() << "WidgetWatcher::load(): " << errMsg << endl;
00303 kdDebug() << "WidgetWatcher::load(): line: " << errLine << " col: " << errCol << endl;
00304 return false;
00305 }
00306
00307 return loadFormFromDom(form, container, inBuf);
00308 }
00309
00310 bool
00311 FormIO::loadFormFromDom(Form *form, QWidget *container, QDomDocument &inBuf)
00312 {
00313 m_currentForm = form;
00314
00315 QDomElement ui = inBuf.namedItem("UI").toElement();
00316
00317
00318 form->headerProperties()->clear();
00319 QDomElement headerPropertiesEl = ui.namedItem("kfd:customHeader").toElement();
00320 QDomAttr attr = headerPropertiesEl.firstChild().toAttr();
00321 while (!attr.isNull() && attr.isAttr()) {
00322 form->headerProperties()->insert(attr.name().latin1(), attr.value());
00323 attr = attr.nextSibling().toAttr();
00324 }
00325
00326 uint ver = 1;
00327 if (form->headerProperties()->contains("version")) {
00328 bool ok;
00329 uint v = (*form->headerProperties())["version"].toUInt(&ok);
00330 if (ok)
00331 ver = v;
00332 }
00333 kdDebug() << "FormIO::loadFormFromDom(): original format version: " << ver << endl;
00334 form->setOriginalFormatVersion( ver );
00335 if (ver < KFormDesigner::version()) {
00338 kdDebug() << "FormIO::loadFormFromDom(): original format is older than current: " << KFormDesigner::version() << endl;
00339 form->setFormatVersion( KFormDesigner::version() );
00340 }
00341 else
00342 form->setFormatVersion( ver );
00343
00344 if (ver > KFormDesigner::version()) {
00346 kdDebug() << "FormIO::loadFormFromDom(): original format is newer than current: " << KFormDesigner::version() << endl;
00347 }
00348
00349
00350 m_savePixmapsInline = ( (ui.namedItem("pixmapinproject").isNull()) || (!ui.namedItem("images").isNull()) );
00351 form->pixmapCollection()->load(ui.namedItem("collection"));
00352
00353 QDomElement element = ui.namedItem("widget").toElement();
00354 createToplevelWidget(form, container, element);
00355
00356
00357 QDomElement tabStops = ui.namedItem("tabstops").toElement();
00358
00359
00360 if(!tabStops.isNull()) {
00361 int i = 0;
00362 uint itemsNotFound = 0;
00363 for(QDomNode n = tabStops.firstChild(); !n.isNull(); n = n.nextSibling(), i++)
00364 {
00365 QString name = n.toElement().text();
00366 ObjectTreeItem *item = form->objectTree()->lookup(name);
00367 if(!item)
00368 {
00369 kdDebug() << "FormIO::loadFormFromDom ERROR : no ObjectTreeItem " << endl;
00370 continue;
00371 }
00372 const int index = form->tabStops()->findRef(item);
00373
00374 const int realIndex = i - itemsNotFound;
00375 if((index != -1) && (index != realIndex))
00376 {
00377 form->tabStops()->remove(item);
00378 form->tabStops()->insert(realIndex, item);
00379 }
00380 if(index == -1) {
00381 itemsNotFound++;
00382 kdDebug() << "FormIO: item '" << name << "' not in list" << endl;
00383 }
00384 }
00385 }
00386
00387
00388 form->connectionBuffer()->load(ui.namedItem("connections"));
00389
00390 m_currentForm = 0;
00391 m_currentItem = 0;
00392
00393 return true;
00394 }
00395
00399
00400 void
00401 FormIO::savePropertyValue(QDomElement &parentNode, QDomDocument &parent, const char *name,
00402 const QVariant &value, QWidget *w, WidgetLibrary *lib)
00403 {
00404
00405
00406 WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(w);
00407 QWidget *subwidget = w;
00408 bool addSubwidgetFlag = false;
00409 int propertyId = w->metaObject()->findProperty(name, true);
00410 if (propertyId == -1 && subpropIface && subpropIface->subwidget()) {
00411 subwidget = subpropIface->subwidget();
00412 propertyId = subpropIface->subwidget()->metaObject()->findProperty(name, true);
00413 addSubwidgetFlag = true;
00414 }
00415 if(propertyId == -1)
00416 {
00417 kdDebug() << "FormIO::savePropertyValue() The object doesn't have this property. Let's try the WidgetLibrary." << endl;
00418 if(lib)
00419 lib->saveSpecialProperty(w->className(), name, value, w, parentNode, parent);
00420 return;
00421 }
00422
00423 const QMetaProperty *meta = subwidget->metaObject()->property(propertyId, true);
00424 if (!meta->stored( subwidget ))
00425 return;
00426 QDomElement propertyE = parent.createElement("property");
00427 propertyE.setAttribute("name", name);
00428 if (addSubwidgetFlag)
00429 propertyE.setAttribute("subwidget", "true");
00430
00431 if(meta && meta->isEnumType())
00432 {
00433
00434 QDomElement type;
00435 QDomText valueE;
00436
00437 if(meta->isSetType())
00438 {
00439 QStringList list = QStringList::fromStrList(meta->valueToKeys(value.toInt()));
00440 type = parent.createElement("set");
00441 valueE = parent.createTextNode(list.join("|"));
00442 type.appendChild(valueE);
00443 }
00444 else
00445 {
00446 QString s = meta->valueToKey(value.toInt());
00447 type = parent.createElement("enum");
00448 valueE = parent.createTextNode(s);
00449 type.appendChild(valueE);
00450 }
00451 propertyE.appendChild(type);
00452 parentNode.appendChild(propertyE);
00453 return;
00454 }
00455
00456 if(value.type() == QVariant::Pixmap) {
00457 QDomText valueE;
00458 QDomElement type = parent.createElement("pixmap");
00459 QCString property = propertyE.attribute("name").latin1();
00460
00461 if(m_savePixmapsInline )
00462 valueE = parent.createTextNode(saveImage(parent, value.toPixmap()));
00463 else
00464 valueE = parent.createTextNode(m_currentItem->pixmapName(property));
00465 type.appendChild(valueE);
00466 propertyE.appendChild(type);
00467 parentNode.appendChild(propertyE);
00468 return;
00469 }
00470
00471
00472 writeVariant(parent, propertyE, value);
00473 parentNode.appendChild(propertyE);
00474 }
00475
00476 void
00477 FormIO::writeVariant(QDomDocument &parent, QDomElement &parentNode, QVariant value)
00478 {
00479 QDomElement type;
00480 QDomText valueE;
00481
00482 switch(value.type())
00483 {
00484 case QVariant::String:
00485 {
00486 type = parent.createElement("string");
00487 valueE = parent.createTextNode(value.toString());
00488 type.appendChild(valueE);
00489 break;
00490 }
00491 case QVariant::CString:
00492 {
00493 type = parent.createElement("cstring");
00494 valueE = parent.createTextNode(value.toString());
00495 type.appendChild(valueE);
00496 break;
00497 }
00498 case QVariant::Rect:
00499 {
00500 type = parent.createElement("rect");
00501 QDomElement x = parent.createElement("x");
00502 QDomElement y = parent.createElement("y");
00503 QDomElement w = parent.createElement("width");
00504 QDomElement h = parent.createElement("height");
00505 QDomText valueX = parent.createTextNode(QString::number(value.toRect().x()));
00506 QDomText valueY = parent.createTextNode(QString::number(value.toRect().y()));
00507 QDomText valueW = parent.createTextNode(QString::number(value.toRect().width()));
00508 QDomText valueH = parent.createTextNode(QString::number(value.toRect().height()));
00509
00510 x.appendChild(valueX);
00511 y.appendChild(valueY);
00512 w.appendChild(valueW);
00513 h.appendChild(valueH);
00514
00515 type.appendChild(x);
00516 type.appendChild(y);
00517 type.appendChild(w);
00518 type.appendChild(h);
00519 break;
00520 }
00521 case QVariant::Color:
00522 {
00523 type = parent.createElement("color");
00524 QDomElement r = parent.createElement("red");
00525 QDomElement g = parent.createElement("green");
00526 QDomElement b = parent.createElement("blue");
00527 QDomText valueR = parent.createTextNode(QString::number(value.toColor().red()));
00528 QDomText valueG = parent.createTextNode(QString::number(value.toColor().green()));
00529 QDomText valueB = parent.createTextNode(QString::number(value.toColor().blue()));
00530
00531 r.appendChild(valueR);
00532 g.appendChild(valueG);
00533 b.appendChild(valueB);
00534
00535 type.appendChild(r);
00536 type.appendChild(g);
00537 type.appendChild(b);
00538 break;
00539 }
00540 case QVariant::Bool:
00541 {
00542 type = parent.createElement("bool");
00543
00544 valueE = parent.createTextNode(value.toBool() ? "true" : "false");
00545 type.appendChild(valueE);
00546 break;
00547 }
00548 case QVariant::Int:
00549 case QVariant::UInt:
00550 {
00551 type = parent.createElement("number");
00552 valueE = parent.createTextNode(QString::number(value.toInt()));
00553 type.appendChild(valueE);
00554 break;
00555 }
00556 case QVariant::Size:
00557 {
00558 type = parent.createElement("size");
00559 QDomElement w = parent.createElement("width");
00560 QDomElement h = parent.createElement("height");
00561 QDomText valueW = parent.createTextNode(QString::number(value.toSize().width()));
00562 QDomText valueH = parent.createTextNode(QString::number(value.toSize().height()));
00563
00564 w.appendChild(valueW);
00565 h.appendChild(valueH);
00566
00567 type.appendChild(w);
00568 type.appendChild(h);
00569 break;
00570 }
00571 case QVariant::Point:
00572 {
00573 type = parent.createElement("point");
00574 QDomElement x = parent.createElement("x");
00575 QDomElement y = parent.createElement("y");
00576 QDomText valueX = parent.createTextNode(QString::number(value.toPoint().x()));
00577 QDomText valueY = parent.createTextNode(QString::number(value.toPoint().y()));
00578
00579 x.appendChild(valueX);
00580 y.appendChild(valueY);
00581
00582 type.appendChild(x);
00583 type.appendChild(y);
00584 break;
00585 }
00586 case QVariant::Font:
00587 {
00588 type = parent.createElement("font");
00589 QDomElement f = parent.createElement("family");
00590 QDomElement p = parent.createElement("pointsize");
00591 QDomElement w = parent.createElement("weight");
00592 QDomElement b = parent.createElement("bold");
00593 QDomElement i = parent.createElement("italic");
00594 QDomElement u = parent.createElement("underline");
00595 QDomElement s = parent.createElement("strikeout");
00596 QDomText valueF = parent.createTextNode(value.toFont().family());
00597 QDomText valueP = parent.createTextNode(QString::number(value.toFont().pointSize()));
00598 QDomText valueW = parent.createTextNode(QString::number(value.toFont().weight()));
00599 QDomText valueB = parent.createTextNode(QString::number(value.toFont().bold()));
00600 QDomText valueI = parent.createTextNode(QString::number(value.toFont().italic()));
00601 QDomText valueU = parent.createTextNode(QString::number(value.toFont().underline()));
00602 QDomText valueS = parent.createTextNode(QString::number(value.toFont().strikeOut()));
00603
00604 f.appendChild(valueF);
00605 p.appendChild(valueP);
00606 w.appendChild(valueW);
00607 b.appendChild(valueB);
00608 i.appendChild(valueI);
00609 u.appendChild(valueU);
00610 s.appendChild(valueS);
00611
00612 type.appendChild(f);
00613 type.appendChild(p);
00614 type.appendChild(w);
00615 type.appendChild(b);
00616 type.appendChild(i);
00617 type.appendChild(u);
00618 type.appendChild(s);
00619 break;
00620 }
00621 case QVariant::Cursor:
00622 {
00623 type = parent.createElement("cursor");
00624 valueE = parent.createTextNode(QString::number(value.toCursor().shape()));
00625 type.appendChild(valueE);
00626 break;
00627 }
00628 case QVariant::SizePolicy:
00629 {
00630 type = parent.createElement("sizepolicy");
00631 QDomElement h = parent.createElement("hsizetype");
00632 QDomElement v = parent.createElement("vsizetype");
00633 QDomElement hs = parent.createElement("horstretch");
00634 QDomElement vs = parent.createElement("verstretch");
00635 QDomText valueH = parent.createTextNode(QString::number(value.toSizePolicy().horData()));
00636 QDomText valueV = parent.createTextNode(QString::number(value.toSizePolicy().verData()));
00637 QDomText valueHS = parent.createTextNode(QString::number(value.toSizePolicy().horStretch()));
00638 QDomText valueVS = parent.createTextNode(QString::number(value.toSizePolicy().verStretch()));
00639
00640 h.appendChild(valueH);
00641 v.appendChild(valueV);
00642 hs.appendChild(valueHS);
00643 vs.appendChild(valueVS);
00644
00645 type.appendChild(h);
00646 type.appendChild(v);
00647 type.appendChild(hs);
00648 type.appendChild(vs);
00649 break;
00650 }
00651 case QVariant::Time:
00652 {
00653 type = parent.createElement("time");
00654 QDomElement h = parent.createElement("hour");
00655 QDomElement m = parent.createElement("minute");
00656 QDomElement s = parent.createElement("second");
00657 QDomText valueH = parent.createTextNode(QString::number(value.toTime().hour()));
00658 QDomText valueM = parent.createTextNode(QString::number(value.toTime().minute()));
00659 QDomText valueS = parent.createTextNode(QString::number(value.toTime().second()));
00660
00661 h.appendChild(valueH);
00662 m.appendChild(valueM);
00663 s.appendChild(valueS);
00664
00665 type.appendChild(h);
00666 type.appendChild(m);
00667 type.appendChild(s);
00668 break;
00669 }
00670 case QVariant::Date:
00671 {
00672 type = parent.createElement("date");
00673 QDomElement y = parent.createElement("year");
00674 QDomElement m = parent.createElement("month");
00675 QDomElement d = parent.createElement("day");
00676 QDomText valueY = parent.createTextNode(QString::number(value.toDate().year()));
00677 QDomText valueM = parent.createTextNode(QString::number(value.toDate().month()));
00678 QDomText valueD = parent.createTextNode(QString::number(value.toDate().day()));
00679
00680 y.appendChild(valueY);
00681 m.appendChild(valueM);
00682 d.appendChild(valueD);
00683
00684 type.appendChild(y);
00685 type.appendChild(m);
00686 type.appendChild(d);
00687 break;
00688 }
00689 case QVariant::DateTime:
00690 {
00691 type = parent.createElement("datetime");
00692 QDomElement h = parent.createElement("hour");
00693 QDomElement m = parent.createElement("minute");
00694 QDomElement s = parent.createElement("second");
00695 QDomElement y = parent.createElement("year");
00696 QDomElement mo = parent.createElement("month");
00697 QDomElement d = parent.createElement("day");
00698 QDomText valueH = parent.createTextNode(QString::number(value.toDateTime().time().hour()));
00699 QDomText valueM = parent.createTextNode(QString::number(value.toDateTime().time().minute()));
00700 QDomText valueS = parent.createTextNode(QString::number(value.toDateTime().time().second()));
00701 QDomText valueY = parent.createTextNode(QString::number(value.toDateTime().date().year()));
00702 QDomText valueMo = parent.createTextNode(QString::number(value.toDateTime().date().month()));
00703 QDomText valueD = parent.createTextNode(QString::number(value.toDateTime().date().day()));
00704
00705 h.appendChild(valueH);
00706 m.appendChild(valueM);
00707 s.appendChild(valueS);
00708 y.appendChild(valueY);
00709 mo.appendChild(valueMo);
00710 d.appendChild(valueD);
00711
00712 type.appendChild(h);
00713 type.appendChild(m);
00714 type.appendChild(s);
00715 type.appendChild(y);
00716 type.appendChild(mo);
00717 type.appendChild(d);
00718 break;
00719 }
00720 default:
00721 break;
00722 }
00723
00724 parentNode.appendChild(type);
00725 }
00726
00727 void
00728 FormIO::savePropertyElement(QDomElement &parentNode, QDomDocument &domDoc, const QString &tagName, const QString &property, const QVariant &value)
00729 {
00730 QDomElement propertyE = domDoc.createElement(tagName);
00731 propertyE.setAttribute("name", property);
00732 writeVariant(domDoc, propertyE, value);
00733 parentNode.appendChild(propertyE);
00734 }
00735
00736 QVariant
00737 FormIO::readPropertyValue(QDomNode node, QObject *obj, const QString &name)
00738 {
00739 QDomElement tag = node.toElement();
00740 QString text = tag.text();
00741 QString type = tag.tagName();
00742
00743 if(type == "string" || type == "cstring")
00744 return text;
00745 else if(type == "rect")
00746 {
00747 QDomElement x = node.namedItem("x").toElement();
00748 QDomElement y = node.namedItem("y").toElement();
00749 QDomElement w = node.namedItem("width").toElement();
00750 QDomElement h = node.namedItem("height").toElement();
00751
00752 int rx = x.text().toInt();
00753 int ry = y.text().toInt();
00754 int rw = w.text().toInt();
00755 int rh = h.text().toInt();
00756
00757 return QRect(rx, ry, rw, rh);
00758 }
00759 else if(type == "color")
00760 {
00761 QDomElement r = node.namedItem("red").toElement();
00762 QDomElement g = node.namedItem("green").toElement();
00763 QDomElement b = node.namedItem("blue").toElement();
00764
00765 int red = r.text().toInt();
00766 int green = g.text().toInt();
00767 int blue = b.text().toInt();
00768
00769 return QColor(red, green, blue);
00770 }
00771 else if(type == "bool")
00772 {
00773 if(text == "true")
00774 return QVariant(true, 3);
00775 else if(text == "false")
00776 return QVariant(false, 3);
00777 return QVariant(text.toInt(), 3);
00778 }
00779 else if(type == "number")
00780 {
00781 return text.toInt();
00782 }
00783 else if(type == "size")
00784 {
00785 QDomElement w = node.namedItem("width").toElement();
00786 QDomElement h = node.namedItem("height").toElement();
00787
00788 return QSize(w.text().toInt(), h.text().toInt());
00789 }
00790 else if(type == "point")
00791 {
00792 QDomElement x = node.namedItem("x").toElement();
00793 QDomElement y = node.namedItem("y").toElement();
00794
00795 return QPoint(x.text().toInt(), y.text().toInt());
00796 }
00797 else if(type == "font")
00798 {
00799 QDomElement fa = node.namedItem("family").toElement();
00800 QDomElement p = node.namedItem("pointsize").toElement();
00801 QDomElement w = node.namedItem("weight").toElement();
00802 QDomElement b = node.namedItem("bold").toElement();
00803 QDomElement i = node.namedItem("italic").toElement();
00804 QDomElement u = node.namedItem("underline").toElement();
00805 QDomElement s = node.namedItem("strikeout").toElement();
00806
00807 QFont f;
00808 f.setFamily(fa.text());
00809 f.setPointSize(p.text().toInt());
00810 f.setWeight(w.text().toInt());
00811 f.setBold(b.text().toInt());
00812 f.setItalic(i.text().toInt());
00813 f.setUnderline(u.text().toInt());
00814 f.setStrikeOut(s.text().toInt());
00815
00816 return f;
00817 }
00818 else if(type == "cursor")
00819 {
00820 return QCursor(text.toInt());
00821 }
00822 else if(type == "time")
00823 {
00824 QDomElement h = node.namedItem("hour").toElement();
00825 QDomElement m = node.namedItem("minute").toElement();
00826 QDomElement s = node.namedItem("second").toElement();
00827
00828 return QTime(h.text().toInt(), m.text().toInt(), s.text().toInt());
00829 }
00830 else if(type == "date")
00831 {
00832 QDomElement y = node.namedItem("year").toElement();
00833 QDomElement m = node.namedItem("month").toElement();
00834 QDomElement d = node.namedItem("day").toElement();
00835
00836 return QDate(y.text().toInt(), m.text().toInt(), d.text().toInt());
00837 }
00838 else if(type == "datetime")
00839 {
00840 QDomElement h = node.namedItem("hour").toElement();
00841 QDomElement m = node.namedItem("minute").toElement();
00842 QDomElement s = node.namedItem("second").toElement();
00843 QDomElement y = node.namedItem("year").toElement();
00844 QDomElement mo = node.namedItem("month").toElement();
00845 QDomElement d = node.namedItem("day").toElement();
00846
00847 QTime t(h.text().toInt(), m.text().toInt(), s.text().toInt());
00848 QDate da(y.text().toInt(), mo.text().toInt(), d.text().toInt());
00849
00850 return QDateTime(da, t);
00851 }
00852 else if(type == "sizepolicy")
00853 {
00854 QDomElement h = node.namedItem("hsizetype").toElement();
00855 QDomElement v = node.namedItem("vsizetype").toElement();
00856 QDomElement hs = node.namedItem("horstretch").toElement();
00857 QDomElement vs = node.namedItem("verstretch").toElement();
00858
00859 QSizePolicy s;
00860 s.setHorData((QSizePolicy::SizeType)h.text().toInt());
00861 s.setVerData((QSizePolicy::SizeType)v.text().toInt());
00862 s.setHorStretch(hs.text().toInt());
00863 s.setVerStretch(vs.text().toInt());
00864 return s;
00865 }
00866 else if(type == "pixmap")
00867 {
00868 if(m_savePixmapsInline || !m_currentForm || !m_currentItem || !m_currentForm->pixmapCollection()->contains(text))
00869 return loadImage(tag.ownerDocument(), text);
00870 else
00871 {
00872 m_currentItem->setPixmapName(name.latin1(), text);
00873 return m_currentForm->pixmapCollection()->getPixmap(text);
00874 }
00875 return QVariant(QPixmap());
00876 }
00877 else if(type == "enum")
00878 return text;
00879 else if(type == "set")
00880 {
00881 WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(obj);
00882 QObject *subobject = (subpropIface && subpropIface->subwidget()) ? subpropIface->subwidget() : obj;
00883 const int count = subobject->metaObject()->findProperty(name.latin1(), true);
00884 const QMetaProperty *meta = count!=-1 ? subobject->metaObject()->property(count, true) : 0;
00885
00886 if (meta) {
00887 if (meta->isSetType()) {
00888 QStrList keys;
00889 const QStringList list( QStringList::split("|", text) );
00890 for (QStringList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it)
00891 keys.append((*it).latin1());
00892
00893 return meta->keysToValue(keys);
00894 }
00895 }
00896 else {
00897
00898
00899
00900
00901 return QStringList::split("|", text);
00902 }
00903 }
00904 return QVariant();
00905 }
00906
00910
00911 void
00912 FormIO::saveWidget(ObjectTreeItem *item, QDomElement &parent, QDomDocument &domDoc, bool insideGridLayout)
00913 {
00914 if (!item)
00915 return;
00916 bool savedAlignment = false;
00917
00918 if(item->className() == "Spring")
00919 {
00920 Spring::saveSpring(item, parent, domDoc, insideGridLayout);
00921 return;
00922 }
00923
00924 bool resetCurrentForm = false;
00925 m_currentItem = item;
00926 if(!m_currentForm)
00927 {
00928 resetCurrentForm = true;
00929 m_currentForm = item->container() ? item->container()->form() : item->parent()->container()->form();
00930 }
00931
00932
00933 WidgetLibrary *lib = m_currentForm->library();
00934
00935
00936
00937
00938
00939
00940 QDomElement tclass = domDoc.createElement("widget");
00941 parent.appendChild(tclass);
00942
00943 if(insideGridLayout)
00944 {
00945 tclass.setAttribute("row", item->gridRow());
00946 tclass.setAttribute("column", item->gridCol());
00947 if(item->spanMultipleCells())
00948 {
00949 tclass.setAttribute("rowspan", item->gridRowSpan());
00950 tclass.setAttribute("colspan", item->gridColSpan());
00951 }
00952 }
00953
00954 if(!item->parent())
00955 tclass.setAttribute("class", "QWidget");
00956
00957 else if(item->widget()->isA("HBox") || item->widget()->isA("VBox") || item->widget()->isA("Grid")
00958 || item->widget()->isA("HFlow") || item->widget()->isA("VFlow"))
00959 tclass.setAttribute("class", "QLayoutWidget");
00960 else if(item->widget()->isA("CustomWidget"))
00961 tclass.setAttribute("class", item->className());
00962 else
00963 tclass.setAttribute("class", lib->savingName(item->widget()->className()) );
00964
00965 savePropertyValue(tclass, domDoc, "name", item->widget()->property("name"), item->widget());
00966
00967
00968
00969
00971
00972
00973
00974
00975 if(item && !item->parent()) {
00976
00977 savePropertyValue(tclass, domDoc, "geometry",
00978 QRect( QPoint(0,0), item->widget()->size()),
00979 item->widget());
00980 }
00981
00982 else if(parent.tagName() == "widget" || parent.tagName() == "UI")
00983 savePropertyValue(tclass, domDoc, "geometry", item->widget()->property("geometry"), item->widget());
00984
00985
00986 if(item->widget()->inherits("QLabel") && ((QLabel*)item->widget())->buddy())
00987 savePropertyElement(tclass, domDoc, "property", "buddy", ((QLabel*)item->widget())->buddy()->name());
00988
00989
00990 QVariantMap *map = new QVariantMap( *(item->modifiedProperties()) );
00991 QMap<QString,QVariant>::ConstIterator endIt = map->constEnd();
00992 for(QMap<QString,QVariant>::ConstIterator it = map->constBegin(); it != endIt; ++it)
00993 {
00994 const QCString name( it.key().latin1() );
00995 if(name == "hAlign" || name == "vAlign" || name == "wordbreak" || name == "alignment") {
00996 if(!savedAlignment)
00997 {
00998 savePropertyValue(tclass, domDoc, "alignment", item->widget()->property("alignment"), item->widget());
00999 savedAlignment = true;
01000 }
01001 }
01002 else if(name == "name" || name == "geometry" || name == "layout") {
01003
01004 }
01005 else {
01006 savePropertyValue(tclass, domDoc, it.key().latin1(), item->widget()->property(it.key().latin1()),
01007 item->widget(), lib);
01008 }
01009 }
01010 delete map;
01011
01012 if(item->widget()->isA("CustomWidget")) {
01013 QDomDocument doc("TEMP");
01014 doc.setContent(item->m_unknownProps);
01015 for(QDomNode n = doc.firstChild(); !n.isNull(); n = n.nextSibling()) {
01016 tclass.appendChild(n.cloneNode());
01017 }
01018
01019 }
01020
01021 QDomElement layout;
01022 if(item->container() && item->container()->layoutType() != Container::NoLayout)
01023 {
01024 if(item->container()->layout())
01025 {
01026 layout = domDoc.createElement("temp");
01027 savePropertyValue(layout, domDoc, "name", "unnamed", item->widget());
01028 if(item->modifiedProperties()->contains("layoutMargin"))
01029 savePropertyElement(layout, domDoc, "property", "margin", item->container()->layoutMargin());
01030 if(item->modifiedProperties()->contains("layoutSpacing"))
01031 savePropertyElement(layout, domDoc, "property", "spacing", item->container()->layoutSpacing());
01032 tclass.appendChild(layout);
01033 }
01034 }
01035
01036 int layoutType = item->container() ? item->container()->layoutType() : Container::NoLayout;
01037 switch(layoutType) {
01038 case Container::Grid:
01039 {
01040 layout.setTagName("grid");
01041 for(ObjectTreeItem *objIt = item->children()->first(); objIt; objIt = item->children()->next())
01042 saveWidget(objIt, layout, domDoc, true);
01043 break;
01044 }
01045 case Container::HBox: case Container::VBox:
01046 {
01047
01048 WidgetList *list;
01049 if(layout.tagName() == "hbox") {
01050 list = new HorWidgetList();
01051 layout.setTagName("hbox");
01052 }
01053 else {
01054 list = new VerWidgetList();
01055 layout.setTagName("vbox");
01056 }
01057
01058 for(ObjectTreeItem *objTree = item->children()->first(); objTree; objTree = item->children()->next())
01059 list->append(objTree->widget());
01060 list->sort();
01061
01062 for(QWidget *obj = list->first(); obj; obj = list->next()) {
01063 ObjectTreeItem *titem = item->container()->form()->objectTree()->lookup(obj->name());
01064 if(item)
01065 saveWidget(titem, layout, domDoc);
01066 }
01067 delete list;
01068 break;
01069 }
01070 case Container::HFlow: case Container::VFlow:
01071 {
01072 layout.setTagName("grid");
01073 KexiFlowLayout *flow = static_cast<KexiFlowLayout*>(item->container()->layout());
01074 if(!flow) break;
01075 WidgetList *list = (WidgetList*)flow->widgetList();
01076
01077
01078 savePropertyElement(layout, domDoc, "property", "customLayout", Container::layoutTypeToString(item->container()->layoutType()) );
01079 savePropertyElement(layout, domDoc, "property", "justify", QVariant(static_cast<KexiFlowLayout*>(item->container()->layout())->isJustified(), 3) );
01080
01081
01082 item->container()->createGridLayout(true);
01083 for(QWidget *obj = list->first(); obj; obj = list->next()) {
01084 ObjectTreeItem *titem = item->container()->form()->objectTree()->lookup(obj->name());
01085 if(item)
01086 saveWidget(titem, layout, domDoc, true);
01087 }
01088 delete list;
01089 break;
01090 }
01091 default:
01092 {
01093 for(ObjectTreeItem *objIt = item->children()->first(); objIt; objIt = item->children()->next())
01094 saveWidget(objIt, tclass, domDoc);
01095 }
01096 }
01097
01098 addIncludeFileName(lib->includeFileName(item->widget()->className()), domDoc);
01099
01100 if(resetCurrentForm)
01101 m_currentForm = 0;
01102 m_currentItem = 0;
01103 }
01104
01105 void
01106 FormIO::cleanClipboard(QDomElement &uiElement)
01107 {
01108
01109 if(!uiElement.namedItem("includehints").isNull())
01110 uiElement.removeChild(uiElement.namedItem("includehints"));
01111
01112 if(!uiElement.namedItem("connections").isNull())
01113 uiElement.insertAfter(uiElement.namedItem("connections"), QDomNode());
01114 if(!uiElement.namedItem("images").isNull())
01115 uiElement.insertAfter(uiElement.namedItem("images"), QDomNode());
01116 }
01117
01118 void
01119 FormIO::loadWidget(Container *container, const QDomElement &el, QWidget *parent)
01120 {
01121 bool resetCurrentForm = false;
01122 if(!m_currentForm)
01123 {
01124 resetCurrentForm = true;
01125 m_currentForm = container->form();
01126 }
01127
01128
01129 QString wname;
01130 for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
01131 {
01132 if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "name"))
01133 {
01134 wname = n.toElement().text();
01135 break;
01136 }
01137 }
01138
01139 QWidget *w;
01140 QCString classname, alternate;
01141
01142 if(el.tagName() == "spacer")
01143 classname = "Spring";
01144 else if(el.attribute("class") == "QLayoutWidget")
01145 {
01146 for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
01147 {
01148 QString tagName = n.toElement().tagName();
01149 if(tagName == "property")
01150 continue;
01151 if(tagName == "hbox")
01152 classname = "HBox";
01153 else if(tagName == "vbox")
01154 classname = "VBox";
01155 else if(tagName == "grid") {
01156
01157 for(QDomNode child = n.firstChild(); !child.isNull(); child = child.nextSibling()) {
01158 if((child.toElement().tagName() == "property")
01159 && (child.toElement().attribute("name") == "customLayout"))
01160 {
01161 classname = child.toElement().text().latin1();
01162 break;
01163 }
01164 }
01165
01166 if(classname.isEmpty())
01167 classname = "Grid";
01168 }
01169 }
01170 }
01171 else
01172
01173 {
01174 classname = el.attribute("class").latin1();
01175 alternate = container->form()->library()->classNameForAlternate(classname);
01176 }
01177
01178 if(alternate == "CustomWidget")
01179 w = new CustomWidget(classname, container->widget(), wname.latin1());
01180 else
01181 {
01182 if(!alternate.isNull())
01183 classname = alternate;
01184
01185 int widgetOptions = WidgetFactory::DefaultOptions;
01186 if (!container->form()->designMode()) {
01187 widgetOptions ^= WidgetFactory::DesignViewMode;
01188 }
01189
01190 if(!parent)
01191 w = container->form()->library()->createWidget(classname, container->widget(),
01192 wname.latin1(), container, widgetOptions);
01193 else
01194 w = container->form()->library()->createWidget(classname, parent, wname.latin1(),
01195 container, widgetOptions);
01196 }
01197
01198 if(!w)
01199 return;
01200 #if KDE_VERSION >= KDE_MAKE_VERSION(3,4,0)
01202 if (m_currentForm->designMode()) {
01203
01204 KAcceleratorManager::setNoAccel(w);
01205 }
01206 #endif
01207 w->setStyle(&(container->widget()->style()));
01208 w->show();
01209
01210
01211 ObjectTreeItem *item = container->form()->objectTree()->lookup(wname);
01212 if (!item) {
01213
01214 item = new ObjectTreeItem(container->form()->library()->displayName(classname),
01215 wname, w, container);
01216 if(parent) {
01217 ObjectTreeItem *titem = container->form()->objectTree()->lookup(parent->name());
01218 if(titem)
01219 container->form()->objectTree()->addItem(titem, item);
01220 else
01221 kdDebug() << "FORMIO :: ERROR no parent widget " << endl;
01222 }
01223 else
01224 container->form()->objectTree()->addItem(container->objectTree(), item);
01225 }
01226
01227
01228 if (container->form()->designMode() && dynamic_cast<DesignTimeDynamicChildWidgetHandler*>(w)) {
01229 dynamic_cast<DesignTimeDynamicChildWidgetHandler*>(w)->assignItem(item);
01230 }
01231
01232 m_currentItem = item;
01233
01234 if(container->layoutType() == Container::Grid) {
01235 QGridLayout *layout = (QGridLayout*)container->layout();
01236 if(el.hasAttribute("rowspan")) {
01237 if(layout)
01238 layout->addMultiCellWidget(w, el.attribute("row").toInt(), el.attribute("row").toInt() + el.attribute("rowspan").toInt()-1,
01239 el.attribute("column").toInt(), el.attribute("column").toInt() + el.attribute("colspan").toInt()-1);
01240 item->setGridPos(el.attribute("row").toInt(), el.attribute("column").toInt(), el.attribute("rowspan").toInt(),
01241 el.attribute("colspan").toInt());
01242 }
01243 else {
01244 if(layout)
01245 layout->addWidget(w, el.attribute("row").toInt(), el.attribute("column").toInt());
01246 item->setGridPos(el.attribute("row").toInt(), el.attribute("column").toInt(), 0, 0);
01247 }
01248 }
01249 else if(container->layout())
01250 container->layout()->add(w);
01251
01252 readChildNodes(item, container, el, w);
01253
01254 if(item->container() && item->container()->layout())
01255 item->container()->layout()->activate();
01256
01257
01258 QValueList<QCString> list(container->form()->library()->autoSaveProperties(w->className()));
01259 QValueList<QCString>::ConstIterator endIt = list.constEnd();
01260 KFormDesigner::WidgetWithSubpropertiesInterface* subpropIface
01261 = dynamic_cast<KFormDesigner::WidgetWithSubpropertiesInterface*>(w);
01262 QWidget *subwidget = (subpropIface && subpropIface->subwidget()) ? subpropIface->subwidget() : w;
01263 for(QValueList<QCString>::ConstIterator it = list.constBegin(); it != endIt; ++it) {
01264 if(subwidget->metaObject()->findProperty(*it, true) != -1)
01265 item->addModifiedProperty(*it, subwidget->property(*it));
01266 }
01267
01268 if(resetCurrentForm)
01269 m_currentForm = 0;
01270 m_currentItem = 0;
01271 }
01272
01273 void
01274 FormIO::createToplevelWidget(Form *form, QWidget *container, QDomElement &el)
01275 {
01276
01277 QString wname;
01278 for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
01279 {
01280 if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "name"))
01281 {
01282 wname = n.toElement().text();
01283 break;
01284 }
01285
01286 }
01287
01288 container->setName(wname.latin1());
01289 if(form->objectTree())
01290 form->objectTree()->rename(form->objectTree()->name(), wname);
01291 form->setInteractiveMode(false);
01292
01293 QDict<QLabel> *oldBuddies = 0;
01294 if(m_buddies)
01295 oldBuddies = m_buddies;
01296 m_buddies = new QDict<QLabel>();
01297 m_currentItem = form->objectTree();
01298
01299 readChildNodes(form->objectTree(), form->toplevelContainer(), el, container);
01300
01301
01302 QDictIterator<QLabel> it(*m_buddies);
01303 for(; it.current(); ++it)
01304 {
01305 ObjectTreeItem *item = form->objectTree()->lookup(it.currentKey());
01306 if(!item || !item->widget())
01307 {
01308 kdDebug() << "Cannot assign buddy for widget " << it.current()->name() << " to " << it.currentKey() << endl;
01309 continue;
01310 }
01311 it.current()->setBuddy(item->widget());
01312 }
01313 delete m_buddies;
01314 m_buddies = oldBuddies;
01315
01316 m_currentItem = 0;
01317
01318 form->setInteractiveMode(true);
01319 }
01320
01321 void
01322 FormIO::readChildNodes(ObjectTreeItem *item, Container *container, const QDomElement &el, QWidget *w)
01323 {
01324 QString eltag = el.tagName();
01325
01326 WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(w);
01327 QWidget *subwidget = (subpropIface && subpropIface->subwidget()) ? subpropIface->subwidget() : w;
01328
01329 for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
01330 {
01331 QString tag = n.toElement().tagName();
01332 QDomElement node = n.toElement();
01333
01334 if((tag == "property") || (tag == "attribute"))
01335 {
01336 QString name = node.attribute("name");
01337
01338
01339 if( ((eltag == "grid") || (eltag == "hbox") || (eltag == "vbox")) &&
01340 (name == "name"))
01341 continue;
01342
01343 if (node.attribute("subwidget")=="true") {
01344
01345
01346 const QVariant val( readPropertyValue(node.firstChild(), w, name) );
01347 kdDebug() << val.toStringList() << endl;
01348 item->addSubproperty( name.latin1(), val );
01349
01350 item->addModifiedProperty( name.latin1(), val );
01351 continue;
01352 }
01353
01354
01355 if(name == "buddy")
01356 m_buddies->insert(readPropertyValue(node.firstChild(), w, name).toString(), (QLabel*)w);
01357 else if(((eltag == "grid") || (eltag == "hbox") || (eltag == "vbox")) &&
01358 item->container() && item->container()->layout()) {
01359
01360 if(name == "margin") {
01361 int margin = readPropertyValue(node.firstChild(), w, name).toInt();
01362 item->container()->setLayoutMargin(margin);
01363 item->container()->layout()->setMargin(margin);
01364 }
01365
01366 else if(name == "spacing") {
01367 int spacing = readPropertyValue(node.firstChild(), w, name).toInt();
01368 item->container()->setLayoutSpacing(spacing);
01369 item->container()->layout()->setSpacing(spacing);
01370 }
01371 else if((name == "justify")){
01372 bool justify = readPropertyValue(node.firstChild(), w, name).toBool();
01373 KexiFlowLayout *flow = static_cast<KexiFlowLayout*>(item->container()->layout());
01374 if(flow)
01375 flow->setJustified(justify);
01376 }
01377 }
01378
01379 else if(subwidget->metaObject()->findProperty(name.latin1(), true) == -1)
01380 {
01381 if(w->className() == QString::fromLatin1("CustomWidget"))
01382 item->storeUnknownProperty(node);
01383 else {
01384 bool read = container->form()->library()->readSpecialProperty(
01385 w->className(), node, w, item);
01386 if(!read)
01387 item->storeUnknownProperty(node);
01388 }
01389 }
01390 else
01391 {
01392 QVariant val( readPropertyValue(node.firstChild(), w, name) );
01393 if(name == "geometry" && dynamic_cast<FormWidget*>(w)) {
01394
01395 QRect r( val.toRect() );
01396 if (r.left()<0)
01397 r.moveLeft(0);
01398 if (r.top()<0)
01399 r.moveTop(0);
01400 val = r;
01401 }
01402 subwidget->setProperty(name.latin1(), val);
01403
01404
01405
01406
01407
01408 item->addModifiedProperty(name.latin1(), val);
01409 }
01410 }
01411 else if(tag == "widget")
01412 {
01413 if(item->container())
01414 loadWidget(item->container(), node);
01415 else
01416 loadWidget(container, node, w);
01417 }
01418 else if(tag == "spacer") {
01419 loadWidget(container, node, w);
01420 }
01421 else if(tag == "grid") {
01422
01423 QString layoutName;
01424 for(QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
01425 if((child.toElement().tagName() == "property") && (child.toElement().attribute("name") == "customLayout")) {
01426 layoutName = child.toElement().text();
01427 break;
01428 }
01429 }
01430
01431 if(layoutName == "HFlow") {
01432 item->container()->m_layType = Container::HFlow;
01433 KexiFlowLayout *layout = new KexiFlowLayout(item->widget());
01434 layout->setOrientation(Horizontal);
01435 item->container()->m_layout = (QLayout*)layout;
01436 }
01437 else if(layoutName == "VFlow") {
01438 item->container()->m_layType = Container::VFlow;
01439 KexiFlowLayout *layout = new KexiFlowLayout(item->widget());
01440 layout->setOrientation(Vertical);
01441 item->container()->m_layout = (QLayout*)layout;
01442 }
01443 else {
01444 item->container()->m_layType = Container::Grid;
01445 QGridLayout *layout = new QGridLayout(item->widget(), 1, 1);
01446 item->container()->m_layout = (QLayout*)layout;
01447 }
01448 readChildNodes(item, container, node, w);
01449 }
01450 else if(tag == "vbox") {
01451 item->container()->m_layType = Container::VBox;
01452 QVBoxLayout *layout = new QVBoxLayout(item->widget());
01453 item->container()->m_layout = (QLayout*)layout;
01454 readChildNodes(item, container, node, w);
01455 }
01456 else if(tag == "hbox") {
01457 item->container()->m_layType = Container::HBox;
01458 QHBoxLayout *layout = new QHBoxLayout(item->widget());
01459 item->container()->m_layout = (QLayout*)layout;
01460 readChildNodes(item, container, node, w);
01461 }
01462 else {
01463 if(w->className() == QString::fromLatin1("CustomWidget"))
01464 item->storeUnknownProperty(node);
01465 else {
01466 bool read = container->form()->library()->readSpecialProperty(
01467 w->className(), node, w, item);
01468 if(!read)
01469 item->storeUnknownProperty(node);
01470 }
01471 }
01472 }
01473 }
01474
01478
01479 void
01480 FormIO::addIncludeFileName(const QString &include, QDomDocument &domDoc)
01481 {
01482 if(include.isEmpty())
01483 return;
01484
01485 QDomElement includes;
01486 QDomElement uiEl = domDoc.namedItem("UI").toElement();
01487 if(uiEl.namedItem("includehints").isNull())
01488 {
01489 includes = domDoc.createElement("includehints");
01490 uiEl.appendChild(includes);
01491 }
01492 else
01493 includes = uiEl.namedItem("includehints").toElement();
01494
01495
01496 for(QDomNode n = includes.firstChild(); !n.isNull(); n = n.nextSibling())
01497 {
01498 if(n.toElement().text() == include)
01499 return;
01500 }
01501
01502 QDomElement includeHint = domDoc.createElement("includehint");
01503 includes.appendChild(includeHint);
01504 QDomText includeText = domDoc.createTextNode(include);
01505 includeHint.appendChild(includeText);
01506 }
01507
01509
01510 QString
01511 FormIO::saveImage(QDomDocument &domDoc, const QPixmap &pixmap)
01512 {
01513 QDomNode node = domDoc.namedItem("images");
01514 QDomElement images;
01515 if(node.isNull())
01516 {
01517 images = domDoc.createElement("images");
01518 QDomElement ui = domDoc.namedItem("UI").toElement();
01519 ui.appendChild(images);
01520 }
01521 else
01522 images = node.toElement();
01523
01524 int count = images.childNodes().count();
01525 QDomElement image = domDoc.createElement("image");
01526 QString name = "image" + QString::number(count);
01527 image.setAttribute("name", name);
01528
01529 QImage img = pixmap.convertToImage();
01530 QByteArray ba;
01531 QBuffer buf(ba);
01532 buf.open( IO_WriteOnly | IO_Translate );
01533 QString format = img.depth() > 1 ? "XPM" : "XBM";
01534 QImageIO iio( &buf, format.latin1() );
01535 iio.setImage( img );
01536 iio.write();
01537 buf.close();
01538 QByteArray bazip = qCompress( ba );
01539 ulong len = bazip.size();
01540
01541 QDomElement data = domDoc.createElement("data");
01542 data.setAttribute("format", format + ".GZ");
01543 data.setAttribute("length", ba.size());
01544
01545 static const char hexchars[] = "0123456789abcdef";
01546 QString content;
01547 for(int i = 4; i < (int)len; ++i)
01548 {
01549 uchar s = (uchar) bazip[i];
01550 content += hexchars[s >> 4];
01551 content += hexchars[s & 0x0f];
01552 }
01553
01554 QDomText text = domDoc.createTextNode(content);
01555 data.appendChild(text);
01556 image.appendChild(data);
01557 images.appendChild(image);
01558
01559 return name;
01560 }
01561
01562 QPixmap
01563 FormIO::loadImage(QDomDocument domDoc, const QString& name)
01564 {
01565 QDomElement images = domDoc.namedItem("UI").namedItem("images").toElement();
01566 if(images.isNull())
01567 return 0;
01568
01569 QDomElement image;
01570 for(QDomNode n = images.firstChild(); !n.isNull(); n = n.nextSibling())
01571 {
01572 if((n.toElement().tagName() == "image") && (n.toElement().attribute("name") == name))
01573 {
01574 image = n.toElement();
01575 break;
01576 }
01577 }
01578
01579 QPixmap pix;
01580 QString data = image.namedItem("data").toElement().text();
01581 const int lengthOffset = 4;
01582 int baSize = data.length() / 2 + lengthOffset;
01583 uchar *ba = new uchar[baSize];
01584 for(int i = lengthOffset; i < baSize; ++i)
01585 {
01586 char h = data[2 * (i-lengthOffset)].latin1();
01587 char l = data[2 * (i-lengthOffset) + 1].latin1();
01588 uchar r = 0;
01589 if(h <= '9')
01590 r += h - '0';
01591 else
01592 r += h - 'a' + 10;
01593 r = r << 4;
01594 if(l <= '9')
01595 r += l - '0';
01596 else
01597 r += l - 'a' + 10;
01598 ba[i] = r;
01599 }
01600
01601 QString format = image.namedItem("data").toElement().attribute("format", "PNG");
01602 if((format == "XPM.GZ") || (format == "XBM.GZ"))
01603 {
01604 ulong len = image.attribute("length").toULong();
01605 if(len < data.length() * 5)
01606 len = data.length() * 5;
01607
01608
01609 ba[0] = ( len & 0xff000000 ) >> 24;
01610 ba[1] = ( len & 0x00ff0000 ) >> 16;
01611 ba[2] = ( len & 0x0000ff00 ) >> 8;
01612 ba[3] = ( len & 0x000000ff );
01613 QByteArray baunzip = qUncompress(ba, baSize);
01614 pix.loadFromData( (const uchar*)baunzip.data(), baunzip.size(), format.left(format.find('.')).latin1() );
01615 }
01616 else
01617 pix.loadFromData( (const uchar*)ba+lengthOffset, baSize-lengthOffset, format.latin1() );
01618
01619 delete[] ba;
01620
01621 return pix;
01622 }
01623
01625
01626 #include "formIO.moc"