File indexing completed on 2024-04-28 08:44:20

0001 /*
0002 SPDX-FileCopyrightText: 2014 Till Theato <root@ttill.de>
0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 #include "notesplugin.h"
0007 #include "core.h"
0008 #include "dialogs/noteswidget.h"
0009 #include "doc/kdenlivedoc.h"
0010 #include "klocalizedstring.h"
0011 #include "mainwindow.h"
0012 #include "monitor/monitormanager.h"
0013 #include "project/projectmanager.h"
0014 
0015 #include <QStyle>
0016 #include <QVBoxLayout>
0017 
0018 NotesPlugin::NotesPlugin(ProjectManager *projectManager)
0019     : QObject(projectManager)
0020 {
0021     QWidget *container = new QWidget();
0022     auto *lay = new QVBoxLayout();
0023     lay->setSpacing(0);
0024     m_tb = new QToolBar();
0025     m_tb->setToolButtonStyle(Qt::ToolButtonIconOnly);
0026     int size = container->style()->pixelMetric(QStyle::PM_SmallIconSize);
0027     QSize iconSize(size, size);
0028     m_tb->setIconSize(iconSize);
0029     lay->addWidget(m_tb);
0030     m_widget = new NotesWidget();
0031     lay->addWidget(m_widget);
0032     container->setLayout(lay);
0033     connect(m_widget, &NotesWidget::insertNotesTimecode, this, &NotesPlugin::slotInsertTimecode);
0034     connect(m_widget, &NotesWidget::insertTextNote, this, &NotesPlugin::slotInsertText);
0035     connect(m_widget, &NotesWidget::reAssign, this, &NotesPlugin::slotReAssign);
0036     m_widget->setTabChangesFocus(true);
0037     m_widget->setPlaceholderText(i18n("Enter your project notes here …"));
0038     m_notesDock = pCore->window()->addDock(i18n("Project Notes"), QStringLiteral("notes_widget"), container);
0039     m_notesDock->close();
0040     connect(projectManager, &ProjectManager::docOpened, this, &NotesPlugin::setProject);
0041 }
0042 
0043 void NotesPlugin::setProject(KdenliveDoc *document)
0044 {
0045     connect(m_widget, SIGNAL(textChanged()), document, SLOT(setModified()));
0046     connect(m_widget, &NotesWidget::seekProject, pCore->projectManager(), &ProjectManager::seekTimeline, Qt::UniqueConnection);
0047     if (m_tb->actions().isEmpty()) {
0048         // initialize toolbar
0049         m_tb->addAction(pCore->window()->action("add_project_note"));
0050         QAction *a = new QAction(QIcon::fromTheme(QStringLiteral("edit-find-replace")), i18n("Reassign selected timecodes to current Bin clip"));
0051         connect(a, &QAction::triggered, m_widget, &NotesWidget::assignProjectNote);
0052         m_tb->addAction(a);
0053         a = new QAction(QIcon::fromTheme(QStringLiteral("list-add")), i18n("Create markers from selected timecodes"));
0054         a->setWhatsThis(
0055             xi18nc("@info:whatsthis", "Creates markers in the timeline from the selected timecodes (doesn’t matter if other text is selected too)."));
0056         connect(a, &QAction::triggered, m_widget, &NotesWidget::createMarkers);
0057         m_tb->addAction(a);
0058     }
0059 }
0060 
0061 void NotesPlugin::showDock()
0062 {
0063     m_notesDock->show();
0064     m_notesDock->raise();
0065 }
0066 
0067 void NotesPlugin::slotInsertTimecode()
0068 {
0069     if (pCore->monitorManager()->isActive(Kdenlive::ClipMonitor)) {
0070         // Add a note on the current bin clip
0071         int frames = pCore->monitorManager()->clipMonitor()->position();
0072         QString position = pCore->timecode().getTimecodeFromFrames(frames);
0073         const QString binId = pCore->monitorManager()->clipMonitor()->activeClipId();
0074         if (binId.isEmpty()) {
0075             pCore->displayMessage(i18n("Cannot add note, no clip selected in project bin"), ErrorMessage);
0076             return;
0077         }
0078         QString clipName = pCore->bin()->getBinClipName(binId);
0079         m_widget->insertHtml(QString("<a href=\"%1#%2\">%3:%4</a> ").arg(binId, QString::number(frames), clipName, position));
0080     } else {
0081         int frames = pCore->monitorManager()->projectMonitor()->position();
0082         QString position = pCore->timecode().getTimecodeFromFrames(frames);
0083         QPair<int, QString> currentTrackInfo = pCore->currentTrackInfo();
0084         const QUuid uuid = pCore->currentTimelineId();
0085         if (currentTrackInfo.first != -1) {
0086             // Insert timeline position with track reference
0087             m_widget->insertHtml(
0088                 QString("<a href=\"%1!%2?%3\">%4 %5</a> ")
0089                     .arg(uuid.toString(), QString::number(frames), QString::number(currentTrackInfo.first), currentTrackInfo.second, position));
0090         } else {
0091             m_widget->insertHtml(QString("<a href=\"%1!%2\">%3</a> ").arg(uuid.toString(), QString::number(frames), position));
0092         }
0093     }
0094 }
0095 
0096 void NotesPlugin::slotReAssign(const QStringList &anchors, const QList<QPoint> &points)
0097 {
0098     const QString binId = pCore->monitorManager()->clipMonitor()->activeClipId();
0099     int ix = 0;
0100     if (points.count() != anchors.count()) {
0101         // Something is wrong, abort
0102         pCore->displayMessage(i18n("Cannot perform assign"), ErrorMessage);
0103         return;
0104     }
0105     for (const QString &a : anchors) {
0106         QPoint pt = points.at(ix);
0107         QString updatedLink = a;
0108         int position = 0;
0109         if (a.contains(QLatin1Char('#'))) {
0110             // Link was previously attached to another clip
0111             updatedLink = a.section(QLatin1Char('#'), 1);
0112             position = updatedLink.toInt();
0113             if (!binId.isEmpty()) {
0114                 updatedLink.prepend(QString("%1#").arg(binId));
0115             }
0116         } else {
0117             position = a.toInt();
0118             if (!binId.isEmpty()) {
0119                 updatedLink.prepend(QString("%1#").arg(binId));
0120             }
0121         }
0122         QTextCursor cur(m_widget->textCursor());
0123         cur.setPosition(pt.x());
0124         cur.setPosition(pt.y(), QTextCursor::KeepAnchor);
0125         QString pos = pCore->timecode().getTimecodeFromFrames(position);
0126         if (!binId.isEmpty()) {
0127             QString clipName = pCore->bin()->getBinClipName(binId);
0128             cur.insertHtml(QString("<a href=\"%1\">%2:%3</a> ").arg(updatedLink, clipName, pos));
0129         } else {
0130             // Timestamp relative to project timeline
0131             cur.insertHtml(QString("<a href=\"%1\">%2</a> ").arg(updatedLink, pos));
0132         }
0133         ix++;
0134     }
0135 }
0136 
0137 void NotesPlugin::slotInsertText(const QString &text)
0138 {
0139     m_widget->insertHtml(text);
0140 }
0141 
0142 NotesWidget *NotesPlugin::widget()
0143 {
0144     return m_widget;
0145 }
0146 
0147 void NotesPlugin::clear()
0148 {
0149     m_widget->clear();
0150 }