nodes: revised text node
Clarifies text node's ability to parse HTML with Qt. Removes janky incomplete "rich text editing" functionality. I don't think this is the right approach.
This commit is contained in:
@@ -26,9 +26,9 @@ add_subdirectory(keyframeproperties)
|
|||||||
add_subdirectory(preferences)
|
add_subdirectory(preferences)
|
||||||
add_subdirectory(progress)
|
add_subdirectory(progress)
|
||||||
add_subdirectory(rendercancel)
|
add_subdirectory(rendercancel)
|
||||||
add_subdirectory(richtext)
|
|
||||||
add_subdirectory(sequence)
|
add_subdirectory(sequence)
|
||||||
add_subdirectory(task)
|
add_subdirectory(task)
|
||||||
|
add_subdirectory(text)
|
||||||
|
|
||||||
set(OLIVE_SOURCES
|
set(OLIVE_SOURCES
|
||||||
${OLIVE_SOURCES}
|
${OLIVE_SOURCES}
|
||||||
|
|||||||
@@ -1,339 +0,0 @@
|
|||||||
/***
|
|
||||||
|
|
||||||
Olive - Non-Linear Video Editor
|
|
||||||
Copyright (C) 2021 Olive Team
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
***/
|
|
||||||
|
|
||||||
#include "richtext.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QDialogButtonBox>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
#include "ui/icons/icons.h"
|
|
||||||
|
|
||||||
namespace olive {
|
|
||||||
|
|
||||||
RichTextDialog::RichTextDialog(QString start, QWidget* parent) :
|
|
||||||
QDialog(parent)
|
|
||||||
{
|
|
||||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
|
||||||
|
|
||||||
// Create toolbar
|
|
||||||
QHBoxLayout* toolbar_layout = new QHBoxLayout();
|
|
||||||
|
|
||||||
bold_btn_ = CreateToolbarButton(tr("B"), tr("Bold"), {QStringLiteral("b"), QStringLiteral("strong")});
|
|
||||||
toolbar_layout->addWidget(bold_btn_);
|
|
||||||
italic_btn_ = CreateToolbarButton(tr("I"), tr("Italic"), {QStringLiteral("i"), QStringLiteral("em")});
|
|
||||||
toolbar_layout->addWidget(italic_btn_);
|
|
||||||
underline_btn_ = CreateToolbarButton(tr("U"), tr("Underline"), {QStringLiteral("u")});
|
|
||||||
toolbar_layout->addWidget(underline_btn_);
|
|
||||||
strikeout_btn_ = CreateToolbarButton(tr("S"), tr("Strikethrough"), {QStringLiteral("strike")});
|
|
||||||
toolbar_layout->addWidget(strikeout_btn_);
|
|
||||||
font_combo_ = new QFontComboBox();
|
|
||||||
font_combo_->setToolTip(tr("Font Family"));
|
|
||||||
toolbar_layout->addWidget(font_combo_);
|
|
||||||
size_slider_ = new FloatSlider();
|
|
||||||
size_slider_->SetMinimum(0.1);
|
|
||||||
size_slider_->SetLadderElementCount(1);
|
|
||||||
size_slider_->setToolTip(tr("Font Size"));
|
|
||||||
toolbar_layout->addWidget(size_slider_);
|
|
||||||
|
|
||||||
toolbar_layout->addStretch();
|
|
||||||
|
|
||||||
left_align_btn_ = CreateToolbarButton(tr("L"), tr("Left Align"), {});
|
|
||||||
toolbar_layout->addWidget(left_align_btn_);
|
|
||||||
center_align_btn_ = CreateToolbarButton(tr("C"), tr("Center Align"), {});
|
|
||||||
toolbar_layout->addWidget(center_align_btn_);
|
|
||||||
right_align_btn_ = CreateToolbarButton(tr("R"), tr("Right Align"), {});
|
|
||||||
toolbar_layout->addWidget(right_align_btn_);
|
|
||||||
justify_align_btn_ = CreateToolbarButton(tr("J"), tr("Justify Align"), {});
|
|
||||||
toolbar_layout->addWidget(justify_align_btn_);
|
|
||||||
|
|
||||||
layout->addLayout(toolbar_layout);
|
|
||||||
|
|
||||||
// Create text edit widget
|
|
||||||
text_edit_ = new QTextEdit();
|
|
||||||
text_edit_->setWordWrapMode(QTextOption::NoWrap);
|
|
||||||
connect(text_edit_, &QTextEdit::cursorPositionChanged, this, &RichTextDialog::UpdateButtons);
|
|
||||||
start.replace(QStringLiteral("<br>"), QStringLiteral("\n"));
|
|
||||||
text_edit_->document()->setPlainText(start);
|
|
||||||
layout->addWidget(text_edit_);
|
|
||||||
|
|
||||||
// Create buttons
|
|
||||||
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
|
||||||
layout->addWidget(buttons);
|
|
||||||
connect(buttons, &QDialogButtonBox::accepted, this, &RichTextDialog::accept);
|
|
||||||
connect(buttons, &QDialogButtonBox::rejected, this, &RichTextDialog::reject);
|
|
||||||
|
|
||||||
// Connect font buttons
|
|
||||||
/*
|
|
||||||
connect(size_slider_, &FloatSlider::ValueChanged, text_edit_, &QTextEdit::setFontPointSize);
|
|
||||||
connect(left_align_btn_, &QPushButton::clicked, this, [this](){
|
|
||||||
text_edit_->setAlignment(Qt::AlignLeft);
|
|
||||||
UpdateButtons();
|
|
||||||
});
|
|
||||||
connect(center_align_btn_, &QPushButton::clicked, this, [this](){
|
|
||||||
text_edit_->setAlignment(Qt::AlignCenter);
|
|
||||||
UpdateButtons();
|
|
||||||
});
|
|
||||||
connect(right_align_btn_, &QPushButton::clicked, this, [this](){
|
|
||||||
text_edit_->setAlignment(Qt::AlignRight);
|
|
||||||
UpdateButtons();
|
|
||||||
});
|
|
||||||
connect(justify_align_btn_, &QPushButton::clicked, this, [this](){
|
|
||||||
text_edit_->setAlignment(Qt::AlignJustify);
|
|
||||||
UpdateButtons();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
connect(font_combo_, &QFontComboBox::currentTextChanged, this, [this](const QString& s){
|
|
||||||
text_edit_->setFontFamily(s);
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
QPushButton *RichTextDialog::CreateToolbarButton(const QString& label, const QString& tooltip, const QStringList &tags)
|
|
||||||
{
|
|
||||||
QPushButton* btn = new QPushButton(label);
|
|
||||||
btn->setCheckable(true);
|
|
||||||
btn->setToolTip(tooltip);
|
|
||||||
btn->setFixedWidth(btn->sizeHint().height());
|
|
||||||
|
|
||||||
if (!tags.isEmpty()) {
|
|
||||||
btn->setProperty("tag", tags);
|
|
||||||
connect(btn, &QPushButton::clicked, this, &RichTextDialog::TagButtonToggled);
|
|
||||||
}
|
|
||||||
|
|
||||||
return btn;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SnapPositionOutsideTags(const QString& text, int pos)
|
|
||||||
{
|
|
||||||
// Look for closest opening bracket before position
|
|
||||||
int opening_bracket_pos = text.lastIndexOf('<', pos - text.size() -1);
|
|
||||||
|
|
||||||
// Look for closest closing bracket before position
|
|
||||||
int closing_bracket_pos = text.indexOf('>', opening_bracket_pos);
|
|
||||||
|
|
||||||
if (opening_bracket_pos > -1 && closing_bracket_pos >= pos) {
|
|
||||||
// Must be inside an angle bracket, snap to closest position outside of bracket
|
|
||||||
closing_bracket_pos++;
|
|
||||||
|
|
||||||
if (pos - opening_bracket_pos < closing_bracket_pos - pos) {
|
|
||||||
// Closer to opening bracket pos
|
|
||||||
return opening_bracket_pos;
|
|
||||||
} else {
|
|
||||||
return closing_bracket_pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RichTextDialog::SetTags(const QStringList &t, bool enabled)
|
|
||||||
{
|
|
||||||
QString s = text_edit_->toPlainText();
|
|
||||||
|
|
||||||
int selection_start, selection_end;
|
|
||||||
|
|
||||||
{
|
|
||||||
QTextCursor c = text_edit_->textCursor();
|
|
||||||
|
|
||||||
if (c.hasSelection()) {
|
|
||||||
selection_start = SnapPositionOutsideTags(s, c.selectionStart());
|
|
||||||
selection_end = SnapPositionOutsideTags(s, c.selectionEnd());
|
|
||||||
|
|
||||||
c.clearSelection();
|
|
||||||
c.setPosition(selection_start, QTextCursor::MoveAnchor);
|
|
||||||
c.setPosition(selection_end, QTextCursor::KeepAnchor);
|
|
||||||
} else {
|
|
||||||
selection_start = SnapPositionOutsideTags(s, c.position());
|
|
||||||
selection_end = selection_start;
|
|
||||||
c.setPosition(selection_start, QTextCursor::MoveAnchor);
|
|
||||||
}
|
|
||||||
|
|
||||||
text_edit_->setTextCursor(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString open_tag = CreateOpeningTag(t.first());
|
|
||||||
QString close_tag = CreateClosingTag(t.first());
|
|
||||||
|
|
||||||
// Insert tags
|
|
||||||
QString new_text;
|
|
||||||
|
|
||||||
if (!enabled) {
|
|
||||||
std::swap(open_tag, close_tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool open_tag_cancels_out = !QString::compare(s.mid(selection_start - close_tag.size(), close_tag.size()), close_tag, Qt::CaseInsensitive);
|
|
||||||
bool close_tag_cancels_out = !QString::compare(s.mid(selection_end, open_tag.size()), open_tag, Qt::CaseInsensitive);
|
|
||||||
|
|
||||||
QString selected_text = text_edit_->textCursor().selectedText();
|
|
||||||
|
|
||||||
if (open_tag_cancels_out && close_tag_cancels_out) {
|
|
||||||
|
|
||||||
// Both tags cancel each other out, simply remove
|
|
||||||
selection_start -= close_tag.size();
|
|
||||||
|
|
||||||
QTextCursor c = text_edit_->textCursor();
|
|
||||||
c.clearSelection();
|
|
||||||
c.setPosition(selection_start, QTextCursor::MoveAnchor);
|
|
||||||
c.setPosition(selection_end + open_tag.size(), QTextCursor::KeepAnchor);
|
|
||||||
text_edit_->setTextCursor(c);
|
|
||||||
|
|
||||||
selection_end -= close_tag.size();
|
|
||||||
|
|
||||||
new_text = selected_text;
|
|
||||||
|
|
||||||
} else if (open_tag_cancels_out) {
|
|
||||||
|
|
||||||
// Open tag cancels out, shift close tag rather than inserting new tags
|
|
||||||
selection_start -= close_tag.size();
|
|
||||||
|
|
||||||
QTextCursor c = text_edit_->textCursor();
|
|
||||||
c.clearSelection();
|
|
||||||
c.setPosition(selection_start, QTextCursor::MoveAnchor);
|
|
||||||
c.setPosition(selection_end, QTextCursor::KeepAnchor);
|
|
||||||
text_edit_->setTextCursor(c);
|
|
||||||
|
|
||||||
selection_end -= close_tag.size();
|
|
||||||
|
|
||||||
new_text = selected_text;
|
|
||||||
new_text.append(close_tag);
|
|
||||||
|
|
||||||
} else if (close_tag_cancels_out) {
|
|
||||||
|
|
||||||
// Close tag cancels out, shift open tag rather than inserting new tags
|
|
||||||
selection_end += open_tag.size();
|
|
||||||
|
|
||||||
QTextCursor c = text_edit_->textCursor();
|
|
||||||
c.clearSelection();
|
|
||||||
c.setPosition(selection_start, QTextCursor::MoveAnchor);
|
|
||||||
c.setPosition(selection_end, QTextCursor::KeepAnchor);
|
|
||||||
text_edit_->setTextCursor(c);
|
|
||||||
|
|
||||||
selection_start += open_tag.size();
|
|
||||||
|
|
||||||
new_text = open_tag;
|
|
||||||
new_text.append(selected_text);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Nothing is cancelled out, simply insert tags
|
|
||||||
new_text = QStringLiteral("%1%2%3").arg(open_tag,
|
|
||||||
selected_text,
|
|
||||||
close_tag);
|
|
||||||
|
|
||||||
selection_start += open_tag.size();
|
|
||||||
selection_end += open_tag.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
text_edit_->insertPlainText(new_text);
|
|
||||||
|
|
||||||
text_edit_->setFocus();
|
|
||||||
|
|
||||||
{
|
|
||||||
// Re-select text
|
|
||||||
QTextCursor c = text_edit_->textCursor();
|
|
||||||
|
|
||||||
c.clearSelection();
|
|
||||||
c.setPosition(selection_start, QTextCursor::MoveAnchor);
|
|
||||||
c.setPosition(selection_end, QTextCursor::KeepAnchor);
|
|
||||||
text_edit_->setTextCursor(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString RichTextDialog::CreateOpeningTag(const QString &s)
|
|
||||||
{
|
|
||||||
return QStringLiteral("<%1>").arg(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString RichTextDialog::CreateClosingTag(const QString &s)
|
|
||||||
{
|
|
||||||
return QStringLiteral("</%1>").arg(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RichTextDialog::UpdateTagButton(QPushButton *btn,
|
|
||||||
const QString &text,
|
|
||||||
int cursor_pos)
|
|
||||||
{
|
|
||||||
QStringList tags = btn->property("tag").toStringList();
|
|
||||||
foreach (const QString& t, tags) {
|
|
||||||
QString opening = CreateOpeningTag(t);
|
|
||||||
QString closing = CreateClosingTag(t);
|
|
||||||
|
|
||||||
int opening_index = text.lastIndexOf(opening,
|
|
||||||
cursor_pos - text.size() - 1,
|
|
||||||
Qt::CaseInsensitive);
|
|
||||||
int closing_index = text.indexOf(closing,
|
|
||||||
opening_index,
|
|
||||||
Qt::CaseInsensitive);
|
|
||||||
|
|
||||||
if (opening_index > -1 && closing_index + closing.size() > cursor_pos) {
|
|
||||||
btn->setChecked(true);
|
|
||||||
btn->setProperty("foundtag", t);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
btn->setChecked(false);
|
|
||||||
btn->setProperty("foundtag", QVariant());
|
|
||||||
}
|
|
||||||
|
|
||||||
void RichTextDialog::TagButtonToggled(bool checked)
|
|
||||||
{
|
|
||||||
QPushButton* src = static_cast<QPushButton*>(sender());
|
|
||||||
QStringList tags;
|
|
||||||
|
|
||||||
if (src->property("foundtag").isNull()) {
|
|
||||||
tags = src->property("tag").toStringList();
|
|
||||||
} else {
|
|
||||||
tags = QStringList({src->property("foundtag").toString()});
|
|
||||||
}
|
|
||||||
|
|
||||||
SetTags(tags, checked);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RichTextDialog::UpdateButtons()
|
|
||||||
{
|
|
||||||
QString text = text_edit_->toPlainText();
|
|
||||||
int cursor_pos = text_edit_->textCursor().position();
|
|
||||||
|
|
||||||
UpdateTagButton(bold_btn_, text, cursor_pos);
|
|
||||||
UpdateTagButton(italic_btn_, text, cursor_pos);
|
|
||||||
UpdateTagButton(underline_btn_, text, cursor_pos);
|
|
||||||
UpdateTagButton(strikeout_btn_, text, cursor_pos);
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
// Update font family
|
|
||||||
font_combo_->blockSignals(true);
|
|
||||||
font_combo_->setCurrentFont(text_edit_->currentFont().family());
|
|
||||||
font_combo_->blockSignals(false);
|
|
||||||
|
|
||||||
size_slider_->SetValue(text_edit_->fontPointSize());
|
|
||||||
|
|
||||||
left_align_btn_->setChecked(text_edit_->alignment() == Qt::AlignLeft);
|
|
||||||
center_align_btn_->setChecked(text_edit_->alignment() == Qt::AlignCenter);
|
|
||||||
right_align_btn_->setChecked(text_edit_->alignment() == Qt::AlignRight);
|
|
||||||
justify_align_btn_->setChecked(text_edit_->alignment() == Qt::AlignJustify);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
/***
|
|
||||||
|
|
||||||
Olive - Non-Linear Video Editor
|
|
||||||
Copyright (C) 2021 Olive Team
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
***/
|
|
||||||
|
|
||||||
#ifndef RICHTEXTDIALOG_H
|
|
||||||
#define RICHTEXTDIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QFontComboBox>
|
|
||||||
#include <QTextEdit>
|
|
||||||
|
|
||||||
#include "common/define.h"
|
|
||||||
#include "widget/slider/floatslider.h"
|
|
||||||
|
|
||||||
namespace olive {
|
|
||||||
|
|
||||||
class RichTextDialog : public QDialog
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
RichTextDialog(QString start, QWidget* parent = nullptr);
|
|
||||||
|
|
||||||
QString text() const
|
|
||||||
{
|
|
||||||
QString s = text_edit_->document()->toPlainText();
|
|
||||||
|
|
||||||
// Convert linebreaks
|
|
||||||
s.replace('\n', QStringLiteral("<br>"));
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QPushButton* CreateToolbarButton(const QString &label,
|
|
||||||
const QString &tooltip,
|
|
||||||
const QStringList& tags);
|
|
||||||
|
|
||||||
void SetTags(const QStringList& t, bool enabled);
|
|
||||||
|
|
||||||
static QString CreateOpeningTag(const QString& s);
|
|
||||||
static QString CreateClosingTag(const QString& s);
|
|
||||||
|
|
||||||
static void UpdateTagButton(QPushButton* btn,
|
|
||||||
const QString &text,
|
|
||||||
int cursor_pos);
|
|
||||||
|
|
||||||
QFontDatabase font_db_;
|
|
||||||
|
|
||||||
QTextEdit* text_edit_;
|
|
||||||
|
|
||||||
QPushButton* bold_btn_;
|
|
||||||
QPushButton* italic_btn_;
|
|
||||||
QPushButton* underline_btn_;
|
|
||||||
QPushButton* strikeout_btn_;
|
|
||||||
QFontComboBox* font_combo_;
|
|
||||||
FloatSlider* size_slider_;
|
|
||||||
QPushButton* left_align_btn_;
|
|
||||||
QPushButton* center_align_btn_;
|
|
||||||
QPushButton* right_align_btn_;
|
|
||||||
QPushButton* justify_align_btn_;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void TagButtonToggled(bool checked);
|
|
||||||
|
|
||||||
void UpdateButtons();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // RICHTEXTDIALOG_H
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
set(OLIVE_SOURCES
|
set(OLIVE_SOURCES
|
||||||
${OLIVE_SOURCES}
|
${OLIVE_SOURCES}
|
||||||
dialog/richtext/richtext.h
|
dialog/text/text.h
|
||||||
dialog/richtext/richtext.cpp
|
dialog/text/text.cpp
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/***
|
||||||
|
|
||||||
|
Olive - Non-Linear Video Editor
|
||||||
|
Copyright (C) 2021 Olive Team
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***/
|
||||||
|
|
||||||
|
#include "text.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include "ui/icons/icons.h"
|
||||||
|
|
||||||
|
namespace olive {
|
||||||
|
|
||||||
|
TextDialog::TextDialog(const QString &start, QWidget* parent) :
|
||||||
|
QDialog(parent)
|
||||||
|
{
|
||||||
|
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
// Create text edit widget
|
||||||
|
text_edit_ = new QPlainTextEdit();
|
||||||
|
text_edit_->document()->setPlainText(start);
|
||||||
|
layout->addWidget(text_edit_);
|
||||||
|
|
||||||
|
// Create buttons
|
||||||
|
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||||
|
layout->addWidget(buttons);
|
||||||
|
connect(buttons, &QDialogButtonBox::accepted, this, &TextDialog::accept);
|
||||||
|
connect(buttons, &QDialogButtonBox::rejected, this, &TextDialog::reject);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/***
|
||||||
|
|
||||||
|
Olive - Non-Linear Video Editor
|
||||||
|
Copyright (C) 2021 Olive Team
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***/
|
||||||
|
|
||||||
|
#ifndef RICHTEXTDIALOG_H
|
||||||
|
#define RICHTEXTDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QFontComboBox>
|
||||||
|
#include <QPlainTextEdit>
|
||||||
|
|
||||||
|
#include "common/define.h"
|
||||||
|
#include "widget/slider/floatslider.h"
|
||||||
|
|
||||||
|
namespace olive {
|
||||||
|
|
||||||
|
class TextDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
TextDialog(const QString &start, QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
QString text() const
|
||||||
|
{
|
||||||
|
return text_edit_->toPlainText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPlainTextEdit* text_edit_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // RICHTEXTDIALOG_H
|
||||||
@@ -32,6 +32,7 @@ enum TextVerticalAlign {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const QString TextGenerator::kTextInput = QStringLiteral("text_in");
|
const QString TextGenerator::kTextInput = QStringLiteral("text_in");
|
||||||
|
const QString TextGenerator::kHtmlInput = QStringLiteral("html_in");
|
||||||
const QString TextGenerator::kColorInput = QStringLiteral("color_in");
|
const QString TextGenerator::kColorInput = QStringLiteral("color_in");
|
||||||
const QString TextGenerator::kVAlignInput = QStringLiteral("valign_in");
|
const QString TextGenerator::kVAlignInput = QStringLiteral("valign_in");
|
||||||
const QString TextGenerator::kFontInput = QStringLiteral("font_in");
|
const QString TextGenerator::kFontInput = QStringLiteral("font_in");
|
||||||
@@ -41,6 +42,8 @@ TextGenerator::TextGenerator()
|
|||||||
{
|
{
|
||||||
AddInput(kTextInput, NodeValue::kText, tr("Sample Text"));
|
AddInput(kTextInput, NodeValue::kText, tr("Sample Text"));
|
||||||
|
|
||||||
|
AddInput(kHtmlInput, NodeValue::kBoolean, false);
|
||||||
|
|
||||||
AddInput(kColorInput, NodeValue::kColor, QVariant::fromValue(Color(1.0f, 1.0f, 1.0)));
|
AddInput(kColorInput, NodeValue::kColor, QVariant::fromValue(Color(1.0f, 1.0f, 1.0)));
|
||||||
|
|
||||||
AddInput(kVAlignInput, NodeValue::kCombo, 1);
|
AddInput(kVAlignInput, NodeValue::kCombo, 1);
|
||||||
@@ -78,6 +81,7 @@ QString TextGenerator::Description() const
|
|||||||
void TextGenerator::Retranslate()
|
void TextGenerator::Retranslate()
|
||||||
{
|
{
|
||||||
SetInputName(kTextInput, tr("Text"));
|
SetInputName(kTextInput, tr("Text"));
|
||||||
|
SetInputName(kHtmlInput, tr("Enable HTML"));
|
||||||
SetInputName(kFontInput, tr("Font"));
|
SetInputName(kFontInput, tr("Font"));
|
||||||
SetInputName(kFontSizeInput, tr("Font Size"));
|
SetInputName(kFontSizeInput, tr("Font Size"));
|
||||||
SetInputName(kColorInput, tr("Color"));
|
SetInputName(kColorInput, tr("Color"));
|
||||||
@@ -91,6 +95,7 @@ NodeValueTable TextGenerator::Value(const QString &output, NodeValueDatabase &va
|
|||||||
|
|
||||||
GenerateJob job;
|
GenerateJob job;
|
||||||
job.InsertValue(this, kTextInput, value);
|
job.InsertValue(this, kTextInput, value);
|
||||||
|
job.InsertValue(this, kHtmlInput, value);
|
||||||
job.InsertValue(this, kColorInput, value);
|
job.InsertValue(this, kColorInput, value);
|
||||||
job.InsertValue(this, kVAlignInput, value);
|
job.InsertValue(this, kVAlignInput, value);
|
||||||
job.InsertValue(this, kFontInput, value);
|
job.InsertValue(this, kFontInput, value);
|
||||||
@@ -126,7 +131,13 @@ void TextGenerator::GenerateFrame(FramePtr frame, const GenerateJob& job) const
|
|||||||
// Center by default
|
// Center by default
|
||||||
text_doc.setDefaultTextOption(QTextOption(Qt::AlignCenter));
|
text_doc.setDefaultTextOption(QTextOption(Qt::AlignCenter));
|
||||||
|
|
||||||
text_doc.setHtml(job.GetValue(kTextInput).data().toString());
|
QString html = job.GetValue(kTextInput).data().toString();
|
||||||
|
if (job.GetValue(kHtmlInput).data().toBool()) {
|
||||||
|
html.replace('\n', QStringLiteral("<br>"));
|
||||||
|
text_doc.setHtml(html);
|
||||||
|
} else {
|
||||||
|
text_doc.setPlainText(html);
|
||||||
|
}
|
||||||
|
|
||||||
// Align to 80% width because that's considered the "title safe" area
|
// Align to 80% width because that's considered the "title safe" area
|
||||||
int tenth_of_width = frame->video_params().width() / 10;
|
int tenth_of_width = frame->video_params().width() / 10;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public:
|
|||||||
virtual void GenerateFrame(FramePtr frame, const GenerateJob &job) const override;
|
virtual void GenerateFrame(FramePtr frame, const GenerateJob &job) const override;
|
||||||
|
|
||||||
static const QString kTextInput;
|
static const QString kTextInput;
|
||||||
|
static const QString kHtmlInput;
|
||||||
static const QString kColorInput;
|
static const QString kColorInput;
|
||||||
static const QString kVAlignInput;
|
static const QString kVAlignInput;
|
||||||
static const QString kFontInput;
|
static const QString kFontInput;
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ set(OLIVE_SOURCES
|
|||||||
widget/nodeparamview/nodeparamviewitem.cpp
|
widget/nodeparamview/nodeparamviewitem.cpp
|
||||||
widget/nodeparamview/nodeparamviewkeyframecontrol.h
|
widget/nodeparamview/nodeparamviewkeyframecontrol.h
|
||||||
widget/nodeparamview/nodeparamviewkeyframecontrol.cpp
|
widget/nodeparamview/nodeparamviewkeyframecontrol.cpp
|
||||||
widget/nodeparamview/nodeparamviewrichtext.h
|
widget/nodeparamview/nodeparamviewtextedit.h
|
||||||
widget/nodeparamview/nodeparamviewrichtext.cpp
|
widget/nodeparamview/nodeparamviewtextedit.cpp
|
||||||
widget/nodeparamview/nodeparamviewundo.h
|
widget/nodeparamview/nodeparamviewundo.h
|
||||||
widget/nodeparamview/nodeparamviewundo.cpp
|
widget/nodeparamview/nodeparamviewundo.cpp
|
||||||
widget/nodeparamview/nodeparamviewwidgetbridge.h
|
widget/nodeparamview/nodeparamviewwidgetbridge.h
|
||||||
|
|||||||
+10
-10
@@ -18,46 +18,46 @@
|
|||||||
|
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include "nodeparamviewrichtext.h"
|
#include "nodeparamviewtextedit.h"
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
||||||
#include "dialog/richtext/richtext.h"
|
#include "dialog/text/text.h"
|
||||||
#include "ui/icons/icons.h"
|
#include "ui/icons/icons.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
NodeParamViewRichText::NodeParamViewRichText(QWidget *parent) :
|
NodeParamViewTextEdit::NodeParamViewTextEdit(QWidget *parent) :
|
||||||
QWidget(parent)
|
QWidget(parent)
|
||||||
{
|
{
|
||||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||||
layout->setMargin(0);
|
layout->setMargin(0);
|
||||||
|
|
||||||
line_edit_ = new QTextEdit();
|
line_edit_ = new QPlainTextEdit();
|
||||||
line_edit_->setUndoRedoEnabled(true);
|
line_edit_->setUndoRedoEnabled(true);
|
||||||
connect(line_edit_, &QTextEdit::textChanged, this, &NodeParamViewRichText::InnerWidgetTextChanged);
|
connect(line_edit_, &QPlainTextEdit::textChanged, this, &NodeParamViewTextEdit::InnerWidgetTextChanged);
|
||||||
layout->addWidget(line_edit_);
|
layout->addWidget(line_edit_);
|
||||||
|
|
||||||
QPushButton* edit_btn = new QPushButton();
|
QPushButton* edit_btn = new QPushButton();
|
||||||
edit_btn->setIcon(icon::ToolEdit);
|
edit_btn->setIcon(icon::ToolEdit);
|
||||||
edit_btn->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
|
edit_btn->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
|
||||||
layout->addWidget(edit_btn);
|
layout->addWidget(edit_btn);
|
||||||
connect(edit_btn, &QPushButton::clicked, this, &NodeParamViewRichText::ShowRichTextDialog);
|
connect(edit_btn, &QPushButton::clicked, this, &NodeParamViewTextEdit::ShowTextDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeParamViewRichText::ShowRichTextDialog()
|
void NodeParamViewTextEdit::ShowTextDialog()
|
||||||
{
|
{
|
||||||
RichTextDialog d(this->text(), this);
|
TextDialog d(this->text(), this);
|
||||||
if (d.exec() == QDialog::Accepted) {
|
if (d.exec() == QDialog::Accepted) {
|
||||||
QString s = d.text();
|
QString s = d.text();
|
||||||
|
|
||||||
line_edit_->setText(s);
|
line_edit_->setPlainText(s);
|
||||||
emit textEdited(s);
|
emit textEdited(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeParamViewRichText::InnerWidgetTextChanged()
|
void NodeParamViewTextEdit::InnerWidgetTextChanged()
|
||||||
{
|
{
|
||||||
emit textEdited(this->text());
|
emit textEdited(this->text());
|
||||||
}
|
}
|
||||||
+11
-11
@@ -18,32 +18,32 @@
|
|||||||
|
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#ifndef NODEPARAMVIEWRICHTEXT_H
|
#ifndef NODEPARAMVIEWTEXTEDIT_H
|
||||||
#define NODEPARAMVIEWRICHTEXT_H
|
#define NODEPARAMVIEWTEXTEDIT_H
|
||||||
|
|
||||||
#include <QTextEdit>
|
#include <QPlainTextEdit>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "common/define.h"
|
#include "common/define.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
class NodeParamViewRichText : public QWidget
|
class NodeParamViewTextEdit : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
NodeParamViewRichText(QWidget* parent = nullptr);
|
NodeParamViewTextEdit(QWidget* parent = nullptr);
|
||||||
|
|
||||||
QString text() const
|
QString text() const
|
||||||
{
|
{
|
||||||
return line_edit_->toPlainText().replace('\n', QStringLiteral("<br>"));
|
return line_edit_->toPlainText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setText(QString s)
|
void setText(const QString &s)
|
||||||
{
|
{
|
||||||
line_edit_->blockSignals(true);
|
line_edit_->blockSignals(true);
|
||||||
line_edit_->setPlainText(s.replace(QStringLiteral("<br>"), QStringLiteral("\n")));
|
line_edit_->setPlainText(s);
|
||||||
line_edit_->blockSignals(false);
|
line_edit_->blockSignals(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,10 +65,10 @@ signals:
|
|||||||
void textEdited(const QString &);
|
void textEdited(const QString &);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTextEdit* line_edit_;
|
QPlainTextEdit* line_edit_;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ShowRichTextDialog();
|
void ShowTextDialog();
|
||||||
|
|
||||||
void InnerWidgetTextChanged();
|
void InnerWidgetTextChanged();
|
||||||
|
|
||||||
@@ -76,4 +76,4 @@ private slots:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NODEPARAMVIEWRICHTEXT_H
|
#endif // NODEPARAMVIEWTEXTEDIT_H
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
#include "node/node.h"
|
#include "node/node.h"
|
||||||
#include "node/project/sequence/sequence.h"
|
#include "node/project/sequence/sequence.h"
|
||||||
#include "nodeparamviewarraywidget.h"
|
#include "nodeparamviewarraywidget.h"
|
||||||
#include "nodeparamviewrichtext.h"
|
#include "nodeparamviewtextedit.h"
|
||||||
#include "nodeparamviewundo.h"
|
#include "nodeparamviewundo.h"
|
||||||
#include "undo/undostack.h"
|
#include "undo/undostack.h"
|
||||||
#include "widget/colorbutton/colorbutton.h"
|
#include "widget/colorbutton/colorbutton.h"
|
||||||
@@ -143,9 +143,9 @@ void NodeParamViewWidgetBridge::CreateWidgets()
|
|||||||
}
|
}
|
||||||
case NodeValue::kText:
|
case NodeValue::kText:
|
||||||
{
|
{
|
||||||
NodeParamViewRichText* line_edit = new NodeParamViewRichText();
|
NodeParamViewTextEdit* line_edit = new NodeParamViewTextEdit();
|
||||||
widgets_.append(line_edit);
|
widgets_.append(line_edit);
|
||||||
connect(line_edit, &NodeParamViewRichText::textEdited, this, &NodeParamViewWidgetBridge::WidgetCallback);
|
connect(line_edit, &NodeParamViewTextEdit::textEdited, this, &NodeParamViewWidgetBridge::WidgetCallback);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeValue::kBoolean:
|
case NodeValue::kBoolean:
|
||||||
@@ -358,7 +358,7 @@ void NodeParamViewWidgetBridge::WidgetCallback()
|
|||||||
case NodeValue::kText:
|
case NodeValue::kText:
|
||||||
{
|
{
|
||||||
// Sender is a NodeParamViewRichText
|
// Sender is a NodeParamViewRichText
|
||||||
SetInputValue(static_cast<NodeParamViewRichText*>(sender())->text(), 0);
|
SetInputValue(static_cast<NodeParamViewTextEdit*>(sender())->text(), 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeValue::kBoolean:
|
case NodeValue::kBoolean:
|
||||||
@@ -498,7 +498,7 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues()
|
|||||||
}
|
}
|
||||||
case NodeValue::kText:
|
case NodeValue::kText:
|
||||||
{
|
{
|
||||||
NodeParamViewRichText* e = static_cast<NodeParamViewRichText*>(widgets_.first());
|
NodeParamViewTextEdit* e = static_cast<NodeParamViewTextEdit*>(widgets_.first());
|
||||||
e->setTextPreservingCursor(input_.GetValueAtTime(node_time).toString());
|
e->setTextPreservingCursor(input_.GetValueAtTime(node_time).toString());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user