19 #include <QApplication>
23 #include <QDomElement>
28 bool sortAsc(
int left,
int right)
33 Layer::Layer(
Object*
object, LAYER_TYPE eType)
35 Q_ASSERT(eType != UNDEFINED);
41 mId =
object->getUniqueLayerID();
46 for (
auto it : mKeyFrames)
54 void Layer::setObject(
Object* obj)
58 mId = mObject->getUniqueLayerID();
61 void Layer::foreachKeyFrame(std::function<
void(
KeyFrame*)> action)
const
63 for (
auto pair : mKeyFrames)
69 bool Layer::keyExists(
int position)
const
71 return (mKeyFrames.find(position) != mKeyFrames.end());
74 KeyFrame* Layer::getKeyFrameAt(
int position)
const
76 auto it = mKeyFrames.find(position);
77 if (it == mKeyFrames.end())
84 KeyFrame* Layer::getLastKeyFrameAtPosition(
int position)
const
90 auto it = mKeyFrames.lower_bound(position);
91 if (it == mKeyFrames.end())
98 int Layer::getPreviousKeyFramePosition(
int position)
const
100 auto it = mKeyFrames.upper_bound(position);
101 if (it == mKeyFrames.end())
103 return firstKeyFramePosition();
108 int Layer::getNextKeyFramePosition(
int position)
const
112 if (position < firstKeyFramePosition())
114 return firstKeyFramePosition();
117 auto it = mKeyFrames.lower_bound(position);
118 if (it == mKeyFrames.end())
120 return getMaxKeyFramePosition();
123 if (it != mKeyFrames.begin())
130 int Layer::getPreviousFrameNumber(
int position,
bool isAbsolute)
const
135 prevNumber = getPreviousKeyFramePosition(position);
137 prevNumber = position - 1;
139 if (prevNumber >= position)
146 int Layer::getNextFrameNumber(
int position,
bool isAbsolute)
const
151 nextNumber = getNextKeyFramePosition(position);
153 nextNumber = position + 1;
155 if (nextNumber <= position)
161 int Layer::firstKeyFramePosition()
const
163 if (!mKeyFrames.empty())
165 return mKeyFrames.rbegin()->first;
170 int Layer::getMaxKeyFramePosition()
const
172 if (!mKeyFrames.empty())
174 return mKeyFrames.begin()->first;
179 bool Layer::addNewKeyFrameAt(
int position)
181 if (position <= 0)
return false;
183 KeyFrame* key = createKeyFrame(position, mObject);
184 return addKeyFrame(position, key);
187 void Layer::addOrReplaceKeyFrame(
int position,
KeyFrame* pKeyFrame)
189 Q_ASSERT(position > 0);
190 pKeyFrame->setPos(position);
195 bool Layer::addKeyFrame(
int position,
KeyFrame* pKeyFrame)
197 if (keyExists(position))
202 pKeyFrame->setPos(position);
203 mKeyFrames.emplace(position, pKeyFrame);
210 if(position < 1 || position > getMaxKeyFramePosition() || !getKeyFrameAt(position))
216 moveSelectedFrames(1);
222 bool Layer::removeKeyFrame(
int position)
224 if (keyFrameCount() == 1 && this->type() != SOUND) {
return false; }
225 auto frame = getKeyFrameWhichCovers(position);
229 if (frame->isSelected()) {
230 removeFromSelectionList(frame->pos());
232 mKeyFrames.erase(frame->pos());
239 void Layer::removeFromSelectionList(
int position)
241 mSelectedFrames_byLast.
removeAll(position);
242 mSelectedFrames_byPosition.
removeAll(position);
245 bool Layer::moveKeyFrame(
int position,
int offset)
247 int newPos = position + offset;
248 if (newPos < 1) {
return false; }
250 auto listOfFramesLast = mSelectedFrames_byLast;
251 auto listOfFramesPos = mSelectedFrames_byPosition;
252 bool frameSelected = isFrameSelected(position);
254 if (swapKeyFrames(position, newPos)) {
256 auto oldPosIndex = mSelectedFrames_byPosition.
indexOf(position);
257 auto newPosIndex = mSelectedFrames_byPosition.
indexOf(newPos);
259 auto oldLastIndex = mSelectedFrames_byLast.
indexOf(position);
260 auto newLastndex = mSelectedFrames_byLast.
indexOf(newPos);
264 if (oldPosIndex != -1) {
265 mSelectedFrames_byPosition[oldPosIndex] = newPos;
266 mSelectedFrames_byLast[oldLastIndex] = newPos;
270 if (newPosIndex != -1) {
271 mSelectedFrames_byPosition[newPosIndex] = position;
272 mSelectedFrames_byLast[newLastndex] = position;
277 mSelectedFrames_byLast.
clear();
278 mSelectedFrames_byPosition.
clear();
280 setFrameSelected(position,
true);
283 if (!moveSelectedFrames(offset)) {
284 mSelectedFrames_byLast = listOfFramesLast;
285 mSelectedFrames_byPosition = listOfFramesPos;
291 listOfFramesPos.removeOne(position);
293 mSelectedFrames_byLast = listOfFramesLast;
294 mSelectedFrames_byPosition = listOfFramesPos;
297 setFrameSelected(newPos, frameSelected);
303 bool Layer::swapKeyFrames(
int position1,
int position2)
308 if (mKeyFrames.count(position1) != 1 || mKeyFrames.count(position2) != 1)
314 pFirstFrame = mKeyFrames[position1];
315 pSecondFrame = mKeyFrames[position2];
317 mKeyFrames[position1] = pSecondFrame;
318 mKeyFrames[position2] = pFirstFrame;
320 pFirstFrame->setPos(position2);
321 pSecondFrame->setPos(position1);
323 pFirstFrame->modification();
324 pSecondFrame->modification();
334 auto it = mKeyFrames.find(pKey->pos());
335 if (it != mKeyFrames.end())
338 mKeyFrames.erase(it);
340 mKeyFrames.emplace(pKey->pos(), pKey);
351 for (
auto pair : mKeyFrames)
354 Status st = saveKeyFrameFile(keyFrame, sDataFolder);
358 if (!keyFrame->fileName().
isEmpty())
359 attachedFiles.
append(keyFrame->fileName());
364 dd.collect(st.details());
365 dd <<
QString(
"- Keyframe[%1] failed to save").
arg(keyFrame->pos());
371 return Status(Status::FAIL, dd);
376 void Layer::setModified(
int position,
bool modified)
const
378 KeyFrame* key = getKeyFrameAt(position);
381 key->setModified(modified);
385 bool Layer::isFrameSelected(
int position)
const
387 KeyFrame* keyFrame = getKeyFrameWhichCovers(position);
388 if (keyFrame ==
nullptr) {
return false; }
390 int frameFound = mSelectedFrames_byLast.
contains(keyFrame->pos());
391 Q_ASSERT(!frameFound || keyFrame->isSelected());
395 void Layer::setFrameSelected(
int position,
bool isSelected)
397 KeyFrame* keyFrame = getKeyFrameWhichCovers(position);
398 if (keyFrame !=
nullptr)
400 int startPosition = keyFrame->pos();
402 if (isSelected && !mSelectedFrames_byLast.
contains(startPosition))
405 mSelectedFrames_byLast.
insert(0, startPosition);
406 mSelectedFrames_byPosition.
append(startPosition);
410 std::sort(mSelectedFrames_byPosition.
begin(), mSelectedFrames_byPosition.
end(), sortAsc);
412 else if (!isSelected)
414 mSelectedFrames_byLast.
removeOne(startPosition);
415 mSelectedFrames_byPosition.
removeOne(startPosition);
417 keyFrame->setSelected(isSelected);
421 void Layer::toggleFrameSelected(
int position,
bool allowMultiple)
423 bool wasSelected = isFrameSelected(position);
430 setFrameSelected(position, !wasSelected);
433 void Layer::extendSelectionTo(
int position)
435 if (mSelectedFrames_byLast.
count() > 0)
437 int lastSelected = mSelectedFrames_byLast[0];
441 if (lastSelected < position)
443 startPos = lastSelected;
449 endPos = lastSelected;
455 setFrameSelected(i,
true);
467 if (!keyExists(position)) {
return false; }
469 setFrameSelected(position,
true);
472 while (position < getMaxKeyFramePosition() && getKeyFrameWhichCovers(position) !=
nullptr) {
476 extendSelectionTo(position);
481 void Layer::selectAllFramesAfter(
int position)
483 int startPosition = position;
484 int endPosition = getMaxKeyFramePosition();
486 if (!keyExists(startPosition))
488 startPosition = getNextKeyFramePosition(startPosition);
491 if (startPosition > 0 && startPosition <= endPosition)
494 setFrameSelected(startPosition,
true);
495 extendSelectionTo(endPosition);
499 void Layer::deselectAll()
501 mSelectedFrames_byLast.
clear();
502 mSelectedFrames_byPosition.
clear();
504 for (
auto pair : mKeyFrames)
506 pair.second->setSelected(
false);
512 QList<int> newByPositions = mSelectedFrames_byPosition;
514 for (
int pos : newByPositions)
517 if (keyExists(pos) && !newByPositions.contains(pos)) {
527 auto selectedFramesByLast = mSelectedFrames_byLast;
528 auto selectedFramesByPos = mSelectedFrames_byPosition;
530 int addSpaceBetweenFrames = offset;
532 if (selectedFramesByLast.isEmpty()) {
return; }
534 const int max = selectedFramesByPos.
count()-1;
535 const int posForIndex = selectedFramesByPos[max];
536 const int nextPos = getNextKeyFramePosition(selectedFramesByPos[max]);
539 if (posForIndex != nextPos) {
540 selectedFramesByPos.append(nextPos);
543 auto initialLastList = selectedFramesByLast;
544 auto initialPosList = selectedFramesByPos;
549 for (
int offset = 0; offset < selectedFramesByPos.count(); offset++)
551 int pos = selectedFramesByPos[offset];
552 int nextKeyPos = getNextKeyFramePosition(pos);
554 if (pos >= getMaxKeyFramePosition()) {
555 offsetList << (pos - 1) - getPreviousKeyFramePosition(pos) + addSpaceBetweenFrames;
557 offsetList << nextKeyPos - (pos + 1) + addSpaceBetweenFrames;
562 int offsetDirection = offset > 0 ? 1 : -1;
564 for (
int i = 0; i < selectedFramesByPos.count(); i++) {
565 const int itPos = selectedFramesByPos[i];
566 const int nextIndex = i + 1;
567 const int positionInFront = itPos + 1;
570 if (nextIndex < 0 || nextIndex >= selectedFramesByPos.count()) {
576 while ((offset > 0 && getNextKeyFramePosition(itPos) - positionInFront < offsetList[i]) ||
577 (getNextKeyFramePosition(itPos) - positionInFront > offsetList[i] && getNextKeyFramePosition(itPos) - positionInFront > 0)) {
579 selectAllFramesAfter(getNextKeyFramePosition(itPos));
581 for (
int selIndex = 0; selIndex < mSelectedFrames_byPosition.
count(); selIndex++) {
583 if (nextIndex+selIndex >= selectedFramesByPos.count()) {
break; }
585 int pos = selectedFramesByPos[nextIndex+selIndex];
587 if (!mSelectedFrames_byPosition.
contains(pos)) {
continue; }
589 selectedFramesByPos[nextIndex+selIndex] = pos + offsetDirection;
593 int initialPos = initialPosList[nextIndex+selIndex];
594 int indexOfLast = initialLastList.indexOf(initialPos);
595 if (indexOfLast == -1 || nextIndex+selIndex >= selectedFramesByLast.count()) {
598 selectedFramesByLast[indexOfLast] = selectedFramesByLast[indexOfLast] + offsetDirection;
601 moveSelectedFrames(offsetDirection);
609 for (
int pos : selectedFramesByLast) {
611 setFrameSelected(selectedFramesByLast.takeLast(),
true);
617 QList<int> selectedIndexes = mSelectedFrames_byPosition;
619 if (selectedIndexes.
isEmpty()) {
return false; }
621 for (
int swapBegin = 0, swapEnd = selectedIndexes.
count()-1; swapBegin < swapEnd; swapBegin++, swapEnd--) {
622 int oldPos = selectedIndexes[swapBegin];
623 int newPos = selectedIndexes[swapEnd];
624 bool canSwap = swapKeyFrames(oldPos, newPos);
630 bool Layer::moveSelectedFrames(
int offset)
632 if (offset == 0 || mSelectedFrames_byPosition.
count() <= 0) {
637 int indexInSelection = mSelectedFrames_byPosition.
count() - 1;
643 indexInSelection = 0;
647 if (mSelectedFrames_byPosition[0] + offset < 1)
return false;
652 for (; indexInSelection > -1 && indexInSelection < mSelectedFrames_byPosition.
count(); indexInSelection += step)
654 int fromPos = mSelectedFrames_byPosition[indexInSelection];
655 int toPos = fromPos + offset;
658 KeyFrame* selectedFrame = getKeyFrameAt(fromPos);
660 Q_ASSERT(!keyExists(toPos));
662 mKeyFrames.erase(fromPos);
666 selectedFrame->setPos(toPos);
667 mKeyFrames.insert(std::make_pair(toPos, selectedFrame));
672 for (
int& pos : mSelectedFrames_byPosition)
676 for (
int& pos : mSelectedFrames_byLast)
683 bool Layer::isPaintable()
const
685 return (type() == BITMAP || type() == VECTOR);
688 bool Layer::keyExistsWhichCovers(
int frameNumber)
690 return getKeyFrameWhichCovers(frameNumber) !=
nullptr;
693 KeyFrame* Layer::getKeyFrameWhichCovers(
int frameNumber)
const
695 auto keyFrame = getLastKeyFrameAtPosition(frameNumber);
696 if (keyFrame !=
nullptr)
698 if (keyFrame->pos() + keyFrame->length() > frameNumber)
716 void Layer::loadBaseDomElement(
const QDomElement& elem)
723 setName(elem.
attribute(
"name",
"untitled"));
bool insertExposureAt(int position)
Will insert an empty frame (exposure) after the given position.
QString attribute(const QString &name, const QString &defValue) const const
bool newSelectionOfConnectedFrames(int position)
Make a selection from specified position until a blank spot appears The search is only looking forwar...
void setExposureForSelectedFrames(int offset)
Add or subtract exposure from selected frames.
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isNull() const const
int indexOf(const T &value, int from) const const
bool canMoveSelectedFramesToOffset(int offset) const
Predetermines whether the frames can be moved to a new position depending on the offset.
int count(const T &value) const const
void append(const T &value)
void markFrameAsDirty(const int frameNumber)
Mark the frame position as dirty.
void setAttribute(const QString &name, const QString &value)
int toInt(bool *ok, int base) const const
bool isEmpty() const const
bool isEmpty() const const
int removeAll(const T &value)
bool contains(const T &value) const const
void insert(int i, const T &value)
bool reverseOrderOfSelection()
Reverse order of selected frames.
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QDomElement createElement(const QString &tagName)
bool removeOne(const T &value)