/* This file is part of the KDE project Copyright (C) 2004 Cedric Pasteur Copyright (C) 2005-2007 Jaroslaw Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "form.h" #include "container.h" #include "objecttree.h" #include "formmanager.h" #include "widgetlibrary.h" #include "spring.h" #include "pixmapcollection.h" #include "events.h" #include "utils.h" #include "kexiflowlayout.h" #include "widgetwithsubpropertiesinterface.h" #include "formIO.h" /// A blank widget used when the class name is not supported CustomWidget::CustomWidget(const TQCString &className, TQWidget *parent, const char *name) : TQWidget(parent, name), m_className(className) { setBackgroundMode(TQt::PaletteDark); } CustomWidget::~CustomWidget() { } void CustomWidget::paintEvent(TQPaintEvent *) { TQPainter p(this); p.setPen(tqpalette().active().text()); TQRect r(rect()); r.setX(r.x()+2); p.drawText(r, TQt::AlignTop, m_className); } using namespace KFormDesigner; TQDict *FormIO::m_buddies = 0; ObjectTreeItem *FormIO::m_currentItem = 0; Form *FormIO::m_currentForm = 0; bool FormIO::m_savePixmapsInline = false; // FormIO itself KFORMEDITOR_EXPORT uint KFormDesigner::version() { return KFORMDESIGNER_VERSION; } ///////////////////////////////////////////////////////////////////////////// ///////////// Saving/loading functions ////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// FormIO::FormIO() { } FormIO::~FormIO() { } bool FormIO::saveFormToFile(Form *form, const TQString &filename) { TQString m_filename; if(!form->filename().isNull() && filename.isNull()) m_filename = form->filename(); if(filename.isNull()) { m_filename = KFileDialog::getSaveFileName(TQString(), i18n("*.ui|TQt Designer UI Files")); if(m_filename.isNull()) return false; } else m_filename = filename; form->setFilename(m_filename); TQDomDocument domDoc; if (!saveFormToDom(form, domDoc)) return false; TQFile file(m_filename); if (!file.open(IO_WriteOnly)) return false; TQTextStream stream(&file); stream << domDoc.toString(3) << endl; file.close(); return true; } bool FormIO::saveFormToByteArray(Form *form, TQByteArray &dest) { TQDomDocument domDoc; if (!saveFormToDom(form, domDoc)) return false; dest = domDoc.toCString(); return true; } bool FormIO::saveFormToString(Form *form, TQString &dest, int indent) { TQDomDocument domDoc; if (!saveFormToDom(form, domDoc)) return false; dest = domDoc.toString(indent); return true; } bool FormIO::saveFormToDom(Form *form, TQDomDocument &domDoc) { m_currentForm = form; domDoc = TQDomDocument("UI"); TQDomElement uiElement = domDoc.createElement("UI"); domDoc.appendChild(uiElement); uiElement.setAttribute("version", "3.1"); uiElement.setAttribute("stdsetdef", 1); //update format version information form->headerProperties()->insert("version", TQString::number(form->formatVersion())); //custom properties TQDomElement headerPropertiesEl = domDoc.createElement("kfd:customHeader"); for (TQMapConstIterator it=form->headerProperties()->constBegin(); it!=form->headerProperties()->constEnd(); ++it) { headerPropertiesEl.setAttribute(it.key(), it.data()); } uiElement.appendChild(headerPropertiesEl); /// We save the savePixmapsInline property in the Form TQDomElement inlinePix = domDoc.createElement("pixmapinproject"); uiElement.appendChild(inlinePix); // We create the top class element TQDomElement baseClass = domDoc.createElement("class"); uiElement.appendChild(baseClass); TQDomText baseClassV = domDoc.createTextNode(TQWIDGET_OBJECT_NAME_STRING); baseClass.appendChild(baseClassV); // Save the toplevel widgets, and so the whole Form saveWidget(form->objectTree(), uiElement, domDoc); // We then save the layoutdefaults element TQDomElement layoutDefaults = domDoc.createElement("layoutDefaults"); layoutDefaults.setAttribute("spacing", TQString::number(form->defaultSpacing())); layoutDefaults.setAttribute("margin", TQString::number(form->defaultMargin())); uiElement.appendChild(layoutDefaults); /// Save tab Stops if(form->autoTabStops()) form->autoAssignTabStops(); TQDomElement tabStops = domDoc.createElement("tabstops"); uiElement.appendChild(tabStops); for(ObjectTreeListIterator it( form->tabStopsIterator() ); it.current(); ++it) { TQDomElement tabstop = domDoc.createElement("tabstop"); tabStops.appendChild(tabstop); TQDomText tabStopText = domDoc.createTextNode(it.current()->name()); tabstop.appendChild(tabStopText); } // Save the Form 's PixmapCollection form->pixmapCollection()->save(uiElement); // Save the Form connections form->connectionBuffer()->save(uiElement); form->commandHistory()->documentSaved(); m_currentForm = 0; m_currentItem = 0; //m_currentWidget = 0; return true; } bool FormIO::loadFormFromByteArray(Form *form, TQWidget *container, TQByteArray &src, bool preview) { TQString errMsg; int errLine; int errCol; TQDomDocument inBuf; bool parsed = inBuf.setContent(src, false, &errMsg, &errLine, &errCol); if(!parsed) { kdDebug() << "WidgetWatcher::load(): " << errMsg << endl; kdDebug() << "WidgetWatcher::load(): line: " << errLine << " col: " << errCol << endl; return false; } if (!loadFormFromDom(form, container, inBuf)) return false; if(preview) form->setDesignMode(false); return true; } bool FormIO::loadFormFromString(Form *form, TQWidget *container, TQString &src, bool preview) { TQString errMsg; int errLine; int errCol; #ifdef KEXI_DEBUG_GUI form->m_recentlyLoadedUICode = src; #endif TQDomDocument inBuf; bool parsed = inBuf.setContent(src, false, &errMsg, &errLine, &errCol); if(!parsed) { kdDebug() << "WidgetWatcher::load(): " << errMsg << endl; kdDebug() << "WidgetWatcher::load(): line: " << errLine << " col: " << errCol << endl; return false; } if (!loadFormFromDom(form, container, inBuf)) return false; if(preview) form->setDesignMode(false); return true; } bool FormIO::loadFormFromFile(Form *form, TQWidget *container, const TQString &filename) { TQString errMsg; int errLine; int errCol; TQString m_filename; if(filename.isNull()) { m_filename = KFileDialog::getOpenFileName(TQString(), i18n("*.ui|TQt Designer UI Files")); if(m_filename.isNull()) return false; } else m_filename = filename; TQFile file(m_filename); if(!file.open(IO_ReadOnly)) { kdDebug() << "Cannot open the file " << filename << endl; return false; } TQTextStream stream(&file); TQString text = stream.read(); TQDomDocument inBuf; bool parsed = inBuf.setContent(text, false, &errMsg, &errLine, &errCol); if(!parsed) { kdDebug() << "WidgetWatcher::load(): " << errMsg << endl; kdDebug() << "WidgetWatcher::load(): line: " << errLine << " col: " << errCol << endl; return false; } return loadFormFromDom(form, container, inBuf); } bool FormIO::loadFormFromDom(Form *form, TQWidget *container, TQDomDocument &inBuf) { m_currentForm = form; TQDomElement ui = inBuf.namedItem("UI").toElement(); //custom properties form->headerProperties()->clear(); TQDomElement headerPropertiesEl = ui.namedItem("kfd:customHeader").toElement(); TQDomAttr attr = headerPropertiesEl.firstChild().toAttr(); while (!attr.isNull() && attr.isAttr()) { form->headerProperties()->insert(attr.name().latin1(), attr.value()); attr = attr.nextSibling().toAttr(); } //update format version information uint ver = 1; //the default if (form->headerProperties()->contains("version")) { bool ok; uint v = (*form->headerProperties())["version"].toUInt(&ok); if (ok) ver = v; } kdDebug() << "FormIO::loadFormFromDom(): original format version: " << ver << endl; form->setOriginalFormatVersion( ver ); if (ver < KFormDesigner::version()) { //! @todo We can either 1) convert from old format and later save in a new one or 2) keep old format. //! To do this we may need to look at the original format version number. kdDebug() << "FormIO::loadFormFromDom(): original format is older than current: " << KFormDesigner::version() << endl; form->setFormatVersion( KFormDesigner::version() ); } else form->setFormatVersion( ver ); if (ver > KFormDesigner::version()) { //! @todo display information about too new format and that "some information will not be available". kdDebug() << "FormIO::loadFormFromDom(): original format is newer than current: " << KFormDesigner::version() << endl; } // Load the pixmap collection m_savePixmapsInline = ( (ui.namedItem("pixmapinproject").isNull()) || (!ui.namedItem("images").isNull()) ); form->pixmapCollection()->load(ui.namedItem("collection")); TQDomElement element = ui.namedItem("widget").toElement(); createToplevelWidget(form, container, element); // Loading the tabstops TQDomElement tabStops = ui.namedItem("tabstops").toElement(); // if(tabStops.isNull()) // return 1; if(!tabStops.isNull()) { int i = 0; uint itemsNotFound = 0; for(TQDomNode n = tabStops.firstChild(); !n.isNull(); n = n.nextSibling(), i++) { TQString name = n.toElement().text(); ObjectTreeItem *item = form->objectTree()->lookup(name); if(!item) { kdDebug() << "FormIO::loadFormFromDom ERROR : no ObjectTreeItem " << endl; continue; } const int index = form->tabStops()->findRef(item); /* Compute a real destination index: "a number of not found items so far". */ const int realIndex = i - itemsNotFound; if((index != -1) && (index != realIndex)) // the widget is not in the same place, so we move it { form->tabStops()->remove(item); form->tabStops()->insert(realIndex, item); } if(index == -1) { itemsNotFound++; kdDebug() << "FormIO: item '" << name << "' not in list" << endl; } } } // Load the form connections form->connectionBuffer()->load(ui.namedItem("connections")); m_currentForm = 0; m_currentItem = 0; return true; } ///////////////////////////////////////////////////////////////////////////// ///////////// Functions to save/load properties ///////////////////////////// ///////////////////////////////////////////////////////////////////////////// void FormIO::savePropertyValue(TQDomElement &parentNode, TQDomDocument &parent, const char *name, const TQVariant &value, TQWidget *w, WidgetLibrary *lib) { // Widget specific properties and attributes /////////////// // kdDebug() << "FormIO::savePropertyValue() Saving the property: " << name << endl; WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast(w); TQWidget *subwidget = w; bool addSubwidgetFlag = false; int propertyId = w->metaObject()->findProperty(name, true); if (propertyId == -1 && subpropIface && subpropIface->subwidget()) { // try property from subwidget subwidget = subpropIface->subwidget(); propertyId = subpropIface->subwidget()->metaObject()->findProperty(name, true); addSubwidgetFlag = true; } if(propertyId == -1) { kdDebug() << "FormIO::savePropertyValue() The object doesn't have this property. Let's try the WidgetLibrary." << endl; if(lib) lib->saveSpecialProperty(w->className(), name, value, w, parentNode, parent); return; } const TQMetaProperty *meta = subwidget->metaObject()->property(propertyId, true); if (!meta->stored( subwidget )) //not storable return; TQDomElement propertyE = parent.createElement("property"); propertyE.setAttribute("name", name); if (addSubwidgetFlag) propertyE.setAttribute("subwidget", "true"); if(meta && meta->isEnumType()) { // this property is enum or set type TQDomElement type; TQDomText valueE; if(meta->isSetType()) { TQStringList list = TQStringList::fromStrList(meta->valueToKeys(value.toInt())); type = parent.createElement("set"); valueE = parent.createTextNode(list.join("|")); type.appendChild(valueE); } else { TQString s = meta->valueToKey(value.toInt()); type = parent.createElement("enum"); valueE = parent.createTextNode(s); type.appendChild(valueE); } propertyE.appendChild(type); parentNode.appendChild(propertyE); return; } if(value.type() == TQVariant::Pixmap) { TQDomText valueE; TQDomElement type = parent.createElement("pixmap"); TQCString property = propertyE.attribute("name").latin1(); //todo TQCString pixmapName = m_currentItem->widget()->property("pixmapName").toCString(); if(m_savePixmapsInline /* (js)too risky: || m_currentItem->pixmapName(property).isNull() */) valueE = parent.createTextNode(saveImage(parent, value.toPixmap())); else valueE = parent.createTextNode(m_currentItem->pixmapName(property)); type.appendChild(valueE); propertyE.appendChild(type); parentNode.appendChild(propertyE); return; } // Saving a "normal" property writeVariant(parent, propertyE, value); parentNode.appendChild(propertyE); } void FormIO::writeVariant(TQDomDocument &parent, TQDomElement &parentNode, TQVariant value) { TQDomElement type; TQDomText valueE; switch(value.type()) { case TQVariant::String: { type = parent.createElement("string"); valueE = parent.createTextNode(value.toString()); type.appendChild(valueE); break; } case TQVariant::CString: { type = parent.createElement("cstring"); valueE = parent.createTextNode(value.toString()); type.appendChild(valueE); break; } case TQVariant::Rect: { type = parent.createElement("rect"); TQDomElement x = parent.createElement("x"); TQDomElement y = parent.createElement("y"); TQDomElement w = parent.createElement("width"); TQDomElement h = parent.createElement("height"); TQDomText valueX = parent.createTextNode(TQString::number(value.toRect().x())); TQDomText valueY = parent.createTextNode(TQString::number(value.toRect().y())); TQDomText valueW = parent.createTextNode(TQString::number(value.toRect().width())); TQDomText valueH = parent.createTextNode(TQString::number(value.toRect().height())); x.appendChild(valueX); y.appendChild(valueY); w.appendChild(valueW); h.appendChild(valueH); type.appendChild(x); type.appendChild(y); type.appendChild(w); type.appendChild(h); break; } case TQVariant::Color: { type = parent.createElement("color"); TQDomElement r = parent.createElement("red"); TQDomElement g = parent.createElement("green"); TQDomElement b = parent.createElement("blue"); TQDomText valueR = parent.createTextNode(TQString::number(value.toColor().red())); TQDomText valueG = parent.createTextNode(TQString::number(value.toColor().green())); TQDomText valueB = parent.createTextNode(TQString::number(value.toColor().blue())); r.appendChild(valueR); g.appendChild(valueG); b.appendChild(valueB); type.appendChild(r); type.appendChild(g); type.appendChild(b); break; } case TQVariant::Bool: { type = parent.createElement("bool"); //valueE = parent.createTextNode(TQString::number(value.toBool())); valueE = parent.createTextNode(value.toBool() ? "true" : "false"); type.appendChild(valueE); break; } case TQVariant::Int: case TQVariant::UInt: { type = parent.createElement("number"); valueE = parent.createTextNode(TQString::number(value.toInt())); type.appendChild(valueE); break; } case TQVariant::Size: { type = parent.createElement("size"); TQDomElement w = parent.createElement("width"); TQDomElement h = parent.createElement("height"); TQDomText valueW = parent.createTextNode(TQString::number(value.toSize().width())); TQDomText valueH = parent.createTextNode(TQString::number(value.toSize().height())); w.appendChild(valueW); h.appendChild(valueH); type.appendChild(w); type.appendChild(h); break; } case TQVariant::Point: { type = parent.createElement("point"); TQDomElement x = parent.createElement("x"); TQDomElement y = parent.createElement("y"); TQDomText valueX = parent.createTextNode(TQString::number(value.toPoint().x())); TQDomText valueY = parent.createTextNode(TQString::number(value.toPoint().y())); x.appendChild(valueX); y.appendChild(valueY); type.appendChild(x); type.appendChild(y); break; } case TQVariant::Font: { type = parent.createElement("font"); TQDomElement f = parent.createElement("family"); TQDomElement p = parent.createElement("pointsize"); TQDomElement w = parent.createElement("weight"); TQDomElement b = parent.createElement("bold"); TQDomElement i = parent.createElement("italic"); TQDomElement u = parent.createElement("underline"); TQDomElement s = parent.createElement("strikeout"); TQDomText valueF = parent.createTextNode(value.toFont().family()); TQDomText valueP = parent.createTextNode(TQString::number(value.toFont().pointSize())); TQDomText valueW = parent.createTextNode(TQString::number(value.toFont().weight())); TQDomText valueB = parent.createTextNode(TQString::number(value.toFont().bold())); TQDomText valueI = parent.createTextNode(TQString::number(value.toFont().italic())); TQDomText valueU = parent.createTextNode(TQString::number(value.toFont().underline())); TQDomText valueS = parent.createTextNode(TQString::number(value.toFont().strikeOut())); f.appendChild(valueF); p.appendChild(valueP); w.appendChild(valueW); b.appendChild(valueB); i.appendChild(valueI); u.appendChild(valueU); s.appendChild(valueS); type.appendChild(f); type.appendChild(p); type.appendChild(w); type.appendChild(b); type.appendChild(i); type.appendChild(u); type.appendChild(s); break; } case TQVariant::Cursor: { type = parent.createElement("cursor"); valueE = parent.createTextNode(TQString::number(value.toCursor().shape())); type.appendChild(valueE); break; } case TQVariant::SizePolicy: { type = parent.createElement("sizepolicy"); TQDomElement h = parent.createElement("hsizetype"); TQDomElement v = parent.createElement("vsizetype"); TQDomElement hs = parent.createElement("horstretch"); TQDomElement vs = parent.createElement("verstretch"); TQDomText valueH = parent.createTextNode(TQString::number(value.toSizePolicy().horData())); TQDomText valueV = parent.createTextNode(TQString::number(value.toSizePolicy().verData())); TQDomText valueHS = parent.createTextNode(TQString::number(value.toSizePolicy().horStretch())); TQDomText valueVS = parent.createTextNode(TQString::number(value.toSizePolicy().verStretch())); h.appendChild(valueH); v.appendChild(valueV); hs.appendChild(valueHS); vs.appendChild(valueVS); type.appendChild(h); type.appendChild(v); type.appendChild(hs); type.appendChild(vs); break; } case TQVariant::Time: { type = parent.createElement("time"); TQDomElement h = parent.createElement("hour"); TQDomElement m = parent.createElement("minute"); TQDomElement s = parent.createElement("second"); TQDomText valueH = parent.createTextNode(TQString::number(value.toTime().hour())); TQDomText valueM = parent.createTextNode(TQString::number(value.toTime().minute())); TQDomText valueS = parent.createTextNode(TQString::number(value.toTime().second())); h.appendChild(valueH); m.appendChild(valueM); s.appendChild(valueS); type.appendChild(h); type.appendChild(m); type.appendChild(s); break; } case TQVariant::Date: { type = parent.createElement("date"); TQDomElement y = parent.createElement("year"); TQDomElement m = parent.createElement("month"); TQDomElement d = parent.createElement("day"); TQDomText valueY = parent.createTextNode(TQString::number(value.toDate().year())); TQDomText valueM = parent.createTextNode(TQString::number(value.toDate().month())); TQDomText valueD = parent.createTextNode(TQString::number(value.toDate().day())); y.appendChild(valueY); m.appendChild(valueM); d.appendChild(valueD); type.appendChild(y); type.appendChild(m); type.appendChild(d); break; } case TQVariant::DateTime: { type = parent.createElement("datetime"); TQDomElement h = parent.createElement("hour"); TQDomElement m = parent.createElement("minute"); TQDomElement s = parent.createElement("second"); TQDomElement y = parent.createElement("year"); TQDomElement mo = parent.createElement("month"); TQDomElement d = parent.createElement("day"); TQDomText valueH = parent.createTextNode(TQString::number(value.toDateTime().time().hour())); TQDomText valueM = parent.createTextNode(TQString::number(value.toDateTime().time().minute())); TQDomText valueS = parent.createTextNode(TQString::number(value.toDateTime().time().second())); TQDomText valueY = parent.createTextNode(TQString::number(value.toDateTime().date().year())); TQDomText valueMo = parent.createTextNode(TQString::number(value.toDateTime().date().month())); TQDomText valueD = parent.createTextNode(TQString::number(value.toDateTime().date().day())); h.appendChild(valueH); m.appendChild(valueM); s.appendChild(valueS); y.appendChild(valueY); mo.appendChild(valueMo); d.appendChild(valueD); type.appendChild(h); type.appendChild(m); type.appendChild(s); type.appendChild(y); type.appendChild(mo); type.appendChild(d); break; } default: break; } parentNode.appendChild(type); } void FormIO::savePropertyElement(TQDomElement &parentNode, TQDomDocument &domDoc, const TQString &tagName, const TQString &property, const TQVariant &value) { TQDomElement propertyE = domDoc.createElement(tagName); propertyE.setAttribute("name", property); writeVariant(domDoc, propertyE, value); parentNode.appendChild(propertyE); } TQVariant FormIO::readPropertyValue(TQDomNode node, TQObject *obj, const TQString &name) { TQDomElement tag = node.toElement(); TQString text = tag.text(); TQString type = tag.tagName(); if(type == "string" || type == "cstring") return text; else if(type == "rect") { TQDomElement x = node.namedItem("x").toElement(); TQDomElement y = node.namedItem("y").toElement(); TQDomElement w = node.namedItem("width").toElement(); TQDomElement h = node.namedItem("height").toElement(); int rx = x.text().toInt(); int ry = y.text().toInt(); int rw = w.text().toInt(); int rh = h.text().toInt(); return TQRect(rx, ry, rw, rh); } else if(type == "color") { TQDomElement r = node.namedItem("red").toElement(); TQDomElement g = node.namedItem("green").toElement(); TQDomElement b = node.namedItem("blue").toElement(); int red = r.text().toInt(); int green = g.text().toInt(); int blue = b.text().toInt(); return TQColor(red, green, blue); } else if(type == "bool") { if(text == "true") return TQVariant(true, 3); else if(text == "false") return TQVariant(false, 3); return TQVariant(text.toInt(), 3); } else if(type == "number") { return text.toInt(); } else if(type == "size") { TQDomElement w = node.namedItem("width").toElement(); TQDomElement h = node.namedItem("height").toElement(); return TQSize(w.text().toInt(), h.text().toInt()); } else if(type == "point") { TQDomElement x = node.namedItem("x").toElement(); TQDomElement y = node.namedItem("y").toElement(); return TQPoint(x.text().toInt(), y.text().toInt()); } else if(type == "font") { TQDomElement fa = node.namedItem("family").toElement(); TQDomElement p = node.namedItem("pointsize").toElement(); TQDomElement w = node.namedItem("weight").toElement(); TQDomElement b = node.namedItem("bold").toElement(); TQDomElement i = node.namedItem("italic").toElement(); TQDomElement u = node.namedItem("underline").toElement(); TQDomElement s = node.namedItem("strikeout").toElement(); TQFont f; f.setFamily(fa.text()); f.setPointSize(p.text().toInt()); f.setWeight(w.text().toInt()); f.setBold(b.text().toInt()); f.setItalic(i.text().toInt()); f.setUnderline(u.text().toInt()); f.setStrikeOut(s.text().toInt()); return f; } else if(type == "cursor") { return TQCursor(text.toInt()); } else if(type == "time") { TQDomElement h = node.namedItem("hour").toElement(); TQDomElement m = node.namedItem("minute").toElement(); TQDomElement s = node.namedItem("second").toElement(); return TQTime(h.text().toInt(), m.text().toInt(), s.text().toInt()); } else if(type == "date") { TQDomElement y = node.namedItem("year").toElement(); TQDomElement m = node.namedItem("month").toElement(); TQDomElement d = node.namedItem("day").toElement(); return TQDate(y.text().toInt(), m.text().toInt(), d.text().toInt()); } else if(type == "datetime") { TQDomElement h = node.namedItem("hour").toElement(); TQDomElement m = node.namedItem("minute").toElement(); TQDomElement s = node.namedItem("second").toElement(); TQDomElement y = node.namedItem("year").toElement(); TQDomElement mo = node.namedItem("month").toElement(); TQDomElement d = node.namedItem("day").toElement(); TQTime t(h.text().toInt(), m.text().toInt(), s.text().toInt()); TQDate da(y.text().toInt(), mo.text().toInt(), d.text().toInt()); return TQDateTime(da, t); } else if(type == "sizepolicy") { TQDomElement h = node.namedItem("hsizetype").toElement(); TQDomElement v = node.namedItem("vsizetype").toElement(); TQDomElement hs = node.namedItem("horstretch").toElement(); TQDomElement vs = node.namedItem("verstretch").toElement(); TQSizePolicy s; s.setHorData((TQSizePolicy::SizeType)h.text().toInt()); s.setVerData((TQSizePolicy::SizeType)v.text().toInt()); s.setHorStretch(hs.text().toInt()); s.setVerStretch(vs.text().toInt()); return s; } else if(type == "pixmap") { if(m_savePixmapsInline || !m_currentForm || !m_currentItem || !m_currentForm->pixmapCollection()->contains(text)) return loadImage(tag.ownerDocument(), text); else { m_currentItem->setPixmapName(name.latin1(), text); return m_currentForm->pixmapCollection()->getPixmap(text); } return TQVariant(TQPixmap()); } else if(type == "enum") return text; else if(type == "set") { WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast(obj); TQObject *subobject = (subpropIface && subpropIface->subwidget()) ? TQT_TQOBJECT(subpropIface->subwidget()) : obj; const int count = subobject->metaObject()->findProperty(name.latin1(), true); const TQMetaProperty *meta = count!=-1 ? subobject->metaObject()->property(count, true) : 0; if (meta) { if (meta->isSetType()) { TQStrList keys; const TQStringList list( TQStringList::split("|", text) ); for (TQStringList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it) keys.append((*it).latin1()); return meta->keysToValue(keys); } } else { // Metaproperty not found, probably because subwidget is not created. // We will return a string list here with hope that names will // be resolved and translated into an integer value later when subwidget is created, // e.g. near KexiFormView::updateValuesForSubproperties() return TQStringList::split("|", text); } } return TQVariant(); } ///////////////////////////////////////////////////////////////////////////// ///////////// Functions to save/load widgets //////////////////////////////// ///////////////////////////////////////////////////////////////////////////// void FormIO::saveWidget(ObjectTreeItem *item, TQDomElement &parent, TQDomDocument &domDoc, bool insideGridLayout) { if (!item) return; bool savedAlignment = false; // we let Spring class handle saving itself if(item->className() == "Spring") { Spring::saveSpring(item, parent, domDoc, insideGridLayout); return; } bool resetCurrentForm = false; m_currentItem = item; if(!m_currentForm) // copying widget { resetCurrentForm = true; m_currentForm = item->container() ? item->container()->form() : item->parent()->container()->form(); } WidgetLibrary *lib = m_currentForm->library(); // if(item->container()) // lib = item->container()->form()->manager()->lib(); // else // lib = item->parent()->container()->form()->manager()->lib(); // We create the "widget" element TQDomElement tclass = domDoc.createElement("widget"); parent.appendChild(tclass); if(insideGridLayout) { tclass.setAttribute("row", item->gridRow()); tclass.setAttribute("column", item->gridCol()); if(item->spanMultipleCells()) { tclass.setAttribute("rowspan", item->gridRowSpan()); tclass.setAttribute("colspan", item->gridColSpan()); } } if(!item->parent()) // Toplevel widget tclass.setAttribute("class", TQWIDGET_OBJECT_NAME_STRING); // For compatibility, HBox, VBox and Grid are saved as TQLAYOUTWIDGET_OBJECT_NAME_STRING else if(item->widget()->isA("HBox") || item->widget()->isA("VBox") || item->widget()->isA("Grid") || item->widget()->isA("HFlow") || item->widget()->isA("VFlow")) tclass.setAttribute("class", TQLAYOUTWIDGET_OBJECT_NAME_STRING); else if(item->widget()->isA("CustomWidget")) tclass.setAttribute("class", item->className()); else // Normal widgets tclass.setAttribute("class", lib->savingName(item->widget()->className()) ); savePropertyValue(tclass, domDoc, "name", item->widget()->property("name"), item->widget()); // Important: save dataSource property FIRST before properties like "alignment" // - needed when subproperties are defined after subwidget creation, and subwidget is created after setting "dataSource" // (this is the case for KexiDBAutoField) //! @todo more properties like "dataSource" may needed here... // if (-1 != item->widget()->metaObject()->findProperty("dataSource")) // savePropertyValue(tclass, domDoc, "dataSource", item->widget()->property("dataSource"), item->widget()); // We don't want to save the geometry if the widget is inside a tqlayout (so parent.tagName() == "grid" for example) if(item && !item->parent()) { // save form widget size, but not its position savePropertyValue(tclass, domDoc, "geometry", TQRect( TQPoint(0,0), item->widget()->size()), item->widget()); } // normal widget (if == "UI', it means we're copying widget) else if(parent.tagName() == "widget" || parent.tagName() == "UI") savePropertyValue(tclass, domDoc, "geometry", item->widget()->property("geometry"), item->widget()); // Save the buddy widget for a label if(item->widget()->inherits(TQLABEL_OBJECT_NAME_STRING) && ((TQLabel*)item->widget())->buddy()) savePropertyElement(tclass, domDoc, "property", "buddy", ((TQLabel*)item->widget())->buddy()->name()); // We save every property in the modifProp list of the ObjectTreeItem TQVariantMap *map = new TQVariantMap( *(item->modifiedProperties()) ); TQMap::ConstIterator endIt = map->constEnd(); for(TQMap::ConstIterator it = map->constBegin(); it != endIt; ++it) { const TQCString name( it.key().latin1() ); if(name == "hAlign" || name == "vAlign" || name == "wordbreak" || name == "alignment") { if(!savedAlignment) // not to save it twice { savePropertyValue(tclass, domDoc, "alignment", item->widget()->property("alignment"), item->widget()); savedAlignment = true; } } else if(name == "name" || name == "geometry" || name == "tqlayout") { // these have already been saved } else { savePropertyValue(tclass, domDoc, it.key().latin1(), item->widget()->property(it.key().latin1()), item->widget(), lib); } } delete map; if(item->widget()->isA("CustomWidget")) { TQDomDocument doc("TEMP"); doc.setContent(item->m_unknownProps); for(TQDomNode n = doc.firstChild(); !n.isNull(); n = n.nextSibling()) { tclass.appendChild(n.cloneNode()); } } // Saving container 's tqlayout if there is one TQDomElement tqlayout; if(item->container() && item->container()->layoutType() != Container::NoLayout) { if(item->container()->tqlayout()) // there is a tqlayout { tqlayout = domDoc.createElement("temp"); savePropertyValue(tqlayout, domDoc, "name", "unnamed", item->widget()); if(item->modifiedProperties()->contains("layoutMargin")) savePropertyElement(tqlayout, domDoc, "property", "margin", item->container()->layoutMargin()); if(item->modifiedProperties()->contains("layoutSpacing")) savePropertyElement(tqlayout, domDoc, "property", "spacing", item->container()->layoutSpacing()); tclass.appendChild(tqlayout); } } int layoutType = item->container() ? item->container()->layoutType() : Container::NoLayout; switch(layoutType) { case Container::Grid: // grid tqlayout { tqlayout.setTagName("grid"); for(ObjectTreeItem *objIt = item->children()->first(); objIt; objIt = item->children()->next()) saveWidget(objIt, tqlayout, domDoc, true); break; } case Container::HBox: case Container::VBox: { // as we don't save geometry, we need to sort widgets in the right order, not creation order WidgetList *list; if(tqlayout.tagName() == "hbox") { list = new HorWidgetList(item->container()->form()->toplevelContainer()->widget()); tqlayout.setTagName("hbox"); } else { list = new VerWidgetList(item->container()->form()->toplevelContainer()->widget()); tqlayout.setTagName("vbox"); } for(ObjectTreeItem *objTree = item->children()->first(); objTree; objTree = item->children()->next()) list->append(objTree->widget()); list->sort(); for(TQWidget *obj = list->first(); obj; obj = list->next()) { ObjectTreeItem *titem = item->container()->form()->objectTree()->lookup(obj->name()); if(item) saveWidget(titem, tqlayout, domDoc); } delete list; break; } case Container::HFlow: case Container::VFlow: { tqlayout.setTagName("grid"); KexiFlowLayout *flow = static_cast(item->container()->tqlayout()); if(!flow) break; WidgetList *list = (WidgetList*)flow->widgetList(); // save some special properties savePropertyElement(tqlayout, domDoc, "property", "customLayout", Container::layoutTypeToString(item->container()->layoutType()) ); savePropertyElement(tqlayout, domDoc, "property", "justify", TQVariant(static_cast(item->container()->tqlayout())->isJustified(), 3) ); // fill the widget's grid info, ie just simulate grid tqlayout item->container()->createGridLayout(true); for(TQWidget *obj = list->first(); obj; obj = list->next()) { ObjectTreeItem *titem = item->container()->form()->objectTree()->lookup(obj->name()); if(item) saveWidget(titem, tqlayout, domDoc, true); // save grid info for compatibility with TQtDesigner } delete list; break; } default: { for(ObjectTreeItem *objIt = item->children()->first(); objIt; objIt = item->children()->next()) saveWidget(objIt, tclass, domDoc); } } addIncludeFileName(lib->includeFileName(item->widget()->className()), domDoc); if(resetCurrentForm) m_currentForm = 0; m_currentItem = 0; } void FormIO::cleanClipboard(TQDomElement &uiElement) { // remove includehints element not needed if(!uiElement.namedItem("includehints").isNull()) uiElement.removeChild(uiElement.namedItem("includehints")); // and ensure images and connection are at the end if(!uiElement.namedItem("connections").isNull()) uiElement.insertAfter(uiElement.namedItem("connections"), TQDomNode()); if(!uiElement.namedItem("images").isNull()) uiElement.insertAfter(uiElement.namedItem("images"), TQDomNode()); } void FormIO::loadWidget(Container *container, const TQDomElement &el, TQWidget *parent) { bool resetCurrentForm = false; if(!m_currentForm) // pasting widget { resetCurrentForm = true; m_currentForm = container->form(); } // We first look for the widget's name TQString wname; for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling()) { if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "name")) { wname = n.toElement().text(); break; } } TQWidget *w; TQCString classname, alternate; // We translate some name (for compatibility) if(el.tagName() == "spacer") classname = "Spring"; else if(el.attribute("class") == TQLAYOUTWIDGET_OBJECT_NAME_STRING) { for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling()) { TQString tagName = n.toElement().tagName(); if(tagName == "property") continue; if(tagName == "hbox") classname = "HBox"; else if(tagName == "vbox") classname = "VBox"; else if(tagName == "grid") { // first, see if it is flow tqlayout for(TQDomNode child = n.firstChild(); !child.isNull(); child = child.nextSibling()) { if((child.toElement().tagName() == "property") && (child.toElement().attribute("name") == "customLayout")) { classname = child.toElement().text().latin1(); break; } } if(classname.isEmpty()) // normal grid classname = "Grid"; } } } else // We check if this classname is an alternate one, and replace it if necessary { classname = el.attribute("class").latin1(); alternate = container->form()->library()->classNameForAlternate(classname); } if(alternate == "CustomWidget") w = new CustomWidget(classname, container->widget(), wname.latin1()); else { if(!alternate.isNull()) classname = alternate; int widgetOptions = WidgetFactory::DefaultOptions; if (!container->form()->designMode()) { widgetOptions ^= WidgetFactory::DesignViewMode; } if(!parent) w = container->form()->library()->createWidget(classname, container->widget(), wname.latin1(), container, widgetOptions); else w = container->form()->library()->createWidget(classname, parent, wname.latin1(), container, widgetOptions); } if(!w) return; #if KDE_VERSION >= KDE_MAKE_VERSION(3,4,0) //! @todo allow setting this for data view mode as well if (m_currentForm->designMode()) { //don't generate accelerators for widgets in design mode KAcceleratorManager::setNoAccel(w); } #endif w->setStyle(&(container->widget()->tqstyle())); w->show(); // We create and insert the ObjectTreeItem at the good place in the ObjectTree ObjectTreeItem *item = container->form()->objectTree()->lookup(wname); if (!item) { // not yet created item = new ObjectTreeItem(container->form()->library()->displayName(classname), wname, w, container); if(parent) { ObjectTreeItem *titem = container->form()->objectTree()->lookup(parent->name()); if(titem) container->form()->objectTree()->addItem(titem, item); else kdDebug() << "FORMIO :: ERROR no parent widget " << endl; } else container->form()->objectTree()->addItem(container->objectTree(), item); } //assign item for its widget if it supports DesignTimeDynamicChildWidgetHandler interface //(e.g. KexiDBAutoField) if (container->form()->designMode() && dynamic_cast(w)) { dynamic_cast(w)->assignItem(item); } m_currentItem = item; // if we are inside a Grid, we need to insert the widget in the good cell if(container->layoutType() == Container::Grid) { TQGridLayout *tqlayout = (TQGridLayout*)container->tqlayout(); if(el.hasAttribute("rowspan")) { // widget spans multiple cells if(tqlayout) tqlayout->addMultiCellWidget(w, el.attribute("row").toInt(), el.attribute("row").toInt() + el.attribute("rowspan").toInt()-1, el.attribute("column").toInt(), el.attribute("column").toInt() + el.attribute("colspan").toInt()-1); item->setGridPos(el.attribute("row").toInt(), el.attribute("column").toInt(), el.attribute("rowspan").toInt(), el.attribute("colspan").toInt()); } else { if(tqlayout) tqlayout->addWidget(w, el.attribute("row").toInt(), el.attribute("column").toInt()); item->setGridPos(el.attribute("row").toInt(), el.attribute("column").toInt(), 0, 0); } } else if(container->tqlayout()) container->tqlayout()->add(w); readChildNodes(item, container, el, w); if(item->container() && item->container()->tqlayout()) item->container()->tqlayout()->activate(); // We add the autoSaveProperties in the modifProp list of the ObjectTreeItem, so that they are saved later TQValueList list(container->form()->library()->autoSaveProperties(w->className())); TQValueList::ConstIterator endIt = list.constEnd(); KFormDesigner::WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast(w); TQWidget *subwidget = (subpropIface && subpropIface->subwidget()) ? subpropIface->subwidget() : w; for(TQValueList::ConstIterator it = list.constBegin(); it != endIt; ++it) { if(subwidget->metaObject()->findProperty(*it, true) != -1) item->addModifiedProperty(*it, subwidget->property(*it)); } if(resetCurrentForm) m_currentForm = 0; m_currentItem = 0; } void FormIO::createToplevelWidget(Form *form, TQWidget *container, TQDomElement &el) { // We first look for the widget's name TQString wname; for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling()) { if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "name")) { wname = n.toElement().text(); break; } } // And rename the widget and its ObjectTreeItem container->setName(wname.latin1()); if(form->objectTree()) form->objectTree()->rename(form->objectTree()->name(), wname); form->setInteractiveMode(false); TQDict *oldBuddies = 0; if(m_buddies) // save old buddies (for subforms) oldBuddies = m_buddies; m_buddies = new TQDict(); m_currentItem = form->objectTree(); readChildNodes(form->objectTree(), form->toplevelContainer(), el, container); // Now the Form is fully loaded, we can assign the buddies TQDictIterator it(*m_buddies); for(; it.current(); ++it) { ObjectTreeItem *item = form->objectTree()->lookup(it.currentKey()); if(!item || !item->widget()) { kdDebug() << "Cannot assign buddy for widget " << it.current()->name() << " to " << it.currentKey() << endl; continue; } it.current()->setBuddy(item->widget()); } delete m_buddies; m_buddies = oldBuddies; // and restore it m_currentItem = 0; form->setInteractiveMode(true); } void FormIO::readChildNodes(ObjectTreeItem *item, Container *container, const TQDomElement &el, TQWidget *w) { TQString eltag = el.tagName(); WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast(w); TQWidget *subwidget = (subpropIface && subpropIface->subwidget()) ? subpropIface->subwidget() : w; for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling()) { TQString tag = n.toElement().tagName(); TQDomElement node = n.toElement(); if((tag == "property") || (tag == "attribute")) { TQString name = node.attribute("name"); //if(name == "geometry") // hasGeometryProp = true; if( ((eltag == "grid") || (eltag == "hbox") || (eltag == "vbox")) && (name == "name")) // we don't care about tqlayout names continue; if (node.attribute("subwidget")=="true") { //this is property for subwidget: remember it for delayed setting //because now the subwidget could be not created yet (true e.g. for KexiDBAutoField) const TQVariant val( readPropertyValue(node.firstChild(), TQT_TQOBJECT(w), name) ); kdDebug() << val.toStringList() << endl; item->addSubproperty( name.latin1(), val ); //subwidget->setProperty(name.latin1(), val); item->addModifiedProperty( name.latin1(), val ); continue; } // We cannot assign the buddy now as the buddy widget may not be created yet if(name == "buddy") m_buddies->insert(readPropertyValue(node.firstChild(), TQT_TQOBJECT(w), name).toString(), (TQLabel*)w); else if(((eltag == "grid") || (eltag == "hbox") || (eltag == "vbox")) && item->container() && item->container()->tqlayout()) { // We load the margin of a Layout if(name == "margin") { int margin = readPropertyValue(node.firstChild(), TQT_TQOBJECT(w), name).toInt(); item->container()->setLayoutMargin(margin); item->container()->tqlayout()->setMargin(margin); } // We load the spacing of a Layout else if(name == "spacing") { int spacing = readPropertyValue(node.firstChild(), TQT_TQOBJECT(w), name).toInt(); item->container()->setLayoutSpacing(spacing); item->container()->tqlayout()->setSpacing(spacing); } else if((name == "justify")){ bool justify = readPropertyValue(node.firstChild(), TQT_TQOBJECT(w), name).toBool(); KexiFlowLayout *flow = static_cast(item->container()->tqlayout()); if(flow) flow->setJustified(justify); } } // If the object doesn't have this property, we let the Factory handle it (maybe a special property) else if(subwidget->metaObject()->findProperty(name.latin1(), true) == -1) { if(w->className() == TQString::fromLatin1("CustomWidget")) item->storeUnknownProperty(node); else { bool read = container->form()->library()->readSpecialProperty( w->className(), node, w, item); if(!read) // the factory doesn't support this property neither item->storeUnknownProperty(node); } } else // we have a normal property, let's load it { TQVariant val( readPropertyValue(node.firstChild(), TQT_TQOBJECT(w), name) ); if(name == "geometry" && dynamic_cast(w)) { //fix geometry if needed - this is top level form widget TQRect r( val.toRect() ); if (r.left()<0) //negative X! r.moveLeft(0); if (r.top()<0) //negative Y! r.moveTop(0); val = r; } subwidget->setProperty(name.latin1(), val); // int count = w->metaObject()->findProperty(name, true); // const TQMetaProperty *meta = w->metaObject()->property(count, true); // if(meta && meta->isEnumType()) { // val = w->property(name.latin1()); //update: we want a numeric value of enum // } item->addModifiedProperty(name.latin1(), val); } } else if(tag == "widget") // a child widget { if(item->container()) // we are a Container loadWidget(item->container(), node); else loadWidget(container, node, w); } else if(tag == "spacer") { loadWidget(container, node, w); } else if(tag == "grid") { // first, see if it is flow tqlayout TQString layoutName; for(TQDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) { if((child.toElement().tagName() == "property") && (child.toElement().attribute("name") == "customLayout")) { layoutName = child.toElement().text(); break; } } if(layoutName == "HFlow") { item->container()->m_layType = Container::HFlow; KexiFlowLayout *tqlayout = new KexiFlowLayout(item->widget()); tqlayout->setOrientation(Qt::Horizontal); item->container()->m_layout = (TQLayout*)tqlayout; } else if(layoutName == "VFlow") { item->container()->m_layType = Container::VFlow; KexiFlowLayout *tqlayout = new KexiFlowLayout(item->widget()); tqlayout->setOrientation(Qt::Vertical); item->container()->m_layout = (TQLayout*)tqlayout; } else { // grid tqlayout item->container()->m_layType = Container::Grid; TQGridLayout *tqlayout = new TQGridLayout(item->widget(), 1, 1); item->container()->m_layout = (TQLayout*)tqlayout; } readChildNodes(item, container, node, w); } else if(tag == "vbox") { item->container()->m_layType = Container::VBox; TQVBoxLayout *tqlayout = new TQVBoxLayout(item->widget()); item->container()->m_layout = (TQLayout*)tqlayout; readChildNodes(item, container, node, w); } else if(tag == "hbox") { item->container()->m_layType = Container::HBox; TQHBoxLayout *tqlayout = new TQHBoxLayout(item->widget()); item->container()->m_layout = (TQLayout*)tqlayout; readChildNodes(item, container, node, w); } else {// unknown tag, we let the Factory handle it if(w->className() == TQString::fromLatin1("CustomWidget")) item->storeUnknownProperty(node); else { bool read = container->form()->library()->readSpecialProperty( w->className(), node, w, item); if(!read) // the factory doesn't suport this property neither item->storeUnknownProperty(node); } } } } ///////////////////////////////////////////////////////////////////////////// ///////////// Helper functions ////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// void FormIO::addIncludeFileName(const TQString &include, TQDomDocument &domDoc) { if(include.isEmpty()) return; TQDomElement includes; TQDomElement uiEl = domDoc.namedItem("UI").toElement(); if(uiEl.namedItem("includehints").isNull()) { includes = domDoc.createElement("includehints"); uiEl.appendChild(includes); } else includes = uiEl.namedItem("includehints").toElement(); // Check if this include has already been saved, and return if it is the case for(TQDomNode n = includes.firstChild(); !n.isNull(); n = n.nextSibling()) { if(n.toElement().text() == include) return; } TQDomElement includeHint = domDoc.createElement("includehint"); includes.appendChild(includeHint); TQDomText includeText = domDoc.createTextNode(include); includeHint.appendChild(includeText); } //////// TQt Designer code: these two functions were copied (and adapted) from TQt Designer for compatibility //////// TQString FormIO::saveImage(TQDomDocument &domDoc, const TQPixmap &pixmap) { TQDomNode node = domDoc.namedItem("images"); TQDomElement images; if(node.isNull()) { images = domDoc.createElement("images"); TQDomElement ui = domDoc.namedItem("UI").toElement(); ui.appendChild(images); } else images = node.toElement(); int count = images.childNodes().count(); TQDomElement image = domDoc.createElement("image"); TQString name = "image" + TQString::number(count); image.setAttribute("name", name); TQImage img = pixmap.convertToImage(); TQByteArray ba; TQBuffer buf(ba); buf.open( IO_WriteOnly | IO_Translate ); TQString format = img.depth() > 1 ? "XPM" : "XBM"; TQImageIO iio( &buf, format.latin1() ); iio.setImage( img ); iio.write(); buf.close(); TQByteArray bazip = tqCompress( ba ); ulong len = bazip.size(); TQDomElement data = domDoc.createElement("data"); data.setAttribute("format", format + ".GZ"); data.setAttribute("length", ba.size()); static const char hexchars[] = "0123456789abcdef"; TQString content; for(int i = 4; i < (int)len; ++i) { uchar s = (uchar) bazip[i]; content += hexchars[s >> 4]; content += hexchars[s & 0x0f]; } TQDomText text = domDoc.createTextNode(content); data.appendChild(text); image.appendChild(data); images.appendChild(image); return name; } TQPixmap FormIO::loadImage(TQDomDocument domDoc, const TQString& name) { TQDomElement images = domDoc.namedItem("UI").namedItem("images").toElement(); if(images.isNull()) return 0; TQDomElement image; for(TQDomNode n = images.firstChild(); !n.isNull(); n = n.nextSibling()) { if((n.toElement().tagName() == "image") && (n.toElement().attribute("name") == name)) { image = n.toElement(); break; } } TQPixmap pix; TQString data = image.namedItem("data").toElement().text(); const int lengthOffset = 4; int baSize = data.length() / 2 + lengthOffset; uchar *ba = new uchar[baSize]; for(int i = lengthOffset; i < baSize; ++i) { char h = data[2 * (i-lengthOffset)].latin1(); char l = data[2 * (i-lengthOffset) + 1].latin1(); uchar r = 0; if(h <= '9') r += h - '0'; else r += h - 'a' + 10; r = r << 4; if(l <= '9') r += l - '0'; else r += l - 'a' + 10; ba[i] = r; } TQString format = image.namedItem("data").toElement().attribute("format", "PNG"); if((format == "XPM.GZ") || (format == "XBM.GZ")) { ulong len = image.attribute("length").toULong(); if(len < data.length() * 5) len = data.length() * 5; // tqUncompress() expects the first 4 bytes to be the expected length of // the uncompressed data ba[0] = ( len & 0xff000000 ) >> 24; ba[1] = ( len & 0x00ff0000 ) >> 16; ba[2] = ( len & 0x0000ff00 ) >> 8; ba[3] = ( len & 0x000000ff ); TQByteArray baunzip = tqUncompress(ba, baSize); pix.loadFromData( (const uchar*)baunzip.data(), baunzip.size(), format.left(format.find('.')).latin1() ); } else pix.loadFromData( (const uchar*)ba+lengthOffset, baSize-lengthOffset, format.latin1() ); delete[] ba; return pix; } //////// End of TQt Designer code //////////////////////////////////////////////////////// #include "formIO.moc"