1 /***************************************************************************
2 titledocument.h - description
5 copyright : (C) 2008 by Marco Gittler
6 email : g.marco@freenet.de
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 ***************************************************************************/
18 #include "titledocument.h"
21 #include <KTemporaryFile>
22 #include <kio/netaccess.h>
23 #include <KApplication>
25 #include <KMessageBox>
27 #include <QGraphicsScene>
28 #include <QDomElement>
29 #include <QGraphicsItem>
30 #include <QGraphicsRectItem>
31 #include <QGraphicsTextItem>
32 #include <QGraphicsSvgItem>
35 #include <QTextCursor>
38 TitleDocument::TitleDocument()
43 void TitleDocument::setScene(QGraphicsScene* _scene)
48 QDomDocument TitleDocument::xml(QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv)
52 QDomElement main = doc.createElement("kdenlivetitle");
53 doc.appendChild(main);
55 foreach(QGraphicsItem* item, m_scene->items()) {
56 QDomElement e = doc.createElement("item");
57 QDomElement content = doc.createElement("content");
61 switch (item->type()) {
63 e.setAttribute("type", "QGraphicsPixmapItem");
64 content.setAttribute("url", item->data(Qt::UserRole).toString());
67 e.setAttribute("type", "QGraphicsSvgItem");
68 content.setAttribute("url", item->data(Qt::UserRole).toString());
71 e.setAttribute("type", "QGraphicsRectItem");
72 content.setAttribute("rect", rectFToString(((QGraphicsRectItem*)item)->rect().normalized()));
73 content.setAttribute("pencolor", colorToString(((QGraphicsRectItem*)item)->pen().color()));
74 content.setAttribute("penwidth", ((QGraphicsRectItem*)item)->pen().width());
75 content.setAttribute("brushcolor", colorToString(((QGraphicsRectItem*)item)->brush().color()));
78 e.setAttribute("type", "QGraphicsTextItem");
79 t = static_cast<QGraphicsTextItem *>(item);
80 // Don't save empty text nodes
81 if (t->toPlainText().simplified().isEmpty()) continue;
82 //content.appendChild(doc.createTextNode(((QGraphicsTextItem*)item)->toHtml()));
83 content.appendChild(doc.createTextNode(t->toPlainText()));
85 content.setAttribute("font", font.family());
86 content.setAttribute("font-weight", font.weight());
87 content.setAttribute("font-pixel-size", font.pixelSize());
88 content.setAttribute("font-italic", font.italic());
89 content.setAttribute("font-underline", font.underline());
90 content.setAttribute("font-color", colorToString(t->defaultTextColor()));
92 // Only save when necessary.
93 if (t->data(OriginXLeft).toInt() == AxisInverted) {
94 content.setAttribute("kdenlive-axis-x-inverted", t->data(OriginXLeft).toInt());
96 if (t->data(OriginYTop).toInt() == AxisInverted) {
97 content.setAttribute("kdenlive-axis-y-inverted", t->data(OriginYTop).toInt());
99 if (t->textWidth() != -1) {
100 content.setAttribute("alignment", t->textCursor().blockFormat().alignment());
106 QDomElement pos = doc.createElement("position");
107 pos.setAttribute("x", item->pos().x());
108 pos.setAttribute("y", item->pos().y());
109 QTransform transform = item->transform();
110 QDomElement tr = doc.createElement("transform");
111 tr.appendChild(doc.createTextNode(
112 QString("%1,%2,%3,%4,%5,%6,%7,%8,%9").arg(
113 transform.m11()).arg(transform.m12()).arg(transform.m13()).arg(transform.m21()).arg(transform.m22()).arg(transform.m23()).arg(transform.m31()).arg(transform.m32()).arg(transform.m33())
116 e.setAttribute("z-index", item->zValue());
121 e.appendChild(content);
122 if (item->zValue() > -1100) main.appendChild(e);
124 if (startv && endv) {
125 QDomElement endp = doc.createElement("endviewport");
126 QDomElement startp = doc.createElement("startviewport");
127 endp.setAttribute("x", endv->data(0).toString());
128 endp.setAttribute("y", endv->data(1).toString());
129 endp.setAttribute("size", endv->data(2).toString());
130 endp.setAttribute("rect", rectFToString(endv->boundingRect()));
132 startp.setAttribute("x", startv->data(0).toString());
133 startp.setAttribute("y", startv->data(1).toString());
134 startp.setAttribute("size", startv->data(2).toString());
135 startp.setAttribute("rect", rectFToString(startv->boundingRect()));
137 startp.setAttribute("z-index", startv->zValue());
138 endp.setAttribute("z-index", endv->zValue());
139 main.appendChild(startp);
140 main.appendChild(endp);
142 QDomElement backgr = doc.createElement("background");
143 QColor color = getBackgroundColor();
144 backgr.setAttribute("color", colorToString(color));
145 main.appendChild(backgr);
150 /** \brief Get the background color (incl. alpha) from the document, if possibly
151 * \returns The background color of the document, inclusive alpha. If none found, returns (0,0,0,0) */
152 QColor TitleDocument::getBackgroundColor()
154 QColor color(0, 0, 0, 0);
156 QList<QGraphicsItem *> items = m_scene->items();
157 for (int i = 0; i < items.size(); i++) {
158 if (items.at(i)->zValue() == -1100) {
159 color = ((QGraphicsRectItem *)items.at(i))->brush().color();
168 bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv)
173 QDomDocument doc = xml(startv, endv);
174 KTemporaryFile tmpfile;
175 if (!tmpfile.open()) {
176 kWarning() << "///// CANNOT CREATE TMP FILE in: " << tmpfile.fileName();
179 QFile xmlf(tmpfile.fileName());
180 xmlf.open(QIODevice::WriteOnly);
181 xmlf.write(doc.toString().toUtf8());
182 if (xmlf.error() != QFile::NoError) {
187 return KIO::NetAccess::upload(tmpfile.fileName(), url, 0);
190 int TitleDocument::loadDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv)
197 if (KIO::NetAccess::download(url, tmpfile, 0)) {
199 if (file.open(QIODevice::ReadOnly)) {
200 doc.setContent(&file, false);
204 KIO::NetAccess::removeTempFile(tmpfile);
205 return loadFromXml(doc, startv, endv);
210 int TitleDocument::loadFromXml(QDomDocument doc, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv)
212 QDomNodeList titles = doc.elementsByTagName("kdenlivetitle");
216 QDomNodeList items = titles.item(0).childNodes();
217 for (int i = 0; i < items.count(); i++) {
218 QGraphicsItem *gitem = NULL;
219 kDebug() << items.item(i).attributes().namedItem("type").nodeValue();
220 int zValue = items.item(i).attributes().namedItem("z-index").nodeValue().toInt();
221 if (zValue > -1000) {
222 if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsTextItem") {
223 QDomNamedNodeMap txtProperties = items.item(i).namedItem("content").attributes();
224 QFont font(txtProperties.namedItem("font").nodeValue());
226 QDomNode node = txtProperties.namedItem("font-bold");
227 if (!node.isNull()) {
228 // Old: Bold/Not bold.
229 font.setBold(node.nodeValue().toInt());
231 // New: Font weight (QFont::)
232 font.setWeight(txtProperties.namedItem("font-weight").nodeValue().toInt());
234 //font.setBold(txtProperties.namedItem("font-bold").nodeValue().toInt());
235 font.setItalic(txtProperties.namedItem("font-italic").nodeValue().toInt());
236 font.setUnderline(txtProperties.namedItem("font-underline").nodeValue().toInt());
237 // Older Kdenlive version did not store pixel size but point size
238 if (txtProperties.namedItem("font-pixel-size").isNull()) {
239 KMessageBox::information(kapp->activeWindow(), i18n("Some of your text clips were saved with size in points, which means different sizes on different displays. They will be converted to pixel size, making them portable, but you could have to adjust their size."), i18n("Text Clips Updated"));
241 f2.setPointSize(txtProperties.namedItem("font-size").nodeValue().toInt());
242 font.setPixelSize(QFontInfo(f2).pixelSize());
244 font.setPixelSize(txtProperties.namedItem("font-pixel-size").nodeValue().toInt());
245 QColor col(stringToColor(txtProperties.namedItem("font-color").nodeValue()));
246 QGraphicsTextItem *txt = m_scene->addText(items.item(i).namedItem("content").firstChild().nodeValue(), font);
247 txt->setDefaultTextColor(col);
248 txt->setTextInteractionFlags(Qt::NoTextInteraction);
249 if (txtProperties.namedItem("alignment").isNull() == false) {
250 txt->setTextWidth(txt->boundingRect().width());
251 QTextCursor cur = txt->textCursor();
252 QTextBlockFormat format = cur.blockFormat();
253 format.setAlignment((Qt::Alignment) txtProperties.namedItem("alignment").nodeValue().toInt());
254 cur.select(QTextCursor::Document);
255 cur.setBlockFormat(format);
256 txt->setTextCursor(cur);
257 cur.clearSelection();
258 txt->setTextCursor(cur);
261 if (!txtProperties.namedItem("kdenlive-axis-x-inverted").isNull()) {
262 txt->setData(OriginXLeft, txtProperties.namedItem("kdenlive-axis-x-inverted").nodeValue().toInt());
264 if (!txtProperties.namedItem("kdenlive-axis-y-inverted").isNull()) {
265 txt->setData(OriginYTop, txtProperties.namedItem("kdenlive-axis-y-inverted").nodeValue().toInt());
269 } else if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsRectItem") {
270 QString rect = items.item(i).namedItem("content").attributes().namedItem("rect").nodeValue();
271 QString br_str = items.item(i).namedItem("content").attributes().namedItem("brushcolor").nodeValue();
272 QString pen_str = items.item(i).namedItem("content").attributes().namedItem("pencolor").nodeValue();
273 double penwidth = items.item(i).namedItem("content").attributes().namedItem("penwidth").nodeValue().toDouble();
274 QGraphicsRectItem *rec = m_scene->addRect(stringToRect(rect), QPen(QBrush(stringToColor(pen_str)), penwidth), QBrush(stringToColor(br_str)));
276 } else if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsPixmapItem") {
277 QString url = items.item(i).namedItem("content").attributes().namedItem("url").nodeValue();
279 QGraphicsPixmapItem *rec = m_scene->addPixmap(pix);
280 rec->setData(Qt::UserRole, url);
282 } else if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsSvgItem") {
283 QString url = items.item(i).namedItem("content").attributes().namedItem("url").nodeValue();
284 QGraphicsSvgItem *rec = new QGraphicsSvgItem(url);
285 m_scene->addItem(rec);
286 rec->setData(Qt::UserRole, url);
292 QPointF p(items.item(i).namedItem("position").attributes().namedItem("x").nodeValue().toDouble(),
293 items.item(i).namedItem("position").attributes().namedItem("y").nodeValue().toDouble());
295 gitem->setTransform(stringToTransform(items.item(i).namedItem("position").firstChild().firstChild().nodeValue()));
296 int zValue = items.item(i).attributes().namedItem("z-index").nodeValue().toInt();
297 if (zValue > maxZValue) maxZValue = zValue;
298 gitem->setZValue(zValue);
299 gitem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
301 if (items.item(i).nodeName() == "background") {
302 kDebug() << items.item(i).attributes().namedItem("color").nodeValue();
303 QColor color = QColor(stringToColor(items.item(i).attributes().namedItem("color").nodeValue()));
304 //color.setAlpha(items.item(i).attributes().namedItem("alpha").nodeValue().toInt());
305 QList<QGraphicsItem *> items = m_scene->items();
306 for (int i = 0; i < items.size(); i++) {
307 if (items.at(i)->zValue() == -1100) {
308 ((QGraphicsRectItem *)items.at(i))->setBrush(QBrush(color));
312 } else if (items.item(i).nodeName() == "startviewport" && startv) {
313 QString rect = items.item(i).attributes().namedItem("rect").nodeValue();
314 startv->setPolygon(stringToRect(rect));
315 int x = items.item(i).attributes().namedItem("x").nodeValue().toInt();
316 int y = items.item(i).attributes().namedItem("y").nodeValue().toInt();
317 int size = items.item(i).attributes().namedItem("size").nodeValue().toInt();
318 startv->setData(0, x);
319 startv->setData(1, y);
320 startv->setData(2, size);
322 } else if (items.item(i).nodeName() == "endviewport" && endv) {
323 QString rect = items.item(i).attributes().namedItem("rect").nodeValue();
324 endv->setPolygon(stringToRect(rect));
325 int x = items.item(i).attributes().namedItem("x").nodeValue().toInt();
326 int y = items.item(i).attributes().namedItem("y").nodeValue().toInt();
327 int size = items.item(i).attributes().namedItem("size").nodeValue().toInt();
330 endv->setData(2, size);
337 QString TitleDocument::colorToString(const QColor& c)
339 QString ret = "%1,%2,%3,%4";
340 ret = ret.arg(c.red()).arg(c.green()).arg(c.blue()).arg(c.alpha());
344 QString TitleDocument::rectFToString(const QRectF& c)
346 QString ret = "%1,%2,%3,%4";
347 ret = ret.arg(c.left()).arg(c.top()).arg(c.width()).arg(c.height());
351 QRectF TitleDocument::stringToRect(const QString & s)
354 QStringList l = s.split(',');
357 return QRectF(l.at(0).toDouble(), l.at(1).toDouble(), l.at(2).toDouble(), l.at(3).toDouble()).normalized();
360 QColor TitleDocument::stringToColor(const QString & s)
362 QStringList l = s.split(',');
365 return QColor(l.at(0).toInt(), l.at(1).toInt(), l.at(2).toInt(), l.at(3).toInt());;
367 QTransform TitleDocument::stringToTransform(const QString& s)
369 QStringList l = s.split(',');
373 l.at(0).toDouble(), l.at(1).toDouble(), l.at(2).toDouble(),
374 l.at(3).toDouble(), l.at(4).toDouble(), l.at(5).toDouble(),
375 l.at(6).toDouble(), l.at(7).toDouble(), l.at(8).toDouble()