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);
343 dd <<
"\n[Layer SAVE diagnostics]\n";
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 dd <<
"\nError: Failed to save one or more files";
368 return Status(Status::FAIL, dd);
373void Layer::setModified(
int position,
bool modified)
const
375 KeyFrame* key = getKeyFrameAt(position);
378 key->setModified(modified);
382bool Layer::isFrameSelected(
int position)
const
384 KeyFrame* keyFrame = getKeyFrameWhichCovers(position);
385 if (keyFrame ==
nullptr) {
return false; }
387 int frameFound = mSelectedFrames_byLast.
contains(keyFrame->pos());
388 Q_ASSERT(!frameFound || keyFrame->isSelected());
392void Layer::setFrameSelected(
int position,
bool isSelected)
394 KeyFrame* keyFrame = getKeyFrameWhichCovers(position);
395 if (keyFrame !=
nullptr)
397 int startPosition = keyFrame->pos();
399 if (isSelected && !mSelectedFrames_byLast.
contains(startPosition))
402 mSelectedFrames_byLast.
insert(0, startPosition);
403 mSelectedFrames_byPosition.
append(startPosition);
407 std::sort(mSelectedFrames_byPosition.
begin(), mSelectedFrames_byPosition.
end(), sortAsc);
409 else if (!isSelected)
411 mSelectedFrames_byLast.
removeOne(startPosition);
412 mSelectedFrames_byPosition.
removeOne(startPosition);
414 keyFrame->setSelected(isSelected);
418void Layer::toggleFrameSelected(
int position,
bool allowMultiple)
420 bool wasSelected = isFrameSelected(position);
427 setFrameSelected(position, !wasSelected);
430void Layer::extendSelectionTo(
int position)
432 if (mSelectedFrames_byLast.
count() > 0)
434 int lastSelected = mSelectedFrames_byLast[0];
438 if (lastSelected < position)
440 startPos = lastSelected;
446 endPos = lastSelected;
452 setFrameSelected(i,
true);
464 if (!keyExists(position)) {
return false; }
466 setFrameSelected(position,
true);
469 while (position < getMaxKeyFramePosition() && getKeyFrameWhichCovers(position) !=
nullptr) {
473 extendSelectionTo(position);
478void Layer::selectAllFramesAfter(
int position)
480 int startPosition = position;
481 int endPosition = getMaxKeyFramePosition();
483 if (!keyExists(startPosition))
485 startPosition = getNextKeyFramePosition(startPosition);
488 if (startPosition > 0 && startPosition <= endPosition)
491 setFrameSelected(startPosition,
true);
492 extendSelectionTo(endPosition);
496void Layer::deselectAll()
498 mSelectedFrames_byLast.
clear();
499 mSelectedFrames_byPosition.
clear();
501 for (
auto pair : mKeyFrames)
503 pair.second->setSelected(
false);
509 QList<int> newByPositions = mSelectedFrames_byPosition;
511 for (
int pos : newByPositions)
514 if (keyExists(pos) && !newByPositions.
contains(pos)) {
524 auto selectedFramesByLast = mSelectedFrames_byLast;
525 auto selectedFramesByPos = mSelectedFrames_byPosition;
527 int addSpaceBetweenFrames = offset;
529 if (selectedFramesByLast.isEmpty()) {
return; }
531 const int max = selectedFramesByPos.
count()-1;
532 const int posForIndex = selectedFramesByPos[max];
533 const int nextPos = getNextKeyFramePosition(selectedFramesByPos[max]);
536 if (posForIndex != nextPos) {
537 selectedFramesByPos.append(nextPos);
540 auto initialLastList = selectedFramesByLast;
541 auto initialPosList = selectedFramesByPos;
546 for (
int offset = 0; offset < selectedFramesByPos.count(); offset++)
548 int pos = selectedFramesByPos[offset];
549 int nextKeyPos = getNextKeyFramePosition(pos);
551 if (pos >= getMaxKeyFramePosition()) {
552 offsetList << (pos - 1) - getPreviousKeyFramePosition(pos) + addSpaceBetweenFrames;
554 offsetList << nextKeyPos - (pos + 1) + addSpaceBetweenFrames;
559 int offsetDirection = offset > 0 ? 1 : -1;
561 for (
int i = 0; i < selectedFramesByPos.count(); i++) {
562 const int itPos = selectedFramesByPos[i];
563 const int nextIndex = i + 1;
564 const int positionInFront = itPos + 1;
567 if (nextIndex < 0 || nextIndex >= selectedFramesByPos.count()) {
573 while ((offset > 0 && getNextKeyFramePosition(itPos) - positionInFront < offsetList[i]) ||
574 (getNextKeyFramePosition(itPos) - positionInFront > offsetList[i] && getNextKeyFramePosition(itPos) - positionInFront > 0)) {
576 selectAllFramesAfter(getNextKeyFramePosition(itPos));
578 for (
int selIndex = 0; selIndex < mSelectedFrames_byPosition.
count(); selIndex++) {
580 if (nextIndex+selIndex >= selectedFramesByPos.count()) {
break; }
582 int pos = selectedFramesByPos[nextIndex+selIndex];
584 if (!mSelectedFrames_byPosition.
contains(pos)) {
continue; }
586 selectedFramesByPos[nextIndex+selIndex] = pos + offsetDirection;
590 int initialPos = initialPosList[nextIndex+selIndex];
591 int indexOfLast = initialLastList.indexOf(initialPos);
592 if (indexOfLast == -1 || nextIndex+selIndex >= selectedFramesByLast.count()) {
595 selectedFramesByLast[indexOfLast] = selectedFramesByLast[indexOfLast] + offsetDirection;
598 moveSelectedFrames(offsetDirection);
606 for (
int pos : selectedFramesByLast) {
608 setFrameSelected(selectedFramesByLast.takeLast(),
true);
614 QList<int> selectedIndexes = mSelectedFrames_byPosition;
616 if (selectedIndexes.
isEmpty()) {
return false; }
618 for (
int swapBegin = 0, swapEnd = selectedIndexes.
count()-1; swapBegin < swapEnd; swapBegin++, swapEnd--) {
619 int oldPos = selectedIndexes[swapBegin];
620 int newPos = selectedIndexes[swapEnd];
621 bool canSwap = swapKeyFrames(oldPos, newPos);
627bool Layer::moveSelectedFrames(
int offset)
629 if (offset == 0 || mSelectedFrames_byPosition.
count() <= 0) {
634 int indexInSelection = mSelectedFrames_byPosition.
count() - 1;
640 indexInSelection = 0;
644 if (mSelectedFrames_byPosition[0] + offset < 1)
return false;
649 for (; indexInSelection > -1 && indexInSelection < mSelectedFrames_byPosition.
count(); indexInSelection += step)
651 int fromPos = mSelectedFrames_byPosition[indexInSelection];
652 int toPos = fromPos + offset;
655 KeyFrame* selectedFrame = getKeyFrameAt(fromPos);
657 Q_ASSERT(!keyExists(toPos));
659 mKeyFrames.erase(fromPos);
663 selectedFrame->setPos(toPos);
664 mKeyFrames.insert(std::make_pair(toPos, selectedFrame));
669 for (
int& pos : mSelectedFrames_byPosition)
673 for (
int& pos : mSelectedFrames_byLast)
680bool Layer::isPaintable()
const
682 return (type() == BITMAP || type() == VECTOR);
685bool Layer::keyExistsWhichCovers(
int frameNumber)
687 return getKeyFrameWhichCovers(frameNumber) !=
nullptr;
690KeyFrame* Layer::getKeyFrameWhichCovers(
int frameNumber)
const
692 auto keyFrame = getLastKeyFrameAtPosition(frameNumber);
693 if (keyFrame !=
nullptr)
695 if (keyFrame->pos() + keyFrame->length() > frameNumber)
713void Layer::loadBaseDomElement(
const QDomElement& elem)
720 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)