You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
(187) |
Apr
(14) |
May
(38) |
Jun
(84) |
Jul
(60) |
Aug
(35) |
Sep
(32) |
Oct
(192) |
Nov
(130) |
Dec
(124) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2009 |
Jan
(159) |
Feb
(59) |
Mar
(120) |
Apr
(136) |
May
(132) |
Jun
(244) |
Jul
(81) |
Aug
(75) |
Sep
(99) |
Oct
(114) |
Nov
(84) |
Dec
(28) |
2010 |
Jan
(73) |
Feb
(84) |
Mar
(19) |
Apr
(41) |
May
(90) |
Jun
(68) |
Jul
(115) |
Aug
(128) |
Sep
(159) |
Oct
(106) |
Nov
(62) |
Dec
(102) |
2011 |
Jan
(142) |
Feb
(93) |
Mar
(65) |
Apr
(39) |
May
(60) |
Jun
(125) |
Jul
(66) |
Aug
(31) |
Sep
(83) |
Oct
(82) |
Nov
(130) |
Dec
(85) |
2012 |
Jan
(60) |
Feb
(34) |
Mar
(63) |
Apr
(59) |
May
(82) |
Jun
(75) |
Jul
(62) |
Aug
(11) |
Sep
(79) |
Oct
(59) |
Nov
(100) |
Dec
(118) |
2013 |
Jan
(48) |
Feb
(193) |
Mar
(54) |
Apr
(41) |
May
(158) |
Jun
(167) |
Jul
(9) |
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
(15) |
2014 |
Jan
(24) |
Feb
(14) |
Mar
(59) |
Apr
(81) |
May
(50) |
Jun
(6) |
Jul
(32) |
Aug
(78) |
Sep
(30) |
Oct
(22) |
Nov
(5) |
Dec
(128) |
2015 |
Jan
(67) |
Feb
(70) |
Mar
(54) |
Apr
(96) |
May
(91) |
Jun
(54) |
Jul
(67) |
Aug
(56) |
Sep
(128) |
Oct
(65) |
Nov
(137) |
Dec
(186) |
2016 |
Jan
(171) |
Feb
(105) |
Mar
(106) |
Apr
(139) |
May
(114) |
Jun
(154) |
Jul
(139) |
Aug
(45) |
Sep
(116) |
Oct
(38) |
Nov
(84) |
Dec
(153) |
2017 |
Jan
(154) |
Feb
(145) |
Mar
(207) |
Apr
(134) |
May
(83) |
Jun
(87) |
Jul
(108) |
Aug
(7) |
Sep
|
Oct
|
Nov
|
Dec
|
From: Jean-Baptiste M. <nu...@kd...> - 2017-08-02 11:39:14
|
Git commit fcefbc431e2261a75282e6a1af5dd19af23d09b0 by Jean-Baptiste Mardelle. Committed on 02/08/2017 at 11:38. Pushed by mardelle into branch 'refactoring_timeline'. Fix loading of subgroups M +5 -0 src/timeline2/model/groupsmodel.cpp M +1 -0 src/timeline2/model/groupsmodel.hpp M +45 -12 src/timeline2/model/timelineitemmodel.cpp https://commits.kde.org/kdenlive/fcefbc431e2261a75282e6a1af5dd19af23d09b0 diff --git a/src/timeline2/model/groupsmodel.cpp b/src/timeline2/model/groupsmodel.cpp index 552ee02a2..bbff3023a 100644 --- a/src/timeline2/model/groupsmodel.cpp +++ b/src/timeline2/model/groupsmodel.cpp @@ -255,3 +255,8 @@ std::unordered_map<int, int>GroupsModel::groupsData() { return m_upLink; } + +std::unordered_map<int, std::unordered_set<int>>GroupsModel::groupsDataDownlink() +{ + return m_downLink; +} diff --git a/src/timeline2/model/groupsmodel.hpp b/src/timeline2/model/groupsmodel.hpp index 363a79aaa..1498cea47 100644 --- a/src/timeline2/model/groupsmodel.hpp +++ b/src/timeline2/model/groupsmodel.hpp @@ -111,6 +111,7 @@ public: /* @brief Returns group data for saving */ std::unordered_map<int, int>groupsData(); + std::unordered_map<int, std::unordered_set<int>>groupsDataDownlink(); protected: /* @brief Destruct a groupItem in the hierarchy. diff --git a/src/timeline2/model/timelineitemmodel.cpp b/src/timeline2/model/timelineitemmodel.cpp index c3742564f..a1e5ab1fc 100644 --- a/src/timeline2/model/timelineitemmodel.cpp +++ b/src/timeline2/model/timelineitemmodel.cpp @@ -405,6 +405,8 @@ const QString TimelineItemModel::getCompositingTransition() const QString TimelineItemModel::groupsData() { std::unordered_map<int, int>upLinks = m_groups->groupsData(); + std::unordered_map<int, std::unordered_set<int>>downLinks = m_groups->groupsDataDownlink(); + QJsonArray list; for (const auto &uplink : upLinks) { QJsonObject currentGroup; @@ -415,7 +417,7 @@ const QString TimelineItemModel::groupsData() // encountering a group currentGroup.insert(QLatin1String("id"), QJsonValue(cid)); currentGroup.insert(QLatin1String("parent"), QJsonValue(uplink.second)); - std::unordered_set<int> children = m_groups->getLeaves(cid); + std::unordered_set<int> children = downLinks[cid]; QJsonArray array; for (const int &child : children) { if (isClip(child) || isComposition(child)) { @@ -440,8 +442,15 @@ bool TimelineItemModel::loadGroups(const QString &groupsData) qDebug() << "Error : Json file should be an array"; return false; } + QMap <int, int> processedIds; auto list = json.array(); - for (const auto &entry : list) { + int i = 0; + while (processedIds.count() < list.count()) { + if (i >= list.count()) { + // loop + i = 0; + } + auto entry = list.at(i); if (!entry.isObject()) { qDebug() << "Warning : Skipping invalid marker data"; continue; @@ -451,21 +460,45 @@ bool TimelineItemModel::loadGroups(const QString &groupsData) qDebug() << "Warning : Skipping invalid empty group"; continue; } + int previousId = entryObj[QLatin1String("id")].toInt(); + int parentId = entryObj[QLatin1String("parent")].toInt(); + if (processedIds.contains(previousId)) { + //already processed + i++; + continue; + } auto clipList = entryObj[QLatin1String("leaves")].toArray(); std::unordered_set<int> ids; - for (int i = 0; i < clipList.count(); i++) { - QString clip = clipList[i].toString(); - if (clip.contains(QStringLiteral(":"))) { - int track = getTrackIndexFromPosition(clip.section(":", 0, 0).toInt() - 1); - int position = clip.section(":", 1, 1).toInt(); - int cid = getClipByPosition(track, position); - ids.insert(cid); + bool validGroup = true; + for (int j = 0; j < clipList.count(); j++) { + if (clipList[j].isString()) { + QString clip = clipList[j].toString(); + if (clip.contains(QStringLiteral(":"))) { + int track = getTrackIndexFromPosition(clip.section(":", 0, 0).toInt() - 1); + int position = clip.section(":", 1, 1).toInt(); + int cid = getClipByPosition(track, position); + ids.insert(cid); + } else { + qDebug()<<"// PARSING UNKNOWN OBJECT IN GROUP: "<<parentId<<" = "<<clip; + } + } else { + // subgroup + int clip = clipList[j].toInt(); + if (!processedIds.contains(clip)) { + // subgroup has not yet been created, so wait until it is + validGroup = false; + break; + } + ids.insert(processedIds.value(clip)); } } - requestClipsGroup(ids, false, false); - return true; + if (validGroup) { + int newGroupId = requestClipsGroup(ids, false, false); + processedIds.insert(previousId, newGroupId); + } + i++; } - return false; + return true; } bool TimelineItemModel::isInSelection(int cid) const |
From: Jean-Baptiste M. <nu...@kd...> - 2017-08-02 06:27:33
|
Git commit cbc6d258599ca6de5e64fc044070ee0ae84b7964 by Jean-Baptiste Mardelle. Committed on 02/08/2017 at 06:26. Pushed by mardelle into branch 'refactoring_timeline'. Fix cut clip from context menu M +4 -4 src/timeline2/view/qml/Clip.qml https://commits.kde.org/kdenlive/cbc6d258599ca6de5e64fc044070ee0ae84b7964 diff --git a/src/timeline2/view/qml/Clip.qml b/src/timeline2/view/qml/Clip.qml index e0e5ef5c5..eecbdb2c1 100644 --- a/src/timeline2/view/qml/Clip.qml +++ b/src/timeline2/view/qml/Clip.qml @@ -701,10 +701,10 @@ Rectangle { } MenuItem { visible: true - text: i18n('Split At Playhead (S)') - onTriggered: timeline.splitClip(trackIndex, index) + text: i18n('Split At Playhead') + onTriggered: timeline.triggerAction('cut_timeline_clip') } - MenuItem { + /*MenuItem { id: mergeItem text: i18n('Merge with next clip') onTriggered: timeline.mergeClipWithNext(trackIndex, index, false) @@ -712,7 +712,7 @@ Rectangle { MenuItem { text: i18n('Rebuild Audio Waveform') onTriggered: timeline.remakeAudioLevels(trackIndex, index) - } + }*/ /*onPopupVisibleChanged: { if (visible && application.OS !== 'OS X' && __popupGeometry.height > 0) { // Try to fix menu running off screen. This only works intermittently. |
From: Luigi T. <nu...@kd...> - 2017-08-01 23:26:41
|
Git commit bb14c0739ccdb7655a14ea079259a756277f1305 by Luigi Toscano. Committed on 01/08/2017 at 23:25. Pushed by ltoscano into branch 'master'. Fix terminology: mimetype(s) -> MIME type(s) M +1 -1 data/effects/README M +1 -1 src/bin/projectitemmodel.h M +4 -4 src/dialogs/clipcreationdialog.cpp M +1 -1 src/dialogs/renderwidget.cpp M +1 -1 src/dialogs/wizard.cpp M +1 -1 src/kdenlivesettings.kcfg M +1 -1 src/monitor/monitor.cpp M +2 -2 src/project/dialogs/archivewidget.cpp M +1 -1 src/project/dialogs/projectsettings.cpp M +2 -2 src/project/dialogs/slideshowclip.cpp M +1 -1 src/project/dialogs/slideshowclip.h M +3 -3 src/project/projectmanager.h M +1 -1 src/timeline/customtrackview.cpp M +2 -2 src/ui/configenv_ui.ui M +1 -1 src/ui/slideshowclip_ui.ui M +1 -1 src/ui/wizardextra_ui.ui https://commits.kde.org/kdenlive/bb14c0739ccdb7655a14ea079259a756277f1305 diff --git a/data/effects/README b/data/effects/README index 1dfe3651e..c7c5433ca 100644 --- a/data/effects/README +++ b/data/effects/README @@ -110,7 +110,7 @@ The rest: - url/path - represented by button to open "file open" dialog - additional attributes: - - "filter": Filter for file extensions. Example : "*.cpp *.cc *.C|C++ Source Files\n*.h *.H|Header files" or as using mimetype: "image/png text/html" + - "filter": Filter for file extensions. Example : "*.cpp *.cc *.C|C++ Source Files\n*.h *.H|Header files" or as using MIME type: "image/png text/html" - "wipe": - special GUI for the wipe transition makes it possible to select a direction of a slide - "addedgeometry": diff --git a/src/bin/projectitemmodel.h b/src/bin/projectitemmodel.h index a5ee2b95f..94522deaa 100644 --- a/src/bin/projectitemmodel.h +++ b/src/bin/projectitemmodel.h @@ -58,7 +58,7 @@ public: int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; /** @brief Mandatory reimplementation from QAbstractItemModel */ int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - /** @brief Returns the mimetype used for Drag actions */ + /** @brief Returns the MIME type used for Drag actions */ QStringList mimeTypes() const Q_DECL_OVERRIDE; /** @brief Create data that will be used for Drag events */ QMimeData *mimeData(const QModelIndexList &indices) const Q_DECL_OVERRIDE; diff --git a/src/dialogs/clipcreationdialog.cpp b/src/dialogs/clipcreationdialog.cpp index f8f4b021f..0c1ef5e66 100644 --- a/src/dialogs/clipcreationdialog.cpp +++ b/src/dialogs/clipcreationdialog.cpp @@ -52,16 +52,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. // static QStringList ClipCreationDialog::getExtensions() { - // Build list of mime types + // Build list of MIME types QStringList mimeTypes = QStringList() << QStringLiteral("application/x-kdenlive") << QStringLiteral("application/x-kdenlivetitle") << QStringLiteral("video/mlt-playlist") << QStringLiteral("text/plain"); - // Video mimes + // Video MIMEs mimeTypes << QStringLiteral("video/x-flv") << QStringLiteral("application/vnd.rn-realmedia") << QStringLiteral("video/x-dv") << QStringLiteral("video/dv") << QStringLiteral("video/x-msvideo") << QStringLiteral("video/x-matroska") << QStringLiteral("video/mpeg") << QStringLiteral("video/ogg") << QStringLiteral("video/x-ms-wmv") << QStringLiteral("video/mp4") << QStringLiteral("video/quicktime") << QStringLiteral("video/webm") << QStringLiteral("video/3gpp") << QStringLiteral("video/mp2t"); - // Audio mimes + // Audio MIMEs mimeTypes << QStringLiteral("audio/x-flac") << QStringLiteral("audio/x-matroska") << QStringLiteral("audio/mp4") << QStringLiteral("audio/mpeg") << QStringLiteral("audio/x-mp3") << QStringLiteral("audio/ogg") << QStringLiteral("audio/x-wav") << QStringLiteral("audio/x-aiff") << QStringLiteral("audio/aiff") << QStringLiteral("application/ogg") << QStringLiteral("application/mxf") << QStringLiteral("application/x-shockwave-flash") << QStringLiteral("audio/ac3"); - // Image mimes + // Image MIMEs mimeTypes << QStringLiteral("image/gif") << QStringLiteral("image/jpeg") << QStringLiteral("image/png") << QStringLiteral("image/x-tga") << QStringLiteral("image/x-bmp") << QStringLiteral("image/svg+xml") << QStringLiteral("image/tiff") << QStringLiteral("image/x-xcf") << QStringLiteral("image/x-xcf-gimp") << QStringLiteral("image/x-vnd.adobe.photoshop") << QStringLiteral("image/x-pcx") << QStringLiteral("image/x-exr") << QStringLiteral("image/x-portable-pixmap") << QStringLiteral("application/x-krita"); QMimeDatabase db; diff --git a/src/dialogs/renderwidget.cpp b/src/dialogs/renderwidget.cpp index 0ea168d01..ad8303830 100644 --- a/src/dialogs/renderwidget.cpp +++ b/src/dialogs/renderwidget.cpp @@ -1196,7 +1196,7 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, KIO::DesktopExecParser parser(*serv, QList<QUrl>() << QUrl::fromLocalFile(QUrl::toPercentEncoding(dest))); render_process_args << parser.resultingArguments().join(QLatin1Char(' ')); } else { - // no service found to play mime type + // no service found to play MIME type //TODO: inform user //errorMessage(PlaybackError, i18n("No service found to play %1", mime.name())); render_process_args << QStringLiteral("-"); diff --git a/src/dialogs/wizard.cpp b/src/dialogs/wizard.cpp index 1bcf86425..268824ad4 100644 --- a/src/dialogs/wizard.cpp +++ b/src/dialogs/wizard.cpp @@ -660,7 +660,7 @@ void Wizard::installExtraMimes(const QString &baseName, const QStringList &globs return; } if (!mime.isValid() || mime.isDefault()) { - qCDebug(KDENLIVE_LOG) << "mimeType " << baseName << " not found"; + qCDebug(KDENLIVE_LOG) << "MIME type " << baseName << " not found"; } else { QStringList extensions = mime.globPatterns(); QString comment = mime.comment(); diff --git a/src/kdenlivesettings.kcfg b/src/kdenlivesettings.kcfg index 55121665f..905b014d8 100644 --- a/src/kdenlivesettings.kcfg +++ b/src/kdenlivesettings.kcfg @@ -823,7 +823,7 @@ </entry> <entry name="slideshowbymime" type="Bool"> - <label>True if slideshow default method is mimetype.</label> + <label>True if slideshow default method is MIME type.</label> <default>true</default> </entry> diff --git a/src/monitor/monitor.cpp b/src/monitor/monitor.cpp index 0830058e2..c6528cc11 100644 --- a/src/monitor/monitor.cpp +++ b/src/monitor/monitor.cpp @@ -915,7 +915,7 @@ Qt::DropActions Monitor::supportedDropActions() const { QStringList Monitor::mimeTypes() const { QStringList qstrList; - // list of accepted mime types for drop + // list of accepted MIME types for drop qstrList.append(QStringLiteral("kdenlive/clip")); return qstrList; } diff --git a/src/project/dialogs/archivewidget.cpp b/src/project/dialogs/archivewidget.cpp index 100f9b796..aadf83d50 100644 --- a/src/project/dialogs/archivewidget.cpp +++ b/src/project/dialogs/archivewidget.cpp @@ -341,7 +341,7 @@ void ArchiveWidget::generateItems(QTreeWidgetItem *parentItem, const QStringList QUrl slideUrl = QUrl::fromLocalFile(file); QDir dir(slideUrl.adjusted(QUrl::RemoveFilename).toLocalFile()); if (slideUrl.fileName().startsWith(QLatin1String(".all."))) { - // mimetype slideshow (for example *.png) + // MIME type slideshow (for example *.png) QStringList filters; // TODO: improve jpeg image detection with extension like jpeg, requires change in MLT image producers filters << QStringLiteral("*.") + slideUrl.fileName().section(QLatin1Char('.'), -1); @@ -425,7 +425,7 @@ void ArchiveWidget::generateItems(QTreeWidgetItem *parentItem, const QMap<QStrin QUrl slideUrl = QUrl::fromLocalFile(file); QDir dir(slideUrl.adjusted(QUrl::RemoveFilename).toLocalFile()); if (slideUrl.fileName().startsWith(QLatin1String(".all."))) { - // mimetype slideshow (for example *.png) + // MIME type slideshow (for example *.png) QStringList filters; // TODO: improve jpeg image detection with extension like jpeg, requires change in MLT image producers filters << QStringLiteral("*.") + slideUrl.fileName().section(QLatin1Char('.'), -1); diff --git a/src/project/dialogs/projectsettings.cpp b/src/project/dialogs/projectsettings.cpp index 3bb354694..54a98b7c3 100644 --- a/src/project/dialogs/projectsettings.cpp +++ b/src/project/dialogs/projectsettings.cpp @@ -569,7 +569,7 @@ QStringList ProjectSettings::extractSlideshowUrls(const QString &url) QString path = QFileInfo(url).absolutePath(); QDir dir(path); if (url.contains(QStringLiteral(".all."))) { - // this is a mime slideshow, like *.jpeg + // this is a MIME slideshow, like *.jpeg QString ext = url.section(QLatin1Char('.'), -1); QStringList filters; filters << QStringLiteral("*.") + ext; diff --git a/src/project/dialogs/slideshowclip.cpp b/src/project/dialogs/slideshowclip.cpp index 9c5f426ab..a983cc671 100644 --- a/src/project/dialogs/slideshowclip.cpp +++ b/src/project/dialogs/slideshowclip.cpp @@ -90,7 +90,7 @@ SlideshowClip::SlideshowClip(const Timecode &tc, QString clipFolder, ProjectClip if (clip) { QString url = clip->url(); if (QFileInfo(url).fileName().startsWith(QLatin1String(".all."))) { - // the image sequence is defined by mimetype + // the image sequence is defined by MIME type m_view.method_mime->setChecked(true); m_view.folder_url->setText(QFileInfo(url).absolutePath()); QString filter = QFileInfo(url).fileName(); @@ -509,7 +509,7 @@ void SlideshowClip::slotUpdateDurationFormat(int ix) void SlideshowClip::slotMethodChanged(bool active) { if (active) { - // User wants mimetype image sequence + // User wants MIME type image sequence m_view.clip_duration->setText(m_timecode.reformatSeparators(KdenliveSettings::image_duration())); m_view.stackedWidget->setCurrentIndex(0); KdenliveSettings::setSlideshowbymime(true); diff --git a/src/project/dialogs/slideshowclip.h b/src/project/dialogs/slideshowclip.h index ec45ef7dd..3fccf70d8 100644 --- a/src/project/dialogs/slideshowclip.h +++ b/src/project/dialogs/slideshowclip.h @@ -63,7 +63,7 @@ private slots: void slotUpdateDurationFormat(int ix); void slotGenerateThumbs(); void slotSetPixmap(const KFileItem &fileItem, const QPixmap &pix); - /** @brief Display correct widget depenging on user choice (mimetype or pattern method). */ + /** @brief Display correct widget depenging on user choice (MIME type or pattern method). */ void slotMethodChanged(bool active); private: diff --git a/src/project/projectmanager.h b/src/project/projectmanager.h index 88a825eb3..25463685b 100644 --- a/src/project/projectmanager.h +++ b/src/project/projectmanager.h @@ -132,9 +132,9 @@ signals: // void projectOpened(Project *project); private: - /** @brief Checks that the Kdenlive mime type is correctly installed. - * @param open If set to true, this will return the mimetype allowed for file opening (adds .tar.gz format) - * @return The mimetype */ + /** @brief Checks that the Kdenlive MIME type is correctly installed. + * @param open If set to true, this will return the MIME type allowed for file opening (adds .tar.gz format) + * @return The MIME type */ QString getMimeType(bool open = true); /** @brief checks if autoback files exists, recovers from it if user says yes, returns true if files were recovered. */ bool checkForBackupFile(const QUrl &url); diff --git a/src/timeline/customtrackview.cpp b/src/timeline/customtrackview.cpp index 273fff9f1..a59267df4 100644 --- a/src/timeline/customtrackview.cpp +++ b/src/timeline/customtrackview.cpp @@ -3655,7 +3655,7 @@ void CustomTrackView::adjustTimelineTransitions(TimelineMode::EditMode mode, Tra QStringList CustomTrackView::mimeTypes() const { QStringList qstrList; - // list of accepted mime types for drop + // list of accepted MIME types for drop qstrList.append(QStringLiteral("text/plain")); qstrList.append(QStringLiteral("kdenlive/producerslist")); qstrList.append(QStringLiteral("kdenlive/clip")); diff --git a/src/ui/configenv_ui.ui b/src/ui/configenv_ui.ui index 60a788876..663a4350a 100644 --- a/src/ui/configenv_ui.ui +++ b/src/ui/configenv_ui.ui @@ -253,7 +253,7 @@ <item row="0" column="0"> <widget class="QLabel" name="label_5"> <property name="text"> - <string>Additional clip mime types</string> + <string>Additional clip MIME types</string> </property> </widget> </item> @@ -267,7 +267,7 @@ <item row="2" column="0"> <widget class="QLabel" name="label_12"> <property name="text"> - <string>Supported clip mime types</string> + <string>Supported clip MIME types</string> </property> </widget> </item> diff --git a/src/ui/slideshowclip_ui.ui b/src/ui/slideshowclip_ui.ui index 7448b6dc5..ce60a8fc4 100644 --- a/src/ui/slideshowclip_ui.ui +++ b/src/ui/slideshowclip_ui.ui @@ -33,7 +33,7 @@ <item row="0" column="0"> <widget class="QRadioButton" name="method_mime"> <property name="text"> - <string>&Mimetype</string> + <string>&MIME type</string> </property> <property name="checked"> <bool>true</bool> diff --git a/src/ui/wizardextra_ui.ui b/src/ui/wizardextra_ui.ui index 68ae0cf12..9bc8acfe4 100644 --- a/src/ui/wizardextra_ui.ui +++ b/src/ui/wizardextra_ui.ui @@ -63,7 +63,7 @@ <item row="4" column="0" > <widget class="QCheckBox" name="installmimes" > <property name="text" > - <string>Install extra video mimetypes</string> + <string>Install extra video MIME types</string> </property> <property name="checked" > <bool>true</bool> |
From: Jean-Baptiste M. <nu...@kd...> - 2017-08-01 15:04:29
|
Git commit 2c09ea4a57c4d71898671a7c4dbf8dd6c33da46a by Jean-Baptiste Mardelle. Committed on 01/08/2017 at 15:03. Pushed by mardelle into branch 'refactoring_timeline'. Load/save of groups (subgroups not working yet) M +2 -2 src/project/projectmanager.cpp M +2 -20 src/timeline2/model/groupsmodel.cpp M +4 -1 src/timeline2/model/groupsmodel.hpp M +66 -1 src/timeline2/model/timelineitemmodel.cpp M +1 -0 src/timeline2/model/timelineitemmodel.hpp https://commits.kde.org/kdenlive/2c09ea4a57c4d71898671a7c4dbf8dd6c33da46a diff --git a/src/project/projectmanager.cpp b/src/project/projectmanager.cpp index 970cef78f..b817fef19 100644 --- a/src/project/projectmanager.cpp +++ b/src/project/projectmanager.cpp @@ -741,7 +741,7 @@ void ProjectManager::prepareSave() // TODO REFAC: save target tracks, preview chunks and guides pCore->binController()->saveDocumentProperties(m_project->documentProperties(), m_project->metadata(), m_project->getGuideModel()); pCore->binController()->saveProperty(QStringLiteral("kdenlive:documentnotes"), documentNotes()); - pCore->binController()->saveProperty(QStringLiteral("kdenlive:groups"), m_mainTimelineModel->groupsData()); + pCore->binController()->saveProperty(QStringLiteral("kdenlive:docproperties.groups"), m_mainTimelineModel->groupsData()); } void ProjectManager::slotResetProfiles() @@ -865,7 +865,7 @@ void ProjectManager::updateTimeline(int pos) Mlt::Tractor tractor(s); m_mainTimelineModel = TimelineItemModel::construct(&pCore->getCurrentProfile()->profile(), m_project->getGuideModel(), m_project->commandStack()); constructTimelineFromMelt(m_mainTimelineModel, tractor); - + m_mainTimelineModel->loadGroups(m_project->getDocumentProperty(QStringLiteral("groups"))); m_project->loadThumbs(); pCore->monitorManager()->projectMonitor()->setProducer(m_mainTimelineModel->producer(), pos); diff --git a/src/timeline2/model/groupsmodel.cpp b/src/timeline2/model/groupsmodel.cpp index b09deffb8..552ee02a2 100644 --- a/src/timeline2/model/groupsmodel.cpp +++ b/src/timeline2/model/groupsmodel.cpp @@ -24,9 +24,6 @@ #include "timelineitemmodel.hpp" #include <QDebug> #include <QModelIndex> -#include <QJsonArray> -#include <QJsonDocument> -#include <QJsonObject> #include <queue> #include <utility> @@ -254,22 +251,7 @@ void GroupsModel::removeFromGroup(int id) m_upLink[id] = -1; } -const QString GroupsModel::toJson() const +std::unordered_map<int, int>GroupsModel::groupsData() { - READ_LOCK(); - QJsonArray list; - for (const auto &uplink : m_upLink) { - QJsonObject currentGroup; - currentGroup.insert(QLatin1String("id"), QJsonValue(uplink.first)); - currentGroup.insert(QLatin1String("parent"), QJsonValue(uplink.second)); - std::unordered_set<int> children = getLeaves(uplink.first); - QJsonArray array; - for (const int &child : children) { - array.append(child); - } - currentGroup.insert(QLatin1String("leaves"), QJsonValue(array)); - list.push_back(currentGroup); - } - QJsonDocument json(list); - return QString(json.toJson()); + return m_upLink; } diff --git a/src/timeline2/model/groupsmodel.hpp b/src/timeline2/model/groupsmodel.hpp index b3d43ba23..363a79aaa 100644 --- a/src/timeline2/model/groupsmodel.hpp +++ b/src/timeline2/model/groupsmodel.hpp @@ -49,7 +49,6 @@ public: Returns the id of the new group, or -1 on error. */ int groupItems(const std::unordered_set<int> &ids, Fun &undo, Fun &redo, bool temporarySelection = false); - const QString toJson() const; protected: /* Lambda version */ @@ -109,6 +108,10 @@ public: */ std::unordered_set<int> getDirectChildren(int id) const; + /* @brief Returns group data for saving + */ + std::unordered_map<int, int>groupsData(); + protected: /* @brief Destruct a groupItem in the hierarchy. All its children will become their own roots diff --git a/src/timeline2/model/timelineitemmodel.cpp b/src/timeline2/model/timelineitemmodel.cpp index 6b5782264..c3742564f 100644 --- a/src/timeline2/model/timelineitemmodel.cpp +++ b/src/timeline2/model/timelineitemmodel.cpp @@ -38,6 +38,10 @@ #include <mlt++/MltTransition.h> #include <mlt++/MltField.h> +#include <QJsonArray> +#include <QJsonDocument> +#include <QJsonObject> + #include <utility> TimelineItemModel::TimelineItemModel(Mlt::Profile *profile, std::weak_ptr<DocUndoStack> undo_stack) @@ -400,7 +404,68 @@ const QString TimelineItemModel::getCompositingTransition() const QString TimelineItemModel::groupsData() { - return m_groups->toJson(); + std::unordered_map<int, int>upLinks = m_groups->groupsData(); + QJsonArray list; + for (const auto &uplink : upLinks) { + QJsonObject currentGroup; + int cid = uplink.first; + if (isClip(cid) || isComposition(cid)) { + continue; + } else { + // encountering a group + currentGroup.insert(QLatin1String("id"), QJsonValue(cid)); + currentGroup.insert(QLatin1String("parent"), QJsonValue(uplink.second)); + std::unordered_set<int> children = m_groups->getLeaves(cid); + QJsonArray array; + for (const int &child : children) { + if (isClip(child) || isComposition(child)) { + array.append(QString("%1:%2").arg(getTrackMltIndex(getItemTrackId(child))).arg(getItemPosition(child))); + } else { + // this is a subgroup + array.append(child); + } + } + currentGroup.insert(QLatin1String("leaves"), QJsonValue(array)); + } + list.push_back(currentGroup); + } + QJsonDocument json(list); + return QString(json.toJson()); +} + +bool TimelineItemModel::loadGroups(const QString &groupsData) +{ + auto json = QJsonDocument::fromJson(groupsData.toUtf8()); + if (!json.isArray()) { + qDebug() << "Error : Json file should be an array"; + return false; + } + auto list = json.array(); + for (const auto &entry : list) { + if (!entry.isObject()) { + qDebug() << "Warning : Skipping invalid marker data"; + continue; + } + auto entryObj = entry.toObject(); + if (!entryObj.contains(QLatin1String("leaves"))) { + qDebug() << "Warning : Skipping invalid empty group"; + continue; + } + auto clipList = entryObj[QLatin1String("leaves")].toArray(); + std::unordered_set<int> ids; + for (int i = 0; i < clipList.count(); i++) { + QString clip = clipList[i].toString(); + if (clip.contains(QStringLiteral(":"))) { + int track = getTrackIndexFromPosition(clip.section(":", 0, 0).toInt() - 1); + int position = clip.section(":", 1, 1).toInt(); + int cid = getClipByPosition(track, position); + ids.insert(cid); + } + } + requestClipsGroup(ids, false, false); + return true; + } + return false; } bool TimelineItemModel::isInSelection(int cid) const diff --git a/src/timeline2/model/timelineitemmodel.hpp b/src/timeline2/model/timelineitemmodel.hpp index 1bca643ce..66ffea4ca 100644 --- a/src/timeline2/model/timelineitemmodel.hpp +++ b/src/timeline2/model/timelineitemmodel.hpp @@ -89,6 +89,7 @@ public: void buildTrackCompositing(); static const QString getCompositingTransition(); const QString groupsData(); + bool loadGroups(const QString &groupsData); virtual void _beginRemoveRows(const QModelIndex &, int, int) override; virtual void _beginInsertRows(const QModelIndex &, int, int) override; |
From: Jean-Baptiste M. <nu...@kd...> - 2017-08-01 15:04:28
|
Git commit a343393adc8b1b4fdcf8ab715f2319beedb03ad1 by Jean-Baptiste Mardelle. Committed on 01/08/2017 at 14:59. Pushed by mardelle into branch 'refactoring_timeline'. Fix timeline clips created with wrong id M +1 -1 src/timeline2/model/clipmodel.cpp https://commits.kde.org/kdenlive/a343393adc8b1b4fdcf8ab715f2319beedb03ad1 diff --git a/src/timeline2/model/clipmodel.cpp b/src/timeline2/model/clipmodel.cpp index f7200a311..6feb6cbf8 100644 --- a/src/timeline2/model/clipmodel.cpp +++ b/src/timeline2/model/clipmodel.cpp @@ -42,7 +42,7 @@ ClipModel::ClipModel(std::shared_ptr<TimelineModel> parent, std::shared_ptr<Mlt: , m_binClipId(binClipId) { m_producer->set("kdenlive:id", binClipId.toUtf8().constData()); - m_producer->set("_kdenlive_cid", id); + m_producer->set("_kdenlive_cid", getId()); std::shared_ptr<ProjectClip> binClip = pCore->projectItemModel()->getClipByBinID(m_binClipId); if (binClip) { m_endlessResize = !binClip->hasLimitedDuration(); |
From: Jean-Baptiste M. <nu...@kd...> - 2017-08-01 08:49:49
|
Git commit d4425057f71db02cf77fdd62f026289a339fdbe1 by Jean-Baptiste Mardelle. Committed on 01/08/2017 at 07:50. Pushed by mardelle into branch 'refactoring_timeline'. Fix timeline grouping behavior, first steps to save groups M +5 -5 src/doc/kdenlivedoc.cpp M +2 -1 src/doc/kdenlivedoc.h M +1 -1 src/project/projectmanager.cpp M +1 -78 src/timeline/customtrackview.cpp M +35 -12 src/timeline2/model/groupsmodel.cpp M +6 -4 src/timeline2/model/groupsmodel.hpp M +15 -2 src/timeline2/model/timelineitemmodel.cpp M +4 -0 src/timeline2/model/timelineitemmodel.hpp M +14 -8 src/timeline2/model/timelinemodel.cpp M +3 -2 src/timeline2/model/timelinemodel.hpp M +9 -2 src/timeline2/view/qml/Clip.qml M +1 -1 src/timeline2/view/qml/Composition.qml M +2 -1 src/timeline2/view/qml/timeline.qml M +0 -7 src/timeline2/view/timelinecontroller.cpp M +0 -2 src/timeline2/view/timelinecontroller.h https://commits.kde.org/kdenlive/d4425057f71db02cf77fdd62f026289a339fdbe1 diff --git a/src/doc/kdenlivedoc.cpp b/src/doc/kdenlivedoc.cpp index 02fbf02a7..06c9c9e3b 100644 --- a/src/doc/kdenlivedoc.cpp +++ b/src/doc/kdenlivedoc.cpp @@ -583,11 +583,6 @@ ClipManager *KdenliveDoc::clipManager() return m_clipManager; } -QString KdenliveDoc::groupsXml() const -{ - return m_clipManager->groupsXml(); -} - QString KdenliveDoc::projectTempFolder() const { if (m_projectFolder.isEmpty()) { @@ -1699,6 +1694,11 @@ void KdenliveDoc::guidesChanged() m_documentProperties[QStringLiteral("guides")] = m_guideModel->toJson(); } +void KdenliveDoc::groupsChanged(const QString &groups) +{ + m_documentProperties[QStringLiteral("groups")] = groups; +} + const QString KdenliveDoc::documentRoot() const { return m_documentRoot; diff --git a/src/doc/kdenlivedoc.h b/src/doc/kdenlivedoc.h index 9f83ab722..899555ca1 100644 --- a/src/doc/kdenlivedoc.h +++ b/src/doc/kdenlivedoc.h @@ -77,7 +77,6 @@ public: QDomDocument toXml(); std::shared_ptr<DocUndoStack> commandStack(); ClipManager *clipManager(); - QString groupsXml() const; void deleteClip(const QString &clipId, ClipType type, const QString &url); int getFramePos(const QString &duration); @@ -225,6 +224,8 @@ public slots: /** @brief Saves the current project at the autosave location. * @description The autosave files are in ~/.kde/data/stalefiles/kdenlive/ */ void slotAutoSave(); + /** @brief Groups were changed, save to MLT. */ + void groupsChanged(const QString &groups); private slots: void slotClipModified(const QString &path); diff --git a/src/project/projectmanager.cpp b/src/project/projectmanager.cpp index e5395f82a..970cef78f 100644 --- a/src/project/projectmanager.cpp +++ b/src/project/projectmanager.cpp @@ -741,7 +741,7 @@ void ProjectManager::prepareSave() // TODO REFAC: save target tracks, preview chunks and guides pCore->binController()->saveDocumentProperties(m_project->documentProperties(), m_project->metadata(), m_project->getGuideModel()); pCore->binController()->saveProperty(QStringLiteral("kdenlive:documentnotes"), documentNotes()); - pCore->binController()->saveProperty(QStringLiteral("kdenlive:clipgroups"), m_project->groupsXml()); + pCore->binController()->saveProperty(QStringLiteral("kdenlive:groups"), m_mainTimelineModel->groupsData()); } void ProjectManager::slotResetProfiles() diff --git a/src/timeline/customtrackview.cpp b/src/timeline/customtrackview.cpp index c75543363..fa1394c4e 100644 --- a/src/timeline/customtrackview.cpp +++ b/src/timeline/customtrackview.cpp @@ -322,29 +322,7 @@ void CustomTrackView::updateSceneFrameWidth(double fpsChanged) { int frameWidth = getFrameWidth(); if (fpsChanged != 1.0 && m_projectDuration > 0) { - // try to remember and rebuild groups - // Prepare groups for reload - QDomDocument doc; - doc.setContent(m_document->groupsXml()); - QDomNodeList groups; - if (!doc.isNull()) { - groups = doc.documentElement().elementsByTagName(QStringLiteral("group")); - for (int nodeindex = 0; nodeindex < groups.count(); ++nodeindex) { - QDomNode grp = groups.item(nodeindex); - QDomNodeList nodes = grp.childNodes(); - for (int itemindex = 0; itemindex < nodes.count(); ++itemindex) { - QDomElement elem = nodes.item(itemindex).toElement(); - if (!elem.hasAttribute(QStringLiteral("position"))) { - continue; - } - int pos = elem.attribute(QStringLiteral("position")).toInt(); - elem.setAttribute(QStringLiteral("position"), rintf(pos * fpsChanged)); - } - } - } - clearSelection(); - reloadTimeline(); - loadGroups(groups); + } else { QList<QGraphicsItem *> itemList = items(); ClipItem *item; @@ -3749,30 +3727,6 @@ void CustomTrackView::addTrack(const TrackInfo &type, int ix) if (ix <= m_timeline->audioTarget) { m_timeline->audioTarget++; } - // Prepare groups for reload - QDomDocument doc; - doc.setContent(m_document->groupsXml()); - QDomNodeList groups; - if (!doc.isNull()) { - groups = doc.documentElement().elementsByTagName(QStringLiteral("group")); - for (int nodeindex = 0; nodeindex < groups.count(); ++nodeindex) { - QDomNode grp = groups.item(nodeindex); - QDomNodeList nodes = grp.childNodes(); - for (int itemindex = 0; itemindex < nodes.count(); ++itemindex) { - QDomElement elem = nodes.item(itemindex).toElement(); - if (!elem.hasAttribute(QStringLiteral("track"))) { - continue; - } - int track = elem.attribute(QStringLiteral("track")).toInt(); - if (track < ix) { - // No change - continue; - } else { - elem.setAttribute(QStringLiteral("track"), track + 1); - } - } - } - } // insert track in MLT's playlist transitionInfos = m_document->renderer()->mltInsertTrack(ix, type.trackName, type.type == VideoTrack); Mlt::Tractor *tractor = m_document->renderer()->lockService(); @@ -3781,7 +3735,6 @@ void CustomTrackView::addTrack(const TrackInfo &type, int ix) reloadTimeline(); // Refresh track compositing and audio mix m_timeline->refreshTransitions(); - loadGroups(groups); } void CustomTrackView::reloadTimeline() @@ -3842,35 +3795,6 @@ void CustomTrackView::removeTrack(int ix) field->disconnect_service(*mixTr.data()); } } - // Prepare groups for reload - QDomDocument doc; - doc.setContent(m_document->groupsXml()); - QDomNodeList groups; - if (!doc.isNull()) { - groups = doc.documentElement().elementsByTagName(QStringLiteral("group")); - for (int nodeindex = 0; nodeindex < groups.count(); ++nodeindex) { - QDomNode grp = groups.item(nodeindex); - QDomNodeList nodes = grp.childNodes(); - for (int itemindex = 0; itemindex < nodes.count(); ++itemindex) { - QDomElement elem = nodes.item(itemindex).toElement(); - if (!elem.hasAttribute(QStringLiteral("track"))) { - continue; - } - int track = elem.attribute(QStringLiteral("track")).toInt(); - if (track < ix) { - // No change - continue; - } else if (track > ix) { - elem.setAttribute(QStringLiteral("track"), track - 1); - } else { - // track == ix - // A grouped item was on deleted track, remove it from group - elem.setAttribute(QStringLiteral("track"), -1); - } - } - } - } - // Manually remove all transitions issued from track ix, otherwise MLT will relocate it to another track m_timeline->transitionHandler->deleteTrackTransitions(ix); @@ -3880,7 +3804,6 @@ void CustomTrackView::removeTrack(int ix) reloadTimeline(); // Refresh track compositing and audio mix m_timeline->refreshTransitions(); - loadGroups(groups); } void CustomTrackView::configTracks(const QList<TrackInfo> &trackInfos) diff --git a/src/timeline2/model/groupsmodel.cpp b/src/timeline2/model/groupsmodel.cpp index 5ab913e4c..b09deffb8 100644 --- a/src/timeline2/model/groupsmodel.cpp +++ b/src/timeline2/model/groupsmodel.cpp @@ -24,19 +24,22 @@ #include "timelineitemmodel.hpp" #include <QDebug> #include <QModelIndex> +#include <QJsonArray> +#include <QJsonDocument> +#include <QJsonObject> #include <queue> #include <utility> -GroupsModel::GroupsModel(std::weak_ptr<TimelineItemModel> parent) - : m_parent(std::move(parent)) +GroupsModel::GroupsModel(std::weak_ptr<TimelineItemModel> parent) : + m_parent(std::move(parent)) , m_lock(QReadWriteLock::Recursive) { } -Fun GroupsModel::groupItems_lambda(int gid, const std::unordered_set<int> &ids) +Fun GroupsModel::groupItems_lambda(int gid, const std::unordered_set<int> &ids, bool temporarySelection) { QWriteLocker locker(&m_lock); - return [gid, ids, this]() { + return [gid, ids, temporarySelection, this]() { createGroupItem(gid); Q_ASSERT(m_groupIds.count(gid) == 0); @@ -53,7 +56,7 @@ Fun GroupsModel::groupItems_lambda(int gid, const std::unordered_set<int> &ids) std::transform(ids.begin(), ids.end(), std::inserter(roots, roots.begin()), [&](int id) { return getRootId(id); }); for (int id : roots) { setGroup(getRootId(id), gid); - if (ptr->isClip(id)) { + if (!temporarySelection && ptr->isClip(id)) { QModelIndex ix = ptr->makeClipIndexFromID(id); ptr->dataChanged(ix, ix, {TimelineItemModel::GroupedRole}); } @@ -62,7 +65,7 @@ Fun GroupsModel::groupItems_lambda(int gid, const std::unordered_set<int> &ids) }; } -int GroupsModel::groupItems(const std::unordered_set<int> &ids, Fun &undo, Fun &redo) +int GroupsModel::groupItems(const std::unordered_set<int> &ids, Fun &undo, Fun &redo, bool temporarySelection) { QWriteLocker locker(&m_lock); Q_ASSERT(!ids.empty()); @@ -71,7 +74,7 @@ int GroupsModel::groupItems(const std::unordered_set<int> &ids, Fun &undo, Fun & return *(ids.begin()); } int gid = TimelineModel::getNextId(); - auto operation = groupItems_lambda(gid, ids); + auto operation = groupItems_lambda(gid, ids, temporarySelection); if (operation()) { auto reverse = destructGroupItem_lambda(gid); UPDATE_UNDO_REDO(operation, reverse, undo, redo); @@ -80,7 +83,7 @@ int GroupsModel::groupItems(const std::unordered_set<int> &ids, Fun &undo, Fun & return -1; } -bool GroupsModel::ungroupItem(int id, Fun &undo, Fun &redo) +bool GroupsModel::ungroupItem(int id, Fun &undo, Fun &redo, bool temporarySelection) { QWriteLocker locker(&m_lock); int gid = getRootId(id); @@ -89,7 +92,7 @@ bool GroupsModel::ungroupItem(int id, Fun &undo, Fun &redo) return false; } - return destructGroupItem(gid, true, undo, redo); + return destructGroupItem(gid, true, undo, redo, temporarySelection); } void GroupsModel::createGroupItem(int id) @@ -129,7 +132,7 @@ Fun GroupsModel::destructGroupItem_lambda(int id) }; } -bool GroupsModel::destructGroupItem(int id, bool deleteOrphan, Fun &undo, Fun &redo) +bool GroupsModel::destructGroupItem(int id, bool deleteOrphan, Fun &undo, Fun &redo, bool temporarySelection) { QWriteLocker locker(&m_lock); Q_ASSERT(m_upLink.count(id) > 0); @@ -137,10 +140,10 @@ bool GroupsModel::destructGroupItem(int id, bool deleteOrphan, Fun &undo, Fun &r auto old_children = m_downLink[id]; auto operation = destructGroupItem_lambda(id); if (operation()) { - auto reverse = groupItems_lambda(id, old_children); + auto reverse = groupItems_lambda(id, old_children, temporarySelection); UPDATE_UNDO_REDO(operation, reverse, undo, redo); if (parent != -1 && m_downLink[parent].empty() && deleteOrphan) { - return destructGroupItem(parent, true, undo, redo); + return destructGroupItem(parent, true, undo, redo, temporarySelection); } return true; } @@ -250,3 +253,23 @@ void GroupsModel::removeFromGroup(int id) } m_upLink[id] = -1; } + +const QString GroupsModel::toJson() const +{ + READ_LOCK(); + QJsonArray list; + for (const auto &uplink : m_upLink) { + QJsonObject currentGroup; + currentGroup.insert(QLatin1String("id"), QJsonValue(uplink.first)); + currentGroup.insert(QLatin1String("parent"), QJsonValue(uplink.second)); + std::unordered_set<int> children = getLeaves(uplink.first); + QJsonArray array; + for (const int &child : children) { + array.append(child); + } + currentGroup.insert(QLatin1String("leaves"), QJsonValue(array)); + list.push_back(currentGroup); + } + QJsonDocument json(list); + return QString(json.toJson()); +} diff --git a/src/timeline2/model/groupsmodel.hpp b/src/timeline2/model/groupsmodel.hpp index 63ee9424f..b3d43ba23 100644 --- a/src/timeline2/model/groupsmodel.hpp +++ b/src/timeline2/model/groupsmodel.hpp @@ -35,6 +35,7 @@ class TimelineItemModel; */ class GroupsModel { + public: GroupsModel() = delete; GroupsModel(std::weak_ptr<TimelineItemModel> parent); @@ -47,11 +48,12 @@ public: @param redo Lambda function containing the current redo queue. Will be updated with current operation Returns the id of the new group, or -1 on error. */ - int groupItems(const std::unordered_set<int> &ids, Fun &undo, Fun &redo); + int groupItems(const std::unordered_set<int> &ids, Fun &undo, Fun &redo, bool temporarySelection = false); + const QString toJson() const; protected: /* Lambda version */ - Fun groupItems_lambda(int gid, const std::unordered_set<int> &ids); + Fun groupItems_lambda(int gid, const std::unordered_set<int> &ids, bool temporarySelection = false); public: /* Deletes the topmost group containing given element @@ -61,7 +63,7 @@ public: @param undo Lambda function containing the current undo stack. Will be updated with current operation @param redo Lambda function containing the current redo queue. Will be updated with current operation */ - bool ungroupItem(int id, Fun &undo, Fun &redo); + bool ungroupItem(int id, Fun &undo, Fun &redo, bool temporarySelection = false); /* @brief Create a groupItem in the hierarchy. Initially it is not part of a group @param id id of the groupItem @@ -116,7 +118,7 @@ protected: @param undo Lambda function containing the current undo stack. Will be updated with current operation @param redo Lambda function containing the current redo queue. Will be updated with current operation */ - bool destructGroupItem(int id, bool deleteOrphan, Fun &undo, Fun &redo); + bool destructGroupItem(int id, bool deleteOrphan, Fun &undo, Fun &redo, bool temporarySelection = false); /* Lambda version */ Fun destructGroupItem_lambda(int id); diff --git a/src/timeline2/model/timelineitemmodel.cpp b/src/timeline2/model/timelineitemmodel.cpp index 7763dc6af..6b5782264 100644 --- a/src/timeline2/model/timelineitemmodel.cpp +++ b/src/timeline2/model/timelineitemmodel.cpp @@ -241,7 +241,7 @@ QVariant TimelineItemModel::data(const QModelIndex &index, int role) const case DurationRole: return clip->getPlaytime(); case GroupedRole: - return m_groups->isInGroup(id); + return (m_groups->isInGroup(id) && !isInSelection(id)); case InPointRole: return clip->getIn(); case OutPointRole: @@ -398,6 +398,20 @@ const QString TimelineItemModel::getCompositingTransition() return QString(); } +const QString TimelineItemModel::groupsData() +{ + return m_groups->toJson(); +} + +bool TimelineItemModel::isInSelection(int cid) const +{ + if (m_temporarySelectionGroup == -1 || !m_groups->isInGroup(cid)) { + return false; + } + bool res = (m_groups->getRootId(cid) == m_temporarySelectionGroup); + return res; +} + void TimelineItemModel::notifyChange(const QModelIndex &topleft, const QModelIndex &bottomright, bool start, bool duration, bool updateThumb) { QVector<int> roles; @@ -447,4 +461,3 @@ void TimelineItemModel::_resetView() beginResetModel(); endResetModel(); } - diff --git a/src/timeline2/model/timelineitemmodel.hpp b/src/timeline2/model/timelineitemmodel.hpp index 3e53bbe84..1bca643ce 100644 --- a/src/timeline2/model/timelineitemmodel.hpp +++ b/src/timeline2/model/timelineitemmodel.hpp @@ -63,6 +63,9 @@ protected: /* @brief this constructor should not be called. Call the static construct instead */ TimelineItemModel(Mlt::Profile *profile, std::weak_ptr<DocUndoStack> undo_stack); + /* @brief returns true if clip is in temporary selection group. + */ + bool isInSelection(int cid) const; public: ~TimelineItemModel(); @@ -85,6 +88,7 @@ public: void notifyChange(const QModelIndex &topleft, const QModelIndex &bottomright, QVector<int> roles) override; void buildTrackCompositing(); static const QString getCompositingTransition(); + const QString groupsData(); virtual void _beginRemoveRows(const QModelIndex &, int, int) override; virtual void _beginInsertRows(const QModelIndex &, int, int) override; diff --git a/src/timeline2/model/timelinemodel.cpp b/src/timeline2/model/timelinemodel.cpp index 45b3d5c45..35a8c6577 100644 --- a/src/timeline2/model/timelinemodel.cpp +++ b/src/timeline2/model/timelinemodel.cpp @@ -787,19 +787,21 @@ int TimelineModel::requestClipsGroup(const std::unordered_set<int> &ids, bool lo QWriteLocker locker(&m_lock); Fun undo = []() { return true; }; Fun redo = []() { return true; }; - if (temporarySelection && m_temporarySelectionGroup > -1) { - requestClipUngroup(m_temporarySelectionGroup, undo, redo); + if (m_temporarySelectionGroup > -1) { + requestClipUngroup(m_temporarySelectionGroup, undo, redo, true); m_temporarySelectionGroup = -1; } - int result = requestClipsGroup(ids, undo, redo); - if (result > -1 && logUndo) { + int result = requestClipsGroup(ids, undo, redo, temporarySelection); + if (temporarySelection) { m_temporarySelectionGroup = result; + } + if (result > -1 && logUndo) { PUSH_UNDO(undo, redo, i18n("Group clips")); } return result; } -int TimelineModel::requestClipsGroup(const std::unordered_set<int> &ids, Fun &undo, Fun &redo) +int TimelineModel::requestClipsGroup(const std::unordered_set<int> &ids, Fun &undo, Fun &redo, bool temporarySelection) { #ifdef LOGGING std::stringstream group; @@ -827,7 +829,11 @@ int TimelineModel::requestClipsGroup(const std::unordered_set<int> &ids, Fun &un return -1; } } - int groupId = m_groups->groupItems(ids, undo, redo); + int groupId = m_groups->groupItems(ids, undo, redo, temporarySelection); + if (temporarySelection && *(ids.begin()) == groupId) { + // only one element selected, no group created + return -1; + } return groupId; } @@ -846,9 +852,9 @@ bool TimelineModel::requestClipUngroup(int id, bool logUndo) return result; } -bool TimelineModel::requestClipUngroup(int id, Fun &undo, Fun &redo) +bool TimelineModel::requestClipUngroup(int id, Fun &undo, Fun &redo, bool temporarySelection) { - return m_groups->ungroupItem(id, undo, redo); + return m_groups->ungroupItem(id, undo, redo, temporarySelection); } bool TimelineModel::requestTrackInsertion(int position, int &id) diff --git a/src/timeline2/model/timelinemodel.hpp b/src/timeline2/model/timelinemodel.hpp index ca0c63752..b9a50f5e1 100644 --- a/src/timeline2/model/timelinemodel.hpp +++ b/src/timeline2/model/timelinemodel.hpp @@ -366,7 +366,7 @@ public: @param ids Set of ids to group */ int requestClipsGroup(const std::unordered_set<int> &ids, bool logUndo = true, bool temporarySelection = false); - int requestClipsGroup(const std::unordered_set<int> &ids, Fun &undo, Fun &redo); + int requestClipsGroup(const std::unordered_set<int> &ids, Fun &undo, Fun &redo, bool temporarySelection = false); /* @brief Destruct the topmost group containing clip This action is undoable @@ -375,7 +375,7 @@ public: */ bool requestClipUngroup(int id, bool logUndo = true); /* Same function, but accumulates undo and redo*/ - bool requestClipUngroup(int id, Fun &undo, Fun &redo); + bool requestClipUngroup(int id, Fun &undo, Fun &redo, bool temporarySelection = false); /* @brief Create a track at given position This action is undoable @@ -604,5 +604,6 @@ protected: virtual QModelIndex makeCompositionIndexFromID(int) const = 0; virtual QModelIndex makeTrackIndexFromID(int) const = 0; virtual void _resetView() = 0; + }; #endif diff --git a/src/timeline2/view/qml/Clip.qml b/src/timeline2/view/qml/Clip.qml index faef8a55d..e0e5ef5c5 100644 --- a/src/timeline2/view/qml/Clip.qml +++ b/src/timeline2/view/qml/Clip.qml @@ -182,14 +182,21 @@ Rectangle { root.stopScrolling = false parent.y = 0 var delta = parent.x - startX + var moved = false if (Math.abs(delta) >= 1.0 || trackId !== originalTrackId) { + moved = true parent.moved(clipRoot) originalX = parent.x originalTrackId = trackId } else { - parent.dropped(clipRoot) + if (Math.abs(delta) >= 1.0) { + parent.dropped(clipRoot) + moved = true; + } + } + if (!clipRoot.selected || moved == false) { + clipRoot.clicked(clipRoot, mouse.modifiers === Qt.ShiftModifier) } - clipRoot.clicked(clipRoot, mouse.modifiers === Qt.ShiftModifier) } onDoubleClicked: timeline.position = clipRoot.x / timeline.scaleFactor onWheel: zoomByWheel(wheel) diff --git a/src/timeline2/view/qml/Composition.qml b/src/timeline2/view/qml/Composition.qml index 745e8cae1..4f4034727 100644 --- a/src/timeline2/view/qml/Composition.qml +++ b/src/timeline2/view/qml/Composition.qml @@ -184,7 +184,7 @@ Item { compositionRoot.moved(compositionRoot) originalX = compositionRoot.x originalTrackId = trackId - } else { + } else if (Math.abs(delta) >= 1.0) { compositionRoot.dropped(compositionRoot) } } diff --git a/src/timeline2/view/qml/timeline.qml b/src/timeline2/view/qml/timeline.qml index 302e38125..5fb569bf1 100644 --- a/src/timeline2/view/qml/timeline.qml +++ b/src/timeline2/view/qml/timeline.qml @@ -796,7 +796,7 @@ Rectangle { currentTrack = track if (shiftClick === 1) { timeline.addSelection(clip.clipId) - } else if (!timeline.isInSelection(clip.clipId) ) { + } else { timeline.selection = [ clip.clipId ] } timeline.showAsset(clip.clipId) @@ -949,3 +949,4 @@ Rectangle { } } } + diff --git a/src/timeline2/view/timelinecontroller.cpp b/src/timeline2/view/timelinecontroller.cpp index 265744f17..5d9629aba 100644 --- a/src/timeline2/view/timelinecontroller.cpp +++ b/src/timeline2/view/timelinecontroller.cpp @@ -636,10 +636,3 @@ void TimelineController::focusItem(int itemId) setPosition(start); } -bool TimelineController::isInSelection(int cid) const -{ - if (m_model->m_temporarySelectionGroup == -1 || !m_model->m_groups->isInGroup(cid)) { - return false; - } - return (m_model->m_groups->getRootId(cid) == m_model->m_temporarySelectionGroup); -} diff --git a/src/timeline2/view/timelinecontroller.h b/src/timeline2/view/timelinecontroller.h index aec975026..a2c056bda 100644 --- a/src/timeline2/view/timelinecontroller.h +++ b/src/timeline2/view/timelinecontroller.h @@ -119,8 +119,6 @@ public: Q_INVOKABLE void triggerAction(const QString &name); - Q_INVOKABLE bool isInSelection(int cid) const; - /* @brief Do we want to display video thumbnails */ bool showThumbnails() const; |
From: Jean-Baptiste M. <nu...@kd...> - 2017-08-01 08:49:48
|
Git commit ba22eca89be4c370b24888830a3076e94c9066f2 by Jean-Baptiste Mardelle. Committed on 01/08/2017 at 08:35. Pushed by mardelle into branch 'refactoring_timeline'. Resizable track header M +2 -2 src/kdenlivesettings.kcfg M +2 -2 src/timeline/timeline.cpp M +2 -2 src/timeline2/view/qml/TrackHead.qml M +46 -2 src/timeline2/view/qml/timeline.qml M +10 -0 src/timeline2/view/timelinecontroller.cpp M +4 -0 src/timeline2/view/timelinecontroller.h https://commits.kde.org/kdenlive/ba22eca89be4c370b24888830a3076e94c9066f2 diff --git a/src/kdenlivesettings.kcfg b/src/kdenlivesettings.kcfg index 9d5a52615..19469c44f 100644 --- a/src/kdenlivesettings.kcfg +++ b/src/kdenlivesettings.kcfg @@ -183,9 +183,9 @@ </group> <group name="timeline"> - <entry name="timelineheaderwidth" type="String"> + <entry name="headerwidth" type="Int"> <label>Default width for timeline track headers.</label> - <default></default> + <default>140</default> </entry> <entry name="defaultkeyframeinterp" type="Int"> <label>Default interpolation for keyframes.</label> diff --git a/src/timeline/timeline.cpp b/src/timeline/timeline.cpp index a54e76a46..1915e738f 100644 --- a/src/timeline/timeline.cpp +++ b/src/timeline/timeline.cpp @@ -176,7 +176,7 @@ Timeline::Timeline(KdenliveDoc *doc, const QList<QAction *> &actions, const QLis connect(m_disablePreview, &QAction::triggered, this, &Timeline::disablePreview); m_disablePreview->setEnabled(false); m_trackview->initTools(); - splitter->restoreState(QByteArray::fromBase64(KdenliveSettings::timelineheaderwidth().toUtf8())); + //splitter->restoreState(QByteArray::fromBase64(KdenliveSettings::timelineheaderwidth().toUtf8())); QAction *previewRender = m_doc->getAction(QStringLiteral("prerender_timeline_zone")); previewRender->setEnabled(true); } @@ -2130,7 +2130,7 @@ void Timeline::clearPreviewRange() void Timeline::storeHeaderSize(int, int) { - KdenliveSettings::setTimelineheaderwidth(splitter->saveState().toBase64()); + //KdenliveSettings::setTimelineheaderwidth(splitter->saveState().toBase64()); } void Timeline::switchComposite(int mode) diff --git a/src/timeline2/view/qml/TrackHead.qml b/src/timeline2/view/qml/TrackHead.qml index ee7cc55a2..d169791ee 100644 --- a/src/timeline2/view/qml/TrackHead.qml +++ b/src/timeline2/view/qml/TrackHead.qml @@ -280,7 +280,7 @@ Rectangle { Rectangle { id: resizer Layout.fillWidth: true - height: 5 + height: 4 color: 'red' opacity: 0 Drag.active: trimInMouseArea.drag.active @@ -312,7 +312,7 @@ Rectangle { if (mouse.buttons === Qt.LeftButton) { parent.opacity = 0.5 var newHeight = originalY + (mapToItem(null, x, y).y - startY) - newHeight = Math.max(trackLabel.height + resizer.height + 4, newHeight) + newHeight = Math.max(trackLabel.height + resizer.height + 3, newHeight) trackHeadRoot.collapsed = newHeight < nameEdit.height * 2 trackHeadRoot.myTrackHeight = newHeight } diff --git a/src/timeline2/view/qml/timeline.qml b/src/timeline2/view/qml/timeline.qml index 5fb569bf1..05a5470cd 100644 --- a/src/timeline2/view/qml/timeline.qml +++ b/src/timeline2/view/qml/timeline.qml @@ -93,7 +93,7 @@ Rectangle { return col } - property int headerWidth: 140 + property int headerWidth: timeline.headerWidth property int activeTool: 0 property real baseUnit: fontMetrics.font.pointSize property int currentTrack: 0 @@ -380,9 +380,53 @@ Rectangle { console.log('track name: ',index, ' = ', model.name) //timeline.selectTrackHead(currentTrack) } + } + } + } + Column { + id: trackHeadersResizer + spacing: 0 + width: 5 + Rectangle { + id: resizer + height: trackHeaders.height + width: 3 + x: root.headerWidth - 2 + color: 'red' + opacity: 0 + Drag.active: headerMouseArea.drag.active + Drag.proposedAction: Qt.MoveAction + + MouseArea { + id: headerMouseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.SizeHorCursor + drag.target: parent + drag.axis: Drag.XAxis + property double startX + property double originalX + drag.smoothed: false + + onPressed: { + root.stopScrolling = true + } + onReleased: { + root.stopScrolling = false + parent.opacity = 0 + } + onEntered: parent.opacity = 0.5 + onExited: parent.opacity = 0 + onPositionChanged: { + if (mouse.buttons === Qt.LeftButton) { + parent.opacity = 0.5 + headerWidth = Math.max(10, mapToItem(null, x, y).x + 2) + timeline.setHeaderWidth(headerWidth) + } + } + } } } - } } } MouseArea { diff --git a/src/timeline2/view/timelinecontroller.cpp b/src/timeline2/view/timelinecontroller.cpp index 5d9629aba..d046618a8 100644 --- a/src/timeline2/view/timelinecontroller.cpp +++ b/src/timeline2/view/timelinecontroller.cpp @@ -636,3 +636,13 @@ void TimelineController::focusItem(int itemId) setPosition(start); } +int TimelineController::headerWidth() const +{ + return qMax(10, KdenliveSettings::headerwidth()); +} + +void TimelineController::setHeaderWidth(int width) +{ + KdenliveSettings::setHeaderwidth(width); +} + diff --git a/src/timeline2/view/timelinecontroller.h b/src/timeline2/view/timelinecontroller.h index a2c056bda..45256a7ff 100644 --- a/src/timeline2/view/timelinecontroller.h +++ b/src/timeline2/view/timelinecontroller.h @@ -50,6 +50,7 @@ class TimelineController : public QObject Q_PROPERTY(bool showThumbnails READ showThumbnails NOTIFY showThumbnailsChanged) Q_PROPERTY(bool showMarkers READ showMarkers NOTIFY showMarkersChanged) Q_PROPERTY(bool showAudioThumbnails READ showAudioThumbnails NOTIFY showAudioThumbnailsChanged) + Q_PROPERTY(int headerWidth READ headerWidth WRITE setHeaderWidth) public: TimelineController(KActionCollection *actionCollection, QObject *parent); @@ -161,6 +162,9 @@ public: Q_INVOKABLE void selectItems(QVariantList arg, int startFrame, int endFrame); + Q_INVOKABLE int headerWidth() const; + Q_INVOKABLE void setHeaderWidth(int width); + /* @brief Seek to next snap point */ void gotoNextSnap(); |
From: Christoph F. <nu...@kd...> - 2017-07-30 23:59:28
|
Git commit 4cac44220ec1d2ea04c6dae91341b58b614df69d by Christoph Feck. Committed on 30/07/2017 at 23:59. Pushed by cfeck into branch 'Applications/17.08'. GIT_SILENT Upgrade KDE Applications version to 17.07.90. M +1 -1 CMakeLists.txt https://commits.kde.org/kdenlive/4cac44220ec1d2ea04c6dae91341b58b614df69d diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e6ed1571..6e0e39a4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ project(Kdenlive) # KDE Application Version, managed by release script set (KDE_APPLICATIONS_VERSION_MAJOR "17") set (KDE_APPLICATIONS_VERSION_MINOR "07") -set (KDE_APPLICATIONS_VERSION_MICRO "80") +set (KDE_APPLICATIONS_VERSION_MICRO "90") set(KDENLIVE_VERSION ${KDE_APPLICATIONS_VERSION_MAJOR}.${KDE_APPLICATIONS_VERSION_MINOR}.${KDE_APPLICATIONS_VERSION_MICRO}) cmake_minimum_required(VERSION 3.0) |
From: Nicolas C. <nu...@kd...> - 2017-07-30 13:20:13
|
Git commit 2458320af597a4788d1840020b9b4cd12a822b89 by Nicolas Carion. Committed on 30/07/2017 at 13:23. Pushed by alcinos into branch 'refactoring_timeline'. Start using new scheme for binClip insertion and implement it for ColorClip M +17 -9 src/bin/bin.cpp M +2 -0 src/bin/bin.h M +47 -7 src/bin/projectitemmodel.cpp M +14 -0 src/bin/projectitemmodel.h M +9 -14 src/dialogs/clipcreationdialog.cpp M +2 -1 src/dialogs/clipcreationdialog.h https://commits.kde.org/kdenlive/2458320af597a4788d1840020b9b4cd12a822b89 diff --git a/src/bin/bin.cpp b/src/bin/bin.cpp index 9d06af11a..9fb3eda96 100644 --- a/src/bin/bin.cpp +++ b/src/bin/bin.cpp @@ -1293,13 +1293,7 @@ void Bin::createClip(const QDomElement &xml) QString Bin::slotAddFolder(const QString &folderName) { - // Check parent item - QModelIndex ix = m_proxyModel->selectionModel()->currentIndex(); - std::shared_ptr<ProjectFolder> parentFolder = m_itemModel->getRootFolder(); - if (ix.isValid() && m_proxyModel->selectionModel()->isSelected(ix)) { - std::shared_ptr<AbstractProjectItem> currentItem = m_itemModel->getBinItemByIndex(m_proxyModel->mapToSource(ix)); - parentFolder = std::static_pointer_cast<ProjectFolder>(currentItem->getEnclosingFolder()); - } + auto parentFolder = m_itemModel->getFolderByBinId(getCurrentFolder()); qDebug() << "pranteforder id" << parentFolder->clipId(); QString newId; Fun undo = []() { return true; }; @@ -1313,7 +1307,7 @@ QString Bin::slotAddFolder(const QString &folderName) return newId; } auto folder = m_itemModel->getFolderByBinId(newId); - ix = m_itemModel->getIndexFromItem(folder); + auto ix = m_itemModel->getIndexFromItem(folder); qDebug() << "selecting" << ix; if (ix.isValid()) { qDebug() << "ix valid"; @@ -2346,9 +2340,10 @@ void Bin::slotCreateProjectClip() } ClipType type = (ClipType)act->data().toInt(); QStringList folderInfo = getFolderInfo(); + QString parentFolder = getCurrentFolder(); switch (type) { case Color: - ClipCreationDialog::createColorClip(m_doc, folderInfo, this); + ClipCreationDialog::createColorClip(m_doc, parentFolder, m_itemModel); break; case SlideShow: ClipCreationDialog::createSlideshowClip(m_doc, folderInfo, this); @@ -3503,3 +3498,16 @@ std::shared_ptr<EffectStackModel> Bin::getClipEffectStack(int itemId) std::shared_ptr<EffectStackModel> effectStack = std::static_pointer_cast<ClipController>(clip)->m_effectStack; return effectStack; } + + +QString Bin::getCurrentFolder() +{ + // Check parent item + QModelIndex ix = m_proxyModel->selectionModel()->currentIndex(); + std::shared_ptr<ProjectFolder> parentFolder = m_itemModel->getRootFolder(); + if (ix.isValid() && m_proxyModel->selectionModel()->isSelected(ix)) { + std::shared_ptr<AbstractProjectItem> currentItem = m_itemModel->getBinItemByIndex(m_proxyModel->mapToSource(ix)); + parentFolder = std::static_pointer_cast<ProjectFolder>(currentItem->getEnclosingFolder()); + } + return parentFolder->clipId(); +} diff --git a/src/bin/bin.h b/src/bin/bin.h index 94435f855..64e1d9781 100644 --- a/src/bin/bin.h +++ b/src/bin/bin.h @@ -302,6 +302,8 @@ public: QStringList getProxyHashList(); /** @brief Get info (id, name) of a folder (or the currently selected one) */ const QStringList getFolderInfo(const QModelIndex &selectedIx = QModelIndex()); + /** @brief Get binId of the current selected folder */ + QString getCurrentFolder(); /** @brief Save a clip zone as MLT playlist */ void saveZone(const QStringList &info, const QDir &dir); QVariantList audioFrameCache(const QString &id); diff --git a/src/bin/projectitemmodel.cpp b/src/bin/projectitemmodel.cpp index e689f8fc5..df4988258 100644 --- a/src/bin/projectitemmodel.cpp +++ b/src/bin/projectitemmodel.cpp @@ -31,6 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "projectclip.h" #include "projectfolder.h" #include "projectsubclip.h" +#include "xml/xml.hpp" #include <KLocalizedString> #include <QIcon> @@ -43,10 +44,16 @@ ProjectItemModel::ProjectItemModel(QObject *parent) , m_lock(QReadWriteLock::Recursive) , m_binPlaylist(new BinPlaylist()) , m_nextId(1) + , m_blankThumb() { KImageCache::deleteCache(QStringLiteral("kdenlive-thumbs")); m_pixmapCache.reset(new KImageCache(QStringLiteral("kdenlive-thumbs"), 10000000)); m_pixmapCache->setEvictionPolicy(KSharedDataCache::EvictOldest); + + QPixmap pix(QSize(160, 90)); + pix.fill(Qt::lightGray); + m_blankThumb.addPixmap(pix); + } std::shared_ptr<ProjectItemModel> ProjectItemModel::construct(QObject *parent) @@ -427,7 +434,7 @@ int ProjectItemModel::getFreeClipId() return m_nextId++; } -bool ProjectItemModel::requestAddFolder(QString &id, const QString &name, const QString &parentId, Fun &undo, Fun &redo) +bool ProjectItemModel::addItem(std::shared_ptr<AbstractProjectItem> item, const QString &parentId, Fun &undo, Fun &redo) { QWriteLocker locker(&m_lock); std::shared_ptr<ProjectFolder> parentFolder = getFolderByBinId(parentId); @@ -435,17 +442,50 @@ bool ProjectItemModel::requestAddFolder(QString &id, const QString &name, const qCDebug(KDENLIVE_LOG) << " / / ERROR IN PARENT FOLDER"; return false; } + Fun operation = addItem_lambda(item, parentFolder->getId()); + int itemId = item->getId(); + Fun reverse = removeItem_lambda(itemId); + bool res = operation(); + Q_ASSERT(item->isInModel()); + if (res) { + UPDATE_UNDO_REDO(operation, reverse, undo, redo); + } + return res; +} + +bool ProjectItemModel::requestAddFolder(QString &id, const QString &name, const QString &parentId, Fun &undo, Fun &redo) +{ + QWriteLocker locker(&m_lock); if (id.isEmpty()) { id = QString::number(getFreeFolderId()); } std::shared_ptr<ProjectFolder> new_folder = ProjectFolder::construct(id, name, std::static_pointer_cast<ProjectItemModel>(shared_from_this())); - Fun operation = addItem_lambda(new_folder, parentFolder->getId()); - int folderId = new_folder->getId(); - Fun reverse = removeItem_lambda(folderId); - bool res = operation(); - Q_ASSERT(new_folder->isInModel()); + return addItem(new_folder, parentId, undo, redo); +} + +bool ProjectItemModel::requestAddBinClip(QString &id, const QDomElement &description, const QString &parentId, Fun &undo, Fun &redo) +{ + QWriteLocker locker(&m_lock); + if (id.isEmpty()) { + QString defaultId = QString::number(getFreeFolderId()); + id = Xml::getTagContentByAttribute(description, QStringLiteral("property"), QStringLiteral("name"), QStringLiteral("kdenlive:id"), defaultId); + } + std::shared_ptr<ProjectClip> new_clip = ProjectClip::construct(id, description, m_blankThumb, std::static_pointer_cast<ProjectItemModel>(shared_from_this())); + bool res = addItem(new_clip, parentId, undo, redo); if (res) { - UPDATE_UNDO_REDO(operation, reverse, undo, redo); + //TODO Not very clean, improve (should pass pointer to projectClip instead of xml) + pCore->currentDoc()->getFileProperties(description, new_clip->clipId(), 150, true); + } + return res; +} + +bool ProjectItemModel::requestAddBinClip(QString &id, const QDomElement &description, const QString &parentId, const QString &undoText) +{ + Fun undo = []() { return true; }; + Fun redo = []() { return true; }; + bool res = requestAddBinClip(id, description, parentId, undo, redo); + if (res) { + pCore->pushUndo(undo, redo, undoText.isEmpty() ? i18n("Rename Folder") : undoText); } return res; } diff --git a/src/bin/projectitemmodel.h b/src/bin/projectitemmodel.h index dedf6292f..39971e56f 100644 --- a/src/bin/projectitemmodel.h +++ b/src/bin/projectitemmodel.h @@ -117,6 +117,15 @@ public: */ bool requestAddFolder(QString &id, const QString &name, const QString &parentId, Fun &undo, Fun &redo); + /* @brief Request creation of a bin clip + @param id Id of the requested bin. If this is empty, it will be used as a return parameter to give the automatic bin id used. + @param description Xml description of the clip + @param parentId Bin id of the parent folder + @param undo,redo: lambdas that are updated to accumulate operation. + */ + bool requestAddBinClip(QString &id, const QDomElement &description, const QString &parentId, Fun &undo, Fun &redo); + bool requestAddBinClip(QString &id, const QDomElement &description, const QString &parentId, const QString &undoText = QString()); + /* @brief Request that a folder's name is changed @param clip : pointer to the folder to rename @param name: new name of the folder @@ -145,6 +154,9 @@ protected: /* @brief Helper function to generate a lambda that rename a folder */ Fun requestRenameFolder_lambda(std::shared_ptr<AbstractProjectItem> folder, const QString &newName); + /* @brief Helper function to add a given item to the tree */ + bool addItem(std::shared_ptr<AbstractProjectItem> item, const QString &parentId, Fun &undo, Fun &redo); + std::unique_ptr<KImageCache> m_pixmapCache; public slots: /** @brief An item in the list was modified, notify */ @@ -159,6 +171,8 @@ private: std::unique_ptr<BinPlaylist> m_binPlaylist; int m_nextId; + + QIcon m_blankThumb; signals: void discardJobs(const QString &id, AbstractClipJob::JOBTYPE type); void startJob(const QString &id, AbstractClipJob::JOBTYPE type); diff --git a/src/dialogs/clipcreationdialog.cpp b/src/dialogs/clipcreationdialog.cpp index b48f1f2e9..69972896e 100644 --- a/src/dialogs/clipcreationdialog.cpp +++ b/src/dialogs/clipcreationdialog.cpp @@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "clipcreationdialog.h" #include "bin/bin.h" #include "bin/bincommands.h" +#include "bin/projectitemmodel.h" #include "bin/projectclip.h" #include "doc/docundostack.hpp" #include "doc/kdenlivedoc.h" @@ -117,17 +118,17 @@ void ClipCreationDialog::createClipFromXml(KdenliveDoc *doc, QDomElement &xml, c } // static -void ClipCreationDialog::createColorClip(KdenliveDoc *doc, const QStringList &groupInfo, Bin *bin) +void ClipCreationDialog::createColorClip(KdenliveDoc *doc, const QString &parentFolder, std::shared_ptr<ProjectItemModel> model) { - QPointer<QDialog> dia = new QDialog(bin); + QScopedPointer<QDialog> dia(new QDialog(qApp->activeWindow())); Ui::ColorClip_UI dia_ui; - dia_ui.setupUi(dia); + dia_ui.setupUi(dia.data()); dia->setWindowTitle(i18n("Color Clip")); dia_ui.clip_name->setText(i18n("Color Clip")); - TimecodeDisplay *t = new TimecodeDisplay(doc->timecode()); + QScopedPointer<TimecodeDisplay> t(new TimecodeDisplay(doc->timecode())); t->setValue(KdenliveSettings::color_duration()); - dia_ui.clip_durationBox->addWidget(t); + dia_ui.clip_durationBox->addWidget(t.data()); dia_ui.clip_color->setColor(KdenliveSettings::colorclipcolor()); if (dia->exec() == QDialog::Accepted) { @@ -139,25 +140,19 @@ void ClipCreationDialog::createColorClip(KdenliveDoc *doc, const QStringList &gr QDomElement prod = xml.createElement(QStringLiteral("producer")); xml.appendChild(prod); prod.setAttribute(QStringLiteral("type"), (int) Color); - int id = bin->getFreeClipId(); - prod.setAttribute(QStringLiteral("id"), QString::number(id)); prod.setAttribute(QStringLiteral("in"), QStringLiteral("0")); prod.setAttribute(QStringLiteral("length"), doc->getFramePos(doc->timecode().getTimecode(t->gentime()))); QMap<QString, QString> properties; properties.insert(QStringLiteral("resource"), color); properties.insert(QStringLiteral("kdenlive:clipname"), dia_ui.clip_name->text()); properties.insert(QStringLiteral("mlt_service"), QStringLiteral("color")); - if (!groupInfo.isEmpty()) { - properties.insert(QStringLiteral("kdenlive:folderid"), groupInfo.at(0)); - } addXmlProperties(prod, properties); qDebug() << xml.toString(); qDebug() << Xml::getTagContentByAttribute(xml.documentElement(), QStringLiteral("property"), QStringLiteral("name"), QStringLiteral("resource")); - AddClipCommand *command = new AddClipCommand(bin, xml.documentElement(), QString::number(id), true); - doc->commandStack()->push(command); + + QString id; + model->requestAddBinClip(id, xml.documentElement(), parentFolder, i18n("Create color clip")); } - delete t; - delete dia; } void ClipCreationDialog::createQTextClip(KdenliveDoc *doc, const QStringList &groupInfo, Bin *bin, ProjectClip *clip) diff --git a/src/dialogs/clipcreationdialog.h b/src/dialogs/clipcreationdialog.h index 762b8aa14..8201a7b00 100644 --- a/src/dialogs/clipcreationdialog.h +++ b/src/dialogs/clipcreationdialog.h @@ -28,6 +28,7 @@ class KdenliveDoc; class QUndoCommand; class Bin; class ProjectClip; +class ProjectItemModel; /** * @namespace ClipCreationDialog @@ -38,7 +39,7 @@ class ProjectClip; namespace ClipCreationDialog { QStringList getExtensions(); -void createColorClip(KdenliveDoc *doc, const QStringList &groupInfo, Bin *bin); +void createColorClip(KdenliveDoc *doc, const QString &parentFolder, std::shared_ptr<ProjectItemModel> model); void createQTextClip(KdenliveDoc *doc, const QStringList &groupInfo, Bin *bin, ProjectClip *clip = nullptr); void createClipFromXml(KdenliveDoc *doc, QDomElement &xml, const QStringList &groupInfo, Bin *bin); void createSlideshowClip(KdenliveDoc *doc, const QStringList &groupInfo, Bin *bin); |
From: Nicolas C. <nu...@kd...> - 2017-07-30 12:19:29
|
Git commit f3ec78c9aea7912b87d275b8c192b7b87e7b2463 by Nicolas Carion. Committed on 30/07/2017 at 12:23. Pushed by alcinos into branch 'refactoring_timeline'. Add application to tests to fix various issues M +2 -0 tests/TestMain.cpp https://commits.kde.org/kdenlive/f3ec78c9aea7912b87d275b8c192b7b87e7b2463 diff --git a/tests/TestMain.cpp b/tests/TestMain.cpp index fcf877df2..01fc45d49 100644 --- a/tests/TestMain.cpp +++ b/tests/TestMain.cpp @@ -2,6 +2,7 @@ #include "catch.hpp" #include "core.h" +#include <QApplication> #include <mlt++/MltFactory.h> #include <mlt++/MltRepository.h> /* This file is intended to remain empty. @@ -9,6 +10,7 @@ Write your tests in a file with a name corresponding to what you're testing */ int main(int argc, char *argv[]) { + QApplication app(argc, argv); std::unique_ptr<Mlt::Repository> repo(Mlt::Factory::init(nullptr)); Core::build(); |
From: Nicolas C. <nu...@kd...> - 2017-07-30 12:10:53
|
Git commit b87c127a55b28f5027f97e54ebc652f629bcf019 by Nicolas Carion. Committed on 30/07/2017 at 12:14. Pushed by alcinos into branch 'refactoring_timeline'. Force ProjectClips to be constructed using id M +2 -2 src/bin/abstractprojectitem.cpp M +1 -1 src/bin/abstractprojectitem.h M +6 -1 src/bin/bin.cpp M +6 -5 src/bin/projectclip.cpp M +3 -3 src/bin/projectclip.h M +5 -6 src/bin/projectitemmodel.h https://commits.kde.org/kdenlive/b87c127a55b28f5027f97e54ebc652f629bcf019 diff --git a/src/bin/abstractprojectitem.cpp b/src/bin/abstractprojectitem.cpp index 06a3a35c3..493f5338f 100644 --- a/src/bin/abstractprojectitem.cpp +++ b/src/bin/abstractprojectitem.cpp @@ -46,13 +46,13 @@ AbstractProjectItem::AbstractProjectItem(PROJECTITEMTYPE type, const QString &id { } -AbstractProjectItem::AbstractProjectItem(PROJECTITEMTYPE type, const QDomElement &description, const std::shared_ptr<ProjectItemModel> &model) +AbstractProjectItem::AbstractProjectItem(PROJECTITEMTYPE type, const QString &id, const QDomElement &description, const std::shared_ptr<ProjectItemModel> &model) : TreeItem(QList<QVariant>(), std::static_pointer_cast<AbstractTreeModel>(model), false) , m_name() , m_description() , m_thumbnail(QIcon()) , m_date() - , m_binId(description.attribute(QStringLiteral("id"))) + , m_binId(id) , m_usage(0) , m_clipStatus(StatusReady) , m_jobType(AbstractClipJob::NOJOBTYPE) diff --git a/src/bin/abstractprojectitem.h b/src/bin/abstractprojectitem.h index d37a5a214..031cd5b16 100644 --- a/src/bin/abstractprojectitem.h +++ b/src/bin/abstractprojectitem.h @@ -68,7 +68,7 @@ public: * * We try to read the attributes "name" and "description" */ - AbstractProjectItem(PROJECTITEMTYPE type, const QDomElement &description, const std::shared_ptr<ProjectItemModel> &model); + AbstractProjectItem(PROJECTITEMTYPE type, const QString &id, const QDomElement &description, const std::shared_ptr<ProjectItemModel> &model); bool operator==(const std::shared_ptr<AbstractProjectItem> &projectItem) const; diff --git a/src/bin/bin.cpp b/src/bin/bin.cpp index 4fb9f76d9..9d06af11a 100644 --- a/src/bin/bin.cpp +++ b/src/bin/bin.cpp @@ -50,6 +50,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "ui_qtextclip_ui.h" #include "undohelper.hpp" #include "utils/KoIconUtils.h" +#include "xml/xml.hpp" #include <KColorScheme> #include <KMessageBox> @@ -1282,7 +1283,11 @@ void Bin::createClip(const QDomElement &xml) } } } - auto newClip = ProjectClip::construct(xml, m_blankThumb, m_itemModel); + QString id = Xml::getTagContentByAttribute(xml, QStringLiteral("property"), QStringLiteral("name"), QStringLiteral("kdenlive:id")); + if (id.isEmpty()) { + id = QString::number(m_itemModel->getFreeClipId()); + } + auto newClip = ProjectClip::construct(id, xml, m_blankThumb, m_itemModel); parentFolder->appendChild(newClip); } diff --git a/src/bin/projectclip.cpp b/src/bin/projectclip.cpp index f3b5acb02..7514c278b 100644 --- a/src/bin/projectclip.cpp +++ b/src/bin/projectclip.cpp @@ -41,6 +41,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "timeline/clip.h" #include "timeline2/model/snapmodel.hpp" #include "utils/KoIconUtils.h" +#include "xml/xml.hpp" #include <kimagecache.h> #include <QPainter> @@ -96,9 +97,9 @@ std::shared_ptr<ProjectClip> ProjectClip::construct(const QString &id, const QIc return self; } -ProjectClip::ProjectClip(const QDomElement &description, const QIcon &thumb, std::shared_ptr<ProjectItemModel> model) - : AbstractProjectItem(AbstractProjectItem::ClipItem, description, model) - , ClipController(description.attribute(QStringLiteral("id")), pCore->binController()) +ProjectClip::ProjectClip(const QString &id, const QDomElement &description, const QIcon &thumb, std::shared_ptr<ProjectItemModel> model) + : AbstractProjectItem(AbstractProjectItem::ClipItem, id, description, model) + , ClipController(id, pCore->binController()) , m_abortAudioThumb(false) , m_thumbsProducer(nullptr) { @@ -127,9 +128,9 @@ ProjectClip::ProjectClip(const QDomElement &description, const QIcon &thumb, std }); } -std::shared_ptr<ProjectClip> ProjectClip::construct(const QDomElement &description, const QIcon &thumb, std::shared_ptr<ProjectItemModel> model) +std::shared_ptr<ProjectClip> ProjectClip::construct(const QString &id, const QDomElement &description, const QIcon &thumb, std::shared_ptr<ProjectItemModel> model) { - std::shared_ptr<ProjectClip> self(new ProjectClip(description, thumb, model)); + std::shared_ptr<ProjectClip> self(new ProjectClip(id, description, thumb, model)); baseFinishConstruct(self); pCore->binController()->addClipToBin(description.attribute(QStringLiteral("id")), self, true); return self; diff --git a/src/bin/projectclip.h b/src/bin/projectclip.h index bba1352e9..ef4472d15 100644 --- a/src/bin/projectclip.h +++ b/src/bin/projectclip.h @@ -64,13 +64,13 @@ public: std::shared_ptr<Mlt::Producer> producer); /** * @brief Constructor. - * @param description element describing the clip; the "id" attribute and "resource" property are used + * @param description element describing the clip; the "kdenlive:id" attribute and "resource" property are used */ - static std::shared_ptr<ProjectClip> construct(const QDomElement &description, const QIcon &thumb, std::shared_ptr<ProjectItemModel> model); + static std::shared_ptr<ProjectClip> construct(const QString &id, const QDomElement &description, const QIcon &thumb, std::shared_ptr<ProjectItemModel> model); protected: ProjectClip(const QString &id, const QIcon &thumb, std::shared_ptr<ProjectItemModel> model, std::shared_ptr<Mlt::Producer> producer); - ProjectClip(const QDomElement &description, const QIcon &thumb, std::shared_ptr<ProjectItemModel> model); + ProjectClip(const QString &id, const QDomElement &description, const QIcon &thumb, std::shared_ptr<ProjectItemModel> model); public: virtual ~ProjectClip(); diff --git a/src/bin/projectitemmodel.h b/src/bin/projectitemmodel.h index 5357e2ca5..dedf6292f 100644 --- a/src/bin/projectitemmodel.h +++ b/src/bin/projectitemmodel.h @@ -129,6 +129,11 @@ public: /* @brief Request that the unused clips are deleted */ bool requestCleanup(); + /* @brief Retrieves the next id available for attribution to a folder */ + int getFreeFolderId(); + + /* @brief Retrieves the next id available for attribution to a clip */ + int getFreeClipId(); protected: /* @brief Register the existence of a new element */ @@ -137,12 +142,6 @@ protected: void deregisterItem(int id, TreeItem *item) override; - /* @brief Retrieves the next id available for attribution to a folder */ - int getFreeFolderId(); - - /* @brief Retrieves the next id available for attribution to a clip */ - int getFreeClipId(); - /* @brief Helper function to generate a lambda that rename a folder */ Fun requestRenameFolder_lambda(std::shared_ptr<AbstractProjectItem> folder, const QString &newName); |
From: Montel L. <nu...@kd...> - 2017-07-30 12:04:59
|
Git commit 5e0b0db076cc93ddc8486ea837aabb13512785dd by Montel Laurent. Committed on 30/07/2017 at 12:04. Pushed by mlaurent into branch 'master'. Const'ify code M +2 -2 src/bin/projectitemmodel.cpp M +1 -1 src/capture/mltdevicecapture.cpp M +2 -2 src/doc/documentvalidator.cpp M +3 -3 src/dvdwizard/dvdwizardvob.cpp M +1 -1 src/effectstack/graphicsscenerectmove.cpp M +1 -1 src/effectstack/widgets/curves/bezier/cubicbezierspline.cpp M +1 -1 src/effectstack/widgets/curves/cubic/kis_cubic_curve.cpp https://commits.kde.org/kdenlive/5e0b0db076cc93ddc8486ea837aabb13512785dd diff --git a/src/bin/projectitemmodel.cpp b/src/bin/projectitemmodel.cpp index 7da1fa315..86ac72b26 100644 --- a/src/bin/projectitemmodel.cpp +++ b/src/bin/projectitemmodel.cpp @@ -139,7 +139,7 @@ bool ProjectItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action if (data->hasFormat(QStringLiteral("kdenlive/producerslist"))) { // Dropping an Bin item - QStringList ids = QString(data->data(QStringLiteral("kdenlive/producerslist"))).split(QLatin1Char(';')); + const QStringList ids = QString(data->data(QStringLiteral("kdenlive/producerslist"))).split(QLatin1Char(';')); emit itemDropped(ids, parent); return true; } @@ -152,7 +152,7 @@ bool ProjectItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action } if (data->hasFormat(QStringLiteral("kdenlive/clip"))) { - QStringList list = QString(data->data(QStringLiteral("kdenlive/clip"))).split(QLatin1Char(';')); + const QStringList list = QString(data->data(QStringLiteral("kdenlive/clip"))).split(QLatin1Char(';')); emit addClipCut(list.at(0), list.at(1).toInt(), list.at(2).toInt()); } diff --git a/src/capture/mltdevicecapture.cpp b/src/capture/mltdevicecapture.cpp index 5e1614ffe..b072014c1 100644 --- a/src/capture/mltdevicecapture.cpp +++ b/src/capture/mltdevicecapture.cpp @@ -366,7 +366,7 @@ bool MltDeviceCapture::slotStartCapture(const QString ¶ms, const QString &pa // without this line a call to mlt_properties_get_int(terminate on pause) for in mlt/src/modules/core/consumer_multi.c is returning 1 // and going into and endless loop. renderProps->set("mlt_profile", m_activeProfile.toUtf8().constData()); - QStringList paramList = params.split(' ', QString::SkipEmptyParts); + const QStringList paramList = params.split(' ', QString::SkipEmptyParts); for (int i = 0; i < paramList.count(); ++i) { tmp = qstrdup(paramList.at(i).section(QLatin1Char('='), 0, 0).toUtf8().constData()); QString value = paramList.at(i).section(QLatin1Char('='), 1, 1); diff --git a/src/doc/documentvalidator.cpp b/src/doc/documentvalidator.cpp index daaa9b47c..8ca4740e4 100644 --- a/src/doc/documentvalidator.cpp +++ b/src/doc/documentvalidator.cpp @@ -1219,7 +1219,7 @@ void DocumentValidator::updateProducerInfo(const QDomElement &prod, const QDomEl } if (source.hasAttribute(QStringLiteral("cutzones"))) { QString zoneData = source.attribute(QStringLiteral("cutzones")); - QStringList zoneList = zoneData.split(QLatin1Char(';')); + const QStringList zoneList = zoneData.split(QLatin1Char(';')); int ct = 1; foreach (const QString &data, zoneList) { QString zoneName = data.section(QLatin1Char('-'), 2); @@ -1429,7 +1429,7 @@ bool DocumentValidator::checkMovit() QString DocumentValidator::factorizeGeomValue(const QString &value, double factor) { - QStringList vals = value.split(QLatin1Char(';')); + const QStringList vals = value.split(QLatin1Char(';')); QString result; QLocale locale; for (int i = 0; i < vals.count(); i++) { diff --git a/src/dvdwizard/dvdwizardvob.cpp b/src/dvdwizard/dvdwizardvob.cpp index 39c5a6c9d..6f3e30b3d 100644 --- a/src/dvdwizard/dvdwizardvob.cpp +++ b/src/dvdwizard/dvdwizardvob.cpp @@ -177,7 +177,7 @@ void DvdWizardVob::slotShowTranscodeInfo() if (m_duration == 0) { if (log.contains(QStringLiteral("Duration:"))) { QString durationstr = log.section(QStringLiteral("Duration:"), 1, 1).section(QLatin1Char(','), 0, 0).simplified(); - QStringList numbers = durationstr.split(QLatin1Char(':')); + const QStringList numbers = durationstr.split(QLatin1Char(':')); if (numbers.size() < 3) { return; } @@ -192,7 +192,7 @@ void DvdWizardVob::slotShowTranscodeInfo() int progress; QString time = log.section(QStringLiteral("time="), 1, 1).simplified().section(QLatin1Char(' '), 0, 0); if (time.contains(QLatin1Char(':'))) { - QStringList numbers = time.split(QLatin1Char(':')); + const QStringList numbers = time.split(QLatin1Char(':')); if (numbers.size() < 3) { return; } @@ -722,7 +722,7 @@ void DvdWizardVob::processTranscoding() } bool replaceVfParams = false; - QStringList splitted = params.split(QLatin1Char(' ')); + const QStringList splitted = params.split(QLatin1Char(' ')); foreach (QString s, splitted) { if (replaceVfParams) { parameters << postParams.at(1); diff --git a/src/effectstack/graphicsscenerectmove.cpp b/src/effectstack/graphicsscenerectmove.cpp index 3d274a409..2d1224044 100644 --- a/src/effectstack/graphicsscenerectmove.cpp +++ b/src/effectstack/graphicsscenerectmove.cpp @@ -174,7 +174,7 @@ void MyTextItem::updateGeometry(int, int, int) double lineSpacing = data(TitleDocument::LineSpacing).toInt() + metrics.lineSpacing(); // Calculate line width - QStringList lines = text.split(QLatin1Char('\n')); + const QStringList lines = text.split(QLatin1Char('\n')); double linePos = metrics.ascent(); QRectF bounding = boundingRect(); /*if (lines.count() > 0) { diff --git a/src/effectstack/widgets/curves/bezier/cubicbezierspline.cpp b/src/effectstack/widgets/curves/bezier/cubicbezierspline.cpp index f332738ce..54ce4b01d 100644 --- a/src/effectstack/widgets/curves/bezier/cubicbezierspline.cpp +++ b/src/effectstack/widgets/curves/bezier/cubicbezierspline.cpp @@ -54,7 +54,7 @@ void CubicBezierSpline::fromString(const QString &spline) const QStringList points = bpoint.split(QLatin1Char('#')); QVector<QPointF> values; for (const QString &point : points) { - QStringList xy = point.split(QLatin1Char(';')); + const QStringList xy = point.split(QLatin1Char(';')); if (xy.count() == 2) { values.append(QPointF(locale.toDouble(xy.at(0)), locale.toDouble(xy.at(1)))); } diff --git a/src/effectstack/widgets/curves/cubic/kis_cubic_curve.cpp b/src/effectstack/widgets/curves/cubic/kis_cubic_curve.cpp index 6050cfcf8..4d4e6e49d 100644 --- a/src/effectstack/widgets/curves/cubic/kis_cubic_curve.cpp +++ b/src/effectstack/widgets/curves/cubic/kis_cubic_curve.cpp @@ -436,7 +436,7 @@ QString KisCubicCurve::toString() const void KisCubicCurve::fromString(const QString &string) { - QStringList data = string.split(QLatin1Char(';')); + const QStringList data = string.split(QLatin1Char(';')); QList<QPointF> points; QLocale locale; |
From: Nicolas C. <nu...@kd...> - 2017-07-29 16:30:46
|
Git commit d6efc183b0ae58d89249b1706b590539807c7980 by Nicolas Carion. Committed on 29/07/2017 at 16:34. Pushed by alcinos into branch 'refactoring_timeline'. add helper xml function to retrieve element by attribute M +3 -0 src/dialogs/clipcreationdialog.cpp M +24 -1 src/xml/xml.cpp M +9 -0 src/xml/xml.hpp https://commits.kde.org/kdenlive/d6efc183b0ae58d89249b1706b590539807c7980 diff --git a/src/dialogs/clipcreationdialog.cpp b/src/dialogs/clipcreationdialog.cpp index 710ae39fd..b48f1f2e9 100644 --- a/src/dialogs/clipcreationdialog.cpp +++ b/src/dialogs/clipcreationdialog.cpp @@ -33,6 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "titletemplatedialog.h" #include "ui_colorclip_ui.h" #include "ui_qtextclip_ui.h" +#include "xml/xml.hpp" #include "klocalizedstring.h" #include <KFileWidget> @@ -150,6 +151,8 @@ void ClipCreationDialog::createColorClip(KdenliveDoc *doc, const QStringList &gr properties.insert(QStringLiteral("kdenlive:folderid"), groupInfo.at(0)); } addXmlProperties(prod, properties); + qDebug() << xml.toString(); + qDebug() << Xml::getTagContentByAttribute(xml.documentElement(), QStringLiteral("property"), QStringLiteral("name"), QStringLiteral("resource")); AddClipCommand *command = new AddClipCommand(bin, xml.documentElement(), QString::number(id), true); doc->commandStack()->push(command); } diff --git a/src/xml/xml.cpp b/src/xml/xml.cpp index 393b55fbe..a3a355761 100644 --- a/src/xml/xml.cpp +++ b/src/xml/xml.cpp @@ -44,7 +44,7 @@ QVector<QDomNode> Xml::getDirectChildrenByTagName(const QDomElement &element, co auto children = element.childNodes(); QVector<QDomNode> result; for (int i = 0; i < children.count(); ++i) { - if (children.item(i).isNull()) { + if (children.item(i).isNull() || !children.item(i).isElement()) { continue; } QDomElement child = children.item(i).toElement(); @@ -54,3 +54,26 @@ QVector<QDomNode> Xml::getDirectChildrenByTagName(const QDomElement &element, co } return result; } + +QString Xml::getTagContentByAttribute(const QDomElement &element, const QString &tagName, const QString &attribute, const QString &value, const QString &defaultReturn, bool directChildren) +{ + QDomNodeList nodes; + if (directChildren) { + nodes = element.childNodes(); + } else { + nodes = element.elementsByTagName(tagName); + } + for (int i = 0; i < nodes.count(); ++i) { + auto current = nodes.item(i); + if (current.isNull() || !current.isElement()) { + continue; + } + auto elem = current.toElement(); + if (elem.tagName() == tagName && elem.hasAttribute(attribute)) { + if (elem.attribute(attribute) == value) { + return elem.text(); + } + } + } + return defaultReturn; +} diff --git a/src/xml/xml.hpp b/src/xml/xml.hpp index 1f59354c3..6e1c4daea 100644 --- a/src/xml/xml.hpp +++ b/src/xml/xml.hpp @@ -44,6 +44,15 @@ namespace Xml This is an alternative to QDomElement::elementsByTagName which returns also non-direct children */ QVector<QDomNode> getDirectChildrenByTagName(const QDomElement &element, const QString &tagName); + + /* @brief Returns the content of a children tag of @param element, which respects the following conditions : + - Its type is @param tagName + - It as an attribute named @param attribute with value @param value + For example, if your element is <html><param val="foo">bar</param></html>, you can retrieve "bar" with parameters: tagName="param", attribute="val", and value="foo" + Returns @param defaultReturn when nothing is found. The methods returns the first match found, so make sure there can't be more than one. + If @param directChildren is true, only immediate children of the node are considered + */ + QString getTagContentByAttribute(const QDomElement &element, const QString &tagName, const QString &attribute, const QString &value, const QString &defaultReturn = QString(), bool directChildren = true); } #endif |
From: Nicolas C. <nu...@kd...> - 2017-07-29 16:30:45
|
Git commit 1c660fe9fdd119fe7a37b085c036ec4c87d2a2de by Nicolas Carion. Committed on 29/07/2017 at 16:34. Pushed by alcinos into branch 'refactoring_timeline'. Enforce kdenlive:id being stored by clipController M +4 -2 src/mltcontroller/clipcontroller.cpp https://commits.kde.org/kdenlive/1c660fe9fdd119fe7a37b085c036ec4c87d2a2de diff --git a/src/mltcontroller/clipcontroller.cpp b/src/mltcontroller/clipcontroller.cpp index 703ce1e6f..4a475f107 100644 --- a/src/mltcontroller/clipcontroller.cpp +++ b/src/mltcontroller/clipcontroller.cpp @@ -61,6 +61,7 @@ ClipController::ClipController(const QString clipId, std::shared_ptr<BinControll return; } if (m_properties) { + setProducerProperty(QStringLiteral("kdenlive:id"), m_controllerBinId); m_service = m_properties->get("mlt_service"); QString proxy = m_properties->get("kdenlive:proxy"); QString path = m_properties->get("resource"); @@ -104,7 +105,7 @@ void ClipController::addMasterProducer(const std::shared_ptr<Mlt::Producer> &pro QString documentRoot = pCore->currentDoc()->documentRoot(); m_masterProducer = producer; m_properties = new Mlt::Properties(m_masterProducer->get_properties()); - int id = m_properties->get_int("kdenlive:id"); + int id = m_controllerBinId.toInt(); m_effectStack = EffectStackModel::construct(producer, {ObjectType::BinClip, id}, pCore->undoStack()); if (!m_masterProducer->is_valid()) { m_masterProducer = ClipController::mediaUnavailable; @@ -128,7 +129,8 @@ void ClipController::addMasterProducer(const std::shared_ptr<Mlt::Producer> &pro } m_path = QFileInfo(path).absoluteFilePath(); getInfoForProducer(); - emitProducerChanged(QString::number(id), producer); + emitProducerChanged(m_controllerBinId, producer); + setProducerProperty(QStringLiteral("kdenlive:id"), m_controllerBinId); } } |
From: Nicolas C. <nu...@kd...> - 2017-07-29 16:30:44
|
Git commit c89a90ec57c064772c122b91a3fdd255e0140d70 by Nicolas Carion. Committed on 29/07/2017 at 16:34. Pushed by alcinos into branch 'refactoring_timeline'. ensure unique ids between clips and folders M +0 -3 src/bin/binplaylist.cpp M +2 -0 src/bin/binplaylist.hpp M +4 -6 src/bin/projectitemmodel.cpp M +1 -2 src/bin/projectitemmodel.h https://commits.kde.org/kdenlive/c89a90ec57c064772c122b91a3fdd255e0140d70 diff --git a/src/bin/binplaylist.cpp b/src/bin/binplaylist.cpp index fe3102ada..d6f42639b 100644 --- a/src/bin/binplaylist.cpp +++ b/src/bin/binplaylist.cpp @@ -47,7 +47,6 @@ void BinPlaylist::manageBinClipInsertion(const std::shared_ptr<AbstractProjectIt case AbstractProjectItem::ClipItem: { Q_ASSERT(m_allClips.count(id) == 0); auto clip = std::static_pointer_cast<ProjectClip>(binElem); - qDebug() << "BBBBBBBBBBBBBPPPPPPPPPPPP insert"<<id << clip->isValid(); if (clip->isValid()) { m_binPlaylist->append(*clip->originalProducer().get()); } else { @@ -78,7 +77,6 @@ void BinPlaylist::manageBinClipDeletion(AbstractProjectItem *binElem) break; } case AbstractProjectItem::ClipItem: { - qDebug() << "BBBBBBBBBBBBBPPPPPPPPPPPP delete"<<id; Q_ASSERT(m_allClips.count(id) > 0); m_allClips.erase(id); removeBinClip(id); @@ -107,7 +105,6 @@ void BinPlaylist::removeBinClip(const QString &id) void BinPlaylist::changeProducer(const QString &id, const std::shared_ptr<Mlt::Producer> &producer) { - qDebug() << "BBBBBBBBBBBBBPPPPPPPPPPPP change"<<id; Q_ASSERT(m_allClips.count(id) > 0); removeBinClip(id); m_binPlaylist->append(*producer.get()); diff --git a/src/bin/binplaylist.hpp b/src/bin/binplaylist.hpp index ea262b6ac..680f0aa22 100644 --- a/src/bin/binplaylist.hpp +++ b/src/bin/binplaylist.hpp @@ -52,6 +52,7 @@ public: This is because the function will be called in the middle of the element's destructor, so no smart pointer is available at that time. */ void manageBinClipDeletion(AbstractProjectItem *binElem); + /* @brief This function updates the underlying binPlaylist object to reflect insertion of a bin item @param binElem is the bin item inserted */ @@ -61,6 +62,7 @@ protected: /* @brief This is an helper function that removes a clip from the playlist given its id */ void removeBinClip(const QString &id); + /* @brief This handles the fact that a clip has changed its producer (for example, loading is done) It should be called directly as a slot of ClipController's signal, so you probably don't want to call this directly. @param id: binId of the producer diff --git a/src/bin/projectitemmodel.cpp b/src/bin/projectitemmodel.cpp index bfae63e89..e689f8fc5 100644 --- a/src/bin/projectitemmodel.cpp +++ b/src/bin/projectitemmodel.cpp @@ -42,8 +42,7 @@ ProjectItemModel::ProjectItemModel(QObject *parent) : AbstractTreeModel(parent) , m_lock(QReadWriteLock::Recursive) , m_binPlaylist(new BinPlaylist()) - , m_clipCounter(1) - , m_folderCounter(1) + , m_nextId(1) { KImageCache::deleteCache(QStringLiteral("kdenlive-thumbs")); m_pixmapCache.reset(new KImageCache(QStringLiteral("kdenlive-thumbs"), 10000000)); @@ -340,8 +339,7 @@ void ProjectItemModel::clean() rootItem->removeChild(child); } Q_ASSERT(rootItem->childCount() == 0); - m_clipCounter = 1; - m_folderCounter = 1; + m_nextId = 1; m_pixmapCache->clear(); } @@ -421,12 +419,12 @@ void ProjectItemModel::deregisterItem(int id, TreeItem *item) int ProjectItemModel::getFreeFolderId() { - return m_folderCounter++; + return m_nextId++; } int ProjectItemModel::getFreeClipId() { - return m_clipCounter++; + return m_nextId++; } bool ProjectItemModel::requestAddFolder(QString &id, const QString &name, const QString &parentId, Fun &undo, Fun &redo) diff --git a/src/bin/projectitemmodel.h b/src/bin/projectitemmodel.h index cec78e5ba..5357e2ca5 100644 --- a/src/bin/projectitemmodel.h +++ b/src/bin/projectitemmodel.h @@ -159,8 +159,7 @@ private: std::unique_ptr<BinPlaylist> m_binPlaylist; - int m_clipCounter; - int m_folderCounter; + int m_nextId; signals: void discardJobs(const QString &id, AbstractClipJob::JOBTYPE type); void startJob(const QString &id, AbstractClipJob::JOBTYPE type); |
From: Nicolas C. <nu...@kd...> - 2017-07-29 16:30:44
|
Git commit 1a04b8ee4bd88ec0a5d6dc5ab2e5a005e59150c6 by Nicolas Carion. Committed on 29/07/2017 at 16:34. Pushed by alcinos into branch 'refactoring_timeline'. make xml utilities a namespace instead of a static class M +5 -7 src/xml/xml.hpp https://commits.kde.org/kdenlive/1a04b8ee4bd88ec0a5d6dc5ab2e5a005e59150c6 diff --git a/src/xml/xml.hpp b/src/xml/xml.hpp index c2ed9adba..1f59354c3 100644 --- a/src/xml/xml.hpp +++ b/src/xml/xml.hpp @@ -29,23 +29,21 @@ /** @brief This static class provides helper functions to manipulate Dom objects easily */ -class Xml +namespace Xml { -public: - Xml() = delete; /* @brief Returns the content of a given tag within the current DomElement. For example, if your @param element looks like <html><title>foo</title><head>bar</head></html>, passing @tagName = "title" will return foo, and @tagName = "head" returns bar Returns empty string if tag is not found. */ - static QString getSubTagContent(const QDomElement &element, const QString &tagName); + QString getSubTagContent(const QDomElement &element, const QString &tagName); - /* @brief Returns the direct children of given @element whose tag name matches given @paam tagName + /* @brief Returns the direct children of given @element whose tag name matches given @param tagName This is an alternative to QDomElement::elementsByTagName which returns also non-direct children */ - static QVector<QDomNode> getDirectChildrenByTagName(const QDomElement &element, const QString &tagName); -}; + QVector<QDomNode> getDirectChildrenByTagName(const QDomElement &element, const QString &tagName); +} #endif |
From: Jean-Baptiste M. <nu...@kd...> - 2017-07-29 06:48:02
|
Git commit 27092bf1df141cae8d26089df597f9209e6772fb by Jean-Baptiste Mardelle. Committed on 29/07/2017 at 06:47. Pushed by mardelle into branch 'refactoring_timeline'. Clear existing selection on rubber band select M +1 -0 src/timeline2/view/timelinecontroller.cpp https://commits.kde.org/kdenlive/27092bf1df141cae8d26089df597f9209e6772fb diff --git a/src/timeline2/view/timelinecontroller.cpp b/src/timeline2/view/timelinecontroller.cpp index 5b3b83abb..265744f17 100644 --- a/src/timeline2/view/timelinecontroller.cpp +++ b/src/timeline2/view/timelinecontroller.cpp @@ -464,6 +464,7 @@ void TimelineController::setZoneOut(int outPoint) void TimelineController::selectItems(QVariantList arg, int startFrame, int endFrame) { + m_selection.selectedClips.clear(); std::unordered_set<int>clipsToSelect; for (int i = 0; i < arg.count(); i++) { std::unordered_set<int> trackClips = m_model->getTrackById(arg.at(i).toInt())->getClipsAfterPosition(startFrame, endFrame); |
From: Jean-Baptiste M. <nu...@kd...> - 2017-07-29 06:41:33
|
Git commit 7cc8d9e6a62c1329b8dd239e2e8fae094f31ea27 by Jean-Baptiste Mardelle. Committed on 29/07/2017 at 06:40. Pushed by mardelle into branch 'refactoring_timeline'. Fix track index on clip click M +1 -1 src/timeline2/view/qml/Track.qml M +1 -2 src/timeline2/view/qml/timeline.qml https://commits.kde.org/kdenlive/7cc8d9e6a62c1329b8dd239e2e8fae094f31ea27 diff --git a/src/timeline2/view/qml/Track.qml b/src/timeline2/view/qml/Track.qml index 2a0c97e92..f9e180229 100644 --- a/src/timeline2/view/qml/Track.qml +++ b/src/timeline2/view/qml/Track.qml @@ -200,7 +200,7 @@ Column{ onClicked: { console.log("Clip clicked",clip.clipId) - trackRoot.clipClicked(clip, trackRoot, shiftClick); + trackRoot.clipClicked(clip, clip.trackIndex, shiftClick); clip.draggedX = clip.x } onMoved: { //called when the movement is finished diff --git a/src/timeline2/view/qml/timeline.qml b/src/timeline2/view/qml/timeline.qml index c62e9b534..302e38125 100644 --- a/src/timeline2/view/qml/timeline.qml +++ b/src/timeline2/view/qml/timeline.qml @@ -793,14 +793,13 @@ Rectangle { trackId: item selection: timeline.selection onClipClicked: { - currentTrack = track.DelegateModel.itemsIndex + currentTrack = track if (shiftClick === 1) { timeline.addSelection(clip.clipId) } else if (!timeline.isInSelection(clip.clipId) ) { timeline.selection = [ clip.clipId ] } timeline.showAsset(clip.clipId) - //root.clipClicked() } onClipDragged: { continuousScrolling(x) |
From: Jean-Baptiste M. <nu...@kd...> - 2017-07-28 16:07:09
|
Git commit 7460f6e56f1f0ab00649b194c67f7e6f85df9cbf by Jean-Baptiste Mardelle. Committed on 28/07/2017 at 16:06. Pushed by mardelle into branch 'refactoring_timeline'. mostly working rubber selection in timeline M +7 -1 src/timeline2/model/timelinemodel.cpp M +4 -1 src/timeline2/model/timelinemodel.hpp M +1 -1 src/timeline2/view/qml/Clip.qml M +1 -1 src/timeline2/view/qml/timeline.qml M +16 -1 src/timeline2/view/timelinecontroller.cpp M +2 -0 src/timeline2/view/timelinecontroller.h https://commits.kde.org/kdenlive/7460f6e56f1f0ab00649b194c67f7e6f85df9cbf diff --git a/src/timeline2/model/timelinemodel.cpp b/src/timeline2/model/timelinemodel.cpp index 117374b04..45b3d5c45 100644 --- a/src/timeline2/model/timelinemodel.cpp +++ b/src/timeline2/model/timelinemodel.cpp @@ -58,6 +58,7 @@ TimelineModel::TimelineModel(Mlt::Profile *profile, std::weak_ptr<DocUndoStack> , m_lock(QReadWriteLock::Recursive) , m_timelineEffectsEnabled(true) , m_id(getNextId()) + , m_temporarySelectionGroup(-1) { // Create black background track m_blackClip->set("id", "black_track"); @@ -781,13 +782,18 @@ bool TimelineModel::requestClipTrim(int clipId, int delta, bool right, bool ripp return requestItemResize(clipId, m_allClips[clipId]->getPlaytime() - delta, right, logUndo); } -int TimelineModel::requestClipsGroup(const std::unordered_set<int> &ids, bool logUndo) +int TimelineModel::requestClipsGroup(const std::unordered_set<int> &ids, bool logUndo, bool temporarySelection) { QWriteLocker locker(&m_lock); Fun undo = []() { return true; }; Fun redo = []() { return true; }; + if (temporarySelection && m_temporarySelectionGroup > -1) { + requestClipUngroup(m_temporarySelectionGroup, undo, redo); + m_temporarySelectionGroup = -1; + } int result = requestClipsGroup(ids, undo, redo); if (result > -1 && logUndo) { + m_temporarySelectionGroup = result; PUSH_UNDO(undo, redo, i18n("Group clips")); } return result; diff --git a/src/timeline2/model/timelinemodel.hpp b/src/timeline2/model/timelinemodel.hpp index b0ade58e9..ca0c63752 100644 --- a/src/timeline2/model/timelinemodel.hpp +++ b/src/timeline2/model/timelinemodel.hpp @@ -365,7 +365,7 @@ public: Typically, ids would be ids of clips, but for convenience, some of them can be ids of groups as well. @param ids Set of ids to group */ - int requestClipsGroup(const std::unordered_set<int> &ids, bool logUndo = true); + int requestClipsGroup(const std::unordered_set<int> &ids, bool logUndo = true, bool temporarySelection = false); int requestClipsGroup(const std::unordered_set<int> &ids, Fun &undo, Fun &redo); /* @brief Destruct the topmost group containing clip @@ -589,6 +589,9 @@ protected: bool m_id; // id of the timeline itself + // id of the currently selected group in timeline, should be destroyed on each new selection + int m_temporarySelectionGroup; + // what follows are some virtual function that corresponds to the QML. They are implemented in TimelineItemModel protected: virtual void _beginRemoveRows(const QModelIndex &, int, int) = 0; diff --git a/src/timeline2/view/qml/Clip.qml b/src/timeline2/view/qml/Clip.qml index 853c82a5c..faef8a55d 100644 --- a/src/timeline2/view/qml/Clip.qml +++ b/src/timeline2/view/qml/Clip.qml @@ -170,7 +170,6 @@ Rectangle { originalTrackId = clipRoot.trackId startX = parent.x clipRoot.forceActiveFocus(); - clipRoot.clicked(clipRoot, mouse.modifiers === Qt.ShiftModifier) } onPositionChanged: { if (mouse.y < 0 || mouse.y > height) { @@ -190,6 +189,7 @@ Rectangle { } else { parent.dropped(clipRoot) } + clipRoot.clicked(clipRoot, mouse.modifiers === Qt.ShiftModifier) } onDoubleClicked: timeline.position = clipRoot.x / timeline.scaleFactor onWheel: zoomByWheel(wheel) diff --git a/src/timeline2/view/qml/timeline.qml b/src/timeline2/view/qml/timeline.qml index 23ca1d350..c62e9b534 100644 --- a/src/timeline2/view/qml/timeline.qml +++ b/src/timeline2/view/qml/timeline.qml @@ -796,7 +796,7 @@ Rectangle { currentTrack = track.DelegateModel.itemsIndex if (shiftClick === 1) { timeline.addSelection(clip.clipId) - } else { + } else if (!timeline.isInSelection(clip.clipId) ) { timeline.selection = [ clip.clipId ] } timeline.showAsset(clip.clipId) diff --git a/src/timeline2/view/timelinecontroller.cpp b/src/timeline2/view/timelinecontroller.cpp index 4f66d30df..5b3b83abb 100644 --- a/src/timeline2/view/timelinecontroller.cpp +++ b/src/timeline2/view/timelinecontroller.cpp @@ -31,6 +31,7 @@ #include "timeline2/model/timelineitemmodel.hpp" #include "timeline2/model/trackmodel.hpp" #include "timeline2/model/compositionmodel.hpp" +#include <timeline2/model/groupsmodel.hpp> #include "timelinewidget.h" #include "utils/KoIconUtils.h" @@ -80,6 +81,9 @@ void TimelineController::addSelection(int newSelection) return; } m_selection.selectedClips << newSelection; + std::unordered_set<int> ids; + ids.insert(m_selection.selectedClips.cbegin(), m_selection.selectedClips.cend()); + m_model->requestClipsGroup(ids, true, true); emit selectionChanged(); if (!m_selection.selectedClips.isEmpty()) @@ -152,6 +156,9 @@ void TimelineController::setSelection(const QList<int> &newSelection, int trackI m_selection.selectedClips = newSelection; m_selection.selectedTrack = trackIndex; m_selection.isMultitrackSelected = isMultitrack; + std::unordered_set<int> ids; + ids.insert(m_selection.selectedClips.cbegin(), m_selection.selectedClips.cend()); + m_model->requestClipsGroup(ids, true, true); emit selectionChanged(); if (!m_selection.selectedClips.isEmpty()) @@ -359,7 +366,6 @@ void TimelineController::editMarker(const QString &cid, int frame) void TimelineController::editGuide(int frame) { - bool markerFound = false; if (frame == -1) { frame = m_position; } @@ -466,6 +472,7 @@ void TimelineController::selectItems(QVariantList arg, int startFrame, int endFr for (int x: clipsToSelect) { m_selection.selectedClips << x; } + m_model->requestClipsGroup(clipsToSelect, true, true); emit selectionChanged(); } @@ -627,3 +634,11 @@ void TimelineController::focusItem(int itemId) int start = m_model->getItemPosition(itemId); setPosition(start); } + +bool TimelineController::isInSelection(int cid) const +{ + if (m_model->m_temporarySelectionGroup == -1 || !m_model->m_groups->isInGroup(cid)) { + return false; + } + return (m_model->m_groups->getRootId(cid) == m_model->m_temporarySelectionGroup); +} diff --git a/src/timeline2/view/timelinecontroller.h b/src/timeline2/view/timelinecontroller.h index a2c056bda..aec975026 100644 --- a/src/timeline2/view/timelinecontroller.h +++ b/src/timeline2/view/timelinecontroller.h @@ -119,6 +119,8 @@ public: Q_INVOKABLE void triggerAction(const QString &name); + Q_INVOKABLE bool isInSelection(int cid) const; + /* @brief Do we want to display video thumbnails */ bool showThumbnails() const; |
From: Jean-Baptiste M. <nu...@kd...> - 2017-07-28 12:36:37
|
Git commit f4192f9f1e7ddbe16fd17e16be7be525b22427e1 by Jean-Baptiste Mardelle. Committed on 28/07/2017 at 12:35. Pushed by mardelle into branch 'refactoring_timeline'. Preliminary support for rubber selection in timeline M +1 -0 src/timeline2/model/trackmodel.cpp M +60 -12 src/timeline2/view/qml/timeline.qml M +13 -0 src/timeline2/view/timelinecontroller.cpp M +2 -0 src/timeline2/view/timelinecontroller.h https://commits.kde.org/kdenlive/f4192f9f1e7ddbe16fd17e16be7be525b22427e1 diff --git a/src/timeline2/model/trackmodel.cpp b/src/timeline2/model/trackmodel.cpp index 4fc432476..980f37008 100644 --- a/src/timeline2/model/trackmodel.cpp +++ b/src/timeline2/model/trackmodel.cpp @@ -823,3 +823,4 @@ bool TrackModel::hasIntersectingComposition(int in, int out) const return false; } + diff --git a/src/timeline2/view/qml/timeline.qml b/src/timeline2/view/qml/timeline.qml index aed2f8ef2..23ca1d350 100644 --- a/src/timeline2/view/qml/timeline.qml +++ b/src/timeline2/view/qml/timeline.qml @@ -405,7 +405,17 @@ Rectangle { } onPressed: { focus = true - if (root.activeTool === 2 && mouse.y > ruler.height) { + if (mouse.modifiers & Qt.ShiftModifier) { + // rubber selection + rubberSelect.visible = true + rubberSelect.x = mouse.x + tracksArea.x + rubberSelect.y = mouse.y + rubberSelect.originX = mouse.x + rubberSelect.originY = rubberSelect.y + rubberSelect.width = 0 + rubberSelect.height = 0 + } else if (mouse.button & Qt.LeftButton) { + if (root.activeTool === 2 && mouse.y > ruler.height) { // spacer tool var y = mouse.y - ruler.height var frame = (scrollView.flickableItem.contentX + mouse.x) / timeline.scaleFactor @@ -418,22 +428,21 @@ Rectangle { spacerClickFrame = frame spacerFrame = controller.getClipPosition(spacerGroup) } - } - } - onClicked: { - if (mouse.button & Qt.RightButton) { - menu.clickedX = mouse.x - menu.clickedY = mouse.y - menu.popup() - } else { - if (root.activeTool === 0 || mouse.y <= ruler.height) { + } else if (root.activeTool === 0 || mouse.y <= ruler.height) { timeline.seekPosition = (scrollView.flickableItem.contentX + mouse.x) / timeline.scaleFactor timeline.position = timeline.seekPosition } else if (root.activeTool === 1) { // razor tool var y = mouse.y - ruler.height timeline.cutClipUnderCursor((scrollView.flickableItem.contentX + mouse.x) / timeline.scaleFactor, tracksRepeater.itemAt(Logic.getTrackIndexFromPos(y)).trackId) - } + } + } + } + onClicked: { + if (mouse.button & Qt.RightButton) { + menu.clickedX = mouse.x + menu.clickedY = mouse.y + menu.popup() } } property bool scim: false @@ -441,7 +450,24 @@ Rectangle { scim = false } onPositionChanged: { - if (mouse.buttons === Qt.LeftButton) { + if (rubberSelect.visible) { + var newX = mouse.x + var newY = mouse.y + if (newX < rubberSelect.originX) { + rubberSelect.x = newX + tracksArea.x + rubberSelect.width = rubberSelect.originX - newX + } else { + rubberSelect.x = rubberSelect.originX + tracksArea.x + rubberSelect.width = newX - rubberSelect.originX + } + if (newY < rubberSelect.originY) { + rubberSelect.y = newY + rubberSelect.height = rubberSelect.originY - newY + } else { + rubberSelect.y = rubberSelect.originY + rubberSelect.height= newY - rubberSelect.originY + } + } else if (mouse.buttons === Qt.LeftButton) { if (root.activeTool === 0) { timeline.seekPosition = (scrollView.flickableItem.contentX + mouse.x) / timeline.scaleFactor timeline.position = timeline.seekPosition @@ -463,6 +489,18 @@ Rectangle { } } onReleased: { + if (rubberSelect.visible) { + rubberSelect.visible = false + var topTrack = Logic.getTrackIndexFromPos(rubberSelect.y - ruler.height) + var bottomTrack = Logic.getTrackIndexFromPos(rubberSelect.y - ruler.height + rubberSelect.height) + var t = [] + for (var i = topTrack; i <= bottomTrack; i++) { + t.push(tracksRepeater.itemAt(i).trackId) + } + var startFrame = (scrollView.flickableItem.contentX - tracksArea.x + rubberSelect.x) / timeline.scaleFactor + var endFrame = (scrollView.flickableItem.contentX - tracksArea.x + rubberSelect.x + rubberSelect.width) / timeline.scaleFactor + timeline.selectItems(t, startFrame, endFrame); + } if (spacerGroup > -1) { var frame = controller.getClipPosition(spacerGroup) timeline.requestSpacerEndOperation(spacerGroup, spacerFrame, frame); @@ -717,6 +755,16 @@ Rectangle { bubbleHelp.opacity = 0 } } + + Rectangle { + id: rubberSelect + property int originX + property int originY + color: Qt.rgba(activePalette.highlight.r, activePalette.highlight.g, activePalette.highlight.b, 0.4) + border.color: activePalette.highlight + border.width: 1 + visible: false + } /*DropShadow { source: bubbleHelp anchors.fill: bubbleHelp diff --git a/src/timeline2/view/timelinecontroller.cpp b/src/timeline2/view/timelinecontroller.cpp index ab0c6daa6..4f66d30df 100644 --- a/src/timeline2/view/timelinecontroller.cpp +++ b/src/timeline2/view/timelinecontroller.cpp @@ -456,6 +456,19 @@ void TimelineController::setZoneOut(int outPoint) emit zoneMoved(m_zone); } +void TimelineController::selectItems(QVariantList arg, int startFrame, int endFrame) +{ + std::unordered_set<int>clipsToSelect; + for (int i = 0; i < arg.count(); i++) { + std::unordered_set<int> trackClips = m_model->getTrackById(arg.at(i).toInt())->getClipsAfterPosition(startFrame, endFrame); + clipsToSelect.insert(trackClips.begin(), trackClips.end()); + } + for (int x: clipsToSelect) { + m_selection.selectedClips << x; + } + emit selectionChanged(); +} + void TimelineController::cutClipUnderCursor(int position, int track) { if (position == -1) { diff --git a/src/timeline2/view/timelinecontroller.h b/src/timeline2/view/timelinecontroller.h index 3b5d269bb..a2c056bda 100644 --- a/src/timeline2/view/timelinecontroller.h +++ b/src/timeline2/view/timelinecontroller.h @@ -159,6 +159,8 @@ public: */ Q_INVOKABLE void showAsset(int id); + Q_INVOKABLE void selectItems(QVariantList arg, int startFrame, int endFrame); + /* @brief Seek to next snap point */ void gotoNextSnap(); |
From: Jean-Baptiste M. <nu...@kd...> - 2017-07-28 12:36:36
|
Git commit e582fd8df3bbf2a5aa7d07e418eadf52ce4ff5f2 by Jean-Baptiste Mardelle. Committed on 28/07/2017 at 07:12. Pushed by mardelle into branch 'refactoring_timeline'. Cleanup monitor activation, try to avoid unnecessary refresh M +3 -15 src/bin/bin.cpp M +0 -1 src/bin/bin.h M +0 -1 src/mainwindow.cpp M +3 -7 src/monitor/monitor.cpp M +1 -1 src/monitor/monitor.h M +2 -6 src/monitor/monitormanager.cpp M +6 -3 src/project/projectmanager.cpp M +1 -1 src/project/projectmanager.h https://commits.kde.org/kdenlive/e582fd8df3bbf2a5aa7d07e418eadf52ce4ff5f2 diff --git a/src/bin/bin.cpp b/src/bin/bin.cpp index 9c100df19..4fb9f76d9 100644 --- a/src/bin/bin.cpp +++ b/src/bin/bin.cpp @@ -847,7 +847,9 @@ void Bin::slotCreateAudioThumbs() bool Bin::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::MouseButtonRelease) { - m_monitor->slotActivateMonitor(); + if (!m_monitor->isActive()) { + m_monitor->slotActivateMonitor(); + } bool success = QWidget::eventFilter(obj, event); if (m_gainedFocus) { QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); @@ -1224,7 +1226,6 @@ void Bin::setDocument(KdenliveDoc *project) slotInitView(nullptr); bool binEffectsDisabled = getDocumentProperty(QStringLiteral("disablebineffects")).toInt() == 1; setBinEffectsEnabled(!binEffectsDisabled); - autoSelect(); } void Bin::slotAddUrl(const QString &url, int folderId, const QMap<QString, QString> &dataMap) @@ -1497,17 +1498,6 @@ void Bin::selectProxyModel(const QModelIndex &id) } } -void Bin::autoSelect() -{ - /*QModelIndex current = m_proxyModel->selectionModel()->currentIndex(); - AbstractProjectItem *currentItem = static_cast<AbstractProjectItem *>(m_proxyModel->mapToSource(current).internalPointer()); - if (!currentItem) { - QModelIndex id = m_proxyModel->index(0, 0, QModelIndex()); - //selectModel(id); - //m_proxyModel->selectionModel()->select(m_proxyModel->mapFromSource(id), QItemSelectionModel::Select); - }*/ -} - QList<std::shared_ptr<ProjectClip>> Bin::selectedClips() { // TODO: handle clips inside folders @@ -2021,7 +2011,6 @@ void Bin::slotProducerReady(const requestClipInfo &info, std::shared_ptr<Mlt::Pr } } } else if (currentClip == info.clipId) { - emit openClip(std::shared_ptr<ProjectClip>()); setCurrent(clip); } } @@ -2066,7 +2055,6 @@ void Bin::selectClip(const std::shared_ptr<ProjectClip> &clip) } selectProxyModel(m_proxyModel->mapFromSource(ix)); m_itemView->scrollTo(m_proxyModel->mapFromSource(ix)); - pCore->monitorManager()->activateMonitor(Kdenlive::ClipMonitor); emit openClip(clip); } diff --git a/src/bin/bin.h b/src/bin/bin.h index 5735aa5b3..94435f855 100644 --- a/src/bin/bin.h +++ b/src/bin/bin.h @@ -326,7 +326,6 @@ private slots: const QString &details = QString()); void slotSetIconSize(int size); void selectProxyModel(const QModelIndex &id); - void autoSelect(); void slotSaveHeaders(); void slotItemDropped(const QStringList &ids, const QModelIndex &parent); void slotItemDropped(const QList<QUrl> &urls, const QModelIndex &parent); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b73455faf..8961eec01 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1955,7 +1955,6 @@ void MainWindow::connectDocument() connect(project, &KdenliveDoc::startAutoSave, pCore->projectManager(), &ProjectManager::slotStartAutoSave); connect(project, &KdenliveDoc::reloadEffects, this, &MainWindow::slotReloadEffects); KdenliveSettings::setProject_fps(pCore->getCurrentFps()); - m_clipMonitorDock->raise(); // TODO REFAC: reconnect to new timeline /* diff --git a/src/monitor/monitor.cpp b/src/monitor/monitor.cpp index 6745df60c..8faa6c61b 100644 --- a/src/monitor/monitor.cpp +++ b/src/monitor/monitor.cpp @@ -1223,7 +1223,6 @@ void Monitor::start() void Monitor::slotRefreshMonitor(bool visible) { if (visible) { - parentWidget()->raise(); slotActivateMonitor(true); } } @@ -1314,10 +1313,6 @@ void Monitor::slotOpenClip(std::shared_ptr<ProjectClip> controller, int in, int } m_controller = controller; m_snaps.reset(new SnapModel()); - if (!m_glMonitor->isVisible()) { - // Don't load clip if monitor is not active (disabled) - return; - } if (controller) { m_controller->getMarkerModel()->registerSnapModel(m_snaps); connect(m_controller->getMarkerModel().get(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &, const QVector<int> &)), this, @@ -1345,6 +1340,7 @@ void Monitor::slotOpenClip(std::shared_ptr<ProjectClip> controller, int in, int m_glMonitor->setAudioThumb(); m_audioMeterWidget->audioChannels = 0; } + slotActivateMonitor(); checkOverlay(); } @@ -2088,9 +2084,9 @@ void Monitor::requestSeek(int pos) m_glMonitor->seek(pos); } -void Monitor::setProducer(Mlt::Producer *producer) +void Monitor::setProducer(Mlt::Producer *producer, int pos) { - m_glMonitor->setProducer(producer, isActive(), -1); + m_glMonitor->setProducer(producer, isActive(), pos); } void Monitor::reconfigure() diff --git a/src/monitor/monitor.h b/src/monitor/monitor.h index 128a54bc7..09797205e 100644 --- a/src/monitor/monitor.h +++ b/src/monitor/monitor.h @@ -154,7 +154,7 @@ public: void activateSplit(); /** @brief Clear monitor display **/ void clearDisplay(); - void setProducer(Mlt::Producer *producer); + void setProducer(Mlt::Producer *producer, int pos = -1); /** @brief Returns current monitor's duration in frames **/ int duration() const; void reconfigure(); diff --git a/src/monitor/monitormanager.cpp b/src/monitor/monitormanager.cpp index e5a82b93b..46434d9c3 100644 --- a/src/monitor/monitormanager.cpp +++ b/src/monitor/monitormanager.cpp @@ -53,7 +53,6 @@ Timecode MonitorManager::timecode() const void MonitorManager::setDocument(KdenliveDoc *doc) { m_document = doc; - activateMonitor(Kdenlive::ProjectMonitor); } QAction *MonitorManager::getAction(const QString &name) @@ -146,16 +145,15 @@ bool MonitorManager::activateMonitor(Kdenlive::MonitorId name, bool forceRefresh return false; } QMutexLocker locker(&m_switchMutex); - m_activeMonitor = nullptr; + bool stopCurrent = m_activeMonitor != nullptr; for (int i = 0; i < m_monitorsList.count(); ++i) { if (m_monitorsList.at(i)->id() == name) { m_activeMonitor = m_monitorsList.at(i); - } else { + } else if (stopCurrent) { m_monitorsList.at(i)->stop(); } } if (m_activeMonitor) { - m_activeMonitor->blockSignals(true); m_activeMonitor->parentWidget()->raise(); if (name == Kdenlive::ClipMonitor) { emit updateOverlayInfos(name, KdenliveSettings::displayClipMonitorInfo()); @@ -166,8 +164,6 @@ bool MonitorManager::activateMonitor(Kdenlive::MonitorId name, bool forceRefresh m_clipMonitor->displayAudioMonitor(false); m_projectMonitor->displayAudioMonitor(true); } - m_activeMonitor->blockSignals(false); - m_activeMonitor->start(); } emit checkColorScopes(); return (m_activeMonitor != nullptr); diff --git a/src/project/projectmanager.cpp b/src/project/projectmanager.cpp index 88462380b..e5395f82a 100644 --- a/src/project/projectmanager.cpp +++ b/src/project/projectmanager.cpp @@ -234,6 +234,7 @@ void ProjectManager::newFile(bool showProjectSettings, bool force) emit docOpened(m_project); //pCore->monitorManager()->activateMonitor(Kdenlive::ClipMonitor); m_lastSave.start(); + pCore->monitorManager()->activateMonitor(Kdenlive::ClipMonitor, true); } bool ProjectManager::closeCurrentDocument(bool saveChanges, bool quit) @@ -570,7 +571,7 @@ void ProjectManager::doOpenFile(const QUrl &url, KAutoSaveFile *stale) disableEffects->blockSignals(false); } }*/ - updateTimeline(); + updateTimeline(m_project->getDocumentProperty("position").toInt()); pCore->window()->connectDocument(); emit docOpened(m_project); @@ -594,6 +595,8 @@ void ProjectManager::doOpenFile(const QUrl &url, KAutoSaveFile *stale) m_lastSave.start(); delete m_progressDialog; m_progressDialog = nullptr; + pCore->monitorManager()->activateMonitor(Kdenlive::ProjectMonitor, true); + //pCore->monitorManager()->projectMonitor()->refreshMonitorIfActive(); } void ProjectManager::adjustProjectDuration() @@ -853,7 +856,7 @@ void ProjectManager::slotMoveFinished(KJob *job) } } -void ProjectManager::updateTimeline() +void ProjectManager::updateTimeline(int pos) { pCore->producerQueue()->abortOperations(); // qDebug() << "Loading xml"<<m_project->getProjectXml().constData(); @@ -865,7 +868,7 @@ void ProjectManager::updateTimeline() m_project->loadThumbs(); - pCore->monitorManager()->projectMonitor()->setProducer(m_mainTimelineModel->producer()); + pCore->monitorManager()->projectMonitor()->setProducer(m_mainTimelineModel->producer(), pos); pCore->window()->getMainTimeline()->setModel(m_mainTimelineModel); m_mainTimelineModel->setUndoStack(m_project->commandStack()); } diff --git a/src/project/projectmanager.h b/src/project/projectmanager.h index ef72ec2af..923e27163 100644 --- a/src/project/projectmanager.h +++ b/src/project/projectmanager.h @@ -152,7 +152,7 @@ signals: // void projectOpened(Project *project); protected: - void updateTimeline(); + void updateTimeline(int pos = -1); private: /** @brief Checks that the Kdenlive mime type is correctly installed. |
From: Nicolas C. <nu...@kd...> - 2017-07-27 17:51:12
|
Git commit 4b77eab9d90f57d3465444160d31be54ef53c5d2 by Nicolas Carion. Committed on 27/07/2017 at 17:06. Pushed by alcinos into branch 'refactoring_timeline'. More cleanup on guides/markers and create common GUI function for edition M +31 -26 src/bin/model/markerlistmodel.cpp M +15 -7 src/bin/model/markerlistmodel.hpp M +0 -24 src/bin/projectclip.cpp M +0 -4 src/bin/projectclip.h M +2 -1 src/dialogs/CMakeLists.txt R +0 -0 src/dialogs/markerdialog.cpp [from: src/timeline/markerdialog.cpp - 100% similarity] R +0 -0 src/dialogs/markerdialog.h [from: src/timeline/markerdialog.h - 100% similarity] M +0 -17 src/doc/kdenlivedoc.cpp M +0 -4 src/doc/kdenlivedoc.h M +12 -39 src/mainwindow.cpp M +4 -15 src/mltcontroller/clippropertiescontroller.cpp M +20 -34 src/monitor/monitor.cpp M +0 -1 src/timeline/CMakeLists.txt M +8 -1 src/timeline/customtrackview.cpp D +0 -136 src/timeline2/view/dialogs/markerdialog.cpp D +0 -64 src/timeline2/view/dialogs/markerdialog.h M +9 -36 src/timeline2/view/timelinecontroller.cpp https://commits.kde.org/kdenlive/4b77eab9d90f57d3465444160d31be54ef53c5d2 diff --git a/src/bin/model/markerlistmodel.cpp b/src/bin/model/markerlistmodel.cpp index bc17976e7..f4c80f4a7 100644 --- a/src/bin/model/markerlistmodel.cpp +++ b/src/bin/model/markerlistmodel.cpp @@ -23,6 +23,7 @@ #include "bin/bin.h" #include "bin/projectclip.h" #include "core.h" +#include "dialogs/markerdialog.h" #include "doc/docundostack.hpp" #include "kdenlivesettings.h" #include "macros.hpp" @@ -94,7 +95,7 @@ bool MarkerListModel::addMarker(GenTime pos, const QString &comment, int type, F return false; } -void MarkerListModel::addMarker(GenTime pos, const QString &comment, int type) +bool MarkerListModel::addMarker(GenTime pos, const QString &comment, int type) { QWriteLocker locker(&m_lock); Fun undo = []() { return true; }; @@ -109,6 +110,7 @@ void MarkerListModel::addMarker(GenTime pos, const QString &comment, int type) PUSH_UNDO(undo, redo, m_guide ? i18n("Add guide") : i18n("Add marker")); } } + return res; } bool MarkerListModel::removeMarker(GenTime pos, Fun &undo, Fun &redo) @@ -126,7 +128,7 @@ bool MarkerListModel::removeMarker(GenTime pos, Fun &undo, Fun &redo) return false; } -void MarkerListModel::removeMarker(GenTime pos) +bool MarkerListModel::removeMarker(GenTime pos) { QWriteLocker locker(&m_lock); Fun undo = []() { return true; }; @@ -136,36 +138,16 @@ void MarkerListModel::removeMarker(GenTime pos) if (res) { PUSH_UNDO(undo, redo, m_guide ? i18n("Delete guide") : i18n("Delete marker")); } + return res; } -void MarkerListModel::removeAllMarkers() -{ - QWriteLocker locker(&m_lock); - Fun undo = []() { return true; }; - Fun redo = []() { return true; }; - - bool res = false; - QList <GenTime> times; - // Collect marker positions - for (const auto &marker : m_markerList) { - times << marker.first; - } - // delete - for (int i = 0; i < times.count(); i++) { - res = removeMarker(times.at(i), undo, redo); - } - if (res) { - PUSH_UNDO(undo, redo, m_guide ? i18n("Delete all guides") : i18n("Delete all markers")); - } -} - -void MarkerListModel::editMarker(GenTime oldPos, GenTime pos, const QString &comment, int type) +bool MarkerListModel::editMarker(GenTime oldPos, GenTime pos, const QString &comment, int type) { QWriteLocker locker(&m_lock); Q_ASSERT(m_markerList.count(oldPos) > 0); QString oldComment = m_markerList[oldPos].first; int oldType = m_markerList[oldPos].second; - if (oldPos == pos && oldComment == comment && oldType == type) return; + if (oldPos == pos && oldComment == comment && oldType == type) return true; Fun undo = []() { return true; }; Fun redo = []() { return true; }; bool res = removeMarker(oldPos, undo, redo); @@ -178,6 +160,7 @@ void MarkerListModel::editMarker(GenTime oldPos, GenTime pos, const QString &com bool undone = undo(); Q_ASSERT(undone); } + return res; } Fun MarkerListModel::changeComment_lambda(GenTime pos, const QString &comment, int type) @@ -431,7 +414,7 @@ QString MarkerListModel::toJson() const } -bool MarkerListModel::deleteAllMarkers() +bool MarkerListModel::removeAllMarkers() { QWriteLocker locker(&m_lock); std::vector<GenTime> all_pos; @@ -452,3 +435,25 @@ bool MarkerListModel::deleteAllMarkers() PUSH_UNDO(local_undo, local_redo, m_guide ? i18n("Delete all guides") : i18n("Delete all markers")); return true; } + +bool MarkerListModel::editMarkerGui(const GenTime &pos, QWidget *parent, bool createIfNotFound, ClipController* clip) +{ + bool exists; + auto marker = getMarker(pos, &exists); + Q_ASSERT(exists || createIfNotFound); + + if (!exists && createIfNotFound) { + marker = CommentedTime(GenTime(), QString()); + } + + QScopedPointer<MarkerDialog> dialog(new MarkerDialog(clip, marker, pCore->bin()->projectTimecode(), m_guide ? i18n("Edit guide") : i18n("Edit marker"), parent)); + + if (dialog->exec() == QDialog::Accepted) { + marker = dialog->newMarker(); + if (exists) { + return editMarker(pos, marker.time(), marker.comment(), marker.markerType()); + } + return addMarker(marker.time(), marker.comment(), marker.markerType()); + } + return false; +} diff --git a/src/bin/model/markerlistmodel.hpp b/src/bin/model/markerlistmodel.hpp index 03b32ac18..b8151d506 100644 --- a/src/bin/model/markerlistmodel.hpp +++ b/src/bin/model/markerlistmodel.hpp @@ -32,6 +32,7 @@ #include <map> #include <memory> +class ClipController; class DocUndoStack; class SnapModel; @@ -61,7 +62,7 @@ public: @param comment is the text associated with the marker @param type is the type (color) associated with the marker. If -1 is passed, then the value is pulled from kdenlive's defaults */ - void addMarker(GenTime pos, const QString &comment, int type = -1); + bool addMarker(GenTime pos, const QString &comment, int type = -1); protected: /* @brief Same function but accumulates undo/redo */ @@ -69,8 +70,9 @@ protected: public: /* @brief Removes the marker at the given position. */ - void removeMarker(GenTime pos); - void removeAllMarkers(); + bool removeMarker(GenTime pos); + /* @brief Delete all the markers of the model */ + bool removeAllMarkers(); protected: /* @brief Same function but accumulates undo/redo */ @@ -83,7 +85,7 @@ public: @param comment is the text associated with the marker @param type is the type (color) associated with the marker. If -1 is passed, then the value is pulled from kdenlive's defaults */ - void editMarker(GenTime oldPos, GenTime pos, const QString &comment, int type = -1); + bool editMarker(GenTime oldPos, GenTime pos, const QString &comment, int type = -1); /* @brief This describes the available markers type and their corresponding colors */ static std::array<QColor, 5> markerTypes; @@ -94,9 +96,6 @@ public: /* @brief Returns all markers in model */ QList<CommentedTime> getAllMarkers() const; - /* @brief Delete all the markers of the model */ - bool deleteAllMarkers(); - /* @brief Returns true if a marker exists at given pos Notice that add/remove queries are done in real time (gentime), but this request is made in frame */ @@ -113,6 +112,15 @@ public: /* @brief Exports the model to json using format above */ QString toJson() const; + /* @brief Shows a dialog to edit a marker/guide + @param pos: position of the marker to edit, or new position for a marker + @param widget: qt widget that will be the parent of the dialog + @param createIfNotFound: if true, we create a marker if none is found at pos + @param clip: pointer to the clip if we are editing a marker + @return true if dialog was accepted and modification successful + */ + bool editMarkerGui(const GenTime &pos, QWidget *parent, bool createIfNotFound, ClipController* clip = nullptr); + // Mandatory overloads QVariant data(const QModelIndex &index, int role) const override; QHash<int, QByteArray> roleNames() const override; diff --git a/src/bin/projectclip.cpp b/src/bin/projectclip.cpp index 0d51d42ae..f3b5acb02 100644 --- a/src/bin/projectclip.cpp +++ b/src/bin/projectclip.cpp @@ -653,30 +653,6 @@ bool ProjectClip::rename(const QString &name, int column) return edited; } - - -void ProjectClip::addMarkers(QList<CommentedTime> &markers) -{ - // TODO refac : this must be cleaned - for (int i = 0; i < markers.count(); ++i) { - if (markers.at(i).markerType() < 0) { - m_markerModel->removeMarker(markers.at(i).time()); - } else { - m_markerModel->addMarker(markers.at(i).time(), markers.at(i).comment(), markers.at(i).markerType()); - } - } - // refresh markers in clip monitor - //if (auto ptr = m_model.lock()) std::static_pointer_cast<ProjectItemModel>(ptr)->bin()->refreshClipMarkers(m_binId); - // refresh markers in timeline clips - setProducerProperty(QStringLiteral("kdenlive:markers"), m_markerModel->toJson()); - emit refreshClipDisplay(); -} - -CommentedTime ProjectClip::getMarker(const GenTime &pos, bool *ok) const -{ - return m_markerModel->getMarker(pos, ok); -} - /*QVariant ProjectClip::getData(DataType type) const { switch (type) { diff --git a/src/bin/projectclip.h b/src/bin/projectclip.h index 238e4ef13..bba1352e9 100644 --- a/src/bin/projectclip.h +++ b/src/bin/projectclip.h @@ -166,7 +166,6 @@ public: /** @brief Returns true if the clip matched a condition, for example vcodec=mpeg1video. */ bool matches(const QString &condition); - void addMarkers(QList<CommentedTime> &markers); /** @brief Create audio thumbnail for this clip. */ void createAudioThumbs(); /** @brief Returns the number of audio channels. */ @@ -188,9 +187,6 @@ public: /** @brief Returns true if this producer has audio and can be splitted on timeline*/ bool isSplittable() const; - /** @brief Returns a marker data at given pos */ - CommentedTime getMarker(const GenTime &pos, bool *ok) const; - /** @brief Returns true if a clip corresponding to this bin is inserted in a timeline. Note that this function does not account for children, use TreeItem::accumulate if you want to get that information as well. */ diff --git a/src/dialogs/CMakeLists.txt b/src/dialogs/CMakeLists.txt index 438256d5b..8dbe14c60 100644 --- a/src/dialogs/CMakeLists.txt +++ b/src/dialogs/CMakeLists.txt @@ -3,9 +3,10 @@ set(kdenlive_SRCS dialogs/clipcreationdialog.cpp dialogs/encodingprofilesdialog.cpp dialogs/kdenlivesettingsdialog.cpp + dialogs/markerdialog.cpp dialogs/profilesdialog.cpp dialogs/renderwidget.cpp - dialogs/wizard.cpp dialogs/titletemplatedialog.cpp + dialogs/wizard.cpp PARENT_SCOPE) diff --git a/src/timeline/markerdialog.cpp b/src/dialogs/markerdialog.cpp similarity index 100% rename from src/timeline/markerdialog.cpp rename to src/dialogs/markerdialog.cpp diff --git a/src/timeline/markerdialog.h b/src/dialogs/markerdialog.h similarity index 100% rename from src/timeline/markerdialog.h rename to src/dialogs/markerdialog.h diff --git a/src/doc/kdenlivedoc.cpp b/src/doc/kdenlivedoc.cpp index 40903c187..02fbf02a7 100644 --- a/src/doc/kdenlivedoc.cpp +++ b/src/doc/kdenlivedoc.cpp @@ -1694,23 +1694,6 @@ std::shared_ptr<MarkerListModel> KdenliveDoc::getGuideModel() const return m_guideModel; } -void KdenliveDoc::addGuides(QList<CommentedTime> &markers) -{ - for (int i = 0; i < markers.count(); ++i) { - if (markers.at(i).markerType() < 0) { - m_guideModel->removeMarker(markers.at(i).time()); - } else { - m_guideModel->addMarker(markers.at(i).time(), markers.at(i).comment(), markers.at(i).markerType()); - } - } - m_documentProperties[QStringLiteral("guides")] = m_guideModel->toJson(); -} - -CommentedTime KdenliveDoc::getGuide(const GenTime &pos, bool *ok) const -{ - return m_guideModel->getMarker(pos, ok); -} - void KdenliveDoc::guidesChanged() { m_documentProperties[QStringLiteral("guides")] = m_guideModel->toJson(); diff --git a/src/doc/kdenlivedoc.h b/src/doc/kdenlivedoc.h index c798a7b1d..9f83ab722 100644 --- a/src/doc/kdenlivedoc.h +++ b/src/doc/kdenlivedoc.h @@ -164,12 +164,8 @@ public: /** @brief Returns a pointer to the guide model */ std::shared_ptr<MarkerListModel> getGuideModel() const; - /** @brief Edit timeline guide */ - void addGuides(QList<CommentedTime> &markers); /** @brief Load bin thumbnails after document opening */ void loadThumbs(); - /** @brief Get timeline guide at pos. ok set to false if no guide */ - CommentedTime getGuide(const GenTime &pos, bool *ok) const; // TODO REFAC: delete */ Render *renderer(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 7f57c76b2..b73455faf 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -58,7 +58,6 @@ #include "scopes/scopemanager.h" #include "timeline/clipitem.h" #include "timeline/customtrackview.h" -#include "timeline/markerdialog.h" #include "timeline/timeline.h" #include "timeline/timelinesearch.h" #include "timeline/track.h" @@ -2254,10 +2253,6 @@ void MainWindow::slotAddClipMarker() std::shared_ptr<ProjectClip> clip(nullptr); GenTime pos; if (m_projectMonitor->isActive()) { - if (getMainTimeline()) { - // TODO - // getMainTimeline()->addMarkerInCurrentClip(); - } return; } else { clip = m_clipMonitor->currentController(); @@ -2268,16 +2263,7 @@ void MainWindow::slotAddClipMarker() return; } QString id = clip->AbstractProjectItem::clipId(); - CommentedTime marker(pos, i18n("Marker"), KdenliveSettings::default_marker_type()); - QPointer<MarkerDialog> d = new MarkerDialog(clip.get(), marker, project->timecode(), i18n("Add Marker"), this); - if (d->exec() == QDialog::Accepted) { - clip->addMarkers(QList<CommentedTime>() << d->newMarker()); - QString hash = clip->getClipHash(); - if (!hash.isEmpty()) { - project->cacheImage(hash + QLatin1Char('#') + QString::number(d->newMarker().time().frames(pCore->getCurrentFps())), d->markerImage()); - } - } - delete d; + clip->getMarkerModel()->editMarkerGui(pos, this, true, clip.get()); } void MainWindow::slotDeleteClipMarker(bool allowGuideDeletion) @@ -2304,7 +2290,7 @@ void MainWindow::slotDeleteClipMarker(bool allowGuideDeletion) QString id = clip->AbstractProjectItem::clipId(); bool markerFound = false; - CommentedTime marker = clip->getMarker(pos, &markerFound); + CommentedTime marker = clip->getMarkerModel()->getMarker(pos, &markerFound); if (!markerFound) { if (allowGuideDeletion && m_projectMonitor->isActive()) { slotDeleteGuide(); @@ -2313,9 +2299,7 @@ void MainWindow::slotDeleteClipMarker(bool allowGuideDeletion) } return; } - marker.setMarkerType(-1); - QList<CommentedTime> markers = {marker}; - clip->addMarkers(markers); + clip->getMarkerModel()->removeMarker(pos); } void MainWindow::slotDeleteAllClipMarkers() @@ -2336,7 +2320,11 @@ void MainWindow::slotDeleteAllClipMarkers() m_messageLabel->setMessage(i18n("Cannot find clip to remove marker"), ErrorMessage); return; } - clip->getMarkerModel()->deleteAllMarkers(); + bool ok = clip->getMarkerModel()->removeAllMarkers(); + if (!ok) { + m_messageLabel->setMessage(i18n("An error occured while deleting markers"), ErrorMessage); + return; + } } void MainWindow::slotEditClipMarker() @@ -2357,34 +2345,19 @@ void MainWindow::slotEditClipMarker() pos = GenTime(m_clipMonitor->position(), pCore->getCurrentFps()); } if (!clip) { - m_messageLabel->setMessage(i18n("Cannot find clip to remove marker"), ErrorMessage); + m_messageLabel->setMessage(i18n("Cannot find clip to edit marker"), ErrorMessage); return; } QString id = clip->AbstractProjectItem::clipId(); bool markerFound = false; - CommentedTime oldMarker = clip->getMarker(pos, &markerFound); + CommentedTime oldMarker = clip->getMarkerModel()->getMarker(pos, &markerFound); if (!markerFound) { m_messageLabel->setMessage(i18n("No marker found at cursor time"), ErrorMessage); return; } - QPointer<MarkerDialog> d = new MarkerDialog(clip.get(), oldMarker, pCore->currentDoc()->timecode(), i18n("Edit Marker"), this); - if (d->exec() == QDialog::Accepted) { - clip->addMarkers(QList<CommentedTime>() << d->newMarker()); - QString hash = clip->getClipHash(); - if (!hash.isEmpty()) { - pCore->currentDoc()->cacheImage(hash + QLatin1Char('#') + QString::number(d->newMarker().time().frames(pCore->getCurrentFps())), - d->markerImage()); - } - if (d->newMarker().time() != pos) { - // remove old marker - oldMarker.setMarkerType(-1); - QList<CommentedTime> markers = {oldMarker}; - clip->addMarkers(markers); - } - } - delete d; + clip->getMarkerModel()->editMarkerGui(pos, this, false, clip.get()); } void MainWindow::slotAddMarkerGuideQuickly() @@ -2402,7 +2375,7 @@ void MainWindow::slotAddMarkerGuideQuickly() return; } CommentedTime marker(pos, pCore->currentDoc()->timecode().getDisplayTimecode(pos, false), KdenliveSettings::default_marker_type()); - clip->addMarkers(QList<CommentedTime>() << marker); + clip->getMarkerModel()->addMarker(marker.time(), marker.comment(), marker.markerType()); } else { getMainTimeline()->controller()->switchGuide(); } diff --git a/src/mltcontroller/clippropertiescontroller.cpp b/src/mltcontroller/clippropertiescontroller.cpp index 3639c5b0f..ad8c748cc 100644 --- a/src/mltcontroller/clippropertiescontroller.cpp +++ b/src/mltcontroller/clippropertiescontroller.cpp @@ -29,7 +29,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "kdenlivesettings.h" #include "project/projectmanager.h" #include "timecodedisplay.h" -#include "timeline/markerdialog.h" #include "utils/KoIconUtils.h" #include "widgets/choosecolorwidget.h" @@ -895,14 +894,7 @@ void ClipPropertiesController::slotEditMarker() auto current = m_markerTree->currentIndex(); if (!current.isValid()) return; GenTime pos(markerModel->data(current, MarkerListModel::PosRole).toDouble()); - bool markerFound = false; - CommentedTime marker = markerModel->getMarker(pos, &markerFound); - Q_ASSERT(markerFound); - QScopedPointer<MarkerDialog> d(new MarkerDialog(m_controller, marker, m_tc, i18n("Edit Marker"), this)); - if (d->exec() == QDialog::Accepted) { - marker = d->newMarker(); - markerModel->editMarker(pos, marker.time(), marker.comment(), marker.markerType()); - } + markerModel->editMarkerGui(pos, this, false, m_controller); } void ClipPropertiesController::slotDeleteMarker() @@ -916,12 +908,9 @@ void ClipPropertiesController::slotDeleteMarker() void ClipPropertiesController::slotAddMarker() { - CommentedTime marker(GenTime(m_controller->originalProducer()->position(), m_tc.fps()), i18n("Marker")); - QScopedPointer<MarkerDialog> d(new MarkerDialog(m_controller, marker, m_tc, i18n("Add Marker"), this)); - if (d->exec() == QDialog::Accepted) { - marker = d->newMarker(); - m_controller->getMarkerModel()->addMarker(marker.time(), marker.comment(), marker.markerType()); - } + auto markerModel = m_controller->getMarkerModel(); + GenTime pos(m_controller->originalProducer()->position(), m_tc.fps()); + markerModel->editMarkerGui(pos, this, true, m_controller); } void ClipPropertiesController::slotSaveMarkers() diff --git a/src/monitor/monitor.cpp b/src/monitor/monitor.cpp index 8704eb071..6745df60c 100644 --- a/src/monitor/monitor.cpp +++ b/src/monitor/monitor.cpp @@ -1052,22 +1052,16 @@ void Monitor::checkOverlay(int pos) pos = m_timePos->getValue(); } QPoint zone = m_glMonitor->getControllerProxy()->zone(); - if (m_id == Kdenlive::ClipMonitor) { - if (m_controller) { - bool found = false; - CommentedTime marker = m_controller->getMarker(GenTime(pos, m_monitorManager->timecode().fps()), &found); - if (!found) { - if (pos == zone.x()) { - overlayText = i18n("In Point"); - } else if (pos == zone.y()) { - overlayText = i18n("Out Point"); - } - } else - overlayText = marker.comment(); - } + std::shared_ptr<MarkerListModel> model; + if (m_id == Kdenlive::ClipMonitor && m_controller) { + model = m_controller->getMarkerModel(); } else if (m_id == Kdenlive::ProjectMonitor && pCore->currentDoc()) { + model = pCore->currentDoc()->getGuideModel(); + } + + if (model) { bool found = false; - CommentedTime marker = pCore->currentDoc()->getGuide(GenTime(pos, m_monitorManager->timecode().fps()), &found); + CommentedTime marker = model->getMarker(GenTime(pos, m_monitorManager->timecode().fps()), &found); if (!found) { if (pos == zone.x()) { overlayText = i18n("In Point"); @@ -1076,7 +1070,6 @@ void Monitor::checkOverlay(int pos) } } else { overlayText = marker.comment(); - qDebug() << "/// POSITOIN: " << pos << " = " << overlayText; } } m_glMonitor->rootObject()->setProperty("markerText", overlayText); @@ -1999,29 +1992,22 @@ void Monitor::slotEditInlineMarker() { QQuickItem *root = m_glMonitor->rootObject(); if (root) { + std::shared_ptr<MarkerListModel> model; if (m_controller) { // We are editing a clip marker - QString newComment = root->property("markerText").toString(); - bool found = false; - CommentedTime oldMarker = m_controller->getMarker(m_timePos->gentime(), &found); - if (!found || newComment == oldMarker.comment()) { - // No change - return; - } - oldMarker.setComment(newComment); - m_controller->addMarkers(QList<CommentedTime>() << oldMarker); + model = m_controller->getMarkerModel(); } else { - // We are editing a timeline guide - QString newComment = root->property("markerText").toString(); - bool found = false; - CommentedTime oldMarker = pCore->currentDoc()->getGuide(m_timePos->gentime(), &found); - if (!found || newComment == oldMarker.comment()) { - // No change - return; - } - oldMarker.setComment(newComment); - pCore->currentDoc()->addGuides(QList<CommentedTime>() << oldMarker); + model = pCore->currentDoc()->getGuideModel(); + } + QString newComment = root->property("markerText").toString(); + bool found = false; + CommentedTime oldMarker = model->getMarker(m_timePos->gentime(), &found); + if (!found || newComment == oldMarker.comment()) { + // No change + return; } + oldMarker.setComment(newComment); + model->addMarker(oldMarker.time(), oldMarker.comment(), oldMarker.markerType()); } } diff --git a/src/timeline/CMakeLists.txt b/src/timeline/CMakeLists.txt index 53500fc53..d60a3e398 100644 --- a/src/timeline/CMakeLists.txt +++ b/src/timeline/CMakeLists.txt @@ -12,7 +12,6 @@ set(kdenlive_SRCS timeline/guide.cpp timeline/headertrack.cpp timeline/keyframeview.cpp - timeline/markerdialog.cpp timeline/spacerdialog.cpp timeline/timeline.cpp timeline/timelinecommands.cpp diff --git a/src/timeline/customtrackview.cpp b/src/timeline/customtrackview.cpp index d99bb4e30..c75543363 100644 --- a/src/timeline/customtrackview.cpp +++ b/src/timeline/customtrackview.cpp @@ -39,7 +39,6 @@ #include "managers/selectmanager.h" #include "managers/spacermanager.h" #include "managers/trimmanager.h" -#include "markerdialog.h" #include "mltcontroller/clipcontroller.h" #include "mltcontroller/effectscontroller.h" #include "project/clipmanager.h" @@ -6233,6 +6232,7 @@ bool CustomTrackView::addGuide(const GenTime &pos, const QString &comment, bool void CustomTrackView::slotAddGuide(bool dialog) { + /* CommentedTime marker(GenTime(m_cursorPos, pCore->getCurrentFps()), i18n("Guide")); if (dialog) { QPointer<MarkerDialog> d = new MarkerDialog(nullptr, marker, m_document->timecode(), i18n("Add Guide"), this); @@ -6249,10 +6249,12 @@ void CustomTrackView::slotAddGuide(bool dialog) EditGuideCommand *command = new EditGuideCommand(this, GenTime(), QString(), marker.time(), marker.comment(), false); m_commandStack->push(command); } + */ } void CustomTrackView::slotEditGuide(int guidePos, const QString &newText) { + /* GenTime pos; if (guidePos == -1) { pos = GenTime(m_cursorPos, pCore->getCurrentFps()); @@ -6276,20 +6278,24 @@ void CustomTrackView::slotEditGuide(int guidePos, const QString &newText) if (!found) { emit displayMessage(i18n("No guide at cursor time"), ErrorMessage); } + */ } void CustomTrackView::slotEditGuide(const CommentedTime &guide) { + /* QPointer<MarkerDialog> d = new MarkerDialog(nullptr, guide, m_document->timecode(), i18n("Edit Guide"), this); if (d->exec() == QDialog::Accepted) { EditGuideCommand *command = new EditGuideCommand(this, guide.time(), guide.comment(), d->newMarker().time(), d->newMarker().comment(), true); m_commandStack->push(command); } delete d; + */ } void CustomTrackView::slotEditTimeLineGuide() { + /* if (m_dragGuide == nullptr) { return; } @@ -6300,6 +6306,7 @@ void CustomTrackView::slotEditTimeLineGuide() m_commandStack->push(command); } delete d; + */ } void CustomTrackView::slotDeleteGuide(int guidePos) diff --git a/src/timeline2/view/dialogs/markerdialog.cpp b/src/timeline2/view/dialogs/markerdialog.cpp deleted file mode 100644 index 2434a723a..000000000 --- a/src/timeline2/view/dialogs/markerdialog.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Jean-Baptiste Mardelle (jb...@kd...) * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - ***************************************************************************/ - -#include "markerdialog.h" - -#include "doc/kthumb.h" -#include "kdenlivesettings.h" -#include "mltcontroller/clipcontroller.h" - -#include <QWheelEvent> -#include "kdenlive_debug.h" -#include <QTimer> -#include <QFontDatabase> - -#include "klocalizedstring.h" - -MarkerDialog::MarkerDialog(ClipController *clip, const CommentedTime &t, const Timecode &tc, const QString &caption, QWidget *parent) - : QDialog(parent) - , m_clip(clip) - , m_dar(4.0 / 3.0) -{ - setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); - setupUi(this); - setWindowTitle(caption); - - // Set up categories - for (int i = 0; i < 5; ++i) { - marker_type->insertItem(i, i18n("Category %1", i)); - marker_type->setItemData(i, CommentedTime::markerColor(i), Qt::DecorationRole); - } - marker_type->setCurrentIndex(t.markerType()); - - m_in = new TimecodeDisplay(tc, this); - inputLayout->addWidget(m_in); - m_in->setValue(t.time()); - - m_previewTimer = new QTimer(this); - - if (m_clip != nullptr) { - m_in->setRange(0, m_clip->getPlaytime().frames(tc.fps())); - m_previewTimer->setInterval(500); - connect(m_previewTimer, &QTimer::timeout, this, &MarkerDialog::slotUpdateThumb); - m_dar = m_clip->dar(); - int width = Kdenlive::DefaultThumbHeight * m_dar; - QPixmap p(width, Kdenlive::DefaultThumbHeight); - p.fill(Qt::transparent); - QString colour = clip->property(QStringLiteral("colour")); - - switch (m_clip->clipType()) { - case Video: - case AV: - case SlideShow: - case Playlist: - m_previewTimer->start(); - connect(this, SIGNAL(updateThumb()), m_previewTimer, SLOT(start())); - break; - case Image: - case Text: - case QText: - m_previewTimer->start(); - //p = m_clip->pixmap(m_in->getValue(), width, height); - break; - case Color: - colour = colour.replace(0, 2, QLatin1Char('#')); - p.fill(QColor(colour.left(7))); - break; - //UNKNOWN, AUDIO, VIRTUAL: - default: - p.fill(Qt::black); - } - - if (!p.isNull()) { - clip_thumb->setFixedWidth(p.width()); - clip_thumb->setFixedHeight(p.height()); - clip_thumb->setPixmap(p); - } - connect(m_in, &TimecodeDisplay::timeCodeEditingFinished, this, &MarkerDialog::updateThumb); - } else { - clip_thumb->setHidden(true); - label_category->setHidden(true); - marker_type->setHidden(true); - } - - marker_comment->setText(t.comment()); - marker_comment->selectAll(); - marker_comment->setFocus(); - adjustSize(); -} - -MarkerDialog::~MarkerDialog() -{ - delete m_previewTimer; -} - -void MarkerDialog::slotUpdateThumb() -{ - m_previewTimer->stop(); - int pos = m_in->getValue(); - int width = Kdenlive::DefaultThumbHeight * m_dar; - /*m_image = KThumb::getFrame(m_producer, pos, swidth, width, 100); - const QPixmap p = QPixmap::fromImage(m_image);*/ - const QPixmap p = m_clip->pixmap(pos, width, Kdenlive::DefaultThumbHeight); - if (!p.isNull()) { - clip_thumb->setPixmap(p); - } else { - qCDebug(KDENLIVE_LOG) << "!!!!!!!!!!! ERROR CREATING THUMB"; - } -} - -QImage MarkerDialog::markerImage() const -{ - return clip_thumb->pixmap()->toImage(); -} - -CommentedTime MarkerDialog::newMarker() -{ - KdenliveSettings::setDefault_marker_type(marker_type->currentIndex()); - return CommentedTime(m_in->gentime(), marker_comment->text(), marker_type->currentIndex()); -} - diff --git a/src/timeline2/view/dialogs/markerdialog.h b/src/timeline2/view/dialogs/markerdialog.h deleted file mode 100644 index c48b90423..000000000 --- a/src/timeline2/view/dialogs/markerdialog.h +++ /dev/null @@ -1,64 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2008 by Jean-Baptiste Mardelle (jb...@kd...) * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * -***************************************************************************/ - -#ifndef MARKERDIALOG_H -#define MARKERDIALOG_H - -#include "ui_markerdialog_ui.h" - -#include "definitions.h" -#include "timecode.h" -#include "timecodedisplay.h" - -class ClipController; - -namespace Mlt { -} - -/** - * @class MarkerDialog - * @brief A dialog for editing markers and guides. - * @author Jean-Baptiste Mardelle - */ - -class MarkerDialog : public QDialog, public Ui::MarkerDialog_UI -{ - Q_OBJECT - -public: - explicit MarkerDialog(ClipController *clip, const CommentedTime &t, const Timecode &tc, const QString &caption, QWidget *parent = nullptr); - ~MarkerDialog(); - - CommentedTime newMarker(); - QImage markerImage() const; - -private slots: - void slotUpdateThumb(); - -private: - ClipController *m_clip; - TimecodeDisplay *m_in; - double m_dar; - QTimer *m_previewTimer; - -signals: - void updateThumb(); -}; - -#endif diff --git a/src/timeline2/view/timelinecontroller.cpp b/src/timeline2/view/timelinecontroller.cpp index 77f30b3eb..ab0c6daa6 100644 --- a/src/timeline2/view/timelinecontroller.cpp +++ b/src/timeline2/view/timelinecontroller.cpp @@ -25,7 +25,6 @@ #include "bin/model/markerlistmodel.hpp" #include "bin/projectclip.h" #include "core.h" -#include "dialogs/markerdialog.h" #include "doc/kdenlivedoc.h" #include "kdenlivesettings.h" #include "project/projectmanager.h" @@ -354,21 +353,8 @@ void TimelineController::setOutPoint() void TimelineController::editMarker(const QString &cid, int frame) { std::shared_ptr<ProjectClip> clip = pCore->bin()->getBinClip(cid); - bool markerFound = false; - CommentedTime marker = clip->getMarker(GenTime(frame, pCore->getCurrentFps()), &markerFound); - Q_ASSERT(markerFound); - QPointer<MarkerDialog> d = new MarkerDialog(clip.get(), marker, pCore->bin()->projectTimecode(), i18n("Edit Marker"), qApp->activeWindow()); - if (d->exec() == QDialog::Accepted) { - QList<CommentedTime> markers; - CommentedTime newMarker = d->newMarker(); - if (newMarker.time() != marker.time()) { - // marker was moved - marker.setMarkerType(-1); - markers << marker; - } - markers << newMarker; - clip->addMarkers(markers); - } + GenTime pos(frame, pCore->getCurrentFps()); + clip->getMarkerModel()->editMarkerGui(pos, qApp->activeWindow(), false, clip.get()); } void TimelineController::editGuide(int frame) @@ -377,20 +363,9 @@ void TimelineController::editGuide(int frame) if (frame == -1) { frame = m_position; } - CommentedTime marker = pCore->projectManager()->current()->getGuideModel().get()->getMarker(GenTime(frame, pCore->getCurrentFps()), &markerFound); - Q_ASSERT(markerFound); - QPointer<MarkerDialog> d = new MarkerDialog(nullptr, marker, pCore->bin()->projectTimecode(), i18n("Edit Marker"), qApp->activeWindow()); - if (d->exec() == QDialog::Accepted) { - QList<CommentedTime> markers; - CommentedTime newMarker = d->newMarker(); - if (newMarker.time() != marker.time()) { - // marker was moved - marker.setMarkerType(-1); - markers << marker; - } - markers << newMarker; - pCore->projectManager()->current()->addGuides(markers); - } + auto guideModel = pCore->projectManager()->current()->getGuideModel(); + GenTime pos(frame, pCore->getCurrentFps()); + guideModel->editMarkerGui(pos, qApp->activeWindow(), false); } void TimelineController::switchGuide(int frame, bool deleteOnly) @@ -399,19 +374,17 @@ void TimelineController::switchGuide(int frame, bool deleteOnly) if (frame == -1) { frame = m_position; } - CommentedTime marker = pCore->projectManager()->current()->getGuideModel().get()->getMarker(GenTime(frame, pCore->getCurrentFps()), &markerFound); + CommentedTime marker = pCore->projectManager()->current()->getGuideModel()->getMarker(GenTime(frame, pCore->getCurrentFps()), &markerFound); if (!markerFound) { if (deleteOnly) { pCore->displayMessage(i18n("No guide found at current position"), InformationMessage, 500); return; } - marker = CommentedTime(GenTime(frame, pCore->getCurrentFps()), i18n("guide")); + GenTime pos(frame, pCore->getCurrentFps()); + pCore->projectManager()->current()->getGuideModel()->addMarker(pos, i18n("guide")); } else { - marker.setMarkerType(-1); + pCore->projectManager()->current()->getGuideModel()->removeMarker(marker.time()); } - QList<CommentedTime> markers; - markers << marker; - pCore->projectManager()->current()->addGuides(markers); } void TimelineController::addAsset(const QVariantMap data) |
From: Nicolas C. <nu...@kd...> - 2017-07-27 17:51:10
|
Git commit 6f6e3739098b100f386cdd4e9d7e97036be07685 by Nicolas Carion. Committed on 27/07/2017 at 17:06. Pushed by alcinos into branch 'refactoring_timeline'. Make sure markers modifications are stored in ProjectClip's property M +6 -0 src/bin/projectclip.cpp https://commits.kde.org/kdenlive/6f6e3739098b100f386cdd4e9d7e97036be07685 diff --git a/src/bin/projectclip.cpp b/src/bin/projectclip.cpp index 813a3934c..0d51d42ae 100644 --- a/src/bin/projectclip.cpp +++ b/src/bin/projectclip.cpp @@ -75,6 +75,9 @@ ProjectClip::ProjectClip(const QString &id, const QIcon &thumb, std::shared_ptr< hash(); connect(this, &ProjectClip::updateJobStatus, this, &ProjectClip::setJobStatus); connect(this, &ProjectClip::updateThumbProgress, model.get(), &ProjectItemModel::updateThumbProgress); + connect(m_markerModel.get(), &MarkerListModel::modelChanged, [&](){ + setProducerProperty(QStringLiteral("kdenlive:markers"), m_markerModel->toJson()); + }); QString markers = getProducerProperty(QStringLiteral("kdenlive:markers")); if (!markers.isEmpty()) { QMetaObject::invokeMethod(m_markerModel.get(), "importFromJson", Qt::QueuedConnection, Q_ARG(const QString &, markers), Q_ARG(bool, true), Q_ARG(bool, false)); @@ -119,6 +122,9 @@ ProjectClip::ProjectClip(const QDomElement &description, const QIcon &thumb, std } connect(this, &ProjectClip::updateJobStatus, this, &ProjectClip::setJobStatus); connect(this, &ProjectClip::updateThumbProgress, model.get(), &ProjectItemModel::updateThumbProgress); + connect(m_markerModel.get(), &MarkerListModel::modelChanged, [&](){ + setProducerProperty(QStringLiteral("kdenlive:markers"), m_markerModel->toJson()); + }); } std::shared_ptr<ProjectClip> ProjectClip::construct(const QDomElement &description, const QIcon &thumb, std::shared_ptr<ProjectItemModel> model) |
From: Jean-Baptiste M. <nu...@kd...> - 2017-07-27 11:18:56
|
Git commit 18e864b95915e4362197db4e105461bb38a51d7a by Jean-Baptiste Mardelle. Committed on 27/07/2017 at 11:18. Pushed by mardelle into branch 'refactoring_timeline'. Move documentRoot property to kdenlivedoc M +0 -5 src/core.cpp M +0 -3 src/core.h M +10 -5 src/doc/kdenlivedoc.cpp M +4 -0 src/doc/kdenlivedoc.h M +1 -1 src/mainwindow.cpp M +3 -20 src/mltcontroller/bincontroller.cpp M +1 -10 src/mltcontroller/bincontroller.h M +4 -3 src/mltcontroller/clipcontroller.cpp M +2 -1 src/mltcontroller/producerqueue.cpp M +1 -1 src/renderer.cpp https://commits.kde.org/kdenlive/18e864b95915e4362197db4e105461bb38a51d7a diff --git a/src/core.cpp b/src/core.cpp index f0e122891..10186d074 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -503,8 +503,3 @@ std::shared_ptr<ProjectItemModel> Core::projectItemModel() return m_projectItemModel; } -QString Core::getDocumentRoot() const -{ - // TODO refac: the root should probably be stored elsewhere - return m_binController->documentRoot(); -} diff --git a/src/core.h b/src/core.h index 936aaa591..7b4b45d32 100644 --- a/src/core.h +++ b/src/core.h @@ -115,9 +115,6 @@ public: /** @brief Returns frame rate of current profile */ double getCurrentFps() const; - /** @brief Returns the root of the document */ - QString getDocumentRoot() const; - /** @brief Returns the frame size (width x height) of current profile */ QSize getCurrentFrameSize() const; /** @brief Returns the frame display size (width x height) of current profile */ diff --git a/src/doc/kdenlivedoc.cpp b/src/doc/kdenlivedoc.cpp index a5295688c..40903c187 100644 --- a/src/doc/kdenlivedoc.cpp +++ b/src/doc/kdenlivedoc.cpp @@ -877,7 +877,7 @@ QMap<QString, QString> KdenliveDoc::getRenderProperties() const // Check that we have a full path QString value = i.value(); if (QFileInfo(value).isRelative()) { - value.prepend(pCore->binController()->documentRoot()); + value.prepend(m_documentRoot); } renderProperties.insert(i.key(), value); } else { @@ -1283,9 +1283,9 @@ void KdenliveDoc::loadDocumentProperties() { QDomNodeList list = m_document.elementsByTagName(QStringLiteral("playlist")); QDomElement baseElement = m_document.documentElement(); - QString root = baseElement.attribute(QStringLiteral("root")); - if (!root.isEmpty()) { - root = QDir::cleanPath(root) + QDir::separator(); + m_documentRoot = baseElement.attribute(QStringLiteral("root")); + if (!m_documentRoot.isEmpty()) { + m_documentRoot = QDir::cleanPath(m_documentRoot) + QDir::separator(); } if (!list.isEmpty()) { QDomElement pl = list.at(0).toElement(); @@ -1304,7 +1304,7 @@ void KdenliveDoc::loadDocumentProperties() // Make sure we have an absolute path QString value = e.firstChild().nodeValue(); if (QFileInfo(value).isRelative()) { - value.prepend(root); + value.prepend(m_documentRoot); } m_documentProperties.insert(name, value); } else if (name == QStringLiteral("guides")) { @@ -1715,3 +1715,8 @@ void KdenliveDoc::guidesChanged() { m_documentProperties[QStringLiteral("guides")] = m_guideModel->toJson(); } + +const QString KdenliveDoc::documentRoot() const +{ + return m_documentRoot; +} diff --git a/src/doc/kdenlivedoc.h b/src/doc/kdenlivedoc.h index cb2a003d7..c798a7b1d 100644 --- a/src/doc/kdenlivedoc.h +++ b/src/doc/kdenlivedoc.h @@ -173,10 +173,14 @@ public: // TODO REFAC: delete */ Render *renderer(); + /** @brief Returns MLT's root (base path) */ + const QString documentRoot() const; private: QUrl m_url; QDomDocument m_document; + /** @brief MLT's root (base path) that is stripped from urls in saved xml */ + QString m_documentRoot; KDirWatch m_fileWatcher; /** Timer used to reload clips when they have been externally modified */ QTimer m_modifiedTimer; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index dde6448cc..7f57c76b2 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3459,7 +3459,7 @@ void MainWindow::slotPrepareRendering(bool scriptExport, bool zoneOnly, const QS // replace proxy clips with originals // TODO - QMap<QString, QString> proxies = pCore->binController()->getProxies(); + QMap<QString, QString> proxies = pCore->binController()->getProxies(pCore->currentDoc()->documentRoot()); QDomNodeList producers = doc.elementsByTagName(QStringLiteral("producer")); QString producerResource; diff --git a/src/mltcontroller/bincontroller.cpp b/src/mltcontroller/bincontroller.cpp index ded268d22..99ae9b8c2 100644 --- a/src/mltcontroller/bincontroller.cpp +++ b/src/mltcontroller/bincontroller.cpp @@ -54,23 +54,6 @@ void BinController::destroyBin() m_clipList.clear(); } -void BinController::setDocumentRoot(const QString &root) -{ - if (root.isEmpty()) { - m_documentRoot.clear(); - } else { - m_documentRoot = root; - if (!m_documentRoot.endsWith(QLatin1Char('/'))) { - m_documentRoot.append(QLatin1Char('/')); - } - } -} - -const QString BinController::documentRoot() const -{ - return m_documentRoot; -} - void BinController::loadExtraProducer(const QString &id, Mlt::Producer *prod) { if (m_extraClipList.contains(id)) { @@ -558,7 +541,7 @@ const QString BinController::getProperty(const QString &name) return QString(m_binPlaylist->get(name.toUtf8().constData())); } -QMap<QString, QString> BinController::getProxies() +QMap<QString, QString> BinController::getProxies(const QString &root) { QMap<QString, QString> proxies; int size = m_binPlaylist->count(); @@ -570,11 +553,11 @@ QMap<QString, QString> BinController::getProxies() QString proxy = prod->parent().get("kdenlive:proxy"); if (proxy.length() > 2) { if (QFileInfo(proxy).isRelative()) { - proxy.prepend(m_documentRoot); + proxy.prepend(root); } QString sourceUrl(prod->parent().get("kdenlive:originalurl")); if (QFileInfo(sourceUrl).isRelative()) { - sourceUrl.prepend(m_documentRoot); + sourceUrl.prepend(root); } proxies.insert(proxy, sourceUrl); } diff --git a/src/mltcontroller/bincontroller.h b/src/mltcontroller/bincontroller.h index 94bd1668d..1d7a3b15c 100644 --- a/src/mltcontroller/bincontroller.h +++ b/src/mltcontroller/bincontroller.h @@ -157,13 +157,7 @@ public: const QString getProperty(const QString &name); /** @brief Return a list of proxy / original url */ - QMap<QString, QString> getProxies(); - - /** @brief Loads the MLT's XML document root */ - void setDocumentRoot(const QString &); - - /** @brief Returns the MLT's XML document root */ - const QString documentRoot() const; + QMap<QString, QString> getProxies(const QString &root); /** @brief Returns a list of all clips hashes. */ QStringList getProjectHashes(); @@ -189,9 +183,6 @@ private: /** @brief This list holds all extra controllers (slowmotion, video only, ... that are in timeline, indexed by id */ QMap<QString, Mlt::Producer *> m_extraClipList; - /** @brief Stores MLT's xml playlist document root, useful to recover full urls */ - QString m_documentRoot; - /** @brief Remove a clip from MLT's special bin playlist */ void removeBinPlaylistClip(const QString &id); diff --git a/src/mltcontroller/clipcontroller.cpp b/src/mltcontroller/clipcontroller.cpp index 84758ded1..703ce1e6f 100644 --- a/src/mltcontroller/clipcontroller.cpp +++ b/src/mltcontroller/clipcontroller.cpp @@ -30,6 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "profiles/profilemodel.hpp" #include "timeline/effectmanager.h" #include "timeline/timeline.h" +#include "doc/kdenlivedoc.h" #include "core.h" #include "kdenlive_debug.h" @@ -67,11 +68,11 @@ ClipController::ClipController(const QString clipId, std::shared_ptr<BinControll // This is a proxy producer, read original url from kdenlive property path = m_properties->get("kdenlive:originalurl"); if (QFileInfo(path).isRelative()) { - path.prepend(pCore->getDocumentRoot()); + path.prepend(pCore->currentDoc()->documentRoot()); } m_usesProxy = true; } else if (m_service != QLatin1String("color") && m_service != QLatin1String("colour") && QFileInfo(path).isRelative()) { - path.prepend(pCore->getDocumentRoot()); + path.prepend(pCore->currentDoc()->documentRoot()); } m_path = QFileInfo(path).absoluteFilePath(); getInfoForProducer(); @@ -100,7 +101,7 @@ AudioStreamInfo *ClipController::audioInfo() const void ClipController::addMasterProducer(const std::shared_ptr<Mlt::Producer> &producer) { - QString documentRoot = pCore->getDocumentRoot(); + QString documentRoot = pCore->currentDoc()->documentRoot(); m_masterProducer = producer; m_properties = new Mlt::Properties(m_masterProducer->get_properties()); int id = m_properties->get_int("kdenlive:id"); diff --git a/src/mltcontroller/producerqueue.cpp b/src/mltcontroller/producerqueue.cpp index e02d67f91..9453a58a2 100644 --- a/src/mltcontroller/producerqueue.cpp +++ b/src/mltcontroller/producerqueue.cpp @@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "bin/projectclip.h" #include "bincontroller.h" #include "clipcontroller.h" +#include "doc/kdenlivedoc.h" #include "core.h" #include "dialogs/profilesdialog.h" #include "doc/kthumb.h" @@ -188,7 +189,7 @@ void ProducerQueue::processFileProperties() if (proxy == QLatin1String("-")) { path = ProjectClip::getXmlProperty(info.xml, QStringLiteral("kdenlive:originalurl")); if (QFileInfo(path).isRelative()) { - path.prepend(m_binController->documentRoot()); + path.prepend(pCore->currentDoc()->documentRoot()); } proxyProducer = false; } else { diff --git a/src/renderer.cpp b/src/renderer.cpp index fa659c7fc..28fd9ee87 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -483,7 +483,7 @@ int Render::setSceneList(QString playlist, int position) } // init MLT's document root, useful to find full urls - m_binController->setDocumentRoot(doc.documentElement().attribute(QStringLiteral("root"))); + //m_binController->setDocumentRoot(doc.documentElement().attribute(QStringLiteral("root"))); // Fill Bin's playlist Mlt::Service service(m_mltProducer->parent().get_service()); |
From: Jean-Baptiste M. <nu...@kd...> - 2017-07-27 10:49:16
|
Git commit 4a6879212a36eb1c20ab3aff3e656e5db7b42c81 by Jean-Baptiste Mardelle. Committed on 27/07/2017 at 10:48. Pushed by mardelle into branch 'refactoring_timeline'. Use compositing transition available on system, warn if none found M +1 -1 src/core.h M +26 -2 src/timeline2/model/timelineitemmodel.cpp M +1 -0 src/timeline2/model/timelineitemmodel.hpp https://commits.kde.org/kdenlive/4a6879212a36eb1c20ab3aff3e656e5db7b42c81 diff --git a/src/core.h b/src/core.h index f31e39d8a..936aaa591 100644 --- a/src/core.h +++ b/src/core.h @@ -139,7 +139,7 @@ public: void pushUndo(const Fun &undo, const Fun &redo, const QString &text); void pushUndo(QUndoCommand *command); /** @brief display a user info/warning message in statusbar */ - void displayMessage(const QString &message, MessageType type, int timeout); + void displayMessage(const QString &message, MessageType type, int timeout = -1); /** @brief Clear asset view if itemId is displayed. */ void clearAssetPanel(int itemId); void adjustAssetRange(int itemId, int in, int out); diff --git a/src/timeline2/model/timelineitemmodel.cpp b/src/timeline2/model/timelineitemmodel.cpp index 1ef90c73e..7763dc6af 100644 --- a/src/timeline2/model/timelineitemmodel.cpp +++ b/src/timeline2/model/timelineitemmodel.cpp @@ -29,6 +29,8 @@ #include "macros.hpp" #include "trackmodel.hpp" #include "transitions/transitionsrepository.hpp" +#include "kdenlivesettings.h" +#include "core.h" #include <QDebug> #include <QFileInfo> #include <mlt++/MltProfile.h> @@ -352,11 +354,12 @@ void TimelineItemModel::buildTrackCompositing() auto it = m_allTracks.cbegin(); QScopedPointer<Mlt::Field> field(m_tractor->field()); field->lock(); + QString composite = getCompositingTransition(); while (it != m_allTracks.cend()) { int trackId = getTrackMltIndex((*it)->getId()); - if ((*it)->getProperty("kdenlive:audio_track").toInt() != 1) { + if (!composite.isEmpty() && (*it)->getProperty("kdenlive:audio_track").toInt() != 1) { // video track, add composition - Mlt::Transition *transition = TransitionsRepository::get()->getTransition(QStringLiteral("qtblend")); + Mlt::Transition *transition = TransitionsRepository::get()->getTransition(composite); transition->set("internal_added", 237); transition->set("always_active", 1); int ret = field->plant_transition(*transition, 0, trackId); @@ -372,6 +375,27 @@ void TimelineItemModel::buildTrackCompositing() ++it; } field->unlock(); + if (composite.isEmpty()) { + pCore->displayMessage(i18n("Could not setup track compositing, check your install"), MessageType::ErrorMessage); + } +} + +// static +const QString TimelineItemModel::getCompositingTransition() +{ + if (KdenliveSettings::gpu_accel()) { + return QStringLiteral("movit.overlay"); + } + if (TransitionsRepository::get()->exists(QStringLiteral("qtblend"))) { + return QStringLiteral("qtblend"); + } + if (TransitionsRepository::get()->exists(QStringLiteral("frei0r.cairoblend"))) { + return QStringLiteral("frei0r.cairoblend"); + } + if (TransitionsRepository::get()->exists(QStringLiteral("composite"))) { + return QStringLiteral("composite"); + } + return QString(); } void TimelineItemModel::notifyChange(const QModelIndex &topleft, const QModelIndex &bottomright, bool start, bool duration, bool updateThumb) diff --git a/src/timeline2/model/timelineitemmodel.hpp b/src/timeline2/model/timelineitemmodel.hpp index 0ced6dbda..3e53bbe84 100644 --- a/src/timeline2/model/timelineitemmodel.hpp +++ b/src/timeline2/model/timelineitemmodel.hpp @@ -84,6 +84,7 @@ public: void notifyChange(const QModelIndex &topleft, const QModelIndex &bottomright, bool start, bool duration, bool updateThumb) override; void notifyChange(const QModelIndex &topleft, const QModelIndex &bottomright, QVector<int> roles) override; void buildTrackCompositing(); + static const QString getCompositingTransition(); virtual void _beginRemoveRows(const QModelIndex &, int, int) override; virtual void _beginInsertRows(const QModelIndex &, int, int) override; |