initial upload
17
iconos.qrc
Normal file
@@ -0,0 +1,17 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>images/insertimage.png</file>
|
||||
<file>images/simplifyrichtext.png</file>
|
||||
<file>images/textanchor.png</file>
|
||||
<file>images/textbold.png</file>
|
||||
<file>images/textcenter.png</file>
|
||||
<file>images/textitalic.png</file>
|
||||
<file>images/textjustify.png</file>
|
||||
<file>images/textleft.png</file>
|
||||
<file>images/textright.png</file>
|
||||
<file>images/textsubscript.png</file>
|
||||
<file>images/textsuperscript.png</file>
|
||||
<file>images/textunder.png</file>
|
||||
<file>images/righttoleft.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
BIN
images/insertimage.png
Normal file
|
After Width: | Height: | Size: 885 B |
BIN
images/righttoleft.png
Normal file
|
After Width: | Height: | Size: 131 B |
BIN
images/simplifyrichtext.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
images/textanchor.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
images/textbold.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
images/textcenter.png
Normal file
|
After Width: | Height: | Size: 627 B |
BIN
images/textitalic.png
Normal file
|
After Width: | Height: | Size: 829 B |
BIN
images/textjustify.png
Normal file
|
After Width: | Height: | Size: 695 B |
BIN
images/textleft.png
Normal file
|
After Width: | Height: | Size: 673 B |
BIN
images/textright.png
Normal file
|
After Width: | Height: | Size: 677 B |
BIN
images/textsubscript.png
Normal file
|
After Width: | Height: | Size: 897 B |
BIN
images/textsuperscript.png
Normal file
|
After Width: | Height: | Size: 864 B |
BIN
images/textunder.png
Normal file
|
After Width: | Height: | Size: 971 B |
27
include/addlinkdialog.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef ADDLINKDIALOG_H
|
||||
#define ADDLINKDIALOG_H
|
||||
|
||||
#include "ui_addlinkdialog.h"
|
||||
#include "richtexteditor.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class AddLinkDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AddLinkDialog(RichTextEditor *editor, QWidget *parent = nullptr);
|
||||
~AddLinkDialog() override;
|
||||
|
||||
int showDialog();
|
||||
|
||||
public Q_SLOTS:
|
||||
void accept() override;
|
||||
|
||||
private:
|
||||
RichTextEditor *m_editor;
|
||||
QT_PREPEND_NAMESPACE(Ui)::AddLinkDialog *m_ui;
|
||||
};
|
||||
|
||||
#endif // ADDLINKDIALOG_H
|
||||
26
include/coloraction.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef COLORACTION_H
|
||||
#define COLORACTION_H
|
||||
|
||||
#include <QAction>
|
||||
#include <QColor>
|
||||
|
||||
class ColorAction : public QAction
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ColorAction(QObject *parent);
|
||||
|
||||
const QColor& color() const { return m_color; }
|
||||
void setColor(const QColor &color);
|
||||
|
||||
Q_SIGNALS:
|
||||
void colorChanged(const QColor &color);
|
||||
|
||||
private Q_SLOTS:
|
||||
void chooseColor();
|
||||
|
||||
private:
|
||||
QColor m_color;
|
||||
};
|
||||
#endif // COLORACTION_H
|
||||
43
include/htmlhighlighter.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef HTMLHIGHLIGHTER_H
|
||||
#define HTMLHIGHLIGHTER_H
|
||||
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QTextCharFormat>
|
||||
#include <QTextEdit>
|
||||
|
||||
/* HTML syntax highlighter based on Qt Quarterly example */
|
||||
class HtmlHighlighter : public QSyntaxHighlighter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Construct {
|
||||
Entity,
|
||||
Tag,
|
||||
Comment,
|
||||
Attribute,
|
||||
Value,
|
||||
LastConstruct = Value
|
||||
};
|
||||
|
||||
HtmlHighlighter(QTextEdit *textEdit);
|
||||
|
||||
void setFormatFor(Construct construct, const QTextCharFormat &format);
|
||||
|
||||
QTextCharFormat formatFor(Construct construct) const
|
||||
{ return m_formats[construct]; }
|
||||
|
||||
protected:
|
||||
enum State {
|
||||
NormalState = -1,
|
||||
InComment,
|
||||
InTag
|
||||
};
|
||||
|
||||
void highlightBlock(const QString &text) override;
|
||||
|
||||
private:
|
||||
QTextCharFormat m_formats[LastConstruct + 1];
|
||||
};
|
||||
|
||||
#endif // HTMLHIGHLIGHTER_H
|
||||
23
include/htmltextedit.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef HTMLTEXTEDIT_H
|
||||
#define HTMLTEXTEDIT_H
|
||||
|
||||
#include <QTextEdit>
|
||||
#include <QAction>
|
||||
#include <QContextMenuEvent>
|
||||
|
||||
class HtmlTextEdit : public QTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HtmlTextEdit(QWidget *parent = nullptr)
|
||||
: QTextEdit(parent)
|
||||
{}
|
||||
|
||||
void contextMenuEvent(QContextMenuEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void actionTriggered(QAction *action);
|
||||
};
|
||||
|
||||
#endif // HTMLTEXTEDIT_H
|
||||
34
include/richtexteditor.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef RICHTEXTEDITOR_H
|
||||
#define RICHTEXTEDITOR_H
|
||||
|
||||
#include <QTextEdit>
|
||||
#include <QToolBar>
|
||||
|
||||
class RichTextEditor : public QTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RichTextEditor(QWidget *parent = nullptr);
|
||||
void setDefaultFont(QFont font);
|
||||
|
||||
QToolBar *createToolBar(QWidget *parent = nullptr);
|
||||
|
||||
QString text(Qt::TextFormat format) const;
|
||||
|
||||
bool simplifyRichText() const { return m_simplifyRichText; }
|
||||
|
||||
public Q_SLOTS:
|
||||
void setFontBold(bool b);
|
||||
void setFontPointSize(double);
|
||||
void setText(const QString &text);
|
||||
void setSimplifyRichText(bool v);
|
||||
|
||||
Q_SIGNALS:
|
||||
void stateChanged();
|
||||
void simplifyRichTextChanged(bool);
|
||||
|
||||
private:
|
||||
bool m_simplifyRichText;
|
||||
};
|
||||
|
||||
#endif // RICHTEXTEDITOR_H
|
||||
37
include/richtexteditordialog.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef RICHTEXTEDITORDIALOG_H
|
||||
#define RICHTEXTEDITORDIALOG_H
|
||||
|
||||
#include "richtexteditor.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QTextEdit>
|
||||
#include <QTabWidget>
|
||||
|
||||
class RichTextEditorDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RichTextEditorDialog(QWidget *parent = nullptr);
|
||||
~RichTextEditorDialog();
|
||||
|
||||
int showDialog();
|
||||
void setDefaultFont(const QFont &font);
|
||||
void setText(const QString &text);
|
||||
QString text(Qt::TextFormat format = Qt::AutoText) const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void tabIndexChanged(int newIndex);
|
||||
void richTextChanged();
|
||||
void sourceChanged();
|
||||
|
||||
private:
|
||||
enum TabIndex { RichTextIndex, SourceIndex };
|
||||
enum State { Clean, RichTextChanged, SourceChanged };
|
||||
RichTextEditor *m_editor;
|
||||
QTextEdit *m_text_edit;
|
||||
QTabWidget *m_tab_widget;
|
||||
State m_state;
|
||||
int m_initialTab;
|
||||
};
|
||||
|
||||
#endif // RICHTEXTEDITORDIALOG_H
|
||||
57
include/richtexteditortoolbar.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef RICHTEXTEDITORTOOLBAR_H
|
||||
#define RICHTEXTEDITORTOOLBAR_H
|
||||
|
||||
#include "richtexteditor.h"
|
||||
#include "coloraction.h"
|
||||
|
||||
#include <QToolBar>
|
||||
#include <QComboBox>
|
||||
#include <QFontComboBox>
|
||||
#include <QPointer>
|
||||
#include <QAction>
|
||||
|
||||
QIcon createIconSet(const QString &name);
|
||||
|
||||
class RichTextEditorToolBar : public QToolBar
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RichTextEditorToolBar(RichTextEditor *editor,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
public Q_SLOTS:
|
||||
void updateActions();
|
||||
|
||||
private Q_SLOTS:
|
||||
void alignmentActionTriggered(QAction *action);
|
||||
void sizeInputActivated(const QString &size);
|
||||
void fontFamilyActivated(const QString &font);
|
||||
void colorChanged(const QColor &color);
|
||||
void setVAlignSuper(bool super);
|
||||
void setVAlignSub(bool sub);
|
||||
void insertLink();
|
||||
void insertImage();
|
||||
void layoutDirectionChanged();
|
||||
|
||||
private:
|
||||
QAction *m_bold_action;
|
||||
QAction *m_italic_action;
|
||||
QAction *m_underline_action;
|
||||
QAction *m_valign_sup_action;
|
||||
QAction *m_valign_sub_action;
|
||||
QAction *m_align_left_action;
|
||||
QAction *m_align_center_action;
|
||||
QAction *m_align_right_action;
|
||||
QAction *m_align_justify_action;
|
||||
QAction *m_layoutDirectionAction;
|
||||
QAction *m_link_action;
|
||||
QAction *m_image_action;
|
||||
QAction *m_simplify_richtext_action;
|
||||
ColorAction *m_color_action;
|
||||
QComboBox *m_font_size_input;
|
||||
QFontComboBox *m_font_family_input;
|
||||
|
||||
QPointer<RichTextEditor> m_editor;
|
||||
};
|
||||
|
||||
#endif // RICHTEXTEDITORTOOLBAR_H
|
||||
45
src/addlinkdialog.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "addlinkdialog.h"
|
||||
|
||||
AddLinkDialog::AddLinkDialog(RichTextEditor *editor, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
m_ui(new QT_PREPEND_NAMESPACE(Ui)::AddLinkDialog)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_editor = editor;
|
||||
}
|
||||
|
||||
AddLinkDialog::~AddLinkDialog()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
int AddLinkDialog::showDialog()
|
||||
{
|
||||
// Set initial focus
|
||||
const QTextCursor cursor = m_editor->textCursor();
|
||||
if (cursor.hasSelection()) {
|
||||
m_ui->titleInput->setText(cursor.selectedText());
|
||||
m_ui->urlInput->setFocus();
|
||||
} else {
|
||||
m_ui->titleInput->setFocus();
|
||||
}
|
||||
|
||||
return exec();
|
||||
}
|
||||
|
||||
void AddLinkDialog::accept()
|
||||
{
|
||||
const QString title = m_ui->titleInput->text();
|
||||
const QString url = m_ui->urlInput->text();
|
||||
|
||||
if (!title.isEmpty()) {
|
||||
const QString html = "<a href=\"" + url + "\">" + title + "</a>";
|
||||
m_editor->insertHtml(html);
|
||||
}
|
||||
|
||||
m_ui->titleInput->clear();
|
||||
m_ui->urlInput->clear();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
36
src/coloraction.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "coloraction.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPixmap>
|
||||
#include <QColorDialog>
|
||||
|
||||
ColorAction::ColorAction(QObject *parent):
|
||||
QAction(parent)
|
||||
{
|
||||
setText(tr("Text Color"));
|
||||
setColor(Qt::black);
|
||||
connect(this, &QAction::triggered, this, &ColorAction::chooseColor);
|
||||
}
|
||||
|
||||
void ColorAction::setColor(const QColor &color)
|
||||
{
|
||||
if (color == m_color)
|
||||
return;
|
||||
m_color = color;
|
||||
QPixmap pix(24, 24);
|
||||
QPainter painter(&pix);
|
||||
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||
painter.fillRect(pix.rect(), m_color);
|
||||
painter.setPen(m_color.darker());
|
||||
painter.drawRect(pix.rect().adjusted(0, 0, -1, -1));
|
||||
setIcon(pix);
|
||||
}
|
||||
|
||||
void ColorAction::chooseColor()
|
||||
{
|
||||
const QColor col = QColorDialog::getColor(m_color, nullptr);
|
||||
if (col.isValid() && col != m_color) {
|
||||
setColor(col);
|
||||
emit colorChanged(m_color);
|
||||
}
|
||||
}
|
||||
142
src/htmlhighlighter.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
#include "htmlhighlighter.h"
|
||||
|
||||
#include <QTextStream>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
HtmlHighlighter::HtmlHighlighter(QTextEdit *textEdit)
|
||||
: QSyntaxHighlighter(textEdit->document())
|
||||
{
|
||||
QTextCharFormat entityFormat;
|
||||
entityFormat.setForeground(Qt::red);
|
||||
setFormatFor(Entity, entityFormat);
|
||||
|
||||
QTextCharFormat tagFormat;
|
||||
tagFormat.setForeground(Qt::darkMagenta);
|
||||
tagFormat.setFontWeight(QFont::Bold);
|
||||
setFormatFor(Tag, tagFormat);
|
||||
|
||||
QTextCharFormat commentFormat;
|
||||
commentFormat.setForeground(Qt::gray);
|
||||
commentFormat.setFontItalic(true);
|
||||
setFormatFor(Comment, commentFormat);
|
||||
|
||||
QTextCharFormat attributeFormat;
|
||||
attributeFormat.setForeground(Qt::black);
|
||||
attributeFormat.setFontWeight(QFont::Bold);
|
||||
setFormatFor(Attribute, attributeFormat);
|
||||
|
||||
QTextCharFormat valueFormat;
|
||||
valueFormat.setForeground(Qt::blue);
|
||||
setFormatFor(Value, valueFormat);
|
||||
}
|
||||
|
||||
void HtmlHighlighter::setFormatFor(Construct construct,
|
||||
const QTextCharFormat &format)
|
||||
{
|
||||
m_formats[construct] = format;
|
||||
rehighlight();
|
||||
}
|
||||
|
||||
void HtmlHighlighter::highlightBlock(const QString &text)
|
||||
{
|
||||
static const QChar tab = u'\t';
|
||||
static const QChar space = u' ';
|
||||
|
||||
int state = previousBlockState();
|
||||
qsizetype len = text.size();
|
||||
qsizetype start = 0;
|
||||
qsizetype pos = 0;
|
||||
|
||||
while (pos < len) {
|
||||
switch (state) {
|
||||
case NormalState:
|
||||
default:
|
||||
while (pos < len) {
|
||||
QChar ch = text.at(pos);
|
||||
if (ch == u'<') {
|
||||
if (QStringView{text}.sliced(pos).startsWith("<!--"_L1)) {
|
||||
state = InComment;
|
||||
} else {
|
||||
state = InTag;
|
||||
start = pos;
|
||||
while (pos < len && text.at(pos) != space
|
||||
&& text.at(pos) != u'>'
|
||||
&& text.at(pos) != tab
|
||||
&& !QStringView{text}.sliced(pos).startsWith("/>"_L1)) {
|
||||
++pos;
|
||||
}
|
||||
if (QStringView{text}.sliced(pos).startsWith("/>"_L1))
|
||||
++pos;
|
||||
setFormat(start, pos - start,
|
||||
m_formats[Tag]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ch == u'&') {
|
||||
start = pos;
|
||||
while (pos < len && text.at(pos++) != u';')
|
||||
;
|
||||
setFormat(start, pos - start,
|
||||
m_formats[Entity]);
|
||||
} else {
|
||||
// No tag, comment or entity started, continue...
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InComment:
|
||||
start = pos;
|
||||
for ( ; pos < len; ++pos) {
|
||||
if (QStringView{text}.sliced(pos).startsWith("-->"_L1)) {
|
||||
pos += 3;
|
||||
state = NormalState;
|
||||
break;
|
||||
}
|
||||
}
|
||||
setFormat(start, pos - start, m_formats[Comment]);
|
||||
break;
|
||||
case InTag:
|
||||
QChar quote = QChar::Null;
|
||||
while (pos < len) {
|
||||
QChar ch = text.at(pos);
|
||||
if (quote.isNull()) {
|
||||
start = pos;
|
||||
if (ch == '\''_L1 || ch == u'"') {
|
||||
quote = ch;
|
||||
} else if (ch == u'>') {
|
||||
++pos;
|
||||
setFormat(start, pos - start, m_formats[Tag]);
|
||||
state = NormalState;
|
||||
break;
|
||||
} else if (QStringView{text}.sliced(pos).startsWith("/>"_L1)) {
|
||||
pos += 2;
|
||||
setFormat(start, pos - start, m_formats[Tag]);
|
||||
state = NormalState;
|
||||
break;
|
||||
} else if (ch != space && text.at(pos) != tab) {
|
||||
// Tag not ending, not a quote and no whitespace, so
|
||||
// we must be dealing with an attribute.
|
||||
++pos;
|
||||
while (pos < len && text.at(pos) != space
|
||||
&& text.at(pos) != tab
|
||||
&& text.at(pos) != u'=')
|
||||
++pos;
|
||||
setFormat(start, pos - start, m_formats[Attribute]);
|
||||
start = pos;
|
||||
}
|
||||
} else if (ch == quote) {
|
||||
quote = QChar::Null;
|
||||
|
||||
// Anything quoted is a value
|
||||
setFormat(start, pos - start, m_formats[Value]);
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
setCurrentBlockState(state);
|
||||
}
|
||||
|
||||
40
src/htmltextedit.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "htmltextedit.h"
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
void HtmlTextEdit::contextMenuEvent(QContextMenuEvent *event)
|
||||
{
|
||||
QMenu *menu = createStandardContextMenu();
|
||||
QMenu *htmlMenu = new QMenu(tr("Insert HTML entity"), menu);
|
||||
|
||||
typedef struct {
|
||||
const char *text;
|
||||
const char *entity;
|
||||
} Entry;
|
||||
|
||||
const Entry entries[] = {
|
||||
{ "&& (&&)", "&" },
|
||||
{ "& ", " " },
|
||||
{ "&< (<)", "<" },
|
||||
{ "&> (>)", ">" },
|
||||
{ "&© (Copyright)", "©" },
|
||||
{ "&® (Trade Mark)", "®" },
|
||||
};
|
||||
|
||||
for (const Entry &e : entries) {
|
||||
QAction *entityAction = new QAction(QLatin1StringView(e.text),
|
||||
htmlMenu);
|
||||
entityAction->setData(QLatin1StringView(e.entity));
|
||||
htmlMenu->addAction(entityAction);
|
||||
}
|
||||
|
||||
menu->addMenu(htmlMenu);
|
||||
connect(htmlMenu, &QMenu::triggered, this, &HtmlTextEdit::actionTriggered);
|
||||
menu->exec(event->globalPos());
|
||||
delete menu;
|
||||
}
|
||||
|
||||
void HtmlTextEdit::actionTriggered(QAction *action)
|
||||
{
|
||||
insertPlainText(action->data().toString());
|
||||
}
|
||||
179
src/richtexteditor.cpp
Normal file
@@ -0,0 +1,179 @@
|
||||
#include "richtexteditor.h"
|
||||
#include "richtexteditortoolbar.h"
|
||||
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QStringView>
|
||||
#include <QStringLiteral>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
const bool simplifyRichTextDefault = true;
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
// Richtext simplification filter helpers: Elements to be discarded
|
||||
static inline bool filterElement(QStringView name)
|
||||
{
|
||||
return name != "meta"_L1 && name != "style"_L1;
|
||||
}
|
||||
|
||||
// Richtext simplification filter helpers: Filter attributes of elements
|
||||
static inline void filterAttributes(QStringView name,
|
||||
QXmlStreamAttributes *atts,
|
||||
bool *paragraphAlignmentFound)
|
||||
{
|
||||
if (atts->isEmpty())
|
||||
return;
|
||||
|
||||
// No style attributes for <body>
|
||||
if (name == "body"_L1) {
|
||||
atts->clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Clean out everything except 'align' for 'p'
|
||||
if (name == "p"_L1) {
|
||||
for (auto it = atts->begin(); it != atts->end(); ) {
|
||||
if (it->name() == "align"_L1) {
|
||||
++it;
|
||||
*paragraphAlignmentFound = true;
|
||||
} else {
|
||||
it = atts->erase(it);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Richtext simplification filter helpers: Check for blank QStringView.
|
||||
static inline bool isWhiteSpace(QStringView in)
|
||||
{
|
||||
return std::all_of(in.cbegin(), in.cend(),
|
||||
[](QChar c) { return c.isSpace(); });
|
||||
}
|
||||
|
||||
// Richtext simplification filter: Remove hard-coded font settings,
|
||||
// <style> elements, <p> attributes other than 'align' and
|
||||
// and unnecessary meta-information.
|
||||
QString simplifyRichTextFilter(const QString &in, bool *isPlainTextPtr = nullptr)
|
||||
{
|
||||
unsigned elementCount = 0;
|
||||
bool paragraphAlignmentFound = false;
|
||||
QString out;
|
||||
QXmlStreamReader reader(in);
|
||||
QXmlStreamWriter writer(&out);
|
||||
writer.setAutoFormatting(false);
|
||||
writer.setAutoFormattingIndent(0);
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
switch (reader.readNext()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
elementCount++;
|
||||
if (filterElement(reader.name())) {
|
||||
const auto name = reader.name();
|
||||
QXmlStreamAttributes attributes = reader.attributes();
|
||||
filterAttributes(name, &attributes, ¶graphAlignmentFound);
|
||||
writer.writeStartElement(name.toString());
|
||||
if (!attributes.isEmpty())
|
||||
writer.writeAttributes(attributes);
|
||||
} else {
|
||||
reader.readElementText(); // Skip away all nested elements and characters.
|
||||
}
|
||||
break;
|
||||
case QXmlStreamReader::Characters:
|
||||
if (!isWhiteSpace(reader.text()))
|
||||
writer.writeCharacters(reader.text().toString());
|
||||
break;
|
||||
case QXmlStreamReader::EndElement:
|
||||
writer.writeEndElement();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Check for plain text (no spans, just <html><head><body><p>)
|
||||
if (isPlainTextPtr)
|
||||
*isPlainTextPtr = !paragraphAlignmentFound && elementCount == 4u; //
|
||||
return out;
|
||||
}
|
||||
|
||||
RichTextEditor::RichTextEditor(QWidget *parent)
|
||||
: QTextEdit(parent), m_simplifyRichText(simplifyRichTextDefault)
|
||||
{
|
||||
connect(this, &RichTextEditor::currentCharFormatChanged,
|
||||
this, &RichTextEditor::stateChanged);
|
||||
connect(this, &RichTextEditor::cursorPositionChanged,
|
||||
this, &RichTextEditor::stateChanged);
|
||||
}
|
||||
|
||||
QToolBar *RichTextEditor::createToolBar(QWidget *parent)
|
||||
{
|
||||
return new RichTextEditorToolBar(this, parent);
|
||||
}
|
||||
|
||||
void RichTextEditor::setFontBold(bool b)
|
||||
{
|
||||
if (b)
|
||||
setFontWeight(QFont::Bold);
|
||||
else
|
||||
setFontWeight(QFont::Normal);
|
||||
}
|
||||
|
||||
void RichTextEditor::setFontPointSize(double d)
|
||||
{
|
||||
QTextEdit::setFontPointSize(qreal(d));
|
||||
}
|
||||
|
||||
void RichTextEditor::setText(const QString &text)
|
||||
{
|
||||
|
||||
if (Qt::mightBeRichText(text))
|
||||
setHtml(text);
|
||||
else
|
||||
setPlainText(text);
|
||||
}
|
||||
|
||||
void RichTextEditor::setSimplifyRichText(bool v)
|
||||
{
|
||||
if (v != m_simplifyRichText) {
|
||||
m_simplifyRichText = v;
|
||||
emit simplifyRichTextChanged(v);
|
||||
}
|
||||
}
|
||||
|
||||
void RichTextEditor::setDefaultFont(QFont font)
|
||||
{
|
||||
// Some default fonts on Windows have a default size of 7.8,
|
||||
// which results in complicated rich text generated by toHtml().
|
||||
// Use an integer value.
|
||||
const int pointSize = qRound(font.pointSizeF());
|
||||
if (pointSize > 0 && !qFuzzyCompare(qreal(pointSize), font.pointSizeF())) {
|
||||
font.setPointSize(pointSize);
|
||||
}
|
||||
|
||||
document()->setDefaultFont(font);
|
||||
if (font.pointSize() > 0)
|
||||
setFontPointSize(font.pointSize());
|
||||
else
|
||||
setFontPointSize(QFontInfo(font).pointSize());
|
||||
emit textChanged();
|
||||
}
|
||||
|
||||
QString RichTextEditor::text(Qt::TextFormat format) const
|
||||
{
|
||||
switch (format) {
|
||||
case Qt::PlainText:
|
||||
return toPlainText();
|
||||
case Qt::RichText:
|
||||
return m_simplifyRichText ? simplifyRichTextFilter(toHtml()) : toHtml();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const QString html = toHtml();
|
||||
bool isPlainText;
|
||||
const QString simplifiedHtml = simplifyRichTextFilter(html, &isPlainText);
|
||||
if (isPlainText)
|
||||
return toPlainText();
|
||||
return m_simplifyRichText ? simplifiedHtml : html;
|
||||
}
|
||||
143
src/richtexteditordialog.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#include "richtexteditordialog.h"
|
||||
#include "htmltextedit.h"
|
||||
#include "htmlhighlighter.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QToolBar>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
|
||||
RichTextEditorDialog::RichTextEditorDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
m_editor(new RichTextEditor()),
|
||||
m_text_edit(new HtmlTextEdit),
|
||||
m_tab_widget(new QTabWidget),
|
||||
m_state(Clean),
|
||||
m_initialTab(RichTextIndex)
|
||||
{
|
||||
setWindowTitle(tr("Edit text"));
|
||||
|
||||
m_initialTab = RichTextIndex;
|
||||
|
||||
m_text_edit->setAcceptRichText(false);
|
||||
new HtmlHighlighter(m_text_edit);
|
||||
|
||||
connect(m_editor, &QTextEdit::textChanged, this, &RichTextEditorDialog::richTextChanged);
|
||||
connect(m_editor, &RichTextEditor::simplifyRichTextChanged,
|
||||
this, &RichTextEditorDialog::richTextChanged);
|
||||
connect(m_text_edit, &QTextEdit::textChanged, this, &RichTextEditorDialog::sourceChanged);
|
||||
|
||||
// The toolbar needs to be created after the RichTextEditor
|
||||
QToolBar *tool_bar = m_editor->createToolBar(this);
|
||||
tool_bar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
|
||||
QWidget *rich_edit = new QWidget;
|
||||
QVBoxLayout *rich_edit_layout = new QVBoxLayout(rich_edit);
|
||||
rich_edit_layout->addWidget(tool_bar);
|
||||
rich_edit_layout->addWidget(m_editor);
|
||||
|
||||
QWidget *plain_edit = new QWidget;
|
||||
QVBoxLayout *plain_edit_layout = new QVBoxLayout(plain_edit);
|
||||
plain_edit_layout->addWidget(m_text_edit);
|
||||
|
||||
m_tab_widget->setTabPosition(QTabWidget::South);
|
||||
m_tab_widget->addTab(rich_edit, tr("Rich Text"));
|
||||
m_tab_widget->addTab(plain_edit, tr("Source"));
|
||||
connect(m_tab_widget, &QTabWidget::currentChanged,
|
||||
this, &RichTextEditorDialog::tabIndexChanged);
|
||||
|
||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal);
|
||||
QPushButton *ok_button = buttonBox->button(QDialogButtonBox::Ok);
|
||||
ok_button->setText(tr("&OK"));
|
||||
ok_button->setDefault(true);
|
||||
buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("&Cancel"));
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->addWidget(m_tab_widget);
|
||||
layout->addWidget(buttonBox);
|
||||
}
|
||||
|
||||
RichTextEditorDialog::~RichTextEditorDialog()
|
||||
{}
|
||||
|
||||
int RichTextEditorDialog::showDialog()
|
||||
{
|
||||
m_tab_widget->setCurrentIndex(m_initialTab);
|
||||
switch (m_initialTab) {
|
||||
case RichTextIndex:
|
||||
m_editor->selectAll();
|
||||
m_editor->setFocus();
|
||||
break;
|
||||
case SourceIndex:
|
||||
m_text_edit->selectAll();
|
||||
m_text_edit->setFocus();
|
||||
break;
|
||||
}
|
||||
return exec();
|
||||
}
|
||||
|
||||
void RichTextEditorDialog::setDefaultFont(const QFont &font)
|
||||
{
|
||||
m_editor->setDefaultFont(font);
|
||||
}
|
||||
|
||||
void RichTextEditorDialog::setText(const QString &text)
|
||||
{
|
||||
// Generally simplify rich text unless verbose text is found.
|
||||
const bool isSimplifiedRichText = !text.startsWith(QStringLiteral("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">"));
|
||||
m_editor->setSimplifyRichText(isSimplifiedRichText);
|
||||
m_editor->setText(text);
|
||||
m_text_edit->setPlainText(text);
|
||||
m_state = Clean;
|
||||
}
|
||||
|
||||
QString RichTextEditorDialog::text(Qt::TextFormat format) const
|
||||
{
|
||||
// In autotext mode, if the user has changed the source, use that
|
||||
if (format == Qt::AutoText && (m_state == Clean || m_state == SourceChanged))
|
||||
return m_text_edit->toPlainText();
|
||||
// If the plain text HTML editor is selected, first copy its contents over
|
||||
// to the rich text editor so that it is converted to Qt-HTML or actual
|
||||
// plain text.
|
||||
if (m_tab_widget->currentIndex() == SourceIndex && m_state == SourceChanged)
|
||||
m_editor->setHtml(m_text_edit->toPlainText());
|
||||
return m_editor->text(format);
|
||||
}
|
||||
|
||||
void RichTextEditorDialog::tabIndexChanged(int newIndex)
|
||||
{
|
||||
// Anything changed, is there a need for a conversion?
|
||||
if (newIndex == SourceIndex && m_state != RichTextChanged)
|
||||
return;
|
||||
if (newIndex == RichTextIndex && m_state != SourceChanged)
|
||||
return;
|
||||
const State oldState = m_state;
|
||||
// Remember the cursor position, since it is invalidated by setPlainText
|
||||
QTextEdit *new_edit = (newIndex == SourceIndex) ? m_text_edit : m_editor;
|
||||
const int position = new_edit->textCursor().position();
|
||||
|
||||
if (newIndex == SourceIndex)
|
||||
m_text_edit->setPlainText(m_editor->text(Qt::RichText));
|
||||
else
|
||||
m_editor->setHtml(m_text_edit->toPlainText());
|
||||
|
||||
QTextCursor cursor = new_edit->textCursor();
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
if (cursor.position() > position) {
|
||||
cursor.setPosition(position);
|
||||
}
|
||||
new_edit->setTextCursor(cursor);
|
||||
m_state = oldState; // Changed is triggered by setting the text
|
||||
}
|
||||
|
||||
void RichTextEditorDialog::richTextChanged()
|
||||
{
|
||||
m_state = RichTextChanged;
|
||||
}
|
||||
|
||||
void RichTextEditorDialog::sourceChanged()
|
||||
{
|
||||
m_state = SourceChanged;
|
||||
}
|
||||
316
src/richtexteditortoolbar.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
#include "richtexteditortoolbar.h"
|
||||
#include "addlinkdialog.h"
|
||||
|
||||
#include <QFontDatabase>
|
||||
#include <QActionGroup>
|
||||
#include <QTextBlock>
|
||||
#include <QTextBlockFormat>
|
||||
#include <QTextCursor>
|
||||
#include <QFileDialog>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
QIcon createIconSet(const QString &name)
|
||||
{
|
||||
constexpr QLatin1StringView prefixes[] = {
|
||||
":/images/"_L1,
|
||||
};
|
||||
|
||||
for (QLatin1StringView prefix : prefixes) {
|
||||
const QString f = prefix + name;
|
||||
if (QFile::exists(f))
|
||||
return QIcon(f);
|
||||
}
|
||||
|
||||
return QIcon();
|
||||
}
|
||||
|
||||
static QAction *createCheckableAction(const QIcon &icon, const QString &text,
|
||||
QObject *parent = nullptr)
|
||||
{
|
||||
QAction *result = new QAction(parent);
|
||||
result->setIcon(icon);
|
||||
result->setText(text);
|
||||
result->setCheckable(true);
|
||||
result->setChecked(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
RichTextEditorToolBar::RichTextEditorToolBar(RichTextEditor *editor,
|
||||
QWidget *parent) :
|
||||
QToolBar(parent),
|
||||
m_link_action(new QAction(this)),
|
||||
m_image_action(new QAction(this)),
|
||||
m_color_action(new ColorAction(this)),
|
||||
m_font_size_input(new QComboBox),
|
||||
m_editor(editor)
|
||||
{
|
||||
// Font comboBox
|
||||
m_font_family_input = new QFontComboBox(this);
|
||||
m_font_family_input->setEditable(false);
|
||||
connect(m_font_family_input, &QComboBox::textActivated,
|
||||
this, &RichTextEditorToolBar::fontFamilyActivated);
|
||||
addWidget(m_font_family_input);
|
||||
|
||||
// Font size combo box
|
||||
m_font_size_input->setEditable(false);
|
||||
const auto font_sizes = QFontDatabase::standardSizes();
|
||||
for (int font_size : font_sizes)
|
||||
m_font_size_input->addItem(QString::number(font_size));
|
||||
|
||||
connect(m_font_size_input, &QComboBox::textActivated,
|
||||
this, &RichTextEditorToolBar::sizeInputActivated);
|
||||
addWidget(m_font_size_input);
|
||||
|
||||
addSeparator();
|
||||
|
||||
// Bold, italic and underline buttons
|
||||
|
||||
m_bold_action = createCheckableAction(
|
||||
createIconSet(u"textbold.png"_s), tr("Bold"), this);
|
||||
connect(m_bold_action, &QAction::triggered, editor, &RichTextEditor::setFontBold);
|
||||
m_bold_action->setShortcut(tr("CTRL+B"));
|
||||
addAction(m_bold_action);
|
||||
|
||||
m_italic_action = createCheckableAction(
|
||||
createIconSet(u"textitalic.png"_s), tr("Italic"), this);
|
||||
connect(m_italic_action, &QAction::triggered, editor, &RichTextEditor::setFontItalic);
|
||||
m_italic_action->setShortcut(tr("CTRL+I"));
|
||||
addAction(m_italic_action);
|
||||
|
||||
m_underline_action = createCheckableAction(
|
||||
createIconSet(u"textunder.png"_s), tr("Underline"), this);
|
||||
connect(m_underline_action, &QAction::triggered, editor, &RichTextEditor::setFontUnderline);
|
||||
m_underline_action->setShortcut(tr("CTRL+U"));
|
||||
addAction(m_underline_action);
|
||||
|
||||
addSeparator();
|
||||
|
||||
// Left, center, right and justified alignment buttons
|
||||
|
||||
QActionGroup *alignment_group = new QActionGroup(this);
|
||||
connect(alignment_group, &QActionGroup::triggered,
|
||||
this, &RichTextEditorToolBar::alignmentActionTriggered);
|
||||
|
||||
m_align_left_action = createCheckableAction(
|
||||
createIconSet(u"textleft.png"_s), tr("Left Align"), alignment_group);
|
||||
addAction(m_align_left_action);
|
||||
|
||||
m_align_center_action = createCheckableAction(
|
||||
createIconSet(u"textcenter.png"_s), tr("Center"), alignment_group);
|
||||
addAction(m_align_center_action);
|
||||
|
||||
m_align_right_action = createCheckableAction(
|
||||
createIconSet(u"textright.png"_s), tr("Right Align"), alignment_group);
|
||||
addAction(m_align_right_action);
|
||||
|
||||
m_align_justify_action = createCheckableAction(
|
||||
createIconSet(u"textjustify.png"_s), tr("Justify"), alignment_group);
|
||||
addAction(m_align_justify_action);
|
||||
|
||||
m_layoutDirectionAction = createCheckableAction(
|
||||
createIconSet(u"righttoleft.png"_s), tr("Right to Left"));
|
||||
connect(m_layoutDirectionAction, &QAction::triggered,
|
||||
this, &RichTextEditorToolBar::layoutDirectionChanged);
|
||||
addAction(m_layoutDirectionAction);
|
||||
|
||||
addSeparator();
|
||||
|
||||
// Superscript and subscript buttons
|
||||
|
||||
m_valign_sup_action = createCheckableAction(
|
||||
createIconSet(u"textsuperscript.png"_s), tr("Superscript"), this);
|
||||
connect(m_valign_sup_action, &QAction::triggered,
|
||||
this, &RichTextEditorToolBar::setVAlignSuper);
|
||||
addAction(m_valign_sup_action);
|
||||
|
||||
m_valign_sub_action = createCheckableAction(
|
||||
createIconSet(u"textsubscript.png"_s), tr("Subscript"), this);
|
||||
connect(m_valign_sub_action, &QAction::triggered,
|
||||
this, &RichTextEditorToolBar::setVAlignSub);
|
||||
addAction(m_valign_sub_action);
|
||||
|
||||
addSeparator();
|
||||
|
||||
// Insert hyperlink and image buttons
|
||||
|
||||
m_link_action->setIcon(createIconSet(u"textanchor.png"_s));
|
||||
m_link_action->setText(tr("Insert &Link"));
|
||||
connect(m_link_action, &QAction::triggered, this, &RichTextEditorToolBar::insertLink);
|
||||
addAction(m_link_action);
|
||||
|
||||
m_image_action->setIcon(createIconSet(u"insertimage.png"_s));
|
||||
m_image_action->setText(tr("Insert &Image"));
|
||||
connect(m_image_action, &QAction::triggered, this, &RichTextEditorToolBar::insertImage);
|
||||
addAction(m_image_action);
|
||||
|
||||
addSeparator();
|
||||
|
||||
// Text color button
|
||||
connect(m_color_action, &ColorAction::colorChanged,
|
||||
this, &RichTextEditorToolBar::colorChanged);
|
||||
addAction(m_color_action);
|
||||
|
||||
addSeparator();
|
||||
|
||||
// Simplify rich text
|
||||
m_simplify_richtext_action
|
||||
= createCheckableAction(createIconSet(u"simplifyrichtext.png"_s), tr("Simplify Rich Text"));
|
||||
connect(m_simplify_richtext_action, &QAction::triggered,
|
||||
m_editor, &RichTextEditor::setSimplifyRichText);
|
||||
m_simplify_richtext_action->setChecked(m_editor->simplifyRichText());
|
||||
connect(m_editor.data(), &RichTextEditor::simplifyRichTextChanged,
|
||||
m_simplify_richtext_action, &QAction::setChecked);
|
||||
addAction(m_simplify_richtext_action);
|
||||
|
||||
connect(editor, &QTextEdit::textChanged, this, &RichTextEditorToolBar::updateActions);
|
||||
connect(editor, &RichTextEditor::stateChanged, this, &RichTextEditorToolBar::updateActions);
|
||||
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void RichTextEditorToolBar::alignmentActionTriggered(QAction *action)
|
||||
{
|
||||
Qt::Alignment new_alignment;
|
||||
|
||||
if (action == m_align_left_action) {
|
||||
new_alignment = Qt::AlignLeft;
|
||||
} else if (action == m_align_center_action) {
|
||||
new_alignment = Qt::AlignCenter;
|
||||
} else if (action == m_align_right_action) {
|
||||
new_alignment = Qt::AlignRight;
|
||||
} else {
|
||||
new_alignment = Qt::AlignJustify;
|
||||
}
|
||||
|
||||
m_editor->setAlignment(new_alignment);
|
||||
}
|
||||
|
||||
void RichTextEditorToolBar::colorChanged(const QColor &color)
|
||||
{
|
||||
m_editor->setTextColor(color);
|
||||
m_editor->setFocus();
|
||||
}
|
||||
|
||||
void RichTextEditorToolBar::sizeInputActivated(const QString &size)
|
||||
{
|
||||
bool ok;
|
||||
int i = size.toInt(&ok);
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
m_editor->setFontPointSize(i);
|
||||
m_editor->setFocus();
|
||||
}
|
||||
|
||||
void RichTextEditorToolBar::fontFamilyActivated(const QString &font)
|
||||
{
|
||||
QTextCharFormat fmt;
|
||||
fmt.setFontFamilies({font});
|
||||
QTextCursor cursor = m_editor->textCursor();
|
||||
if (!cursor.hasSelection())
|
||||
cursor.select(QTextCursor::WordUnderCursor);
|
||||
cursor.mergeCharFormat(fmt);
|
||||
m_editor->mergeCurrentCharFormat(fmt);
|
||||
}
|
||||
|
||||
void RichTextEditorToolBar::setVAlignSuper(bool super)
|
||||
{
|
||||
const QTextCharFormat::VerticalAlignment align = super ?
|
||||
QTextCharFormat::AlignSuperScript : QTextCharFormat::AlignNormal;
|
||||
|
||||
QTextCharFormat charFormat = m_editor->currentCharFormat();
|
||||
charFormat.setVerticalAlignment(align);
|
||||
m_editor->setCurrentCharFormat(charFormat);
|
||||
|
||||
m_valign_sub_action->setChecked(false);
|
||||
}
|
||||
|
||||
void RichTextEditorToolBar::setVAlignSub(bool sub)
|
||||
{
|
||||
const QTextCharFormat::VerticalAlignment align = sub ?
|
||||
QTextCharFormat::AlignSubScript : QTextCharFormat::AlignNormal;
|
||||
|
||||
QTextCharFormat charFormat = m_editor->currentCharFormat();
|
||||
charFormat.setVerticalAlignment(align);
|
||||
m_editor->setCurrentCharFormat(charFormat);
|
||||
|
||||
m_valign_sup_action->setChecked(false);
|
||||
}
|
||||
|
||||
void RichTextEditorToolBar::insertLink()
|
||||
{
|
||||
AddLinkDialog linkDialog(m_editor, this);
|
||||
linkDialog.showDialog();
|
||||
m_editor->setFocus();
|
||||
}
|
||||
|
||||
void RichTextEditorToolBar::insertImage()
|
||||
{
|
||||
const QString path = QFileDialog::getOpenFileName(this, tr("Open File"),
|
||||
QDir::homePath(),
|
||||
tr("Images (*.png *.xpm *.jpg)"));
|
||||
if (!path.isEmpty())
|
||||
m_editor->insertHtml(QStringLiteral("<img src=\"") + path + QStringLiteral("\"/>"));
|
||||
}
|
||||
|
||||
void RichTextEditorToolBar::layoutDirectionChanged()
|
||||
{
|
||||
QTextCursor cursor = m_editor->textCursor();
|
||||
QTextBlock block = cursor.block();
|
||||
if (block.isValid()) {
|
||||
QTextBlockFormat format = block.blockFormat();
|
||||
const Qt::LayoutDirection newDirection = m_layoutDirectionAction->isChecked() ? Qt::RightToLeft : Qt::LeftToRight;
|
||||
if (format.layoutDirection() != newDirection) {
|
||||
format.setLayoutDirection(newDirection);
|
||||
cursor.setBlockFormat(format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RichTextEditorToolBar::updateActions()
|
||||
{
|
||||
if (m_editor == nullptr) {
|
||||
setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const Qt::Alignment alignment = m_editor->alignment();
|
||||
const QTextCursor cursor = m_editor->textCursor();
|
||||
const QTextCharFormat charFormat = cursor.charFormat();
|
||||
const QFont font = charFormat.font();
|
||||
const QTextCharFormat::VerticalAlignment valign =
|
||||
charFormat.verticalAlignment();
|
||||
const bool superScript = valign == QTextCharFormat::AlignSuperScript;
|
||||
const bool subScript = valign == QTextCharFormat::AlignSubScript;
|
||||
|
||||
if (alignment & Qt::AlignLeft) {
|
||||
m_align_left_action->setChecked(true);
|
||||
} else if (alignment & Qt::AlignRight) {
|
||||
m_align_right_action->setChecked(true);
|
||||
} else if (alignment & Qt::AlignHCenter) {
|
||||
m_align_center_action->setChecked(true);
|
||||
} else {
|
||||
m_align_justify_action->setChecked(true);
|
||||
}
|
||||
m_layoutDirectionAction->setChecked(cursor.blockFormat().layoutDirection() == Qt::RightToLeft);
|
||||
|
||||
m_bold_action->setChecked(font.bold());
|
||||
m_italic_action->setChecked(font.italic());
|
||||
m_underline_action->setChecked(font.underline());
|
||||
m_valign_sup_action->setChecked(superScript);
|
||||
m_valign_sub_action->setChecked(subScript);
|
||||
|
||||
const int size = font.pointSize();
|
||||
const int idx = m_font_size_input->findText(QString::number(size));
|
||||
if (idx != -1)
|
||||
m_font_size_input->setCurrentIndex(idx);
|
||||
|
||||
const int fidx = m_font_family_input->findText(QFontInfo(font).family());
|
||||
if (fidx != -1)
|
||||
m_font_family_input->setCurrentIndex(fidx);
|
||||
|
||||
m_color_action->setColor(m_editor->textColor());
|
||||
}
|
||||
112
uis/addlinkdialog.ui
Normal file
@@ -0,0 +1,112 @@
|
||||
<ui version="4.0" >
|
||||
<class>AddLinkDialog</class>
|
||||
<widget class="QDialog" name="AddLinkDialog" >
|
||||
<property name="windowTitle" >
|
||||
<string>Insert Link</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="modal" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
<item>
|
||||
<layout class="QFormLayout" >
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Title:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLineEdit" name="titleInput" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>337</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>URL:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLineEdit" name="urlInput" />
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AddLinkDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AddLinkDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||