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