19#include <QApplication>
27bool sortAsc(
int left,
int right)
32Layer::Layer(
int id, LAYER_TYPE eType)
34 Q_ASSERT(eType != UNDEFINED);
37 mName =
QString(tr(
"Undefined Layer"));
44 for (
auto it : mKeyFrames)
52void Layer::foreachKeyFrame(std::function<
void(
KeyFrame*)> action)
const
54 for (
auto pair : mKeyFrames)
60bool Layer::keyExists(
int position)
const
62 return (mKeyFrames.find(position) != mKeyFrames.end());
65KeyFrame* Layer::getKeyFrameAt(
int position)
const
67 auto it = mKeyFrames.find(position);
68 if (it == mKeyFrames.end())
75KeyFrame* Layer::getLastKeyFrameAtPosition(
int position)
const
81 auto it = mKeyFrames.lower_bound(position);
82 if (it == mKeyFrames.end())
89int Layer::getPreviousKeyFramePosition(
int position)
const
91 auto it = mKeyFrames.upper_bound(position);
92 if (it == mKeyFrames.end())
94 return firstKeyFramePosition();
99int Layer::getNextKeyFramePosition(
int position)
const
103 if (position < firstKeyFramePosition())
105 return firstKeyFramePosition();
108 auto it = mKeyFrames.lower_bound(position);
109 if (it == mKeyFrames.end())
111 return getMaxKeyFramePosition();
114 if (it != mKeyFrames.begin())
121int Layer::getPreviousFrameNumber(
int position,
bool isAbsolute)
const
126 prevNumber = getPreviousKeyFramePosition(position);
128 prevNumber = position - 1;
130 if (prevNumber >= position)
137int Layer::getNextFrameNumber(
int position,
bool isAbsolute)
const
142 nextNumber = getNextKeyFramePosition(position);
144 nextNumber = position + 1;
146 if (nextNumber <= position)
152int Layer::firstKeyFramePosition()
const
154 if (!mKeyFrames.empty())
156 return mKeyFrames.rbegin()->first;
161int Layer::getMaxKeyFramePosition()
const
163 if (!mKeyFrames.empty())
165 return mKeyFrames.begin()->first;
172 if (position <= 0)
return false;
174 KeyFrame* key = createKeyFrame(position);
183void Layer::addOrReplaceKeyFrame(
int position,
KeyFrame* pKeyFrame)
185 Q_ASSERT(position > 0);
186 pKeyFrame->setPos(position);
193 if (keyExists(position))
198 pKeyFrame->setPos(position);
199 mKeyFrames.emplace(position, pKeyFrame);
206 if(position < 1 || position > getMaxKeyFramePosition() || !getKeyFrameAt(position))
212 moveSelectedFrames(1);
218bool Layer::removeKeyFrame(
int position)
220 if (keyFrameCount() == 1 && this->type() != SOUND) {
return false; }
221 auto frame = getKeyFrameWhichCovers(position);
225 if (frame->isSelected()) {
226 removeFromSelectionList(frame->pos());
228 mKeyFrames.erase(frame->pos());
235void Layer::removeFromSelectionList(
int position)
237 mSelectedFrames_byLast.
removeAll(position);
238 mSelectedFrames_byPosition.
removeAll(position);
241bool Layer::moveKeyFrame(
int position,
int offset)
243 int newPos = position + offset;
244 if (newPos < 1) {
return false; }
246 auto listOfFramesLast = mSelectedFrames_byLast;
247 auto listOfFramesPos = mSelectedFrames_byPosition;
248 bool frameSelected = isFrameSelected(position);
250 if (swapKeyFrames(position, newPos)) {
252 auto oldPosIndex = mSelectedFrames_byPosition.
indexOf(position);
253 auto newPosIndex = mSelectedFrames_byPosition.
indexOf(newPos);
255 auto oldLastIndex = mSelectedFrames_byLast.
indexOf(position);
256 auto newLastndex = mSelectedFrames_byLast.
indexOf(newPos);
260 if (oldPosIndex != -1) {
261 mSelectedFrames_byPosition[oldPosIndex] = newPos;
262 mSelectedFrames_byLast[oldLastIndex] = newPos;
266 if (newPosIndex != -1) {
267 mSelectedFrames_byPosition[newPosIndex] = position;
268 mSelectedFrames_byLast[newLastndex] = position;
273 mSelectedFrames_byLast.
clear();
274 mSelectedFrames_byPosition.
clear();
276 setFrameSelected(position,
true);
279 if (!moveSelectedFrames(offset)) {
280 mSelectedFrames_byLast = listOfFramesLast;
281 mSelectedFrames_byPosition = listOfFramesPos;
287 listOfFramesPos.removeOne(position);
289 mSelectedFrames_byLast = listOfFramesLast;
290 mSelectedFrames_byPosition = listOfFramesPos;
293 setFrameSelected(newPos, frameSelected);
299bool Layer::swapKeyFrames(
int position1,
int position2)
304 if (mKeyFrames.count(position1) != 1 || mKeyFrames.count(position2) != 1)
310 pFirstFrame = mKeyFrames[position1];
311 pSecondFrame = mKeyFrames[position2];
313 mKeyFrames[position1] = pSecondFrame;
314 mKeyFrames[position2] = pFirstFrame;
316 pFirstFrame->setPos(position2);
317 pSecondFrame->setPos(position1);
319 pFirstFrame->modification();
320 pSecondFrame->modification();
330 auto it = mKeyFrames.find(pKey->pos());
331 if (it != mKeyFrames.end())
334 mKeyFrames.erase(it);
336 mKeyFrames.emplace(pKey->pos(), pKey);
347 for (
auto pair : mKeyFrames)
350 Status st = saveKeyFrameFile(keyFrame, sDataFolder);
354 if (!keyFrame->fileName().
isEmpty())
355 attachedFiles.
append(keyFrame->fileName());
360 dd.collect(st.details());
361 dd <<
QString(
"- Keyframe[%1] failed to save").
arg(keyFrame->pos());
367 return Status(Status::FAIL, dd);
372void Layer::setModified(
int position,
bool modified)
const
374 KeyFrame* key = getKeyFrameAt(position);
377 key->setModified(modified);
381bool Layer::isFrameSelected(
int position)
const
383 KeyFrame* keyFrame = getKeyFrameWhichCovers(position);
384 if (keyFrame ==
nullptr) {
return false; }
386 int frameFound = mSelectedFrames_byLast.
contains(keyFrame->pos());
387 Q_ASSERT(!frameFound || keyFrame->isSelected());
391void Layer::setFrameSelected(
int position,
bool isSelected)
393 KeyFrame* keyFrame = getKeyFrameWhichCovers(position);
394 if (keyFrame !=
nullptr)
396 int startPosition = keyFrame->pos();
398 if (isSelected && !mSelectedFrames_byLast.
contains(startPosition))
401 mSelectedFrames_byLast.
insert(0, startPosition);
402 mSelectedFrames_byPosition.
append(startPosition);
406 std::sort(mSelectedFrames_byPosition.
begin(), mSelectedFrames_byPosition.
end(), sortAsc);
408 else if (!isSelected)
410 mSelectedFrames_byLast.
removeOne(startPosition);
411 mSelectedFrames_byPosition.
removeOne(startPosition);
413 keyFrame->setSelected(isSelected);
417void Layer::toggleFrameSelected(
int position,
bool allowMultiple)
419 bool wasSelected = isFrameSelected(position);
426 setFrameSelected(position, !wasSelected);
429void Layer::extendSelectionTo(
int position)
431 if (mSelectedFrames_byLast.
count() > 0)
433 int lastSelected = mSelectedFrames_byLast[0];
437 if (lastSelected < position)
439 startPos = lastSelected;
445 endPos = lastSelected;
451 setFrameSelected(i,
true);
463 if (!keyExists(position)) {
return false; }
465 setFrameSelected(position,
true);
468 while (position < getMaxKeyFramePosition() && getKeyFrameWhichCovers(position) !=
nullptr) {
472 extendSelectionTo(position);
477void Layer::selectAllFramesAfter(
int position)
479 int startPosition = position;
480 int endPosition = getMaxKeyFramePosition();
482 if (!keyExists(startPosition))
484 startPosition = getNextKeyFramePosition(startPosition);
487 if (startPosition > 0 && startPosition <= endPosition)
490 setFrameSelected(startPosition,
true);
491 extendSelectionTo(endPosition);
495void Layer::deselectAll()
497 mSelectedFrames_byLast.
clear();
498 mSelectedFrames_byPosition.
clear();
500 for (
auto pair : mKeyFrames)
502 pair.second->setSelected(
false);
508 QList<int> newByPositions = mSelectedFrames_byPosition;
510 for (
int pos : newByPositions)
513 if (keyExists(pos) && !newByPositions.
contains(pos)) {
523 auto selectedFramesByLast = mSelectedFrames_byLast;
524 auto selectedFramesByPos = mSelectedFrames_byPosition;
526 int addSpaceBetweenFrames = offset;
528 if (selectedFramesByLast.isEmpty()) {
return; }
530 const int max = selectedFramesByPos.
count()-1;
531 const int posForIndex = selectedFramesByPos[max];
532 const int nextPos = getNextKeyFramePosition(selectedFramesByPos[max]);
535 if (posForIndex != nextPos) {
536 selectedFramesByPos.append(nextPos);
539 auto initialLastList = selectedFramesByLast;
540 auto initialPosList = selectedFramesByPos;
545 for (
int offset = 0; offset < selectedFramesByPos.count(); offset++)
547 int pos = selectedFramesByPos[offset];
548 int nextKeyPos = getNextKeyFramePosition(pos);
550 if (pos >= getMaxKeyFramePosition()) {
551 offsetList << (pos - 1) - getPreviousKeyFramePosition(pos) + addSpaceBetweenFrames;
553 offsetList << nextKeyPos - (pos + 1) + addSpaceBetweenFrames;
558 int offsetDirection = offset > 0 ? 1 : -1;
560 for (
int i = 0; i < selectedFramesByPos.count(); i++) {
561 const int itPos = selectedFramesByPos[i];
562 const int nextIndex = i + 1;
563 const int positionInFront = itPos + 1;
566 if (nextIndex < 0 || nextIndex >= selectedFramesByPos.count()) {
572 while ((offset > 0 && getNextKeyFramePosition(itPos) - positionInFront < offsetList[i]) ||
573 (getNextKeyFramePosition(itPos) - positionInFront > offsetList[i] && getNextKeyFramePosition(itPos) - positionInFront > 0)) {
575 selectAllFramesAfter(getNextKeyFramePosition(itPos));
577 for (
int selIndex = 0; selIndex < mSelectedFrames_byPosition.
count(); selIndex++) {
579 if (nextIndex+selIndex >= selectedFramesByPos.count()) {
break; }
581 int pos = selectedFramesByPos[nextIndex+selIndex];
583 if (!mSelectedFrames_byPosition.
contains(pos)) {
continue; }
585 selectedFramesByPos[nextIndex+selIndex] = pos + offsetDirection;
589 int initialPos = initialPosList[nextIndex+selIndex];
590 int indexOfLast = initialLastList.indexOf(initialPos);
591 if (indexOfLast == -1 || nextIndex+selIndex >= selectedFramesByLast.count()) {
594 selectedFramesByLast[indexOfLast] = selectedFramesByLast[indexOfLast] + offsetDirection;
597 moveSelectedFrames(offsetDirection);
605 for (
int pos : selectedFramesByLast) {
607 setFrameSelected(selectedFramesByLast.takeLast(),
true);
613 QList<int> selectedIndexes = mSelectedFrames_byPosition;
615 if (selectedIndexes.
isEmpty()) {
return false; }
617 for (
int swapBegin = 0, swapEnd = selectedIndexes.
count()-1; swapBegin < swapEnd; swapBegin++, swapEnd--) {
618 int oldPos = selectedIndexes[swapBegin];
619 int newPos = selectedIndexes[swapEnd];
620 bool canSwap = swapKeyFrames(oldPos, newPos);
626bool Layer::moveSelectedFrames(
int offset)
628 if (offset == 0 || mSelectedFrames_byPosition.
count() <= 0) {
633 int indexInSelection = mSelectedFrames_byPosition.
count() - 1;
639 indexInSelection = 0;
643 if (mSelectedFrames_byPosition[0] + offset < 1)
return false;
648 for (; indexInSelection > -1 && indexInSelection < mSelectedFrames_byPosition.
count(); indexInSelection += step)
650 int fromPos = mSelectedFrames_byPosition[indexInSelection];
651 int toPos = fromPos + offset;
654 KeyFrame* selectedFrame = getKeyFrameAt(fromPos);
656 Q_ASSERT(!keyExists(toPos));
658 mKeyFrames.erase(fromPos);
662 selectedFrame->setPos(toPos);
663 mKeyFrames.insert(std::make_pair(toPos, selectedFrame));
668 for (
int& pos : mSelectedFrames_byPosition)
672 for (
int& pos : mSelectedFrames_byLast)
679bool Layer::isPaintable()
const
681 return (type() == BITMAP || type() == VECTOR);
684bool Layer::keyExistsWhichCovers(
int frameNumber)
686 return getKeyFrameWhichCovers(frameNumber) !=
nullptr;
689KeyFrame* Layer::getKeyFrameWhichCovers(
int frameNumber)
const
691 auto keyFrame = getLastKeyFrameAtPosition(frameNumber);
692 if (keyFrame !=
nullptr)
694 if (keyFrame->pos() + keyFrame->length() > frameNumber)
712void Layer::loadBaseDomElement(
const QDomElement& elem)
719 setName(elem.
attribute(
"name",
"untitled"));
void markFrameAsDirty(const int frameNumber)
Mark the frame position as dirty.
bool newSelectionOfConnectedFrames(int position)
Make a selection from specified position until a blank spot appears The search is only looking forwar...
bool addNewKeyFrameAt(int position)
Creates a new keyframe at the given position, unless one already exists.
bool reverseOrderOfSelection()
Reverse order of selected frames.
virtual bool addKeyFrame(int position, KeyFrame *pKeyFrame)
Adds a keyframe at the given position, unless one already exists.
void setExposureForSelectedFrames(int offset)
Add or subtract exposure from selected frames.
bool canMoveSelectedFramesToOffset(int offset) const
Predetermines whether the frames can be moved to a new position depending on the offset.
bool insertExposureAt(int position)
Will insert an empty frame (exposure) after the given position.
QDomElement createElement(const QString &tagName)
QString attribute(const QString &name, const QString &defValue) const const
void setAttribute(const QString &name, const QString &value)
void append(const T &value)
bool contains(const T &value) const const
int count(const T &value) const const
int indexOf(const T &value, int from) const const
void insert(int i, const T &value)
bool isEmpty() const const
int removeAll(const T &value)
bool removeOne(const T &value)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
bool isEmpty() const const
bool isNull() const const
int toInt(bool *ok, int base) const const
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)