X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Ftitledocument.cpp;h=8774ac8fe5ef3835085e164ec94a27b1c74bc49d;hb=f40d5c236532a8bbb9099fd53b3f7c56edb5ecad;hp=ed9bc0b2815d9f6ce85e485a0d7d6464272ea913;hpb=6e66b0a3c76db9f2ca1e115bfef1ba75859c855f;p=kdenlive diff --git a/src/titledocument.cpp b/src/titledocument.cpp index ed9bc0b2..8774ac8f 100644 --- a/src/titledocument.cpp +++ b/src/titledocument.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -30,19 +31,37 @@ #include #include #include +#include +#include #include #include #include +#include + #if QT_VERSION >= 0x040600 #include #include #include #endif +QByteArray fileToByteArray(const QString& filename) +{ + QByteArray ret; + QFile file(filename); + if (file.open(QIODevice::ReadOnly)) { + while (!file.atEnd()) { + ret.append(file.readLine()); + } + } + return ret; +} + TitleDocument::TitleDocument() { m_scene = NULL; + m_width = 0; + m_height = 0; } void TitleDocument::setScene(QGraphicsScene* _scene, int width, int height) @@ -52,16 +71,66 @@ void TitleDocument::setScene(QGraphicsScene* _scene, int width, int height) m_height = height; } -QDomDocument TitleDocument::xml(QGraphicsRectItem* startv, QGraphicsRectItem* endv) +int TitleDocument::base64ToUrl(QGraphicsItem* item, QDomElement& content, bool embed) +{ + if (embed) { + if (!item->data(Qt::UserRole + 1).toString().isEmpty()) { + content.setAttribute("base64", item->data(Qt::UserRole + 1).toString()); + } else if (!item->data(Qt::UserRole).toString().isEmpty()) { + content.setAttribute("base64", fileToByteArray(item->data(Qt::UserRole).toString()).toBase64().data()); + } + content.removeAttribute("url"); + } else { + // save for project files to disk + QString base64 = item->data(Qt::UserRole + 1).toString(); + if (!base64.isEmpty()) { + QString titlePath; + if (!m_projectPath.isEmpty()) { + titlePath = m_projectPath; + } else { + titlePath = "/tmp/titles"; + } + QString filename = extractBase64Image(titlePath, base64); + if (!filename.isEmpty()) { + content.setAttribute("url", filename); + content.removeAttribute("base64"); + } + + } else { + return 1; + } + } + return 0; +} + + +//static +const QString TitleDocument::extractBase64Image(const QString &titlePath, const QString &data) +{ + QString filename = titlePath + QString(QCryptographicHash::hash(data.toAscii(), QCryptographicHash::Md5).toHex().append(".titlepart")); + KStandardDirs::makeDir(titlePath); + QFile f(filename); + if (f.open(QIODevice::WriteOnly)) { + f.write(QByteArray::fromBase64(data.toAscii())) ; + f.close(); + return filename; + } + return QString(); +} + +QDomDocument TitleDocument::xml(QGraphicsRectItem* startv, QGraphicsRectItem* endv, bool embed) { QDomDocument doc; QDomElement main = doc.createElement("kdenlivetitle"); main.setAttribute("width", m_width); main.setAttribute("height", m_height); + // Save locale + const char *locale = setlocale(LC_NUMERIC, NULL); + main.setAttribute("LC_NUMERIC", locale); doc.appendChild(main); - foreach(QGraphicsItem* item, m_scene->items()) { + foreach(QGraphicsItem * item, m_scene->items()) { QDomElement e = doc.createElement("item"); QDomElement content = doc.createElement("content"); QFont font; @@ -71,10 +140,12 @@ QDomDocument TitleDocument::xml(QGraphicsRectItem* startv, QGraphicsRectItem* en case 7: e.setAttribute("type", "QGraphicsPixmapItem"); content.setAttribute("url", item->data(Qt::UserRole).toString()); + base64ToUrl(item, content, embed); break; case 13: e.setAttribute("type", "QGraphicsSvgItem"); content.setAttribute("url", item->data(Qt::UserRole).toString()); + base64ToUrl(item, content, embed); break; case 3: e.setAttribute("type", "QGraphicsRectItem"); @@ -102,11 +173,16 @@ QDomDocument TitleDocument::xml(QGraphicsRectItem* startv, QGraphicsRectItem* en QColor fontcolor = cursor.charFormat().foreground().color(); content.setAttribute("font-color", colorToString(fontcolor)); if (!t->data(101).isNull()) content.setAttribute("font-outline", t->data(101).toDouble()); - if (!t->data(102).isNull()) content.setAttribute("font-outline-color", colorToString(QColor(t->data(102).toString()))); + if (!t->data(102).isNull()) { + QVariant variant = t->data(102); + QColor outlineColor = variant.value(); + content.setAttribute("font-outline-color", colorToString(outlineColor)); + } } if (!t->data(100).isNull()) { QStringList effectParams = t->data(100).toStringList(); QString effectName = effectParams.takeFirst(); + content.setAttribute("textwidth", t->sceneBoundingRect().width()); content.setAttribute(effectName, effectParams.join(";")); } @@ -209,20 +285,23 @@ QColor TitleDocument::getBackgroundColor() } -bool TitleDocument::saveDocument(const KUrl& url, QGraphicsRectItem* startv, QGraphicsRectItem* endv, int out) +bool TitleDocument::saveDocument(const KUrl& url, QGraphicsRectItem* startv, QGraphicsRectItem* endv, int duration, bool embed) { if (!m_scene) return false; - QDomDocument doc = xml(startv, endv); - doc.documentElement().setAttribute("out", out); + QDomDocument doc = xml(startv, endv, embed); + doc.documentElement().setAttribute("duration", duration); + // keep some time for backwards compatibility (opening projects with older versions) - 26/12/12 + doc.documentElement().setAttribute("out", duration); KTemporaryFile tmpfile; if (!tmpfile.open()) { kWarning() << "///// CANNOT CREATE TMP FILE in: " << tmpfile.fileName(); return false; } QFile xmlf(tmpfile.fileName()); - xmlf.open(QIODevice::WriteOnly); + if (!xmlf.open(QIODevice::WriteOnly)) + return false; xmlf.write(doc.toString().toUtf8()); if (xmlf.error() != QFile::NoError) { xmlf.close(); @@ -232,8 +311,9 @@ bool TitleDocument::saveDocument(const KUrl& url, QGraphicsRectItem* startv, QGr return KIO::NetAccess::upload(tmpfile.fileName(), url, 0); } -int TitleDocument::loadFromXml(QDomDocument doc, QGraphicsRectItem* startv, QGraphicsRectItem* endv, int *out) +int TitleDocument::loadFromXml(QDomDocument doc, QGraphicsRectItem* startv, QGraphicsRectItem* endv, int *duration, const QString& projectpath) { + m_projectPath = projectpath; QDomNodeList titles = doc.elementsByTagName("kdenlivetitle"); //TODO: Check if the opened title size is equal to project size, otherwise warn user and rescale if (doc.documentElement().hasAttribute("width") && doc.documentElement().hasAttribute("height")) { @@ -245,12 +325,24 @@ int TitleDocument::loadFromXml(QDomDocument doc, QGraphicsRectItem* startv, QGra m_width = doc_width; m_height = doc_height; } + } else { + // Document has no size info, it is likely an old version title, so ignore viewport data + QDomNodeList viewportlist = doc.documentElement().elementsByTagName("startviewport"); + if (!viewportlist.isEmpty()) { + doc.documentElement().removeChild(viewportlist.at(0)); + } + viewportlist = doc.documentElement().elementsByTagName("endviewport"); + if (!viewportlist.isEmpty()) { + doc.documentElement().removeChild(viewportlist.at(0)); + } } //TODO: get default title duration instead of hardcoded one - if (doc.documentElement().hasAttribute("out")) - *out = doc.documentElement().attribute("out").toInt(); + if (doc.documentElement().hasAttribute("duration")) + *duration = doc.documentElement().attribute("duration").toInt(); + else if (doc.documentElement().hasAttribute("out")) + *duration = doc.documentElement().attribute("out").toInt(); else - *out = 125; + *duration = 125; int maxZValue = 0; if (titles.size()) { @@ -333,20 +425,45 @@ int TitleDocument::loadFromXml(QDomDocument doc, QGraphicsRectItem* startv, QGra 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))); + QGraphicsRectItem *rec = m_scene->addRect(stringToRect(rect), QPen(QBrush(stringToColor(pen_str)), penwidth, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin), 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); + QString base64 = items.item(i).namedItem("content").attributes().namedItem("base64").nodeValue(); + QPixmap pix; + if (base64.isEmpty()) { + pix.load(url); + } else { + pix.loadFromData(QByteArray::fromBase64(base64.toAscii())); + } QGraphicsPixmapItem *rec = m_scene->addPixmap(pix); + rec->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); rec->setData(Qt::UserRole, url); + if (!base64.isEmpty()) { + rec->setData(Qt::UserRole + 1, base64); + } 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; + QString base64 = items.item(i).namedItem("content").attributes().namedItem("base64").nodeValue(); + QGraphicsSvgItem *rec = NULL; + if (base64.isEmpty()) { + rec = new QGraphicsSvgItem(url); + } else { + rec = new QGraphicsSvgItem(); + QSvgRenderer *renderer = new QSvgRenderer(QByteArray::fromBase64(base64.toAscii()), rec); + rec->setSharedRenderer(renderer); + //QString elem=rec->elementId(); + //QRectF bounds = renderer->boundsOnElement(elem); + } + if (rec) { + m_scene->addItem(rec); + rec->setData(Qt::UserRole, url); + if (!base64.isEmpty()) { + rec->setData(Qt::UserRole + 1, base64); + } + gitem = rec; + } } } //pos and transform