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 }