]> git.sesse.net Git - kdenlive/blobdiff - src/titlewidget.cpp
Fix title clip duration (1 frame offset):
[kdenlive] / src / titlewidget.cpp
index 3c7b15974a5a417310608c546ab8aa6dae3e3ba1..4bb5ddf62743c9138fc8535bc31ae1cbeabe814d 100644 (file)
@@ -18,7 +18,7 @@
 #include "titlewidget.h"
 #include "kdenlivesettings.h"
 #include "KoSliderCombo.h"
-
+#include "kthumb.h"
 #include <cmath>
 
 #include <KDebug>
@@ -38,6 +38,8 @@
 #include <QSignalMapper>
 #include <QTextBlockFormat>
 #include <QTextCursor>
+#include <QComboBox>
+#include <QCryptographicHash>
 
 #if QT_VERSION >= 0x040600
 #include <QGraphicsEffect>
@@ -45,6 +47,8 @@
 #include <QGraphicsDropShadowEffect>
 #endif
 
+static QList<TitleTemplate> titletemplates;
+
 int settingUp = false;
 
 const int IMAGEITEM = 7;
@@ -138,8 +142,9 @@ TitleWidget::TitleWidget(KUrl url, Timecode tc, QString projectTitlePath, Render
     m_frameHeight = render->renderHeight();
     showToolbars(TITLE_SELECT);
 
-    //TODO: get default title duration instead of hardcoded one
-    title_duration->setText(m_tc.getTimecode(GenTime(5000 / 1000.0)));
+    //If project is drop frame, set the input mask as such.
+    title_duration->setInputMask(m_tc.inputMask());
+    title_duration->setText(m_tc.reformatSeparators(KdenliveSettings::title_duration()));
 
     connect(backgroundColor, SIGNAL(clicked()), this, SLOT(slotChangeBackground())) ;
     connect(backgroundAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotChangeBackground())) ;
