1 /*
2     SPDX-FileCopyrightText: 2016 Jean-Baptiste Mardelle <jb@kdenlive.org>
3     This file is part of Kdenlive. See www.kdenlive.org.
4 
5     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
6 */
7 
8 #ifndef LIBRARYWIDGET_H
9 #define LIBRARYWIDGET_H
10 
11 #include "definitions.h"
12 
13 #include <QApplication>
14 #include <QDir>
15 #include <QMutex>
16 #include <QPainter>
17 #include <QStyledItemDelegate>
18 #include <QTimer>
19 #include <QTreeWidget>
20 
21 #include <KIO/ListJob>
22 #include <KIO/PreviewJob>
23 #include <KIOCore/KCoreDirLister>
24 #include <KIOCore/KFileItem>
25 #include <KMessageWidget>
26 
27 class ProjectManager;
28 class KJob;
29 class QProgressBar;
30 class QToolBar;
31 
32 /**
33  * @class BinItemDelegate
34  * @brief This class is responsible for drawing items in the QTreeView.
35  */
36 class LibraryItemDelegate : public QStyledItemDelegate
37 {
38 public:
39     explicit LibraryItemDelegate(QObject *parent = nullptr)
QStyledItemDelegate(parent)40         : QStyledItemDelegate(parent)
41     {
42     }
43 
updateEditorGeometry(QWidget * editor,const QStyleOptionViewItem & option,const QModelIndex & index)44     void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override
45     {
46         QStyleOptionViewItem opt = option;
47         initStyleOption(&opt, index);
48         QRect r1 = option.rect;
49         QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
50         const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
51         int decoWidth = int(2 * textMargin + r1.height() * 1.8);
52         int mid = r1.height() / 2;
53         r1.adjust(decoWidth, 0, 0, -mid);
54         QFont ft = option.font;
55         ft.setBold(true);
56         QFontMetricsF fm(ft);
57         QRect r2 = fm.boundingRect(r1, Qt::AlignLeft | Qt::AlignTop, index.data(Qt::DisplayRole).toString()).toRect();
58         editor->setGeometry(r2);
59     }
60 
sizeHint(const QStyleOptionViewItem & option,const QModelIndex & index)61     QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
62     {
63         QSize hint = QStyledItemDelegate::sizeHint(option, index);
64         QString text = index.data(Qt::UserRole + 1).toString();
65         QRectF r = option.rect;
66         QFont ft = option.font;
67         ft.setBold(true);
68         QFontMetricsF fm(ft);
69         QStyle *style = option.widget ? option.widget->style() : QApplication::style();
70         const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
71         int width = int(fm.boundingRect(r, Qt::AlignLeft | Qt::AlignTop, text).width() + option.decorationSize.width() + 2 * textMargin);
72         hint.setWidth(width);
73         return {hint.width(), qMax(option.fontMetrics.lineSpacing() * 2 + 4, qMax(hint.height(), option.decorationSize.height()))};
74     }
75 
paint(QPainter * painter,const QStyleOptionViewItem & option,const QModelIndex & index)76     void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
77     {
78         if (index.column() == 0) {
79             QRect r1 = option.rect;
80             painter->save();
81             painter->setClipRect(r1);
82             QStyleOptionViewItem opt(option);
83             initStyleOption(&opt, index);
84             QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
85             const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
86             // QRect r = QStyle::alignedRect(opt.direction, Qt::AlignVCenter | Qt::AlignLeft, opt.decorationSize, r1);
87 
88             style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
89             if (option.state & QStyle::State_Selected) {
90                 painter->setPen(option.palette.highlightedText().color());
91             } else {
92                 painter->setPen(option.palette.text().color());
93             }
94             QRect r = r1;
95             QFont font = painter->font();
96             font.setBold(true);
97             painter->setFont(font);
98             int decoWidth = int(2 * textMargin + r1.height() * 1.8);
99             r.setWidth(int(r1.height() * 1.8));
100             // Draw thumbnail
101             opt.icon.paint(painter, r);
102             int mid = r1.height() / 2;
103             r1.adjust(decoWidth, 0, 0, -mid);
104             QRect r2 = option.rect;
105             r2.adjust(decoWidth, mid, 0, 0);
106             QRectF bounding;
107             painter->drawText(r1, Qt::AlignLeft | Qt::AlignTop, index.data(Qt::DisplayRole).toString(), &bounding);
108             font.setBold(false);
109             painter->setFont(font);
110             QString subText = index.data(Qt::UserRole + 1).toString();
111             r2.adjust(0, int(bounding.bottom() - r2.top()), 0, 0);
112             QColor subTextColor = painter->pen().color();
113             subTextColor.setAlphaF(.5);
114             painter->setPen(subTextColor);
115             painter->drawText(r2, Qt::AlignLeft | Qt::AlignTop, subText, &bounding);
116             painter->restore();
117         } else {
118             QStyledItemDelegate::paint(painter, option, index);
119         }
120     }
121 };
122 
123 /** @class LibraryTree
124     @brief \@todo Describe class LibraryTree
125     @todo Describe class LibraryTree
126  */
127 class LibraryTree : public QTreeWidget
128 {
129     Q_OBJECT
130 public:
131     explicit LibraryTree(QWidget *parent = nullptr);
132 
133 protected:
134     QStringList mimeTypes() const override;
135     QMimeData *mimeData(const QList<QTreeWidgetItem *> list) const override;
136     void dropEvent(QDropEvent *event) override;
137     void mousePressEvent(QMouseEvent *event) override;
138 
139 public slots:
140     void slotUpdateThumb(const QString &path, const QString &iconPath);
141     void slotUpdateThumb(const QString &path, const QPixmap &pix);
142 
143 signals:
144     void moveData(const QList<QUrl> &, const QString &);
145     void importSequence(const QStringList &, const QString &);
146 };
147 
148 /** @class LibraryWidget
149     @brief A "library" that contains a list of clips to be used across projects
150     @author Jean-Baptiste Mardelle
151  */
152 class LibraryWidget : public QWidget
153 {
154     Q_OBJECT
155 
156 public:
157     explicit LibraryWidget(ProjectManager *m_manager, QWidget *parent = nullptr);
158     void setupActions(const QList<QAction *> &list);
159 
160 public slots:
161     void slotAddToLibrary();
162     void slotUpdateLibraryPath();
163 
164 private slots:
165     void slotAddToProject();
166     void slotDeleteFromLibrary();
167     void updateActions();
168     void slotAddFolder();
169     void slotRenameItem();
170     void slotMoveData(const QList<QUrl> &, QString);
171     void slotSaveSequence(const QStringList &info, QString dest);
172     void slotItemEdited(QTreeWidgetItem *item, int column);
173     void slotDownloadFinished(KJob *);
174     void slotDownloadProgress(KJob *, int);
175     void slotGotPreview(const KFileItem &item, const QPixmap &pix);
176     void slotItemsAdded(const QUrl &url, const KFileItemList &list);
177     void slotItemsDeleted(const KFileItemList &list);
178     void slotClearAll();
179 
180 private:
181     LibraryTree *m_libraryTree;
182     QToolBar *m_toolBar;
183     QProgressBar *m_progressBar;
184     QAction *m_addAction;
185     QAction *m_deleteAction;
186     QTimer m_timer;
187     KMessageWidget *m_infoWidget;
188     ProjectManager *m_manager;
189     QList<QTreeWidgetItem *> m_folders;
190     KIO::PreviewJob *m_previewJob;
191     KCoreDirLister *m_coreLister;
192     QMutex m_treeMutex;
193     QDir m_directory;
194     void showMessage(const QString &text, KMessageWidget::MessageType type = KMessageWidget::Warning);
195 
196 signals:
197     void addProjectClips(const QList<QUrl> &);
198     void thumbReady(const QString &, const QString &);
199     void enableAddSelection(bool);
200     void saveTimelineSelection(QDir);
201 };
202 
203 #endif
204