File indexing completed on 2024-04-21 04:51:23

0001 /*
0002     SPDX-FileCopyrightText: 2008 Jean-Baptiste Mardelle <jb@kdenlive.org>
0003     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 #pragma once
0007 
0008 #include <QPainter>
0009 #include <QPushButton>
0010 #include <QStyledItemDelegate>
0011 
0012 namespace Purpose {
0013 class Menu;
0014 }
0015 
0016 #include "bin/model/markerlistmodel.hpp"
0017 #include "definitions.h"
0018 #include "render/renderrequest.h"
0019 #include "renderpresets/renderpresetmodel.hpp"
0020 #include "renderpresets/tree/renderpresettreemodel.hpp"
0021 #include "ui_renderwidget_ui.h"
0022 #include <KNSWidgets/Button>
0023 #include <knewstuff_version.h>
0024 
0025 class QDomElement;
0026 class QKeyEvent;
0027 
0028 // RenderViewDelegate is used to draw the progress bars.
0029 class RenderViewDelegate : public QStyledItemDelegate
0030 {
0031     Q_OBJECT
0032 public:
0033     explicit RenderViewDelegate(QWidget *parent)
0034         : QStyledItemDelegate(parent)
0035     {
0036     }
0037 
0038     void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
0039     {
0040         if (index.column() == 1) {
0041             painter->save();
0042             QStyleOptionViewItem opt(option);
0043             QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
0044             const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
0045             style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
0046 
0047             QFont font = painter->font();
0048             font.setBold(true);
0049             painter->setFont(font);
0050             QRect r1 = option.rect;
0051             r1.adjust(0, textMargin, 0, -textMargin);
0052             int mid = int((r1.height() / 2));
0053             r1.setBottom(r1.y() + mid);
0054             QRect bounding;
0055             painter->drawText(r1, Qt::AlignLeft | Qt::AlignTop, index.data().toString(), &bounding);
0056             r1.moveTop(r1.bottom() - textMargin);
0057             font.setBold(false);
0058             painter->setFont(font);
0059             painter->drawText(r1, Qt::AlignLeft | Qt::AlignTop, index.data(Qt::UserRole).toString());
0060             int progress = index.data(Qt::UserRole + 3).toInt();
0061             if (progress > 0 && progress < 100) {
0062                 // draw progress bar
0063                 QColor color = option.palette.alternateBase().color();
0064                 QColor fgColor = option.palette.text().color();
0065                 color.setAlpha(150);
0066                 fgColor.setAlpha(150);
0067                 painter->setBrush(QBrush(color));
0068                 painter->setPen(QPen(fgColor));
0069                 int width = qMin(200, r1.width() - 4);
0070                 QRect bgrect(r1.left() + 2, option.rect.bottom() - 6 - textMargin, width, 6);
0071                 painter->drawRoundedRect(bgrect, 3, 3);
0072                 painter->setBrush(QBrush(fgColor));
0073                 bgrect.adjust(2, 2, 0, -1);
0074                 painter->setPen(Qt::NoPen);
0075                 bgrect.setWidth((width - 2) * progress / 100);
0076                 painter->drawRect(bgrect);
0077             } else {
0078                 r1.setBottom(opt.rect.bottom());
0079                 r1.setTop(r1.bottom() - mid);
0080                 painter->drawText(r1, Qt::AlignLeft | Qt::AlignBottom, index.data(Qt::UserRole + 5).toString());
0081             }
0082             painter->restore();
0083         } else {
0084             QStyledItemDelegate::paint(painter, option, index);
0085         }
0086     }
0087 };
0088 
0089 class RenderJobItem : public QTreeWidgetItem
0090 {
0091 public:
0092     explicit RenderJobItem(QTreeWidget *parent, const QStringList &strings, int type = QTreeWidgetItem::Type);
0093     void setStatus(int status);
0094     int status() const;
0095     void setMetadata(const QString &data);
0096     const QString metadata() const;
0097 
0098 private:
0099     int m_status;
0100     QString m_data;
0101 };
0102 
0103 class RenderWidget : public QDialog
0104 {
0105     Q_OBJECT
0106 
0107 public:
0108     enum RenderError {
0109         CompositeError = 0,
0110         PresetError = 1,
0111         ProxyWarning = 2,
0112         PlaybackError = 3,
0113         OptionsError = 4
0114     };
0115 
0116     explicit RenderWidget(bool enableProxy, QWidget *parent = nullptr);
0117     ~RenderWidget() override;
0118     void saveConfig();
0119     void loadConfig();
0120     void setGuides(std::weak_ptr<MarkerListModel> guidesModel);
0121     void focusItem(const QString &profile = QString());
0122     void setRenderProgress(const QString &dest, int progress = 0, int frame = 0);
0123     void setRenderStatus(const QString &dest, int status, const QString &error);
0124     void setRenderProfile(const QMap<QString, QString> &props);
0125     void saveRenderProfile();
0126     void updateDocumentPath();
0127     int waitingJobsCount() const;
0128     int runningJobsCount() const;
0129     QString getFreeScriptName(const QUrl &projectName = QUrl(), const QString &prefix = QString());
0130     bool startWaitingRenderJobs();
0131     /** @brief Show / hide proxy settings. */
0132     void updateProxyConfig(bool enable);
0133 
0134     /** @brief Display warning message in render widget. */
0135     void errorMessage(RenderError type, const QString &message);
0136     /** @brief Update the render duration info when project duration changes. */
0137     void projectDurationChanged(int duration);
0138     /** @brief Update the render duration info when zone changes. */
0139     void zoneDurationChanged(int duration);
0140     /** @brief Update the render duration info. */
0141     void showRenderDuration();
0142 
0143 protected:
0144     QSize sizeHint() const override;
0145     void keyPressEvent(QKeyEvent *e) override;
0146     void parseProfile(QDomElement profile, QTreeWidgetItem *childitem, QString groupName,
0147                       QString extension = QString(), QString renderer = QStringLiteral("avformat"));
0148 
0149 public Q_SLOTS:
0150     void slotAbortCurrentJob();
0151     void slotPrepareExport(bool scriptExport = false);
0152     void adjustViewToProfile();
0153     void reloadGuides();
0154     /** @brief Adjust render file name to current project name. */
0155     void resetRenderPath(const QString &path);
0156     /** @brief Update metadata tooltip with current values. */
0157     void updateMetadataToolTip();
0158     /** @brief Update missing clip info. */
0159     void updateMissingClipsCount(int total, int used);
0160 
0161 private Q_SLOTS:
0162     /**
0163      * Will be called when the user selects an output file via the file dialog.
0164      * File extension will be added automatically.
0165      */
0166     void slotUpdateButtons(const QUrl &url);
0167     /**
0168      * Will be called when the user changes the output file path in the text line.
0169      * File extension must NOT be added, would make editing impossible!
0170      */
0171     void slotUpdateButtons();
0172     void refreshView();
0173 
0174     void slotChangeSelection(const QModelIndex &current, const QModelIndex &previous);
0175     /** @brief Updates available options when a new format has been selected. */
0176     void loadProfile();
0177     void refreshParams();
0178     void slotSavePresetAs();
0179     void slotNewPreset();
0180     void slotEditPreset();
0181 
0182     void slotRenderModeChanged();
0183     void slotUpdateRescaleHeight(int);
0184     void slotUpdateRescaleWidth(int);
0185     void slotCheckStartGuidePosition();
0186     void slotCheckEndGuidePosition();
0187     /** @brief Enable / disable the rescale options. */
0188     void setRescaleEnabled(bool enable);
0189     /** @brief Show updated command parameter in tooltip. */
0190     void adjustSpeed(int videoQuality);
0191 
0192     void slotStartScript();
0193     void slotDeleteScript();
0194     void parseScriptFiles();
0195     void slotCheckScript();
0196     void slotCheckJob();
0197     void slotCleanUpJobs();
0198 
0199     void slotHideLog();
0200     void slotPlayRendering(QTreeWidgetItem *item, int);
0201     void slotStartCurrentJob();
0202     /** @brief User shared a rendered file, give feedback. */
0203     void slotShareActionFinished(const QJsonObject &output, int error, const QString &message);
0204     /** @brief running jobs menu. */
0205     void prepareJobContextMenu(const QPoint &pos);
0206     /** @brief Prepare the render request. */
0207     void slotPrepareExport2(bool scriptExport = false);
0208 
0209 private:
0210     enum Tabs {
0211         RenderTab = 0,
0212         JobsTab,
0213         ScriptsTab
0214     };
0215 
0216     Ui::RenderWidget_UI m_view;
0217     QString m_projectFolder;
0218     RenderViewDelegate *m_scriptsDelegate;
0219     RenderViewDelegate *m_jobsDelegate;
0220     bool m_blockProcessing;
0221     QMap<int, QString> m_errorMessages;
0222     std::weak_ptr<MarkerListModel> m_guidesModel;
0223     std::shared_ptr<RenderPresetTreeModel> m_treeModel;
0224     QString m_currentProfile;
0225     RenderPresetParams m_params;
0226     int m_renderDuration{0};
0227     int m_missingClips{0};
0228     int m_missingUsedClips{0};
0229 
0230     Purpose::Menu *m_shareMenu;
0231     void parseProfiles(const QString &selectedProfile = QString());
0232     QUrl filenameWithExtension(QUrl url, const QString &extension);
0233     /** @brief Check if a job needs to be started. */
0234     void checkRenderStatus();
0235     void startRendering(RenderJobItem *item);
0236     /** @brief Create a rendering profile from MLT preset. */
0237     QTreeWidgetItem *loadFromMltPreset(const QString &groupName, const QString &path, QString profileName, bool codecInName = false);
0238     RenderJobItem *createRenderJob(const RenderRequest::RenderJob &job);
0239     void updateRenderInfoMessage();
0240 
0241 Q_SIGNALS:
0242     void abortProcess(const QString &url);
0243     /** Send the info about rendering that will be saved in the document:
0244     (profile destination, profile name and url of rendered file) */
0245     void selectedRenderProfile(const QMap<QString, QString> &renderProps);
0246     void shutdown();
0247 };