File indexing completed on 2024-04-28 04:51:22

0001 /*
0002 SPDX-FileCopyrightText: 2012 Till Theato <root@ttill.de>
0003 SPDX-FileCopyrightText: 2014 Jean-Baptiste Mardelle <jb@kdenlive.org>
0004 This file is part of Kdenlive. See www.kdenlive.org.
0005 
0006 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0007 */
0008 
0009 #include "abstractprojectitem.h"
0010 #include "bin.h"
0011 #include "core.h"
0012 #include "macros.hpp"
0013 #include "projectitemmodel.h"
0014 
0015 #include <QPainter>
0016 #include <QPainterPath>
0017 #include <QVariant>
0018 
0019 #include <KLocalizedString>
0020 #include <utility>
0021 
0022 AbstractProjectItem::AbstractProjectItem(PROJECTITEMTYPE type, QString id, const std::shared_ptr<ProjectItemModel> &model, bool isRoot)
0023     : TreeItem(QList<QVariant>(), std::static_pointer_cast<AbstractTreeModel>(model), isRoot)
0024     , m_name()
0025     , m_description()
0026     , m_thumbnail(QIcon())
0027     , m_parentDuration()
0028     , m_inPoint()
0029     , m_outPoint()
0030     , m_date()
0031     , m_binId(std::move(id))
0032     , m_totalUsage(0)
0033     , m_currentSequenceUsage(0)
0034     , m_AudioUsage(0)
0035     , m_rating(0)
0036     , m_clipStatus(FileStatus::StatusReady)
0037     , m_itemType(type)
0038     , m_lock(QReadWriteLock::Recursive)
0039     , m_isCurrent(false)
0040 {
0041     Q_ASSERT(!isRoot || type == FolderItem);
0042 }
0043 
0044 bool AbstractProjectItem::operator==(const std::shared_ptr<AbstractProjectItem> &projectItem) const
0045 {
0046     // FIXME: only works for folders
0047     bool equal = this->m_childItems == projectItem->m_childItems;
0048     // equal = equal && (m_parentItem == projectItem->m_parentItem);
0049     return equal;
0050 }
0051 
0052 std::shared_ptr<AbstractProjectItem> AbstractProjectItem::parent() const
0053 {
0054     return std::static_pointer_cast<AbstractProjectItem>(m_parentItem.lock());
0055 }
0056 
0057 void AbstractProjectItem::setRefCount(uint count, uint totalCount)
0058 {
0059     if (count == totalCount) {
0060         if (count == 0) {
0061             m_usageText.clear();
0062         } else {
0063             m_usageText = QString::number(count);
0064         }
0065     } else {
0066         m_usageText = QString("%1|%2").arg(count).arg(totalCount);
0067     }
0068     m_currentSequenceUsage = count;
0069     m_totalUsage = totalCount;
0070     m_VideoUsage = count - m_AudioUsage;
0071     if (auto ptr = m_model.lock())
0072         std::static_pointer_cast<ProjectItemModel>(ptr)->onItemUpdated(
0073             std::static_pointer_cast<AbstractProjectItem>(shared_from_this()),
0074             {AbstractProjectItem::UsageCount, AbstractProjectItem::VideoUsed, AbstractProjectItem::AudioUsed});
0075 }
0076 
0077 uint AbstractProjectItem::refCount() const
0078 {
0079     return m_totalUsage;
0080 }
0081 
0082 void AbstractProjectItem::addRef()
0083 {
0084     m_currentSequenceUsage++;
0085     m_totalUsage++;
0086     if (auto ptr = m_model.lock())
0087         std::static_pointer_cast<ProjectItemModel>(ptr)->onItemUpdated(std::static_pointer_cast<AbstractProjectItem>(shared_from_this()),
0088                                                                        {AbstractProjectItem::UsageCount});
0089 }
0090 
0091 void AbstractProjectItem::removeRef()
0092 {
0093     m_currentSequenceUsage--;
0094     m_totalUsage--;
0095     if (auto ptr = m_model.lock())
0096         std::static_pointer_cast<ProjectItemModel>(ptr)->onItemUpdated(std::static_pointer_cast<AbstractProjectItem>(shared_from_this()),
0097                                                                        {AbstractProjectItem::UsageCount});
0098 }
0099 
0100 const QString &AbstractProjectItem::clipId() const
0101 {
0102     return m_binId;
0103 }
0104 
0105 QPixmap AbstractProjectItem::roundedPixmap(const QPixmap &source)
0106 {
0107     QPixmap pix(source.size());
0108     pix.fill(QColor(0, 0, 0, 100));
0109     QPainter p(&pix);
0110     p.setRenderHint(QPainter::Antialiasing, true);
0111     QPainterPath path;
0112     path.addRoundedRect(0.5, 0.5, pix.width() - 1, pix.height() - 1, 4, 4);
0113     p.setClipPath(path);
0114     p.drawPixmap(0, 0, source);
0115     p.end();
0116     return pix;
0117 }
0118 
0119 AbstractProjectItem::PROJECTITEMTYPE AbstractProjectItem::itemType() const
0120 {
0121     return m_itemType;
0122 }
0123 
0124 const QIcon AbstractProjectItem::icon() const
0125 {
0126     return m_thumbnail;
0127 }
0128 
0129 const QVariant AbstractProjectItem::getData(DataType type) const
0130 {
0131     QVariant data;
0132     switch (type) {
0133     case DataName:
0134         data = QVariant(m_name);
0135         break;
0136     case DataDescription:
0137         data = QVariant(m_description);
0138         break;
0139     case DataThumbnail:
0140         data = QVariant(m_thumbnail);
0141         break;
0142     case DataId:
0143         data = QVariant(m_binId.toInt());
0144         break;
0145     case DataDuration:
0146         data = QVariant(m_duration);
0147         break;
0148     case ParentDuration:
0149         data = QVariant(m_parentDuration);
0150         break;
0151     case DataInPoint:
0152         data = QVariant(m_inPoint);
0153         break;
0154     case DataOutPoint:
0155         data = QVariant(m_outPoint);
0156         break;
0157     case DataDate:
0158         data = QVariant(m_date);
0159         break;
0160     case UsageCount:
0161         data = QVariant(m_usageText);
0162         break;
0163     case AudioUsed:
0164         data = QVariant(m_AudioUsage > 0);
0165         break;
0166     case VideoUsed:
0167         data = QVariant(m_VideoUsage > 0);
0168         break;
0169     case ItemTypeRole:
0170         data = QVariant(m_itemType);
0171         break;
0172     case ClipType:
0173         data = clipType();
0174         break;
0175     case DataTag:
0176         data = QVariant(m_tags);
0177         break;
0178     case DataRating:
0179         data = QVariant(m_rating);
0180         break;
0181     case ClipHasAudioAndVideo:
0182         data = hasAudioAndVideo();
0183         break;
0184     case JobStatus:
0185         if (itemType() == ClipItem) {
0186             data = QVariant::fromValue(pCore->taskManager.jobStatus(ObjectId(KdenliveObjectType::BinClip, m_binId.toInt(), QUuid())));
0187             /*
0188             auto jobIds = pCore->jobManager()->getPendingJobsIds(clipId());
0189             if (jobIds.empty()) {
0190                 jobIds = pCore->jobManager()->getFinishedJobsIds(clipId());
0191             }
0192             if (jobIds.size() > 0) {
0193                 data = QVariant::fromValue(pCore->jobManager()->getJobStatus(jobIds[0]));
0194             } else {
0195                 data = QVariant::fromValue(JobManagerStatus::NoJob);
0196             }*/
0197         }
0198         break;
0199     case JobProgress:
0200         if (itemType() == ClipItem) {
0201             data = pCore->taskManager.getJobProgressForClip(ObjectId(KdenliveObjectType::BinClip, m_binId.toInt(), QUuid()));
0202         }
0203         break;
0204     case JobSuccess:
0205         // TODO: reimplement ?
0206         /*if (itemType() == ClipItem) {
0207             auto jobIds = pCore->jobManager()->getFinishedJobsIds(clipId());
0208             if (jobIds.size() > 0) {
0209                 // Check the last job status
0210                 data = QVariant(pCore->jobManager()->jobSucceded(jobIds[jobIds.size() - 1]));
0211             } else {
0212 
0213             }
0214         }*/
0215         data = QVariant(true);
0216         break;
0217     case SequenceFolder:
0218         if (itemType() == FolderItem) {
0219             if (auto ptr = m_model.lock()) {
0220                 if (m_binId.toInt() == std::static_pointer_cast<ProjectItemModel>(ptr)->defaultSequencesFolder()) {
0221                     data = QVariant(true);
0222                     break;
0223                 }
0224             }
0225         }
0226         data = QVariant(false);
0227         break;
0228     case ClipStatus:
0229         data = QVariant(m_clipStatus);
0230         break;
0231     case ClipToolTip:
0232         data = QVariant(getToolTip());
0233         break;
0234     default:
0235         break;
0236     }
0237     return data;
0238 }
0239 
0240 int AbstractProjectItem::supportedDataCount() const
0241 {
0242     return 9;
0243 }
0244 
0245 QString AbstractProjectItem::name() const
0246 {
0247     return m_name;
0248 }
0249 
0250 void AbstractProjectItem::setName(const QString &name)
0251 {
0252     m_name = name;
0253 }
0254 
0255 QString AbstractProjectItem::description() const
0256 {
0257     return m_description;
0258 }
0259 
0260 void AbstractProjectItem::setDescription(const QString &description)
0261 {
0262     m_description = description;
0263 }
0264 
0265 QPoint AbstractProjectItem::zone() const
0266 {
0267     return {};
0268 }
0269 
0270 void AbstractProjectItem::setClipStatus(FileStatus::ClipStatus status)
0271 {
0272     m_clipStatus = status;
0273 }
0274 
0275 bool AbstractProjectItem::statusReady() const
0276 {
0277     return m_clipStatus == FileStatus::StatusReady || m_clipStatus == FileStatus::StatusProxy || m_clipStatus == FileStatus::StatusProxyOnly;
0278 }
0279 
0280 FileStatus::ClipStatus AbstractProjectItem::clipStatus() const
0281 {
0282     return m_clipStatus;
0283 }
0284 
0285 std::shared_ptr<AbstractProjectItem> AbstractProjectItem::getEnclosingFolder(bool strict)
0286 {
0287     if (!strict && itemType() == AbstractProjectItem::FolderItem) {
0288         return std::static_pointer_cast<AbstractProjectItem>(shared_from_this());
0289     }
0290     if (auto ptr = m_parentItem.lock()) {
0291         return std::static_pointer_cast<AbstractProjectItem>(ptr)->getEnclosingFolder(false);
0292     }
0293     return std::shared_ptr<AbstractProjectItem>();
0294 }
0295 
0296 bool AbstractProjectItem::selfSoftDelete(Fun &undo, Fun &redo)
0297 {
0298     Fun local_undo = []() { return true; };
0299     Fun local_redo = []() { return true; };
0300     for (const auto &child : m_childItems) {
0301         bool res = std::static_pointer_cast<AbstractProjectItem>(child)->selfSoftDelete(local_undo, local_redo);
0302         if (!res) {
0303             bool undone = local_undo();
0304             Q_ASSERT(undone);
0305             return false;
0306         }
0307     }
0308     UPDATE_UNDO_REDO(local_redo, local_undo, undo, redo);
0309     return true;
0310 }
0311 
0312 QString AbstractProjectItem::lastParentId() const
0313 {
0314     return m_lastParentId;
0315 }
0316 
0317 void AbstractProjectItem::updateParent(std::shared_ptr<TreeItem> newParent)
0318 {
0319     // bool reload = !m_lastParentId.isEmpty();
0320     m_lastParentId.clear();
0321     if (newParent) {
0322         m_lastParentId = std::static_pointer_cast<AbstractProjectItem>(newParent)->clipId();
0323     }
0324     TreeItem::updateParent(newParent);
0325 }
0326 
0327 const QString &AbstractProjectItem::tags() const
0328 {
0329     return m_tags;
0330 }
0331 
0332 void AbstractProjectItem::setTags(const QString &tags)
0333 {
0334     m_tags = tags;
0335 }
0336 
0337 uint AbstractProjectItem::rating() const
0338 {
0339     return m_rating;
0340 }
0341 
0342 void AbstractProjectItem::setRating(uint rating)
0343 {
0344     m_rating = rating;
0345 }
0346 
0347 Fun AbstractProjectItem::getAudio_lambda()
0348 {
0349     return []() {
0350         qDebug() << "============\n\nABSTRACT AUDIO CHECK\n\n===========";
0351         return true;
0352     };
0353 }