1 | /*************************************************************************** |
2 | * Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org) * |
3 | * * |
4 | * This program is free software; you can redistribute it and/or modify * |
5 | * it under the terms of the GNU General Public License as published by * |
6 | * the Free Software Foundation; either version 2 of the License, or * |
7 | * (at your option) any later version. * |
8 | * * |
9 | * This program is distributed in the hope that it will be useful, * |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
12 | * GNU General Public License for more details. * |
13 | * * |
14 | * You should have received a copy of the GNU General Public License * |
15 | * along with this program; if not, write to the * |
16 | * Free Software Foundation, Inc., * |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * |
18 | ***************************************************************************/ |
19 | |
20 | |
21 | #ifndef PROJECTLIST_H |
22 | #define PROJECTLIST_H |
23 | |
24 | #include "folderprojectitem.h" |
25 | #include "subprojectitem.h" |
26 | #include "jobs/abstractclipjob.h" |
27 | |
28 | #include "definitions.h" |
29 | #include "timecode.h" |
30 | #include "kdenlivesettings.h" |
31 | #include "project/invaliddialog.h" |
32 | |
33 | #include <QDomNodeList> |
34 | #include <QHash> |
35 | #include <QToolBar> |
36 | #include <QToolButton> |
37 | #include <QTreeWidget> |
38 | #include <QPainter> |
39 | #include <QUndoStack> |
40 | #include <QTimer> |
41 | #include <QApplication> |
42 | #include <QFuture> |
43 | #include <QFutureSynchronizer> |
44 | #include <QListWidget> |
45 | #include <QTimeLine> |
46 | #include <QPushButton> |
47 | |
48 | #include <KTreeWidgetSearchLine> |
49 | #include <KUrl> |
50 | #include <KIcon> |
51 | #include <kdeversion.h> |
52 | |
53 | #ifdef NEPOMUK |
54 | #include <nepomuk/kratingpainter.h> |
55 | #include <nepomuk/resource.h> |
56 | #endif |
57 | |
58 | #ifdef NEPOMUKCORE |
59 | #include <nepomuk2/kratingpainter.h> |
60 | #include <nepomuk2/resource.h> |
61 | #endif |
62 | |
63 | #if KDE_IS_VERSION(4,7,0) |
64 | #include <KMessageWidget> |
65 | #else |
66 | // Dummy KMessageWidget to allow compilation of MyMessageWidget class since Qt's moc doesn work inside #ifdef |
67 | #include <QLabel> |
68 | |
69 | class KMessageWidget: public QLabel |
70 | { |
71 | public: |
72 | KMessageWidget(QWidget * = 0) {}; |
73 | KMessageWidget(const QString &, QWidget * = 0) {}; |
74 | virtual ~KMessageWidget(){}; |
75 | }; |
76 | #endif |
77 | |
78 | class MyMessageWidget: public KMessageWidget |
79 | { |
80 | Q_OBJECT |
81 | public: |
82 | MyMessageWidget(QWidget *parent = 0); |
83 | MyMessageWidget(const QString &text, QWidget *parent = 0); |
84 | |
85 | protected: |
86 | bool event(QEvent* ev); |
87 | |
88 | signals: |
89 | void messageClosing(); |
90 | }; |
91 | |
92 | namespace Mlt |
93 | { |
94 | class Producer; |
95 | } |
96 | |
97 | class ProjectItem; |
98 | class ProjectListView; |
99 | class Render; |
100 | class KdenliveDoc; |
101 | class DocClipBase; |
102 | class AbstractClipJob; |
103 | class ItemDelegate; |
104 | |
105 | class SmallInfoLabel: public QPushButton |
106 | { |
107 | Q_OBJECT |
108 | public: |
109 | SmallInfoLabel(QWidget *parent = 0); |
110 | static const QString getStyleSheet(const QPalette &p); |
111 | private: |
112 | enum ItemRole { |
113 | NameRole = Qt::UserRole, |
114 | DurationRole, |
115 | UsageRole |
116 | }; |
117 | |
118 | QTimeLine* m_timeLine; |
119 | |
120 | public slots: |
121 | void slotSetJobCount(int jobCount); |
122 | |
123 | private slots: |
124 | void slotTimeLineChanged(qreal value); |
125 | void slotTimeLineFinished(); |
126 | }; |
127 | |
128 | class ProjectList : public QWidget |
129 | { |
130 | Q_OBJECT |
131 | |
132 | public: |
133 | ProjectList(QWidget *parent = 0); |
134 | virtual ~ProjectList(); |
135 | |
136 | QDomElement producersList(); |
137 | void setRenderer(Render *projectRender); |
138 | void slotUpdateClipProperties(const QString &id, QMap <QString, QString> properties); |
139 | QByteArray () const; |
140 | void (const QByteArray &state); |
141 | void updateProjectFormat(Timecode t); |
142 | void (QMenu *, QAction *defaultAction); |
143 | void (const QHash<QString,QMenu*>& ); |
144 | /** @brief Get a list of selected clip Id's and url's that match a condition. */ |
145 | QMap <QString, QString> getConditionalIds(const QString &condition) const; |
146 | QDomDocument generateTemplateXml(QString data, const QString &replaceString); |
147 | void cleanup(); |
148 | void trashUnusedClips(); |
149 | QList <DocClipBase*> documentClipList() const; |
150 | void addClipCut(const QString &id, int in, int out, const QString desc, bool newItem); |
151 | void removeClipCut(const QString &id, int in, int out); |
152 | void focusTree() const; |
153 | SubProjectItem *getSubItem(ProjectItem *clip, const QPoint &zone); |
154 | void doUpdateClipCut(const QString &id, const QPoint &oldzone, const QPoint &zone, const QString &); |
155 | bool hasMissingClips(); |
156 | void deleteProjectFolder(QMap <QString, QString> map); |
157 | void selectItemById(const QString &clipId); |
158 | |
159 | /** @brief Returns a string list of all supported mime extensions. */ |
160 | static QString getExtensions(); |
161 | /** @brief Returns a list of urls containing original and proxy urls. */ |
162 | QMap <QString, QString> getProxies(); |
163 | /** @brief Enable / disable proxies. */ |
164 | void updateProxyConfig(); |
165 | /** @brief Get a property from the document. */ |
166 | QString getDocumentProperty(const QString &key) const; |
167 | |
168 | /** @brief Does this project allow proxies. */ |
169 | bool useProxy() const; |
170 | /** @brief Should we automatically create proxy clips for newly added clips. */ |
171 | bool generateProxy() const; |
172 | /** @brief Should we automatically create proxy clips for newly added clips. */ |
173 | bool generateImageProxy() const; |
174 | /** @brief Returns a list of the expanded folder ids. */ |
175 | QStringList expandedFolders() const; |
176 | /** @brief Deselect all clips in project tree. */ |
177 | void clearSelection(); |
178 | /** @brief Print required overlays over clip thumb (proxy, stabilized,...). */ |
179 | void processThumbOverlays(ProjectItem *item, QPixmap &pix); |
180 | /** @brief Start an MLT process job. */ |
181 | void startClipFilterJob(const QString &filterName, const QString &condition); |
182 | /** @brief Set current document for the project tree. */ |
183 | void setDocument(KdenliveDoc *doc); |
184 | |
185 | /** @brief Palette was changed, update style. */ |
186 | void updatePalette(); |
187 | |
188 | public slots: |
189 | void updateAllClips(bool displayRatioChanged, bool fpsChanged, const QStringList &brokenClips); |
190 | void slotReplyGetImage(const QString &clipId, const QImage &img); |
191 | void slotReplyGetImage(const QString &clipId, const QString &name, int width, int height); |
192 | void slotReplyGetFileProperties(const QString &clipId, Mlt::Producer *producer, const stringMap &properties, const stringMap &metadata, bool replace); |
193 | void slotAddClip(DocClipBase *clip, bool getProperties); |
194 | void slotDeleteClip(const QString &clipId); |
195 | void slotUpdateClip(const QString &id); |
196 | void slotRefreshClipThumbnail(const QString &clipId, bool update = true); |
197 | void slotRefreshClipThumbnail(QTreeWidgetItem *item, bool update = true); |
198 | void slotRemoveInvalidClip(const QString &id, bool replace); |
199 | void slotRemoveInvalidProxy(const QString &id, bool durationError); |
200 | void slotSelectClip(const QString &ix); |
201 | |
202 | /** @brief Prepares removing the selected items. */ |
203 | void slotRemoveClip(); |
204 | void slotAddClip(const QString &url, const QString &groupName, const QString &groupId); |
205 | void slotAddClip(const QList <QUrl> &givenList = QList <QUrl> (), const QString &groupName = QString(), const QString &groupId = QString()); |
206 | |
207 | /** @brief Adds, edits or deletes a folder item. |
208 | * |
209 | * This is triggered by AddFolderCommand and EditFolderCommand. */ |
210 | void slotAddFolder(const QString &foldername, const QString &clipId, bool remove, bool edit = false); |
211 | void slotResetProjectList(); |
212 | void slotOpenClip(); |
213 | void slotEditClip(); |
214 | void slotReloadClip(const QString &id = QString()); |
215 | |
216 | /** @brief Shows dialog for setting up a color clip. */ |
217 | void slotAddColorClip(); |
218 | void regenerateTemplate(const QString &id); |
219 | void slotUpdateClipCut(QPoint p); |
220 | void slotAddClipCut(const QString &id, int in, int out); |
221 | void slotForceProcessing(const QString &id); |
222 | /** @brief Remove all instances of a proxy and delete the file. */ |
223 | void slotDeleteProxy(const QString proxyPath); |
224 | /** @brief Start a hard cut clip job. */ |
225 | void slotCutClipJob(const QString &id, QPoint zone); |
226 | /** @brief Start transcoding selected clips. */ |
227 | void slotTranscodeClipJob(const QString &condition, QString params, QString desc); |
228 | /** @brief Start an MLT process job. */ |
229 | void slotStartFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QMap <QString, QString>&); |
230 | void slotSetThumbnail(const QString &id, int framePos, QImage img); |
231 | |
232 | |
233 | private: |
234 | ProjectListView *m_listView; |
235 | Render *m_render; |
236 | Timecode m_timecode; |
237 | double m_fps; |
238 | QMenu *; |
239 | QFuture<void> m_queueRunner; |
240 | QUndoStack *m_commandStack; |
241 | ProjectItem *getItemById(const QString &id); |
242 | QTreeWidgetItem *getAnyItemById(const QString &id); |
243 | FolderProjectItem *getFolderItemById(const QString &id); |
244 | FolderProjectItem *getFolderItemByName(const QString &name); |
245 | QAction *m_openAction; |
246 | QAction *m_reloadAction; |
247 | QAction *m_discardCurrentClipJobs; |
248 | QMenu *; |
249 | QMenu *m_transcodeAction; |
250 | QMenu *; |
251 | KdenliveDoc *m_doc; |
252 | ItemDelegate *m_listViewDelegate; |
253 | /** @brief False if we have not yet finished opening the document. */ |
254 | bool m_refreshed; |
255 | /** @brief False if we have not yet finished checking all project tree thumbs. */ |
256 | bool m_allClipsProcessed; |
257 | QToolButton *m_addButton; |
258 | QToolButton *m_deleteButton; |
259 | QToolButton *m_editButton; |
260 | //QMap <QString, QDomElement> m_infoQueue; |
261 | QMap <QString, QDomElement> m_producerQueue; |
262 | QList <QString> m_thumbnailQueue; |
263 | QAction *m_proxyAction; |
264 | QMutex m_jobMutex; |
265 | QMutex m_processMutex; |
266 | bool m_abortAllJobs; |
267 | /** @brief We are cleaning up the project list, so stop processing signals. */ |
268 | bool m_closing; |
269 | QList <AbstractClipJob *> m_jobList; |
270 | QFutureSynchronizer<void> m_jobThreads; |
271 | InvalidDialog *m_invalidClipDialog; |
272 | QMenu *; |
273 | SmallInfoLabel *m_infoLabel; |
274 | /** @brief A list of strings containing the last error logs for clip jobs. */ |
275 | QStringList m_errorLog; |
276 | |
277 | #if KDE_IS_VERSION(4,7,0) |
278 | MyMessageWidget *m_infoMessage; |
279 | /** @brief The action that will trigger the log dialog. */ |
280 | QAction *m_logAction; |
281 | #endif |
282 | |
283 | void requestClipThumbnail(const QString &id); |
284 | |
285 | /** @brief Creates an EditFolderCommand to change the name of an folder item. */ |
286 | void editFolder(const QString folderName, const QString oldfolderName, const QString &clipId); |
287 | |
288 | /** @brief Gets the selected folder (or the folder of the selected item). */ |
289 | QStringList getGroup() const; |
290 | void regenerateTemplate(ProjectItem *clip); |
291 | void editClipSelection(QList<QTreeWidgetItem *> list); |
292 | |
293 | /** @brief Enables and disables transcode actions based on the selected clip's type. */ |
294 | void adjustTranscodeActions(ProjectItem *clip) const; |
295 | /** @brief Enables and disables stabilize actions based on the selected clip's type. */ |
296 | void adjustStabilizeActions(ProjectItem *clip) const; |
297 | /** @brief Enables and disables proxy action based on the selected clip. */ |
298 | void adjustProxyActions(ProjectItem *clip) const; |
299 | |
300 | /** @brief Sets the buttons enabled/disabled according to selected item. */ |
301 | void updateButtons() const; |
302 | |
303 | /** @brief Set the Proxy status on a clip. |
304 | * @param item The clip item to set status |
305 | * @param jobType The job type |
306 | * @param status The job status (see definitions.h) |
307 | * @param progress The job progress (in percents) |
308 | * @param statusMessage The job info message */ |
309 | void setJobStatus(ProjectItem *item, JOBTYPE jobType, ClipJobStatus status, int progress = 0, const QString &statusMessage = QString()); |
310 | void monitorItemEditing(bool enable); |
311 | /** @brief Get cached thumbnail for a project's clip or create it if no cache. */ |
312 | void getCachedThumbnail(ProjectItem *item); |
313 | void getCachedThumbnail(SubProjectItem *item); |
314 | /** @brief The clip is about to be reloaded, cancel thumbnail requests. */ |
315 | void resetThumbsProducer(DocClipBase *clip); |
316 | /** @brief Check if a clip has a running or pending job process. */ |
317 | bool hasPendingJob(ProjectItem *item, JOBTYPE type); |
318 | /** @brief Delete pending jobs for a clip. */ |
319 | void deleteJobsForClip(const QString &clipId); |
320 | /** @brief Discard specific job type for a clip. */ |
321 | void discardJobs(const QString &id, JOBTYPE type = NOJOBTYPE); |
322 | /** @brief Get the list of job names for current clip. */ |
323 | QStringList getPendingJobs(const QString &id); |
324 | /** @brief Start an MLT process job. */ |
325 | void processClipJob(QStringList ids, const QString&destination, bool autoAdd, QStringList jobParams, const QString &description, stringMap = stringMap()); |
326 | /** @brief Create rounded shape pixmap for project tree thumb. */ |
327 | QPixmap roundedPixmap(const QImage &img); |
328 | QPixmap roundedPixmap(const QPixmap &source); |
329 | /** @brief Extract a clip's metadata with the exiftool program. */ |
330 | void (DocClipBase *clip); |
331 | /** @brief Add a special FFmpeg tag if clip matches some properties (for example set full_luma for Sony NEX camcorders. */ |
332 | //void checkCamcorderFilters(DocClipBase *clip, QMap <QString, QString> meta); |
333 | |
334 | private slots: |
335 | void slotClipSelected(); |
336 | void slotAddSlideshowClip(); |
337 | void slotAddTitleClip(); |
338 | void slotAddTitleTemplateClip(); |
339 | |
340 | /** @brief Shows the context menu after enabling and disabling actions based on the item's type. |
341 | * @param pos The position where the menu should pop up |
342 | * @param item The item for which the checks should be done */ |
343 | void (const QPoint &pos, QTreeWidgetItem *item); |
344 | |
345 | /** @brief Creates an AddFolderCommand. */ |
346 | void slotAddFolder(const QString &name = QString()); |
347 | |
348 | /** @brief This is triggered when a clip description has been modified. */ |
349 | void slotItemEdited(QTreeWidgetItem *item, int column); |
350 | void slotUpdateClipProperties(ProjectItem *item, QMap <QString, QString> properties); |
351 | void slotProcessNextThumbnail(); |
352 | void slotCheckForEmptyQueue(); |
353 | void slotPauseMonitor(); |
354 | /** A clip was modified externally, change icon so that user knows it */ |
355 | void slotModifiedClip(const QString &id); |
356 | void slotMissingClip(const QString &id); |
357 | void slotAvailableClip(const QString &id); |
358 | /** @brief Try to find a matching profile for given item. */ |
359 | bool adjustProjectProfileToItem(ProjectItem *item = NULL); |
360 | /** @brief Add a sequence from the stopmotion widget. */ |
361 | void slotAddOrUpdateSequence(const QString &frameName); |
362 | /** @brief A proxy clip was created, update display. */ |
363 | void slotGotProxy(const QString &proxyPath); |
364 | void slotGotProxy(ProjectItem *item); |
365 | /** @brief Enable / disable proxy for current clip. */ |
366 | void slotProxyCurrentItem(bool doProxy, ProjectItem *itemToProxy = NULL); |
367 | /** @brief Put clip in the proxy waiting list. */ |
368 | void slotCreateProxy(const QString &id); |
369 | /** @brief Stop creation of this clip's proxy. */ |
370 | void slotAbortProxy(const QString &id, const QString& path); |
371 | /** @brief Start creation of clip jobs. */ |
372 | void slotProcessJobs(); |
373 | /** @brief Discard running and pending clip jobs. */ |
374 | void slotCancelJobs(); |
375 | /** @brief Discard a running clip jobs. */ |
376 | void slotCancelRunningJob(const QString id, stringMap); |
377 | /** @brief Update a clip's job status. */ |
378 | void slotProcessLog(const QString&, int progress, int, const QString & tmp= QString()); |
379 | /** @brief A clip job crashed, inform user. */ |
380 | void slotUpdateJobStatus(const QString id, int type, int status, const QString label, const QString actionName, const QString details); |
381 | void slotUpdateJobStatus(ProjectItem *item, int type, int status, const QString &label, const QString &actionName = QString(), const QString details = QString()); |
382 | /** @brief Display error log for last failed job. */ |
383 | void slotShowJobLog(); |
384 | /** @brief A proxy clip is ready. */ |
385 | void slotGotProxyForId(const QString); |
386 | /** @brief Check if it is necessary to start a job thread. */ |
387 | void slotCheckJobProcess(); |
388 | /** @brief Fill the jobs menu with current clip's jobs. */ |
389 | void (); |
390 | /** @brief Discard all jobs for current clip. */ |
391 | void slotDiscardClipJobs(); |
392 | /** @brief Make sure current clip is visible in project tree. */ |
393 | void slotCheckScrolling(); |
394 | /** @brief Reset all text and log data from info message widget. */ |
395 | void slotResetInfoMessage(); |
396 | /** @brief close warning info passive popup. */ |
397 | void (); |
398 | /** @brief process clip job result. */ |
399 | void slotGotFilterJobResults(QString ,int , int, stringMap, stringMap); |
400 | |
401 | signals: |
402 | void clipSelected(DocClipBase *, const QPoint &zone = QPoint(), bool forceUpdate = false); |
403 | void receivedClipDuration(const QString &); |
404 | void showClipProperties(DocClipBase *); |
405 | void showClipProperties(const QList <DocClipBase *>&, const QMap<QString, QString> &commonproperties); |
406 | void projectModified(); |
407 | void loadingIsOver(); |
408 | void displayMessage(const QString&, int progress, MessageType type = DefaultMessage); |
409 | void clipNameChanged(const QString&, const QString&); |
410 | void clipNeedsReload(const QString&); |
411 | /** @brief A property affecting display was changed, so we need to update monitors and thumbnails |
412 | * @param id: The clip's id string |
413 | * @param resetThumbs Should we recreate the timeline thumbnails. */ |
414 | void refreshClip(const QString &id, bool resetThumbs); |
415 | void updateRenderStatus(); |
416 | void deleteProjectClips(const QStringList &ids, const QMap <QString, QString> &folderids); |
417 | void findInTimeline(const QString &clipId); |
418 | /** @brief Request a profile change for current document. */ |
419 | void updateProfile(const QString &); |
420 | void processNextThumbnail(); |
421 | /** @brief Activate the clip monitor. */ |
422 | void raiseClipMonitor(bool forceRefresh); |
423 | /** @brief Set number of running jobs. */ |
424 | void jobCount(int); |
425 | void cancelRunningJob(const QString&, const stringMap&); |
426 | void processLog(const QString&, int , int, const QString & = QString()); |
427 | void addClip(const QString, const QString &, const QString &); |
428 | void updateJobStatus(const QString&, int, int, const QString &label = QString(), const QString &actionName = QString(), const QString &details = QString()); |
429 | void gotProxy(const QString&); |
430 | void checkJobProcess(); |
431 | /** @brief A Filter Job produced results, send them back to the clip. */ |
432 | void gotFilterJobResults(const QString &id, int startPos, int track, const stringMap ¶ms, const stringMap &); |
433 | void pauseMonitor(); |
434 | void updateAnalysisData(DocClipBase *); |
435 | void (const QString &, const QList <CommentedTime>&); |
436 | }; |
437 | |
438 | #endif |
439 | |
440 | |
441 | |