abstractprojectitem.cpp 9.48 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/*
Copyright (C) 2012  Till Theato <root@ttill.de>
Copyright (C) 2014  Jean-Baptiste Mardelle <jb@kdenlive.org>
This file is part of Kdenlive. See www.kdenlive.org.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License or (at your option) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
11
by the membership of KDE e.V.), which shall act as a proxy
12
13
14
15
16
17
18
19
20
21
22
23
24
defined in Section 14 of version 3 of the license.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "abstractprojectitem.h"
#include "bin.h"
25
26
#include "core.h"
#include "jobs/jobmanager.h"
Nicolas Carion's avatar
Nicolas Carion committed
27
#include "macros.hpp"
Nicolas Carion's avatar
Nicolas Carion committed
28
#include "projectitemmodel.h"
29

30
31
32
33
#include "jobs/audiothumbjob.hpp"
#include "jobs/loadjob.hpp"
#include "jobs/thumbjob.hpp"

34
#include <QPainter>
Antonio Rojas's avatar
Antonio Rojas committed
35
#include <QPainterPath>
Nicolas Carion's avatar
Nicolas Carion committed
36
#include <QVariant>
37
38

#include <KLocalizedString>
Nicolas Carion's avatar
Nicolas Carion committed
39
#include <utility>
40

Nicolas Carion's avatar
Nicolas Carion committed
41
AbstractProjectItem::AbstractProjectItem(PROJECTITEMTYPE type, QString id, const std::shared_ptr<ProjectItemModel> &model, bool isRoot)
42
    : TreeItem(QList<QVariant>(), std::static_pointer_cast<AbstractTreeModel>(model), isRoot)
43
44
45
46
    , m_name()
    , m_description()
    , m_thumbnail(QIcon())
    , m_date()
Nicolas Carion's avatar
Nicolas Carion committed
47
    , m_binId(std::move(id))
48
    , m_usage(0)
49
    , m_rating(0)
50
    , m_clipStatus(FileStatus::StatusReady)
51
    , m_itemType(type)
Nicolas Carion's avatar
Nicolas Carion committed
52
    , m_lock(QReadWriteLock::Recursive)
53
    , m_isCurrent(false)
54
{
55
    Q_ASSERT(!isRoot || type == FolderItem);
56
57
}

Nicolas Carion's avatar
linting    
Nicolas Carion committed
58
bool AbstractProjectItem::operator==(const std::shared_ptr<AbstractProjectItem> &projectItem) const
59
60
{
    // FIXME: only works for folders
61
    bool equal = this->m_childItems == projectItem->m_childItems;
62
    // equal = equal && (m_parentItem == projectItem->m_parentItem);
63
64
65
    return equal;
}

66
std::shared_ptr<AbstractProjectItem> AbstractProjectItem::parent() const
67
{
68
    return std::static_pointer_cast<AbstractProjectItem>(m_parentItem.lock());
69
70
}

71
72
73
void AbstractProjectItem::setRefCount(uint count)
{
    m_usage = count;
74
    if (auto ptr = m_model.lock())
Nicolas Carion's avatar
Nicolas Carion committed
75
76
        std::static_pointer_cast<ProjectItemModel>(ptr)->onItemUpdated(std::static_pointer_cast<AbstractProjectItem>(shared_from_this()),
                                                                       AbstractProjectItem::UsageCount);
77
78
}

79
80
81
82
83
uint AbstractProjectItem::refCount() const
{
    return m_usage;
}

84
85
86
void AbstractProjectItem::addRef()
{
    m_usage++;
87
    if (auto ptr = m_model.lock())
Nicolas Carion's avatar
Nicolas Carion committed
88
89
        std::static_pointer_cast<ProjectItemModel>(ptr)->onItemUpdated(std::static_pointer_cast<AbstractProjectItem>(shared_from_this()),
                                                                       AbstractProjectItem::UsageCount);
90
91
92
93
94
}

void AbstractProjectItem::removeRef()
{
    m_usage--;
95
    if (auto ptr = m_model.lock())
Nicolas Carion's avatar
Nicolas Carion committed
96
97
        std::static_pointer_cast<ProjectItemModel>(ptr)->onItemUpdated(std::static_pointer_cast<AbstractProjectItem>(shared_from_this()),
                                                                       AbstractProjectItem::UsageCount);
98
99
}

100
101
const QString &AbstractProjectItem::clipId() const
{
Nicolas Carion's avatar
Nicolas Carion committed
102
    return m_binId;
103
104
105
106
}

QPixmap AbstractProjectItem::roundedPixmap(const QPixmap &source)
{
107
    QPixmap pix(source.size());
108
    pix.fill(QColor(0, 0, 0, 100));
109
110
111
112
113
114
115
116
117
118
    QPainter p(&pix);
    p.setRenderHint(QPainter::Antialiasing, true);
    QPainterPath path;
    path.addRoundedRect(0.5, 0.5, pix.width() - 1, pix.height() - 1, 4, 4);
    p.setClipPath(path);
    p.drawPixmap(0, 0, source);
    p.end();
    return pix;
}

119
AbstractProjectItem::PROJECTITEMTYPE AbstractProjectItem::itemType() const
120
{
121
    return m_itemType;
122
123
}

Nicolas Carion's avatar
Nicolas Carion committed
124
QVariant AbstractProjectItem::getData(DataType type) const
125
126
127
{
    QVariant data;
    switch (type) {
128
    case DataName:
129
        data = m_name.isEmpty() ? i18n("Unnamed") : QVariant(m_name);
130
131
132
133
134
135
136
137
        break;
    case DataDescription:
        data = QVariant(m_description);
        break;
    case DataThumbnail:
        data = QVariant(m_thumbnail);
        break;
    case DataId:
138
        data = QVariant(m_binId.toInt());
139
140
141
142
        break;
    case DataDuration:
        data = QVariant(m_duration);
        break;
143
144
145
    case ParentDuration:
        data = QVariant(m_parentDuration);
        break;
146
147
148
    case DataInPoint:
        data = QVariant(m_inPoint);
        break;
149
150
151
    case DataOutPoint:
        data = QVariant(m_outPoint);
        break;
152
153
154
155
156
157
158
159
    case DataDate:
        data = QVariant(m_date);
        break;
    case UsageCount:
        data = QVariant(m_usage);
        break;
    case ItemTypeRole:
        data = QVariant(m_itemType);
160
161
162
        break;
    case ClipType:
        data = clipType();
163
        break;
164
    case DataTag:
165
166
167
168
        data = QVariant(m_tags);
        break;
    case DataRating:
        data = QVariant(m_rating);
169
        break;
170
171
    case ClipHasAudioAndVideo:
        data = hasAudioAndVideo();
172
173
        break;
    case JobType:
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
        if (itemType() == ClipItem) {
            auto jobIds = pCore->jobManager()->getPendingJobsIds(clipId());
            if (jobIds.empty()) {
                jobIds = pCore->jobManager()->getFinishedJobsIds(clipId());
            }
            if (jobIds.size() > 0) {
                data = QVariant(pCore->jobManager()->getJobType(jobIds[0]));
            }
        }
        break;
    case JobStatus:
        if (itemType() == ClipItem) {
            auto jobIds = pCore->jobManager()->getPendingJobsIds(clipId());
            if (jobIds.empty()) {
                jobIds = pCore->jobManager()->getFinishedJobsIds(clipId());
            }
            if (jobIds.size() > 0) {
191
                data = QVariant::fromValue(pCore->jobManager()->getJobStatus(jobIds[0]));
192
            } else {
193
                data = QVariant::fromValue(JobManagerStatus::NoJob);
194
195
            }
        }
196
197
        break;
    case JobProgress:
198
199
200
201
202
203
204
205
        if (itemType() == ClipItem) {
            auto jobIds = pCore->jobManager()->getPendingJobsIds(clipId());
            if (jobIds.size() > 0) {
                data = QVariant(pCore->jobManager()->getJobProgressForClip(jobIds[0], clipId()));
            } else {
                data = QVariant(0);
            }
        }
206
        break;
207
    case JobSuccess:
208
        if (itemType() == ClipItem) {
209
210
211
212
213
214
            auto jobIds = pCore->jobManager()->getFinishedJobsIds(clipId());
            if (jobIds.size() > 0) {
                // Check the last job status
                data = QVariant(pCore->jobManager()->jobSucceded(jobIds[jobIds.size() - 1]));
            } else {
                data = QVariant(true);
215
216
            }
        }
217
218
219
220
221
222
223
224
225
        break;
    case ClipStatus:
        data = QVariant(m_clipStatus);
        break;
    case ClipToolTip:
        data = QVariant(getToolTip());
        break;
    default:
        break;
226
227
228
229
230
231
    }
    return data;
}

int AbstractProjectItem::supportedDataCount() const
{
232
    return 8;
233
234
235
236
237
238
239
}

QString AbstractProjectItem::name() const
{
    return m_name;
}

240
void AbstractProjectItem::setName(const QString &name)
241
242
243
244
245
246
247
248
249
{
    m_name = name;
}

QString AbstractProjectItem::description() const
{
    return m_description;
}

250
void AbstractProjectItem::setDescription(const QString &description)
251
252
253
254
255
256
{
    m_description = description;
}

QPoint AbstractProjectItem::zone() const
{
Nicolas Carion's avatar
Nicolas Carion committed
257
    return {};
258
259
}

260
void AbstractProjectItem::setClipStatus(FileStatus::ClipStatus status)
261
262
263
264
{
    m_clipStatus = status;
}

265
266
bool AbstractProjectItem::statusReady() const
{
267
    return m_clipStatus == FileStatus::StatusReady || m_clipStatus == FileStatus::StatusProxy || m_clipStatus == FileStatus::StatusProxyOnly;
268
269
}

270
FileStatus::ClipStatus AbstractProjectItem::clipStatus() const
271
272
273
274
{
    return m_clipStatus;
}

275
std::shared_ptr<AbstractProjectItem> AbstractProjectItem::getEnclosingFolder(bool strict)
276
277
{
    if (!strict && itemType() == AbstractProjectItem::FolderItem) {
278
        return std::static_pointer_cast<AbstractProjectItem>(shared_from_this());
279
    }
280
281
    if (auto ptr = m_parentItem.lock()) {
        return std::static_pointer_cast<AbstractProjectItem>(ptr)->getEnclosingFolder(false);
282
    }
283
    return std::shared_ptr<AbstractProjectItem>();
284
}
Nicolas Carion's avatar
Nicolas Carion committed
285

286
bool AbstractProjectItem::selfSoftDelete(Fun &undo, Fun &redo)
Nicolas Carion's avatar
Nicolas Carion committed
287
{
288
    pCore->jobManager()->slotDiscardClipJobs(clipId());
Nicolas Carion's avatar
Nicolas Carion committed
289
290
    Fun local_undo = []() { return true; };
    Fun local_redo = []() { return true; };
Nicolas Carion's avatar
Nicolas Carion committed
291
    for (const auto &child : m_childItems) {
292
        bool res = std::static_pointer_cast<AbstractProjectItem>(child)->selfSoftDelete(local_undo, local_redo);
Nicolas Carion's avatar
Nicolas Carion committed
293
294
295
        if (!res) {
            bool undone = local_undo();
            Q_ASSERT(undone);
Nicolas Carion's avatar
Nicolas Carion committed
296
297
298
            return false;
        }
    }
Nicolas Carion's avatar
Nicolas Carion committed
299
300
    UPDATE_UNDO_REDO(local_redo, local_undo, undo, redo);
    return true;
Nicolas Carion's avatar
Nicolas Carion committed
301
}
Nicolas Carion's avatar
Nicolas Carion committed
302
303
304
305
306
307

QString AbstractProjectItem::lastParentId() const
{
    return m_lastParentId;
}

308
void AbstractProjectItem::updateParent(std::shared_ptr<TreeItem> newParent)
Nicolas Carion's avatar
Nicolas Carion committed
309
{
Nicolas Carion's avatar
Nicolas Carion committed
310
    // bool reload = !m_lastParentId.isEmpty();
Nicolas Carion's avatar
Nicolas Carion committed
311
312
313
314
    m_lastParentId.clear();
    if (newParent) {
        m_lastParentId = std::static_pointer_cast<AbstractProjectItem>(newParent)->clipId();
    }
Nicolas Carion's avatar
Nicolas Carion committed
315
    TreeItem::updateParent(newParent);
Nicolas Carion's avatar
Nicolas Carion committed
316
}
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337

const QString & AbstractProjectItem::tags() const
{
    return m_tags;
}

void AbstractProjectItem::setTags(const QString tags)
{
    m_tags = tags;
}


uint AbstractProjectItem::rating() const
{
    return m_rating;
}

void AbstractProjectItem::setRating(uint rating)
{
    m_rating = rating;
}