+Current git
+ * Fix archiving feature not saving playlist clips and slowmotion clips inside them
+ * Fix Crash recovery feature triggering error messages about wrong path
+ * Fix rendering jobs sometimes not starting
+ * Fix crash on proxy creation (concurrency issue)
+ * Fix zone playing
+ * Fix click on monitor sometimes not triggering play
+ * Add Online Resource Widget allowing easy search and download of online services (freesound, openclipart, archive.org)
+ * Introduce generic job framework for project tree jobs
+ * Fix color change not working in title widget
+ * Fix crash when moving a folder and a clip in project tree
+ * Fix profile warning with clips that have 1088 pixels height
+ * Add audio only recording (works while playing)
+
0.8.2.1
* Fix title text oultine transparency not working
* Make titler window fit on smaller resolutions (1024x768)
#include <KDebug>
#include <KApplication>
#include <kio/directorysizejob.h>
+#if KDE_IS_VERSION(4,7,0)
+#include <KMessageWidget>
+#endif
#include <QTreeWidget>
#include <QtConcurrentRun>
m_doc(doc),
m_abortArchive(false),
m_extractMode(false),
- m_extractArchive(NULL)
+ m_extractArchive(NULL),
+ m_missingClips(0)
{
setAttribute(Qt::WA_DeleteOnClose);
setupUi(this);
texts->setIcon(0, KIcon("text-plain"));
texts->setData(0, Qt::UserRole, "texts");
texts->setExpanded(false);
+ QTreeWidgetItem *playlists = new QTreeWidgetItem(files_list, QStringList() << i18n("Playlist clips"));
+ playlists->setIcon(0, KIcon("video-mlt-playlist"));
+ playlists->setData(0, Qt::UserRole, "playlist");
+ playlists->setExpanded(false);
QTreeWidgetItem *others = new QTreeWidgetItem(files_list, QStringList() << i18n("Other clips"));
others->setIcon(0, KIcon("unknown"));
others->setData(0, Qt::UserRole, "others");
QStringList videoUrls;
QStringList imageUrls;
QStringList otherUrls;
+ QStringList playlistUrls;
QStringList proxyUrls;
for (int i = 0; i < list.count(); i++) {
imageUrls << imagefiles;
allFonts << fonts;
} else if (t == PLAYLIST) {
+ playlistUrls << clip->fileURL().path();
QStringList files = ProjectSettings::extractPlaylistUrls(clip->fileURL().path());
otherUrls << files;
}
generateItems(videos, videoUrls);
generateItems(images, imageUrls);
generateItems(slideshows, slideUrls);
+ generateItems(playlists, playlistUrls);
generateItems(others, otherUrls);
generateItems(proxies, proxyUrls);
allFonts.removeDuplicates();
+#if KDE_IS_VERSION(4,7,0)
+ m_infoMessage = new KMessageWidget(this);
+ QVBoxLayout *s = static_cast <QVBoxLayout*> (layout());
+ s->insertWidget(5, m_infoMessage);
+ m_infoMessage->setCloseButtonVisible(false);
+ m_infoMessage->setWordWrap(true);
+ m_infoMessage->hide();
+#endif
+
+ // missing clips, warn user
+ if (m_missingClips > 0) {
+ QString infoText = i18np("You have %1 missing clip in your project.", "You have %1 missing clips in your project.", m_missingClips);
+#if KDE_IS_VERSION(4,7,0)
+ m_infoMessage->setMessageType(KMessageWidget::Warning);
+ m_infoMessage->setText(infoText);
+ m_infoMessage->animatedShow();
+#else
+ KMessageBox::sorry(this, infoText);
+#endif
+ }
+
//TODO: fonts
// Hide unused categories, add item count
buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Archive"));
connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(slotStartArchiving()));
buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
-
+
slotCheckSpace();
}
archive_url->setUrl(KUrl(QDir::homePath()));
buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Extract"));
connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(slotStartExtracting()));
- buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
+ buttonBox->button(QDialogButtonBox::Apply)->setEnabled(true);
adjustSize();
m_archiveThread = QtConcurrent::run(this, &ArchiveWidget::openArchiveForExtraction);
}
}
void ArchiveWidget::slotDisplayMessage(const QString &icon, const QString &text)
-{
+{
icon_info->setPixmap(KIcon(icon).pixmap(16, 16));
text_info->setText(text);
}
+void ArchiveWidget::slotJobResult(bool success, const QString &text)
+{
+#if KDE_IS_VERSION(4,7,0)
+ m_infoMessage->setMessageType(success ? KMessageWidget::Positive : KMessageWidget::Warning);
+ m_infoMessage->setText(text);
+ m_infoMessage->animatedShow();
+#else
+ if (success) icon_info->setPixmap(KIcon("dialog-ok").pixmap(16, 16));
+ else icon_info->setPixmap(KIcon("dialog-close").pixmap(16, 16));
+ text_info->setText(text);
+#endif
+}
+
void ArchiveWidget::openArchiveForExtraction()
{
emit showMessage("system-run", i18n("Opening archive..."));
item->setData(0, Qt::UserRole, fileName);
}
if (!isSlideshow) {
- m_requestedSize += QFileInfo(file).size();
+ qint64 fileSize = QFileInfo(file).size();
+ if (fileSize <= 0) {
+ item->setIcon(0, KIcon("edit-delete"));
+ m_missingClips++;
+ }
+ else m_requestedSize += fileSize;
filesList << fileName;
}
}
// Archiving finished
progressBar->setValue(100);
if (processProjectFile()) {
- slotDisplayMessage("dialog-ok", i18n("Project was successfully archived."));
+ slotJobResult(true, i18n("Project was successfully archived."));
}
else {
- slotDisplayMessage("dialog-close", i18n("There was an error processing project file"));
+ slotJobResult(false, i18n("There was an error processing project file"));
}
} else processProjectFile();
}
else {
m_copyJob = NULL;
- slotDisplayMessage("dialog-close", i18n("There was an error while copying the files: %1", job->errorString()));
+ slotJobResult(false, i18n("There was an error while copying the files: %1", job->errorString()));
}
if (!compressed_archive->isChecked()) {
buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Archive"));
void ArchiveWidget::slotArchivingFinished(bool result)
{
if (result) {
- slotDisplayMessage("dialog-ok", i18n("Project was successfully archived."));
+ slotJobResult(true, i18n("Project was successfully archived."));
+ buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
}
else {
- slotDisplayMessage("dialog-close", i18n("There was an error processing project file"));
+ slotJobResult(false, i18n("There was an error processing project file"));
}
progressBar->setValue(100);
buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Archive"));
#include "docclipbase.h"
#include <kio/global.h>
+#include <KIO/CopyJob>
+#include <KTemporaryFile>
+#include <kdeversion.h>
+
#include <QLabel>
#include <QDialog>
#include <QList>
-#include <KIO/CopyJob>
-#include <KTemporaryFile>
+
class KJob;
class KArchive;
* @author Jean-Baptiste Mardelle
*/
+#if KDE_IS_VERSION(4,7,0)
+ class KMessageWidget;
+#endif
+
class ArchiveWidget : public QDialog, public Ui::ArchiveWidget_UI
{
Q_OBJECT
void slotGotProgress(KJob*);
void openArchiveForExtraction();
void slotDisplayMessage(const QString &icon, const QString &text);
+ void slotJobResult(bool success, const QString &text);
protected:
virtual void closeEvent ( QCloseEvent * e );
QString m_projectName;
QTimer *m_progressTimer;
KArchive *m_extractArchive;
+ int m_missingClips;
+
+#if KDE_IS_VERSION(4,7,0)
+ KMessageWidget *m_infoMessage;
+#endif
/** @brief Generate tree widget subitems from a string list of urls. */
void generateItems(QTreeWidgetItem *parentItem, QStringList items);
#ifdef __cplusplus
class IUnknown
{
- public:
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) = 0;
- virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;
- virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
+public:
+ virtual ~IUnknown() = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) = 0;
+ virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;
+ virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
};
#endif
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
+ if (strColor.length() == 10) {
+ // 0xRRGGBBAA
+ intval = strColor.toUInt(&ok, 16);
+ color.setRgb( ( intval >> 24 ) & 0xff, // r
+ ( intval >> 16 ) & 0xff, // g
+ ( intval >> 8 ) & 0xff, // b
+ ( intval ) & 0xff ); // a
+ } else {
+ // 0xRRGGBB, 0xRGB
+ color.setNamedColor(strColor.replace(0, 2, "#"));
+ }
+ } else {
+ if (strColor.length() == 9) {
+ // #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 {
+ // #RRGGBB, #RGB
+ color.setNamedColor(strColor);
+ }
}
return color;
kDebug() << "++++++++ INVALID CLIP: " << url.path();
continue;
}
+
+ producer.set("video_index", "-1");
if (KdenliveSettings::normaliseaudiothumbs()) {
Mlt::Filter m_convert(prof, "volume");
#include <KFileDialog>
ClipStabilize::ClipStabilize(KUrl::List urls, const QString ¶ms, Mlt::Filter* filter,QWidget * parent) :
- QDialog(parent), m_urls(urls), m_duration(0),m_profile(NULL),m_consumer(NULL),m_playlist(NULL),m_filter(filter),vbox(NULL)
+ QDialog(parent), m_profile(NULL),m_consumer(NULL),m_playlist(NULL),m_urls(urls),m_duration(0),m_filter(filter),vbox(NULL)
{
setFont(KGlobalSettings::toolBarFont());
setupUi(this);
QColor light_bg = scheme.shade(KColorScheme::LightShade);
QString stylesheet(QString("QProgressBar:horizontal {border: 1px solid %1;border-radius:0px;border-top-left-radius: 4px;border-bottom-left-radius: 4px;border-right: 0px;background:%4;padding: 0px;text-align:left center}\
- QProgressBar:horizontal#dragOnly {background: %1} QProgressBar:horizontal:hover#dragOnly {background: %3} QProgressBar:horizontal:hover {border: 1px solid %3;border-right: 0px;}\
- QProgressBar::chunk:horizontal {background: %1;} QProgressBar::chunk:horizontal:hover {background: %3;}\
- QProgressBar:horizontal[inTimeline=\"true\"] { border: 1px solid %2;border-right: 0px;background: %4;padding: 0px;text-align:left center } QProgressBar::chunk:horizontal[inTimeline=\"true\"] {background: %2;}\
- QAbstractSpinBox#dragBox {border: 1px solid %1;border-top-right-radius: 4px;border-bottom-right-radius: 4px;padding-right:0px;} QAbstractSpinBox::down-button#dragBox {width:0px;padding:0px;}\
- QAbstractSpinBox::up-button#dragBox {width:0px;padding:0px;} QAbstractSpinBox[inTimeline=\"true\"]#dragBox { border: 1px solid %2;} QAbstractSpinBox:hover#dragBox {border: 1px solid %3;} ")
- .arg(dark_bg.name()).arg(selected_bg.name()).arg(hover_bg.name()).arg(light_bg.name()));
- setStyleSheet(stylesheet);
+ QProgressBar:horizontal#dragOnly {background: %1} QProgressBar:horizontal:hover#dragOnly {background: %3} QProgressBar:horizontal:hover {border: 1px solid %3;border-right: 0px;}\
+ QProgressBar::chunk:horizontal {background: %1;} QProgressBar::chunk:horizontal:hover {background: %3;}\
+ QProgressBar:horizontal[inTimeline=\"true\"] { border: 1px solid %2;border-right: 0px;background: %4;padding: 0px;text-align:left center } QProgressBar::chunk:horizontal[inTimeline=\"true\"] {background: %2;}\
+ QAbstractSpinBox#dragBox {border: 1px solid %1;border-top-right-radius: 4px;border-bottom-right-radius: 4px;padding-right:0px;} QAbstractSpinBox::down-button#dragBox {width:0px;padding:0px;}\
+ QAbstractSpinBox::up-button#dragBox {width:0px;padding:0px;} QAbstractSpinBox[inTimeline=\"true\"]#dragBox { border: 1px solid %2;} QAbstractSpinBox:hover#dragBox {border: 1px solid %3;} ")
+ .arg(dark_bg.name()).arg(selected_bg.name()).arg(hover_bg.name()).arg(light_bg.name()));
+ setStyleSheet(stylesheet);
if (m_urls.count() == 1) {
QString fileName = m_urls.at(0).path(); //.section('.', 0, -1);
} else transcode_info->setHidden(true);*/
}
- if (filtername=="videostab"){
- QStringList ls;
- ls << "shutterangle,type,int,value,0,min,0,max,100,tooltip,Angle that Images could be maximum rotated";
- fillParameters(ls);
- }else if (filtername=="videostab2"){
- QStringList ls;
- ls << "accuracy,type,int,value,4,min,1,max,10,tooltip,Accuracy of Shakiness detection";
- ls << "shakiness,type,int,value,4,min,1,max,10,tooltip,How shaky is the Video";
- ls << "stepsize,type,int,value,6,min,0,max,100,tooltip,Stepsize of Detection process minimum around";
- ls << "algo,type,bool,value,1,min,0,max,1,tooltip,0 = Bruteforce 1 = small measurement fields";
- ls << "mincontrast,type,double,value,0.3,min,0,max,1,factor,1,decimals,2,tooltip,Below this Contrast Field is discarded";
- ls << "show,type,int,value,0,min,0,max,2,tooltip,0 = draw nothing. 1 or 2 show fields and transforms";
- ls << "smoothing,type,int,value,10,min,0,max,100,tooltip,number of frames for lowpass filtering";
- ls << "maxshift,type,int,value,-1,min,-1,max,1000,tooltip,max number of pixels to shift";
- ls << "maxangle,type,int,value,-1,min,-1,max,1000,tooltip,max anglen to rotate (in rad)";
- ls << "crop,type,bool,value,0,min,0,max,1,tooltip,0 = keep border 1 = black background";
- ls << "invert,type,bool,value,0,min,0,max,1,tooltip,invert transform";
- ls << "realtive,type,bool,value,1,min,0,max,1,tooltip,0 = absolute transform 1= relative";
- ls << "zoom,type,int,value,0,min,-500,max,500,tooltip,additional zoom during transform";
- ls << "optzoom,type,bool,value,1,min,0,max,1,tooltip,use optimal zoom (calulated from transforms)";
- ls << "sharpen,type,double,value,0.8,min,0,max,1,decimals,1,tooltip,sharpen transformed image";
- fillParameters(ls);
-
- }
+ if (filtername=="videostab"){
+ QStringList ls;
+ ls << "shutterangle,type,int,value,0,min,0,max,100,tooltip,Angle that Images could be maximum rotated";
+ fillParameters(ls);
+ }else if (filtername=="videostab2"){
+ QStringList ls;
+ ls << "accuracy,type,int,value,4,min,1,max,10,tooltip,Accuracy of Shakiness detection";
+ ls << "shakiness,type,int,value,4,min,1,max,10,tooltip,How shaky is the Video";
+ ls << "stepsize,type,int,value,6,min,0,max,100,tooltip,Stepsize of Detection process minimum around";
+ ls << "algo,type,bool,value,1,min,0,max,1,tooltip,0 = Bruteforce 1 = small measurement fields";
+ ls << "mincontrast,type,double,value,0.3,min,0,max,1,factor,1,decimals,2,tooltip,Below this Contrast Field is discarded";
+ ls << "show,type,int,value,0,min,0,max,2,tooltip,0 = draw nothing. 1 or 2 show fields and transforms";
+ ls << "smoothing,type,int,value,10,min,0,max,100,tooltip,number of frames for lowpass filtering";
+ ls << "maxshift,type,int,value,-1,min,-1,max,1000,tooltip,max number of pixels to shift";
+ ls << "maxangle,type,int,value,-1,min,-1,max,1000,tooltip,max anglen to rotate (in rad)";
+ ls << "crop,type,bool,value,0,min,0,max,1,tooltip,0 = keep border 1 = black background";
+ ls << "invert,type,bool,value,0,min,0,max,1,tooltip,invert transform";
+ ls << "realtive,type,bool,value,1,min,0,max,1,tooltip,0 = absolute transform 1= relative";
+ ls << "zoom,type,int,value,0,min,-500,max,500,tooltip,additional zoom during transform";
+ ls << "optzoom,type,bool,value,1,min,0,max,1,tooltip,use optimal zoom (calulated from transforms)";
+ ls << "sharpen,type,double,value,0.8,min,0,max,1,decimals,1,tooltip,sharpen transformed image";
+ fillParameters(ls);
+
+ }
connect(button_start, SIGNAL(clicked()), this, SLOT(slotStartStabilize()));
- connect(buttonBox,SIGNAL(rejected()), this, SLOT(slotAbortStabilize()));
-
- m_timer=new QTimer(this);
- connect(m_timer, SIGNAL(timeout()), this, SLOT(slotShowStabilizeInfo()));
-
- vbox=new QVBoxLayout(optionsbox);
- QHashIterator<QString,QHash<QString,QString> > hi(m_ui_params);
- while(hi.hasNext()){
- hi.next();
- QHash<QString,QString> val=hi.value();
- if (val["type"]=="int" || val["type"]=="double"){
- DoubleParameterWidget *dbl=new DoubleParameterWidget(hi.key(), val["value"].toDouble(),
- val["min"].toDouble(),val["max"].toDouble(),val["value"].toDouble(),
- "",0/*id*/,""/*suffix*/,val["decimals"]!=""?val["decimals"].toInt():0,this);
- dbl->setObjectName(hi.key());
- dbl->setToolTip(val["tooltip"]);
- connect(dbl,SIGNAL(valueChanged(double)),this,SLOT(slotUpdateParams()));
- vbox->addWidget(dbl);
- }else if (val["type"]=="bool"){
- QCheckBox *ch=new QCheckBox(hi.key(),this);
- ch->setCheckState(val["value"] == "0" ? Qt::Unchecked : Qt::Checked);
- ch->setObjectName(hi.key());
- connect(ch, SIGNAL(stateChanged(int)) , this,SLOT(slotUpdateParams()));
- ch->setToolTip(val["tooltip"]);
- vbox->addWidget(ch);
-
- }
- }
+ connect(buttonBox,SIGNAL(rejected()), this, SLOT(slotAbortStabilize()));
+
+ m_timer=new QTimer(this);
+ connect(m_timer, SIGNAL(timeout()), this, SLOT(slotShowStabilizeInfo()));
+
+ vbox=new QVBoxLayout(optionsbox);
+ QHashIterator<QString,QHash<QString,QString> > hi(m_ui_params);
+ while(hi.hasNext()){
+ hi.next();
+ QHash<QString,QString> val=hi.value();
+ if (val["type"]=="int" || val["type"]=="double"){
+ DoubleParameterWidget *dbl=new DoubleParameterWidget(hi.key(), val["value"].toDouble(),
+ val["min"].toDouble(),val["max"].toDouble(),val["value"].toDouble(),
+ "",0/*id*/,""/*suffix*/,val["decimals"]!=""?val["decimals"].toInt():0,this);
+ dbl->setObjectName(hi.key());
+ dbl->setToolTip(val["tooltip"]);
+ connect(dbl,SIGNAL(valueChanged(double)),this,SLOT(slotUpdateParams()));
+ vbox->addWidget(dbl);
+ }else if (val["type"]=="bool"){
+ QCheckBox *ch=new QCheckBox(hi.key(),this);
+ ch->setCheckState(val["value"] == "0" ? Qt::Unchecked : Qt::Checked);
+ ch->setObjectName(hi.key());
+ connect(ch, SIGNAL(stateChanged(int)) , this,SLOT(slotUpdateParams()));
+ ch->setToolTip(val["tooltip"]);
+ vbox->addWidget(ch);
+
+ }
+ }
adjustSize();
}
/*if (m_stabilizeProcess.state() != QProcess::NotRunning) {
m_stabilizeProcess.close();
}*/
- if (m_stabilizeRun.isRunning()){
- if (m_consumer){
- m_consumer->stop();
- }
- m_stabilizeRun.waitForFinished();
- }
- if (m_profile) free (m_profile);
- if (m_consumer) free (m_consumer);
- if (m_playlist) free (m_playlist);
+ if (m_stabilizeRun.isRunning()){
+ if (m_consumer){
+ m_consumer->stop();
+ }
+ m_stabilizeRun.waitForFinished();
+ }
+ if (m_profile) free (m_profile);
+ if (m_consumer) free (m_consumer);
+ if (m_playlist) free (m_playlist);
}
void ClipStabilize::slotStartStabilize()
QString s_url = source_url->url().path();
if (QFile::exists(destination)) {
- if (KMessageBox::questionYesNo(this, i18n("File %1 already exists.\nDo you want to overwrite it?", destination )) == KMessageBox::No) return;
+ if (KMessageBox::questionYesNo(this, i18n("File %1 already exists.\nDo you want to overwrite it?", destination )) == KMessageBox::No) return;
}
buttonBox->button(QDialogButtonBox::Abort)->setText(i18n("Abort"));
- if (m_profile){
- m_playlist= new Mlt::Playlist;
- Mlt::Filter filter(*m_profile,filtername.toUtf8().data());
- QHashIterator <QString,QHash<QString,QString> > it(m_ui_params);
- while (it.hasNext()){
- it.next();
- filter.set(
- it.key().toAscii().data(),
- QString::number(it.value()["value"].toDouble()).toAscii().data());
- }
- Mlt::Producer p(*m_profile,s_url.toUtf8().data());
- if (p.is_valid()) {
- m_playlist->append(p);
- m_playlist->attach(filter);
- m_consumer= new Mlt::Consumer(*m_profile,"xml",destination.toUtf8().data());
- m_consumer->set("all","1");
- m_consumer->set("real_time","-2");
- m_consumer->connect(*m_playlist);
- m_stabilizeRun = QtConcurrent::run(this, &ClipStabilize::slotRunStabilize);
- m_timer->start(500);
- button_start->setEnabled(false);
- }
- }
+ if (m_profile){
+ m_playlist= new Mlt::Playlist;
+ Mlt::Filter filter(*m_profile,filtername.toUtf8().data());
+ QHashIterator <QString,QHash<QString,QString> > it(m_ui_params);
+ while (it.hasNext()){
+ it.next();
+ filter.set(
+ it.key().toAscii().data(),
+ QString::number(it.value()["value"].toDouble()).toAscii().data());
+ }
+ Mlt::Producer p(*m_profile,s_url.toUtf8().data());
+ if (p.is_valid()) {
+ m_playlist->append(p);
+ m_playlist->attach(filter);
+ m_consumer= new Mlt::Consumer(*m_profile,"xml",destination.toUtf8().data());
+ m_consumer->set("all",1);
+ m_consumer->set("real_time",-2);
+ m_consumer->connect(*m_playlist);
+ m_stabilizeRun = QtConcurrent::run(this, &ClipStabilize::slotRunStabilize);
+ m_timer->start(500);
+ button_start->setEnabled(false);
+ }
+ }
}
void ClipStabilize::slotRunStabilize()
{
- if (m_consumer)
- {
- m_consumer->run();
- }
+ if (m_consumer)
+ {
+ m_consumer->run();
+ }
}
void ClipStabilize::slotAbortStabilize()
{
- if (m_consumer)
- {
- m_timer->stop();
- m_consumer->stop();
- slotStabilizeFinished(false);
- }
+ if (m_consumer)
+ {
+ m_timer->stop();
+ m_consumer->stop();
+ slotStabilizeFinished(false);
+ }
}
void ClipStabilize::slotShowStabilizeInfo()
{
- if (m_playlist){
+ if (m_playlist){
job_progress->setValue((int) (100.0 * m_consumer->position()/m_playlist->get_out() ));
- if (m_consumer->position()==m_playlist->get_out()){
- m_timer->stop();
- slotStabilizeFinished(true);
- }
- }
+ if (m_consumer->position()==m_playlist->get_out()){
+ m_timer->stop();
+ slotStabilizeFinished(true);
+ }
+ }
}
void ClipStabilize::slotStabilizeFinished(bool success)
if (auto_add->isChecked()) {
KUrl url;
if (urls_list->count() > 0) {
- url = KUrl(dest_url->url().path(KUrl::AddTrailingSlash) + source_url->url().fileName()+".mlt");
+ url = KUrl(dest_url->url().path(KUrl::AddTrailingSlash) + source_url->url().fileName()+".mlt");
} else url = dest_url->url();
emit addClip(url);
}
} else {
log_text->setHtml(log_text->toPlainText() + "<br /><b>" + i18n("Stabilizing FAILED!"));
}
- if (m_playlist){
- free(m_playlist);
- m_playlist=NULL;
- }
- if (m_consumer){
- free(m_consumer);
- m_consumer=NULL;
- }
+ if (m_playlist){
+ free(m_playlist);
+ m_playlist=NULL;
+ }
+ if (m_consumer){
+ free(m_consumer);
+ m_consumer=NULL;
+ }
}
void ClipStabilize::slotUpdateParams()
{
- for (int i=0;i<vbox->count();i++){
- QWidget* w=vbox->itemAt(i)->widget();
- QString name=w->objectName();
- if (name !="" && m_ui_params.contains(name)){
- if (m_ui_params[name]["type"]=="int" || m_ui_params[name]["type"]=="double"){
- DoubleParameterWidget *dbl=(DoubleParameterWidget*)w;
- m_ui_params[name]["value"]=QString::number((double)(dbl->getValue()));
- }else if (m_ui_params[name]["type"]=="bool"){
- QCheckBox *ch=(QCheckBox*)w;
- m_ui_params[name]["value"]= ch->checkState() == Qt::Checked ? "1" : "0" ;
- }
- }
- }
+ for (int i=0;i<vbox->count();i++){
+ QWidget* w=vbox->itemAt(i)->widget();
+ QString name=w->objectName();
+ if (name !="" && m_ui_params.contains(name)){
+ if (m_ui_params[name]["type"]=="int" || m_ui_params[name]["type"]=="double"){
+ DoubleParameterWidget *dbl=(DoubleParameterWidget*)w;
+ m_ui_params[name]["value"]=QString::number((double)(dbl->getValue()));
+ }else if (m_ui_params[name]["type"]=="bool"){
+ QCheckBox *ch=(QCheckBox*)w;
+ m_ui_params[name]["value"]= ch->checkState() == Qt::Checked ? "1" : "0" ;
+ }
+ }
+ }
}
bool ClipStabilize::autoAddClip() const
void ClipStabilize::fillParameters(QStringList lst)
{
- m_ui_params.clear();
- while (!lst.isEmpty()){
- QString vallist=lst.takeFirst();
- QStringList cont=vallist.split(",");
- QString name=cont.takeFirst();
- while (!cont.isEmpty()){
- QString valname=cont.takeFirst();
- QString val;
- if (!cont.isEmpty()){
- val=cont.takeFirst();
- }
- m_ui_params[name][valname]=val;
- }
- }
+ m_ui_params.clear();
+ while (!lst.isEmpty()){
+ QString vallist=lst.takeFirst();
+ QStringList cont=vallist.split(",");
+ QString name=cont.takeFirst();
+ while (!cont.isEmpty()){
+ QString valname=cont.takeFirst();
+ QString val;
+ if (!cont.isEmpty()){
+ val=cont.takeFirst();
+ }
+ m_ui_params[name][valname]=val;
+ }
+ }
}
{
if (m_activeRender) {
if (m_activeRender == m_manager->activeRenderer()) return;
- bool b = m_activeRender->disconnect(this);
+ bool b = true;
+ b &= m_activeRender->disconnect(this);
Q_ASSERT(b);
}
m_activeRender = m_manager->activeRenderer();
viewport()->update();
}
+void CustomTrackView::slotSelectClipsInTrack()
+{
+ QRectF rect(0, m_selectedTrack * m_tracksHeight + m_tracksHeight / 2, sceneRect().width(), m_tracksHeight / 2 - 1);
+ QList<QGraphicsItem *> selection = m_scene->items(rect);
+ m_scene->clearSelection();
+ for (int i = 0; i < selection.count(); i++) {
+ if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET || selection.at(i)->type() == GROUPWIDGET) {
+ selection.at(i)->setSelected(true);
+ }
+ }
+ resetSelectionGroup();
+ groupSelectedItems();
+}
+
+void CustomTrackView::slotSelectAllClips()
+{
+ QList<QGraphicsItem *> selection = m_scene->items();
+ m_scene->clearSelection();
+ for (int i = 0; i < selection.count(); i++) {
+ if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET || selection.at(i)->type() == GROUPWIDGET) {
+ selection.at(i)->setSelected(true);
+ }
+ }
+ resetSelectionGroup();
+ groupSelectedItems();
+}
+
void CustomTrackView::selectClip(bool add, bool group, int track, int pos)
{
QRectF rect;
* @param effect The new effect xml
* @param ix The track index */
void slotAddTrackEffect(const QDomElement &effect, int ix);
+ /** @brief Select all clips in selected track. */
+ void slotSelectClipsInTrack();
+ /** @brief Select all clips in timeline. */
+ void slotSelectAllClips();
/** @brief Update the list of snap points (sticky timeline hotspots).
* @param selected The currently selected clip if any
/** @brief A Filter job producer results. */
void slotGotFilterJobResults(const QString &id, int startPos, int track, const QString &filter, stringMap filterParams);
+
signals:
void cursorMoved(int, int);
void zoomIn();
QString clipType;
QString realPath = e.attribute("resource");
QString id = e.attribute("id");
+ // Tell Kdenlive to recreate proxy
+ e.setAttribute("_replaceproxy", "1");
// Replace proxy url with real clip in MLT producers
QDomNodeList properties;
QDomElement mltProd;
sortByColumn(0, Qt::AscendingOrder);
// populate effects menu
+ QMenu *sub1 = NULL;
+ QMenu *sub2 = NULL;
+ QMenu *sub3 = NULL;
+ QMenu *sub4 = NULL;
for (int i = 0; i < topLevelItemCount(); i++) {
if (!topLevelItem(i)->childCount())
continue;
QMenu *sub = new QMenu(topLevelItem(i)->text(0), effectsMenu);
effectsMenu->addMenu(sub);
- for (int j = 0; j < topLevelItem(i)->childCount(); j++) {
+ int effectsInCategory = topLevelItem(i)->childCount();
+ bool hasSubCategories = false;
+ if (effectsInCategory > 60) {
+ // create subcategories if there are too many effects
+ hasSubCategories = true;
+ sub1 = new QMenu(i18nc("menu name for effects names between these 2 letters", "0 - F"), sub);
+ sub->addMenu(sub1);
+ sub2 = new QMenu(i18nc("menu name for effects names between these 2 letters", "G - L"), sub);
+ sub->addMenu(sub2);
+ sub3 = new QMenu(i18nc("menu name for effects names between these 2 letters", "M - R"), sub);
+ sub->addMenu(sub3);
+ sub4 = new QMenu(i18nc("menu name for effects names between these 2 letters", "S - Z"), sub);
+ sub->addMenu(sub4);
+ }
+ for (int j = 0; j < effectsInCategory; j++) {
QTreeWidgetItem *item = topLevelItem(i)->child(j);
KAction *a = new KAction(KIcon(item->icon(0)), item->text(0), sub);
QStringList data = item->data(0, IdRole).toStringList();
if (id.isEmpty()) id = data.at(0);
a->setData(data);
a->setIconVisibleInMenu(false);
- sub->addAction(a);
+ if (hasSubCategories) {
+ // put action in sub category
+ QRegExp rx("^[s-z].+");
+ if (rx.exactMatch(item->text(0).toLower())) {
+ sub4->addAction(a);
+ } else {
+ rx.setPattern("^[m-r].+");
+ if (rx.exactMatch(item->text(0).toLower())) {
+ sub3->addAction(a);
+ }
+ else {
+ rx.setPattern("^[g-l].+");
+ if (rx.exactMatch(item->text(0).toLower())) {
+ sub2->addAction(a);
+ }
+ else sub1->addAction(a);
+ }
+ }
+ }
+ else sub->addAction(a);
effectActions->addAction("video_effect_" + id, a);
}
}
void EffectStackView::slotItemChanged(QListWidgetItem *item)
{
- bool disable = true;
- if (item->checkState() == Qt::Checked) disable = false;
- m_ui.buttonReset->setEnabled(!disable || !KdenliveSettings::disable_effect_parameters());
+ bool disable = item->checkState() == Qt::Unchecked;
+ int row = m_ui.effectlist->row(item);
int activeRow = m_ui.effectlist->currentRow();
- if (activeRow >= 0) {
+
+ if (row == activeRow) {
+ m_ui.buttonReset->setEnabled(!disable || !KdenliveSettings::disable_effect_parameters());
m_effectedit->updateParameter("disable", QString::number((int) disable));
- if (m_trackMode)
- emit changeEffectState(NULL, m_trackindex, activeRow, disable);
- else
- emit changeEffectState(m_clipref, -1, activeRow, disable);
}
+
+ if (m_trackMode)
+ emit changeEffectState(NULL, m_trackindex, row, disable);
+ else
+ emit changeEffectState(m_clipref, -1, row, disable);
+
slotUpdateCheckAllButton();
}
#include <QTimer>
#include <QDomDocument>
-HeaderTrack::HeaderTrack(int index, TrackInfo info, int height, QWidget *parent) :
+HeaderTrack::HeaderTrack(int index, TrackInfo info, int height, QList <QAction *> actions, QWidget *parent) :
QWidget(parent),
m_index(index),
m_type(info.type),
//horizontalSpacer;
}
- setContextMenuPolicy(Qt::DefaultContextMenu); //Qt::ActionsContextMenu);
- QAction *insertAction = new QAction(i18n("Insert Track"), this);
- m_menu.addAction(insertAction);
- connect(insertAction, SIGNAL(triggered()), this, SLOT(slotAddTrack()));
-
- QAction *removeAction = new QAction(KIcon("edit-delete"), i18n("Delete Track"), this);
- m_menu.addAction(removeAction);
- connect(removeAction, SIGNAL(triggered()), this, SLOT(slotDeleteTrack()));
-
- QAction *configAction = new QAction(KIcon("configure"), i18n("Configure Track"), this);
- m_menu.addAction(configAction);
- connect(configAction, SIGNAL(triggered()), this, SLOT(slotConfigTrack()));
+ setContextMenuPolicy(Qt::ActionsContextMenu);
+ addActions(actions);
}
/*HeaderTrack::~HeaderTrack()
QWidget::mousePressEvent(event);
}
-// virtual
-void HeaderTrack::contextMenuEvent(QContextMenuEvent * event)
-{
- if (track_number->hasFocus()) {
- track_number->clearFocus();
- return;
- }
- m_menu.popup(event->globalPos());
-}
-
void HeaderTrack::mouseDoubleClickEvent(QMouseEvent* event)
{
if (track_number->hasFocus()) {
track_number->clearFocus();
return;
}
- slotConfigTrack();
+ emit configTrack(m_index);
QWidget::mouseDoubleClickEvent(event);
}
QTimer::singleShot(500, this, SLOT(deleteTrack()));
}
-void HeaderTrack::deleteTrack()
-{
- emit deleteTrack(m_index);
-}
-
-void HeaderTrack::slotAddTrack()
-{
- emit insertTrack(m_index);
-}
-
void HeaderTrack::slotRenameTrack()
{
if (m_name != track_number->text()) emit renameTrack(m_index, track_number->text());
}
-void HeaderTrack::slotConfigTrack()
-{
- emit configTrack(m_index);
-}
#include "headertrack.moc"
Q_OBJECT
public:
- HeaderTrack(int index, TrackInfo info, int height, QWidget *parent = 0);
+ HeaderTrack(int index, TrackInfo info, int height, QList <QAction *> actions, QWidget *parent = 0);
//virtual ~HeaderTrack();
void setLock(bool lock);
void adjustSize(int height);
protected:
virtual void mousePressEvent(QMouseEvent * event);
virtual void mouseDoubleClickEvent(QMouseEvent * event);
- virtual void contextMenuEvent(QContextMenuEvent * event);
virtual void dropEvent(QDropEvent * event);
virtual void dragEnterEvent(QDragEnterEvent *event);
int m_index;
TRACKTYPE m_type;
bool m_isSelected;
- QMenu m_menu;
QString m_name;
private slots:
void switchAudio();
void switchVideo();
void slotDeleteTrack();
- void deleteTrack();
- void slotAddTrack();
void slotRenameTrack();
- void slotConfigTrack();
void switchLock(bool emitSignal = true);
signals:
void switchTrackAudio(int);
void switchTrackVideo(int);
void switchTrackLock(int);
- void insertTrack(int);
- void deleteTrack(int);
void renameTrack(int, QString);
void selectTrack(int);
void configTrack(int);
# KDE Config File
[Desktop Entry]
Name=Kdenlive
+Name[ca]=Kdenlive
Name[cs]=Kdenlive
Name[da]=Kdenlive
Name[de]=Kdenlive
Name[el]=Kdenlive
+Name[es]=Kdenlive
+Name[gl]=Kdenlive
+Name[nb]=Kdenlive
Name[nds]=Kdenlive
Name[nl]=Kdenlive
+Name[pl]=Kdenlive
Name[pt]=Kdenlive
Name[pt_BR]=Kdenlive
Name[sv]=Kdenlive
Name[zh_CN]=Kdenlive
Name[zh_TW]=Kdenlive
GenericName=Video Editor
+GenericName[ca]=Editor de vídeo
GenericName[cs]=Editor videí
GenericName[da]=Videoredigering
GenericName[de]=Video-Editor
GenericName[el]=Επεξεργαστής βίντεο
+GenericName[es]=Editor de video
+GenericName[gl]=Editor de vídeo
+GenericName[nb]=Videoredigeringsprogram
GenericName[nl]=Video-bewerker
+GenericName[pl]=Edytor wideo
GenericName[pt]=Editor de Vídeo
GenericName[pt_BR]=Editor de Vídeo
GenericName[sv]=Videoeditor
GenericName[zh_CN]=视频编辑器
GenericName[zh_TW]=影像編輯器
Comment=Nonlinear video editor for KDE
+Comment[ca]=Editor de vídeo no lineal per al KDE
Comment[da]=Ikke-lineær videoredigering til KDE
Comment[de]=Nichtlinearer Video-Editor für KDE
Comment[el]=Μη γραμμικός επεξεργαστής βίντεο για το KDE
+Comment[es]=Editor no lineal de video para KDE
+Comment[gl]=Editor de vídeo non linear para KDE
+Comment[nb]=Videoredigeringsprogram for KDE med dataklipping
Comment[nl]=Niet-lineaire video-bewerker voor KDE
+Comment[pl]=Nieliniowy edytor wideo dla KDE
Comment[pt]=Editor de vídeo não-linear para o KDE
Comment[pt_BR]=Editor de vídeo não-linear para o KDE
Comment[sv]=Icke-linjär videoeditor för KDE
[Global]
IconName=kdenlive
Comment=Kdenlive
+Comment[ca]=Kdenlive
Comment[cs]=Kdenlive
Comment[da]=Kdenlive
Comment[de]=Kdenlive
Comment[el]=Kdenlive
+Comment[es]=Kdenlive
+Comment[gl]=Kdenlive
+Comment[nb]=Kdenlive
Comment[nds]=Kdenlive
Comment[nl]=Kdenlive
+Comment[pl]=Kdenlive
Comment[pt]=Kdenlive
Comment[pt_BR]=Kdenlive
Comment[sv]=Kdenlive
[Event/RenderFinished]
Name=Rendering finished
+Name[ca]=Ha acabat la renderització
Name[cs]=Renderování bylo dokončeno
Name[da]=Rendering gennemført
Name[el]=Η αποτύπωση ολοκληρώθηκε
+Name[es]=Procesamiento finalizado
+Name[gl]=Renderizado finalizado
+Name[nb]=Opptegning avsluttet
Name[nl]=Weergave uitwerken beëindigd
+Name[pl]=Ukończono renderowanie
Name[pt]=A geração terminou
Name[pt_BR]=A renderização terminou
Name[sv]=Återgivning klar
Name[zh_CN]=渲染结束
Name[zh_TW]=已完成導出
Comment=Rendering is over
+Comment[ca]=La renderització ja ha acabat
Comment[cs]=Renderování je hotové
Comment[da]=Renderingen er slut
Comment[el]=Η αποτύπωση τελείωσε
+Comment[es]=El procesamiento ha finalizado
+Comment[gl]=Rematou o renderizado
+Comment[nb]=Ferdig med opptegning
Comment[nl]=Weergave uitwerken is gereed
+Comment[pl]=Ukończono zostało zakończone
Comment[pt]=A geração terminou
Comment[pt_BR]=A renderização foi terminada
Comment[sv]=Återgivningen är gjord
[Event/RenderStarted]
Name=Rendering started
+Name[ca]=Ha començat la renderització
Name[cs]=Renderování začalo
Name[da]=Rendering påbegyndt
Name[el]=Η αποτύπωση ξεκίνησε
+Name[es]=Procesamiento inciado
+Name[gl]=Iniciado o renderizado
+Name[nb]=Opptegning påbegynt
Name[nl]=Weergave uitwerken begonnen
+Name[pl]=Rozpoczęto renderowanie
Name[pt]=A geração foi iniciada
Name[pt_BR]=A renderização iniciou
Name[sv]=Återgivning startad
Name[zh_CN]=渲染开始
Name[zh_TW]=導出已開始
Comment=Rendering was started
+Comment[ca]=La renderització ja ha començat
Comment[cs]=Renderování bylo začato
Comment[da]=Renderingen blev startet
Comment[el]=Η αποτύπωση ξεκίνησε
+Comment[es]=El procesamiento ha sido iniciado
+Comment[gl]=Vaise iniciar o renderizado
+Comment[nb]=Startet opptegning
Comment[nl]=Weergave uitwerken is begonnen
+Comment[pl]=Renderowanie zostało rozpoczęte
Comment[pt]=A geração foi iniciada
Comment[pt_BR]=A renderização foi iniciada
Comment[sv]=Återgivningen har startats
[Event/FrameCaptured]
Name=Frame captured
+Name[ca]=S'ha capturat un fotograma
Name[da]=Billed indfanget
Name[el]=Σύλληψη πλαισίου
+Name[es]=Fotograma capturado
+Name[gl]=Fotograma capturado
+Name[nb]=Stillbilde tatt
Name[nl]=Frame opgenomen
+Name[pl]=Przechwycono klatkę
Name[pt]=Imagem capturada
Name[pt_BR]=Imagem capturada
Name[sv]=Ram lagrad
Name[zh_CN]=已抓取帧
Name[zh_TW]=影格已擷取
Comment=A frame was captured to disk
+Comment[ca]=S'ha capturat i desat un fotograma al disc
Comment[da]=Et billed blev indfanget til disken
Comment[el]=Έγινε σύλληψη πλαισίου στο δίσκο
+Comment[es]=Un fotograma fue capturado al disco
+Comment[gl]=Capturouse un fotograma para o disco
+Comment[nb]=Et stillbilde ble lagret
Comment[nl]=Een frame is op schijf opgenomen
+Comment[pl]=Klatka została przechwycona na dysk
Comment[pt]=Foi capturada uma imagem para o disco
Comment[pt_BR]=Foi capturada uma imagem para o disco
Comment[sv]=En ram har lagrats på disk
[Event/ReadyToCapture]
Name=Ready to capture
+Name[ca]=A punt per capturar
Name[da]=Klar til at indfange
Name[el]=Έτοιμο για σύλληψη
+Name[es]=Listo para capturar
+Name[gl]=Listo para a captura
+Name[nb]=Klar til å ta stillbilde
Name[nl]=Gereed om op te nemen
+Name[pl]=Gotowy do przechwycenia
Name[pt]=Pronto para capturar
Name[pt_BR]=Pronto para capturar
Name[sv]=Klar att lagra
[Event/ErrorMessage]
Name=Error
+Name[ca]=Error
Name[cs]=Chyba
Name[da]=Fejl
Name[de]=Fehler
Name[el]=Σφάλμα
+Name[es]=Error
+Name[gl]=Erro
+Name[nb]=Feil
Name[nds]=Fehler
Name[nl]=Fout
+Name[pl]=Błąd
Name[pt]=Erro
Name[pt_BR]=Erro
Name[sv]=Fel
Name[zh_CN]=错误
Name[zh_TW]=錯誤
Comment=An error occurred in Kdenlive
+Comment[ca]=S'ha produït un error al Kdenlive
Comment[da]=En fejl opstod i Kdenlive
-Comment[de]=Es ist ein Fehler in Kdenlive aufgetreten
+Comment[de]=In Kdenlive ist ein Fehler aufgetreten.
Comment[el]=Εμφανίστηκε σφάλμα στο Kdenlive
+Comment[es]=Ha ocurrido un error en Kdenlive
+Comment[gl]=Aconteceu un erro en Kdenlive
+Comment[nb]=En feil oppsto i Kdenlive
Comment[nl]=Er is een fout opgetreden in Kdenlive
+Comment[pl]=Wystąpił błąd w Kdenlive
Comment[pt]=Ocorreu um erro no Kdenlive
Comment[pt_BR]=Ocorreu um erro no Kdenlive
Comment[sv]=Ett fel uppstod i Kdenlive
*
* If the clip wasn't added before, it tries to add it to the project. */
bool addClipInfo(QDomElement elem, QDomElement orig, QString clipId);
- void slotAddClipFile(const KUrl &url, const QString &group, const QString &groupId = QString(), const QString &comment = QString());
- void slotAddClipList(const KUrl::List urls, const QString &group, const QString &groupId = QString());
+ void slotAddClipFile(const KUrl &url, const QString &group = QString(), const QString &groupId = QString(), const QString &comment = QString());
+ void slotAddClipList(const KUrl::List urls, const QString &group = QString(), const QString &groupId = QString());
void deleteClip(const QString &clipId);
int getFramePos(QString duration);
DocClipBase *getBaseClip(const QString &clipId);
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<gui name="kdenlive" version="68">
+<gui name="kdenlive" version="69">
<ToolBar name="extraToolBar" >
<text>Extra Toolbar</text>
<Action name="project_render" />
<Action name="insert_track" />
<Action name="delete_track" />
<Action name="config_tracks" />
+ <Separator />
+ <Action name="select_track" />
+ <Action name="select_all_tracks" />
</Menu>
<Separator />
<Action name="stopmotion" />
#include <QStylePainter>
#include <QApplication>
+const int margin = 5;
+const int cursorWidth = 6;
KeyframeHelper::KeyframeHelper(QWidget *parent) :
QWidget(parent),
m_position(0),
m_scale(0),
m_movingKeyframe(false),
- m_lineHeight(10),
+ m_lineHeight(9),
m_drag(false),
m_hoverKeyframe(-1)
{
void KeyframeHelper::mousePressEvent(QMouseEvent * event)
{
m_hoverKeyframe = -1;
- if (event->button() == Qt::LeftButton) m_drag = true;
- else {
+ if (event->button() != Qt::LeftButton) {
QWidget::mousePressEvent(event);
return;
}
+ int xPos = event->x() - margin;
if (m_geom != NULL && (event->y() < m_lineHeight)) {
// check if we want to move a keyframe
- int mousePos = qMax((int)(event->x() / m_scale), 0);
+ int mousePos = qMax((int)(xPos / m_scale), 0);
Mlt::GeometryItem item;
if (m_geom->next_key(&item, mousePos) == 0) {
- if (qAbs(item.frame() * m_scale - (int)(event->x())) < 4) {
+ if (qAbs(item.frame() * m_scale - xPos) < 4) {
+ m_drag = true;
m_movingItem.x(item.x());
m_movingItem.y(item.y());
m_movingItem.w(item.w());
}
}
}
- m_position = event->x() / m_scale;
- emit positionChanged(m_position);
- update();
+ if (event->y() >= m_lineHeight && event->y() < height()) {
+ m_drag = true;
+ m_position = xPos / m_scale;
+ emit positionChanged(m_position);
+ update();
+ }
+}
+
+void KeyframeHelper::leaveEvent( QEvent * event )
+{
+ Q_UNUSED(event);
+ if (m_hoverKeyframe != -1) {
+ m_hoverKeyframe = -1;
+ update();
+ }
}
// virtual
void KeyframeHelper::mouseMoveEvent(QMouseEvent * event)
{
+ int xPos = event->x() - margin;
if (!m_drag) {
+ int mousePos = qMax((int)(xPos / m_scale), 0);
+ if (qAbs(m_position * m_scale - xPos) < cursorWidth && event->y() >= m_lineHeight) {
+ // Mouse over time cursor
+ if (m_hoverKeyframe != -2) {
+ m_hoverKeyframe = -2;
+ update();
+ }
+ event->accept();
+ return;
+ }
if (m_geom != NULL && (event->y() < m_lineHeight)) {
// check if we want to move a keyframe
- int mousePos = qMax((int)(event->x() / m_scale), 0);
Mlt::GeometryItem item;
if (m_geom->next_key(&item, mousePos) == 0) {
- if (qAbs(item.frame() * m_scale - (int)(event->x())) < 4) {
+ if (qAbs(item.frame() * m_scale - xPos) < 4) {
if (m_hoverKeyframe == item.frame()) return;
m_hoverKeyframe = item.frame();
setCursor(Qt::PointingHandCursor);
}
if (m_movingKeyframe) {
if (!m_dragStart.isNull()) {
- if ((event->pos() - m_dragStart).manhattanLength() < QApplication::startDragDistance()) return;
+ if ((QPoint(xPos, event->y()) - m_dragStart).manhattanLength() < QApplication::startDragDistance()) return;
m_dragStart = QPoint();
m_geom->remove(m_movingItem.frame());
for (int i = 0; i < m_extraGeometries.count(); i++)
m_extraGeometries[i]->remove(m_movingItem.frame());
}
- int pos = qBound(0, (int)(event->x() / m_scale), frameLength);
+ int pos = qBound(0, (int)(xPos / m_scale), frameLength);
if (KdenliveSettings::snaptopoints() && qAbs(pos - m_position) < 5) pos = m_position;
m_movingItem.frame(pos);
for (int i = 0; i < m_extraMovingItems.count(); i++) {
update();
return;
}
- m_position = event->x() / m_scale;
+ m_position = xPos / m_scale;
m_position = qMax(0, m_position);
m_position = qMin(frameLength, m_position);
+ m_hoverKeyframe = -2;
emit positionChanged(m_position);
update();
}
{
if (m_geom != NULL && event->button() == Qt::LeftButton) {
// check if we want to move a keyframe
- int mousePos = qMax((int)(event->x() / m_scale - 5), 0);
+ int xPos = event->x() - margin;
+ int mousePos = qMax((int)(xPos / m_scale - 5), 0);
Mlt::GeometryItem item;
if (m_geom->next_key(&item, mousePos) == 0 && item.frame() - mousePos < 10) {
// There is already a keyframe close to mouse click
return;
}
// add new keyframe
- emit addKeyframe((int)(event->x() / m_scale));
+ emit addKeyframe((int)(xPos / m_scale));
}
}
void KeyframeHelper::mouseReleaseEvent(QMouseEvent * event)
{
m_drag = false;
- m_hoverKeyframe = -1;
setCursor(Qt::ArrowCursor);
+ m_hoverKeyframe = -1;
if (m_movingKeyframe) {
m_geom->insert(m_movingItem);
m_movingKeyframe = false;
QStylePainter p(this);
const QRectF clipRect = e->rect();
p.setClipRect(clipRect);
- m_scale = (double) width() / frameLength;
+ m_scale = (double) (width() - 2 * margin) / frameLength;
if (m_geom != NULL) {
int pos = 0;
p.setPen(m_keyframe);
if (pos == m_hoverKeyframe) {
p.setBrush(m_selected);
}
- int scaledPos = pos * m_scale;
+ int scaledPos = margin + pos * m_scale;
// draw keyframes
p.drawLine(scaledPos, 9, scaledPos, 15);
// draw pointer
if (m_movingKeyframe) {
p.setBrush(m_selected);
- int scaledPos = (int)(m_movingItem.frame() * m_scale);
+ int scaledPos = margin + (int)(m_movingItem.frame() * m_scale);
// draw keyframes
p.drawLine(scaledPos, 9, scaledPos, 15);
// draw pointer
}
}
p.setPen(palette().dark().color());
- p.drawLine(clipRect.x(), m_lineHeight, clipRect.right(), m_lineHeight);
+ p.drawLine(margin, m_lineHeight, width() - margin - 1, m_lineHeight);
+ p.drawLine(margin, m_lineHeight - 3, margin, m_lineHeight + 3);
+ p.drawLine(width() - margin - 1, m_lineHeight - 3, width() - margin - 1, m_lineHeight + 3);
// draw pointer
QPolygon pa(3);
- const int cursor = m_position * m_scale;
- pa.setPoints(3, cursor - 5, 16, cursor + 5, 16, cursor, 11);
- p.setBrush(palette().dark().color());
+ const int cursor = margin + m_position * m_scale;
+ pa.setPoints(3, cursor - cursorWidth, 16, cursor + cursorWidth, 16, cursor, 10);
+ if (m_hoverKeyframe == -2)
+ p.setBrush(palette().highlight());
+ else
+ p.setBrush(palette().dark().color());
p.drawPolygon(pa);
}
virtual void mouseMoveEvent(QMouseEvent * event);
virtual void mouseReleaseEvent(QMouseEvent * event);
virtual void mouseDoubleClickEvent(QMouseEvent * event);
+ virtual void leaveEvent( QEvent * event );
private:
Mlt::Geometry *m_geom;
/*ScriptingPart* sp = new ScriptingPart(this, QStringList());
guiFactory()->addClient(sp);*/
+ QMenu *trackMenu = (QMenu*)(factory()->container("track_menu", this));
+ if (trackMenu) trackMenu->addActions(m_tracksActionCollection->actions());
+
QMenu *saveLayout = (QMenu*)(factory()->container("layout_save_as", this));
if (saveLayout)
collection.addAction("delete_space", removeSpace);
connect(removeSpace, SIGNAL(triggered()), this, SLOT(slotRemoveSpace()));
- KAction *insertTrack = new KAction(KIcon(), i18n("Insert Track"), this);
- collection.addAction("insert_track", insertTrack);
+ m_tracksActionCollection = new KActionCollection(m_tracksActionCollection, KGlobal::mainComponent());
+ m_tracksActionCollection->addAssociatedWidget(m_timelineArea);
+
+ KAction *insertTrack = new KAction(KIcon(), i18n("Insert Track"), m_tracksActionCollection);
+ m_tracksActionCollection->addAction("insert_track", insertTrack);
connect(insertTrack, SIGNAL(triggered()), this, SLOT(slotInsertTrack()));
- KAction *deleteTrack = new KAction(KIcon(), i18n("Delete Track"), this);
- collection.addAction("delete_track", deleteTrack);
+ KAction *deleteTrack = new KAction(KIcon(), i18n("Delete Track"), m_tracksActionCollection);
+ m_tracksActionCollection->addAction("delete_track", deleteTrack);
connect(deleteTrack, SIGNAL(triggered()), this, SLOT(slotDeleteTrack()));
- KAction *configTracks = new KAction(KIcon("configure"), i18n("Configure Tracks"), this);
- collection.addAction("config_tracks", configTracks);
+ KAction *configTracks = new KAction(KIcon("configure"), i18n("Configure Tracks"), m_tracksActionCollection);
+ m_tracksActionCollection->addAction("config_tracks", configTracks);
connect(configTracks, SIGNAL(triggered()), this, SLOT(slotConfigTrack()));
+ KAction *selectTrack = new KAction(KIcon(), i18n("Select All in Current Track"), m_tracksActionCollection);
+ connect(selectTrack, SIGNAL(triggered()), this, SLOT(slotSelectTrack()));
+ m_tracksActionCollection->addAction("select_track", selectTrack);
+
+ QAction *selectAll = KStandardAction::selectAll(this, SLOT(slotSelectAllTracks()), m_tracksActionCollection);
+ selectAll->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ m_tracksActionCollection->addAction("select_all_tracks", selectAll);
+
KAction *addGuide = new KAction(KIcon("document-new"), i18n("Add Guide"), this);
collection.addAction("add_guide", addGuide);
connect(addGuide, SIGNAL(triggered()), this, SLOT(slotAddGuide()));
KdenliveDoc *doc = new KdenliveDoc(KUrl(), projectFolder, m_commandStack, profileName, documentProperties, documentMetadata, projectTracks, m_projectMonitor->render, m_notesWidget, &openBackup, this);
doc->m_autosave = new KAutoSaveFile(KUrl(), doc);
bool ok;
- TrackView *trackView = new TrackView(doc, &ok, this);
+ TrackView *trackView = new TrackView(doc, m_tracksActionCollection->actions(), &ok, this);
m_timelineArea->addTab(trackView, KIcon("kdenlive"), doc->description());
if (!ok) {
// MLT is broken
// Save timeline thumbnails
m_activeTimeline->projectView()->saveThumbnails();
m_activeDocument->setUrl(KUrl(outputFileName));
+ QByteArray hash = QCryptographicHash::hash(KUrl(outputFileName).encodedPath(), QCryptographicHash::Md5).toHex();
if (m_activeDocument->m_autosave == NULL) {
- m_activeDocument->m_autosave = new KAutoSaveFile(KUrl(outputFileName), this);
- } else m_activeDocument->m_autosave->setManagedFile(KUrl(outputFileName));
+ m_activeDocument->m_autosave = new KAutoSaveFile(KUrl(hash), this);
+ } else m_activeDocument->m_autosave->setManagedFile(KUrl(hash));
setCaption(m_activeDocument->description());
m_timelineArea->setTabText(m_timelineArea->currentIndex(), m_activeDocument->description());
m_timelineArea->setTabToolTip(m_timelineArea->currentIndex(), m_activeDocument->url().path());
if (!KdenliveSettings::activatetabs()) if (!closeCurrentDocument()) return;
// Check for backup file
- QList<KAutoSaveFile *> staleFiles = KAutoSaveFile::staleFiles(url);
+ QByteArray hash = QCryptographicHash::hash(url.encodedPath(), QCryptographicHash::Md5).toHex();
+ QList<KAutoSaveFile *> staleFiles = KAutoSaveFile::staleFiles(KUrl(hash));
if (!staleFiles.isEmpty()) {
if (KMessageBox::questionYesNo(this,
i18n("Auto-saved files exist. Do you want to recover them now?"),
i18n("File Recovery"),
KGuiItem(i18n("Recover")), KGuiItem(i18n("Don't recover"))) == KMessageBox::Yes) {
- recoverFiles(staleFiles);
+ recoverFiles(staleFiles, url);
return;
} else {
// remove the stale files
qApp->processEvents();
bool openBackup;
- KdenliveDoc *doc = new KdenliveDoc(url, KdenliveSettings::defaultprojectfolder(), m_commandStack, KdenliveSettings::default_profile(), QMap <QString, QString> (), QMap <QString, QString> (), QPoint(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()), m_projectMonitor->render, m_notesWidget, &openBackup, this, &progressDialog);
+ KdenliveDoc *doc = new KdenliveDoc(stale ? KUrl(stale->fileName()) : url, KdenliveSettings::defaultprojectfolder(), m_commandStack, KdenliveSettings::default_profile(), QMap <QString, QString> (), QMap <QString, QString> (), QPoint(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()), m_projectMonitor->render, m_notesWidget, &openBackup, this, &progressDialog);
progressDialog.progressBar()->setValue(1);
progressDialog.progressBar()->setMaximum(4);
qApp->processEvents();
if (stale == NULL) {
- stale = new KAutoSaveFile(url, doc);
+ QByteArray hash = QCryptographicHash::hash(url.encodedPath(), QCryptographicHash::Md5).toHex();
+ stale = new KAutoSaveFile(KUrl(hash), doc);
doc->m_autosave = stale;
} else {
doc->m_autosave = stale;
- doc->setUrl(stale->managedFile());
+ doc->setUrl(url);//stale->managedFile());
doc->setModified(true);
stale->setParent(doc);
}
qApp->processEvents();
bool ok;
- TrackView *trackView = new TrackView(doc, &ok, this);
+ TrackView *trackView = new TrackView(doc, m_tracksActionCollection->actions(), &ok, this);
connectDocument(trackView, doc);
progressDialog.progressBar()->setValue(3);
qApp->processEvents();
if (openBackup) slotOpenBackupDialog(url);
}
-void MainWindow::recoverFiles(QList<KAutoSaveFile *> staleFiles)
+void MainWindow::recoverFiles(QList<KAutoSaveFile *> staleFiles, const KUrl &originUrl)
{
foreach(KAutoSaveFile * stale, staleFiles) {
/*if (!stale->open(QIODevice::QIODevice::ReadOnly)) {
}*/
kDebug() << "// OPENING RECOVERY: " << stale->fileName() << "\nMANAGED: " << stale->managedFile().path();
// the stalefiles also contain ".lock" files so we must ignore them... bug in KAutoSaveFile?
- if (!stale->fileName().endsWith(".lock")) doOpenFile(KUrl(stale->fileName()), stale);
+ if (!stale->fileName().endsWith(".lock")) doOpenFile(originUrl, stale);
else KIO::NetAccess::del(KUrl(stale->fileName()), this);
}
}
disconnect(m_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap)), m_activeTimeline->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap)));
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)));
disconnect(m_activeTimeline, SIGNAL(configTrack(int)), this, SLOT(slotConfigTrack(int)));
disconnect(m_activeDocument, SIGNAL(docModified(bool)), this, SLOT(slotUpdateDocumentState(bool)));
disconnect(m_effectStack, SIGNAL(updateEffect(ClipItem*, int, QDomElement, QDomElement, int)), m_activeTimeline->projectView(), SLOT(slotUpdateClipEffect(ClipItem*, int, QDomElement, QDomElement, int)));
connect(m_projectList, SIGNAL(clipNameChanged(const QString, const QString)), trackView->projectView(), SLOT(clipNameChanged(const QString, const QString)));
//connect(trackView, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(activateMonitor()));
- connect(trackView, SIGNAL(insertTrack(int)), this, SLOT(slotInsertTrack(int)));
- connect(trackView, SIGNAL(deleteTrack(int)), this, SLOT(slotDeleteTrack(int)));
connect(trackView, SIGNAL(configTrack(int)), this, SLOT(slotConfigTrack(int)));
connect(trackView, SIGNAL(updateTracksInfo()), this, SLOT(slotUpdateTrackInfo()));
connect(trackView, SIGNAL(mousePosition(int)), this, SLOT(slotUpdateMousePosition(int)));
connect(trackView->projectView(), SIGNAL(activateDocumentMonitor()), m_projectMonitor, SLOT(activateMonitor()));
connect(trackView, SIGNAL(zoneMoved(int, int)), this, SLOT(slotZoneMoved(int, int)));
connect(m_projectList, SIGNAL(loadingIsOver()), trackView->projectView(), SLOT(slotUpdateAllThumbs()));
-
-
- trackView->projectView()->setContextMenu(m_timelineContextMenu, m_timelineContextClipMenu, m_timelineContextTransitionMenu, m_clipTypeGroup, (QMenu*)(factory()->container("marker_menu", this)));
+ trackView->projectView()->setContextMenu(m_timelineContextMenu, m_timelineContextClipMenu, m_timelineContextTransitionMenu, m_clipTypeGroup, static_cast<QMenu*>(factory()->container("marker_menu", this)));
m_activeTimeline = trackView;
if (m_renderWidget) {
slotCheckRenderStatus();
KShortcutsDialog dialog(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsAllowed, this);
dialog.addCollection(actionCollection(), i18nc("general keyboard shortcuts", "General"));
dialog.addCollection(m_effectsActionCollection, i18nc("effects and transitions keyboard shortcuts", "Effects & Transitions"));
+ dialog.addCollection(m_tracksActionCollection, i18nc("timeline track keyboard shortcuts", "Timeline and Tracks"));
dialog.configure();
}
void MainWindow::slotInsertTrack(int ix)
{
m_projectMonitor->activateMonitor();
- if (m_activeTimeline)
+ if (m_activeTimeline) {
+ if (ix == -1) ix = m_activeTimeline->projectView()->selectedTrack();
m_activeTimeline->projectView()->slotInsertTrack(ix);
+ }
if (m_activeDocument)
m_transitionConfig->updateProjectFormat(m_activeDocument->mltProfile(), m_activeDocument->timecode(), m_activeDocument->tracksList());
}
void MainWindow::slotDeleteTrack(int ix)
{
m_projectMonitor->activateMonitor();
- if (m_activeTimeline)
+ if (m_activeTimeline) {
+ if (ix == -1) ix = m_activeTimeline->projectView()->selectedTrack();
m_activeTimeline->projectView()->slotDeleteTrack(ix);
+ }
if (m_activeDocument)
m_transitionConfig->updateProjectFormat(m_activeDocument->mltProfile(), m_activeDocument->timecode(), m_activeDocument->tracksList());
}
m_transitionConfig->updateProjectFormat(m_activeDocument->mltProfile(), m_activeDocument->timecode(), m_activeDocument->tracksList());
}
+void MainWindow::slotSelectTrack()
+{
+ m_projectMonitor->activateMonitor();
+ if (m_activeTimeline) {
+ m_activeTimeline->projectView()->slotSelectClipsInTrack();
+ }
+}
+
+void MainWindow::slotSelectAllTracks()
+{
+ m_projectMonitor->activateMonitor();
+ if (m_activeTimeline)
+ m_activeTimeline->projectView()->slotSelectAllClips();
+}
+
void MainWindow::slotEditGuide()
{
if (m_activeTimeline)
StatusBarMessageLabel *m_messageLabel;
QActionGroup *m_clipTypeGroup;
KActionCollection *m_effectsActionCollection;
+ KActionCollection *m_tracksActionCollection;
bool m_findActivated;
QString m_findString;
void connectDocumentInfo(KdenliveDoc *doc);
void findAhead();
void doOpenFile(const KUrl &url, KAutoSaveFile *stale);
- void recoverFiles(QList<KAutoSaveFile *> staleFiles);
+ void recoverFiles(QList<KAutoSaveFile *> staleFiles, const KUrl &originUrl);
/** @brief Loads static and dynamic plugins.
*
void slotResizeItemStart();
void slotResizeItemEnd();
void configureNotifications();
- void slotInsertTrack(int ix = 0);
- void slotDeleteTrack(int ix = 0);
+ void slotInsertTrack(int ix = -1);
+ void slotDeleteTrack(int ix = -1);
/** @brief Shows the configure tracks dialog and updates transitions afterwards. */
void slotConfigTrack(int ix = -1);
+ /** @brief Select all clips in active track. */
+ void slotSelectTrack();
+ /** @brief Select all clips in timeline. */
+ void slotSelectAllTracks();
void slotGetNewLumaStuff();
void slotGetNewTitleStuff();
void slotGetNewRenderStuff();
if (show) {
m_effectWidget->getScene()->slotZoomFit();
}
+ m_videoBox->setEnabled(show);
render->doRefresh();
}
}
bool ProjectItem::hasProxy() const
{
if (m_clip == NULL) return false;
- if (m_clip->getProperty("proxy").isEmpty() || m_clip->getProperty("proxy") == "-" || data(0, JobProgressRole).toInt() == JOBCRASHED) return false;
+ if (m_clip->getProperty("proxy").size() < 2 || data(0, JobProgressRole).toInt() == JOBCRASHED) return false;
return true;
}
connect(this, SIGNAL(cancelRunningJob(const QString, stringMap )), this, SLOT(slotCancelRunningJob(const QString, stringMap)));
connect(this, SIGNAL(processLog(const QString, int , int, const QString)), this, SLOT(slotProcessLog(const QString, int , int, const QString)));
- connect(this, SIGNAL(updateJobStatus(const QString &, int, int, const QString &, const QString &, const QString)), this, SLOT(slotUpdateJobStatus(const QString &, int, int, const QString &, const QString &, const QString)));
+ connect(this, SIGNAL(updateJobStatus(const QString, int, int, const QString, const QString, const QString)), this, SLOT(slotUpdateJobStatus(const QString, int, int, const QString, const QString, const QString)));
connect(this, SIGNAL(gotProxy(const QString)), this, SLOT(slotGotProxyForId(const QString)));
{
m_render = projectRender;
m_listView->setIconSize(QSize((ProjectItem::itemDefaultHeight() - 2) * m_render->dar(), ProjectItem::itemDefaultHeight() - 2));
+ connect(m_render, SIGNAL(requestProxy(QString)), this, SLOT(slotCreateProxy(QString)));
}
void ProjectList::slotClipSelected()
m_doc->setModified(true);
}
-void ProjectList::slotAddFolder()
+void ProjectList::slotAddFolder(const QString &name)
{
- AddFolderCommand *command = new AddFolderCommand(this, i18n("Folder"), QString::number(m_doc->clipManager()->getFreeFolderId()), true);
+ AddFolderCommand *command = new AddFolderCommand(this, name.isEmpty() ? i18n("Folder") : name, QString::number(m_doc->clipManager()->getFreeFolderId()), true);
m_commandStack->push(command);
}
} else {
item = static_cast <ProjectItem *>(*it);
clip = item->referencedClip();
- if (item->referencedClip()->getProducer() == NULL) {
+ if (clip->getProducer() == NULL) {
bool replace = false;
if (brokenClips.contains(item->clipId())) {
// if this is a proxy clip, disable proxy
xml.removeAttribute("file_hash");
xml.removeAttribute("proxy_out");
}
- if (!replace) replace = xml.attribute("replace") == "1";
+ if (!replace) replace = xml.attribute("_replaceproxy") == "1";
+ xml.removeAttribute("_replaceproxy");
if (replace) {
resetThumbsProducer(clip);
}
getCachedThumbnail(item);
}
if (item->data(0, DurationRole).toString().isEmpty()) {
- item->changeDuration(item->referencedClip()->getProducer()->get_playtime());
+ item->changeDuration(clip->getProducer()->get_playtime());
}
if (clip->isPlaceHolder()) {
QPixmap pixmap = qVariantValue<QPixmap>(item->data(0, Qt::DecorationRole));
p.end();
item->setData(0, Qt::DecorationRole, pixmap);
}
+ else if (clip->getProperty("_replaceproxy") == "1") {
+ clip->setProperty("_replaceproxy", QString());
+ slotCreateProxy(clip->getId());
+ }
}
item->setData(0, UsageRole, QString::number(item->numReferences()));
}
for (int i = 0; i < givenList.count(); i++)
list << givenList.at(i);
}
+ QList <KUrl::List> foldersList;
foreach(const KUrl & file, list) {
// Check there is no folder here
KMimeType::Ptr type = KMimeType::findByUrl(file);
if (type->is("inode/directory")) {
- // user dropped a folder
+ // user dropped a folder, import its files
list.removeAll(file);
+ QDir dir(file.path());
+ QStringList result = dir.entryList(QDir::Files);
+ KUrl::List folderFiles;
+ folderFiles << file;
+ foreach(const QString & path, result) {
+ KUrl newFile = file;
+ newFile.addPath(path);
+ folderFiles.append(newFile);
+ }
+ if (folderFiles.count() > 1) foldersList.append(folderFiles);
}
}
- if (list.isEmpty())
- return;
-
- if (givenList.isEmpty()) {
+ if (givenList.isEmpty() && !list.isEmpty()) {
QStringList groupInfo = getGroup();
m_doc->slotAddClipList(list, groupInfo.at(0), groupInfo.at(1));
- } else {
+ } else if (!list.isEmpty()) {
m_doc->slotAddClipList(list, groupName, groupId);
}
+
+ if (!foldersList.isEmpty()) {
+ // create folders
+ for (int i = 0; i < foldersList.count(); i++) {
+ KUrl::List urls = foldersList.at(i);
+ KUrl folderUrl = urls.takeFirst();
+ QString folderName = folderUrl.fileName();
+ FolderProjectItem *folder = NULL;
+ if (!folderName.isEmpty()) {
+ folder = getFolderItemByName(folderName);
+ if (folder == NULL) {
+ slotAddFolder(folderName);
+ folder = getFolderItemByName(folderName);
+ }
+ }
+ if (folder)
+ m_doc->slotAddClipList(urls, folder->groupName(), folder->clipId());
+ else m_doc->slotAddClipList(urls);
+ }
+ }
}
void ProjectList::slotRemoveInvalidClip(const QString &id, bool replace)
return NULL;
}
+FolderProjectItem *ProjectList::getFolderItemByName(const QString &name)
+{
+ FolderProjectItem *item = NULL;
+ QList <QTreeWidgetItem *> hits = m_listView->findItems(name, Qt::MatchExactly, 0);
+ for (int i = 0; i < hits.count(); i++) {
+ if (hits.at(i)->type() == PROJECTFOLDERTYPE) {
+ item = static_cast<FolderProjectItem *>(hits.at(i));
+ break;
+ }
+ }
+ return item;
+}
+
FolderProjectItem *ProjectList::getFolderItemById(const QString &id)
{
FolderProjectItem *item;
slotUpdateJobStatus(item, PROXYJOB, JOBCRASHED, i18n("Failed to create proxy, empty path."));
return;
}
-
- ProxyJob *job = new ProxyJob(item->clipType(), id, QStringList() << path << item->clipUrl().path() << item->referencedClip()->producerProperty("_exif_orientation") << m_doc->getDocumentProperty("proxyparams").simplified() << QString::number(m_render->frameRenderWidth()) << QString::number(m_render->renderHeight()));
- if (job->isExclusive() && hasPendingJob(item, job->jobType)) {
- delete job;
- return;
- }
-
+
if (QFileInfo(path).size() > 0) {
// Proxy already created
setJobStatus(item, PROXYJOB, JOBDONE);
return;
}
+ ProxyJob *job = new ProxyJob(item->clipType(), id, QStringList() << path << item->clipUrl().path() << item->referencedClip()->producerProperty("_exif_orientation") << m_doc->getDocumentProperty("proxyparams").simplified() << QString::number(m_render->frameRenderWidth()) << QString::number(m_render->renderHeight()));
+ if (job->isExclusive() && hasPendingJob(item, job->jobType)) {
+ delete job;
+ return;
+ }
+
m_jobList.append(job);
setJobStatus(item, job->jobType, JOBWAITING, 0, job->statusMessage());
slotCheckJobProcess();
break;
}
QString destination = job->destination();
-
// Check if the clip is still here
- ProjectItem *processingItem = getItemById(job->clipId());
- if (processingItem == NULL) {
+ DocClipBase *currentClip = m_doc->clipManager()->getClipById(job->clipId());
+ //ProjectItem *processingItem = getItemById(job->clipId());
+ if (currentClip == NULL) {
job->setStatus(JOBDONE);
continue;
}
if (job->jobType == MLTJOB) {
MeltJob *jb = static_cast<MeltJob *> (job);
- jb->setProducer(processingItem->referencedClip()->getProducer());
+ jb->setProducer(currentClip->getProducer());
}
job->startJob();
if (job->jobStatus == JOBDONE) {
emit addClip(destination, QString(), QString());
}
} else if (job->jobStatus == JOBCRASHED || job->jobStatus == JOBABORTED) {
- emit updateJobStatus(job->clipId(), job->jobType, job->jobStatus, job->errorMessage());
+ emit updateJobStatus(job->clipId(), job->jobType, job->jobStatus, job->errorMessage(), QString(), job->logDetails());
}
}
// Thread finished, cleanup & update count
// remove proxy
QMap <QString, QString> newProps;
newProps.insert("proxy", QString());
- newProps.insert("replace", "1");
// insert required duration for proxy
newProps.insert("proxy_out", item->referencedClip()->producerProperty("out"));
new EditClipCommand(this, item->clipId(), item->referencedClip()->currentProperties(newProps), newProps, true, command);
// remove proxy
QMap <QString, QString> newProps;
newProps.insert("proxy", QString());
- newProps.insert("replace", "1");
new EditClipCommand(this, item->clipId(), item->referencedClip()->properties(), newProps, true, command);
}
}
{
if (item->hasProxy()) {
QPainter p(&pix);
- QColor c = QPalette().base().color();
- c.setAlpha(200);
- QBrush br(c);
- p.setBrush(br);
- p.setPen(Qt::NoPen);
- QRect r(1, 1, 15, 15);
- p.drawRoundedRect(r, 2, 2);
- p.setPen(QPalette().text().color());
+ QColor c(220, 220, 10, 200);
+ QRect r(0, 0, 12, 12);
+ p.fillRect(r, c);
QFont font = p.font();
font.setBold(true);
p.setFont(font);
+ p.setPen(Qt::black);
p.drawText(r, Qt::AlignCenter, i18nc("The first letter of Proxy, used as abbreviation", "P"));
}
}
command->setText(i18np("Cancel job", "Cancel jobs", m_jobList.count()));
m_jobMutex.lock();
for (int i = 0; i < m_jobList.count(); i++) {
- ProjectItem *item = getItemById(m_jobList.at(i)->clipId());
- if (!item || !item->referencedClip()) continue;
+ DocClipBase *currentClip = m_doc->clipManager()->getClipById(m_jobList.at(i)->clipId());
+ if (!currentClip) continue;
QMap <QString, QString> newProps = m_jobList.at(i)->cancelProperties();
if (newProps.isEmpty()) continue;
- QMap <QString, QString> oldProps = item->referencedClip()->currentProperties(newProps);
+ QMap <QString, QString> oldProps = currentClip->currentProperties(newProps);
new EditClipCommand(this, m_jobList.at(i)->clipId(), oldProps, newProps, true, command);
}
m_jobMutex.unlock();
void ProjectList::slotCancelRunningJob(const QString id, stringMap newProps)
{
if (newProps.isEmpty() || m_closing) return;
- ProjectItem *item = getItemById(id);
- if (!item || !item->referencedClip()) return;
- QMap <QString, QString> oldProps = item->referencedClip()->currentProperties(newProps);
+ DocClipBase *currentClip = m_doc->clipManager()->getClipById(id);
+ if (!currentClip) return;
+ QMap <QString, QString> oldProps = currentClip->currentProperties(newProps);
if (newProps == oldProps) return;
QMapIterator<QString, QString> i(oldProps);
EditClipCommand *command = new EditClipCommand(this, id, oldProps, newProps, true);
}
}
-void ProjectList::slotUpdateJobStatus(const QString &id, int type, int status, const QString &label, const QString &actionName, const QString details)
+void ProjectList::slotUpdateJobStatus(const QString id, int type, int status, const QString label, const QString actionName, const QString details)
{
ProjectItem *item = getItemById(id);
if (!item) return;
ProjectItem *getItemById(const QString &id);
QTreeWidgetItem *getAnyItemById(const QString &id);
FolderProjectItem *getFolderItemById(const QString &id);
+ FolderProjectItem *getFolderItemByName(const QString &name);
QAction *m_openAction;
QAction *m_reloadAction;
QAction *m_discardCurrentClipJobs;
void slotContextMenu(const QPoint &pos, QTreeWidgetItem *item);
/** @brief Creates an AddFolderCommand. */
- void slotAddFolder();
+ void slotAddFolder(const QString &name = QString());
/** @brief This is triggered when a clip description has been modified. */
void slotItemEdited(QTreeWidgetItem *item, int column);
/** @brief Update a clip's job status. */
void slotProcessLog(const QString, int progress, int, const QString = QString());
/** @brief A clip job crashed, inform user. */
- void slotUpdateJobStatus(const QString &id, int type, int status, const QString &label, const QString &actionName, const QString details);
+ void slotUpdateJobStatus(const QString id, int type, int status, const QString label, const QString actionName, const QString details);
void slotUpdateJobStatus(ProjectItem *item, int type, int status, const QString &label, const QString &actionName = QString(), const QString details = QString());
/** @brief Display error log for last failed job. */
void slotShowJobLog();
void cancelRunningJob(const QString, stringMap);
void processLog(const QString, int , int, const QString = QString());
void addClip(const QString, const QString &, const QString &);
- void updateJobStatus(const QString, int, int, const QString &label = QString(), const QString &actionName = QString(), const QString details = QString());
+ void updateJobStatus(const QString, int, int, const QString label = QString(), const QString actionName = QString(), const QString details = QString());
void gotProxy(const QString);
void checkJobProcess();
/** @brief A Filter Job produced results, send them back to the clip. */
QTreeWidgetItem *texts = new QTreeWidgetItem(files_list, QStringList() << i18n("Text clips"));
texts->setIcon(0, KIcon("text-plain"));
texts->setExpanded(true);
+ QTreeWidgetItem *playlists = new QTreeWidgetItem(files_list, QStringList() << i18n("Playlist clips"));
+ playlists->setIcon(0, KIcon("video-mlt-playlist"));
+ playlists->setExpanded(true);
QTreeWidgetItem *others = new QTreeWidgetItem(files_list, QStringList() << i18n("Other clips"));
others->setIcon(0, KIcon("unknown"));
others->setExpanded(true);
case IMAGE:
new QTreeWidgetItem(images, QStringList() << clip->fileURL().path());
break;
+ case PLAYLIST:
+ new QTreeWidgetItem(playlists, QStringList() << clip->fileURL().path());
+ break;
case UNKNOWN:
new QTreeWidgetItem(others, QStringList() << clip->fileURL().path());
break;
QString type = EffectsList::property(e, "mlt_service");
if (type != "colour") {
QString url = EffectsList::property(e, "resource");
+ if (type == "framebuffer") {
+ url = url.section('?', 0, 0);
+ }
if (!url.isEmpty()) {
if (!url.startsWith('/')) url.prepend(root);
if (url.section('.', 0, -2).endsWith("/.all")) {
return m_errorMessage;
}
+const QString AbstractClipJob::logDetails() const
+{
+ return m_logDetails;
+}
+
void AbstractClipJob::startJob()
{
}
bool replaceClip;
const QString clipId() const;
const QString errorMessage() const;
+ const QString logDetails() const;
void setStatus(CLIPJOBSTATUS status);
virtual const QString destination() const;
virtual void startJob();
protected:
QString m_errorMessage;
+ QString m_logDetails;
QProcess *m_jobProcess;
signals:
{
if (!m_jobProcess || m_jobDuration == 0 || jobStatus == JOBABORTED) return;
QString log = m_jobProcess->readAll();
- if (!log.isEmpty()) m_errorMessage.append(log + '\n');
+ if (!log.isEmpty()) m_logDetails.append(log + '\n');
int progress;
// Parse FFmpeg output
if (log.contains("frame=")) {
if (QFileInfo(m_dest).size() == 0) {
// File was not created
processLogInfo();
- m_errorMessage.append(i18n("Failed to create file."));
+ m_errorMessage.append(i18n("Failed to create proxy clip."));
setStatus(JOBCRASHED);
}
else setStatus(JOBDONE);
{
if (!m_jobProcess || jobStatus == JOBABORTED) return;
QString log = m_jobProcess->readAll();
- if (!log.isEmpty()) m_errorMessage.append(log + '\n');
+ if (!log.isEmpty()) m_logDetails.append(log + '\n');
else return;
int progress;
if (m_isFfmpegJob) {
bool proxyProducer;
if (info.xml.hasAttribute("proxy") && info.xml.attribute("proxy") != "-") {
path = info.xml.attribute("proxy");
- proxyProducer = true;
+ // Check for missing proxies
+ if (QFileInfo(path).size() <= 0) {
+ // proxy is missing, re-create it
+ emit requestProxy(info.clipId);
+ proxyProducer = false;
+ path = info.xml.attribute("resource");
+ }
+ else proxyProducer = true;
}
else {
path = info.xml.attribute("resource");
{
if (!m_mltProducer)
return;
-
resetZoneMode();
m_mltProducer->seek(pos);
if (m_mltProducer->get_speed() == 0) {
if (m_mltProducer) {
double pos = m_mltProducer->position();
if (m_isLoopMode) play(m_loopStart);
- else if (m_isZoneMode) resetZoneMode();
+ //else if (m_isZoneMode) resetZoneMode();
emit rendererStopped((int) pos);
}
}
*/
void removeInvalidProxy(const QString &id, bool durationError);
void refreshDocumentProducers(bool displayRatioChanged, bool fpsChanged);
+ /** @brief A proxy clip is missing, ask for creation. */
+ void requestProxy(QString);
+
/** @brief A frame's image has to be shown.
*
const int ProgressRole = Qt::UserRole + 3;
const int ExtraInfoRole = Qt::UserRole + 5;
-const int ScriptType = QTreeWidgetItem::UserType;
+const int DirectRenderType = QTreeWidgetItem::Type;
+const int ScriptRenderType = QTreeWidgetItem::UserType;
// Running job status
emit selectedRenderProfile(renderProps);
// insert item in running jobs list
- RenderJobItem *renderItem;
+ RenderJobItem *renderItem = NULL;
QList<QTreeWidgetItem *> existing = m_view.running_jobs->findItems(dest, Qt::MatchExactly, 1);
if (!existing.isEmpty()) {
renderItem = static_cast<RenderJobItem*> (existing.at(0));
- if (renderItem->status() == RUNNINGJOB) {
+ if (renderItem->status() == RUNNINGJOB || renderItem->status() == WAITINGJOB) {
KMessageBox::information(this, i18n("There is already a job writing file:<br /><b>%1</b><br />Abort the job if you want to overwrite it...", dest), i18n("Already running"));
return;
}
- renderItem->setData(1, ProgressRole, 0);
- renderItem->setStatus(WAITINGJOB);
- } else {
- renderItem = new RenderJobItem(m_view.running_jobs, QStringList() << QString() << dest);
- }
+ if (renderItem->type() != DirectRenderType) {
+ delete renderItem;
+ renderItem = NULL;
+ }
+ else {
+ renderItem->setData(1, ProgressRole, 0);
+ renderItem->setStatus(WAITINGJOB);
+ renderItem->setIcon(0, KIcon("media-playback-pause"));
+ renderItem->setData(1, Qt::UserRole, i18n("Waiting..."));
+ renderItem->setData(1, ParametersRole, dest);
+ }
+ }
+ if (!renderItem) renderItem = new RenderJobItem(m_view.running_jobs, QStringList() << QString() << dest);
renderItem->setData(1, TimeRole, QTime::currentTime());
// Set rendering type
// check if we have a job waiting to render
if (m_blockProcessing) return;
RenderJobItem* item = static_cast<RenderJobItem*> (m_view.running_jobs->topLevelItem(0));
+
+ // Make sure no other rendering is running
while (item) {
if (item->status() == RUNNINGJOB) return;
item = static_cast<RenderJobItem*> (m_view.running_jobs->itemBelow(item));
}
item = static_cast<RenderJobItem*> (m_view.running_jobs->topLevelItem(0));
bool waitingJob = false;
+
+ // Find first aiting job
while (item) {
if (item->status() == WAITINGJOB) {
item->setData(1, TimeRole, QTime::currentTime());
void RenderWidget::startRendering(RenderJobItem *item)
{
- if (item->type() == QTreeWidgetItem::Type) {
+ if (item->type() == DirectRenderType) {
// Normal render process
+ kDebug()<<"// Normal process";
if (QProcess::startDetached(m_renderer, item->data(1, ParametersRole).toStringList()) == false) {
item->setStatus(FAILEDJOB);
} else {
KNotification::event("RenderStarted", i18n("Rendering <i>%1</i> started", item->text(1)), QPixmap(), this);
}
- } else if (item->type() == ScriptType){
+ } else if (item->type() == ScriptRenderType){
// Script item
+ kDebug()<<"// SCRIPT process: "<<item->data(1, ParametersRole).toString();
if (QProcess::startDetached(item->data(1, ParametersRole).toString()) == false) {
item->setStatus(FAILEDJOB);
}
{
RenderJobItem* item = static_cast<RenderJobItem*> (m_view.scripts_list->currentItem());
if (item) {
+ kDebug() << "// STARTING SCRIPT: "<<item->text(1);
QString destination = item->data(1, Qt::UserRole).toString();
QString path = item->data(1, Qt::UserRole + 1).toString();
// Insert new job in queue
- RenderJobItem *renderItem;
+ RenderJobItem *renderItem = NULL;
QList<QTreeWidgetItem *> existing = m_view.running_jobs->findItems(destination, Qt::MatchExactly, 1);
kDebug() << "------ START SCRIPT";
if (!existing.isEmpty()) {
renderItem = static_cast<RenderJobItem*> (existing.at(0));
- if (renderItem->status() == RUNNINGJOB) {
+ if (renderItem->status() == RUNNINGJOB || renderItem->status() == WAITINGJOB) {
KMessageBox::information(this, i18n("There is already a job writing file:<br /><b>%1</b><br />Abort the job if you want to overwrite it...", destination), i18n("Already running"));
return;
}
- } else renderItem = new RenderJobItem(m_view.running_jobs, QStringList() << QString() << destination, ScriptType);
+ else if (renderItem->type() != ScriptRenderType) {
+ delete renderItem;
+ renderItem = NULL;
+ }
+ }
+ if (!renderItem) renderItem = new RenderJobItem(m_view.running_jobs, QStringList() << QString() << destination, ScriptRenderType);
renderItem->setData(1, ProgressRole, 0);
renderItem->setStatus(WAITINGJOB);
renderItem->setIcon(0, KIcon("media-playback-pause"));
RenderJobItem *item = static_cast<RenderJobItem*> (m_view.running_jobs->topLevelItem(0));
while (item) {
if (item->status() == WAITINGJOB) {
- if (item->type() == QTreeWidgetItem::Type) {
+ if (item->type() == DirectRenderType) {
// Add render process for item
const QString params = item->data(1, ParametersRole).toStringList().join(" ");
outStream << m_renderer << " " << params << "\n";
- } else if (item->type() == ScriptType){
+ } else if (item->type() == ScriptRenderType){
// Script item
outStream << item->data(1, ParametersRole).toString() << "\n";
}
,m_scale(1)
,m_maxval(25)
,m_manager(manager)
+ ,m_overCursor(false)
{
m_zoneStart = 10;
m_zoneEnd = 60;
- m_zoneColor = KStatefulBrush(KColorScheme::View, KColorScheme::PositiveBackground, KSharedConfig::openConfig(KdenliveSettings::colortheme())).brush(this).color();
+ KSharedConfigPtr config = KSharedConfig::openConfig(KdenliveSettings::colortheme());
+ m_zoneBrush = KStatefulBrush(KColorScheme::View, KColorScheme::PositiveBackground, config);
+
setMouseTracking(true);
setMinimumHeight(10);
}
} else emit seekRenderer((int) pos);
}
+void SmallRuler::leaveEvent( QEvent * event )
+{
+ Q_UNUSED(event);
+ if (m_overCursor) {
+ m_overCursor = false;
+ update();
+ }
+}
+
// virtual
void SmallRuler::mouseMoveEvent(QMouseEvent * event)
{
const int pos = event->x() / m_scale;
- if (event->buttons() & Qt::LeftButton) emit seekRenderer((int) pos);
+ if (event->button() == Qt::NoButton) {
+ if (qAbs(pos * m_scale - m_cursorPosition) < 6) {
+ if (!m_overCursor) {
+ m_overCursor = true;
+ update();
+ }
+ }
+ else if (m_overCursor) {
+ m_overCursor = false;
+ update();
+ }
+ }
+ if (event->buttons() & Qt::LeftButton) {
+ m_overCursor = true;
+ emit seekRenderer((int) pos);
+ }
else {
if (qAbs((pos - m_zoneStart) * m_scale) < 4) {
setToolTip(i18n("Zone start: %1", m_manager->timecode().getTimecodeFromFrames(m_zoneStart)));
const int zoneStart = (int)(m_zoneStart * m_scale);
const int zoneEnd = (int)(m_zoneEnd * m_scale);
- p.fillRect(zoneStart, height() / 2 - 1, zoneEnd - zoneStart, height() / 2, m_zoneColor);
+ p.setPen(Qt::NoPen);
+ p.setBrush(m_zoneBrush.brush(this));
+ p.drawRect(zoneStart, height() / 2 - 1, zoneEnd - zoneStart, height() / 2);
// draw ruler
p.setPen(palette().text().color());
// draw pointer
QPolygon pa(3);
- pa.setPoints(3, m_cursorPosition - 5, 10, m_cursorPosition + 5, 10, m_cursorPosition/*+0*/, 5);
- p.setBrush(palette().text().color());
+ pa.setPoints(3, m_cursorPosition - 6, 10, m_cursorPosition + 6, 10, m_cursorPosition/*+0*/, 4);
+ if (m_overCursor) p.setBrush(palette().highlight());
+ else p.setBrush(palette().text().color());
p.setPen(Qt::NoPen);
p.drawPolygon(pa);
}
#ifndef SMALLRULER_H
#define SMALLRULER_H
+#include <KColorScheme>
#include <QWidget>
#include "monitormanager.h"
+
class SmallRuler : public QWidget
{
Q_OBJECT
SmallRuler(MonitorManager *manager, QWidget *parent = 0);
virtual void mousePressEvent(QMouseEvent * event);
virtual void mouseMoveEvent(QMouseEvent * event);
+ virtual void leaveEvent( QEvent * event );
void adjustScale(int maximum);
void setZone(int start, int end);
QPoint zone();
int m_maxval;
int m_zoneStart;
int m_zoneEnd;
- QColor m_zoneColor;
+ KStatefulBrush m_zoneBrush;
QList <int> m_markers;
QPixmap m_pixmap;
MonitorManager *m_manager;
+ /** @brief True is mouse is over the ruler cursor. */
+ bool m_overCursor;
void updatePixmap();
public slots:
#include <QScrollBar>
#include <QInputDialog>
-TrackView::TrackView(KdenliveDoc *doc, bool *ok, QWidget *parent) :
+TrackView::TrackView(KdenliveDoc *doc, QList <QAction*> actions, bool *ok, QWidget *parent) :
QWidget(parent),
m_scale(1.0),
m_projectTracks(0),
m_doc(doc),
m_verticalZoom(1)
{
-
+ m_trackActions << actions;
setupUi(this);
// ruler_frame->setMaximumHeight();
// size_frame->setMaximumHeight();
frame->setFixedHeight(1);
headers_container->layout()->addWidget(frame);
TrackInfo info = list.at(max - i - 1);
- header = new HeaderTrack(i, info, height, headers_container);
+ header = new HeaderTrack(i, info, height, m_trackActions, headers_container);
header->setPalette(p);
header->setSelectedIndex(m_trackview->selectedTrack());
connect(header, SIGNAL(switchTrackVideo(int)), m_trackview, SLOT(slotSwitchTrackVideo(int)));
connect(header, SIGNAL(switchTrackAudio(int)), m_trackview, SLOT(slotSwitchTrackAudio(int)));
connect(header, SIGNAL(switchTrackLock(int)), m_trackview, SLOT(slotSwitchTrackLock(int)));
connect(header, SIGNAL(selectTrack(int)), m_trackview, SLOT(slotSelectTrack(int)));
- connect(header, SIGNAL(deleteTrack(int)), this, SIGNAL(deleteTrack(int)));
- connect(header, SIGNAL(insertTrack(int)), this, SIGNAL(insertTrack(int)));
connect(header, SIGNAL(renameTrack(int, QString)), this, SLOT(slotRenameTrack(int, QString)));
connect(header, SIGNAL(configTrack(int)), this, SIGNAL(configTrack(int)));
connect(header, SIGNAL(addTrackInfo(const QDomElement, int)), m_trackview, SLOT(slotAddTrackEffect(const QDomElement, int)));
Q_OBJECT
public:
- explicit TrackView(KdenliveDoc *doc, bool *ok, QWidget *parent = 0);
+ explicit TrackView(KdenliveDoc *doc, QList <QAction *> actions, bool *ok, QWidget *parent = 0);
virtual ~ TrackView();
void setEditMode(const QString & editMode);
const QString & editMode() const;
KdenliveDoc *m_doc;
int m_verticalZoom;
QString m_documentErrors;
+ QList <QAction *> m_trackActions;
+
void parseDocument(QDomDocument doc);
int slotAddProjectTrack(int ix, QDomElement xml, bool locked, QDomNodeList producers);
DocClipBase *getMissingProducer(const QString id) const;
void mousePosition(int);
void cursorMoved();
void zoneMoved(int, int);
- void insertTrack(int);
- void deleteTrack(int);
void configTrack(int);
void updateTracksInfo();
void setZoom(int);
<rect>
<x>0</x>
<y>0</y>
- <width>263</width>
- <height>197</height>
+ <width>266</width>
+ <height>219</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0" colspan="2">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string/>
<property name="flat">
<bool>true</bool>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="margin">
- <number>0</number>
- </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
</layout>
</widget>
</item>
- <item row="1" column="0" colspan="2">
+ <item>
<widget class="QCheckBox" name="compressed_archive">
<property name="text">
<string>Compressed archive</string>
</property>
</widget>
</item>
- <item row="2" column="0" colspan="2">
- <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="icon_info">
<property name="sizePolicy">
</item>
</layout>
</item>
- <item row="3" column="0" colspan="2">
+ <item>
<widget class="QLabel" name="project_files">
<property name="text">
<string/>
</property>
</widget>
</item>
- <item row="4" column="0" colspan="2">
+ <item>
<widget class="QTreeWidget" name="files_list">
<property name="alternatingRowColors">
<bool>true</bool>
</column>
</widget>
</item>
- <item row="5" column="0">
- <widget class="QProgressBar" name="progressBar">
- <property name="value">
- <number>0</number>
- </property>
- </widget>
- </item>
- <item row="5" column="1">
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="standardButtons">
- <set>QDialogButtonBox::Apply|QDialogButtonBox::Close</set>
- </property>
- </widget>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QProgressBar" name="progressBar">
+ <property name="value">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Apply|QDialogButtonBox::Close</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
</layout>
</widget>
<rect>
<x>0</x>
<y>0</y>
- <width>133</width>
- <height>85</height>
+ <width>129</width>
+ <height>86</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="minimumSize">
<size>
<width>0</width>
- <height>16</height>
+ <height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
- <height>16</height>
+ <height>20</height>
</size>
</property>
</widget>
[Desktop Entry]
Type=Service
Name=MLT Playlist
+Name[ca]=Llista de reproducció del MLT
Name[cs]=Seznam skladeb MLT
Name[da]=MLT-spilleliste
Name[de]=MLT-Wiedergabeliste
Name[el]=Λίστα αναπαραγωγής MLT
+Name[es]=Lista de reproducción de MLT
+Name[gl]=Lista de reprodución MLT
+Name[nb]=MLT-spilleliste
Name[nl]=MLT-afspeellijst
+Name[pl]=Lista odtwarzania MLT
Name[pt]=Lista de Reprodução MLT
Name[pt_BR]=Lista de Reprodução MLT
Name[sv]=MLT-spellista