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 removeFromSelectionList(frame->pos());
226 mKeyFrames.erase(frame->pos());
233void Layer::removeFromSelectionList(
int position)
235 mSelectedFrames_byLast.
removeAll(position);
236 mSelectedFrames_byPosition.
removeAll(position);
239bool Layer::moveKeyFrame(
int position,
int offset)
241 int newPos = position + offset;
242 if (newPos < 1) {
return false; }
244 auto listOfFramesLast = mSelectedFrames_byLast;
245 auto listOfFramesPos = mSelectedFrames_byPosition;
246 bool frameSelected = isFrameSelected(position);
248 if (swapKeyFrames(position, newPos)) {
250 auto oldPosIndex = mSelectedFrames_byPosition.
indexOf(position);
251 auto newPosIndex = mSelectedFrames_byPosition.
indexOf(newPos);
253 auto oldLastIndex = mSelectedFrames_byLast.
indexOf(position);
254 auto newLastndex = mSelectedFrames_byLast.
indexOf(newPos);
258 if (oldPosIndex != -1) {
259 mSelectedFrames_byPosition[oldPosIndex] = newPos;
260 mSelectedFrames_byLast[oldLastIndex] = newPos;
264 if (newPosIndex != -1) {
265 mSelectedFrames_byPosition[newPosIndex] = position;
266 mSelectedFrames_byLast[newLastndex] = position;
271 mSelectedFrames_byLast.
clear();
272 mSelectedFrames_byPosition.
clear();
274 setFrameSelected(position,
true);
277 if (!moveSelectedFrames(offset)) {
278 mSelectedFrames_byLast = listOfFramesLast;
279 mSelectedFrames_byPosition = listOfFramesPos;
285 listOfFramesPos.removeOne(position);
287 mSelectedFrames_byLast = listOfFramesLast;
288 mSelectedFrames_byPosition = listOfFramesPos;
291 setFrameSelected(newPos, frameSelected);
297bool Layer::swapKeyFrames(
int position1,
int position2)
302 if (mKeyFrames.count(position1) != 1 || mKeyFrames.count(position2) != 1)
308 pFirstFrame = mKeyFrames[position1];
309 pSecondFrame = mKeyFrames[position2];
311 mKeyFrames[position1] = pSecondFrame;
312 mKeyFrames[position2] = pFirstFrame;
314 pFirstFrame->setPos(position2);
315 pSecondFrame->setPos(position1);
317 pFirstFrame->modification();
318 pSecondFrame->modification();
328 auto it = mKeyFrames.find(pKey->pos());
329 if (it != mKeyFrames.end())
332 mKeyFrames.erase(it);
334 mKeyFrames.emplace(pKey->pos(), pKey);
341 dd <<
"\n[Layer SAVE diagnostics]\n";
345 for (
auto pair : mKeyFrames)
348 Status st = saveKeyFrameFile(keyFrame, sDataFolder);
352 if (!keyFrame->fileName().
isEmpty())
353 attachedFiles.append(keyFrame->fileName());
358 dd.collect(st.details());
359 dd <<
QString(
"- Keyframe[%1] failed to save").
arg(keyFrame->pos());
365 dd <<
"\nError: Failed to save one or more files";
366 return Status(Status::FAIL, dd);
371void Layer::setModified(
int position,
bool modified)
const
373 KeyFrame* key = getKeyFrameAt(position);
376 key->setModified(modified);
380bool Layer::isFrameSelected(
int position)
const
382 KeyFrame* keyFrame = getKeyFrameWhichCovers(position);
383 if (keyFrame ==
nullptr) {
return false; }
385 return mSelectedFrames_byLast.
contains(keyFrame->pos());
388void Layer::setFrameSelected(
int position,
bool isSelected)
390 KeyFrame* keyFrame = getKeyFrameWhichCovers(position);
391 if (keyFrame !=
nullptr)
393 int startPosition = keyFrame->pos();
395 if (isSelected && !mSelectedFrames_byLast.
contains(startPosition))
398 mSelectedFrames_byLast.
insert(0, startPosition);
399 mSelectedFrames_byPosition.
append(startPosition);
403 std::sort(mSelectedFrames_byPosition.
begin(), mSelectedFrames_byPosition.
end(), sortAsc);
405 else if (!isSelected)
407 mSelectedFrames_byLast.
removeOne(startPosition);
408 mSelectedFrames_byPosition.
removeOne(startPosition);
413void Layer::toggleFrameSelected(
int position,
bool allowMultiple)
415 bool wasSelected = isFrameSelected(position);
422 setFrameSelected(position, !wasSelected);
425void Layer::extendSelectionTo(
int position)
427 if (mSelectedFrames_byLast.
count() > 0)
429 int lastSelected = mSelectedFrames_byLast[0];
433 if (lastSelected < position)
435 startPos = lastSelected;
441 endPos = lastSelected;
447 setFrameSelected(i,
true);
459 if (!keyExists(position)) {
return false; }
461 setFrameSelected(position,
true);
464 while (position < getMaxKeyFramePosition() && getKeyFrameWhichCovers(position) !=
nullptr) {
468 extendSelectionTo(position);
473void Layer::selectAllFramesAfter(
int position)
475 int startPosition = position;
476 int endPosition = getMaxKeyFramePosition();
478 if (!keyExists(startPosition))
480 startPosition = getNextKeyFramePosition(startPosition);
483 if (startPosition > 0 && startPosition <= endPosition)
486 setFrameSelected(startPosition,
true);
487 extendSelectionTo(endPosition);
491void Layer::deselectAll()
493 mSelectedFrames_byLast.
clear();
494 mSelectedFrames_byPosition.
clear();
499 QList<int> newByPositions = mSelectedFrames_byPosition;
501 for (
int pos : newByPositions)
504 if (keyExists(pos) && !newByPositions.
contains(pos)) {
514 auto selectedFramesByLast = mSelectedFrames_byLast;
515 auto selectedFramesByPos = mSelectedFrames_byPosition;
517 int addSpaceBetweenFrames = offset;
519 if (selectedFramesByLast.isEmpty()) {
return; }
521 const int max = selectedFramesByPos.
count()-1;
522 const int posForIndex = selectedFramesByPos[max];
523 const int nextPos = getNextKeyFramePosition(selectedFramesByPos[max]);
526 if (posForIndex != nextPos) {
527 selectedFramesByPos.append(nextPos);
530 auto initialLastList = selectedFramesByLast;
531 auto initialPosList = selectedFramesByPos;
536 for (
int offset = 0; offset < selectedFramesByPos.count(); offset++)
538 int pos = selectedFramesByPos[offset];
539 int nextKeyPos = getNextKeyFramePosition(pos);
541 if (pos >= getMaxKeyFramePosition()) {
542 offsetList << (pos - 1) - getPreviousKeyFramePosition(pos) + addSpaceBetweenFrames;
544 offsetList << nextKeyPos - (pos + 1) + addSpaceBetweenFrames;
549 int offsetDirection = offset > 0 ? 1 : -1;
551 for (
int i = 0; i < selectedFramesByPos.count(); i++) {
552 const int itPos = selectedFramesByPos[i];
553 const int nextIndex = i + 1;
554 const int positionInFront = itPos + 1;
557 if (nextIndex < 0 || nextIndex >= selectedFramesByPos.count()) {
563 while ((offset > 0 && getNextKeyFramePosition(itPos) - positionInFront < offsetList[i]) ||
564 (getNextKeyFramePosition(itPos) - positionInFront > offsetList[i] && getNextKeyFramePosition(itPos) - positionInFront > 0)) {
566 selectAllFramesAfter(getNextKeyFramePosition(itPos));
568 for (
int selIndex = 0; selIndex < mSelectedFrames_byPosition.
count(); selIndex++) {
570 if (nextIndex+selIndex >= selectedFramesByPos.count()) {
break; }
572 int pos = selectedFramesByPos[nextIndex+selIndex];
574 if (!mSelectedFrames_byPosition.
contains(pos)) {
continue; }
576 selectedFramesByPos[nextIndex+selIndex] = pos + offsetDirection;
580 int initialPos = initialPosList[nextIndex+selIndex];
581 int indexOfLast = initialLastList.indexOf(initialPos);
582 if (indexOfLast == -1 || nextIndex+selIndex >= selectedFramesByLast.count()) {
585 selectedFramesByLast[indexOfLast] = selectedFramesByLast[indexOfLast] + offsetDirection;
588 moveSelectedFrames(offsetDirection);
596 for (
int pos : selectedFramesByLast) {
598 setFrameSelected(selectedFramesByLast.takeLast(),
true);
604 QList<int> selectedIndexes = mSelectedFrames_byPosition;
606 if (selectedIndexes.
isEmpty()) {
return false; }
608 for (
int swapBegin = 0, swapEnd = selectedIndexes.
count()-1; swapBegin < swapEnd; swapBegin++, swapEnd--) {
609 int oldPos = selectedIndexes[swapBegin];
610 int newPos = selectedIndexes[swapEnd];
611 bool canSwap = swapKeyFrames(oldPos, newPos);
617bool Layer::moveSelectedFrames(
int offset)
619 if (offset == 0 || mSelectedFrames_byPosition.
count() <= 0) {
624 int indexInSelection = mSelectedFrames_byPosition.
count() - 1;
630 indexInSelection = 0;
634 if (mSelectedFrames_byPosition[0] + offset < 1) {
635 offset = 1 - mSelectedFrames_byPosition[0];
640 if (offset == 0) {
return false; }
642 for (; indexInSelection > -1 && indexInSelection < mSelectedFrames_byPosition.
count(); indexInSelection += step)
644 int fromPos = mSelectedFrames_byPosition[indexInSelection];
645 int toPos = fromPos + offset;
648 KeyFrame* selectedFrame = getKeyFrameAt(fromPos);
650 Q_ASSERT(!keyExists(toPos));
652 mKeyFrames.erase(fromPos);
656 selectedFrame->setPos(toPos);
657 mKeyFrames.insert(std::make_pair(toPos, selectedFrame));
662 for (
int& pos : mSelectedFrames_byPosition)
666 for (
int& pos : mSelectedFrames_byLast)
673bool Layer::isPaintable()
const
675 return (type() == BITMAP || type() == VECTOR);
678bool Layer::keyExistsWhichCovers(
int frameNumber)
680 return getKeyFrameWhichCovers(frameNumber) !=
nullptr;
683KeyFrame* Layer::getKeyFrameWhichCovers(
int frameNumber)
const
685 auto keyFrame = getLastKeyFrameAtPosition(frameNumber);
686 if (keyFrame !=
nullptr)
688 if (keyFrame->pos() + keyFrame->length() > frameNumber)
706void Layer::loadBaseDomElement(
const QDomElement& elem)
713 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)