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-bold", font.bold());
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());
225 font.setBold(txtProperties.namedItem("font-bold").nodeValue().toInt());
226 font.setItalic(txtProperties.namedItem("font-italic").nodeValue().toInt());
227 font.setUnderline(txtProperties.namedItem("font-underline").nodeValue().toInt());
228 // Older Kdenlive version did not store pixel size but point size
229 if (txtProperties.namedItem("font-pixel-size").isNull()) {
230 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"));
232 f2.setPointSize(txtProperties.namedItem("font-size").nodeValue().toInt());
233 font.setPixelSize(QFontInfo(f2).pixelSize());
235 font.setPixelSize(txtProperties.namedItem("font-pixel-size").nodeValue().toInt());
236 QColor col(stringToColor(txtProperties.namedItem("font-color").nodeValue()));
237 QGraphicsTextItem *txt = m_scene->addText(items.item(i).namedItem("content").firstChild().nodeValue(), font);
238 txt->setDefaultTextColor(col);
239 txt->setTextInteractionFlags(Qt::NoTextInteraction);
240 if (txtProperties.namedItem("alignment").isNull() == false) {
241 txt->setTextWidth(txt->boundingRect().width());
242 QTextCursor cur = txt->textCursor();
243 QTextBlockFormat format = cur.blockFormat();
244 format.setAlignment((Qt::Alignment) txtProperties.namedItem("alignment").nodeValue().toInt());
245 cur.select(QTextCursor::Document);
246 cur.setBlockFormat(format);
247 txt->setTextCursor(cur);
248 cur.clearSelection();
249 txt->setTextCursor(cur);
252 if (!txtProperties.namedItem("kdenlive-axis-x-inverted").isNull()) {
253 txt->setData(OriginXLeft, txtProperties.namedItem("kdenlive-axis-x-inverted").nodeValue().toInt());
255 if (!txtProperties.namedItem("kdenlive-axis-y-inverted").isNull()) {
256 txt->setData(OriginYTop, txtProperties.namedItem("kdenlive-axis-y-inverted").nodeValue().toInt());
260 } else if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsRectItem") {
261 QString rect = items.item(i).namedItem("content").attributes().namedItem("rect").nodeValue();
262 QString br_str = items.item(i).namedItem("content").attributes().namedItem("brushcolor").nodeValue();
263 QString pen_str = items.item(i).namedItem("content").attributes().namedItem("pencolor").nodeValue();
264 double penwidth = items.item(i).namedItem("content").attributes().namedItem("penwidth").nodeValue().toDouble();
265 QGraphicsRectItem *rec = m_scene->addRect(stringToRect(rect), QPen(QBrush(stringToColor(pen_str)), penwidth), QBrush(stringToColor(br_str)));
267 } else if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsPixmapItem") {
268 QString url = items.item(i).namedItem("content").attributes().namedItem("url").nodeValue();
270 QGraphicsPixmapItem *rec = m_scene->addPixmap(pix);
271 rec->setData(Qt::UserRole, url);
273 } else if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsSvgItem") {
274 QString url = items.item(i).namedItem("content").attributes().namedItem("url").nodeValue();
275 QGraphicsSvgItem *rec = new QGraphicsSvgItem(url);
276 m_scene->addItem(rec);
277 rec->setData(Qt::UserRole, url);
283 QPointF p(items.item(i).namedItem("position").attributes().namedItem("x").nodeValue().toDouble(),
284 items.item(i).namedItem("position").attributes().namedItem("y").nodeValue().toDouble());
286 gitem->setTransform(stringToTransform(items.item(i).namedItem("position").firstChild().firstChild().nodeValue()));
287 int zValue = items.item(i).attributes().namedItem("z-index").nodeValue().toInt();
288 if (zValue > maxZValue) maxZValue = zValue;
289 gitem->setZValue(zValue);
290 gitem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
292 if (items.item(i).nodeName() == "background") {
293 kDebug() << items.item(i).attributes().namedItem("color").nodeValue();
294 QColor color = QColor(stringToColor(items.item(i).attributes().namedItem("color").nodeValue()));
295 //color.setAlpha(items.item(i).attributes().namedItem("alpha").nodeValue().toInt());
296 QList<QGraphicsItem *> items = m_scene->items();
297 for (int i = 0; i < items.size(); i++) {
298 if (items.at(i)->zValue() == -1100) {
299 ((QGraphicsRectItem *)items.at(i))->setBrush(QBrush(color));
303 } else if (items.item(i).nodeName() == "startviewport" && startv) {
304 QString rect = items.item(i).attributes().namedItem("rect").nodeValue();
305 startv->setPolygon(stringToRect(rect));
306 int x = items.item(i).attributes().namedItem("x").nodeValue().toInt();
307 int y = items.item(i).attributes().namedItem("y").nodeValue().toInt();
308 int size = items.item(i).attributes().namedItem("size").nodeValue().toInt();
309 startv->setData(0,x);
310 startv->setData(1,y);
311 startv->setData(2,size);
313 } else if (items.item(i).nodeName() == "endviewport" && endv) {
314 QString rect = items.item(i).attributes().namedItem("rect").nodeValue();
315 endv->setPolygon(stringToRect(rect));
316 int x = items.item(i).attributes().namedItem("x").nodeValue().toInt();
317 int y = items.item(i).attributes().namedItem("y").nodeValue().toInt();
318 int size = items.item(i).attributes().namedItem("size").nodeValue().toInt();
321 endv->setData(2,size);
328 QString TitleDocument::colorToString(const QColor& c)
330 QString ret = "%1,%2,%3,%4";
331 ret = ret.arg(c.red()).arg(c.green()).arg(c.blue()).arg(c.alpha());
335 QString TitleDocument::rectFToString(const QRectF& c)
337 QString ret = "%1,%2,%3,%4";
338 ret = ret.arg(c.left()).arg(c.top()).arg(c.width()).arg(c.height());
342 QRectF TitleDocument::stringToRect(const QString & s)
345 QStringList l = s.split(',');
348 return QRectF(l.at(0).toDouble(), l.at(1).toDouble(), l.at(2).toDouble(), l.at(3).toDouble()).normalized();
351 QColor TitleDocument::stringToColor(const QString & s)
353 QStringList l = s.split(',');
356 return QColor(l.at(0).toInt(), l.at(1).toInt(), l.at(2).toInt(), l.at(3).toInt());;
358 QTransform TitleDocument::stringToTransform(const QString& s)
360 QStringList l = s.split(',');
364 l.at(0).toDouble(), l.at(1).toDouble(), l.at(2).toDouble(),
365 l.at(3).toDouble(), l.at(4).toDouble(), l.at(5).toDouble(),
366 l.at(6).toDouble(), l.at(7).toDouble(), l.at(8).toDouble()