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

0001 /*
0002     SPDX-FileCopyrightText: 2021 Jean-Baptiste Mardelle
0003     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 #pragma once
0007 
0008 #include "ui_textbasededit_ui.h"
0009 #include "definitions.h"
0010 #include "pythoninterfaces/speechtotext.h"
0011 
0012 #include <QProcess>
0013 #include <QAction>
0014 #include <QTextEdit>
0015 #include <QMouseEvent>
0016 #include <QTimer>
0017 #include <QTemporaryFile>
0018 
0019 class ProjectClip;
0020 
0021 /**
0022  * @class VideoTextEdit: Video speech text editor
0023  * @brief A dialog for editing markers and guides.
0024  * @author Jean-Baptiste Mardelle
0025  */
0026 class VideoTextEdit : public QTextEdit
0027 {
0028     Q_OBJECT
0029 
0030 public:
0031     explicit VideoTextEdit(QWidget *parent = nullptr);
0032     void lineNumberAreaPaintEvent(QPaintEvent *event);
0033     int lineNumberAreaWidth();
0034     void repaintLines();
0035     void cleanup();
0036     /** @brief returns the link for the first word at position start in the text.
0037      *    This will seek forwards until a word is found in case selection starts with a space
0038      * @param cursor the current text cursor
0039      * @param start the first position of the selection
0040      * @param max the last position to check in seek operation*/
0041     const QString selectionStartAnchor(QTextCursor &cursor, int start, int max);
0042     /** @brief returns the link for the last word at position end in the text.
0043      *    This will seek backwards until a word is found in case selection ends with a space
0044      * @param cursor the current text cursor
0045      * @param end the last position of the selection
0046      * @param min the first position to check in seek operation*/
0047     const QString selectionEndAnchor(QTextCursor &cursor, int end, int min);
0048     void checkHoverBlock(int yPos);
0049     void blockClicked(Qt::KeyboardModifiers modifiers, bool play = false);
0050     QVector<QPoint> processedZones(const QVector<QPoint> &sourceZones);
0051     QVector<QPoint> getInsertZones();
0052     QVector<QPoint> fullExport();
0053     /** @brief Remove all text outside loadZones
0054      */
0055     void processCutZones(const QList <QPoint> &loadZones);
0056     void rebuildZones();
0057     QVector< QPair<double, double> > speechZones;
0058     QVector <QPoint> cutZones;
0059     QAction *bookmarkAction;
0060     QAction *deleteAction;
0061     
0062 protected:
0063     void mouseMoveEvent(QMouseEvent *e) override;
0064     void mousePressEvent(QMouseEvent *e) override;
0065     void mouseReleaseEvent(QMouseEvent *e) override;
0066     void keyPressEvent(QKeyEvent *e) override;
0067     void wheelEvent(QWheelEvent *e) override;
0068     void resizeEvent(QResizeEvent *e) override;
0069     void contextMenuEvent(QContextMenuEvent *event) override;
0070 
0071 public Q_SLOTS:
0072     void slotRemoveSilence();
0073 
0074 private Q_SLOTS:
0075     void updateLineNumberArea(const QRect &rect, int dy);
0076     
0077 private:
0078     QWidget *lineNumberArea;
0079     int m_hoveredBlock{-1};
0080     int m_lastClickedBlock{-1};
0081     QVector <int> m_selectedBlocks;
0082     int getFirstVisibleBlockId();
0083 };
0084 
0085 class LineNumberArea : public QWidget
0086 {
0087 public:
0088     LineNumberArea(VideoTextEdit *editor) : QWidget(editor), codeEditor(editor)
0089     {
0090         setMouseTracking(true);
0091     }
0092 
0093     QSize sizeHint() const override
0094     {
0095         return QSize(codeEditor->lineNumberAreaWidth(), 0);
0096     }
0097 
0098 protected:
0099     void paintEvent(QPaintEvent *event) override
0100     {
0101         codeEditor->lineNumberAreaPaintEvent(event);
0102     }
0103     void mouseMoveEvent(QMouseEvent *e) override
0104     {
0105         codeEditor->checkHoverBlock(e->pos().y());
0106         QWidget::mouseMoveEvent(e);
0107     }
0108     void mousePressEvent(QMouseEvent *e) override
0109     {
0110         codeEditor->blockClicked(e->modifiers());
0111         QWidget::mousePressEvent(e);
0112     }
0113     void mouseDoubleClickEvent(QMouseEvent *e) override
0114     {
0115         codeEditor->blockClicked(e->modifiers(), true);
0116         QWidget::mouseDoubleClickEvent(e);
0117     }
0118     void wheelEvent(QWheelEvent *e) override
0119     {
0120         qDebug()<<"==== WHEEL OVER LINEAREA";
0121         e->ignore();
0122         //QWidget::wheelEvent(e);
0123     }
0124     void leaveEvent(QEvent *e) override
0125     {
0126         codeEditor->checkHoverBlock(-1);
0127         QWidget::leaveEvent(e);
0128     }
0129 
0130 private:
0131     VideoTextEdit *codeEditor;
0132 };
0133 
0134 /**
0135  * @class TextBasedEdit: Subtitle edit widget
0136  * @brief A dialog for editing markers and guides.
0137  * @author Jean-Baptiste Mardelle
0138  */
0139 class TextBasedEdit : public QWidget, public Ui::TextBasedEdit_UI
0140 {
0141     Q_OBJECT
0142 
0143 public:
0144     explicit TextBasedEdit(QWidget *parent = nullptr);
0145     ~TextBasedEdit() override;
0146     void openClip(std::shared_ptr<ProjectClip>);
0147 
0148 public Q_SLOTS:
0149     void deleteItem();
0150 
0151 private Q_SLOTS:
0152     void startRecognition();
0153     void slotProcessSpeech();
0154     void slotProcessWhisperSpeech();
0155     void slotProcessSpeechError();
0156     void slotProcessSpeechStatus(int, QProcess::ExitStatus status);
0157     /** @brief insert currently selected zones to timeline */
0158     void insertToTimeline();
0159     /** @brief Preview current edited text in the clip monitor */
0160     void previewPlaylist(bool createNew = true);
0161     /** @brief Create a timeline sequence with current edit */
0162     void createSequence();
0163     /** @brief Display info message */
0164     void showMessage(const QString &text, KMessageWidget::MessageType type, QAction *action = nullptr);
0165     void addBookmark();
0166     void updateEngine();
0167     void slotZoomIn();
0168     void slotZoomOut();
0169 
0170 protected:
0171     bool eventFilter(QObject *obj, QEvent *event) override;
0172 
0173 private:
0174     std::unique_ptr<QProcess> m_speechJob;
0175     std::unique_ptr<QProcess> m_tCodeJob;
0176     /** @brief Id of the master bin clip on which speech processing is done */
0177     QString m_binId;
0178     /** @brief Id of the playlist which is processed from the master clip */
0179     QString m_refId;
0180     QString m_sourceUrl;
0181     double m_clipDuration{0.};
0182     int m_lastPosition;
0183     QString m_errorString;
0184     QAction *m_logAction;
0185     QAction *m_voskConfig;
0186     QAction *m_currentMessageAction{nullptr};
0187     VideoTextEdit *m_visualEditor;
0188     QTextDocument m_document;
0189     QString m_playlist;
0190     QTimer m_hideTimer;
0191     double m_clipOffset;
0192     QTemporaryFile m_playlistWav;
0193     QTemporaryFile m_tmpCutWav;
0194     QAction *m_translateAction;
0195     SpeechToText *m_stt;
0196     void applyFontSize();
0197 };