+0.8.2.1
+ * Fix title text oultine transparency not working
+ * Make titler window fit on smaller resolutions (1024x768)
+ * Fix corruption when undoing and redoing a transition add + move
+ * Fix possible crash in thumbnails
+ * Fix possible crashes in clip transcoding and improve feedback when failing
+ * Various small optimizations (unnecessary clip reloads)
+ * Fix timecode widget hard to edit and sometimes giving random values
+ * Workaround locale issue ahappening when system C locale and Qt's locale did not give the same numeric separator
+ * Fix audio thumbnail concurrency issue
+ * Fix various video thumbnails issues (don't load several times the same thumb, load all of them, ...)
+ * Fix crash when opening a file dialog on KDE < 4.5
+ * Fix various proxy issues (missing extension, concurrency, disabling broken proxy, ...)
+ * Fix startup crash caused by invalid parsing of v4l data
+ * Fix project tree disabled after loading some projects / creating new one
+ * Fix corrupted timeline / monitor timecode
+ * Fix search path for Luma files when missing
+
0.8.2
* Load zone thumbnails from disk if available.
* Optimise document loading.
resample
mono
-dynamictext
# Effects need extra GUI to create the resulting melt.xml with the corrected content
videostab
chroma.xml
crop.xml
dust.xml
+dynamictext.xml
freeze.xml
gamma.xml
grain.xml
- multiple choice
- represented by a drop-down menu
- additional parameter attribute:
- - "paramlist": list of possible values separated by comma (no whitespaces!)
+ - "paramlist": list of possible values separated by semicolon (no whitespaces!)
- addtional tag:
- - "paramlistdisplay": (optional) list of names to use for the values
+ - "paramlistdisplay": (optional) list of names to use for the values separated by comma
- "position":
- time stored as frame number
- represented by a slider
- "color":
- - color value, similar to representation HTML ("#rrggbb" or "0xrrggbb")
+ - color value, similar to representation HTML ("#rrggbb"/"#aarrggbb" or "0xrrggbbaa")
- represented by a button opening the KDE color dialog + a color picker button
+ - additional attributes:
+ - "alpha": (default = "0") use to enable alpha support
- "keyframe":
- keyframable number
- keyframes are opt-in (only one keyframe by default -> should be prefered over "constant" whenever possible)
- cubic Bézier spline editor for the frei0r color curves filter (new version, might be reused for other filters)
- "roto-spline":
- GUI for the rotoscoping filter (spline on the monitor)
+ - "keywords":
+ - Text entry with a selection of possible keywords to be inserted in the text.
+ - additional tags:
+ - "keywords": list of possible keyword values separated by semicolon
+ - "keywordsdisplay": list of names to use for the values separated by semicolon
+ - "fontfamily":
+ - Font typeface entry
==========
==========
--- /dev/null
+<!DOCTYPE kpartgui>
+<effect tag="dynamictext" id="dynamictext">
+ <name>Dynamic Text</name>
+ <description>Overlay text with keywords replaced</description>
+ <author>Brian Matherly</author>
+ <parameter type="geometry" name="geometry" default="0%/0%:100%x100%:100" fixed="0">
+ <name>Geometry</name>
+ </parameter>
+ <parameter type="fontfamily" name="family" default="Sans">
+ <name>Font Family</name>
+ </parameter>
+ <parameter type="constant" name="size" max="200" min="8" default="48">
+ <name>Font Size</name>
+ </parameter>
+ <parameter type="constant" name="weight" max="900" min="100" default="400">
+ <name>Font Weight</name>
+ </parameter>
+ <parameter type="color" name="fgcolour" default="0x000000ff" alpha="1">
+ <name>Foreground Color</name>
+ </parameter>
+ <parameter type="color" name="bgcolour" default="0x00000020" alpha="1">
+ <name>Background Color</name>
+ </parameter>
+ <parameter type="color" name="olcolour" default="0x00000000" alpha="1">
+ <name>Outline Color</name>
+ </parameter>
+ <parameter type="constant" name="outline" max="3" min="0" default="0">
+ <name>Outline Width</name>
+ </parameter>
+ <parameter type="constant" name="pad" max="500" min="0" default="0">
+ <name>Padding</name>
+ </parameter>
+ <parameter type="list" name="halign" default="left" paramlist="left;centre;right">
+ <paramlistdisplay>Left,Center,Right</paramlistdisplay>
+ <name>Horizontal Alignment</name>
+ </parameter>
+ <parameter type="list" name="valign" default="top" paramlist="top;middle;bottom">
+ <paramlistdisplay>Top,Middle,Bottom</paramlistdisplay>
+ <name>Vertical Alignment</name>
+ </parameter>
+ <parameter type="keywords" name="argument" default="#timecode#">
+ <name>Text</name>
+ <keywords>#timecode#;#frame#;#filedate#;#meta.media.0.stream.frame_rate#;#meta.media.0.codec.name#;#meta.media.0.codec.bit_rate#;#meta.media.width#;#meta.media.height#;#meta.attr.comment.markup#</keywords>
+ <keywordsdisplay>timecode;frame;file date;source frame rate;source codec;source bit rate;source width;source height;source comment</keywordsdisplay>
+ </parameter>
+</effect>
widgets/wizardextra_ui.ui
widgets/wizardmltcheck_ui.ui
widgets/wizardstandard_ui.ui
+ widgets/keywordval_ui.ui
+ widgets/fontval_ui.ui
)
if(OPENGL_FOUND)
#include <KColorButton>
#include <KLocalizedString>
+#include <kdeversion.h>
+static QColor stringToColor(QString strColor)
+{
+ bool ok = false;
+ QColor color("black");
+ int intval = 0;
+
+ if (strColor.startsWith("0x")) {
+ // Format must be 0xRRGGBBAA
+ intval = strColor.toUInt(&ok, 16);
+ color.setRgb( ( intval >> 24 ) & 0xff, // r
+ ( intval >> 16 ) & 0xff, // g
+ ( intval >> 8 ) & 0xff, // b
+ ( intval ) & 0xff ); // a
+ } else if (strColor.startsWith("#") && strColor.length() == 9) {
+ // Format must be #AARRGGBB
+ strColor = strColor.replace('#', "0x");
+ intval = strColor.toUInt(&ok, 16);
+ color.setRgb( ( intval >> 16 ) & 0xff, // r
+ ( intval >> 8 ) & 0xff, // g
+ ( intval ) & 0xff, // b
+ ( intval >> 24 ) & 0xff ); // a
+ } else if (strColor.startsWith("#") && strColor.length() == 7) {
+ // Format must be #RRGGBB
+ strColor = strColor.replace('#', "0x");
+ intval = strColor.toUInt(&ok, 16);
+ color.setRgb( ( intval >> 16 ) & 0xff, // r
+ ( intval >> 8 ) & 0xff, // g
+ ( intval ) & 0xff, // b
+ 0xff ); // a
+ }
+
+ return color;
+}
-ChooseColorWidget::ChooseColorWidget(QString text, QColor color, QWidget *parent) :
+static QString colorToString(QColor color, bool alpha)
+{
+ QString colorStr;
+ QTextStream stream(&colorStr);
+ stream << "#";
+ stream.setIntegerBase(16);
+ stream.setFieldWidth(2);
+ stream.setFieldAlignment(QTextStream::AlignRight);
+ stream.setPadChar('0');
+ if(alpha)
+ {
+ stream << color.alpha();
+ }
+ stream << color.red() << color.green() << color.blue();
+
+ return colorStr;
+}
+
+ChooseColorWidget::ChooseColorWidget(QString text, QString color, QWidget *parent) :
QWidget(parent)
{
QHBoxLayout *layout = new QHBoxLayout(this);
layout->setSpacing(0);
QLabel *label = new QLabel(text, this);
- m_button = new KColorButton(color, this);
- m_button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
- ColorPickerWidget *picker = new ColorPickerWidget(this);
+
+ QWidget *rightSide = new QWidget(this);
+ QHBoxLayout *rightSideLayout = new QHBoxLayout(rightSide);
+ rightSideLayout->setContentsMargins(0, 0, 0, 0);
+ rightSideLayout->setSpacing(0);
+
+ m_button = new KColorButton(stringToColor(color), rightSide);
+// m_button->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
+ ColorPickerWidget *picker = new ColorPickerWidget(rightSide);
layout->addWidget(label);
- layout->addWidget(m_button);
- layout->addWidget(picker, 0, Qt::AlignRight);
+ layout->addWidget(rightSide);
+ rightSideLayout->addWidget(m_button);
+ rightSideLayout->addWidget(picker, 0, Qt::AlignRight);
connect(picker, SIGNAL(colorPicked(QColor)), this, SLOT(setColor(QColor)));
connect(picker, SIGNAL(displayMessage(const QString&, int)), this, SIGNAL(displayMessage(const QString&, int)));
connect(m_button, SIGNAL(changed(QColor)), this, SIGNAL(modified()));
}
-QColor ChooseColorWidget::getColor()
+QString ChooseColorWidget::getColor()
+{
+ bool alphaChannel = false;
+#if KDE_IS_VERSION(4,5,0)
+ alphaChannel = m_button->isAlphaChannelEnabled();
+#endif
+ return colorToString(m_button->color(), alphaChannel);
+}
+
+void ChooseColorWidget::setAlphaChannelEnabled(bool enabled)
{
- return m_button->color();
+#if KDE_IS_VERSION(4,5,0)
+ m_button->setAlphaChannelEnabled(enabled);
+#endif
}
void ChooseColorWidget::setColor(QColor color)
/** @brief Sets up the widget.
* @param text (optional) What the color will be used for
* @param color (optional) initial color */
- ChooseColorWidget(QString text = QString(), QColor color = QColor(), QWidget* parent = 0);
+ ChooseColorWidget(QString text = QString(), QString color = "0xffffffff", QWidget* parent = 0);
/** @brief Gets the choosen color. */
- QColor getColor();
+ QString getColor();
+ /** @brief Enable the use of alpha channel.
+ * @param enabled (required) whether alpha is enabled or disabled */
+ void setAlphaChannelEnabled(bool enabled);
private:
KColorButton *m_button;
ClipItem::~ClipItem()
{
blockSignals(true);
+ m_endThumbTimer.stop();
+ m_startThumbTimer.stop();
if (scene()) scene()->removeItem(this);
if (m_clipType == VIDEO || m_clipType == AV || m_clipType == SLIDESHOW || m_clipType == PLAYLIST) {
//disconnect(m_clip->thumbProducer(), SIGNAL(thumbReady(int, QImage)), this, SLOT(slotThumbReady(int, QImage)));
if (!frames.isEmpty()) m_clip->slotExtractImage(frames);
}
+void ClipItem::stopThumbs()
+{
+ // Clip is about to be deleted, make sure we don't request thumbnails
+ disconnect(&m_startThumbTimer, SIGNAL(timeout()), this, SLOT(slotGetStartThumb()));
+ disconnect(&m_endThumbTimer, SIGNAL(timeout()), this, SLOT(slotGetEndThumb()));
+}
+
void ClipItem::slotGetStartThumb()
{
m_startThumbRequested = true;
* Which producer is returned depends on the type of this clip (audioonly, videoonly, normal) */
Mlt::Producer *getProducer(int track, bool trackSpecific = true);
void resetFrameWidth(int width);
+ /** @brief Clip is about to be deleted, block thumbs. */
+ void stopThumbs();
protected:
//virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
QObject(),
m_audioThumbsQueue(),
m_doc(doc),
- m_generatingAudioId(),
m_abortThumb(false),
- m_closing(false)
+ m_closing(false),
+ m_abortAudioThumb(false)
{
m_clipIdCounter = 1;
m_folderIdCounter = 1;
{
m_closing = true;
m_abortThumb = true;
+ m_abortAudioThumb = true;
m_thumbsThread.waitForFinished();
+ m_audioThumbsThread.waitForFinished();
m_thumbsMutex.lock();
m_requestedThumbs.clear();
- m_thumbsMutex.unlock();
m_audioThumbsQueue.clear();
- m_generatingAudioId.clear();
- m_thumbsMutex.lock();
- m_requestedThumbs.clear();
m_thumbsMutex.unlock();
+
qDeleteAll(m_clipList);
m_clipList.clear();
#if KDE_IS_VERSION(4,5,0)
void ClipManager::clear()
{
m_abortThumb = true;
+ m_abortAudioThumb = true;
m_thumbsThread.waitForFinished();
+ m_audioThumbsThread.waitForFinished();
m_thumbsMutex.lock();
m_requestedThumbs.clear();
+ m_audioThumbsQueue.clear();
m_thumbsMutex.unlock();
m_abortThumb = false;
+ m_abortAudioThumb = false;
m_folderList.clear();
- m_audioThumbsQueue.clear();
m_modifiedClips.clear();
qDeleteAll(m_clipList);
m_clipList.clear();
void ClipManager::stopThumbs(const QString &id)
{
- if (m_requestedThumbs.isEmpty() || m_closing) return;
+ if (m_closing || (m_requestedThumbs.isEmpty() && m_processingThumbId != id && m_audioThumbsQueue.isEmpty() && m_processingAudioThumbId != id)) return;
+ // Abort video thumbs for this clip
m_abortThumb = true;
m_thumbsThread.waitForFinished();
m_thumbsMutex.lock();
m_requestedThumbs.remove(id);
+ m_audioThumbsQueue.removeAll(id);
m_thumbsMutex.unlock();
m_abortThumb = false;
- if (!m_thumbsThread.isRunning()) {
+
+ // Abort audio thumbs for this clip
+ if (m_processingAudioThumbId == id) {
+ m_abortAudioThumb = true;
+ m_audioThumbsThread.waitForFinished();
+ m_abortAudioThumb = false;
+ }
+
+ if (!m_thumbsThread.isRunning() && !m_requestedThumbs.isEmpty()) {
m_thumbsThread = QtConcurrent::run(this, &ClipManager::slotGetThumbs);
}
+
+ if (!m_audioThumbsThread.isRunning() && !m_audioThumbsQueue.isEmpty()) {
+ m_audioThumbsThread = QtConcurrent::run(this, &ClipManager::slotGetAudioThumbs);
+ }
}
void ClipManager::slotGetThumbs()
{
- QMap<QString, int>::iterator i = m_requestedThumbs.begin();
+ QMap<QString, int>::const_iterator i;
int max;
int done = 0;
- while (i != m_requestedThumbs.end() && !m_abortThumb) {
- QString producerId = i.key();
+ while (!m_requestedThumbs.isEmpty() && !m_abortThumb) {
m_thumbsMutex.lock();
- QList<int> values = m_requestedThumbs.values(producerId);
- m_requestedThumbs.remove(producerId);
- i = m_requestedThumbs.begin();
+ i = m_requestedThumbs.constBegin();
+ m_processingThumbId = i.key();
+ QList<int> values = m_requestedThumbs.values(m_processingThumbId);
+ m_requestedThumbs.remove(m_processingThumbId);
m_thumbsMutex.unlock();
qSort(values);
- DocClipBase *clip = getClipById(producerId);
+ DocClipBase *clip = getClipById(m_processingThumbId);
if (!clip) continue;
max = m_requestedThumbs.size() + values.count();
while (!values.isEmpty() && clip->thumbProducer() && !m_abortThumb) {
if (max > 3) emit displayMessage(i18n("Loading thumbnails"), 100 * done / max);
}
}
+ m_processingThumbId.clear();
emit displayMessage(QString(), -1);
}
void ClipManager::checkAudioThumbs()
{
if (!KdenliveSettings::audiothumbnails()) {
- if (!m_generatingAudioId.isEmpty()) {
- DocClipBase *clip = getClipById(m_generatingAudioId);
- if (clip) clip->slotClearAudioCache();
+ if (m_audioThumbsThread.isRunning()) {
+ m_abortAudioThumb = true;
+ m_thumbsMutex.lock();
+ m_audioThumbsQueue.clear();
+ m_thumbsMutex.unlock();
+ m_audioThumbsThread.waitForFinished();
+ m_abortAudioThumb = false;
}
- m_audioThumbsQueue.clear();
- m_generatingAudioId.clear();
return;
}
+ m_thumbsMutex.lock();
for (int i = 0; i < m_clipList.count(); i++) {
- m_audioThumbsQueue.append(m_clipList.at(i)->getId());
+ DocClipBase *clip = m_clipList.at(i);
+ if (clip->hasAudioThumb() && !clip->audioThumbCreated())
+ m_audioThumbsQueue.append(m_clipList.at(i)->getId());
+ }
+ m_thumbsMutex.unlock();
+ if (!m_audioThumbsThread.isRunning() && !m_audioThumbsQueue.isEmpty()) {
+ m_audioThumbsThread = QtConcurrent::run(this, &ClipManager::slotGetAudioThumbs);
}
- if (m_generatingAudioId.isEmpty()) startAudioThumbsGeneration();
}
void ClipManager::askForAudioThumb(const QString &id)
{
DocClipBase *clip = getClipById(id);
- if (clip && KdenliveSettings::audiothumbnails()) {
- m_audioThumbsQueue.append(id);
- if (m_generatingAudioId.isEmpty()) startAudioThumbsGeneration();
+ if (clip && KdenliveSettings::audiothumbnails() && (clip->hasAudioThumb())) {
+ m_thumbsMutex.lock();
+ if (!m_audioThumbsQueue.contains(id)) m_audioThumbsQueue.append(id);
+ m_thumbsMutex.unlock();
+ if (!m_audioThumbsThread.isRunning()) m_audioThumbsThread = QtConcurrent::run(this, &ClipManager::slotGetAudioThumbs);
}
}
-void ClipManager::startAudioThumbsGeneration()
+void ClipManager::slotGetAudioThumbs()
{
- if (!KdenliveSettings::audiothumbnails()) {
- m_audioThumbsQueue.clear();
- m_generatingAudioId.clear();
- return;
- }
- if (!m_audioThumbsQueue.isEmpty()) {
- m_generatingAudioId = m_audioThumbsQueue.takeFirst();
- DocClipBase *clip = getClipById(m_generatingAudioId);
- if (!clip || !clip->slotGetAudioThumbs())
- endAudioThumbsGeneration(m_generatingAudioId);
- } else {
- m_generatingAudioId.clear();
- }
-}
+ Mlt::Profile prof((char*) KdenliveSettings::current_profile().toUtf8().constData());
+ mlt_audio_format audioFormat = mlt_audio_pcm;
+ while (!m_abortAudioThumb && !m_audioThumbsQueue.isEmpty()) {
+ m_thumbsMutex.lock();
+ m_processingAudioThumbId = m_audioThumbsQueue.takeFirst();
+ m_thumbsMutex.unlock();
+ DocClipBase *clip = getClipById(m_processingAudioThumbId);
+ if (!clip || clip->audioThumbCreated()) continue;
+ KUrl url = clip->fileURL();
+ QString hash = clip->getClipHash();
+ if (hash.isEmpty()) continue;
+ QString audioPath = projectFolder() + "/thumbs/" + hash + ".thumb";
+ double lengthInFrames = clip->duration().frames(m_doc->fps());
+ //FIXME: should this be hardcoded??
+ int channels = 2;
+ int frequency = 48000;
+ int arrayWidth = 20;
+ double frame = 0.0;
+ audioByteArray storeIn;
+ QFile f(audioPath);
+ if (QFileInfo(audioPath).size() > 0 && f.open(QIODevice::ReadOnly)) {
+ const QByteArray channelarray = f.readAll();
+ f.close();
+ if (channelarray.size() != arrayWidth*(frame + lengthInFrames) * channels) {
+ kDebug() << "--- BROKEN THUMB FOR: " << url.fileName() << " ---------------------- ";
+ f.remove();
+ continue;
+ }
+ kDebug() << "reading audio thumbs from file";
+
+ int h1 = arrayWidth * channels;
+ int h2 = (int) frame * h1;
+ int h3;
+ for (int z = (int) frame; z < (int)(frame + lengthInFrames) && !m_abortAudioThumb; z++) {
+ h3 = 0;
+ for (int c = 0; c < channels; c++) {
+ QByteArray audioArray(arrayWidth, '\x00');
+ for (int i = 0; i < arrayWidth; i++) {
+ audioArray[i] = channelarray.at(h2 + h3 + i);
+ }
+ h3 += arrayWidth;
+ storeIn[z][c] = audioArray;
+ }
+ h2 += h1;
+ }
+ if (!m_abortAudioThumb) clip->updateAudioThumbnail(storeIn);
+ continue;
+ }
+
+ if (!f.open(QIODevice::WriteOnly)) {
+ kDebug() << "++++++++ ERROR WRITING TO FILE: " << audioPath;
+ kDebug() << "++++++++ DISABLING AUDIO THUMBS";
+ m_thumbsMutex.lock();
+ m_audioThumbsQueue.clear();
+ m_thumbsMutex.unlock();
+ KdenliveSettings::setAudiothumbnails(false);
+ break;
+ }
-void ClipManager::endAudioThumbsGeneration(const QString &requestedId)
-{
- if (!KdenliveSettings::audiothumbnails()) {
- m_audioThumbsQueue.clear();
- m_generatingAudioId.clear();
- return;
- }
- if (!m_audioThumbsQueue.isEmpty()) {
- if (m_generatingAudioId == requestedId) {
- startAudioThumbsGeneration();
+ Mlt::Producer producer(prof, url.path().toUtf8().constData());
+ if (!producer.is_valid()) {
+ kDebug() << "++++++++ INVALID CLIP: " << url.path();
+ continue;
+ }
+
+ if (KdenliveSettings::normaliseaudiothumbs()) {
+ Mlt::Filter m_convert(prof, "volume");
+ m_convert.set("gain", "normalise");
+ producer.attach(m_convert);
+ }
+
+ int last_val = 0;
+ int val = 0;
+ double framesPerSecond = mlt_producer_get_fps(producer.get_producer());
+ Mlt::Frame *mlt_frame;
+
+ for (int z = (int) frame; z < (int)(frame + lengthInFrames) && producer.is_valid() && !m_abortAudioThumb; z++) {
+ val = (int)((z - frame) / (frame + lengthInFrames) * 100.0);
+ if (last_val != val && val > 1) {
+ setThumbsProgress(i18n("Creating audio thumbnail for %1", url.fileName()), val);
+ last_val = val;
+ }
+ producer.seek(z);
+ mlt_frame = producer.get_frame();
+ if (mlt_frame && mlt_frame->is_valid()) {
+ int samples = mlt_sample_calculator(framesPerSecond, frequency, mlt_frame_get_position(mlt_frame->get_frame()));
+ qint16* pcm = static_cast<qint16*>(mlt_frame->get_audio(audioFormat, frequency, channels, samples));
+ for (int c = 0; c < channels; c++) {
+ QByteArray audioArray;
+ audioArray.resize(arrayWidth);
+ for (int i = 0; i < audioArray.size(); i++) {
+ audioArray[i] = ((*(pcm + c + i * samples / audioArray.size())) >> 9) + 127 / 2 ;
+ }
+ f.write(audioArray);
+ storeIn[z][c] = audioArray;
+ }
+ } else {
+ f.write(QByteArray(arrayWidth, '\x00'));
+ }
+ delete mlt_frame;
+ }
+ f.close();
+ setThumbsProgress(i18n("Creating audio thumbnail for %1", url.fileName()), -1);
+ if (m_abortAudioThumb) {
+ f.remove();
+ } else {
+ clip->updateAudioThumbnail(storeIn);
}
- } else {
- m_generatingAudioId.clear();
}
+ m_processingAudioThumbId.clear();
}
void ClipManager::setThumbsProgress(const QString &message, int progress)
int getFreeClipId();
int getFreeFolderId();
int lastClipId() const;
- void startAudioThumbsGeneration();
- void endAudioThumbsGeneration(const QString &requestedId);
void askForAudioThumb(const QString &id);
QString projectFolder() const;
void clearUnusedProducers();
/** Check the list of externally modified clips, and process them if they were not modified in the last 1500 milliseconds */
void slotProcessModifiedClips();
void slotGetThumbs();
+ void slotGetAudioThumbs();
private: // Private attributes
/** the list of clips in the document */
KdenliveDoc *m_doc;
int m_clipIdCounter;
int m_folderIdCounter;
- QString m_generatingAudioId;
KDirWatch m_fileWatcher;
/** Timer used to reload clips when they have been externally modified */
QTimer m_modifiedTimer;
QMap <QString, int> m_requestedThumbs;
QMutex m_thumbsMutex;
QFuture<void> m_thumbsThread;
+ /** @brief The id of currently processed clip for thumbs creation. */
+ QString m_processingThumbId;
/** @brief If true, abort processing of clip thumbs before removing a clip. */
bool m_abortThumb;
/** @brief We are about to delete the clip producer, stop processing thumbs. */
bool m_closing;
+ QFuture<void> m_audioThumbsThread;
+ /** @brief If true, abort processing of audio thumbs. */
+ bool m_abortAudioThumb;
+ /** @brief The id of currently processed clip for audio thumbs creation. */
+ QString m_processingAudioThumbId;
signals:
void reloadClip(const QString &);
m_view.clip_filesize->setHidden(true);
m_view.label_size->setHidden(true);
}
- m_view.clip_duration->setInputMask("");
- m_view.clip_duration->setValidator(tc.validator());
+ m_view.clip_duration->setInputMask(tc.mask());
m_view.clip_duration->setText(tc.getTimecode(m_clip->duration()));
if (t != IMAGE && t != COLOR && t != TEXT) m_view.clip_duration->setReadOnly(true);
else {
void ClipProperties::slotApplyProperties()
{
- if (m_clip != NULL)
- emit applyNewClipProperties(m_clip->getId(), m_clip->properties(), properties(), needsTimelineRefresh(), needsTimelineReload());
+ if (m_clip != NULL) {
+ QMap <QString, QString> props = properties();
+ emit applyNewClipProperties(m_clip->getId(), m_clip->currentProperties(props), props, needsTimelineRefresh(), needsTimelineReload());
+ }
m_view.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
}
setFont(KGlobalSettings::toolBarFont());
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
+#if KDE_IS_VERSION(4,7,0)
+ m_infoMessage = new KMessageWidget;
+ QGridLayout *s = static_cast <QGridLayout*> (layout());
+ s->addWidget(m_infoMessage, 10, 0, 1, -1);
+ m_infoMessage->setCloseButtonVisible(false);
+ m_infoMessage->hide();
+#endif
log_text->setHidden(true);
setWindowTitle(i18n("Transcode Clip"));
auto_add->setText(i18np("Add clip to project", "Add clips to project", m_urls.count()));
if (m_transcodeProcess.state() != QProcess::NotRunning) {
m_transcodeProcess.close();
}
+#if KDE_IS_VERSION(4,7,0)
+ delete m_infoMessage;
+#endif
}
void ClipTranscode::slotStartTransCode()
return;
}
m_duration = 0;
+ m_destination.clear();
+#if KDE_IS_VERSION(4,7,0)
+ m_infoMessage->animatedHide();
+#endif
QStringList parameters;
QString destination;
QString params = ffmpeg_params->toPlainText().simplified();
- if (urls_list->count() > 0) {
+ if (m_urls.count() > 0 && urls_list->count() > 0) {
+ // We are processing multiple clips
source_url->setUrl(m_urls.takeFirst());
destination = dest_url->url().path(KUrl::AddTrailingSlash) + source_url->url().fileName();
QList<QListWidgetItem *> matching = urls_list->findItems(source_url->url().path(), Qt::MatchExactly);
}
QString extension = params.section("%1", 1, 1).section(' ', 0, 0);
QString s_url = source_url->url().path();
-
parameters << "-i" << s_url;
if (QFile::exists(destination + extension)) {
if (KMessageBox::questionYesNo(this, i18n("File %1 already exists.\nDo you want to overwrite it?", destination + extension)) == KMessageBox::No) return;
parameters << "-y";
}
foreach(QString s, params.split(' '))
- parameters << s.replace("%1", destination);
+ parameters << s.replace("%1", destination);
buttonBox->button(QDialogButtonBox::Abort)->setText(i18n("Abort"));
- //kDebug() << "/// FFMPEG ARGS: " << parameters;
-
+ m_destination = destination + extension;
m_transcodeProcess.start("ffmpeg", parameters);
+ source_url->setEnabled(false);
+ dest_url->setEnabled(false);
button_start->setEnabled(false);
}
void ClipTranscode::slotShowTranscodeInfo()
{
QString log = QString(m_transcodeProcess.readAll());
- int progress;
if (m_duration == 0) {
if (log.contains("Duration:")) {
QString data = log.section("Duration:", 1, 1).section(',', 0, 0).simplified();
QStringList numbers = data.split(':');
+ if (numbers.size() < 3) return;
m_duration = numbers.at(0).toInt() * 3600 + numbers.at(1).toInt() * 60 + numbers.at(2).toDouble();
log_text->setHidden(true);
job_progress->setHidden(false);
}
}
else if (log.contains("time=")) {
+ int progress;
QString time = log.section("time=", 1, 1).simplified().section(' ', 0, 0);
if (time.contains(':')) {
QStringList numbers = time.split(':');
+ if (numbers.size() < 3) return;
progress = numbers.at(0).toInt() * 3600 + numbers.at(1).toInt() * 60 + numbers.at(2).toDouble();
}
else progress = (int) time.toDouble();
- kDebug()<<"// PROGRESS: "<<progress<<", "<<m_duration;
job_progress->setValue((int) (100.0 * progress / m_duration));
}
- //kDebug() << "//LOG: " << log;
log_text->setPlainText(log);
}
{
buttonBox->button(QDialogButtonBox::Abort)->setText(i18n("Close"));
button_start->setEnabled(true);
+ source_url->setEnabled(true);
+ dest_url->setEnabled(true);
m_duration = 0;
+ if (QFileInfo(m_destination).size() <= 0) {
+ // Destination file does not exist, transcoding failed
+ exitCode = 1;
+ }
if (exitCode == 0 && exitStatus == QProcess::NormalExit) {
log_text->setHtml(log_text->toPlainText() + "<br /><b>" + i18n("Transcoding finished."));
if (auto_add->isChecked()) {
slotStartTransCode();
return;
} else if (auto_close->isChecked()) accept();
+ else {
+#if KDE_IS_VERSION(4,7,0)
+ m_infoMessage->setMessageType(KMessageWidget::Positive);
+ m_infoMessage->setText(i18n("Transcoding finished."));
+ m_infoMessage->animatedShow();
+#else
+ log_text->setVisible(true);
+#endif
+ }
} else {
+#if KDE_IS_VERSION(4,7,0)
+ m_infoMessage->setMessageType(KMessageWidget::Warning);
+ m_infoMessage->setText(i18n("Transcoding FAILED!"));
+ m_infoMessage->animatedShow();
+#else
log_text->setHtml(log_text->toPlainText() + "<br /><b>" + i18n("Transcoding FAILED!"));
+#endif
+ log_text->setVisible(true);
}
-
m_transcodeProcess.close();
+
+ //Refill url list in case user wants to transcode to another format
+ if (urls_list->count() > 0) {
+ m_urls.clear();
+ for (int i = 0; i < urls_list->count(); i++)
+ m_urls << urls_list->item(i)->text();
+ }
}
void ClipTranscode::slotUpdateParams(int ix)
#include "ui_cliptranscode_ui.h"
#include <KUrl>
+#include <kdeversion.h>
+#if KDE_IS_VERSION(4,7,0)
+#include <KMessageWidget>
+#endif
#include <QProcess>
QProcess m_transcodeProcess;
KUrl::List m_urls;
int m_duration;
+ /** @brief The path for destination transcoded file. */
+ QString m_destination;
+#if KDE_IS_VERSION(4,7,0)
+ KMessageWidget *m_infoMessage;
+#endif
+
signals:
void addClip(KUrl url);
};
// razor tool over a clip, display current frame in monitor
if (false && !m_blockRefresh && item->type() == AVWIDGET) {
//TODO: solve crash when showing frame when moving razor over clip
- emit showClipFrame(((ClipItem *) item)->baseClip(), QPoint(), mappedXPos - (clip->startPos() - clip->cropStart()).frames(m_document->fps()));
+ emit showClipFrame(((ClipItem *) item)->baseClip(), QPoint(), false, mappedXPos - (clip->startPos() - clip->cropStart()).frames(m_document->fps()));
}
event->accept();
return;
emit displayMessage(i18n("Error removing clip at %1 on track %2", m_document->timecode().getTimecodeFromFrames(info.startPos.frames(m_document->fps())), info.track), ErrorMessage);
kDebug()<<"CANNOT REMOVE: "<<info.startPos.frames(m_document->fps())<<", TK: "<<info.track;
//m_document->renderer()->saveSceneList(QString("/tmp/error%1.mlt").arg(m_ct), QDomElement());
- exit(1);
return;
}
m_waitingThumbs.removeAll(item);
+ item->stopThumbs();
if (item->isSelected()) emit clipItemSelected(NULL);
item->baseClip()->removeReference();
m_document->updateClip(item->baseClip()->getId());
emit displayMessage(i18n("Waiting for clip..."), InformationMessage);
emit forceClipProcessing(clipId);
qApp->processEvents();
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 10; i++) {
if (baseclip->getProducer() == NULL) {
- m_producerNotReady.wait(&m_mutex, 500 + 500 * i);
+ qApp->processEvents();
+ m_producerNotReady.wait(&m_mutex, 200);
} else break;
}
if (baseclip->getProducer() == NULL) {
Transition *CustomTrackView::getTransitionItemAt(int pos, int track)
{
- const QPointF p(pos, (track + 1) * m_tracksHeight);
+ const QPointF p(pos, track * m_tracksHeight + Transition::itemOffset() + 1);
QList<QGraphicsItem *> list = scene()->items(p);
Transition *clip = NULL;
for (int i = 0; i < list.size(); i++) {
Transition *CustomTrackView::getTransitionItemAtEnd(GenTime pos, int track)
{
int framepos = (int)(pos.frames(m_document->fps()));
- const QPointF p(framepos - 1, (track + 1) * m_tracksHeight);
+ const QPointF p(framepos - 1, track * m_tracksHeight + Transition::itemOffset() + 1);
QList<QGraphicsItem *> list = scene()->items(p);
Transition *clip = NULL;
for (int i = 0; i < list.size(); i++) {
Transition *CustomTrackView::getTransitionItemAtStart(GenTime pos, int track)
{
- const QPointF p(pos.frames(m_document->fps()), (track + 1) * m_tracksHeight);
+ const QPointF p(pos.frames(m_document->fps()), track * m_tracksHeight + Transition::itemOffset() + 1);
QList<QGraphicsItem *> list = scene()->items(p);
Transition *clip = NULL;
for (int i = 0; i < list.size(); ++i) {
void trackHeightChanged();
void tracksChanged();
void displayMessage(const QString &, MessageType);
- void showClipFrame(DocClipBase *, QPoint, const int);
+ void showClipFrame(DocClipBase *, QPoint, bool, const int);
void doTrackLock(int, bool);
void updateClipMarkers(DocClipBase *);
void updateTrackHeaders();
m_videoOnlyProducer(NULL),
m_snapMarkers(QList < CommentedTime >()),
m_duration(),
- m_audioTimer(NULL),
m_thumbProd(NULL),
m_audioThumbCreated(false),
m_id(id),
if (!m_properties.contains("name")) m_properties.insert("name", url.fileName());
m_thumbProd = new KThumb(clipManager, url, m_id, m_properties.value("file_hash"));
- if (m_clipType == AV || m_clipType == AUDIO || m_clipType == PLAYLIST) slotCreateAudioTimer();
+
+ // Setup timer to trigger audio thumbs creation
+ m_audioTimer.setSingleShot(true);
+ m_audioTimer.setInterval(800);
+ connect(&m_audioTimer, SIGNAL(timeout()), m_thumbProd, SLOT(slotCreateAudioThumbs()));
+
}
DocClipBase::~DocClipBase()
{
+ m_audioTimer.stop();
delete m_thumbProd;
- if (m_audioTimer) {
- m_audioTimer->stop();
- delete m_audioTimer;
- }
+ m_thumbProd = NULL;
qDeleteAll(m_toDeleteProducers);
m_toDeleteProducers.clear();
qDeleteAll(m_baseTrackProducers);
return zone;
}
-void DocClipBase::slotCreateAudioTimer()
-{
- connect(m_thumbProd, SIGNAL(audioThumbReady(const audioByteArray&)), this , SLOT(updateAudioThumbnail(const audioByteArray&)));
- m_audioTimer = new QTimer(this);
- connect(m_audioTimer, SIGNAL(timeout()), this, SLOT(slotGetAudioThumbs()));
-}
-void DocClipBase::askForAudioThumbs()
+bool DocClipBase::hasAudioThumb() const
{
- if (m_thumbProd && m_audioTimer) m_thumbProd->askForAudioThumbs(getId());
+ if (m_clipType == AUDIO || m_clipType == AV || m_clipType == PLAYLIST) return true;
+ return false;
}
void DocClipBase::slotClearAudioCache()
{
- if (m_thumbProd) m_thumbProd->stopAudioThumbs();
- if (m_audioTimer != NULL) m_audioTimer->stop();
m_audioFrameCache.clear();
m_audioThumbCreated = false;
}
void DocClipBase::setClipType(CLIPTYPE type)
{
m_clipType = type;
-
m_properties.insert("type", QString::number((int) type));
- if (m_thumbProd && m_audioTimer == NULL && (m_clipType == AV || m_clipType == AUDIO || m_clipType == PLAYLIST))
- slotCreateAudioTimer();
}
KUrl DocClipBase::fileURL() const
m_audioThumbCreated = isDone;
}
-
-void DocClipBase::setThumbnail(const QPixmap & pixmap)
-{
- m_thumbnail = pixmap;
-}
-
-const QPixmap & DocClipBase::thumbnail() const
-{
- return m_thumbnail;
-}
-
void DocClipBase::updateAudioThumbnail(const audioByteArray& data)
{
//kDebug() << "CLIPBASE RECIEDVED AUDIO DATA*********************************************";
m_thumbProd->setProducer(producer);
}
else m_thumbProd->setProducer(producer);
+ getAudioThumbs();
}
bool updated = false;
if (id.contains('_')) {
return m_properties;
}
-bool DocClipBase::slotGetAudioThumbs()
+QMap <QString, QString> DocClipBase::currentProperties(QMap <QString, QString> props)
{
- if (m_thumbProd == NULL || isPlaceHolder()) return false;
- if (!KdenliveSettings::audiothumbnails() || m_audioTimer == NULL) {
- if (m_audioTimer != NULL) m_audioTimer->stop();
- return false;
+ QMap <QString, QString> currentProps;
+ QMap<QString, QString>::const_iterator i = props.constBegin();
+ while (i != props.constEnd()) {
+ currentProps.insert(i.key(), m_properties.value(i.key()));
+ ++i;
}
+ return currentProps;
+}
+
+bool DocClipBase::getAudioThumbs()
+{
+ if (m_thumbProd == NULL || isPlaceHolder() || !KdenliveSettings::audiothumbnails()) return false;
if (m_audioThumbCreated) {
- m_audioTimer->stop();
return false;
}
- m_audioTimer->start(1500);
- double lengthInFrames = duration().frames(KdenliveSettings::project_fps());
- m_thumbProd->getAudioThumbs(2, 0, lengthInFrames /*must be number of frames*/, 20);
+ m_audioTimer.start();
return true;
}
m_thumbProd->extractImage(frames);
}
-QPixmap DocClipBase::extractImage(int frame, int width, int height)
+QImage DocClipBase::extractImage(int frame, int width, int height)
{
- if (m_thumbProd == NULL) return QPixmap(width, height);
+ if (m_thumbProd == NULL) return QImage();
QMutexLocker locker(&m_producerMutex);
- QPixmap p = m_thumbProd->extractImage(frame, width, height);
- return p;
+ return m_thumbProd->extractImage(frame, width, height);
}
/** Returns the internal unique id of the clip. */
const QString &getId() const;
+ bool hasAudioThumb() const;
//KThumb *thumbCreator;
bool audioThumbCreated() const;
/*void getClipMainThumb();*/
* it uses it as part of it's own composition. */
bool referencesClip(DocClipBase * clip) const;
- /** Sets the thumbnail to be used by this clip */
- void setThumbnail(const QPixmap & pixmap);
-
/** Returns the thumbnail producer used by this clip */
KThumb *thumbProducer();
- /** Returns the thumbnail used by this clip */
- const QPixmap & thumbnail() const;
-
/** Cache for every audio Frame with 10 Bytes */
/** format is frame -> channel ->bytes */
QMap<int, QMap<int, QByteArray> > m_audioFrameCache;
/** Free cache data */
void slotClearAudioCache();
- void askForAudioThumbs();
QString getClipHash() const;
void refreshThumbUrl();
const char *producerProperty(const char *name) const;
bool hasAudioCodec(const QString &codec) const;
bool checkHash() const;
void setPlaceHolder(bool place);
- QPixmap extractImage(int frame, int width, int height);
+ QImage extractImage(int frame, int width, int height);
void clearThumbProducer();
void reloadThumbProducer();
void cleanupProducers();
bool isClean() const;
+ bool getAudioThumbs();
private: // Private attributes
/** A list of snap markers; these markers are added to a clips snap-to points, and are displayed as necessary. */
QList < CommentedTime > m_snapMarkers;
-
- /** A thumbnail for this clip */
- QPixmap m_thumbnail;
GenTime m_duration;
- QTimer *m_audioTimer;
KThumb *m_thumbProd;
bool m_audioThumbCreated;
/** Try to make sure we don't delete a producer while using it */
QMutex m_producerMutex;
QMutex m_replaceMutex;
+
+ /** @brief This timer will trigger creation of audio thumbnails. */
+ QTimer m_audioTimer;
/** Create connections for audio thumbnails */
- void slotCreateAudioTimer();
void slotRefreshProducer();
void setProducerProperty(const char *name, int data);
void setProducerProperty(const char *name, double data);
public slots:
void updateAudioThumbnail(const audioByteArray& data);
- bool slotGetAudioThumbs();
QList < CommentedTime > commentedSnapMarkers() const;
GenTime findNextSnapMarker(const GenTime & currTime);
GenTime findPreviousSnapMarker(const GenTime & currTime);
uint getClipThumbFrame() const;
void setProperties(QMap <QString, QString> properties);
void setMetadata(QMap <QString, QString> properties);
+ /** Returns all current properties for this clip */
QMap <QString, QString> properties() const;
+ /** Return the current values for a set of properties */
+ QMap <QString, QString> currentProperties(QMap <QString, QString> props);
QMap <QString, QString> metadata() const;
void slotExtractImage(QList <int> frames);
// WARNING: what should be done in case the locale does not exist on the system?
setlocale(LC_NUMERIC, mlt.attribute("LC_NUMERIC").toUtf8().constData());
documentLocale = QLocale(mlt.attribute("LC_NUMERIC"));
+
+ // Make sure Qt locale and C++ locale have the same numeric separator, might not be the case
+ // With some locales since C++ and Qt use a different database for locales
+ char *separator = localeconv()->decimal_point;
+ if (separator != documentLocale.decimalPoint()) {
+ kDebug()<<"------\n!!! system locale is not similar to Qt's locale... be prepared for bugs!!!\n------";
+ // HACK: There is a locale conflict, so set locale to at least have correct decimal point
+ if (strncmp(separator, ".", 1) == 0) documentLocale = QLocale::c();
+ else if (strncmp(separator, ",", 1) == 0) documentLocale = QLocale("fr_FR.UTF-8");
+ }
}
documentLocale.setNumberOptions(QLocale::OmitGroupSeparator);
#include "ui_boolval_ui.h"
#include "ui_wipeval_ui.h"
#include "ui_urlval_ui.h"
+#include "ui_keywordval_ui.h"
+#include "ui_fontval_ui.h"
#include "complexparameter.h"
#include "geometryval.h"
#include "positionedit.h"
{
};
+class Keywordval: public QWidget, public Ui::Keywordval_UI
+{
+};
+
+class Fontval: public QWidget, public Ui::Fontval_UI
+{
+};
+
QMap<QString, QImage> EffectStackEdit::iconCache;
EffectStackEdit::EffectStackEdit(Monitor *monitor, QWidget *parent) :
m_keyframeEditor->addParameter(pa);
}
} else if (type == "color") {
- if (value.startsWith('#'))
- value = value.replace('#', "0x");
- bool ok;
- ChooseColorWidget *choosecolor = new ChooseColorWidget(paramName, QColor(value.toUInt(&ok, 16)), this);
+ ChooseColorWidget *choosecolor = new ChooseColorWidget(paramName, value, this);
+ choosecolor->setAlphaChannelEnabled(pa.attribute("alpha") == "1");
m_vbox->addWidget(choosecolor);
m_valueItems[paramName] = choosecolor;
connect(choosecolor, SIGNAL(displayMessage(const QString&, int)), this, SIGNAL(displayMessage(const QString&, int)));
connect(cval->urlwidget, SIGNAL(returnPressed()) , this, SLOT(collectAllParameters()));
connect(cval->urlwidget, SIGNAL(urlSelected(const KUrl&)) , this, SLOT(collectAllParameters()));
m_uiItems.append(cval);
+ } else if (type == "keywords") {
+ Keywordval* kval = new Keywordval;
+ kval->setupUi(toFillin);
+ kval->label->setText(paramName);
+ kval->lineeditwidget->setText(value);
+ QDomElement klistelem = pa.firstChildElement("keywords");
+ QDomElement kdisplaylistelem = pa.firstChildElement("keywordsdisplay");
+ QStringList keywordlist;
+ QStringList keyworddisplaylist;
+ if (!klistelem.isNull()) {
+ keywordlist = klistelem.text().split(';');
+ keyworddisplaylist = i18n(kdisplaylistelem.text().toUtf8().data()).split(';');
+ }
+ if (keyworddisplaylist.count() != keywordlist.count()) {
+ keyworddisplaylist = keywordlist;
+ }
+ for (int i = 0; i < keywordlist.count(); i++) {
+ kval->comboboxwidget->addItem(keyworddisplaylist.at(i), keywordlist.at(i));
+ }
+ // Add disabled user prompt at index 0
+ kval->comboboxwidget->insertItem(0, i18n("<select a keyword>"), "");
+ kval->comboboxwidget->model()->setData( kval->comboboxwidget->model()->index(0,0), QVariant(Qt::NoItemFlags), Qt::UserRole -1);
+ kval->comboboxwidget->setCurrentIndex(0);
+ m_valueItems[paramName] = kval;
+ connect(kval->lineeditwidget, SIGNAL(editingFinished()) , this, SLOT(collectAllParameters()));
+ connect(kval->comboboxwidget, SIGNAL(activated (const QString&)), this, SLOT(collectAllParameters()));
+ m_uiItems.append(kval);
+ } else if (type == "fontfamily") {
+ Fontval* fval = new Fontval;
+ fval->setupUi(toFillin);
+ fval->name->setText(paramName);
+ fval->fontfamilywidget->setCurrentFont(QFont(value));
+ m_valueItems[paramName] = fval;
+ connect(fval->fontfamilywidget, SIGNAL(currentFontChanged(const QFont &)), this, SLOT(collectAllParameters())) ;
+ m_uiItems.append(fval);
} else {
delete toFillin;
toFillin = NULL;
setValue = box->checkState() == Qt::Checked ? "1" : "0" ;
} else if (type == "color") {
ChooseColorWidget *choosecolor = ((ChooseColorWidget*)m_valueItems.value(paramName));
- setValue = choosecolor->getColor().name();
+ setValue = choosecolor->getColor();
} else if (type == "complex") {
ComplexParameter *complex = ((ComplexParameter*)m_valueItems.value(paramName));
namenode.item(i) = complex->getParamDesc();
} else if (type == "url") {
KUrlRequester *req = ((Urlval*)m_valueItems.value(paramName))->urlwidget;
setValue = req->url().path();
+ } else if (type == "keywords"){
+ QLineEdit *line = ((Keywordval*)m_valueItems.value(paramName))->lineeditwidget;
+ QComboBox *combo = ((Keywordval*)m_valueItems.value(paramName))->comboboxwidget;
+ if(combo->currentIndex())
+ {
+ QString comboval = combo->itemData(combo->currentIndex()).toString();
+ line->insert(comboval);
+ combo->setCurrentIndex(0);
+ }
+ setValue = line->text();
+ } else if (type == "fontfamily") {
+ QFontComboBox* fontfamily = ((Fontval*)m_valueItems.value(paramName))->fontfamilywidget;
+ setValue = fontfamily->currentFont().family();
}
if (!setValue.isNull())
return QPoint(video, audio);
}
-void KdenliveDoc::cachePixmap(const QString &fileId, const QPixmap &pix) const
+void KdenliveDoc::cacheImage(const QString &fileId, const QImage &img) const
{
- pix.save(m_projectFolder.path(KUrl::AddTrailingSlash) + "thumbs/" + fileId + ".png");
+ img.save(m_projectFolder.path(KUrl::AddTrailingSlash) + "thumbs/" + fileId + ".png");
}
bool KdenliveDoc::checkDocumentClips(QDomNodeList infoproducers)
* The returned duration might differ from the actual track duration!
* It is the one stored in the track's TrackInfo. */
int trackDuration(int ix);
-
- void cachePixmap(const QString &fileId, const QPixmap &pix) const;
+ void cacheImage(const QString &fileId, const QImage &img) const;
void setProjectFolder(KUrl url);
void setZone(int start, int end);
QPoint zone() const;
#include <QtConcurrentRun>
#include <QVarLengthArray>
-KThumb::KThumb(ClipManager *clipManager, KUrl url, const QString &id, const QString &hash, QObject * parent, const char */*name*/) :
+KThumb::KThumb(ClipManager *clipManager, KUrl url, const QString &id, const QString &hash, QObject * parent) :
QObject(parent),
- m_audioThumbProducer(),
m_url(url),
m_thumbFile(),
m_dar(1),
m_ratio(1),
m_producer(NULL),
m_clipManager(clipManager),
- m_id(id),
- m_stopAudioThumbs(false)
+ m_id(id)
{
m_thumbFile = clipManager->projectFolder() + "/thumbs/" + hash + ".thumb";
}
KThumb::~KThumb()
{
if (m_producer) m_clipManager->stopThumbs(m_id);
+ m_producer = NULL;
m_intraFramesQueue.clear();
- if (m_audioThumbProducer.isRunning()) {
- m_stopAudioThumbs = true;
- m_audioThumbProducer.waitForFinished();
- slotAudioThumbOver();
- }
m_intra.waitForFinished();
}
emit thumbReady(frame, img);
}
-QPixmap KThumb::extractImage(int frame, int width, int height)
+QImage KThumb::extractImage(int frame, int width, int height)
{
if (m_producer == NULL) {
- QPixmap p(width, height);
- p.fill(Qt::black);
- return p;
+ QImage img(width, height, QImage::Format_ARGB32_Premultiplied);
+ img.fill(Qt::black);
+ return img;
}
- QImage img = getProducerFrame(frame, (int) (height * m_ratio + 0.5), width, height);
- return QPixmap::fromImage(img);
+ return getProducerFrame(frame, (int) (height * m_ratio + 0.5), width, height);
}
//static
emit thumbReady(endframe, image);
}
*/
-void KThumb::stopAudioThumbs()
-{
- if (m_audioThumbProducer.isRunning()) {
- m_stopAudioThumbs = true;
- m_audioThumbProducer.waitForFinished();
- slotAudioThumbOver();
- }
-}
-
-void KThumb::removeAudioThumb()
-{
- if (m_thumbFile.isEmpty()) return;
- stopAudioThumbs();
- QFile f(m_thumbFile);
- f.remove();
-}
-
-void KThumb::getAudioThumbs(int channel, double frame, double frameLength, int arrayWidth)
-{
- if (channel == 0) {
- slotAudioThumbOver();
- return;
- }
- if (m_audioThumbProducer.isRunning()) {
- return;
- }
-
- audioByteArray storeIn;
- //FIXME: Hardcoded!!!
- m_frequency = 48000;
- m_channels = channel;
-
- QFile f(m_thumbFile);
- if (f.open(QIODevice::ReadOnly)) {
- const QByteArray channelarray = f.readAll();
- f.close();
- if (channelarray.size() != arrayWidth*(frame + frameLength)*m_channels) {
- kDebug() << "--- BROKEN THUMB FOR: " << m_url.fileName() << " ---------------------- " << endl;
- f.remove();
- slotAudioThumbOver();
- return;
- }
-
- kDebug() << "reading audio thumbs from file";
-
- int h1 = arrayWidth * m_channels;
- int h2 = (int) frame * h1;
- int h3;
- for (int z = (int) frame; z < (int)(frame + frameLength); z++) {
- h3 = 0;
- for (int c = 0; c < m_channels; c++) {
- QByteArray m_array(arrayWidth, '\x00');
- for (int i = 0; i < arrayWidth; i++) {
- m_array[i] = channelarray.at(h2 + h3 + i);
- }
- h3 += arrayWidth;
- storeIn[z][c] = m_array;
- }
- h2 += h1;
- }
- emit audioThumbReady(storeIn);
- slotAudioThumbOver();
- } else {
- if (m_audioThumbProducer.isRunning()) return;
- m_audioThumbFile.setFileName(m_thumbFile);
- m_frame = frame;
- m_frameLength = frameLength;
- m_arrayWidth = arrayWidth;
- m_audioThumbProducer = QtConcurrent::run(this, &KThumb::slotCreateAudioThumbs);
- /*m_audioThumbProducer.init(m_url, m_thumbFile, frame, frameLength, m_frequency, m_channels, arrayWidth);
- m_audioThumbProducer.start(QThread::LowestPriority);*/
- // kDebug() << "STARTING GENERATE THMB FOR: " <<m_id<<", URL: "<< m_url << " ................................";
- }
-}
void KThumb::slotCreateAudioThumbs()
{
- Mlt::Profile prof((char*) KdenliveSettings::current_profile().toUtf8().constData());
- Mlt::Producer producer(prof, m_url.path().toUtf8().constData());
- if (!producer.is_valid()) {
- kDebug() << "++++++++ INVALID CLIP: " << m_url.path();
- return;
- }
- if (!m_audioThumbFile.open(QIODevice::WriteOnly)) {
- kDebug() << "++++++++ ERROR WRITING TO FILE: " << m_audioThumbFile.fileName();
- kDebug() << "++++++++ DISABLING AUDIO THUMBS";
- KdenliveSettings::setAudiothumbnails(false);
- return;
- }
-
- if (KdenliveSettings::normaliseaudiothumbs()) {
- Mlt::Filter m_convert(prof, "volume");
- m_convert.set("gain", "normalise");
- producer.attach(m_convert);
- }
-
- int last_val = 0;
- int val = 0;
- mlt_audio_format m_audioFormat = mlt_audio_pcm;
- double framesPerSecond = mlt_producer_get_fps(producer.get_producer());
- Mlt::Frame *mlt_frame;
-
- for (int z = (int) m_frame; z < (int)(m_frame + m_frameLength) && producer.is_valid(); z++) {
- if (m_stopAudioThumbs) break;
- val = (int)((z - m_frame) / (m_frame + m_frameLength) * 100.0);
- if (last_val != val && val > 1) {
- m_clipManager->setThumbsProgress(i18n("Creating thumbnail for %1", m_url.fileName()), val);
- last_val = val;
- }
- producer.seek(z);
- mlt_frame = producer.get_frame();
- if (mlt_frame && mlt_frame->is_valid()) {
- int m_samples = mlt_sample_calculator(framesPerSecond, m_frequency, mlt_frame_get_position(mlt_frame->get_frame()));
- qint16* m_pcm = static_cast<qint16*>(mlt_frame->get_audio(m_audioFormat, m_frequency, m_channels, m_samples));
- for (int c = 0; c < m_channels; c++) {
- QByteArray m_array;
- m_array.resize(m_arrayWidth);
- for (int i = 0; i < m_array.size(); i++) {
- m_array[i] = ((*(m_pcm + c + i * m_samples / m_array.size())) >> 9) + 127 / 2 ;
- }
- m_audioThumbFile.write(m_array);
-
- }
- } else {
- m_audioThumbFile.write(QByteArray(m_arrayWidth, '\x00'));
- }
- delete mlt_frame;
- }
- m_audioThumbFile.close();
- if (m_stopAudioThumbs) {
- m_audioThumbFile.remove();
- } else {
- slotAudioThumbOver();
- }
-}
-
-void KThumb::slotAudioThumbOver()
-{
- m_clipManager->setThumbsProgress(i18n("Creating thumbnail for %1", m_url.fileName()), -1);
- m_clipManager->endAudioThumbsGeneration(m_id);
-}
-
-void KThumb::askForAudioThumbs(const QString &id)
-{
- m_clipManager->askForAudioThumb(id);
+ m_clipManager->askForAudioThumb(m_id);
}
#if KDE_IS_VERSION(4,5,0)
Q_OBJECT public:
- KThumb(ClipManager *clipManager, KUrl url, const QString &id, const QString &hash, QObject * parent = 0, const char *name = 0);
+ KThumb(ClipManager *clipManager, KUrl url, const QString &id, const QString &hash, QObject * parent = 0);
~KThumb();
void setProducer(Mlt::Producer *producer);
- void askForAudioThumbs(const QString &id);
bool hasProducer() const;
void clearProducer();
void updateThumbUrl(const QString &hash);
void extractImage(QList <int> frames);
- QPixmap extractImage(int frame, int width, int height);
+ QImage extractImage(int frame, int width, int height);
#if KDE_IS_VERSION(4,5,0)
/** @brief Request thumbnails for the frame range. */
void queryIntraThumbs(QList <int> missingFrames);
// static QPixmap getImage(QDomElement xml, int frame, int width, int height);
/* void getImage(KUrl url, int frame, int width, int height);
void getThumbs(KUrl url, int startframe, int endframe, int width, int height);*/
- void stopAudioThumbs();
- void removeAudioThumb();
- void getAudioThumbs(int channel, double frame, double frameLength, int arrayWidth);
+ void slotCreateAudioThumbs();
static QPixmap getImage(KUrl url, int frame, int width, int height);
static QImage getFrame(Mlt::Producer *producer, int framepos, int frameWidth, int displayWidth, int height);
static QImage getFrame(Mlt::Frame *frame, int frameWidth, int displayWidth, int height);
static uint imageVariance(QImage image);
private slots:
- void slotAudioThumbOver();
- void slotCreateAudioThumbs();
#if KDE_IS_VERSION(4,5,0)
/** @brief Fetch all requested frames. */
void slotGetIntraThumbs();
#endif
private:
- QFuture<void> m_audioThumbProducer;
KUrl m_url;
QString m_thumbFile;
double m_dar;
QString m_id;
/** @brief Controls the intra frames thumbnails process (cached thumbnails). */
QFuture<void> m_intra;
- QFile m_audioThumbFile;
- bool m_stopAudioThumbs;
- double m_frame;
- double m_frameLength;
- int m_frequency;
- int m_channels;
- int m_arrayWidth;
/** @brief List of frame numbers from which we want to extract thumbnails. */
QList <int> m_intraFramesQueue;
QMutex m_mutex;
#include <QBitmap>
#include <stdlib.h>
+#include <locale.h>
// Uncomment for deeper debugging
//#define DEBUG_MAINW
// Init locale
QLocale systemLocale = QLocale();
+ setlocale(LC_NUMERIC, NULL);
+ char *separator = localeconv()->decimal_point;
+ if (separator != systemLocale.decimalPoint()) {
+ kDebug()<<"------\n!!! system locale is not similar to Qt's locale... be prepared for bugs!!!\n------";
+ // HACK: There is a locale conflict, so set locale to at least have correct decimal point
+ if (strncmp(separator, ".", 1) == 0) systemLocale = QLocale::c();
+ else if (strncmp(separator, ",", 1) == 0) systemLocale = QLocale("fr_FR.UTF-8");
+ }
+
systemLocale.setNumberOptions(QLocale::OmitGroupSeparator);
QLocale::setDefault(systemLocale);
m_clipMonitorDock->setWidget(m_clipMonitor);
// Connect the project list
- connect(m_projectList, SIGNAL(clipSelected(DocClipBase *, QPoint)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint)));
+ connect(m_projectList, SIGNAL(clipSelected(DocClipBase *, QPoint, bool)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, bool)));
connect(m_projectList, SIGNAL(raiseClipMonitor()), m_clipMonitor, SLOT(activateMonitor()));
connect(m_projectList, SIGNAL(loadingIsOver()), this, SLOT(slotElapsedTime()));
connect(m_projectList, SIGNAL(displayMessage(const QString&, int)), this, SLOT(slotGotProgressInfo(const QString&, int)));
connect(m_projectList, SIGNAL(updateRenderStatus()), this, SLOT(slotCheckRenderStatus()));
connect(m_projectList, SIGNAL(clipNeedsReload(const QString&)),this, SLOT(slotUpdateClip(const QString &)));
connect(m_projectList, SIGNAL(updateProfile(const QString &)), this, SLOT(slotUpdateProjectProfile(const QString &)));
- connect(m_projectList, SIGNAL(refreshClip(const QString &, bool)), m_monitorManager, SLOT(slotRefreshCurrentMonitor()));
+ connect(m_projectList, SIGNAL(refreshClip(const QString &, bool)), m_monitorManager, SLOT(slotRefreshCurrentMonitor(const QString &)));
connect(m_projectList, SIGNAL(findInTimeline(const QString&)), this, SLOT(slotClipInTimeline(const QString&)));
connect(m_clipMonitor, SIGNAL(zoneUpdated(QPoint)), m_projectList, SLOT(slotUpdateClipCut(QPoint)));
disconnect(m_activeTimeline->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(Transition*)));
disconnect(m_activeTimeline->projectView(), SIGNAL(playMonitor()), m_projectMonitor, SLOT(slotPlay()));
disconnect(m_activeTimeline->projectView(), SIGNAL(displayMessage(const QString&, MessageType)), m_messageLabel, SLOT(setMessage(const QString&, MessageType)));
- disconnect(m_activeTimeline->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, const int)));
+ disconnect(m_activeTimeline->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, bool, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, bool, const int)));
disconnect(m_activeTimeline, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(activateMonitor()));
disconnect(m_activeTimeline, SIGNAL(insertTrack(int)), this, SLOT(slotInsertTrack(int)));
disconnect(m_activeTimeline, SIGNAL(deleteTrack(int)), this, SLOT(slotDeleteTrack(int)));
connect(trackView, SIGNAL(setZoom(int)), this, SLOT(slotSetZoom(int)));
connect(trackView->projectView(), SIGNAL(displayMessage(const QString&, MessageType)), m_messageLabel, SLOT(setMessage(const QString&, MessageType)));
- connect(trackView->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, const int)));
+ connect(trackView->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, bool, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, bool, const int)));
connect(trackView->projectView(), SIGNAL(playMonitor()), m_projectMonitor, SLOT(slotPlay()));
connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(ClipItem*)));
else newprops.insert("templatetext", description);
//newprops.insert("xmldata", m_projectList->generateTemplateXml(newtemplate, description).toString());
if (!newprops.isEmpty()) {
- EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newprops, true);
+ EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newprops), newprops, true);
m_activeDocument->commandStack()->push(command);
}
}
if (dia_ui->exec() == QDialog::Accepted) {
QMap <QString, QString> newprops;
newprops.insert("xmldata", dia_ui->xml().toString());
- if (dia_ui->outPoint() != clip->duration().frames(m_activeDocument->fps()) - 1) {
+ if (dia_ui->outPoint() != clip->duration().frames(m_activeDocument->fps())) {
// duration changed, we need to update duration
newprops.insert("out", QString::number(dia_ui->outPoint()));
int currentLength = QString(clip->producerProperty("length")).toInt();
dia_ui->saveTitle(path);
} else newprops.insert("resource", QString());
}
- EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newprops, true);
+ EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newprops), newprops, true);
m_activeDocument->commandStack()->push(command);
//m_activeTimeline->projectView()->slotUpdateClip(clip->getId());
m_activeDocument->setModified(true);
for (int i = 0; i < cliplist.count(); i++) {
DocClipBase *clip = cliplist.at(i);
if (clip->clipType() == IMAGE)
- new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newImageProps, true, command);
+ new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newImageProps), newImageProps, true, command);
else
- new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newProps, true, command);
+ new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newProps), newProps, true, command);
}
m_activeDocument->commandStack()->push(command);
for (int i = 0; i < cliplist.count(); i++)
data.append(list.join(";").toUtf8());
mimeData->setData("kdenlive/clip", data);
drag->setMimeData(mimeData);
- QPixmap pix = m_currentClip->thumbnail();
+ /*QPixmap pix = m_currentClip->thumbnail();
drag->setPixmap(pix);
- drag->setHotSpot(QPoint(0, 50));
+ drag->setHotSpot(QPoint(0, 50));*/
drag->start(Qt::MoveAction);
//Qt::DropAction dropAction;
render->setProducer(prod, render->seekFramePosition());
}
-void Monitor::slotSetClipProducer(DocClipBase *clip, QPoint zone, int position)
+void Monitor::slotSetClipProducer(DocClipBase *clip, QPoint zone, bool forceUpdate, int position)
{
if (render == NULL) return;
if (clip == NULL && m_currentClip != NULL) {
return;
}
- if (clip != m_currentClip) {
+ if (clip != m_currentClip || forceUpdate) {
m_currentClip = clip;
if (m_currentClip) activateMonitor();
updateMarkers(clip);
return render;
}
+void Monitor::reloadProducer(const QString &id)
+{
+ if (!m_currentClip) return;
+ if (m_currentClip->getId() == id)
+ slotSetClipProducer(m_currentClip, m_currentClip->zone(), true);
+}
+
MonitorRefresh::MonitorRefresh(QWidget* parent) :
QWidget(parent)
, m_renderer(NULL)
void updateMarkers(DocClipBase *source);
MonitorEditWidget *getEffectEdit();
QWidget *container();
+ void reloadProducer(const QString &id);
QFrame *m_volumePopup;
protected:
public slots:
void slotOpenFile(const QString &);
- void slotSetClipProducer(DocClipBase *clip, QPoint zone = QPoint(), int position = -1);
+ void slotSetClipProducer(DocClipBase *clip, QPoint zone = QPoint(), bool forceUpdate = false, int position = -1);
void updateClipProducer(Mlt::Producer *prod);
void refreshMonitor(bool visible);
void refreshMonitor();
#include <QTimer>
#include <KDebug>
+
MonitorManager::MonitorManager(QWidget *parent) :
QObject(parent),
m_clipMonitor(NULL),
emit checkColorScopes();
}
-void MonitorManager::slotRefreshCurrentMonitor()
+void MonitorManager::slotRefreshCurrentMonitor(const QString &id)
{
+ // Clip producer was modified, check if clip is currently displayed in clip monitor
+ m_clipMonitor->reloadProducer(id);
if (m_activeMonitor == m_clipMonitor) m_clipMonitor->refreshMonitor();
else m_projectMonitor->refreshMonitor();
}
void slotUpdateAudioMonitoring();
private slots:
- void slotRefreshCurrentMonitor();
+ void slotRefreshCurrentMonitor(const QString &id);
private:
Monitor *m_clipMonitor;
frame->setFrameStyle(QFrame::NoFrame);
QHBoxLayout *box = new QHBoxLayout;
KTreeWidgetSearchLine *searchView = new KTreeWidgetSearchLine;
-
box->addWidget(searchView);
- //int s = style()->pixelMetric(QStyle::PM_SmallIconSize);
- //m_toolbar->setIconSize(QSize(s, s));
+
+ int size = style()->pixelMetric(QStyle::PM_SmallIconSize);
+ QSize iconSize(size, size);
m_addButton = new QToolButton;
m_addButton->setPopupMode(QToolButton::MenuButtonPopup);
m_addButton->setAutoRaise(true);
+ m_addButton->setIconSize(iconSize);
box->addWidget(m_addButton);
m_editButton = new QToolButton;
m_editButton->setAutoRaise(true);
+ m_editButton->setIconSize(iconSize);
box->addWidget(m_editButton);
m_deleteButton = new QToolButton;
m_deleteButton->setAutoRaise(true);
+ m_deleteButton->setIconSize(iconSize);
box->addWidget(m_deleteButton);
frame->setLayout(box);
layout->addWidget(frame);
else if (item->hasProxy() && !item->isProxyRunning()) {
slotCreateProxy(clip->getId());
}
- clip->askForAudioThumbs();
KUrl url = clip->fileURL();
#ifdef NEPOMUK
TimecodeDisplay *t = new TimecodeDisplay(m_timecode);
t->setValue(KdenliveSettings::color_duration());
- t->setTimeCodeFormat(false);
dia_ui.clip_durationBox->addWidget(t);
dia_ui.clip_color->setColor(KdenliveSettings::colorclipcolor());
return;
}
QPixmap pix;
+ QImage img;
int height = m_listView->iconSize().height();
int swidth = (int)(height * m_render->frameRenderWidth() / m_render->renderHeight()+ 0.5);
int dwidth = (int)(height * m_render->dar() + 0.5);
if (clip->clipType() == AUDIO)
pix = KIcon("audio-x-generic").pixmap(QSize(dwidth, height));
else if (clip->clipType() == IMAGE)
- pix = QPixmap::fromImage(KThumb::getFrame(item->referencedClip()->getProducer(), 0, swidth, dwidth, height));
+ img = KThumb::getFrame(item->referencedClip()->getProducer(), 0, swidth, dwidth, height);
else {
- pix = item->referencedClip()->extractImage(frame, dwidth, height);
+ img = item->referencedClip()->extractImage(frame, dwidth, height);
}
- if (!pix.isNull()) {
+ if (!pix.isNull() || !img.isNull()) {
monitorItemEditing(false);
+ if (!img.isNull()) pix = QPixmap::fromImage(img);
it->setData(0, Qt::DecorationRole, pix);
monitorItemEditing(true);
- QString clipId = item->getClipHash();
- if (!clipId.isEmpty()) {
+ QString hash = item->getClipHash();
+ if (!hash.isEmpty() && !img.isNull()) {
if (!isSubItem)
- m_doc->cachePixmap(clipId, pix);
+ m_doc->cacheImage(hash, img);
else
- m_doc->cachePixmap(clipId + '#' + QString::number(frame), pix);
+ m_doc->cacheImage(hash + '#' + QString::number(frame), img);
}
}
if (update)
}
item->setProperties(properties, metadata);
clip->setProducer(producer, replace);
- clip->askForAudioThumbs();
// Proxy stuff
QString size = properties.value("frame_size");
if (queue == 0) {
monitorItemEditing(true);
if (item && m_thumbnailQueue.isEmpty()) {
- m_listView->setCurrentItem(item);
+ if (!item->hasProxy() || m_render->activeClipId() == item->clipId())
+ m_listView->setCurrentItem(item);
bool updatedProfile = false;
if (item->parent()) {
if (item->parent()->type() == PROJECTFOLDERTYPE)
void ProjectList::slotReplyGetImage(const QString &clipId, const QImage &img)
{
- QPixmap pix = QPixmap::fromImage(img);
- setThumbnail(clipId, pix);
+ ProjectItem *item = getItemById(clipId);
+ if (item && !img.isNull()) {
+ QPixmap pix = QPixmap::fromImage(img);
+ monitorItemEditing(false);
+ item->setData(0, Qt::DecorationRole, pix);
+ monitorItemEditing(true);
+ QString hash = item->getClipHash();
+ if (!hash.isEmpty()) m_doc->cacheImage(hash, img);
+ }
}
void ProjectList::slotReplyGetImage(const QString &clipId, const QString &name, int width, int height)
{
- QPixmap pix = KIcon(name).pixmap(QSize(width, height));
- setThumbnail(clipId, pix);
-}
-
-void ProjectList::setThumbnail(const QString &clipId, const QPixmap &pix)
-{
+ // For clips that have a generic icon (like audio clips...)
ProjectItem *item = getItemById(clipId);
+ QPixmap pix = KIcon(name).pixmap(QSize(width, height));
if (item && !pix.isNull()) {
monitorItemEditing(false);
item->setData(0, Qt::DecorationRole, pix);
monitorItemEditing(true);
- //update();
- QString clipId = item->getClipHash();
- if (!clipId.isEmpty()) m_doc->cachePixmap(clipId, pix);
}
}
m_listView->scrollToItem(sub);
m_listView->editItem(sub, 1);
}
- QPixmap p = clip->referencedClip()->extractImage(in, (int)(sub->sizeHint(0).height() * m_render->dar()), sub->sizeHint(0).height() - 2);
- sub->setData(0, Qt::DecorationRole, p);
- QString clipId = clip->getClipHash();
- if (!clipId.isEmpty()) m_doc->cachePixmap(clipId + '#' + QString::number(in), p);
+ QImage img = clip->referencedClip()->extractImage(in, (int)(sub->sizeHint(0).height() * m_render->dar()), sub->sizeHint(0).height() - 2);
+ sub->setData(0, Qt::DecorationRole, QPixmap::fromImage(img));
+ QString hash = clip->getClipHash();
+ if (!hash.isEmpty()) m_doc->cacheImage(hash + '#' + QString::number(in), img);
monitorItemEditing(true);
}
emit projectModified();
{
QTreeWidgetItemIterator it(m_listView);
ProjectItem *item = getItemById(id);
- setProxyStatus(item, NOPROXY);
- slotGotProxy(item);
if (!path.isEmpty() && m_processingProxy.contains(path)) {
m_abortProxy << path;
setProxyStatus(item, NOPROXY);
}
+ else {
+ setProxyStatus(item, NOPROXY);
+ slotGotProxy(item);
+ }
}
void ProjectList::slotGenerateProxy()
if (m_abortProxy.contains(info.dest)) {
m_abortProxy.removeAll(info.dest);
continue;
- }
+ }
// Get the list of clips that will need to get progress info
QTreeWidgetItemIterator it(m_listView);
QList <ProjectItem *> processingItems;
}
else continue;
result = -2;
-
}
else {
QString log = QString(myProcess.readAll());
}
// FFmpeg process terminated normally, but make sure proxy clip exists
- if (QFileInfo(info.dest).size() == 0) {
+ if (result != -2 && QFileInfo(info.dest).size() == 0) {
result = QProcess::CrashExit;
}
newProps.insert("replace", "1");
// insert required duration for proxy
newProps.insert("proxy_out", item->referencedClip()->producerProperty("out"));
- new EditClipCommand(this, item->clipId(), item->referencedClip()->properties(), newProps, true, command);
+ new EditClipCommand(this, item->clipId(), item->referencedClip()->currentProperties(newProps), newProps, true, command);
}
}
else if (t == IMAGE && item->referencedClip() != NULL) {
QList<QTreeWidgetItem *> list;
if (itemToProxy == NULL) list = m_listView->selectedItems();
else list << itemToProxy;
+
+ // expand list (folders, subclips) to get real clips
QTreeWidgetItem *listItem;
- QUndoCommand *command = new QUndoCommand();
- if (doProxy) command->setText(i18np("Add proxy clip", "Add proxy clips", list.count()));
- else command->setText(i18np("Remove proxy clip", "Remove proxy clips", list.count()));
-
- // Make sure the proxy folder exists
- QString proxydir = m_doc->projectFolder().path( KUrl::AddTrailingSlash) + "proxy/";
- KStandardDirs::makeDir(proxydir);
-
- QMap <QString, QString> newProps;
- QMap <QString, QString> oldProps;
- if (!doProxy) newProps.insert("proxy", "-");
+ QList<ProjectItem *> clipList;
for (int i = 0; i < list.count(); i++) {
listItem = list.at(i);
if (listItem->type() == PROJECTFOLDERTYPE) {
for (int j = 0; j < listItem->childCount(); j++) {
QTreeWidgetItem *sub = listItem->child(j);
- if (!list.contains(sub)) list.append(sub);
+ if (sub->type() == PROJECTCLIPTYPE) {
+ ProjectItem *item = static_cast <ProjectItem*>(sub);
+ if (!clipList.contains(item)) clipList.append(item);
+ }
}
}
else if (listItem->type() == PROJECTSUBCLIPTYPE) {
QTreeWidgetItem *sub = listItem->parent();
- if (!list.contains(sub)) list.append(sub);
+ ProjectItem *item = static_cast <ProjectItem*>(sub);
+ if (!clipList.contains(item)) clipList.append(item);
}
else if (listItem->type() == PROJECTCLIPTYPE) {
ProjectItem *item = static_cast <ProjectItem*>(listItem);
- CLIPTYPE t = item->clipType();
- if ((t == VIDEO || t == AV || t == UNKNOWN || t == IMAGE || t == PLAYLIST) && item->referencedClip()) {
- if ((doProxy && item->hasProxy()) || (!doProxy && !item->hasProxy() && item->referencedClip()->getProducer() != NULL)) continue;
- DocClipBase *clip = item->referencedClip();
- if (!clip || !clip->isClean() || m_render->isProcessing(item->clipId())) {
- kDebug()<<"//// TRYING TO PROXY: "<<item->clipId()<<", but it is busy";
- continue;
- }
+ if (!clipList.contains(item)) clipList.append(item);
+ }
+ }
+
+ QUndoCommand *command = new QUndoCommand();
+ if (doProxy) command->setText(i18np("Add proxy clip", "Add proxy clips", clipList.count()));
+ else command->setText(i18np("Remove proxy clip", "Remove proxy clips", clipList.count()));
+
+ // Make sure the proxy folder exists
+ QString proxydir = m_doc->projectFolder().path( KUrl::AddTrailingSlash) + "proxy/";
+ KStandardDirs::makeDir(proxydir);
- resetThumbsProducer(clip);
- oldProps = clip->properties();
- if (doProxy) {
- newProps.clear();
- QString path = proxydir + clip->getClipHash() + "." + (t == IMAGE ? "png" : m_doc->getDocumentProperty("proxyextension"));
- // insert required duration for proxy
- newProps.insert("proxy_out", clip->producerProperty("out"));
- newProps.insert("proxy", path);
- // We need to insert empty proxy so that undo will work
- oldProps.insert("proxy", QString());
- }
- else if (item->referencedClip()->getProducer() == NULL) {
- // Force clip reload
- newProps.insert("resource", item->referencedClip()->getProperty("resource"));
- }
- new EditClipCommand(this, item->clipId(), oldProps, newProps, true, command);
+ QMap <QString, QString> newProps;
+ QMap <QString, QString> oldProps;
+ if (!doProxy) newProps.insert("proxy", "-");
+ for (int i = 0; i < clipList.count(); i++) {
+ ProjectItem *item = clipList.at(i);
+ CLIPTYPE t = item->clipType();
+ if ((t == VIDEO || t == AV || t == UNKNOWN || t == IMAGE || t == PLAYLIST) && item->referencedClip()) {
+ if ((doProxy && item->hasProxy()) || (!doProxy && !item->hasProxy() && item->referencedClip()->getProducer() != NULL)) continue;
+ DocClipBase *clip = item->referencedClip();
+ if (!clip || !clip->isClean() || m_render->isProcessing(item->clipId())) {
+ kDebug()<<"//// TRYING TO PROXY: "<<item->clipId()<<", but it is busy";
+ continue;
}
+
+ oldProps = clip->properties();
+ if (doProxy) {
+ newProps.clear();
+ QString path = proxydir + clip->getClipHash() + "." + (t == IMAGE ? "png" : m_doc->getDocumentProperty("proxyextension"));
+ // insert required duration for proxy
+ newProps.insert("proxy_out", clip->producerProperty("out"));
+ newProps.insert("proxy", path);
+ // We need to insert empty proxy so that undo will work
+ oldProps.insert("proxy", QString());
+ }
+ else if (item->referencedClip()->getProducer() == NULL) {
+ // Force clip reload
+ kDebug()<<"// CLIP HAD NULL PROD------------";
+ newProps.insert("resource", item->referencedClip()->getProperty("resource"));
+ }
+ new EditClipCommand(this, item->clipId(), oldProps, newProps, true, command);
}
}
if (command->childCount() > 0) {
if (item->referencedClip()->getProperty("proxy") == proxyPath) {
QMap <QString, QString> props;
props.insert("proxy", QString());
- new EditClipCommand(this, item->clipId(), item->referencedClip()->properties(), props, true, proxyCommand);
+ new EditClipCommand(this, item->clipId(), item->referencedClip()->currentProperties(props), props, true, proxyCommand);
}
}
QDomElement xml = clip->toXML();
m_render->getFileProperties(xml, clip->getId(), m_listView->iconSize().height(), true);
}
+ else {
+ // Disable proxy for this clip
+ clip->setProperty("proxy", "-");
+ }
}
monitorItemEditing(true);
}
QBrush brush;
QColor color;
if (proxy > 0) {
- proxyText = QString::number(proxy) + "% ";
- proxyText.append(i18n("Generating proxy ..."));
+ proxyText = i18n("Proxy %1\%", proxy);
brush = option.palette.highlight();
color = option.palette.color(QPalette::HighlightedText);
/** @brief Process ffmpeg output to find out process progress. */
void processLogInfo(QList <ProjectItem *>items, int *duration, const QString &log);
void monitorItemEditing(bool enable);
- /** @brief Set thumbnail for a project's clip. */
- void setThumbnail(const QString &clipId, const QPixmap &pix);
/** @brief Get cached thumbnail for a project's clip or create it if no cache. */
void getCachedThumbnail(ProjectItem *item);
void getCachedThumbnail(SubProjectItem *item);
void slotGenerateProxy();
signals:
- void clipSelected(DocClipBase *, QPoint zone = QPoint());
+ void clipSelected(DocClipBase *, QPoint zone = QPoint(), bool forceUpdate = false);
void receivedClipDuration(const QString &);
void showClipProperties(DocClipBase *);
void showClipProperties(QList <DocClipBase *>, QMap<QString, QString> commonproperties);
void Render::forceProcessing(const QString &id)
{
+ if (m_processingClipId == id) return;
m_infoMutex.lock();
for (int i = 0; i < m_requestList.count(); i++) {
requestClipInfo info = m_requestList.at(i);
return m_mltProducer;
}
+const QString Render::activeClipId()
+{
+ if (m_mltProducer) return m_mltProducer->get("id");
+ return QString();
+}
#include "renderer.moc"
Mlt::Tractor *lockService();
/** @brief Unlock the MLT service */
void unlockService(Mlt::Tractor *tractor);
+ const QString activeClipId();
private:
m_blockProcessing(false)
{
m_view.setupUi(this);
+ int size = style()->pixelMetric(QStyle::PM_SmallIconSize);
+ QSize iconSize(size, size);
+
setWindowTitle(i18n("Rendering"));
+ m_view.buttonDelete->setIconSize(iconSize);
+ m_view.buttonEdit->setIconSize(iconSize);
+ m_view.buttonSave->setIconSize(iconSize);
+ m_view.buttonInfo->setIconSize(iconSize);
+ m_view.buttonFavorite->setIconSize(iconSize);
+
m_view.buttonDelete->setIcon(KIcon("trash-empty"));
m_view.buttonDelete->setToolTip(i18n("Delete profile"));
m_view.buttonDelete->setEnabled(false);
m_view.buttonRender->setEnabled(false);
m_view.buttonGenerateScript->setEnabled(false);
- m_view.rescale_box->setEnabled(false);
+ setRescaleEnabled(false);
m_view.guides_box->setVisible(false);
m_view.open_dvd->setVisible(false);
m_view.create_chapter->setVisible(false);
connect(m_view.buttonClose, SIGNAL(clicked()), this, SLOT(hide()));
connect(m_view.buttonClose2, SIGNAL(clicked()), this, SLOT(hide()));
connect(m_view.buttonClose3, SIGNAL(clicked()), this, SLOT(hide()));
- connect(m_view.rescale, SIGNAL(toggled(bool)), m_view.rescale_box, SLOT(setEnabled(bool)));
+ connect(m_view.rescale, SIGNAL(toggled(bool)), this, SLOT(setRescaleEnabled(bool)));
connect(m_view.destination_list, SIGNAL(activated(int)), this, SLOT(refreshCategory()));
connect(m_view.out_file, SIGNAL(textChanged(const QString &)), this, SLOT(slotUpdateButtons()));
connect(m_view.out_file, SIGNAL(urlSelected(const KUrl &)), this, SLOT(slotUpdateButtons(const KUrl &)));
m_view.scripts_list->clear();
delete m_jobsDelegate;
delete m_scriptsDelegate;
+#if KDE_IS_VERSION(4,7,0)
+ delete m_infoMessage;
+#endif
}
void RenderWidget::slotEditItem(QListWidgetItem *item)
if (params.contains(" s=") || params.startsWith("s=") || destination == "audioonly") {
// profile has a fixed size, do not allow resize
m_view.rescale->setEnabled(false);
- m_view.rescale_box->setEnabled(false);
+ setRescaleEnabled(false);
} else {
m_view.rescale->setEnabled(true);
- m_view.rescale_box->setEnabled(m_view.rescale->isChecked());
+ setRescaleEnabled(m_view.rescale->isChecked());
}
KUrl url = filenameWithExtension(m_view.out_file->url(), extension);
m_view.out_file->setUrl(url);
{
return m_view.proxy_render->isChecked();
}
+
+void RenderWidget::setRescaleEnabled(bool enable)
+{
+ for (int i = 0; i < m_view.rescale_box->layout()->count(); i++) {
+ if (m_view.rescale_box->itemAt(i)->widget()) m_view.rescale_box->itemAt(i)->widget()->setEnabled(enable);
+ }
+}
void slotSwitchAspectRatio();
/** @brief Update export audio label depending on current settings. */
void slotUpdateAudioLabel(int ix);
+ /** @brief Enable / disable the rescale options. */
+ void setRescaleEnabled(bool enable);
private:
Ui::RenderWidget_UI m_view;
m_view.animation->addItem(i18n("Zoom"), "Zoom");
m_view.animation->addItem(i18n("Zoom, low-pass"), "Zoom, low-pass");
- m_view.clip_duration->setInputMask("");
- m_view.clip_duration->setValidator(m_timecode.validator());
- m_view.luma_duration->setInputMask("");
- m_view.luma_duration->setValidator(m_timecode.validator());
+ m_view.clip_duration->setInputMask(m_timecode.mask());
+ m_view.luma_duration->setInputMask(m_timecode.mask());
m_view.luma_duration->setText(m_timecode.getTimecodeFromFrames(int(ceil(m_timecode.fps()))));
m_view.folder_url->setUrl(QDir::homePath());
bool framesFormat = ix == 1;
if (framesFormat) {
// switching to frames count, update widget
+ m_view.clip_duration->setInputMask("");
m_view.clip_duration_frames->setValue(m_timecode.getFrameCount(m_view.clip_duration->text()));
+ m_view.luma_duration->setInputMask("");
m_view.luma_duration_frames->setValue(m_timecode.getFrameCount(m_view.luma_duration->text()));
} else {
// switching to timecode format
- m_view.clip_duration->setInputMask("");
- m_view.clip_duration->setValidator(m_timecode.validator());
+ m_view.clip_duration->setInputMask(m_timecode.mask());
m_view.clip_duration->setText(m_timecode.getTimecodeFromFrames(m_view.clip_duration_frames->value()));
- m_view.luma_duration->setInputMask("");
- m_view.luma_duration->setValidator(m_timecode.validator());
+ m_view.luma_duration->setInputMask(m_timecode.mask());
m_view.luma_duration->setText(m_timecode.getTimecodeFromFrames(m_view.luma_duration_frames->value()));
}
m_view.clip_duration_frames->setHidden(!framesFormat);
*/
-#include <QValidator>
#include <KDebug>
#include <KLocale>
Timecode::Timecode(Formats format, double framesPerSecond)
{
- m_validator = new QRegExpValidator(0);
setFormat(framesPerSecond, format);
}
m_dropFrames = round(m_realFps * .066666); //Number of frames to drop on the minute marks is the nearest integer to 6% of the framerate
m_framesPer10Minutes = round(m_realFps * 600); //Number of frames per ten minutes
}
- QRegExp regExp;
- if (m_dropFrameTimecode)
- regExp.setPattern("^\\d{2}:\\d{2}:\\d{2};\\d{2}$");
- else
- regExp.setPattern("^\\d{2}:\\d{2}:\\d{2}:\\d{2}$");
- m_validator->setRegExp(regExp);
}
double Timecode::fps() const
return m_dropFrameTimecode;
}
-const QValidator *Timecode::validator() const
+const QString Timecode::mask(GenTime t) const
{
- return m_validator;
+ if (t < GenTime()) {
+ if (m_dropFrameTimecode) return "#99:99:99,99";
+ else return "#99:99:99:99";
+ }
+ if (m_dropFrameTimecode) return "99:99:99,99";
+ else return "99:99:99:99";
}
QString Timecode::reformatSeparators(QString duration) const
{
if (m_dropFrameTimecode)
- return duration.replace(8, 1, ';');
+ return duration.replace(8, 1, ',');
return duration.replace(8, 1, ':');
}
int Timecode::getFrameCount(const QString &duration) const
{
+ if (duration.isEmpty()) {
+ return 0;
+ }
+ int hours, minutes, seconds, frames;
+ int offset = 0;
+ if (duration.at(0) == '-') {
+ offset = 1;
+ hours = duration.mid(1, 2).toInt();
+ } else {
+ hours = duration.left(2).toInt();
+ }
+ minutes = duration.mid(3 + offset, 2).toInt();
+ seconds = duration.mid(6 + offset, 2).toInt();
+ frames = duration.right(2).toInt();
if (m_dropFrameTimecode) {
-
//CONVERT DROP FRAME TIMECODE TO A FRAME NUMBER
//Code by David Heidelberger, adapted from Andrew Duncan
//Given ints called hours, minutes, seconds, frames, and a double called framerate
- //Get Hours, Minutes, Seconds, Frames from timecode
- int hours, minutes, seconds, frames;
-
- hours = duration.section(':', 0, 0).toInt();
- minutes = duration.section(':', 1, 1).toInt();
- if (duration.contains(';')) {
- seconds = duration.section(';', 0, 0).section(':', 2, 2).toInt();
- frames = duration.section(';', 1, 1).toInt();
- } else {
- //Handle Drop Frame timecode frame calculations, even if the timecode supplied uses incorrect "99:99:99:99" format instead of "99:99:99;99"
- seconds = duration.section(':', 2, 2).toInt();
- frames = duration.section(':', 3, 3).toInt();
- }
-
int totalMinutes = (60 * hours) + minutes; //Total number of minutes
int frameNumber = ((m_displayedFramesPerSecond * 3600 * hours) + (m_displayedFramesPerSecond * 60 * minutes) + (m_displayedFramesPerSecond * seconds) + frames) - (m_dropFrames * (totalMinutes - floor(totalMinutes / 10)));
return frameNumber;
}
- return (int)((duration.section(':', 0, 0).toInt()*3600.0 + duration.section(':', 1, 1).toInt()*60.0 + duration.section(':', 2, 2).toInt()) * m_realFps + duration.section(':', 3, 3).toInt());
+ return (int)((hours * 3600.0 + minutes * 60.0 + seconds) * m_realFps + frames);
}
QString Timecode::getDisplayTimecode(const GenTime & time, bool frameDisplay) const
text.append(':');
text.append(QString::number(seconds).rightJustified(2, '0', false));
if (m_dropFrameTimecode)
- text.append(';');
+ text.append(',');
else
text.append(':');
text.append(QString::number(hundredths).rightJustified(2, '0', false));
text.append(QString::number(minutes).rightJustified(2, '0', false));
text.append(':');
text.append(QString::number(seconds).rightJustified(2, '0', false));
- text.append(';');
+ text.append(',');
text.append(QString::number(frames).rightJustified(2, '0', false));
return text;
#include "gentime.h"
-class QValidator;
-class QRegExpValidator;
-
/**
Handles the conversion of a GenTime into a nicely formatted string, taking into account things such as drop frame if necessary. Handles multiple formats, such as HH:MM:SS:FF, HH:MM:SS:F, All Frames, All Seconds, etc.
const QString getTimecodeFromFrames(int frames) const;
double fps() const;
bool df() const;
- const QValidator *validator() const;
+ const QString mask(GenTime t = GenTime()) const;
QString reformatSeparators(QString duration) const;
private:
double m_realFps;
double m_dropFrames;
int m_framesPer10Minutes;
- QRegExpValidator *m_validator;
const QString getTimecodeHH_MM_SS_FF(const GenTime & time) const;
const QString getTimecodeHH_MM_SS_FF(int frames) const;
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
setAccelerated(true);
+ setValue(m_minimum);
+
setTimeCodeFormat(KdenliveSettings::frametimecode(), true);
connect(lineEdit(), SIGNAL(editingFinished()), this, SLOT(slotEditingFinished()));
- connect(lineEdit(), SIGNAL(cursorPositionChanged(int, int)), this, SLOT(slotCursorPositionChanged(int, int)));
}
// virtual protected
QAbstractSpinBox::StepEnabled TimecodeDisplay::stepEnabled () const
{
QAbstractSpinBox::StepEnabled result = QAbstractSpinBox::StepNone;
- if (getValue() > m_minimum) result |= QAbstractSpinBox::StepDownEnabled;
- if (m_maximum == -1 || getValue() < m_maximum) result |= QAbstractSpinBox::StepUpEnabled;
+ if (m_value > m_minimum) result |= QAbstractSpinBox::StepDownEnabled;
+ if (m_maximum == -1 || m_value < m_maximum) result |= QAbstractSpinBox::StepUpEnabled;
return result;
}
// virtual
void TimecodeDisplay::stepBy(int steps)
{
- int val = getValue();
- val += steps;
+ int val = m_value + steps;
setValue(val);
emit editingFinished();
}
void TimecodeDisplay::setTimeCodeFormat(bool frametimecode, bool init)
{
if (!init && m_frametimecode == frametimecode) return;
- int val = getValue();
m_frametimecode = frametimecode;
+ lineEdit()->clear();
if (m_frametimecode) {
QIntValidator *valid = new QIntValidator(lineEdit());
valid->setBottom(0);
lineEdit()->setValidator(valid);
+ lineEdit()->setInputMask(QString());
} else {
- lineEdit()->setValidator(m_timecode.validator());
+ lineEdit()->setValidator(0);
+ lineEdit()->setInputMask(m_timecode.mask());
}
- setValue(val);
+ setValue(m_value);
}
void TimecodeDisplay::slotUpdateTimeCodeFormat()
void TimecodeDisplay::keyPressEvent(QKeyEvent *e)
{
- if (e->key() == Qt::Key_Return)
- slotEditingFinished();
+ if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
+ e->setAccepted(true);
+ clearFocus();
+ }
else
QAbstractSpinBox::keyPressEvent(e);
}
int TimecodeDisplay::getValue() const
{
- if (m_frametimecode) return lineEdit()->text().toInt();
- else return m_timecode.getFrameCount(lineEdit()->text());
+ return m_value;
}
GenTime TimecodeDisplay::gentime() const
{
- return GenTime(getValue(), m_timecode.fps());
+ return GenTime(m_value, m_timecode.fps());
}
Timecode TimecodeDisplay::timecode() const
value = m_minimum;
if (m_maximum > m_minimum && value > m_maximum)
value = m_maximum;
-
- if (value == getValue() && !lineEdit()->text().isEmpty()) return;
- //downarrow->setEnabled(value > m_minimum);
- //uparrow->setEnabled(m_maximum < m_minimum || value < m_maximum);
+ if (value == m_value && !lineEdit()->text().isEmpty()) return;
+ m_value = value;
if (m_frametimecode)
lineEdit()->setText(QString::number(value));
void TimecodeDisplay::setValue(GenTime value)
{
- setValue(m_timecode.getTimecode(value));
+ setValue((int) value.frames(m_timecode.fps()));
}
-void TimecodeDisplay::slotCursorPositionChanged(int oldPos, int newPos)
-{
- if (!lineEdit()->hasFocus()) return;
- lineEdit()->blockSignals(true);
- QString text = lineEdit()->text();
-
- if (newPos < text.size() && !text.at(newPos).isDigit()) {
- // char at newPos is a separator (':' or ';')
-
- // make it possible move the cursor backwards at separators
- if (newPos == oldPos - 1)
- lineEdit()->setSelection(newPos, -1);
- else
- lineEdit()->setSelection(newPos + 2, -1);
- } else if (newPos < text.size()) {
- lineEdit()->setSelection(newPos + 1, -1);
- } else {
- lineEdit()->setSelection(newPos, -1);
- }
-
- lineEdit()->blockSignals(false);
-}
void TimecodeDisplay::slotEditingFinished()
{
- clearFocus();
lineEdit()->deselect();
+ if (m_frametimecode) setValue(lineEdit()->text().toInt());
+ else setValue(lineEdit()->text());
emit editingFinished();
}
bool m_frametimecode;
int m_minimum;
int m_maximum;
+ int m_value;
public slots:
/** @brief Sets the value.
private slots:
void slotEditingFinished();
- /** @brief Updates the selection when the cursor position changed.
- * The digit after the cursor will be selected.
- * This makes it easier to edit the timecode. */
- void slotCursorPositionChanged(int oldPos, int newPos);
-
signals:
/**
* Emitted every time the value changes (by calling setValue() or
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<QColor>();
+ content.setAttribute("font-outline-color", colorToString(outlineColor));
+ }
}
if (!t->data(100).isNull()) {
QStringList effectParams = t->data(100).toStringList();
setFont(KGlobalSettings::toolBarFont());
frame_properties->setEnabled(false);
frame_properties->setFixedHeight(frame_toolbar->height());
+ int size = style()->pixelMetric(QStyle::PM_SmallIconSize);
+ QSize iconSize(size, size);
+
+#if KDE_IS_VERSION(4,5,0)
+ rectBColor->setAlphaChannelEnabled(true);
+ delete rectBAlpha;
+ rectFColor->setAlphaChannelEnabled(true);
+ delete rectFAlpha;
+ fontColorButton->setAlphaChannelEnabled(true);
+ delete textAlpha;
+ textOutlineColor->setAlphaChannelEnabled(true);
+ delete textOutlineAlpha;
+
+#else
+ rectBAlpha->setMinimum(0);
+ rectBAlpha->setMaximum(255);
+ rectBAlpha->setDecimals(0);
+ rectBAlpha->setValue(255);
+ rectBAlpha->setToolTip(i18n("Color opacity"));
+
+ rectFAlpha->setMinimum(0);
+ rectFAlpha->setMaximum(255);
+ rectFAlpha->setDecimals(0);
+ rectFAlpha->setValue(255);
+ rectFAlpha->setToolTip(i18n("Border opacity"));
+ connect(rectFAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(rectChanged()));
+ connect(rectBAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(rectChanged()));
// Set combo sliders values
textAlpha->setMinimum(0);
textOutlineAlpha->setDecimals(0);
textOutlineAlpha->setValue(255);
textOutlineAlpha->setToolTip(i18n("Outline color opacity"));
+ connect(textAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotUpdateText()));
+ connect(textOutlineAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotUpdateText()));
+#endif
textOutline->setMinimum(0);
textOutline->setMaximum(200);
itemrotatez->setValue(0);
itemrotatez->setToolTip(i18n("Rotation around the Z axis"));
- rectBAlpha->setMinimum(0);
- rectBAlpha->setMaximum(255);
- rectBAlpha->setDecimals(0);
- rectBAlpha->setValue(255);
- rectBAlpha->setToolTip(i18n("Color opacity"));
-
- rectFAlpha->setMinimum(0);
- rectFAlpha->setMaximum(255);
- rectFAlpha->setDecimals(0);
- rectFAlpha->setValue(255);
- rectFAlpha->setToolTip(i18n("Border opacity"));
-
rectLineWidth->setMinimum(0);
rectLineWidth->setMaximum(100);
rectLineWidth->setDecimals(0);
splitter->setStretchFactor(0, 20);
//If project is drop frame, set the input mask as such.
- title_duration->setInputMask("");
- title_duration->setValidator(m_tc.validator());
+ title_duration->setInputMask(m_tc.mask());
title_duration->setText(m_tc.reformatSeparators(KdenliveSettings::title_duration()));
connect(backgroundColor, SIGNAL(clicked()), this, SLOT(slotChangeBackground())) ;
connect(textOutlineColor, SIGNAL(clicked()), this, SLOT(slotUpdateText())) ;
connect(font_family, SIGNAL(currentFontChanged(const QFont &)), this, SLOT(slotUpdateText())) ;
connect(font_size, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateText())) ;
- connect(textAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotUpdateText()));
connect(textOutline, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotUpdateText()));
- connect(textOutlineAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotUpdateText()));
connect(font_weight_box, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateText()));
connect(font_family, SIGNAL(editTextChanged(const QString &)), this, SLOT(slotFontText(const QString&)));
- connect(rectFAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(rectChanged()));
- connect(rectBAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(rectChanged()));
connect(rectFColor, SIGNAL(clicked()), this, SLOT(rectChanged()));
connect(rectBColor, SIGNAL(clicked()), this, SLOT(rectChanged()));
connect(rectLineWidth, SIGNAL(valueChanged(qreal, bool)), this, SLOT(rectChanged()));
font_weight_box->setCurrentIndex(1);
font_weight_box->blockSignals(false);
+ buttonFitZoom->setIconSize(iconSize);
+ buttonRealSize->setIconSize(iconSize);
+ buttonItalic->setIconSize(iconSize);
+ buttonUnder->setIconSize(iconSize);
+ buttonAlignCenter->setIconSize(iconSize);
+ buttonAlignLeft->setIconSize(iconSize);
+ buttonAlignRight->setIconSize(iconSize);
+ buttonAlignNone->setIconSize(iconSize);
+
buttonFitZoom->setIcon(KIcon("zoom-fit-best"));
buttonRealSize->setIcon(KIcon("zoom-original"));
buttonItalic->setIcon(KIcon("format-text-italic"));
buttonUnselectAll->setDefaultAction(m_unselectAll);
buttonUnselectAll->setEnabled(false);
+ zDown->setIconSize(iconSize);
+ zTop->setIconSize(iconSize);
+ zBottom->setIconSize(iconSize);
+
zDown->setIcon(KIcon("kdenlive-zindex-down"));
zTop->setIcon(KIcon("kdenlive-zindex-top"));
zBottom->setIcon(KIcon("kdenlive-zindex-bottom"));
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 opacity"));
- rectFAlpha->setToolTip(i18n("Border opacity"));
zoom_slider->setToolTip(i18n("Zoom"));
buttonRealSize->setToolTip(i18n("Original size (1:1)"));
buttonFitZoom->setToolTip(i18n("Fit zoom"));
buttonSelectImages->setToolTip(getTooltipWithShortcut(i18n("Select image items in current selection"), m_selectImages));
buttonUnselectAll->setToolTip(getTooltipWithShortcut(i18n("Unselect all"), m_unselectAll));
+ itemhcenter->setIconSize(iconSize);
+ itemvcenter->setIconSize(iconSize);
+ itemtop->setIconSize(iconSize);
+ itembottom->setIconSize(iconSize);
+ itemright->setIconSize(iconSize);
+ itemleft->setIconSize(iconSize);
+
itemhcenter->setIcon(KIcon("kdenlive-align-hor"));
itemhcenter->setToolTip(i18n("Align item horizontally"));
itemvcenter->setIcon(KIcon("kdenlive-align-vert"));
frame_toolbar->setLayout(layout);
layout->setContentsMargins(0, 0, 0, 0);
QToolBar *m_toolbar = new QToolBar("titleToolBar", this);
- int s = style()->pixelMetric(QStyle::PM_SmallIconSize);
- m_toolbar->setIconSize(QSize(s, s));
+ m_toolbar->setIconSize(iconSize);
m_buttonCursor = m_toolbar->addAction(KIcon("transform-move"), QString());
m_buttonCursor->setCheckable(true);
templateBox->addItem(t.icon, t.name, t.file);
}
lastDocumentHash = QCryptographicHash::hash(xml().toString().toAscii(), QCryptographicHash::Md5).toHex();
+ adjustSize();
}
TitleWidget::~TitleWidget()
delete m_signalMapper;
}
+QSize TitleWidget::sizeHint() const
+{
+ // Make sure the widget has minimum size on opening
+ return QSize(200, 200);
+}
+
//static
QStringList TitleWidget::getFreeTitleInfo(const KUrl &projectUrl, bool isClone)
{
updateAxisButtons(rect); // back to default
QColor f = rectFColor->color();
+#if not KDE_IS_VERSION(4,5,0)
f.setAlpha(rectFAlpha->value());
+#endif
QPen penf(f);
penf.setWidth(rectLineWidth->value());
penf.setJoinStyle(Qt::RoundJoin);
rect->setPen(penf);
QColor b = rectBColor->color();
+#if not KDE_IS_VERSION(4,5,0)
b.setAlpha(rectBAlpha->value());
+#endif
rect->setBrush(QBrush(b));
rect->setZValue(m_count++);
rect->setData(ZOOMFACTOR, 100);
tt->setFont(font);
QColor color = fontColorButton->color();
+ QColor outlineColor = textOutlineColor->color();
+#if not KDE_IS_VERSION(4,5,0)
color.setAlpha(textAlpha->value());
+ outlineColor.setAlpha(textOutlineAlpha->value());
+#endif
tt->setDefaultTextColor(color);
QTextCursor cur(tt->document());
cur.select(QTextCursor::Document);
QTextBlockFormat format = cur.blockFormat();
QTextCharFormat cformat = cur.charFormat();
- QColor outlineColor = textOutlineColor->color();
- outlineColor.setAlpha(textOutlineAlpha->value());
double outlineWidth = textOutline->value() / 10.0;
tt->setData(101, outlineWidth);
font.setUnderline(buttonUnder->isChecked());
font.setWeight(font_weight_box->itemData(font_weight_box->currentIndex()).toInt());
QColor color = fontColorButton->color();
- color.setAlpha(textAlpha->value());
-
QColor outlineColor = textOutlineColor->color();
+#if not KDE_IS_VERSION(4,5,0)
+ color.setAlpha(textAlpha->value());
outlineColor.setAlpha(textOutlineAlpha->value());
+#endif
+
double outlineWidth = textOutline->value() / 10.0;
int i;
if (l.at(i)->type() == RECTITEM && !settingUp) {
QGraphicsRectItem *rec = static_cast<QGraphicsRectItem *>(l.at(i));
QColor f = rectFColor->color();
+#if not KDE_IS_VERSION(4,5,0)
f.setAlpha(rectFAlpha->value());
+#endif
QPen penf(f);
penf.setWidth(rectLineWidth->value());
penf.setJoinStyle(Qt::RoundJoin);
rec->setPen(penf);
QColor b = rectBColor->color();
+#if not KDE_IS_VERSION(4,5,0)
b.setAlpha(rectBAlpha->value());
+#endif
rec->setBrush(QBrush(b));
}
}
//titleConfig.writeEntry("font_size", font_size->value());
titleConfig.writeEntry("font_pixel_size", font_size->value());
titleConfig.writeEntry("font_color", fontColorButton->color());
- titleConfig.writeEntry("font_alpha", textAlpha->value());
- titleConfig.writeEntry("font_outline", textOutline->value());
titleConfig.writeEntry("font_outline_color", textOutlineColor->color());
+#if KDE_IS_VERSION(4,5,0)
+ titleConfig.writeEntry("font_alpha", fontColorButton->color().alpha());
+ titleConfig.writeEntry("font_outline_alpha", textOutlineColor->color().alpha());
+#else
+ titleConfig.writeEntry("font_alpha", textAlpha->value());
titleConfig.writeEntry("font_outline_alpha", textOutlineAlpha->value());
+#endif
+
+ titleConfig.writeEntry("font_outline", textOutline->value());
titleConfig.writeEntry("font_weight", font_weight_box->itemData(font_weight_box->currentIndex()).toInt());
titleConfig.writeEntry("font_italic", buttonItalic->isChecked());
titleConfig.writeEntry("font_underlined", buttonUnder->isChecked());
- titleConfig.writeEntry("rect_foreground_color", rectFColor->color());
- titleConfig.writeEntry("rect_foreground_alpha", rectFAlpha->value());
titleConfig.writeEntry("rect_background_color", rectBColor->color());
+ titleConfig.writeEntry("rect_foreground_color", rectFColor->color());
+
+#if KDE_IS_VERSION(4,5,0)
+ titleConfig.writeEntry("rect_background_alpha", rectBColor->color().alpha());
+ titleConfig.writeEntry("rect_foreground_alpha", rectFColor->color().alpha());
+#else
titleConfig.writeEntry("rect_background_alpha", rectBAlpha->value());
+ titleConfig.writeEntry("rect_foreground_alpha", rectFAlpha->value());
+#endif
+
titleConfig.writeEntry("rect_line_width", rectLineWidth->value());
titleConfig.writeEntry("background_color", backgroundColor->color());
font_family->setCurrentFont(titleConfig.readEntry("font_family", font_family->currentFont()));
font_size->setValue(titleConfig.readEntry("font_pixel_size", font_size->value()));
m_scene->slotUpdateFontSize(font_size->value());
- fontColorButton->setColor(titleConfig.readEntry("font_color", fontColorButton->color()));
+ QColor fontColor = QColor(titleConfig.readEntry("font_color", fontColorButton->color()));
+ QColor outlineColor = QColor(titleConfig.readEntry("font_outline_color", textOutlineColor->color()));
+#if KDE_IS_VERSION(4,5,0)
+ fontColor.setAlpha(titleConfig.readEntry("font_alpha", fontColor.alpha()));
+ outlineColor.setAlpha(titleConfig.readEntry("font_outline_alpha", outlineColor.alpha()));
+#else
textAlpha->setValue(titleConfig.readEntry("font_alpha", textAlpha->value()));
-
- textOutlineColor->setColor(titleConfig.readEntry("font_outline_color", textOutlineColor->color()));
textOutlineAlpha->setValue(titleConfig.readEntry("font_outline_alpha", textOutlineAlpha->value()));
+#endif
+ fontColorButton->setColor(fontColor);
+ textOutlineColor->setColor(outlineColor);
textOutline->setValue(titleConfig.readEntry("font_outline", textOutline->value()));
int weight;
buttonItalic->setChecked(titleConfig.readEntry("font_italic", buttonItalic->isChecked()));
buttonUnder->setChecked(titleConfig.readEntry("font_underlined", buttonUnder->isChecked()));
- rectFColor->setColor(titleConfig.readEntry("rect_foreground_color", rectFColor->color()));
+ QColor fgColor = QColor(titleConfig.readEntry("rect_foreground_color", rectFColor->color()));
+ QColor bgColor = QColor(titleConfig.readEntry("rect_background_color", rectBColor->color()));
+
+#if KDE_IS_VERSION(4,5,0)
+ fgColor.setAlpha(titleConfig.readEntry("rect_background_alpha", fgColor.alpha()));
+ bgColor.setAlpha(titleConfig.readEntry("rect_background_alpha", bgColor.alpha()));
+#else
rectFAlpha->setValue(titleConfig.readEntry("rect_foreground_alpha", rectFAlpha->value()));
- rectBColor->setColor(titleConfig.readEntry("rect_background_color", rectBColor->color()));
rectBAlpha->setValue(titleConfig.readEntry("rect_background_alpha", rectBAlpha->value()));
+#endif
+ rectFColor->setColor(fgColor);
+ rectBColor->setColor(bgColor);
+
rectLineWidth->setValue(titleConfig.readEntry("rect_line_width", rectLineWidth->value()));
backgroundColor->setColor(titleConfig.readEntry("background_color", backgroundColor->color()));
buttonItalic->blockSignals(true);
buttonUnder->blockSignals(true);
fontColorButton->blockSignals(true);
+#if not KDE_IS_VERSION(4,5,0)
textAlpha->blockSignals(true);
+#endif
buttonAlignLeft->blockSignals(true);
buttonAlignRight->blockSignals(true);
buttonAlignNone->blockSignals(true);
QTextCursor cursor(i->document());
cursor.select(QTextCursor::Document);
QColor color = cursor.charFormat().foreground().color();
+#if not KDE_IS_VERSION(4,5,0)
textAlpha->setValue(color.alpha());
color.setAlpha(255);
+#endif
fontColorButton->setColor(color);
if (!i->data(101).isNull()) {
}
if (!i->data(102).isNull()) {
textOutlineColor->blockSignals(true);
+ QVariant variant = i->data(102);
+ color = variant.value<QColor>();
+#if not KDE_IS_VERSION(4,5,0)
textOutlineAlpha->blockSignals(true);
- color = QColor(i->data(102).toString());
textOutlineAlpha->setValue(color.alpha());
color.setAlpha(255);
+ textOutlineAlpha->blockSignals(false);
+#endif
textOutlineColor->setColor(color);
textOutlineColor->blockSignals(false);
- textOutlineAlpha->blockSignals(false);
}
QTextCursor cur = i->textCursor();
QTextBlockFormat format = cur.blockFormat();
buttonItalic->blockSignals(false);
buttonUnder->blockSignals(false);
fontColorButton->blockSignals(false);
+#if not KDE_IS_VERSION(4,5,0)
textAlpha->blockSignals(false);
+#endif
buttonAlignLeft->blockSignals(false);
buttonAlignRight->blockSignals(false);
buttonAlignNone->blockSignals(false);
toolBox->widget(1)->setEnabled(true);
toolBox->setCurrentIndex(0);*/
//toolBox->setItemEnabled(3, true);
+#if not KDE_IS_VERSION(4,5,0)
rectFAlpha->setValue(rec->pen().color().alpha());
rectBAlpha->setValue(rec->brush().color().alpha());
+#endif
//kDebug() << rec->brush().color().alpha();
QColor fcol = rec->pen().color();
QColor bcol = rec->brush().color();
protected:
virtual void resizeEvent(QResizeEvent * event);
+ virtual QSize sizeHint() const;
private:
return MOVE;
}
+//static
int Transition::itemHeight()
{
return (int) (KdenliveSettings::trackheight() / 3 * 2 - 1);
}
+//static
int Transition::itemOffset()
{
return (int) (KdenliveSettings::trackheight() / 3 * 2);
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Fontval_UI</class>
+ <widget class="QWidget" name="Fontval_UI">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>200</width>
+ <height>60</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="name">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QFontComboBox" name="fontfamilywidget"/>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Keywordval_UI</class>
+ <widget class="QWidget" name="Keywordval_UI">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>194</width>
+ <height>42</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="verticalSpacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item row="0" column="0" colspan="2">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Param</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLineEdit" name="lineeditwidget"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QComboBox" name="comboboxwidget"/>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
<rect>
<x>0</x>
<y>0</y>
- <width>402</width>
- <height>681</height>
+ <width>456</width>
+ <height>677</height>
</rect>
</property>
<property name="windowTitle">
<attribute name="title">
<string>Render Project</string>
</attribute>
- <layout class="QGridLayout" name="gridLayout_7">
- <item row="0" column="0" colspan="2">
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Destination</string>
</property>
</widget>
</item>
- <item row="0" column="2" colspan="2">
+ <item row="0" column="3" colspan="2">
<widget class="KComboBox" name="destination_list"/>
</item>
- <item row="1" column="0" colspan="2">
+ <item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Output file</string>
</property>
</widget>
</item>
- <item row="1" column="2" colspan="2">
+ <item row="1" column="3" colspan="2">
<widget class="KUrlRequester" name="out_file"/>
</item>
<item row="2" column="0">
</property>
</widget>
</item>
- <item row="2" column="1" colspan="2">
+ <item row="2" column="3">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
- <item row="2" column="3">
+ <item row="2" column="4">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QToolButton" name="buttonFavorite">
</item>
</layout>
</item>
- <item row="3" column="0" colspan="4">
+ <item row="3" column="0" colspan="5">
<widget class="QSplitter" name="splitter_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</widget>
</widget>
</item>
- <item row="4" column="0" colspan="2">
+ <item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Scanning</string>
</property>
</widget>
</item>
- <item row="4" column="2">
+ <item row="4" column="3">
<widget class="KComboBox" name="scanning_list">
<item>
<property name="text">
</item>
</widget>
</item>
- <item row="4" column="3" rowspan="4">
+ <item row="4" column="4" rowspan="4">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Bitrate</string>
</property>
</widget>
</item>
- <item row="5" column="2">
+ <item row="5" column="3">
<widget class="KIntNumInput" name="encoder_threads">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
- <item row="6" column="0" colspan="3">
+ <item row="6" column="0" colspan="4">
<widget class="QCheckBox" name="export_audio">
<property name="text">
<string>Export audio</string>
</property>
</widget>
</item>
- <item row="7" column="0" colspan="2">
+ <item row="7" column="0">
<widget class="QCheckBox" name="checkTwoPass">
<property name="text">
<string>2 pass</string>
</property>
</widget>
</item>
- <item row="7" column="2">
+ <item row="7" column="3">
<widget class="QCheckBox" name="proxy_render">
<property name="text">
<string>Render using proxy clips</string>
</property>
</widget>
</item>
- <item row="8" column="0" colspan="4">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QCheckBox" name="rescale">
- <property name="text">
- <string>Rescale</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="rescale_box">
- <property name="title">
- <string/>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- <property name="checkable">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <property name="margin">
- <number>0</number>
- </property>
- <item row="0" column="1">
- <widget class="QLabel" name="label_8">
- <property name="text">
- <string>x</string>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="KIntNumInput" name="rescale_height">
- <property name="minimum">
- <number>0</number>
- </property>
- </widget>
- </item>
- <item row="0" column="3">
- <widget class="QToolButton" name="rescale_keep">
- <property name="text">
- <string>...</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="KIntNumInput" name="rescale_width">
- <property name="minimum">
- <number>0</number>
- </property>
- </widget>
- </item>
- <item row="0" column="4">
- <spacer name="horizontalSpacer_5">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
+ <item row="8" column="0">
+ <widget class="QCheckBox" name="rescale">
+ <property name="text">
+ <string>Rescale</string>
+ </property>
+ </widget>
</item>
- <item row="9" column="0" colspan="4">
+ <item row="9" column="0" colspan="5">
<widget class="QCheckBox" name="open_dvd">
<property name="text">
<string>Open Dvd wizard after rendering</string>
</property>
</widget>
</item>
- <item row="10" column="0" colspan="4">
+ <item row="10" column="0" colspan="5">
<widget class="QCheckBox" name="create_chapter">
<property name="text">
<string>Create chapter file based on guides</string>
</property>
</widget>
</item>
- <item row="11" column="0" colspan="4">
+ <item row="11" column="0" colspan="5">
<widget class="QCheckBox" name="open_browser">
<property name="text">
<string>Open browser window after export</string>
</property>
</widget>
</item>
- <item row="12" column="0" colspan="4">
+ <item row="12" column="0" colspan="5">
<widget class="QCheckBox" name="play_after">
<property name="text">
<string>Play after render</string>
</property>
</widget>
</item>
- <item row="13" column="0" colspan="4">
+ <item row="13" column="0" colspan="5">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QCheckBox" name="tc_overlay">
</item>
</layout>
</item>
- <item row="14" column="0" colspan="4">
+ <item row="14" column="0" colspan="5">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="render_full">
</item>
</layout>
</item>
- <item row="15" column="0" colspan="4">
+ <item row="15" column="0" colspan="5">
<widget class="QGroupBox" name="guides_box">
<property name="title">
<string/>
</layout>
</widget>
</item>
- <item row="17" column="0" colspan="4">
+ <item row="16" column="0" colspan="5">
+ <widget class="QGroupBox" name="errorBox">
+ <property name="title">
+ <string/>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_8">
+ <item row="0" column="0">
+ <widget class="QLabel" name="errorIcon">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="errorLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="17" column="0" colspan="5">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="buttonRender">
</item>
</layout>
</item>
- <item row="16" column="0" colspan="4">
- <widget class="QGroupBox" name="errorBox">
- <property name="title">
- <string/>
- </property>
- <layout class="QGridLayout" name="gridLayout_8">
- <item row="0" column="0">
- <widget class="QLabel" name="errorIcon">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="errorLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
+ <item row="8" column="1" colspan="4">
+ <layout class="QHBoxLayout" name="rescale_box">
+ <item>
+ <widget class="KIntNumInput" name="rescale_width">
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_8">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>x</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KIntNumInput" name="rescale_height">
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="rescale_keep">
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
</item>
</layout>
</widget>
<rect>
<x>0</x>
<y>0</y>
- <width>640</width>
- <height>480</height>
+ <width>1057</width>
+ <height>589</height>
</rect>
</property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
<property name="windowTitle">
<string>Title Clip</string>
</property>
</widget>
</widget>
</item>
+ <item row="3" column="0" colspan="2">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QToolButton" name="buttonFitZoom">
+ <property name="text">
+ <string>V</string>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="buttonRealSize">
+ <property name="text">
+ <string>V</string>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_8">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="zoom_slider">
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>150</number>
+ </property>
+ <property name="pageStep">
+ <number>30</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="zoom_label">
+ <property name="text">
+ <string>x1</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_7">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="displayBg">
+ <property name="text">
+ <string>Show background</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line_6">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_22">
+ <property name="text">
+ <string>Template:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="templateBox"/>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
<item row="2" column="0" colspan="2">
<widget class="QSplitter" name="splitter">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="verticalLayoutWidget">
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QGraphicsView" name="graphicsView">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <layout class="QGridLayout" name="gridLayout_16">
+ <property name="horizontalSpacing">
+ <number>-1</number>
+ </property>
+ <item row="2" column="0">
+ <widget class="QToolButton" name="buttonSelectImages">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>I</string>
</property>
</widget>
</item>
- <item>
- <widget class="QStackedWidget" name="bottomToolbarStack">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <item row="2" column="1">
+ <widget class="QToolButton" name="buttonSelectText">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>T</string>
</property>
- <widget class="QWidget" name="page_5">
- <layout class="QGridLayout" name="bottomToolbarGridLayout">
- <item row="0" column="0">
- <widget class="QToolButton" name="buttonSelectAll">
- <property name="whatsThis">
- <string>Selects all items on the canvas.</string>
- </property>
- <property name="text">
- <string>A</string>
- </property>
- </widget>
- </item>
- <item row="0" column="5">
- <spacer name="spacerBottomStack">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="0" column="2">
- <widget class="QToolButton" name="buttonSelectText">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>T</string>
- </property>
- </widget>
- </item>
- <item row="0" column="4">
- <widget class="QToolButton" name="buttonSelectImages">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>I</string>
- </property>
- </widget>
- </item>
- <item row="0" column="3">
- <widget class="QToolButton" name="buttonSelectRects">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>R</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QToolButton" name="buttonUnselectAll">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>N</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
</widget>
</item>
+ <item row="2" column="2">
+ <widget class="QToolButton" name="buttonUnselectAll">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>N</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="5">
+ <spacer name="spacerBottomStack">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="3">
+ <widget class="QToolButton" name="buttonSelectAll">
+ <property name="whatsThis">
+ <string>Selects all items on the canvas.</string>
+ </property>
+ <property name="text">
+ <string>A</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="4">
+ <widget class="QToolButton" name="buttonSelectRects">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>R</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="6">
+ <widget class="QGraphicsView" name="graphicsView"/>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
</property>
</widget>
</item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="typewriter_start">
+ <property name="suffix">
+ <string> frames</string>
+ </property>
+ </widget>
+ </item>
<item row="2" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
</property>
</spacer>
</item>
- <item row="1" column="1">
- <widget class="QSpinBox" name="typewriter_start">
- <property name="suffix">
- <string> frames</string>
- </property>
- </widget>
- </item>
</layout>
</widget>
</widget>
</layout>
</widget>
</item>
+ <item row="3" column="1">
+ <widget class="KoSliderCombo" name="itemrotatex"/>
+ </item>
+ <item row="4" column="1">
+ <widget class="KoSliderCombo" name="itemrotatey"/>
+ </item>
+ <item row="5" column="1">
+ <widget class="KoSliderCombo" name="itemrotatez"/>
+ </item>
<item row="8" column="0" colspan="2">
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</widget>
</widget>
</item>
- <item row="3" column="1">
- <widget class="KoSliderCombo" name="itemrotatex"/>
- </item>
- <item row="4" column="1">
- <widget class="KoSliderCombo" name="itemrotatey"/>
- </item>
- <item row="5" column="1">
- <widget class="KoSliderCombo" name="itemrotatez"/>
- </item>
</layout>
</widget>
</widget>
</item>
- <item row="3" column="0" colspan="2">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="topMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QToolButton" name="buttonFitZoom">
- <property name="text">
- <string>V</string>
- </property>
- <property name="autoRaise">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="buttonRealSize">
- <property name="text">
- <string>V</string>
- </property>
- <property name="autoRaise">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="Line" name="line_8">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSlider" name="zoom_slider">
- <property name="minimumSize">
- <size>
- <width>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>150</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>150</number>
- </property>
- <property name="pageStep">
- <number>30</number>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="zoom_label">
- <property name="text">
- <string>x1</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="Line" name="line_7">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="displayBg">
- <property name="text">
- <string>Show background</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="Line" name="line_6">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_22">
- <property name="text">
- <string>Template:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="templateBox"/>
- </item>
- <item>
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
- </property>
- </widget>
- </item>
- </layout>
- </item>
</layout>
</widget>
<customwidgets>