]> git.sesse.net Git - kdenlive/blobdiff - src/titledocument.cpp
Save scene dimensions in titles
[kdenlive] / src / titledocument.cpp
index 3a841510acf8b1146453a0b67b2521b1feb48620..cb2852f06f81921f3a57540eeee7adaaf0989c5a 100644 (file)
@@ -20,6 +20,9 @@
 #include <KDebug>
 #include <KTemporaryFile>
 #include <kio/netaccess.h>
+#include <KApplication>
+#include <KLocale>
+#include <KMessageBox>
 
 #include <QGraphicsScene>
 #include <QDomElement>
 #include <QGraphicsSvgItem>
 #include <QFontInfo>
 #include <QFile>
+#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;
 }
 
-QDomDocument TitleDocument::xml(QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv) {
+QDomDocument TitleDocument::xml(QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv)
+{
     QDomDocument doc;
 
     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;
@@ -62,7 +69,7 @@ QDomDocument TitleDocument::xml(QGraphicsPolygonItem* startv, QGraphicsPolygonIt
             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()));
@@ -76,11 +83,22 @@ QDomDocument TitleDocument::xml(QGraphicsPolygonItem* startv, QGraphicsPolygonIt
             content.appendChild(doc.createTextNode(t->toPlainText()));
             font = t->font();
             content.setAttribute("font", font.family());
-            content.setAttribute("font-bold", font.bold());
+            content.setAttribute("font-weight", font.weight());
             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;
@@ -106,13 +124,15 @@ QDomDocument TitleDocument::xml(QGraphicsPolygonItem* startv, QGraphicsPolygonIt
     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());
@@ -129,10 +149,11 @@ QDomDocument TitleDocument::xml(QGraphicsPolygonItem* startv, QGraphicsPolygonIt
 
 /** \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 TitleDocument::getBackgroundColor()
+{
     QColor color(0, 0, 0, 0);
-    if (scene) {
-        QList<QGraphicsItem *> items = scene->items();
+    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();
@@ -144,11 +165,15 @@ QColor TitleDocument::getBackgroundColor() {
 }
 
 
-bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv) {
-    if (!scene)
+bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv, double out)
+{
+    if (!m_scene)
         return false;
 
     QDomDocument doc = xml(startv, endv);
+    doc.documentElement().setAttribute("out", out);
+    doc.documentElement().setAttribute("width", m_scene->width());
+    doc.documentElement().setAttribute("height", m_scene->height());
     KTemporaryFile tmpfile;
     if (!tmpfile.open()) {
         kWarning() << "/////  CANNOT CREATE TMP FILE in: " << tmpfile.fileName();
@@ -165,10 +190,11 @@ bool TitleDocument::saveDocument(const KUrl& url, QGraphicsPolygonItem* startv,
     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, double *out)
+{
     QString tmpfile;
     QDomDocument doc;
-    if (!scene)
+    if (!m_scene)
         return -1;
 
     if (KIO::NetAccess::download(url, tmpfile, 0)) {
@@ -179,62 +205,98 @@ int TitleDocument::loadDocument(const KUrl& url, QGraphicsPolygonItem* startv, Q
         } else
             return -1;
         KIO::NetAccess::removeTempFile(tmpfile);
-        return loadFromXml(doc, startv, endv);
+        return loadFromXml(doc, startv, endv, out);
     }
     return -1;
 }
 
-int TitleDocument::loadFromXml(QDomDocument doc, QGraphicsPolygonItem* /*startv*/, QGraphicsPolygonItem* /*endv*/) {
+int TitleDocument::loadFromXml(QDomDocument doc, QGraphicsPolygonItem* startv, QGraphicsPolygonItem* endv, double *out)
+{
     QDomNodeList titles = doc.elementsByTagName("kdenlivetitle");
+    //TODO: Check if the opened title size is equal to project size, otherwise warn user and rescale
+    //TODO: get default title duration instead of hardcoded one
+    if (doc.documentElement().hasAttribute("out"))
+        *out = doc.documentElement().attribute("out").toDouble();
+    else
+        *out = 5000;
+
     int maxZValue = 0;
     if (titles.size()) {
 
         QDomNodeList items = titles.item(0).childNodes();
-        for (int i = 0;i < items.count();i++) {
+        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 (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());
+
+                    QDomNode node = txtProperties.namedItem("font-bold");
+                    if (!node.isNull()) {
+                        // Old: Bold/Not bold.
+                        font.setBold(node.nodeValue().toInt());
+                    } else {
+                        // New: Font weight (QFont::)
+                        font.setWeight(txtProperties.namedItem("font-weight").nodeValue().toInt());
+                    }
+                    //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 font.setPixelSize(txtProperties.namedItem("font-pixel-size").nodeValue().toInt());
+                    } else
+                        font.setPixelSize(txtProperties.namedItem("font-pixel-size").nodeValue().toInt());
                     QColor col(stringToColor(txtProperties.namedItem("font-color").nodeValue()));
-                    QGraphicsTextItem *txt = scene->addText(items.item(i).namedItem("content").firstChild().nodeValue(), font);
+                    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 = 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;
-                            }
+                } 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;
+                }
+            }
             //pos and transform
             if (gitem) {
                 QPointF p(items.item(i).namedItem("position").attributes().namedItem("x").nodeValue().toDouble(),
@@ -250,66 +312,76 @@ int TitleDocument::loadFromXml(QDomDocument doc, QGraphicsPolygonItem* /*startv*
                 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();
+                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() == "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);
-                }*/
+            } 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) {
+                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(',');
     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) {
+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) {
+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()
            );
 }