From 9fc542e6886733c22a7bcae53837bd0c72a35dfc Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 14 Mar 2019 22:56:23 +1100 Subject: [PATCH] further progress on rich text effect --- dialogs/texteditdialog.cpp | 153 ++++++++++++++++++++++++++-- dialogs/texteditdialog.h | 15 +++ effects/internal/richtexteffect.cpp | 47 ++++++++- effects/internal/richtexteffect.h | 4 + icons/align-center.svg | 3 + icons/align-left.svg | 3 + icons/align-right.svg | 3 + icons/bold.svg | 3 + icons/icons.qrc | 5 + icons/italic.svg | 2 +- icons/justify-center.svg | 3 + icons/underline.svg | 2 +- ui/keyframenavigator.cpp | 2 + ui/texteditex.cpp | 2 +- 14 files changed, 232 insertions(+), 15 deletions(-) create mode 100644 icons/align-center.svg create mode 100644 icons/align-left.svg create mode 100644 icons/align-right.svg create mode 100644 icons/bold.svg create mode 100644 icons/justify-center.svg diff --git a/dialogs/texteditdialog.cpp b/dialogs/texteditdialog.cpp index 69cd149f4..00e338c3a 100644 --- a/dialogs/texteditdialog.cpp +++ b/dialogs/texteditdialog.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "ui/icons.h" @@ -35,9 +36,23 @@ TextEditDialog::TextEditDialog(QWidget *parent, const QString &s, bool rich_text QVBoxLayout* layout = new QVBoxLayout(this); + // Create central text editor object + textEdit = new QTextEdit(this); + textEdit->setUndoRedoEnabled(true); + + // Upper toolbar if (rich_text) { QHBoxLayout* toolbar = new QHBoxLayout(); + // Bold Button + /* + bold_button = new QPushButton(); + bold_button->setIcon(QIcon(":/icons/bold.svg")); + bold_button->setCheckable(true); + connect(bold_button, SIGNAL(clicked(bool)), this, SLOT(SetBold(bool))); + toolbar->addWidget(bold_button); + */ + // Italic Button italic_button = new QPushButton(); italic_button->setIcon(QIcon(":/icons/italic.svg")); @@ -49,36 +64,109 @@ TextEditDialog::TextEditDialog(QWidget *parent, const QString &s, bool rich_text underline_button = new QPushButton(); underline_button->setIcon(QIcon(":/icons/underline.svg")); underline_button->setCheckable(true); + connect(underline_button, SIGNAL(clicked(bool)), textEdit, SLOT(setFontUnderline(bool))); toolbar->addWidget(underline_button); // Font Name font_list = new QFontComboBox(); - connect(font_list, SIGNAL(setCurrentFont(const QFont&)), textEdit, SLOT(setCurrentFont(const QFont&))); + connect(font_list, SIGNAL(currentIndexChanged(const QString&)), textEdit, SLOT(setFontFamily(const QString&))); toolbar->addWidget(font_list); + // Font Weight + font_weight = new QComboBox(); + font_weight->addItem(tr("Thin"), QFont::Thin); + font_weight->addItem(tr("Extra Light"), QFont::ExtraLight); + font_weight->addItem(tr("Light"), QFont::Light); + font_weight->addItem(tr("Normal"), QFont::Normal); + font_weight->addItem(tr("Medium"), QFont::Medium); + font_weight->addItem(tr("Demi Bold"), QFont::DemiBold); + font_weight->addItem(tr("Bold"), QFont::Bold); + font_weight->addItem(tr("Extra Bold"), QFont::ExtraBold); + font_weight->addItem(tr("Black"), QFont::Black); + connect(font_weight, SIGNAL(currentIndexChanged(int)), this, SLOT(SetFontWeight(int))); + toolbar->addWidget(font_weight); + + // Font Size + font_size = new LabelSlider(); + connect(font_size, SIGNAL(valueChanged(double)), textEdit, SLOT(setFontPointSize(qreal))); + toolbar->addWidget(font_size); + + // Font Color + font_color = new ColorButton(); + connect(font_color, SIGNAL(color_changed(const QColor&)), textEdit, SLOT(setTextColor(const QColor &))); + toolbar->addWidget(font_color); toolbar->addStretch(); + // Left Align + left_align_button = new QPushButton(); + left_align_button->setIcon(QIcon(":/icons/align-left.svg")); + left_align_button->setCheckable(true); + left_align_button->setProperty("a", Qt::AlignLeft); + connect(left_align_button, SIGNAL(clicked(bool)), this, SLOT(SetAlignmentFromProperty())); + toolbar->addWidget(left_align_button); + + // Center Align + center_align_button = new QPushButton(); + center_align_button->setIcon(QIcon(":/icons/align-center.svg")); + center_align_button->setCheckable(true); + center_align_button->setProperty("a", Qt::AlignCenter); + connect(center_align_button, SIGNAL(clicked(bool)), this, SLOT(SetAlignmentFromProperty())); + toolbar->addWidget(center_align_button); + + // Right Align + right_align_button = new QPushButton(); + right_align_button->setIcon(QIcon(":/icons/align-right.svg")); + right_align_button->setCheckable(true); + right_align_button->setProperty("a", Qt::AlignRight); + connect(right_align_button, SIGNAL(clicked(bool)), this, SLOT(SetAlignmentFromProperty())); + toolbar->addWidget(right_align_button); + + // Justify Align + justify_align_button = new QPushButton(); + justify_align_button->setIcon(QIcon(":/icons/justify-center.svg")); + justify_align_button->setCheckable(true); + justify_align_button->setProperty("a", Qt::AlignJustify); + connect(justify_align_button, SIGNAL(clicked(bool)), this, SLOT(SetAlignmentFromProperty())); + toolbar->addWidget(justify_align_button); + layout->addLayout(toolbar); } - // Create central text editor object - textEdit = new QTextEdit(this); - textEdit->setUndoRedoEnabled(true); + layout->addWidget(textEdit); + // Lower toolbar + /* + if (rich_text) { + QHBoxLayout* lower_toolbar = new QHBoxLayout(); + + lower_toolbar->addWidget(new QLabel(tr("Letter Spacing:"))); + + letter_spacing = new LabelSlider(); + connect(letter_spacing, SIGNAL(valueChanged(double)), this, SLOT(SetLetterSpacing(qreal))); + lower_toolbar->addWidget(letter_spacing); + + lower_toolbar->addStretch(); + + layout->addLayout(lower_toolbar); + } + */ + + // Create dialog buttons at the bottom + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); + buttons->setCenterButtons(true); + layout->addWidget(buttons); + connect(buttons, SIGNAL(accepted()), this, SLOT(save())); + connect(buttons, SIGNAL(rejected()), this, SLOT(cancel())); + + connect(textEdit, SIGNAL(cursorPositionChanged()), this, SLOT(UpdateUIFromTextCursor())); if (rich_text_) { textEdit->setHtml(s); } else { textEdit->setPlainText(s); } - layout->addWidget(textEdit); - - // Create dialog buttons at the bottom - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); - layout->addWidget(buttons); - connect(buttons, SIGNAL(accepted()), this, SLOT(save())); - connect(buttons, SIGNAL(rejected()), this, SLOT(cancel())); + UpdateUIFromTextCursor(); } const QString& TextEditDialog::get_string() { @@ -94,9 +182,52 @@ void TextEditDialog::cancel() { reject(); } +void TextEditDialog::SetBold(bool bold) +{ + QFont f = textEdit->currentFont(); + f.setBold(bold); + textEdit->setCurrentFont(f); + UpdateUIFromTextCursor(); +} + +void TextEditDialog::SetFontWeight(int i) +{ + textEdit->setFontWeight(font_weight->itemData(i).toInt()); +} + +void TextEditDialog::SetLetterSpacing(qreal spacing) +{ + QFont f = textEdit->currentFont(); + f.setLetterSpacing(f.letterSpacingType(), spacing); + textEdit->setCurrentFont(f); +} + +void TextEditDialog::SetAlignmentFromProperty() +{ + textEdit->setAlignment(static_cast(sender()->property("a").toInt())); + UpdateUIFromTextCursor(); +} + void TextEditDialog::UpdateUIFromTextCursor() { italic_button->setChecked(textEdit->fontItalic()); underline_button->setChecked(textEdit->fontUnderline()); font_list->setCurrentText(textEdit->fontFamily()); + font_size->SetValue(textEdit->fontPointSize()); + font_color->set_color(textEdit->textColor()); + + for (int i=0;icount();i++) { + if (font_weight->itemData(i).toInt() == textEdit->fontWeight()) { + font_weight->blockSignals(true); + font_weight->setCurrentIndex(i); + font_weight->blockSignals(false); + break; + } + } + + Qt::Alignment align = textEdit->alignment(); + left_align_button->setChecked(align == Qt::AlignLeft); + center_align_button->setChecked(align == Qt::AlignCenter); + right_align_button->setChecked(align == Qt::AlignRight); + justify_align_button->setChecked(align == Qt::AlignJustify); } diff --git a/dialogs/texteditdialog.h b/dialogs/texteditdialog.h index 12f342b61..c2ced7d2e 100644 --- a/dialogs/texteditdialog.h +++ b/dialogs/texteditdialog.h @@ -25,6 +25,9 @@ #include #include +#include "ui/labelslider.h" +#include "ui/colorbutton.h" + class TextEditDialog : public QDialog { Q_OBJECT public: @@ -35,6 +38,11 @@ signals: private slots: void save(); void cancel(); + + void SetBold(bool bold); + void SetFontWeight(int i); + void SetLetterSpacing(qreal spacing); + void SetAlignmentFromProperty(); void UpdateUIFromTextCursor(); private: bool rich_text_; @@ -44,6 +52,13 @@ private: QPushButton* italic_button; QPushButton* underline_button; QFontComboBox* font_list; + QComboBox* font_weight; + LabelSlider* font_size; + ColorButton* font_color; + QPushButton* left_align_button; + QPushButton* center_align_button; + QPushButton* right_align_button; + QPushButton* justify_align_button; }; #endif // TEXTEDITDIALOG_H diff --git a/effects/internal/richtexteffect.cpp b/effects/internal/richtexteffect.cpp index 30a1f0fef..2ce6250a7 100644 --- a/effects/internal/richtexteffect.cpp +++ b/effects/internal/richtexteffect.cpp @@ -5,8 +5,32 @@ RichTextEffect::RichTextEffect(Clip *c, const EffectMeta *em) : Effect(c, em) { + SetFlags(Effect::SuperimposeFlag); + EffectRow* text_row = new EffectRow(this, tr("Text")); text_val = new StringField(text_row, "text"); + + EffectRow* padding_row = new EffectRow(this, tr("Padding")); + padding_field = new DoubleField(padding_row, "padding"); + padding_field->SetColumnSpan(2); + + EffectRow* position_row = new EffectRow(this, tr("Position")); + position_x = new DoubleField(position_row, "posx"); + position_y = new DoubleField(position_row, "posy"); + + EffectRow* vertical_align_row = new EffectRow(this, tr("Vertical Align:")); + vertical_align = new ComboField(vertical_align_row, "valign"); + vertical_align->AddItem(tr("Top"), Qt::AlignTop); + vertical_align->AddItem(tr("Center"), Qt::AlignCenter); + vertical_align->AddItem(tr("Bottom"), Qt::AlignBottom); + vertical_align->SetValueAt(0, Qt::AlignCenter); + + // Create default text + text_val->SetValueAt(0, "" + "" + "
Sample Text
" + "" + ""); } void RichTextEffect::redraw(double timecode) @@ -18,7 +42,28 @@ void RichTextEffect::redraw(double timecode) img.fill(Qt::transparent); + int padding = qRound(padding_field->GetDoubleAt(timecode)); + + width -= 2 * padding; + height -= 2 * padding; + QTextDocument td; td.setHtml(text_val->GetStringAt(timecode)); - td.drawContents(&p); + td.setTextWidth(width); + + int translate_x = qRound(position_x->GetDoubleAt(timecode) + padding); + int translate_y = qRound(position_y->GetDoubleAt(timecode) + padding); + + if (vertical_align->GetValueAt(timecode).toInt() == Qt::AlignCenter) { + translate_y += height / 2 - td.size().height() / 2; + } else if (vertical_align->GetValueAt(timecode).toInt() == Qt::AlignBottom) { + translate_y += height - td.size().height(); + } + + QRect clip_rect = img.rect(); + clip_rect.translate(-translate_x, -translate_y); + p.translate(translate_x, translate_y); + + + td.drawContents(&p, clip_rect); } diff --git a/effects/internal/richtexteffect.h b/effects/internal/richtexteffect.h index 37eb50530..b172af288 100644 --- a/effects/internal/richtexteffect.h +++ b/effects/internal/richtexteffect.h @@ -10,6 +10,10 @@ public: void redraw(double timecode); private: StringField* text_val; + DoubleField* padding_field; + DoubleField* position_x; + DoubleField* position_y; + ComboField* vertical_align; }; #endif // RICHTEXTEFFECT_H diff --git a/icons/align-center.svg b/icons/align-center.svg new file mode 100644 index 000000000..a75dfa755 --- /dev/null +++ b/icons/align-center.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/icons/align-left.svg b/icons/align-left.svg new file mode 100644 index 000000000..379dca5b5 --- /dev/null +++ b/icons/align-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/icons/align-right.svg b/icons/align-right.svg new file mode 100644 index 000000000..9d1759517 --- /dev/null +++ b/icons/align-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/icons/bold.svg b/icons/bold.svg new file mode 100644 index 000000000..a8643a00c --- /dev/null +++ b/icons/bold.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/icons/icons.qrc b/icons/icons.qrc index d6e6f33b8..8d00cf945 100644 --- a/icons/icons.qrc +++ b/icons/icons.qrc @@ -47,5 +47,10 @@ zoomout.svg italic.svg underline.svg + align-center.svg + align-left.svg + align-right.svg + justify-center.svg + bold.svg diff --git a/icons/italic.svg b/icons/italic.svg index facb40395..c0e5700dd 100644 --- a/icons/italic.svg +++ b/icons/italic.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/icons/justify-center.svg b/icons/justify-center.svg new file mode 100644 index 000000000..73a98ff9f --- /dev/null +++ b/icons/justify-center.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/icons/underline.svg b/icons/underline.svg index a6f80735b..f82f25cd4 100644 --- a/icons/underline.svg +++ b/icons/underline.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/ui/keyframenavigator.cpp b/ui/keyframenavigator.cpp index c27e07415..9a60dd4cc 100644 --- a/ui/keyframenavigator.cpp +++ b/ui/keyframenavigator.cpp @@ -29,6 +29,8 @@ #include "ui/icons.h" KeyframeNavigator::KeyframeNavigator(QWidget *parent, bool addLeftPad) : QWidget(parent) { + setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding); + key_controls = new QHBoxLayout(this); key_controls->setSpacing(0); key_controls->setMargin(0); diff --git a/ui/texteditex.cpp b/ui/texteditex.cpp index 49ee64a8c..1688042b1 100644 --- a/ui/texteditex.cpp +++ b/ui/texteditex.cpp @@ -103,5 +103,5 @@ void TextEditEx::open_text_edit() { void TextEditEx::queue_text_modified() { - emit textModified(toPlainText()); + emit textModified(enable_rich_text_ ? toHtml() : toPlainText()); }