Commit 01a33a03 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle

Merge branch '15.08'

parents 90502913 569d9a39
......@@ -2,7 +2,7 @@
var update = new Object();
update["Graph position"] = new Array(new Array(0.3, function(v, d) { return this.upd1(v, d); }));
update["Curve point number"] = update["Graph position"];
update["Curve point number"] = new Array(new Array(0.2, function(v, d) { return this.upd1(v, d); }));
function upd1(value, isDowngrade) {
if (isDowngrade)
......
......@@ -4,7 +4,22 @@ set(QT_USE_QTSCRIPT 1)
set(QT_USE_QTSVG 1)
set(QT_USE_QTXML 1)
find_package(OpenGL REQUIRED)
add_definitions(${Qt5Gui_DEFINITIONS})
if(${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")
find_package(OpenGL REQUIRED)
set_package_properties(OpenGL PROPERTIES
DESCRIPTION "the OpenGL library"
URL ""
TYPE RUNTIME
PURPOSE "")
else()
find_package(OpenGLES REQUIRED)
set_package_properties(OpenGLES PROPERTIES
DESCRIPTION "the OpenGLES library"
URL ""
TYPE RUNTIME
PURPOSE "")
endif()
option(WITH_JogShuttle "Build Jog/Shuttle support" ON)
......@@ -230,6 +245,7 @@ target_link_libraries(kdenlive
${Qt5_LIBRARIES}
Qt5::Svg
${OPENGL_LIBRARIES}
${OPENGLES_LIBRARIES}
${MLT_LIBRARIES}
${MLTPP_LIBRARIES}
${CMAKE_DL_LIBS}
......
......@@ -221,6 +221,21 @@ void SmallJobLabel::slotSetJobCount(int jobCount)
}
}
LineEventEater::LineEventEater(QObject *parent) : QObject(parent)
{
}
bool LineEventEater::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::ShortcutOverride) {
if (((QKeyEvent*)event)->key() == Qt::Key_Escape) {
emit clearSearchLine();
}
return QObject::eventFilter(obj, event);
}
return QObject::eventFilter(obj, event);
}
EventEater::EventEater(QObject *parent) : QObject(parent)
{
}
......@@ -288,6 +303,10 @@ Bin::Bin(QWidget* parent) :
searchLine->setClearButtonEnabled(true);
searchLine->setFocusPolicy(Qt::ClickFocus);
connect(searchLine, SIGNAL(textChanged(const QString &)), m_proxyModel, SLOT(slotSetSearchString(const QString &)));
LineEventEater *leventEater = new LineEventEater(this);
searchLine->installEventFilter(leventEater);
connect(leventEater, SIGNAL(clearSearchLine()), searchLine, SLOT(clear()));
m_toolbar->addWidget(searchLine);
// Hack, create toolbar spacer
......
......@@ -274,6 +274,19 @@ public:
}
};
class LineEventEater : public QObject
{
Q_OBJECT
public:
explicit LineEventEater(QObject *parent = 0);
protected:
bool eventFilter(QObject *obj, QEvent *event);
signals:
void clearSearchLine();
};
/**
* @class EventEater
* @brief Filter mouse clicks in the Item View.
......
......@@ -32,6 +32,21 @@
#include <QStandardPaths>
TreeEventEater::TreeEventEater(QObject *parent) : QObject(parent)
{
}
bool TreeEventEater::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::ShortcutOverride) {
if (((QKeyEvent*)event)->key() == Qt::Key_Escape) {
emit clearSearchLine();
}
return QObject::eventFilter(obj, event);
}
return QObject::eventFilter(obj, event);
}
EffectsListView::EffectsListView(QWidget *parent) :
QWidget(parent)
{
......@@ -45,7 +60,11 @@ EffectsListView::EffectsListView(QWidget *parent) :
lyr->setContentsMargins(0, 0, 0, 0);
search_effect->setTreeWidget(m_effectsList);
search_effect->setToolTip(i18n("Search in the effect list"));
TreeEventEater *leventEater = new TreeEventEater(this);
search_effect->installEventFilter(leventEater);
connect(leventEater, SIGNAL(clearSearchLine()), search_effect, SLOT(clear()));
int size = style()->pixelMetric(QStyle::PM_SmallIconSize);
QSize iconSize(size, size);
buttonInfo->setIcon(QIcon::fromTheme("help-about"));
......
......@@ -35,6 +35,19 @@ class EffectsListWidget;
class QTreeWidget;
class KActionCategory;
class TreeEventEater : public QObject
{
Q_OBJECT
public:
explicit TreeEventEater(QObject *parent = 0);
protected:
bool eventFilter(QObject *obj, QEvent *event);
signals:
void clearSearchLine();
};
/**
* @class MyDropButton
* @brief A QToolButton accepting effect drops
......
......@@ -384,19 +384,27 @@ void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *au
QDomElement documentElement;
QDomNodeList effects;
QDomElement base = doc.documentElement();
QStringList addedTags;
effects = doc.elementsByTagName("effect");
if (effects.count() == 0) {
int i = effects.count();
if (i == 0) {
qDebug() << "+++++++++++++\nEffect broken: " << name<<"\n+++++++++++";;
return;
}
bool needsLocaleConversion = false;
for (int i = 0; !effects.item(i).isNull(); ++i) {
i--;
for (; i >= 0 ; i--) {
QLocale locale;
documentElement = effects.item(i).toElement();
QDomNode n = effects.item(i);
if (n.isNull()) continue;
documentElement = n.toElement();
QString tag = documentElement.attribute("tag", QString());
QString id = documentElement.hasAttribute("id") ? documentElement.attribute("id") : tag;
if (addedTags.contains(id)) {
// We already processed a version of that filter
continue;
}
//If XML has no description, take it fom MLT's descriptions
if (effectDescriptions.contains(tag)) {
QDomNodeList desc = documentElement.elementsByTagName("description");
......@@ -443,10 +451,11 @@ void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *au
version = metadata->get_double("version");
}
if (metadata) delete metadata;
if (documentElement.hasAttribute("version")) {
// a specific version of the filter is required
if (locale.toDouble(documentElement.attribute("version")) > version) {
return;
continue;
}
}
if (version > -1) {
......@@ -455,7 +464,6 @@ void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *au
versionNode.appendChild(doc.createTextNode(QLocale().toString(version)));
documentElement.appendChild(versionNode);
}
// Parse effect information.
if (base.tagName() != "effectgroup" && (filtersList.contains(tag) || producersList.contains(tag))) {
QString type = documentElement.attribute("type", QString());
......@@ -466,6 +474,7 @@ void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *au
}
else
videoEffectList->append(documentElement);
addedTags << id;
}
}
if (base.tagName() == "effectgroup") {
......
......@@ -654,8 +654,9 @@ CollapsibleEffect *EffectStackView2::getEffectByIndex(int ix)
void EffectStackView2::slotUpdateEffectParams(const QDomElement &old, const QDomElement &e, int ix)
{
if (m_status == TIMELINE_TRACK)
if (m_status == TIMELINE_TRACK) {
emit updateEffect(NULL, m_trackindex, old, e, ix,false);
}
else if (m_status == TIMELINE_CLIP && m_clipref) {
emit updateEffect(m_clipref, -1, old, e, ix, false);
// Make sure the changed effect is currently displayed
......
......@@ -111,8 +111,8 @@ ParameterContainer::ParameterContainer(const QDomElement &effect, const ItemInfo
m_out = (info.cropStart + info.cropDuration).frames(KdenliveSettings::project_fps()) - 1;
QDomNodeList namenode = effect.childNodes(); //elementsByTagName("parameter");
QDomElement e = effect.toElement();
int minFrame = e.attribute("start").toInt();
int maxFrame = e.attribute("end").toInt();
// In transitions, maxFrame is in fact one frame after the end of transition
......@@ -318,7 +318,12 @@ ParameterContainer::ParameterContainer(const QDomElement &effect, const ItemInfo
curve->setMaxPoints(pa.attribute("max").toInt());
QList<QPointF> points;
int number;
if (locale.toDouble(e.attribute("version")) > 0.2) {
double version = 0;
QDomElement namenode = effect.firstChildElement("version");
if (!namenode.isNull()) {
version = locale.toDouble(namenode.text());
}
if (version > 0.2) {
// Rounding gives really weird results. (int) (10 * 0.3) gives 2! So for now, add 0.5 to get correct result
number = locale.toDouble(EffectsList::parameter(e, pa.attribute("number"))) * 10 + 0.5;
} else {
......@@ -334,8 +339,9 @@ ParameterContainer::ParameterContainer(const QDomElement &effect, const ItemInfo
out.replace("%i", QString::number(j));
points << QPointF(locale.toDouble(EffectsList::parameter(e, in)), locale.toDouble(EffectsList::parameter(e, out)));
}
if (!points.isEmpty())
if (!points.isEmpty()) {
curve->setCurve(KisCubicCurve(points));
}
MySpinBox *spinin = new MySpinBox();
spinin->setRange(0, 1000);
MySpinBox *spinout = new MySpinBox();
......@@ -371,6 +377,9 @@ ParameterContainer::ParameterContainer(const QDomElement &effect, const ItemInfo
} else if (type == "wipe") {
Wipeval *wpval = new Wipeval;
wpval->setupUi(toFillin);
// Make sure button shows its pressed state even if widget loses focus
QColor bg = QPalette().highlight().color();
toFillin->setStyleSheet(QString("QPushButton:checked {background-color:rgb(%1,%2,%3);}").arg(bg.red()).arg(bg.green()).arg(bg.blue()));
wipeInfo w = getWipeInfo(value);
switch (w.start) {
case UP:
......@@ -689,7 +698,12 @@ void ParameterContainer::slotCollectAllParameters()
QString outName = pa.attribute("outpoints");
int off = pa.attribute("min").toInt();
int end = pa.attribute("max").toInt();
if (locale.toDouble(oldparam.attribute("version")) > 0.2) {
double version = 0;
QDomElement namenode = m_effect.firstChildElement("version");
if (!namenode.isNull()) {
version = locale.toDouble(namenode.text());
}
if (version > 0.2) {
EffectsList::setParameter(m_effect, number, locale.toString(points.count() / 10.));
} else {
EffectsList::setParameter(m_effect, number, QString::number(points.count()));
......
......@@ -284,6 +284,21 @@ MainWindow::MainWindow(const QString &MltPath, const QUrl &Url, const QString &
new TimelineSearch(this);
new ScopeManager(this);
// Add shortcut to action tooltips
QList< KActionCollection * > collections = KActionCollection::allCollections();
for (int i = 0; i < collections.count(); ++i) {
KActionCollection *coll = collections.at(i);
foreach( QAction* tempAction, coll->actions()) {
// find the shortcut pattern and delete (note the preceding space in the RegEx)
QString strippedTooltip = tempAction->toolTip().remove(QRegExp("\\s\\(.*\\)"));
// append shortcut if it exists for action
if (tempAction->shortcut() == QKeySequence(0))
tempAction->setToolTip( strippedTooltip);
else
tempAction->setToolTip( strippedTooltip + " (" + tempAction->shortcut().toString() + ")");
}
}
setupGUI();
emit GUISetupDone();
......@@ -1035,7 +1050,6 @@ void MainWindow::setupActions()
connect(stickTransition, SIGNAL(triggered(bool)), this, SLOT(slotAutoTransition()));
addAction("group_clip", i18n("Group Clips"), this, SLOT(slotGroupClips()), QIcon::fromTheme("object-group"), Qt::CTRL + Qt::Key_G);
QAction * ungroupClip = new QAction(QIcon::fromTheme("object-ungroup"), i18n("Ungroup Clips"), this);
addAction("ungroup_clip", ungroupClip);
......
......@@ -123,7 +123,7 @@ void ClipController::getProducerXML(QDomDocument& document)
void ClipController::getInfoForProducer()
{
date = QFileInfo(m_properties->get("resource")).created();
date = QFileInfo(m_url.path()).lastModified();
m_audioIndex = int_property("audio_index");
m_videoIndex = int_property("video_index");
if (m_service == "avformat" || m_service == "avformat-novalidate") {
......
......@@ -119,7 +119,9 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
// Tool bar buttons
m_toolbar = new QToolBar(this);
m_toolbar->setIconSize(QSize(s, s));
QWidget *sp1 = new QWidget(this);
sp1->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
m_toolbar->addWidget(sp1);
if (id == Kdenlive::ClipMonitor) {
// Add options for recording
m_recManager = new RecManager(s, this);
......@@ -127,43 +129,26 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
connect(m_recManager, &RecManager::addClipToProject, this, &Monitor::addClipToProject);
}
m_playIcon = QIcon::fromTheme("media-playback-start");
m_pauseIcon = QIcon::fromTheme("media-playback-pause");
if (id != Kdenlive::DvdMonitor) {
m_toolbar->addAction(QIcon::fromTheme("go-first"), i18n("Set zone start"), this, SLOT(slotSetZoneStart()));
m_toolbar->addAction(QIcon::fromTheme("go-last"), i18n("Set zone end"), this, SLOT(slotSetZoneEnd()));
m_toolbar->addAction(manager->getAction("mark_in"));
m_toolbar->addAction(manager->getAction("mark_out"));
}
m_toolbar->addAction(QIcon::fromTheme("media-seek-backward"), i18n("Rewind"), this, SLOT(slotRewind()));
//m_toolbar->addAction(QIcon::fromTheme("media-skip-backward"), i18n("Rewind 1 frame"), this, SLOT(slotRewindOneFrame()));
m_toolbar->addAction(manager->getAction("monitor_seek_backward"));
QToolButton *playButton = new QToolButton(m_toolbar);
m_playMenu = new QMenu(i18n("Play..."), this);
m_playAction = new KDualAction(i18n("Play"), i18n("Pause"), this);
m_playAction->setInactiveIcon(m_playIcon);
m_playAction->setActiveIcon(m_pauseIcon);
m_playAction = static_cast<KDualAction*> (manager->getAction("monitor_play"));
m_playMenu->addAction(m_playAction);
connect(m_playAction, SIGNAL(activeChanged(bool)), this, SLOT(switchPlay(bool)));
playButton->setMenu(m_playMenu);
playButton->setPopupMode(QToolButton::MenuButtonPopup);
m_toolbar->addWidget(playButton);
//m_toolbar->addAction(QIcon::fromTheme("media-skip-forward"), i18n("Forward 1 frame"), this, SLOT(slotForwardOneFrame()));
m_toolbar->addAction(QIcon::fromTheme("media-seek-forward"), i18n("Forward"), this, SLOT(slotForward()));
m_toolbar->addAction(manager->getAction("monitor_seek_forward"));
playButton->setDefaultAction(m_playAction);
m_configMenu = new QMenu(i18n("Misc..."), this);
if (id != Kdenlive::DvdMonitor) {
QToolButton *configButton = new QToolButton(m_toolbar);
m_configMenu = new QMenu(i18n("Misc..."), this);
configButton->setIcon(QIcon::fromTheme("system-run"));
configButton->setMenu(m_configMenu);
configButton->setPopupMode(QToolButton::QToolButton::InstantPopup);
m_toolbar->addWidget(configButton);
if (id == Kdenlive::ClipMonitor) {
m_markerMenu = new QMenu(i18n("Go to marker..."), this);
m_markerMenu->setEnabled(false);
......@@ -235,12 +220,19 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
m_toolbar->addAction(visibilityAction);
}
m_toolbar->addSeparator();
m_timePos = new TimecodeDisplay(m_monitorManager->timecode(), this);
m_toolbar->addWidget(m_timePos);
QToolButton *configButton = new QToolButton(m_toolbar);
configButton->setIcon(QIcon::fromTheme("system-run"));
configButton->setMenu(m_configMenu);
configButton->setPopupMode(QToolButton::QToolButton::InstantPopup);
m_toolbar->addWidget(configButton);
if (m_recManager) m_toolbar->addAction(m_recManager->switchAction());
QWidget *spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
m_toolbar->addWidget(spacer);
if (m_recManager) m_toolbar->addAction(m_recManager->switchAction());
m_timePos = new TimecodeDisplay(m_monitorManager->timecode(), this);
m_toolbar->addWidget(m_timePos);
connect(m_timePos, SIGNAL(timeCodeEditingFinished()), this, SLOT(slotSeek()));
m_toolbar->setMaximumHeight(m_timePos->height());
layout->addWidget(m_toolbar);
......
......@@ -142,8 +142,6 @@ private:
bool m_dragStarted;
//TODO: Move capture stuff in own class
RecManager *m_recManager;
QIcon m_playIcon;
QIcon m_pauseIcon;
/** @brief The widget showing current time position **/
TimecodeDisplay *m_timePos;
KDualAction *m_playAction;
......
......@@ -56,6 +56,11 @@ void MonitorManager::setDocument(KdenliveDoc *doc)
m_document = doc;
}
QAction *MonitorManager::getAction(QString name)
{
return pCore->window()->action(name.toLatin1());
}
void MonitorManager::initMonitors(Monitor *clipMonitor, Monitor *projectMonitor, RecMonitor *recMonitor)
{
m_clipMonitor = clipMonitor;
......@@ -291,10 +296,12 @@ Mlt::Profile *MonitorManager::profile()
void MonitorManager::setupActions()
{
QAction * monitorPlay = new QAction(QIcon::fromTheme("media-playback-start"), i18n("Play"), this);
monitorPlay->setShortcut(Qt::Key_Space);
pCore->window()->addAction("monitor_play", monitorPlay);
connect(monitorPlay, &QAction::triggered, this, &MonitorManager::slotPlay);
KDualAction *playAction = new KDualAction(i18n("Play"), i18n("Pause"), this);
playAction->setInactiveIcon(QIcon::fromTheme("media-playback-start"));
playAction->setActiveIcon(QIcon::fromTheme("media-playback-pause"));
playAction->setShortcut(Qt::Key_Space);
pCore->window()->addAction("monitor_play", playAction);
connect(playAction, &QAction::triggered, this, &MonitorManager::slotPlay);
QAction * monitorPause = new QAction(QIcon::fromTheme("media-playback-stop"), i18n("Pause"), this);
monitorPause->setShortcut(Qt::Key_K);
......@@ -397,12 +404,12 @@ void MonitorManager::setupActions()
pCore->window()->addAction("seek_zone_end", zoneEnd);
connect(zoneEnd, &QAction::triggered, this, &MonitorManager::slotZoneEnd);
QAction *markIn = new QAction(i18n("Set Zone In"), this);
QAction *markIn = new QAction(QIcon::fromTheme("go-first"), i18n("Set Zone In"), this);
markIn->setShortcut(Qt::Key_I);
pCore->window()-> addAction("mark_in", markIn);
pCore->window()->addAction("mark_in", markIn);
connect(markIn, &QAction::triggered, this, &MonitorManager::slotSetInPoint);
QAction *markOut = new QAction(i18n("Set Zone Out"), this);
QAction *markOut = new QAction(QIcon::fromTheme("go-last"), i18n("Set Zone Out"), this);
markOut->setShortcut(Qt::Key_O);
pCore->window()-> addAction("mark_out", markOut);
connect(markOut, &QAction::triggered, this, &MonitorManager::slotSetOutPoint);
......
......@@ -62,7 +62,8 @@ public:
void setConsumerProperty(const QString &name, const QString &value);
BinController *binController();
Mlt::Profile *profile();
/** @brief Return a mainwindow action from its id name. */
QAction *getAction(QString name);
Monitor *clipMonitor();
Monitor *projectMonitor();
......
......@@ -137,7 +137,7 @@ void RecManager::slotRecord(bool record)
if (m_device_selector->currentData().toInt() == Video4Linux) {
if (record) {
QDir captureFolder;
if (KdenliveSettings::capturetoprojectfolder()) captureFolder = QDir(m_monitor->projectFolder());
if (KdenliveSettings::capturetoprojectfolder()) captureFolder = QDir(m_monitor->projectFolder());
else captureFolder = QDir(KdenliveSettings::capturefolder());
QString extension;
if (!m_recVideo->isChecked()) extension = "wav";
......@@ -217,12 +217,15 @@ void RecManager::slotRecord(bool record)
connect(m_captureProcess, &QProcess::readyReadStandardError, this, &RecManager::slotReadProcessInfo);
QString extension = KdenliveSettings::grab_extension();
QString capturePath = KdenliveSettings::capturefolder();
QString path = QUrl(capturePath).path() + QDir::separator() + "capture0000." + extension;
QDir captureFolder;
if (KdenliveSettings::capturetoprojectfolder()) captureFolder = QDir(m_monitor->projectFolder());
else captureFolder = QDir(KdenliveSettings::capturefolder());
QString path = captureFolder.absoluteFilePath("capture0000." + extension);
int i = 1;
while (QFile::exists(path)) {
QString num = QString::number(i).rightJustified(4, '0', false);
path = QUrl(capturePath).path() + QDir::separator() + "capture" + num + '.' + extension;
path = captureFolder.absoluteFilePath("capture" + num + '.' + extension);
++i;
}
m_captureFile = QUrl(path);
......
......@@ -252,7 +252,7 @@ bool ProjectManager::saveFileAs(const QString &outputFileName)
bool ProjectManager::saveFileAs()
{
QFileDialog fd(pCore->window());
fd.setDirectory(m_project->url().isValid() ? m_project->url().path() : m_project->projectFolder().path());
fd.setDirectory(m_project->url().isValid() ? m_project->url().adjusted(QUrl::RemoveFilename).path() : m_project->projectFolder().path());
fd.setMimeTypeFilters(QStringList()<<"application/x-kdenlive");
fd.setAcceptMode(QFileDialog::AcceptSave);
fd.setFileMode(QFileDialog::AnyFile);
......
......@@ -2434,7 +2434,7 @@ bool Render::mltEditEffect(int track, const GenTime &position, EffectsParameterL
if (position < GenTime()) {
return mltEditTrackEffect(track, params);
}
// find filter
Mlt::Service service(m_mltProducer->parent().get_service());
Mlt::Tractor tractor(service);
......@@ -2509,7 +2509,7 @@ bool Render::mltEditEffect(int track, const GenTime &position, EffectsParameterL
for (int j = 0; j < params.count(); ++j) {
filter->set(params.at(j).name().toUtf8().constData(), params.at(j).value().toUtf8().constData());
}
for (int j = 0; j < filtersList.count(); ++j) {
clip->attach(*(filtersList.at(j)));
}
......
......@@ -3134,8 +3134,7 @@ void CustomTrackView::lockTrack(int ix, bool lock, bool requestUpdate)
if (requestUpdate)
emit doTrackLock(ix, lock);
AbstractClipItem *clip = NULL;
QList<QGraphicsItem *> selection = m_scene->items(QRectF(0, (m_timeline->tracksCount() - ix) * m_tracksHeight + m_tracksHeight / 2, sceneRect().width(), m_tracksHeight / 2 - 2));
QList<QGraphicsItem *> selection = m_scene->items(QRectF(0, ix * m_tracksHeight + m_tracksHeight / 2, sceneRect().width(), m_tracksHeight / 2 - 2));
for (int i = 0; i < selection.count(); ++i) {
if (selection.at(i)->type() == GroupWidget && static_cast<AbstractGroupItem*>(selection.at(i)) != m_selectionGroup) {
if (selection.at(i)->parentItem() && m_selectionGroup) {
......@@ -3612,7 +3611,7 @@ void CustomTrackView::completeSpaceOperation(int track, GenTime &timeOffset)
resetSelectionGroup();
for (int i = 0; i < groups.count(); ++i)
{
rebuildGroup(groups.at(i));
rebuildGroup(groups.at(i));
}
clearSelection();
......@@ -4374,11 +4373,15 @@ void CustomTrackView::groupClips(bool group, QList<QGraphicsItem *> itemList, QU
if (itemList.isEmpty()) itemList = scene()->selectedItems();
QList <ItemInfo> clipInfos;
QList <ItemInfo> transitionInfos;
QList<QGraphicsItem *> existingGroups;
// Expand groups
int max = itemList.count();
for (int i = 0; i < max; ++i) {
if (itemList.at(i)->type() == GroupWidget) {
if (!existingGroups.contains(itemList.at(i))) {
existingGroups << itemList.at(i);
}
itemList += itemList.at(i)->childItems();
}
}
......@@ -4393,11 +4396,47 @@ void CustomTrackView::groupClips(bool group, QList<QGraphicsItem *> itemList, QU
}
}
if (clipInfos.count() > 0) {
// break previous groups
QUndoCommand *metaCommand = NULL;
if (group && !command && !existingGroups.isEmpty()) {
metaCommand = new QUndoCommand();
metaCommand->setText(i18n("Group clips"));
}
for (int i = 0; group && i < existingGroups.count(); ++i) {
AbstractGroupItem *grp = static_cast <AbstractGroupItem *>(existingGroups.at(i));
QList <ItemInfo> clipGrpInfos;
QList <ItemInfo> transitionGrpInfos;
QList <QGraphicsItem *> items = grp->childItems();
for (int j = 0; j < items.count(); ++j) {
if (items.at(j)->type() == AVWidget) {
AbstractClipItem *clip = static_cast <AbstractClipItem *>(items.at(j));
if (!clip->isItemLocked()) clipGrpInfos.append(clip->info());
} else if (items.at(j)->type() == TransitionWidget) {
AbstractClipItem *clip = static_cast <AbstractClipItem *>(items.at(j));
if (!clip->isItemLocked()) transitionGrpInfos.append(clip->info());
}
}