mirror of
https://invent.kde.org/multimedia/kdenlive
synced 2025-12-06 08:20:01 +01:00
Compare commits
4 Commits
master
...
work/notes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
187947ea93 | ||
|
|
21b1ca17ae | ||
|
|
3a41707866 | ||
|
|
b9f6a2b29a |
@@ -15,6 +15,7 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
#include <QMenu>
|
||||
#include <QMimeData>
|
||||
#include <QMouseEvent>
|
||||
#include <QTextDocumentFragment>
|
||||
#include <QToolTip>
|
||||
#include <QUuid>
|
||||
|
||||
@@ -22,6 +23,7 @@ NotesWidget::NotesWidget(QWidget *parent)
|
||||
: QTextEdit(parent)
|
||||
{
|
||||
setMouseTracking(true);
|
||||
// setAcceptRichText(true);
|
||||
}
|
||||
|
||||
NotesWidget::~NotesWidget() = default;
|
||||
@@ -215,6 +217,32 @@ void NotesWidget::createMarkers()
|
||||
}
|
||||
}
|
||||
|
||||
void NotesWidget::switchMarkDownEditing(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
QString text = toMarkdown();
|
||||
clear();
|
||||
QTextCursor cursor = textCursor();
|
||||
cursor.select(QTextCursor::Document);
|
||||
cursor.setCharFormat(QTextCharFormat());
|
||||
cursor.clearSelection();
|
||||
setTextCursor(cursor);
|
||||
// setAcceptRichText(false);
|
||||
setPlainText(text);
|
||||
} else {
|
||||
QString text = toPlainText();
|
||||
text.replace(QStringLiteral("\n\n\n"), QStringLiteral("\n<br/>\n\n"));
|
||||
clear();
|
||||
QTextCursor cursor = textCursor();
|
||||
cursor.select(QTextCursor::Document);
|
||||
cursor.setCharFormat(QTextCharFormat());
|
||||
cursor.clearSelection();
|
||||
setTextCursor(cursor);
|
||||
// setAcceptRichText(true);
|
||||
setMarkdown(text);
|
||||
}
|
||||
}
|
||||
|
||||
void NotesWidget::addProjectNote()
|
||||
{
|
||||
if (!textCursor().atBlockStart()) {
|
||||
@@ -239,27 +267,88 @@ void NotesWidget::addTextNote(const QString &text)
|
||||
void NotesWidget::insertFromMimeData(const QMimeData *source)
|
||||
{
|
||||
QString pastedText = source->text();
|
||||
bool enforceHtml = false;
|
||||
bool enforceMarkDown = pastedText.contains(QLatin1String("# "));
|
||||
// Check for timecodes
|
||||
QStringList words = pastedText.split(QLatin1Char(' '));
|
||||
for (const QString &w : std::as_const(words)) {
|
||||
if (w.size() > 4 && w.size() < 13 && w.count(QLatin1Char(':')) > 1) {
|
||||
// This is probably a timecode
|
||||
int frames = pCore->timecode().getFrameCount(w);
|
||||
if (frames > 0) {
|
||||
pastedText.replace(w, QStringLiteral("<a href=\"") + QString::number(frames) + QStringLiteral("\">") + w + QStringLiteral("</a> "));
|
||||
enforceHtml = true;
|
||||
if (frames == 0) {
|
||||
// Check if that is a correct timecode like 00:00:00
|
||||
QString simplified = w;
|
||||
simplified.remove(QLatin1Char(':'));
|
||||
simplified.remove(QLatin1Char('0'));
|
||||
simplified.remove(QLatin1Char('.'));
|
||||
if (simplified.simplified().isEmpty()) {
|
||||
// Ok, we really have a zero timecode
|
||||
pastedText.replace(w, QStringLiteral("[%1](%2)").arg(w).arg(QString::number(0)));
|
||||
enforceMarkDown = true;
|
||||
}
|
||||
} else if (frames > 0) {
|
||||
pastedText.replace(w, QStringLiteral("[%1](%2)").arg(w).arg(QString::number(frames)));
|
||||
enforceMarkDown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (enforceHtml || Qt::mightBeRichText(pastedText)) {
|
||||
pastedText.replace(QLatin1Char('\n'), QStringLiteral("<br/>"));
|
||||
insertHtml(pastedText);
|
||||
|
||||
if (enforceMarkDown) {
|
||||
textCursor().insertMarkdown(pastedText);
|
||||
} else {
|
||||
insertPlainText(pastedText);
|
||||
}
|
||||
}
|
||||
|
||||
void NotesWidget::insertMarkDown(const QString &md)
|
||||
{
|
||||
textCursor().insertMarkdown(md);
|
||||
}
|
||||
|
||||
void NotesWidget::switchBoldText()
|
||||
{
|
||||
QTextCursor cur = textCursor();
|
||||
int nCurPos = cur.position();
|
||||
if (!cur.hasSelection()) {
|
||||
cur.select(QTextCursor::WordUnderCursor);
|
||||
} else {
|
||||
int startPos = cur.selectionStart();
|
||||
int endPos = cur.selectionEnd();
|
||||
cur.setPosition(endPos, QTextCursor::MoveAnchor);
|
||||
cur.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor);
|
||||
cur.setPosition(startPos, QTextCursor::QTextCursor::KeepAnchor);
|
||||
// Get current text style
|
||||
cur.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
|
||||
}
|
||||
QTextCharFormat format;
|
||||
if (cur.charFormat().font().bold()) {
|
||||
format.setFontWeight(QFont::Normal);
|
||||
} else {
|
||||
format.setFontWeight(QFont::Bold);
|
||||
}
|
||||
cur.mergeCharFormat(format);
|
||||
cur.setPosition(nCurPos);
|
||||
setTextCursor(cur);
|
||||
}
|
||||
|
||||
void NotesWidget::switchHeaderText()
|
||||
{
|
||||
QTextCursor cur = textCursor();
|
||||
cur.movePosition(QTextCursor::StartOfLine, QTextCursor::MoveAnchor);
|
||||
cur.select(QTextCursor::LineUnderCursor);
|
||||
QString currentText = cur.selection().toMarkdown();
|
||||
if (currentText.startsWith(QStringLiteral("# "))) {
|
||||
// Already a header, clear
|
||||
cur.setCharFormat(QTextCharFormat());
|
||||
currentText.remove(0, 2);
|
||||
} else {
|
||||
cur.setCharFormat(QTextCharFormat());
|
||||
currentText.prepend(QStringLiteral("# "));
|
||||
}
|
||||
cur.removeSelectedText();
|
||||
setTextCursor(cur);
|
||||
insertMarkDown(currentText);
|
||||
}
|
||||
|
||||
bool NotesWidget::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::ToolTip) {
|
||||
|
||||
@@ -24,6 +24,9 @@ public:
|
||||
* @param text the text
|
||||
*/
|
||||
void addTextNote(const QString &text);
|
||||
void insertMarkDown(const QString &md);
|
||||
void switchBoldText();
|
||||
void switchHeaderText();
|
||||
|
||||
protected:
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
@@ -35,6 +38,7 @@ protected:
|
||||
public Q_SLOTS:
|
||||
void createMarkers();
|
||||
void assignProjectNote();
|
||||
void switchMarkDownEditing(bool enable);
|
||||
|
||||
private:
|
||||
void createMarker(const QStringList &anchors);
|
||||
|
||||
@@ -56,6 +56,24 @@ void NotesPlugin::setProject(KdenliveDoc *document)
|
||||
xi18nc("@info:whatsthis", "Creates markers in the timeline from the selected timecodes (doesn’t matter if other text is selected too)."));
|
||||
connect(a, &QAction::triggered, m_widget, &NotesWidget::createMarkers);
|
||||
m_tb->addAction(a);
|
||||
m_tb->addSeparator();
|
||||
a = new QAction(QIcon::fromTheme(QStringLiteral("format-text-bold")), i18n("Bold"));
|
||||
a->setWhatsThis(xi18nc("@info:whatsthis", "Make selected text bold."));
|
||||
connect(a, &QAction::triggered, m_widget, &NotesWidget::switchBoldText);
|
||||
m_tb->addAction(a);
|
||||
a = new QAction(QIcon::fromTheme(QStringLiteral("format-font-size-more")), i18n("Header"));
|
||||
a->setWhatsThis(xi18nc("@info:whatsthis", "Switch header format"));
|
||||
connect(a, &QAction::triggered, m_widget, &NotesWidget::switchHeaderText);
|
||||
m_tb->addAction(a);
|
||||
|
||||
QWidget *empty = new QWidget();
|
||||
empty->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
m_tb->addWidget(empty);
|
||||
m_markDownEdit = new QAction(QIcon::fromTheme(QStringLiteral("format-text-code")), i18n("Edit Markdown source code"));
|
||||
m_markDownEdit->setCheckable(true);
|
||||
m_markDownEdit->setWhatsThis(xi18nc("@info:whatsthis", "Enable or disable markdown editing."));
|
||||
connect(m_markDownEdit, &QAction::triggered, m_widget, &NotesWidget::switchMarkDownEditing);
|
||||
m_tb->addAction(m_markDownEdit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +83,16 @@ void NotesPlugin::showDock()
|
||||
m_notesDock->raise();
|
||||
}
|
||||
|
||||
void NotesPlugin::loadNotes(QString text)
|
||||
{
|
||||
m_widget->clear();
|
||||
if (m_markDownEdit->isChecked()) {
|
||||
m_markDownEdit->trigger();
|
||||
}
|
||||
text.replace(QStringLiteral("\n\n\n"), QStringLiteral("\n<br />\n\n"));
|
||||
m_widget->setMarkdown(text);
|
||||
}
|
||||
|
||||
void NotesPlugin::slotInsertTimecode()
|
||||
{
|
||||
if (pCore->monitorManager()->isActive(Kdenlive::ClipMonitor)) {
|
||||
@@ -78,7 +106,7 @@ void NotesPlugin::slotInsertTimecode()
|
||||
}
|
||||
const QString clipName = pCore->bin()->getBinClipName(binId);
|
||||
const QString uuid = pCore->projectItemModel()->getBinClipUuid(binId);
|
||||
m_widget->insertHtml(QStringLiteral("<a href=\"%1#%2\">%3:%4</a> ").arg(uuid, QString::number(frames), clipName, position));
|
||||
m_widget->insertMarkDown(QStringLiteral("[%3:%4](%1#%2) ").arg(uuid, QString::number(frames), clipName, position));
|
||||
} else {
|
||||
int frames = pCore->monitorManager()->projectMonitor()->position();
|
||||
QString position = pCore->timecode().getTimecodeFromFrames(frames);
|
||||
@@ -86,11 +114,11 @@ void NotesPlugin::slotInsertTimecode()
|
||||
const QUuid uuid = pCore->currentTimelineId();
|
||||
if (currentTrackInfo.first != -1) {
|
||||
// Insert timeline position with track reference
|
||||
m_widget->insertHtml(
|
||||
QStringLiteral("<a href=\"%1!%2?%3\">%4 %5</a> ")
|
||||
m_widget->insertMarkDown(
|
||||
QStringLiteral("[%4 %5](%1!%2?%3) ")
|
||||
.arg(uuid.toString(), QString::number(frames), QString::number(currentTrackInfo.first), currentTrackInfo.second, position));
|
||||
} else {
|
||||
m_widget->insertHtml(QStringLiteral("<a href=\"%1!%2\">%3</a> ").arg(uuid.toString(), QString::number(frames), position));
|
||||
m_widget->insertMarkDown(QStringLiteral("[%3](%1!%2) ").arg(uuid.toString(), QString::number(frames), position));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,7 +176,7 @@ void NotesPlugin::slotReAssign(const QStringList &anchors, const QList<QPoint> &
|
||||
|
||||
void NotesPlugin::slotInsertText(const QString &text)
|
||||
{
|
||||
m_widget->insertHtml(text);
|
||||
m_widget->insertMarkDown(text);
|
||||
}
|
||||
|
||||
NotesWidget *NotesPlugin::widget()
|
||||
|
||||
@@ -12,6 +12,7 @@ class KdenliveDoc;
|
||||
class ProjectManager;
|
||||
class QDockWidget;
|
||||
class QToolBar;
|
||||
class QAction;
|
||||
|
||||
/** @class NotesPlugin
|
||||
@brief Handles connection of NotesWidget
|
||||
@@ -27,6 +28,7 @@ public:
|
||||
NotesWidget *widget();
|
||||
void clear();
|
||||
void showDock();
|
||||
void loadNotes(QString text);
|
||||
|
||||
private Q_SLOTS:
|
||||
void setProject(KdenliveDoc *document);
|
||||
@@ -41,4 +43,5 @@ private:
|
||||
NotesWidget *m_widget;
|
||||
QDockWidget *m_notesDock;
|
||||
QToolBar *m_tb;
|
||||
QAction *m_markDownEdit;
|
||||
};
|
||||
|
||||
@@ -1280,7 +1280,7 @@ void ProjectManager::setDocumentNotes(QString ¬es, QStringList deprecatedBinI
|
||||
notes = notes.replace(pattern, replacement);
|
||||
}
|
||||
}
|
||||
m_notesPlugin->widget()->setHtml(notes);
|
||||
m_notesPlugin->loadNotes(notes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1290,7 +1290,7 @@ QString ProjectManager::documentNotes() const
|
||||
if (text.isEmpty()) {
|
||||
return QString();
|
||||
}
|
||||
return m_notesPlugin->widget()->toHtml();
|
||||
return m_notesPlugin->widget()->toMarkdown();
|
||||
}
|
||||
|
||||
void ProjectManager::slotAddProjectNote()
|
||||
|
||||
Reference in New Issue
Block a user