Commit 566b2da2 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle

Merge branch '1904'

parents 976441cf d0046fee
......@@ -130,7 +130,7 @@ GLWidget::GLWidget(int id, QObject *parent)
m_blackClip->set("out", 3);
connect(&m_refreshTimer, &QTimer::timeout, this, &GLWidget::refresh);
m_producer = m_blackClip;
rootContext()->setContextProperty("markersModel", 0);
if (!initGPUAccel()) {
disableGPUAccel();
}
......@@ -956,6 +956,8 @@ int GLWidget::setProducer(const std::shared_ptr<Mlt::Producer> &producer, bool i
removeAudioOverlay();
}
m_producer = m_blackClip;
// Reset markersModel
rootContext()->setContextProperty("markersModel", 0);
}
// redundant check. postcondition of above is m_producer != null
if (m_producer) {
......
......@@ -1353,7 +1353,6 @@ void Monitor::slotOpenClip(const std::shared_ptr<ProjectClip> &controller, int i
disconnect(m_controller->getMarkerModel().get(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SLOT(checkOverlay()));
}
m_controller = controller;
loadQmlScene(MonitorSceneDefault);
m_snaps.reset(new SnapModel());
m_glMonitor->getControllerProxy()->resetZone();
if (controller) {
......@@ -1367,6 +1366,7 @@ void Monitor::slotOpenClip(const std::shared_ptr<ProjectClip> &controller, int i
return;
}
m_glMonitor->setRulerInfo((int)m_controller->frameDuration(), controller->getMarkerModel());
loadQmlScene(MonitorSceneDefault);
m_timePos->setRange(0, (int)m_controller->frameDuration());
updateMarkers();
connect(m_glMonitor->getControllerProxy(), &MonitorProxy::addSnap, this, &Monitor::addSnapPoint, Qt::DirectConnection);
......@@ -1389,6 +1389,7 @@ void Monitor::slotOpenClip(const std::shared_ptr<ProjectClip> &controller, int i
m_glMonitor->getControllerProxy()->setClipHasAV(controller->hasAudioAndVideo());
// hasEffects = controller->hasEffects();
} else {
loadQmlScene(MonitorSceneDefault);
m_glMonitor->setProducer(nullptr, isActive());
m_glMonitor->setAudioThumb();
m_audioMeterWidget->audioChannels = 0;
......
......@@ -62,6 +62,8 @@ void QmlManager::setScene(Kdenlive::MonitorId id, MonitorSceneType type, QSize p
}
m_sceneType = type;
QQuickItem *root = nullptr;
const QFont ft = QFontDatabase::systemFont(QFontDatabase::FixedFont);
m_view->rootContext()->setContextProperty("fixedFont", ft);
switch (type) {
case MonitorSceneGeometry:
m_view->setSource(QUrl(QStringLiteral("qrc:/qml/kdenlivemonitoreffectscene.qml")));
......@@ -117,8 +119,6 @@ void QmlManager::setScene(Kdenlive::MonitorId id, MonitorSceneType type, QSize p
if (root && duration > 0) {
root->setProperty("duration", duration);
}
const QFont ft = QFontDatabase::systemFont(QFontDatabase::FixedFont);
m_view->rootContext()->setContextProperty("fixedFont", ft);
}
void QmlManager::effectRectChanged()
......
......@@ -44,6 +44,7 @@ ClipModel::ClipModel(const std::shared_ptr<TimelineModel> &parent, std::shared_p
, m_currentState(state)
, m_speed(speed)
, m_fakeTrack(-1)
, m_positionOffset(0)
{
m_producer->set("kdenlive:id", binClipId.toUtf8().constData());
m_producer->set("_kdenlive_cid", m_id);
......@@ -726,3 +727,23 @@ void ClipModel::setSubPlaylistIndex(int index)
m_subPlaylistIndex = index;
}
void ClipModel::setOffset(int offset)
{
m_positionOffset = offset;
if (auto ptr = m_parent.lock()) {
QModelIndex ix = ptr->makeClipIndexFromID(m_id);
ptr->dataChanged(ix, ix, {TimelineModel::PositionOffsetRole});
}
}
void ClipModel::clearOffset()
{
if (m_positionOffset != 0) {
setOffset(0);
}
}
int ClipModel::getOffset() const
{
return m_positionOffset;
}
......@@ -195,6 +195,12 @@ protected:
bool isAudioOnly() const;
double getSpeed() const;
/** @brief Returns the clip offset (calculated in the model between 2 clips from same bin clip */
void setOffset(int offset);
/** @brief Clears the clip offset (calculated in the model between 2 clips from same bin clip */
void clearOffset();
int getOffset() const;
/*@brief This is a debug function to ensure the clip is in a valid state */
bool checkConsistency();
......@@ -220,6 +226,8 @@ protected:
// Fake track id, used when dragging in insert/overwrite mode
int m_fakeTrack;
int m_fakePosition;
// Temporary val to store offset between two clips with same bin id.
int m_positionOffset;
int m_subPlaylistIndex; // Tracks have two sub playlists to enable same track transitions, we store in which one this clip is.
};
......
......@@ -224,6 +224,7 @@ QHash<int, QByteArray> TimelineItemModel::roleNames() const
roles[CanBeAudioRole] = "canBeAudio";
roles[CanBeVideoRole] = "canBeVideo";
roles[ReloadThumbRole] = "reloadThumb";
roles[PositionOffsetRole] = "positionOffset";
roles[ThumbsFormatRole] = "thumbsFormat";
roles[AudioRecordRole] = "audioRecord";
roles[TrackActiveRole] = "trackActive";
......@@ -333,6 +334,8 @@ QVariant TimelineItemModel::data(const QModelIndex &index, int role) const
return clip->fadeOut();
case ReloadThumbRole:
return clip->forceThumbReload;
case PositionOffsetRole:
return clip->getOffset();
case SpeedRole:
return clip->getSpeed();
case GrabbedRole:
......
......@@ -2962,6 +2962,13 @@ bool TimelineModel::requestClearSelection(bool onDeletion)
}
if (isGroup(m_currentSelection)) {
if (m_groups->getType(m_currentSelection) == GroupType::Selection) {
// Reset offset display on clips
std::unordered_set<int> items = getCurrentSelection();
for (auto &id : items) {
if (isClip(id)) {
m_allClips[id]->clearOffset();
}
}
m_groups->destructGroupItem(m_currentSelection);
}
} else {
......@@ -3047,6 +3054,34 @@ bool TimelineModel::requestSetSelection(const std::unordered_set<int> &ids)
} else {
Fun undo = []() { return true; };
Fun redo = []() { return true; };
if (ids.size() == 2) {
// Check if we selected 2 clips from the same master
QList<int> pairIds;
for(auto &id : roots) {
if (isClip(id)) {
pairIds << id;
}
}
if (pairIds.size() == 2 && getClipBinId(pairIds.at(0)) == getClipBinId(pairIds.at(1))) {
// Check if they have same bin id
// Both clips have same bin ID, display offset
int pos1 = getClipPosition(pairIds.at(0));
int pos2 = getClipPosition(pairIds.at(1));
if (pos2 > pos1) {
int offset = pos2 - pos1 - getClipIn(pairIds.at(1)) - getClipIn(pairIds.at(0));
if (offset != 0) {
m_allClips[pairIds.at(1)]->setOffset(offset);
m_allClips[pairIds.at(0)]->setOffset(-offset);
}
} else {
int offset = pos1 - pos2 - getClipIn(pairIds.at(0)) - getClipIn(pairIds.at(1));
if (offset != 0) {
m_allClips[pairIds.at(0)]->setOffset(offset);
m_allClips[pairIds.at(1)]->setOffset(-offset);
}
}
}
}
result = (m_currentSelection = m_groups->groupItems(ids, undo, redo, GroupType::Selection)) >= 0;
Q_ASSERT(m_currentSelection >= 0);
}
......
......@@ -147,6 +147,7 @@ public:
FileHashRole, /// clip only
SpeedRole, /// clip only
ReloadThumbRole, /// clip only
PositionOffsetRole,/// clip only
ItemATrack, /// composition only
ItemIdRole,
ThumbsFormatRole, /// track only
......
......@@ -49,6 +49,7 @@ Rectangle {
property int fadeIn: 0
property int fadeOut: 0
property int binId: 0
property int positionOffset: 0
property var parentTrack
property int trackIndex //Index in track repeater
property int clipId //Id of the clip in the model
......@@ -84,6 +85,11 @@ Rectangle {
}
}
function clearAndMove(offset) {
controller.requestClearSelection()
controller.requestClipMove(clipRoot.clipId, clipRoot.trackId, clipRoot.modelStart - offset, true, true, true);
}
onInPointChanged: {
if (parentTrack && parentTrack.isAudio && thumbsLoader.item) {
thumbsLoader.item.reload()
......@@ -326,6 +332,52 @@ Rectangle {
styleColor: 'black'
}
}
Rectangle {
// Offset info
id: offsetRect
color: 'darkgreen'
width: offsetLabel.width + radius
height: offsetLabel.height
radius: height/3
x: labelRect.width + 4
visible: labelRect.visible && positionOffset != 0
MouseArea {
id: offsetArea
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
clearAndMove(positionOffset)
}
ToolTip {
visible: offsetArea.containsMouse
font.pixelSize: root.baseUnit
delay: 1000
timeout: 5000
background: Rectangle {
color: activePalette.alternateBase
border.color: activePalette.light
}
contentItem: Label {
color: activePalette.text
text: i18n('Offset') + (positionOffset < 0 ? ( ': -' + timeline.timecode(-positionOffset)) : ': ' + timeline.timecode(positionOffset))
}
}
Text {
id: offsetLabel
text: positionOffset
font.pixelSize: root.baseUnit * 1.2
anchors {
horizontalCenter: parent.horizontalCenter
topMargin: 1
leftMargin: 1
}
color: 'white'
style: Text.Outline
styleColor: 'black'
}
}
}
Rectangle {
// effects
id: effectsRect
......@@ -486,7 +538,7 @@ Rectangle {
}
contentItem: Label {
color: activePalette.text
text: 'Click to add composition'
text: i18n('Click to add composition')
}
}
}
......@@ -536,7 +588,7 @@ Rectangle {
}
contentItem: Label {
color: activePalette.text
text: 'Click to add composition'
text: i18n('Click to add composition')
}
}
}
......
......@@ -104,6 +104,12 @@ Column{
value: model.fadeIn
when: loader.status == Loader.Ready && isClip(model.clipType)
}
Binding {
target: loader.item
property: "positionOffset"
value: model.positionOffset
when: loader.status == Loader.Ready && isClip(model.clipType)
}
Binding {
target: loader.item
property: "effectNames"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment