]> git.sesse.net Git - kdenlive/blobdiff - src/titledocument.cpp
initial work for titleproducer
[kdenlive] / src / titledocument.cpp
index 5a5b005e9f4a2844f0a9d89c671cefefb46e4d1b..df7c5c88f40324b8c421a30deaf66b08490db226 100644 (file)
  *   (at your option) any later version.                                   *
  *                                                                         *
  ***************************************************************************/
+
 #include "titledocument.h"
+
+#include <KDebug>
+#include <KTemporaryFile>
+#include <kio/netaccess.h>
+#include <KApplication>
+#include <KLocale>
+#include <KMessageBox>
+
 #include <QGraphicsScene>
-#include <QDomDocument>
 #include <QDomElement>
 #include <QGraphicsItem>
 #include <QGraphicsRectItem>
 #include <QGraphicsTextItem>
 #include <QGraphicsSvgItem>
-#include <KDebug>
+#include <QFontInfo>
 #include <QFile>
-#include <KTemporaryFile>
-#include <kio/netaccess.h>
+#include <QTextCursor>
+
 
-TitleDocument::TitleDocument() {
-    scene = NULL;
+TitleDocument::TitleDocument()
+{
+    m_scene = NULL;
 }
 
-void TitleDocument::setScene(QGraphicsScene* _scene) {
-    scene = _scene;
+void TitleDocument::setScene(QGraphicsScene* _scene)
+{
+    m_scene = _scene;
 }
 
-bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv) {
+QDomDocument TitleDocument::xml(QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv)
+{
     QDomDocument doc;
 
-    if (!scene)
-        return false;
-
     QDomElement main = doc.createElement("kdenlivetitle");
     doc.appendChild(main);
 
-    foreach(QGraphicsItem* item, scene->items()) {
+    foreach(QGraphicsItem* item, m_scene->items()) {
         QDomElement e = doc.createElement("item");
         QDomElement content = doc.createElement("content");
         QFont font;
@@ -61,7 +69,7 @@ bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv,
             break;
         case 3:
             e.setAttribute("type", "QGraphicsRectItem");
-            content.setAttribute("rect", rectFToString(((QGraphicsRectItem*)item)->rect()));
+            content.setAttribute("rect", rectFToString(((QGraphicsRectItem*)item)->rect().normalized()));
             content.setAttribute("pencolor", colorToString(((QGraphicsRectItem*)item)->pen().color()));
             content.setAttribute("penwidth", ((QGraphicsRectItem*)item)->pen().width());
             content.setAttribute("brushcolor", colorToString(((QGraphicsRectItem*)item)->brush().color()));
@@ -69,15 +77,28 @@ bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv,
         case 8:
             e.setAttribute("type", "QGraphicsTextItem");
             t = static_cast<QGraphicsTextItem *>(item);
+            // Don't save empty text nodes
+            if (t->toPlainText().simplified().isEmpty()) continue;
             //content.appendChild(doc.createTextNode(((QGraphicsTextItem*)item)->toHtml()));
             content.appendChild(doc.createTextNode(t->toPlainText()));
             font = t->font();
             content.setAttribute("font", font.family());
             content.setAttribute("font-bold", font.bold());
-            content.setAttribute("font-size", font.pointSize());
+            content.setAttribute("font-pixel-size", font.pixelSize());
             content.setAttribute("font-italic", font.italic());
             content.setAttribute("font-underline", font.underline());
             content.setAttribute("font-color", colorToString(t->defaultTextColor()));
+
+            // Only save when necessary.
+            if (t->data(OriginXLeft).toInt() == AxisInverted) {
+                content.setAttribute("kdenlive-axis-x-inverted", t->data(OriginXLeft).toInt());
+            }
+            if (t->data(OriginYTop).toInt() == AxisInverted) {
+                content.setAttribute("kdenlive-axis-y-inverted", t->data(OriginYTop).toInt());
+            }
+            if (t->textWidth() != -1) {
+                content.setAttribute("alignment", t->textCursor().blockFormat().alignment());
+            }
             break;
         default:
             continue;
@@ -103,13 +124,15 @@ bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv,
     if (startv && endv) {
         QDomElement endp = doc.createElement("endviewport");
         QDomElement startp = doc.createElement("startviewport");
-        endp.setAttribute("x", endv->pos().x());
-        endp.setAttribute("y", endv->pos().y());
-        endp.setAttribute("size", endv->sceneBoundingRect().width() / 2);
+        endp.setAttribute("x", endv->data(0).toString() );
+        endp.setAttribute("y", endv->data(1).toString() );
+        endp.setAttribute("size", endv->data(2).toString());
+       endp.setAttribute("rect",rectFToString(endv->boundingRect()));
 
-        startp.setAttribute("x", startv->pos().x());
-        startp.setAttribute("y", startv->pos().y());
-        startp.setAttribute("size", startv->sceneBoundingRect().width() / 2);
+        startp.setAttribute("x", startv->data(0).toString() );
+        startp.setAttribute("y", startv->data(1).toString());
+        startp.setAttribute("size", startv->data(2).toString());
+       startp.setAttribute("rect",rectFToString(startv->boundingRect()));
 
         startp.setAttribute("z-index", startv->zValue());
         endp.setAttribute("z-index", endv->zValue());
@@ -117,33 +140,58 @@ bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv,
         main.appendChild(endp);
     }
     QDomElement backgr = doc.createElement("background");
-    QList<QGraphicsItem *> items = scene->items();
+    QColor color = getBackgroundColor();
+    backgr.setAttribute("color", colorToString(color));
+    main.appendChild(backgr);
+
+    return doc;
+}
+
+/** \brief Get the background color (incl. alpha) from the document, if possibly
+  * \returns The background color of the document, inclusive alpha. If none found, returns (0,0,0,0) */
+QColor TitleDocument::getBackgroundColor()
+{
     QColor color(0, 0, 0, 0);
-    for (int i = 0; i < items.size(); i++) {
-        if (items.at(i)->zValue() == -1100) {
-            color = ((QGraphicsRectItem *)items.at(i))->brush().color();
-            break;
+    if (m_scene) {
+        QList<QGraphicsItem *> items = m_scene->items();
+        for (int i = 0; i < items.size(); i++) {
+            if (items.at(i)->zValue() == -1100) {
+                color = ((QGraphicsRectItem *)items.at(i))->brush().color();
+                return color;
+            }
         }
     }
-    backgr.setAttribute("color", colorToString(color));
-    main.appendChild(backgr);
+    return color;
+}
 
+
+bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv)
+{
+    if (!m_scene)
+        return false;
+
+    QDomDocument doc = xml(startv, endv);
     KTemporaryFile tmpfile;
-    if (!tmpfile.open()) kWarning() << "/////  CANNOT CREATE TMP FILE in: " << tmpfile.fileName();
+    if (!tmpfile.open()) {
+        kWarning() << "/////  CANNOT CREATE TMP FILE in: " << tmpfile.fileName();
+        return false;
+    }
     QFile xmlf(tmpfile.fileName());
     xmlf.open(QIODevice::WriteOnly);
-    xmlf.write(doc.toString().toAscii());
+    xmlf.write(doc.toString().toUtf8());
+    if (xmlf.error() != QFile::NoError) {
+        xmlf.close();
+        return false;
+    }
     xmlf.close();
-    kDebug() << KIO::NetAccess::upload(tmpfile.fileName(), url, 0);
-
+    return KIO::NetAccess::upload(tmpfile.fileName(), url, 0);
 }
 
-int TitleDocument::loadDocument(const KUrl& url , QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv) {
+int TitleDocument::loadDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv)
+{
     QString tmpfile;
     QDomDocument doc;
-    int maxZValue = 0;
-    double aspect_ratio = 4.0 / 3.0;
-    if (!scene)
+    if (!m_scene)
         return -1;
 
     if (KIO::NetAccess::download(url, tmpfile, 0)) {
@@ -154,125 +202,167 @@ int TitleDocument::loadDocument(const KUrl& url , QGraphicsPolygonItem* startv,
         } else
             return -1;
         KIO::NetAccess::removeTempFile(tmpfile);
-        QDomNodeList titles = doc.elementsByTagName("kdenlivetitle");
-        if (titles.size()) {
+        return loadFromXml(doc, startv, endv);
+    }
+    return -1;
+}
 
-            QDomNodeList items = titles.item(0).childNodes();
-            for (int i = 0;i < items.count();i++) {
-                QGraphicsItem *gitem = NULL;
-                kDebug() << items.item(i).attributes().namedItem("type").nodeValue();
-                int zValue = items.item(i).attributes().namedItem("z-index").nodeValue().toInt();
-                if (zValue > -1000)
-                    if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsTextItem") {
-                        QFont font(items.item(i).namedItem("content").attributes().namedItem("font").nodeValue());
-                        font.setBold(items.item(i).namedItem("content").attributes().namedItem("font-bold").nodeValue().toInt());
-                        font.setItalic(items.item(i).namedItem("content").attributes().namedItem("font-italic").nodeValue().toInt());
-                        font.setUnderline(items.item(i).namedItem("content").attributes().namedItem("font-underline").nodeValue().toInt());
-                        font.setPointSize(items.item(i).namedItem("content").attributes().namedItem("font-size").nodeValue().toInt());
-                        QColor col(stringToColor(items.item(i).namedItem("content").attributes().namedItem("font-color").nodeValue()));
-                        QGraphicsTextItem *txt = scene->addText(items.item(i).namedItem("content").firstChild().nodeValue(), font);
-                        txt->setDefaultTextColor(col);
-                        txt->setTextInteractionFlags(Qt::NoTextInteraction);
-                        gitem = txt;
+int TitleDocument::loadFromXml(QDomDocument doc, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv)
+{
+    QDomNodeList titles = doc.elementsByTagName("kdenlivetitle");
+    int maxZValue = 0;
+    if (titles.size()) {
+
+        QDomNodeList items = titles.item(0).childNodes();
+        for (int i = 0; i < items.count(); i++) {
+            QGraphicsItem *gitem = NULL;
+            kDebug() << items.item(i).attributes().namedItem("type").nodeValue();
+            int zValue = items.item(i).attributes().namedItem("z-index").nodeValue().toInt();
+            if (zValue > -1000) {
+                if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsTextItem") {
+                    QDomNamedNodeMap txtProperties = items.item(i).namedItem("content").attributes();
+                    QFont font(txtProperties.namedItem("font").nodeValue());
+                    font.setBold(txtProperties.namedItem("font-bold").nodeValue().toInt());
+                    font.setItalic(txtProperties.namedItem("font-italic").nodeValue().toInt());
+                    font.setUnderline(txtProperties.namedItem("font-underline").nodeValue().toInt());
+                    // Older Kdenlive version did not store pixel size but point size
+                    if (txtProperties.namedItem("font-pixel-size").isNull()) {
+                        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"));
+                        QFont f2;
+                        f2.setPointSize(txtProperties.namedItem("font-size").nodeValue().toInt());
+                        font.setPixelSize(QFontInfo(f2).pixelSize());
                     } else
-                        if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsRectItem") {
-                            QString rect = items.item(i).namedItem("content").attributes().namedItem("rect").nodeValue();
-                            QString br_str = items.item(i).namedItem("content").attributes().namedItem("brushcolor").nodeValue();
-                            QString pen_str = items.item(i).namedItem("content").attributes().namedItem("pencolor").nodeValue();
-                            double penwidth = items.item(i).namedItem("content").attributes().namedItem("penwidth").nodeValue().toDouble();
-                            QGraphicsRectItem *rec = scene->addRect(stringToRect(rect), QPen(QBrush(stringToColor(pen_str)), penwidth), QBrush(stringToColor(br_str)));
-                            gitem = rec;
-                        } else
-                            if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsPixmapItem") {
-                                QString url = items.item(i).namedItem("content").attributes().namedItem("url").nodeValue();
-                                QPixmap pix(url);
-                                QGraphicsPixmapItem *rec = scene->addPixmap(pix);
-                                rec->setData(Qt::UserRole, url);
-                                gitem = rec;
-                            } else
-                                if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsSvgItem") {
-                                    QString url = items.item(i).namedItem("content").attributes().namedItem("url").nodeValue();
-                                    QGraphicsSvgItem *rec = new QGraphicsSvgItem(url);
-                                    scene->addItem(rec);
-                                    rec->setData(Qt::UserRole, url);
-                                    gitem = rec;
-                                }
-                //pos and transform
-                if (gitem) {
-                    QPointF p(items.item(i).namedItem("position").attributes().namedItem("x").nodeValue().toDouble(),
-                              items.item(i).namedItem("position").attributes().namedItem("y").nodeValue().toDouble());
-                    gitem->setPos(p);
-                    gitem->setTransform(stringToTransform(items.item(i).namedItem("position").firstChild().firstChild().nodeValue()));
-                    int zValue = items.item(i).attributes().namedItem("z-index").nodeValue().toInt();
-                    if (zValue > maxZValue) maxZValue = zValue;
-                    gitem->setZValue(zValue);
-                    gitem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
+                        font.setPixelSize(txtProperties.namedItem("font-pixel-size").nodeValue().toInt());
+                    QColor col(stringToColor(txtProperties.namedItem("font-color").nodeValue()));
+                    QGraphicsTextItem *txt = m_scene->addText(items.item(i).namedItem("content").firstChild().nodeValue(), font);
+                    txt->setDefaultTextColor(col);
+                    txt->setTextInteractionFlags(Qt::NoTextInteraction);
+                    if (txtProperties.namedItem("alignment").isNull() == false) {
+                        txt->setTextWidth(txt->boundingRect().width());
+                        QTextCursor cur = txt->textCursor();
+                        QTextBlockFormat format = cur.blockFormat();
+                        format.setAlignment((Qt::Alignment) txtProperties.namedItem("alignment").nodeValue().toInt());
+                        cur.select(QTextCursor::Document);
+                        cur.setBlockFormat(format);
+                        txt->setTextCursor(cur);
+                        cur.clearSelection();
+                        txt->setTextCursor(cur);
+                    }
+
+                    if (!txtProperties.namedItem("kdenlive-axis-x-inverted").isNull()) {
+                        txt->setData(OriginXLeft, txtProperties.namedItem("kdenlive-axis-x-inverted").nodeValue().toInt());
+                    }
+                    if (!txtProperties.namedItem("kdenlive-axis-y-inverted").isNull()) {
+                        txt->setData(OriginYTop, txtProperties.namedItem("kdenlive-axis-y-inverted").nodeValue().toInt());
+                    }
+
+                    gitem = txt;
+                } else if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsRectItem") {
+                    QString rect = items.item(i).namedItem("content").attributes().namedItem("rect").nodeValue();
+                    QString br_str = items.item(i).namedItem("content").attributes().namedItem("brushcolor").nodeValue();
+                    QString pen_str = items.item(i).namedItem("content").attributes().namedItem("pencolor").nodeValue();
+                    double penwidth = items.item(i).namedItem("content").attributes().namedItem("penwidth").nodeValue().toDouble();
+                    QGraphicsRectItem *rec = m_scene->addRect(stringToRect(rect), QPen(QBrush(stringToColor(pen_str)), penwidth), QBrush(stringToColor(br_str)));
+                    gitem = rec;
+                } else if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsPixmapItem") {
+                    QString url = items.item(i).namedItem("content").attributes().namedItem("url").nodeValue();
+                    QPixmap pix(url);
+                    QGraphicsPixmapItem *rec = m_scene->addPixmap(pix);
+                    rec->setData(Qt::UserRole, url);
+                    gitem = rec;
+                } else if (items.item(i).attributes().namedItem("type").nodeValue() == "QGraphicsSvgItem") {
+                    QString url = items.item(i).namedItem("content").attributes().namedItem("url").nodeValue();
+                    QGraphicsSvgItem *rec = new QGraphicsSvgItem(url);
+                    m_scene->addItem(rec);
+                    rec->setData(Qt::UserRole, url);
+                    gitem = rec;
                 }
-                if (items.item(i).nodeName() == "background") {
-                    kDebug() << items.item(i).attributes().namedItem("color").nodeValue();
-                    QColor color = QColor(stringToColor(items.item(i).attributes().namedItem("color").nodeValue()));
-                    //color.setAlpha(items.item(i).attributes().namedItem("alpha").nodeValue().toInt());
-                    QList<QGraphicsItem *> items = scene->items();
-                    for (int i = 0; i < items.size(); i++) {
-                        if (items.at(i)->zValue() == -1100) {
-                            ((QGraphicsRectItem *)items.at(i))->setBrush(QBrush(color));
-                            break;
-                        }
+            }
+            //pos and transform
+            if (gitem) {
+                QPointF p(items.item(i).namedItem("position").attributes().namedItem("x").nodeValue().toDouble(),
+                          items.item(i).namedItem("position").attributes().namedItem("y").nodeValue().toDouble());
+                gitem->setPos(p);
+                gitem->setTransform(stringToTransform(items.item(i).namedItem("position").firstChild().firstChild().nodeValue()));
+                int zValue = items.item(i).attributes().namedItem("z-index").nodeValue().toInt();
+                if (zValue > maxZValue) maxZValue = zValue;
+                gitem->setZValue(zValue);
+                gitem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
+            }
+            if (items.item(i).nodeName() == "background") {
+                kDebug() << items.item(i).attributes().namedItem("color").nodeValue();
+                QColor color = QColor(stringToColor(items.item(i).attributes().namedItem("color").nodeValue()));
+                //color.setAlpha(items.item(i).attributes().namedItem("alpha").nodeValue().toInt());
+                QList<QGraphicsItem *> items = m_scene->items();
+                for (int i = 0; i < items.size(); i++) {
+                    if (items.at(i)->zValue() == -1100) {
+                        ((QGraphicsRectItem *)items.at(i))->setBrush(QBrush(color));
+                        break;
                     }
-                } /*else if (items.item(i).nodeName() == "startviewport" && startv) {
-                    QPointF p(items.item(i).attributes().namedItem("x").nodeValue().toDouble(), items.item(i).attributes().namedItem("y").nodeValue().toDouble());
-                    double width = items.item(i).attributes().namedItem("size").nodeValue().toDouble();
-                    QRectF rect(-width, -width / aspect_ratio, width*2.0, width / aspect_ratio*2.0);
-                    kDebug() << width << rect;
-                    startv->setPolygon(rect);
-                    startv->setPos(p);
+                }
+            } else if (items.item(i).nodeName() == "startviewport" && startv) {
+                   QString rect = items.item(i).attributes().namedItem("rect").nodeValue();
+                    startv->setPolygon(stringToRect(rect));
+                   int x = items.item(i).attributes().namedItem("x").nodeValue().toInt();
+                   int y = items.item(i).attributes().namedItem("y").nodeValue().toInt();
+                   int size = items.item(i).attributes().namedItem("size").nodeValue().toInt();
+                   startv->setData(0,x);
+                   startv->setData(1,y);
+                   startv->setData(2,size);
+                    //startv->setPos(p);
                 } else if (items.item(i).nodeName() == "endviewport" && endv) {
-                    QPointF p(items.item(i).attributes().namedItem("x").nodeValue().toDouble(), items.item(i).attributes().namedItem("y").nodeValue().toDouble());
-                    double width = items.item(i).attributes().namedItem("size").nodeValue().toDouble();
-                    QRectF rect(-width, -width / aspect_ratio, width*2.0, width / aspect_ratio*2.0);
-                    kDebug() << width << rect;
-                    endv->setPolygon(rect);
-                    endv->setPos(p);
-                }*/
-            }
+                   QString rect = items.item(i).attributes().namedItem("rect").nodeValue();
+                    endv->setPolygon(stringToRect(rect));
+                    int x = items.item(i).attributes().namedItem("x").nodeValue().toInt();
+                   int y = items.item(i).attributes().namedItem("y").nodeValue().toInt();
+                   int size = items.item(i).attributes().namedItem("size").nodeValue().toInt();
+                   endv->setData(0,x);
+                   endv->setData(1,y);
+                   endv->setData(2,size);
+                }
         }
     }
     return maxZValue;
 }
 
-QString TitleDocument::colorToString(const QColor& c) {
+QString TitleDocument::colorToString(const QColor& c)
+{
     QString ret = "%1,%2,%3,%4";
     ret = ret.arg(c.red()).arg(c.green()).arg(c.blue()).arg(c.alpha());
     return ret;
 }
 
-QString TitleDocument::rectFToString(const QRectF& c) {
+QString TitleDocument::rectFToString(const QRectF& c)
+{
     QString ret = "%1,%2,%3,%4";
-    ret = ret.arg(c.x()).arg(c.y()).arg(c.width()).arg(c.height());
+    ret = ret.arg(c.left()).arg(c.top()).arg(c.width()).arg(c.height());
     return ret;
 }
 
-QRectF TitleDocument::stringToRect(const QString & s) {
+QRectF TitleDocument::stringToRect(const QString & s)
+{
 
-    QStringList l = s.split(",");
+    QStringList l = s.split(',');
     if (l.size() < 4)
         return QRectF();
-    return QRectF(l[0].toDouble(), l[1].toDouble(), l[2].toDouble(), l[3].toDouble());
+    return QRectF(l.at(0).toDouble(), l.at(1).toDouble(), l.at(2).toDouble(), l.at(3).toDouble()).normalized();
 }
 
-QColor TitleDocument::stringToColor(const QString & s) {
-    QStringList l = s.split(",");
+QColor TitleDocument::stringToColor(const QString & s)
+{
+    QStringList l = s.split(',');
     if (l.size() < 4)
         return QColor();
-    return QColor(l[0].toInt(), l[1].toInt(), l[2].toInt(), l[3].toInt());;
+    return QColor(l.at(0).toInt(), l.at(1).toInt(), l.at(2).toInt(), l.at(3).toInt());;
 }
-QTransform TitleDocument::stringToTransform(const QString& s) {
-    QStringList l = s.split(",");
+QTransform TitleDocument::stringToTransform(const QString& s)
+{
+    QStringList l = s.split(',');
     if (l.size() < 9)
         return QTransform();
     return QTransform(
-               l[0].toDouble(), l[1].toDouble(), l[2].toDouble(),
-               l[3].toDouble(), l[4].toDouble(), l[5].toDouble(),
-               l[6].toDouble(), l[7].toDouble(), l[8].toDouble()
+               l.at(0).toDouble(), l.at(1).toDouble(), l.at(2).toDouble(),
+               l.at(3).toDouble(), l.at(4).toDouble(), l.at(5).toDouble(),
+               l.at(6).toDouble(), l.at(7).toDouble(), l.at(8).toDouble()
            );
 }