@@ -217,7 +222,6 @@ TitleWidget::TitleWidget(KUrl url, Timecode tc, QString projectTitlePath, Render
     connect(buttonAlignRight, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
     connect(buttonAlignCenter, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
     connect(buttonAlignNone, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
-    //connect(buttonInsertUnicode, SIGNAL(clicked()), this, SLOT(slotInsertUnicode()));
     connect(displayBg, SIGNAL(stateChanged(int)), this, SLOT(displayBackgroundFrame()));
 
     connect(m_unicodeDialog, SIGNAL(charSelected(QString)), this, SLOT(slotInsertUnicodeString(QString)));
@@ -268,13 +272,16 @@ TitleWidget::TitleWidget(KUrl url, Timecode tc, QString projectTitlePath, Render
     zDown->setDefaultAction(m_zDown);
 
     m_zTop = new QAction(KIcon("kdenlive-zindex-top"), QString(), this);
-    m_zTop->setShortcut(Qt::Key_Home);
+    // TODO mbt 1414: Shortcut should change z index only if
+    // cursor is NOT in a text field ...
+    //m_zTop->setShortcut(Qt::Key_Home);
     m_zTop->setToolTip(i18n("Raise object to top"));
     connect(m_zTop, SIGNAL(triggered()), this, SLOT(slotZIndexTop()));
     zTop->setDefaultAction(m_zTop);
 
     m_zBottom = new QAction(KIcon("kdenlive-zindex-bottom"), QString(), this);
-    m_zBottom->setShortcut(Qt::Key_End);
+    // TODO mbt 1414
+    //m_zBottom->setShortcut(Qt::Key_End);
     m_zBottom->setToolTip(i18n("Lower object to bottom"));
     connect(m_zBottom, SIGNAL(triggered()), this, SLOT(slotZIndexBottom()));
     zBottom->setDefaultAction(m_zBottom);
@@ -290,13 +297,13 @@ TitleWidget::TitleWidget(KUrl url, Timecode tc, QString projectTitlePath, Render
     origin_y_top->setToolTip(i18n("Invert y axis and change 0 point"));
     rectBColor->setToolTip(i18n("Select fill color"));
     rectFColor->setToolTip(i18n("Select border color"));
-    rectBAlpha->setToolTip(i18n("Fill transparency"));
-    rectFAlpha->setToolTip(i18n("Border transparency"));
+    rectBAlpha->setToolTip(i18n("Fill opacity"));
+    rectFAlpha->setToolTip(i18n("Border opacity"));
     zoom_slider->setToolTip(i18n("Zoom"));
     buttonRealSize->setToolTip(i18n("Original size (1:1)"));
     buttonFitZoom->setToolTip(i18n("Fit zoom"));
     backgroundColor->setToolTip(i18n("Select background color"));
-    backgroundAlpha->setToolTip(i18n("Background Transparency"));
+    backgroundAlpha->setToolTip(i18n("Background opacity"));
 
     itemhcenter->setIcon(KIcon("kdenlive-align-hor"));
     itemhcenter->setToolTip(i18n("Align item horizontally"));
@@ -422,8 +429,17 @@ TitleWidget::TitleWidget(KUrl url, Timecode tc, QString projectTitlePath, Render
     initAnimation();
     connect(anim_start, SIGNAL(toggled(bool)), this, SLOT(slotAnimStart(bool)));
     connect(anim_end, SIGNAL(toggled(bool)), this, SLOT(slotAnimEnd(bool)));
+    connect(templateBox, SIGNAL(currentIndexChanged(int)), this, SLOT(templateIndexChanged(int)));
 
     buttonBox->button(QDialogButtonBox::Ok)->setEnabled(KdenliveSettings::hastitleproducer());
+    refreshTitleTemplates();
+    //templateBox->setIconSize(QSize(60,60));
+    templateBox->clear();
+    templateBox->addItem("");
+    foreach(TitleTemplate t, titletemplates) {
+        templateBox->addItem(t.icon, t.name, t.file);
+    }
+    lastDocumentHash = QCryptographicHash::hash(xml().toString().toAscii(), QCryptographicHash::Md5).toHex();
 }
 
 TitleWidget::~TitleWidget()
@@ -491,7 +507,54 @@ QStringList TitleWidget::extractImageList(QString xml)
     return result;
 }
 
-
+// static
+QStringList TitleWidget::extractFontList(QString xml)
+{
+    QStringList result;
+    if (xml.isEmpty()) return result;
+    QDomDocument doc;
+    doc.setContent(xml);
+    QDomNodeList images = doc.elementsByTagName("content");
+    for (int i = 0; i < images.count(); i++) {
+        if (images.at(i).toElement().hasAttribute("font"))
+            result.append(images.at(i).toElement().attribute("font"));
+    }
+    return result;
+}
+//static
+void TitleWidget::refreshTitleTemplates()
+{
+    QStringList titlenamelist = QStringList() << i18n("None");
+    QStringList titlefiles = QStringList() << QString();
+    QStringList filters;
+    filters << "*.kdenlivetitle" ;
+    titletemplates.clear();
+    QStringList titleTemplates = KGlobal::dirs()->findDirs("appdata", "titles");
+    foreach(const QString &folder, titleTemplates) {
+        QStringList filesnames = QDir(folder).entryList(filters, QDir::Files);
+        foreach(const QString &fname, filesnames) {
+            //titlenamelist.append(fname);
+            //titlefiles.append(KUrl(folder).path(KUrl::AddTrailingSlash) + fname);
+            TitleTemplate t;
+            t.name = fname;
+            t.file = KUrl(folder).path(KUrl::AddTrailingSlash) + fname;
+            t.icon = QIcon(KThumb::getImage(t.file, 0, 60, 60));
+            titletemplates.append(t);
+        }
+    }
+    kDebug()  << titlenamelist << titlefiles;
+}
+void TitleWidget::templateIndexChanged(int index)
+{
+    QString item = templateBox->itemData(index).toString();
+    if (item != "") {
+        if (lastDocumentHash != QCryptographicHash::hash(xml().toString().toAscii(), QCryptographicHash::Md5).toHex()) {
+            if (KMessageBox::questionYesNo(this, i18n("Title was changed !\nDo you really want to load a new template?\nAll changes in this document are lost !!")) == KMessageBox::No) return;
+        }
+        loadTitle(item);
+        lastDocumentHash = QCryptographicHash::hash(xml().toString().toAscii(), QCryptographicHash::Md5).toHex();
+    }
+}
 //virtual
 void TitleWidget::resizeEvent(QResizeEvent * /*event*/)
 {
@@ -709,6 +772,7 @@ void TitleWidget::slotNewRect(QGraphicsRectItem * rect)
     f.setAlpha(rectFAlpha->value());
     QPen penf(f);
     penf.setWidth(rectLineWidth->value());
+    penf.setJoinStyle(Qt::RoundJoin);
     rect->setPen(penf);
     QColor b = rectBColor->color();
     b.setAlpha(rectBAlpha->value());
@@ -1469,6 +1533,7 @@ void TitleWidget::rectChanged()
         f.setAlpha(rectFAlpha->value());
         QPen penf(f);
         penf.setWidth(rectLineWidth->value());
+        penf.setJoinStyle(Qt::RoundJoin);
         rec->setPen(penf);
         QColor b = rectBColor->color();
         b.setAlpha(rectBAlpha->value());
@@ -1706,7 +1771,7 @@ void TitleWidget::saveTitle(KUrl url)
         delete fs;
     }
     if (!url.isEmpty()) {
-        if (m_titledocument.saveDocument(url, m_startViewport, m_endViewport, m_tc.getFrameCount(title_duration->text())) == false)
+        if (m_titledocument.saveDocument(url, m_startViewport, m_endViewport, m_tc.getFrameCount(title_duration->text()) - 1) == false)
             KMessageBox::error(this, i18n("Cannot write to file %1", url.path()));
     }
 }
@@ -1714,13 +1779,13 @@ void TitleWidget::saveTitle(KUrl url)
 QDomDocument TitleWidget::xml()
 {
     QDomDocument doc = m_titledocument.xml(m_startViewport, m_endViewport);
-    doc.documentElement().setAttribute("out", m_tc.getFrameCount(title_duration->text()));
+    doc.documentElement().setAttribute("out", m_tc.getFrameCount(title_duration->text()) - 1);
     return doc;
 }
 
-int TitleWidget::duration() const
+int TitleWidget::outPoint() const
 {
-    return m_tc.getFrameCount(title_duration->text());
+    return m_tc.getFrameCount(title_duration->text()) - 1;
 }
 
 void TitleWidget::setXml(QDomDocument doc)
@@ -1728,7 +1793,7 @@ void TitleWidget::setXml(QDomDocument doc)
     int out;
     m_count = m_titledocument.loadFromXml(doc, m_startViewport, m_endViewport, &out);
     adjustFrameSize();
-    title_duration->setText(m_tc.getTimecode(GenTime(out, m_render->fps())));
+    title_duration->setText(m_tc.getTimecode(GenTime(out + 1, m_render->fps())));
     /*if (doc.documentElement().hasAttribute("out")) {
     GenTime duration = GenTime(doc.documentElement().attribute("out").toDouble() / 1000.0);
     title_duration->setText(m_tc.getTimecode(duration));
@@ -1752,9 +1817,9 @@ void TitleWidget::setXml(QDomDocument doc)
                 x.rotatez = rotlist[2].toDouble();
 
                 // Try to adjust zoom
-                t.rotate(x.rotatex * (-1), Qt::XAxis);
-                t.rotate(x.rotatey * (-1), Qt::YAxis);
-                t.rotate(x.rotatez * (-1), Qt::ZAxis);
+                t.rotate(x.rotatex *(-1), Qt::XAxis);
+                t.rotate(x.rotatey *(-1), Qt::YAxis);
+                t.rotate(x.rotatez *(-1), Qt::ZAxis);
                 x.scalex = t.m11();
                 x.scaley = t.m22();
             } else {
@@ -2093,7 +2158,7 @@ void TitleWidget::slotFontText(const QString& s)
     // in older Qt versions.
 }
 
-void TitleWidget::slotEditTypewriter(int ix)
+void TitleWidget::slotEditTypewriter(int /*ix*/)
 {
     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
     if (l.size() == 1) {
@@ -2133,12 +2198,18 @@ void TitleWidget::slotEditShadow()
 #endif
 }
 
-qreal TitleWidget::zIndexBounds(bool maxBound)
+qreal TitleWidget::zIndexBounds(bool maxBound, bool intersectingOnly)
 {
     qreal bound = maxBound ? -99 : 99;
     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
     if (l.size() > 0) {
-        QList<QGraphicsItem*> lItems = graphicsView->scene()->items(l[0]->sceneBoundingRect(), Qt::IntersectsItemShape);
+        QList<QGraphicsItem*> lItems;
+        // Get items (all or intersecting only)
+        if (intersectingOnly) {
+            lItems = graphicsView->scene()->items(l[0]->sceneBoundingRect(), Qt::IntersectsItemShape);
+        } else {
+            lItems = graphicsView->scene()->items();
+        }
         if (lItems.size() > 0) {
             int n = lItems.size();
             qreal z;
@@ -2169,7 +2240,7 @@ void TitleWidget::slotZIndexUp()
     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
     if (l.size() >= 1) {
         qreal currentZ = l[0]->zValue();
-        qreal max = zIndexBounds(true);
+        qreal max = zIndexBounds(true, true);
         if (currentZ <= max) {
             l[0]->setZValue(currentZ + 1);
             updateDimension(l[0]);
@@ -2182,7 +2253,7 @@ void TitleWidget::slotZIndexTop()
     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
     if (l.size() >= 1) {
         qreal currentZ = l[0]->zValue();
-        qreal max = zIndexBounds(true);
+        qreal max = zIndexBounds(true, false);
         if (currentZ <= max) {
             l[0]->setZValue(max + 1);
             updateDimension(l[0]);
@@ -2195,7 +2266,7 @@ void TitleWidget::slotZIndexDown()
     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
     if (l.size() >= 1) {
         qreal currentZ = l[0]->zValue();
-        qreal min = zIndexBounds(false);
+        qreal min = zIndexBounds(false, true);
         if (currentZ >= min) {
             l[0]->setZValue(currentZ - 1);
             updateDimension(l[0]);
@@ -2208,7 +2279,7 @@ void TitleWidget::slotZIndexBottom()
     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
     if (l.size() >= 1) {
         qreal currentZ = l[0]->zValue();
-        qreal min = zIndexBounds(false);
+        qreal min = zIndexBounds(false, false);
         if (currentZ >= min) {
             l[0]->setZValue(min - 1);
             updateDimension(l[0]);