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->pos().x());
128 endp.setAttribute("y", endv->pos().y());
129 endp.setAttribute("size", endv->sceneBoundingRect().width() / 2);
131 startp.setAttribute("x", startv->pos().x());
132 startp.setAttribute("y", startv->pos().y());
133 startp.setAttribute("size", startv->sceneBoundingRect().width() / 2);
135 startp.setAttribute("z-index", startv->zValue());
136 endp.setAttribute("z-index", endv->zValue());
137 main.appendChild(startp);
138 main.appendChild(endp);
140 QDomElement backgr = doc.createElement("background");
141 QColor color = getBackgroundColor();
142 backgr.setAttribute("color", colorToString(color));
143 main.appendChild(backgr);
148 /** \brief Get the background color (incl. alpha) from the document, if possibly
149 * \returns The background color of the document, inclusive alpha. If none found, returns (0,0,0,0) */
150 QColor TitleDocument::getBackgroundColor()
152 QColor color(0, 0, 0, 0);
154 QList<QGraphicsItem *> items = m_scene->items();
155 for (int i = 0; i < items.size(); i++) {
156 if (items.at(i)->zValue() == -1100) {
157 color = ((QGraphicsRectItem *)items.at(i))->brush().color();
166 bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv)
171 QDomDocument doc = xml(startv, endv);
172 KTemporaryFile tmpfile;
173 if (!tmpfile.open()) {
174 kWarning() << "///// CANNOT CREATE TMP FILE in: " << tmpfile.fileName();
177 QFile xmlf(tmpfile.fileName());
178 xmlf.open(QIODevice::WriteOnly);
179 xmlf.write(doc.toString().toUtf8());
180 if (xmlf.error() != QFile::NoError) {
185 return KIO::NetAccess::upload(tmpfile.fileName(), url, 0);
188 int TitleDocument::loadDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv)
195 if (KIO::NetAccess::download(url, tmpfile, 0)) {
197 if (file.open(QIODevice::ReadOnly)) {
198 doc.setContent(&file, false);
202 KIO::NetAccess::removeTempFile(tmpfile);
203 return loadFromXml(doc, startv, endv);
208 int TitleDocument::loadFromXml(QDomDocument doc, QGraphicsPolygonItem* /*startv*/, QGraphicsPolygonItem* /*endv*/)
210 QDomNodeList titles = doc.elementsByTagName("kdenlivetitle");
214 QDomNodeList items = titles.item(0).childNodes();
215 for (int i = 0; i < items.count(); i++) {
216 QGraphicsItem *gitem = NULL;
217 kDebug() << items.item(i).attributes().namedItem("type").nodeValue();
218 int zValue = items.item(i).attributes().namedItem("z-index").nodeValue().toInt();
219 if (zValue > -1000) {
220 if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsTextItem") {
221 QDomNamedNodeMap txtProperties = items.item(i).namedItem("content").attributes();
222 QFont font(txtProperties.namedItem("font").nodeValue());
223 font.setBold(txtProperties.namedItem("font-bold").nodeValue().toInt());
224 font.setItalic(txtProperties.namedItem("font-italic").nodeValue().toInt());
225 font.setUnderline(txtProperties.namedItem("font-underline").nodeValue().toInt());
226 // Older Kdenlive version did not store pixel size but point size
227 if (txtProperties.namedItem("font-pixel-size").isNull()) {
228 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"));
230 f2.setPointSize(txtProperties.namedItem("font-size").nodeValue().toInt());
231 font.setPixelSize(QFontInfo(f2).pixelSize());
233 font.setPixelSize(txtProperties.namedItem("font-pixel-size").nodeValue().toInt());
234 QColor col(stringToColor(txtProperties.namedItem("font-color").nodeValue()));
235 QGraphicsTextItem *txt = m_scene->addText(items.item(i).namedItem("content").firstChild().nodeValue(), font);
236 txt->setDefaultTextColor(col);
237 txt->setTextInteractionFlags(Qt::NoTextInteraction);
238 if (txtProperties.namedItem("alignment").isNull() == false) {
239 txt->setTextWidth(txt->boundingRect().width());
240 QTextCursor cur = txt->textCursor();
241 QTextBlockFormat format = cur.blockFormat();
242 format.setAlignment((Qt::Alignment) txtProperties.namedItem("alignment").nodeValue().toInt());
243 cur.select(QTextCursor::Document);
244 cur.setBlockFormat(format);
245 txt->setTextCursor(cur);
246 cur.clearSelection();
247 txt->setTextCursor(cur);
250 if (!txtProperties.namedItem("kdenlive-axis-x-inverted").isNull()) {
251 txt->setData(OriginXLeft, txtProperties.namedItem("kdenlive-axis-x-inverted").nodeValue().toInt());
253 if (!txtProperties.namedItem("kdenlive-axis-y-inverted").isNull()) {
254 txt->setData(OriginYTop, txtProperties.namedItem("kdenlive-axis-y-inverted").nodeValue().toInt());
258 } else if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsRectItem") {
259 QString rect = items.item(i).namedItem("content").attributes().namedItem("rect").nodeValue();
260 QString br_str = items.item(i).namedItem("content").attributes().namedItem("brushcolor").nodeValue();
261 QString pen_str = items.item(i).namedItem("content").attributes().namedItem("pencolor").nodeValue();
262 double penwidth = items.item(i).namedItem("content").attributes().namedItem("penwidth").nodeValue().toDouble();
263 QGraphicsRectItem *rec = m_scene->addRect(stringToRect(rect), QPen(QBrush(stringToColor(pen_str)), penwidth), QBrush(stringToColor(br_str)));
265 } else if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsPixmapItem") {
266 QString url = items.item(i).namedItem("content").attributes().namedItem("url").nodeValue();
268 QGraphicsPixmapItem *rec = m_scene->addPixmap(pix);
269 rec->setData(Qt::UserRole, url);
271 } else if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsSvgItem") {
272 QString url = items.item(i).namedItem("content").attributes().namedItem("url").nodeValue();
273 QGraphicsSvgItem *rec = new QGraphicsSvgItem(url);
274 m_scene->addItem(rec);
275 rec->setData(Qt::UserRole, url);
281 QPointF p(items.item(i).namedItem("position").attributes().namedItem("x").nodeValue().toDouble(),
282 items.item(i).namedItem("position").attributes().namedItem("y").nodeValue().toDouble());
284 gitem->setTransform(stringToTransform(items.item(i).namedItem("position").firstChild().firstChild().nodeValue()));
285 int zValue = items.item(i).attributes().namedItem("z-index").nodeValue().toInt();
286 if (zValue > maxZValue) maxZValue = zValue;
287 gitem->setZValue(zValue);
288 gitem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
290 if (items.item(i).nodeName() == "background") {
291 kDebug() << items.item(i).attributes().namedItem("color").nodeValue();
292 QColor color = QColor(stringToColor(items.item(i).attributes().namedItem("color").nodeValue()));
293 //color.setAlpha(items.item(i).attributes().namedItem("alpha").nodeValue().toInt());
294 QList<QGraphicsItem *> items = m_scene->items();
295 for (int i = 0; i < items.size(); i++) {
296 if (items.at(i)->zValue() == -1100) {
297 ((QGraphicsRectItem *)items.at(i))->setBrush(QBrush(color));
301 } /*else if (items.item(i).nodeName() == "startviewport" && startv) {
302 QPointF p(items.item(i).attributes().namedItem("x").nodeValue().toDouble(), items.item(i).attributes().namedItem("y").nodeValue().toDouble());
303 double width = items.item(i).attributes().namedItem("size").nodeValue().toDouble();
304 QRectF rect(-width, -width / aspect_ratio, width*2.0, width / aspect_ratio*2.0);
305 kDebug() << width << rect;
306 startv->setPolygon(rect);
308 } else if (items.item(i).nodeName() == "endviewport" && endv) {
309 QPointF p(items.item(i).attributes().namedItem("x").nodeValue().toDouble(), items.item(i).attributes().namedItem("y").nodeValue().toDouble());
310 double width = items.item(i).attributes().namedItem("size").nodeValue().toDouble();
311 QRectF rect(-width, -width / aspect_ratio, width*2.0, width / aspect_ratio*2.0);
312 kDebug() << width << rect;
313 endv->setPolygon(rect);
321 QString TitleDocument::colorToString(const QColor& c)
323 QString ret = "%1,%2,%3,%4";
324 ret = ret.arg(c.red()).arg(c.green()).arg(c.blue()).arg(c.alpha());
328 QString TitleDocument::rectFToString(const QRectF& c)
330 QString ret = "%1,%2,%3,%4";
331 ret = ret.arg(c.top()).arg(c.left()).arg(c.width()).arg(c.height());
335 QRectF TitleDocument::stringToRect(const QString & s)
338 QStringList l = s.split(',');
341 return QRectF(l.at(0).toDouble(), l.at(1).toDouble(), l.at(2).toDouble(), l.at(3).toDouble()).normalized();
344 QColor TitleDocument::stringToColor(const QString & s)
346 QStringList l = s.split(',');
349 return QColor(l.at(0).toInt(), l.at(1).toInt(), l.at(2).toInt(), l.at(3).toInt());;
351 QTransform TitleDocument::stringToTransform(const QString& s)
353 QStringList l = s.split(',');
357 l.at(0).toDouble(), l.at(1).toDouble(), l.at(2).toDouble(),
358 l.at(3).toDouble(), l.at(4).toDouble(), l.at(5).toDouble(),
359 l.at(6).toDouble(), l.at(7).toDouble(), l.at(8).toDouble()