diff options
author | Ariya Hidayat <ariya.hidayat@trolltech.com> | 2009-03-11 11:10:16 +0100 |
---|---|---|
committer | Ariya Hidayat <ariya.hidayat@trolltech.com> | 2009-03-11 11:17:03 +0100 |
commit | c8d0c381b994d7417863832929cc4c3f710f2db5 (patch) | |
tree | 3242d6bc641b746ae307c9cf312b2539a228b064 /htmleditor | |
parent | f31d32a82828ce05a591b7a453447ecdfb5d0e92 (diff) |
Add a new example: WYSIWYG HTML editor
Diffstat (limited to 'htmleditor')
38 files changed, 1853 insertions, 0 deletions
diff --git a/htmleditor/example.html b/htmleditor/example.html new file mode 100644 index 0000000..8c63613 --- /dev/null +++ b/htmleditor/example.html @@ -0,0 +1,73 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<html><head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>HTML Editor Demo</title> +</head> + +<body> +<h1 align="center">WYSIWYG HTML Editor</h1> + +<!-- This is just a comment. We start here --> + +<p>WYSIWYG HTML Editor can be realized using QtWebKit, by utilizing the contentEditable property of a web page. If this is set to true, "live editing" of the web page is possible.</p> + +<p>If you are viewing this document in the <i>HTML Editor</i> demo, you can edit this HTML file to explore QtWebKit editing features. We have included some comments in each of the following sections to encourage you to experiment.</p> + +<h2>Formatting</h2> + +<p>This editor supports <b>bold</b>, <i>italic</i>, <u>underline</u>, and <s>strikethrough</s> character formatting. If you place the cursor in a region of formatted text, the controls in the tool bars will change to reflect the current formatting.</p> + +<p>The text can use different font, like <span style="font-family: Helvetica">Helvetica</span> or <span style="font-family: Times">Times</span>. Even <span style="color: rgb(128, 0, 0)">with</span> <span style="color: rgb(128, 128, 0)">different</span> <span style="color: rgb(128, 0, 128)">colors</span>, and can be <span style="background-color: rgb(255, 255, 128)">highlighted</span> as well. +Different font sizes are supported: <span style="font-size: xx-small">xx-small</span>, <span style="font-size: x-small">x-small</span>, <span style="font-size: small">small</span>, <span style="font-size: medium">medium</span>, <span style="font-size: x-large">x-large</span>, and <span style="font-size: xx-large">xx-large</span>. </p> + +<blockquote>Paragraphs can be indented, for example like this one. In HTML term, this is known as "blockquote".</blockquote> + +<p>Paragraphs can be formatted so that the text is left-aligned, right-aligned, centered, or fully justified.</p> +<p style="text-align: center;">This paragraph is centered, ...</p> +<p style="text-align: right;">while this one is right-aligned, ...</p> +<p>Try changing the alignment of some text and resize the editor to see how the text layout changes.</p> + +<p>Each paragraph can be set as a heading. Use menu <i>Format</i>, <i>Style</i> and choose a proper heading, Heading 1 is for the highest-level. +A heading can be reverted back to a normal paragraph by choosing Paragraph in that Style menu.</p> + +<h2>Lists</h2> + +<p>Both bulleted and numbered lists are supported.</p> + +<p>Here is an example of bulleted list:</p> +<ul> +<li>Mercurius</li> +<li>Venus</li> +<li>Earth</li> +</ul> + +<p>And this is an example of numbered list:</p> +<ol> +<li>Mars</li> +<li>Jupiter</li> +<li>Uranus</li> +<li>Saturnus</li> +</ol> + +<h2>Images</h2> + +<p>As with normal HTML document, images can be inserted in the text, like this example:</p> + +<p><img src="qrc:/qtlogo.png"></p> + +<p>To insert an image, use the icon <img src="qrc:/images/image-x-generic.png"> in the tool bar or use the menu <i>Edit</i>, <i>Insert Image</i>. Try to delete the above image and replace it with a new one.</p> + +<h2>Hyperlinks</h2> + +<p>Since this is an HTML editor, it is not complete without the support for create hyperlinks. You can do this by using the icon <img src="qrc:/images/text-html.png"> in the tool bar or menu <i>Edit</i> , <i>Create Link</i>. Here is an example of a link to <a href="http://www.qtsoftware.com">Qt Software website</a>.</p> + +<p>If a link is clicked, it will be opened in the default web browser. A confirmation dialog pops up before the link is opened.</p> + +<h2>Undo and Redo</h2> + +<p>Full support for undo and redo operations is built into the editing feature. Try making changes to this document and press Ctrl+Z to undo them. You can always recover the original contents of the document.</span> </p> + +<h2>Note</h2> +<p>Icons used in this program are taken from the public domain <a href="http://tango.freedesktop.org/Tango_Desktop_Project">Tango Desktop Project</a>.</p> + +</body></html> diff --git a/htmleditor/highlighter.cpp b/htmleditor/highlighter.cpp new file mode 100644 index 0000000..6d10629 --- /dev/null +++ b/htmleditor/highlighter.cpp @@ -0,0 +1,269 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Graphics Dojo project on Qt Labs. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 or 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include "highlighter.h" + +#include <QtGui> + +Highlighter::Highlighter(QTextDocument *document) + : QSyntaxHighlighter(document) +{ + m_colors[DocType] = QColor(192, 192, 192); + m_colors[Entity] = QColor(128, 128, 128); + m_colors[Tag] = QColor(136, 18, 128); + m_colors[Comment] = QColor( 35, 110, 37); + m_colors[AttributeName] = QColor(153, 69, 0); + m_colors[AttributeValue] = QColor( 36, 36, 170); +} + +void Highlighter::highlightBlock(const QString &text) +{ + int state = previousBlockState(); + int len = text.length(); + int start = 0; + int pos = 0; + + while (pos < len) { + + switch (state) { + + case State_Text: + default: + + while (pos < len) { + QChar ch = text.at(pos); + if (ch == '<') { + if (text.mid(pos, 4) == "<!--") { + state = State_Comment; + } else { + if (text.mid(pos, 9).toUpper() == "<!DOCTYPE") + state = State_DocType; + else + state = State_TagStart; + } + break; + } else if (ch == '&') { + start = pos; + while (pos < len + && text.at(pos++) != ';') + ; + setFormat(start, pos - start, m_colors[Entity]); + } else { + ++pos; + } + } + break; + + + case State_Comment: + start = pos; + while (pos < len) { + if (text.mid(pos, 3) == "-->") { + pos += 3; + state = State_Text; + break; + } else { + ++pos; + } + } + setFormat(start, pos - start, m_colors[Comment]); + break; + + case State_DocType: + start = pos; + while (pos < len) { + QChar ch = text.at(pos); + ++pos; + if (ch == '>') { + state = State_Text; + break; + } + } + setFormat(start, pos - start, m_colors[DocType]); + break; + + // at '<' in e.g. "<span>foo</span>" + case State_TagStart: + start = pos + 1; + while (pos < len) { + QChar ch = text.at(pos); + ++pos; + if (ch == '>') { + state = State_Text; + break; + } + if (!ch.isSpace()) { + --pos; + state = State_TagName; + break; + } + } + break; + + // at 'b' in e.g "<blockquote>foo</blockquote>" + case State_TagName: + start = pos; + while (pos < len) { + QChar ch = text.at(pos); + ++pos; + if (ch.isSpace()) { + --pos; + state = State_InsideTag; + break; + } + if (ch == '>') { + state = State_Text; + break; + } + } + setFormat(start, pos - start, m_colors[Tag]); + break; + + // anywhere after tag name and before tag closing ('>') + case State_InsideTag: + start = pos; + + while (pos < len) { + QChar ch = text.at(pos); + ++pos; + + if (ch == '/') + continue; + + if (ch == '>') { + state = State_Text; + break; + } + + if (!ch.isSpace()) { + --pos; + state = State_AttributeName; + break; + } + + } + + break; + + // at 's' in e.g. <img src=bla.png/> + case State_AttributeName: + start = pos; + + while (pos < len) { + QChar ch = text.at(pos); + ++pos; + + if (ch == '=') { + state = State_AttributeValue; + break; + } + + if (ch == '>' || ch == '/') { + state = State_InsideTag; + break; + } + } + + setFormat(start, pos - start, m_colors[AttributeName]); + break; + + // after '=' in e.g. <img src=bla.png/> + case State_AttributeValue: + start = pos; + + // find first non-space character + while (pos < len) { + QChar ch = text.at(pos); + ++pos; + + // handle opening single quote + if (ch == '\'') { + state = State_SingleQuote; + break; + } + + // handle opening double quote + if (ch == '"') { + state = State_DoubleQuote; + break; + } + + if (!ch.isSpace()) + break; + } + + if (state == State_AttributeValue) { + // attribute value without quote + // just stop at non-space or tag delimiter + start = pos; + while (pos < len) { + QChar ch = text.at(pos); + if (ch.isSpace()) + break; + if (ch == '>' || ch == '/') + break; + ++pos; + } + state = State_InsideTag; + setFormat(start, pos - start, m_colors[AttributeValue]); + } + + break; + + // after the opening single quote in an attribute value + case State_SingleQuote: + start = pos; + + while (pos < len) { + QChar ch = text.at(pos); + ++pos; + if (ch == '\'') + break; + } + + state = State_InsideTag; + + setFormat(start, pos - start, m_colors[AttributeValue]); + break; + + // after the opening double quote in an attribute value + case State_DoubleQuote: + start = pos; + + while (pos < len) { + QChar ch = text.at(pos); + ++pos; + if (ch == '"') + break; + } + + state = State_InsideTag; + + setFormat(start, pos - start, m_colors[AttributeValue]); + break; + + } + } + + setCurrentBlockState(state); +} diff --git a/htmleditor/highlighter.h b/htmleditor/highlighter.h new file mode 100644 index 0000000..603433e --- /dev/null +++ b/htmleditor/highlighter.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Graphics Dojo project on Qt Labs. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 or 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef HIGHLIGHTER_H +#define HIGHLIGHTER_H + +#include <QHash> +#include <QSyntaxHighlighter> + +// based on http://doc.trolltech.com/qq/qq21-syntaxhighlighter.html + +class Highlighter : public QSyntaxHighlighter +{ + Q_OBJECT + +public: + + Highlighter(QTextDocument *document); + + enum Construct { + DocType, + Entity, + Tag, + Comment, + AttributeName, + AttributeValue + }; + +protected: + enum State { + State_Text = -1, + State_DocType, + State_Comment, + State_TagStart, + State_TagName, + State_InsideTag, + State_AttributeName, + State_SingleQuote, + State_DoubleQuote, + State_AttributeValue, + }; + + void highlightBlock(const QString &text); + +private: + QHash<int, QColor> m_colors; +}; + + +#endif // HIGHLIGHTER_H diff --git a/htmleditor/htmleditor.cpp b/htmleditor/htmleditor.cpp new file mode 100644 index 0000000..7e009c8 --- /dev/null +++ b/htmleditor/htmleditor.cpp @@ -0,0 +1,609 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Graphics Dojo project on Qt Labs. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 or 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + + +#include "htmleditor.h" +#include "highlighter.h" + +#include "ui_htmleditor.h" +#include "ui_inserthtmldialog.h" + +#include <QtGui> +#include <QtWebKit> + +#define FORWARD_ACTION(action1, action2) \ + connect(action1, SIGNAL(triggered()), \ + ui->webView->pageAction(action2), SLOT(trigger())); \ + connect(ui->webView->pageAction(action2), \ + SIGNAL(changed()), SLOT(adjustActions())); + + +HtmlEditor::HtmlEditor(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui_MainWindow) + , sourceDirty(true) + , highlighter(0) + , ui_dialog(0) + , insertHtmlDialog(0) +{ + ui->setupUi(this); + ui->tabWidget->setTabText(0, "Normal View"); + ui->tabWidget->setTabText(1, "HTML Source"); + connect(ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(changeTab(int))); + resize(600, 600); + + highlighter = new Highlighter(ui->plainTextEdit->document()); + + QWidget *spacer = new QWidget(this); + spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + ui->standardToolBar->insertWidget(ui->actionZoomOut, spacer); + + zoomLabel = new QLabel; + ui->standardToolBar->insertWidget(ui->actionZoomOut, zoomLabel); + + zoomSlider = new QSlider(this); + zoomSlider->setOrientation(Qt::Horizontal); + zoomSlider->setMaximumWidth(150); + zoomSlider->setRange(25, 400); + zoomSlider->setSingleStep(25); + zoomSlider->setPageStep(100); + connect(zoomSlider, SIGNAL(valueChanged(int)), SLOT(changeZoom(int))); + ui->standardToolBar->insertWidget(ui->actionZoomIn, zoomSlider); + + connect(ui->actionFileNew, SIGNAL(triggered()), SLOT(fileNew())); + connect(ui->actionFileOpen, SIGNAL(triggered()), SLOT(fileOpen())); + connect(ui->actionFileSave, SIGNAL(triggered()), SLOT(fileSave())); + connect(ui->actionFileSaveAs, SIGNAL(triggered()), SLOT(fileSaveAs())); + connect(ui->actionExit, SIGNAL(triggered()), SLOT(close())); + connect(ui->actionInsertImage, SIGNAL(triggered()), SLOT(insertImage())); + connect(ui->actionCreateLink, SIGNAL(triggered()), SLOT(createLink())); + connect(ui->actionInsertHtml, SIGNAL(triggered()), SLOT(insertHtml())); + connect(ui->actionZoomOut, SIGNAL(triggered()), SLOT(zoomOut())); + connect(ui->actionZoomIn, SIGNAL(triggered()), SLOT(zoomIn())); + + // these are forward to internal QWebView + FORWARD_ACTION(ui->actionEditUndo, QWebPage::Undo); + FORWARD_ACTION(ui->actionEditRedo, QWebPage::Redo); + FORWARD_ACTION(ui->actionEditCut, QWebPage::Cut); + FORWARD_ACTION(ui->actionEditCopy, QWebPage::Copy); + FORWARD_ACTION(ui->actionEditPaste, QWebPage::Paste); + FORWARD_ACTION(ui->actionFormatBold, QWebPage::ToggleBold); + FORWARD_ACTION(ui->actionFormatItalic, QWebPage::ToggleItalic); + FORWARD_ACTION(ui->actionFormatUnderline, QWebPage::ToggleUnderline); + + // Qt 4.5.0 has a bug: always returns 0 for QWebPage::SelectAll + connect(ui->actionEditSelectAll, SIGNAL(triggered()), SLOT(editSelectAll())); + + connect(ui->actionStyleParagraph, SIGNAL(triggered()), SLOT(styleParagraph())); + connect(ui->actionStyleHeading1, SIGNAL(triggered()), SLOT(styleHeading1())); + connect(ui->actionStyleHeading2, SIGNAL(triggered()), SLOT(styleHeading2())); + connect(ui->actionStyleHeading3, SIGNAL(triggered()), SLOT(styleHeading3())); + connect(ui->actionStyleHeading4, SIGNAL(triggered()), SLOT(styleHeading4())); + connect(ui->actionStyleHeading5, SIGNAL(triggered()), SLOT(styleHeading5())); + connect(ui->actionStyleHeading6, SIGNAL(triggered()), SLOT(styleHeading6())); + connect(ui->actionStylePreformatted, SIGNAL(triggered()), SLOT(stylePreformatted())); + connect(ui->actionStyleAddress, SIGNAL(triggered()), SLOT(styleAddress())); + connect(ui->actionFormatFontName, SIGNAL(triggered()), SLOT(formatFontName())); + connect(ui->actionFormatFontSize, SIGNAL(triggered()), SLOT(formatFontSize())); + connect(ui->actionFormatTextColor, SIGNAL(triggered()), SLOT(formatTextColor())); + connect(ui->actionFormatBackgroundColor, SIGNAL(triggered()), SLOT(formatBackgroundColor())); + + // no page action exists yet for these, so use execCommand trick + connect(ui->actionFormatStrikethrough, SIGNAL(triggered()), SLOT(formatStrikeThrough())); + connect(ui->actionFormatAlignLeft, SIGNAL(triggered()), SLOT(formatAlignLeft())); + connect(ui->actionFormatAlignCenter, SIGNAL(triggered()), SLOT(formatAlignCenter())); + connect(ui->actionFormatAlignRight, SIGNAL(triggered()), SLOT(formatAlignRight())); + connect(ui->actionFormatAlignJustify, SIGNAL(triggered()), SLOT(formatAlignJustify())); + connect(ui->actionFormatDecreaseIndent, SIGNAL(triggered()), SLOT(formatDecreaseIndent())); + connect(ui->actionFormatIncreaseIndent, SIGNAL(triggered()), SLOT(formatIncreaseIndent())); + connect(ui->actionFormatNumberedList, SIGNAL(triggered()), SLOT(formatNumberedList())); + connect(ui->actionFormatBulletedList, SIGNAL(triggered()), SLOT(formatBulletedList())); + + + // necessary to sync our actions + connect(ui->webView->page(), SIGNAL(selectionChanged()), SLOT(adjustActions())); + + connect(ui->webView->page(), SIGNAL(contentsChanged()), SLOT(adjustSource())); + ui->webView->setFocus(); + + setCurrentFileName(QString()); + + QString initialFile = ":/example.html"; + const QStringList args = QCoreApplication::arguments(); + if (args.count() == 2) + initialFile = args.at(1); + + if (!load(initialFile)) + fileNew(); + + adjustActions(); + adjustSource(); + setWindowModified(false); + changeZoom(100); +} + +HtmlEditor::~HtmlEditor() +{ + delete ui; + delete ui_dialog; +} + +bool HtmlEditor::maybeSave() +{ + if (!isWindowModified()) + return true; + + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("HTML Editor"), + tr("The document has been modified.\n" + "Do you want to save your changes?"), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return fileSave(); + else if (ret == QMessageBox::Cancel) + return false; + return true; +} + +void HtmlEditor::fileNew() +{ + if (maybeSave()) { + ui->webView->setHtml("<p></p>"); + ui->webView->setFocus(); + ui->webView->page()->setContentEditable(true); + setCurrentFileName(QString()); + setWindowModified(false); + + // quirk in QWebView: need an initial mouse click to show the cursor + int mx = ui->webView->width() / 2; + int my = ui->webView->height() / 2; + QPoint center = QPoint(mx, my); + QMouseEvent *e1 = new QMouseEvent(QEvent::MouseButtonPress, center, + Qt::LeftButton, Qt::LeftButton, + Qt::NoModifier); + QMouseEvent *e2 = new QMouseEvent(QEvent::MouseButtonRelease, center, + Qt::LeftButton, Qt::LeftButton, + Qt::NoModifier); + QApplication::postEvent(ui->webView, e1); + QApplication::postEvent(ui->webView, e2); + } +} + +void HtmlEditor::fileOpen() +{ + QString fn = QFileDialog::getOpenFileName(this, tr("Open File..."), + QString(), tr("HTML-Files (*.htm *.html);;All Files (*)")); + if (!fn.isEmpty()) + load(fn); +} + +bool HtmlEditor::fileSave() +{ + if (fileName.isEmpty() || fileName.startsWith(QLatin1String(":/"))) + return fileSaveAs(); + + QFile file(fileName); + bool success = file.open(QIODevice::WriteOnly); + if (success) { + // FIXME: here we always use UTF-8 encoding + QString content = ui->webView->page()->mainFrame()->toHtml(); + QByteArray data = content.toUtf8(); + qint64 c = file.write(data); + success = (c >= data.length()); + } + + setWindowModified(false); + return success; +} + +bool HtmlEditor::fileSaveAs() +{ + QString fn = QFileDialog::getSaveFileName(this, tr("Save as..."), + QString(), tr("HTML-Files (*.htm *.html);;All Files (*)")); + if (fn.isEmpty()) + return false; + if (!(fn.endsWith(".htm", Qt::CaseInsensitive) || fn.endsWith(".html", Qt::CaseInsensitive))) + fn += ".htm"; // default + setCurrentFileName(fn); + return fileSave(); +} + +void HtmlEditor::insertImage() +{ + QString filters; + filters += tr("Common Graphics (*.png *.jpg *.jpeg *.gif);;"); + filters += tr("Portable Network Graphics (PNG) (*.png);;"); + filters += tr("JPEG (*.jpg *.jpeg);;"); + filters += tr("Graphics Interchange Format (*.gif);;"); + filters += tr("All Files (*)"); + + QString fn = QFileDialog::getOpenFileName(this, tr("Open image..."), + QString(), filters); + if (fn.isEmpty()) + return; + if (!QFile::exists(fn)) + return; + + QUrl url = QUrl::fromLocalFile(fn); + execCommand("insertImage", url.toString()); +} + +// shamelessly copied from Qt Demo Browser +static QUrl guessUrlFromString(const QString &string) +{ + QString urlStr = string.trimmed(); + QRegExp test(QLatin1String("^[a-zA-Z]+\\:.*")); + + // Check if it looks like a qualified URL. Try parsing it and see. + bool hasSchema = test.exactMatch(urlStr); + if (hasSchema) { + QUrl url(urlStr, QUrl::TolerantMode); + if (url.isValid()) + return url; + } + + // Might be a file. + if (QFile::exists(urlStr)) + return QUrl::fromLocalFile(urlStr); + + // Might be a shorturl - try to detect the schema. + if (!hasSchema) { + int dotIndex = urlStr.indexOf(QLatin1Char('.')); + if (dotIndex != -1) { + QString prefix = urlStr.left(dotIndex).toLower(); + QString schema = (prefix == QLatin1String("ftp")) ? prefix : QLatin1String("http"); + QUrl url(schema + QLatin1String("://") + urlStr, QUrl::TolerantMode); + if (url.isValid()) + return url; + } + } + + // Fall back to QUrl's own tolerant parser. + return QUrl(string, QUrl::TolerantMode); +} + +void HtmlEditor::createLink() +{ + QString link = QInputDialog::getText(this, tr("Create link"), + "Enter URL"); + if (!link.isEmpty()) { + QUrl url = guessUrlFromString(link); + if (url.isValid()) + execCommand("createLink", url.toString()); + } +} + +void HtmlEditor::insertHtml() +{ + if (!insertHtmlDialog) { + insertHtmlDialog = new QDialog(this); + if (!ui_dialog) + ui_dialog = new Ui_Dialog; + ui_dialog->setupUi(insertHtmlDialog); + connect(ui_dialog->buttonBox, SIGNAL(accepted()), + insertHtmlDialog, SLOT(accept())); + connect(ui_dialog->buttonBox, SIGNAL(rejected()), + insertHtmlDialog, SLOT(reject())); + } + + ui_dialog->plainTextEdit->clear(); + ui_dialog->plainTextEdit->setFocus(); + Highlighter *hilite = new Highlighter(ui_dialog->plainTextEdit->document()); + + if (insertHtmlDialog->exec() == QDialog::Accepted) + execCommand("insertHTML", ui_dialog->plainTextEdit->toPlainText()); + + delete hilite; +} + +void HtmlEditor::zoomOut() +{ + int percent = static_cast<int>(ui->webView->zoomFactor() * 100); + if (percent > 25) { + percent -= 25; + percent = 25 * (int((percent + 25 - 1) / 25)); + qreal factor = static_cast<qreal>(percent) / 100; + ui->webView->setZoomFactor(factor); + ui->actionZoomOut->setEnabled(percent > 25); + ui->actionZoomIn->setEnabled(true); + zoomSlider->setValue(percent); + } +} + +void HtmlEditor::zoomIn() +{ + int percent = static_cast<int>(ui->webView->zoomFactor() * 100); + if (percent < 400) { + percent += 25; + percent = 25 * (int(percent / 25)); + qreal factor = static_cast<qreal>(percent) / 100; + ui->webView->setZoomFactor(factor); + ui->actionZoomIn->setEnabled(percent < 400); + ui->actionZoomOut->setEnabled(true); + zoomSlider->setValue(percent); + } +} + +void HtmlEditor::editSelectAll() +{ + ui->webView->triggerPageAction(QWebPage::SelectAll); +} + +void HtmlEditor::execCommand(const QString &cmd) +{ + QWebFrame *frame = ui->webView->page()->mainFrame(); + QString js = QString("document.execCommand(\"%1\", false, null)").arg(cmd); + frame->evaluateJavaScript(js); +} + +void HtmlEditor::execCommand(const QString &cmd, const QString &arg) +{ + QWebFrame *frame = ui->webView->page()->mainFrame(); + QString js = QString("document.execCommand(\"%1\", false, \"%2\")").arg(cmd).arg(arg); + frame->evaluateJavaScript(js); +} + +bool HtmlEditor::queryCommandState(const QString &cmd) +{ + QWebFrame *frame = ui->webView->page()->mainFrame(); + QString js = QString("document.queryCommandState(\"%1\", false, null)").arg(cmd); + QVariant result = frame->evaluateJavaScript(js); + return result.toString().simplified().toLower() == "true"; +} + +void HtmlEditor::styleParagraph() +{ + execCommand("formatBlock", "p"); +} + +void HtmlEditor::styleHeading1() +{ + execCommand("formatBlock", "h1"); +} + +void HtmlEditor::styleHeading2() +{ + execCommand("formatBlock", "h2"); +} + +void HtmlEditor::styleHeading3() +{ + execCommand("formatBlock", "h3"); +} + +void HtmlEditor::styleHeading4() +{ + execCommand("formatBlock", "h4"); +} + +void HtmlEditor::styleHeading5() +{ + execCommand("formatBlock", "h5"); +} + +void HtmlEditor::styleHeading6() +{ + execCommand("formatBlock", "h6"); +} + +void HtmlEditor::stylePreformatted() +{ + execCommand("formatBlock", "pre"); +} + +void HtmlEditor::styleAddress() +{ + execCommand("formatBlock", "address"); +} + +void HtmlEditor::formatStrikeThrough() +{ + execCommand("strikeThrough"); +} + +void HtmlEditor::formatAlignLeft() +{ + execCommand("justifyLeft"); +} + +void HtmlEditor::formatAlignCenter() +{ + execCommand("justifyCenter"); +} + +void HtmlEditor::formatAlignRight() +{ + execCommand("justifyRight"); +} + +void HtmlEditor::formatAlignJustify() +{ + execCommand("justifyFull"); +} + +void HtmlEditor::formatIncreaseIndent() +{ + execCommand("indent"); +} + +void HtmlEditor::formatDecreaseIndent() +{ + execCommand("outdent"); +} + +void HtmlEditor::formatNumberedList() +{ + execCommand("insertOrderedList"); +} + +void HtmlEditor::formatBulletedList() +{ + execCommand("insertUnorderedList"); +} + +void HtmlEditor::formatFontName() +{ + QStringList families = QFontDatabase().families(); + bool ok = false; + QString family = QInputDialog::getItem(this, tr("Font"), tr("Select font:"), + families, 0, false, &ok); + + if (ok) + execCommand("fontName", family); +} + +void HtmlEditor::formatFontSize() +{ + QStringList sizes; + sizes << "xx-small"; + sizes << "x-small"; + sizes << "small"; + sizes << "medium"; + sizes << "large"; + sizes << "x-large"; + sizes << "xx-large"; + + bool ok = false; + QString size = QInputDialog::getItem(this, tr("Font Size"), tr("Select font size:"), + sizes, sizes.indexOf("medium"), false, &ok); + + if (ok) + execCommand("fontSize", QString::number(sizes.indexOf(size))); +} + +void HtmlEditor::formatTextColor() +{ + QColor color = QColorDialog::getColor(Qt::black, this); + if (color.isValid()) + execCommand("foreColor", color.name()); +} + +void HtmlEditor::formatBackgroundColor() +{ + QColor color = QColorDialog::getColor(Qt::white, this); + if (color.isValid()) + execCommand("hiliteColor", color.name()); +} + +#define FOLLOW_ENABLE(a1, a2) a1->setEnabled(ui->webView->pageAction(a2)->isEnabled()) +#define FOLLOW_CHECK(a1, a2) a1->setChecked(ui->webView->pageAction(a2)->isChecked()) + +void HtmlEditor::adjustActions() +{ + FOLLOW_ENABLE(ui->actionEditUndo, QWebPage::Undo); + FOLLOW_ENABLE(ui->actionEditRedo, QWebPage::Redo); + FOLLOW_ENABLE(ui->actionEditCut, QWebPage::Cut); + FOLLOW_ENABLE(ui->actionEditCopy, QWebPage::Copy); + FOLLOW_ENABLE(ui->actionEditPaste, QWebPage::Paste); + FOLLOW_CHECK(ui->actionFormatBold, QWebPage::ToggleBold); + FOLLOW_CHECK(ui->actionFormatItalic, QWebPage::ToggleItalic); + FOLLOW_CHECK(ui->actionFormatUnderline, QWebPage::ToggleUnderline); + + ui->actionFormatStrikethrough->setChecked(queryCommandState("strikeThrough")); + ui->actionFormatNumberedList->setChecked(queryCommandState("insertOrderedList")); + ui->actionFormatBulletedList->setChecked(queryCommandState("insertUnorderedList")); +} + +void HtmlEditor::adjustSource() +{ + setWindowModified(true); + sourceDirty = true; + + if (ui->tabWidget->currentIndex() == 1) + changeTab(1); +} + +void HtmlEditor::changeTab(int index) +{ + if (sourceDirty && (index == 1)) { + QString content = ui->webView->page()->mainFrame()->toHtml(); + ui->plainTextEdit->setPlainText(content); + sourceDirty = false; + } +} + +void HtmlEditor::openLink(const QUrl &url) +{ + QString msg = QString(tr("Open %1 ?")).arg(url.toString()); + if (QMessageBox::question(this, tr("Open link"), msg, + QMessageBox::Open | QMessageBox::Cancel) == + QMessageBox::Open) + QDesktopServices::openUrl(url); +} + +void HtmlEditor::changeZoom(int percent) +{ + ui->actionZoomOut->setEnabled(percent > 25); + ui->actionZoomIn->setEnabled(percent < 400); + qreal factor = static_cast<qreal>(percent) / 100; + ui->webView->setZoomFactor(factor); + + zoomLabel->setText(tr(" Zoom: %1% ").arg(percent)); + zoomSlider->setValue(percent); +} + +void HtmlEditor::closeEvent(QCloseEvent *e) +{ + if (maybeSave()) + e->accept(); + else + e->ignore(); +} + +bool HtmlEditor::load(const QString &f) +{ + if (!QFile::exists(f)) + return false; + QFile file(f); + if (!file.open(QFile::ReadOnly)) + return false; + + QByteArray data = file.readAll(); + ui->webView->setContent(data, "text/html"); + ui->webView->page()->setContentEditable(true); + ui->webView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); + connect(ui->webView, SIGNAL(linkClicked(QUrl)), SLOT(openLink(QUrl))); + + setCurrentFileName(f); + return true; +} + +void HtmlEditor::setCurrentFileName(const QString &fileName) +{ + this->fileName = fileName; + + QString shownName; + if (fileName.isEmpty()) + shownName = "untitled"; + else + shownName = QFileInfo(fileName).fileName(); + + setWindowTitle(tr("%1[*] - %2").arg(shownName).arg(tr("HTML Editor"))); + setWindowModified(false); + + bool allowSave = true; + if (fileName.isEmpty() || fileName.startsWith(QLatin1String(":/"))) + allowSave = false; + ui->actionFileSave->setEnabled(allowSave); +} diff --git a/htmleditor/htmleditor.h b/htmleditor/htmleditor.h new file mode 100644 index 0000000..bc99d39 --- /dev/null +++ b/htmleditor/htmleditor.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Graphics Dojo project on Qt Labs. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 or 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + + +#ifndef HTML_EDITOR_H +#define HTML_EDITOR_H + +#include <QMainWindow> +#include "highlighter.h" + +#if QT_VERSION < 0x040500 +#error You must use Qt >= 4.5.0! +#endif + +class Ui_MainWindow; +class Ui_Dialog; + +class QLabel; +class QSlider; +class QUrl; + +class HtmlEditor : public QMainWindow +{ + Q_OBJECT + +public: + HtmlEditor(QWidget *parent = 0); + ~HtmlEditor(); + +protected: + virtual void closeEvent(QCloseEvent *e); + +private: + void setupActions(); + void setupToolBar(); + void setupMenu(); + bool load(const QString &f); + bool maybeSave(); + void setCurrentFileName(const QString &fileName); + void execCommand(const QString&); + void execCommand(const QString &cmd, const QString &arg); + bool queryCommandState(const QString&); + +private slots: + void fileNew(); + void fileOpen(); + bool fileSave(); + bool fileSaveAs(); + void editSelectAll(); + void styleParagraph(); + void styleHeading1(); + void styleHeading2(); + void styleHeading3(); + void styleHeading4(); + void styleHeading5(); + void styleHeading6(); + void stylePreformatted(); + void styleAddress(); + void formatStrikeThrough(); + void formatAlignLeft(); + void formatAlignCenter(); + void formatAlignRight(); + void formatAlignJustify(); + void formatIncreaseIndent(); + void formatDecreaseIndent(); + void formatNumberedList(); + void formatBulletedList(); + void formatFontName(); + void formatFontSize(); + void formatTextColor(); + void formatBackgroundColor(); + void insertImage(); + void createLink(); + void insertHtml(); + void zoomOut(); + void zoomIn(); + void adjustActions(); + void adjustSource(); + void changeTab(int); + void openLink(const QUrl&); + void changeZoom(int); + +private: + Ui_MainWindow *ui; + QString fileName; + bool sourceDirty; + QLabel *zoomLabel; + QSlider *zoomSlider; + Highlighter *highlighter; + Ui_Dialog *ui_dialog; + QDialog *insertHtmlDialog; +}; + +#endif // HTML_EDITOR_H diff --git a/htmleditor/htmleditor.pro b/htmleditor/htmleditor.pro new file mode 100644 index 0000000..a38ee0f --- /dev/null +++ b/htmleditor/htmleditor.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +QT += network webkit + +TARGET = htmleditor +HEADERS = htmleditor.h highlighter.h +SOURCES = htmleditor.cpp main.cpp highlighter.cpp +FORMS = htmleditor.ui inserthtmldialog.ui +RESOURCES = htmleditor.qrc diff --git a/htmleditor/htmleditor.qrc b/htmleditor/htmleditor.qrc new file mode 100644 index 0000000..baf4314 --- /dev/null +++ b/htmleditor/htmleditor.qrc @@ -0,0 +1,32 @@ +<RCC> + <qresource prefix="/" > + <file>example.html</file> + <file>images/document-new.png</file> + <file>images/document-open.png</file> + <file>images/document-save.png</file> + <file>images/edit-copy.png</file> + <file>images/edit-cut.png</file> + <file>images/edit-paste.png</file> + <file>images/edit-redo.png</file> + <file>images/edit-select-all.png</file> + <file>images/edit-undo.png</file> + <file>images/format-indent-less.png</file> + <file>images/format-indent-more.png</file> + <file>images/format-justify-center.png</file> + <file>images/format-justify-fill.png</file> + <file>images/format-justify-left.png</file> + <file>images/format-justify-right.png</file> + <file>images/format-text-bold.png</file> + <file>images/format-text-italic.png</file> + <file>images/format-text-underline.png</file> + <file>images/format-text-strikethrough.png</file> + <file>images/bulleted-list.png</file> + <file>images/numbered-list.png</file> + <file>images/image-x-generic.png</file> + <file>qtlogo.png</file> + <file>images/text-html.png</file> + <file>images/list-remove.png</file> + <file>images/list-add.png</file> + <file>images/insert-html.png</file> + </qresource> +</RCC> diff --git a/htmleditor/htmleditor.ui b/htmleditor/htmleditor.ui new file mode 100644 index 0000000..2450320 --- /dev/null +++ b/htmleditor/htmleditor.ui @@ -0,0 +1,601 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>659</width> + <height>398</height> + </rect> + </property> + <property name="windowTitle"> + <string>HTML Editor</string> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="tabPosition"> + <enum>QTabWidget::South</enum> + </property> + <property name="tabShape"> + <enum>QTabWidget::Rounded</enum> + </property> + <property name="currentIndex"> + <number>0</number> + </property> + <property name="documentMode"> + <bool>true</bool> + </property> + <widget class="QWidget" name="tab"> + <attribute name="title"> + <string>Tab 1</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QWebView" name="webView"> + <property name="url"> + <url> + <string>about:blank</string> + </url> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_2"> + <attribute name="title"> + <string>Tab 2</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QPlainTextEdit" name="plainTextEdit"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>659</width> + <height>26</height> + </rect> + </property> + <widget class="QMenu" name="menu_File"> + <property name="title"> + <string>&File</string> + </property> + <addaction name="actionFileNew"/> + <addaction name="actionFileOpen"/> + <addaction name="actionFileSave"/> + <addaction name="actionFileSaveAs"/> + <addaction name="separator"/> + <addaction name="actionExit"/> + </widget> + <widget class="QMenu" name="menu_Edit"> + <property name="title"> + <string>&Edit</string> + </property> + <addaction name="actionEditUndo"/> + <addaction name="actionEditRedo"/> + <addaction name="separator"/> + <addaction name="actionEditCut"/> + <addaction name="actionEditCopy"/> + <addaction name="actionEditPaste"/> + <addaction name="separator"/> + <addaction name="actionEditSelectAll"/> + <addaction name="separator"/> + <addaction name="actionInsertImage"/> + <addaction name="actionCreateLink"/> + <addaction name="actionInsertHtml"/> + </widget> + <widget class="QMenu" name="menuF_ormat"> + <property name="title"> + <string>F&ormat</string> + </property> + <widget class="QMenu" name="menuSt_yle"> + <property name="title"> + <string>St&yle</string> + </property> + <addaction name="actionStyleParagraph"/> + <addaction name="actionStyleHeading1"/> + <addaction name="actionStyleHeading2"/> + <addaction name="actionStyleHeading3"/> + <addaction name="actionStyleHeading4"/> + <addaction name="actionStyleHeading5"/> + <addaction name="actionStyleHeading6"/> + <addaction name="actionStylePreformatted"/> + <addaction name="actionStyleAddress"/> + </widget> + <widget class="QMenu" name="menu_Align"> + <property name="title"> + <string>&Align</string> + </property> + <addaction name="actionFormatAlignLeft"/> + <addaction name="actionFormatAlignCenter"/> + <addaction name="actionFormatAlignRight"/> + <addaction name="actionFormatAlignJustify"/> + </widget> + <addaction name="menuSt_yle"/> + <addaction name="menu_Align"/> + <addaction name="separator"/> + <addaction name="actionFormatBold"/> + <addaction name="actionFormatItalic"/> + <addaction name="actionFormatUnderline"/> + <addaction name="actionFormatStrikethrough"/> + <addaction name="separator"/> + <addaction name="actionFormatIncreaseIndent"/> + <addaction name="actionFormatDecreaseIndent"/> + <addaction name="separator"/> + <addaction name="actionFormatNumberedList"/> + <addaction name="actionFormatBulletedList"/> + <addaction name="separator"/> + <addaction name="actionFormatFontName"/> + <addaction name="actionFormatFontSize"/> + <addaction name="separator"/> + <addaction name="actionFormatTextColor"/> + <addaction name="actionFormatBackgroundColor"/> + </widget> + <addaction name="menu_File"/> + <addaction name="menu_Edit"/> + <addaction name="menuF_ormat"/> + </widget> + <widget class="QToolBar" name="standardToolBar"> + <property name="windowTitle"> + <string>Standard</string> + </property> + <attribute name="toolBarArea"> + <enum>TopToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak"> + <bool>false</bool> + </attribute> + <addaction name="actionFileNew"/> + <addaction name="actionFileOpen"/> + <addaction name="actionFileSave"/> + <addaction name="separator"/> + <addaction name="actionEditUndo"/> + <addaction name="actionEditRedo"/> + <addaction name="separator"/> + <addaction name="actionEditCut"/> + <addaction name="actionEditCopy"/> + <addaction name="actionEditPaste"/> + <addaction name="separator"/> + <addaction name="actionZoomOut"/> + <addaction name="actionZoomIn"/> + </widget> + <widget class="QToolBar" name="formatToolBar"> + <property name="windowTitle"> + <string>Formatting</string> + </property> + <attribute name="toolBarArea"> + <enum>TopToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak"> + <bool>true</bool> + </attribute> + <addaction name="actionFormatBold"/> + <addaction name="actionFormatItalic"/> + <addaction name="actionFormatUnderline"/> + <addaction name="actionFormatStrikethrough"/> + <addaction name="separator"/> + <addaction name="actionFormatAlignLeft"/> + <addaction name="actionFormatAlignCenter"/> + <addaction name="actionFormatAlignRight"/> + <addaction name="actionFormatAlignJustify"/> + <addaction name="separator"/> + <addaction name="actionFormatDecreaseIndent"/> + <addaction name="actionFormatIncreaseIndent"/> + <addaction name="separator"/> + <addaction name="actionFormatNumberedList"/> + <addaction name="actionFormatBulletedList"/> + <addaction name="separator"/> + <addaction name="actionInsertImage"/> + <addaction name="actionCreateLink"/> + <addaction name="actionInsertHtml"/> + </widget> + <action name="actionFileNew"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/document-new.png</normaloff>:/images/document-new.png</iconset> + </property> + <property name="text"> + <string>&New</string> + </property> + <property name="shortcut"> + <string>Ctrl+N</string> + </property> + </action> + <action name="actionFileOpen"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/document-open.png</normaloff>:/images/document-open.png</iconset> + </property> + <property name="text"> + <string>&Open...</string> + </property> + <property name="shortcut"> + <string>Ctrl+O</string> + </property> + </action> + <action name="actionFileSave"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/document-save.png</normaloff>:/images/document-save.png</iconset> + </property> + <property name="text"> + <string>&Save</string> + </property> + <property name="shortcut"> + <string>Ctrl+S</string> + </property> + </action> + <action name="actionFileSaveAs"> + <property name="text"> + <string>Save &As...</string> + </property> + </action> + <action name="actionEditUndo"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/edit-undo.png</normaloff>:/images/edit-undo.png</iconset> + </property> + <property name="text"> + <string>&Undo</string> + </property> + <property name="shortcut"> + <string>Ctrl+Z</string> + </property> + </action> + <action name="actionEditRedo"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/edit-redo.png</normaloff>:/images/edit-redo.png</iconset> + </property> + <property name="text"> + <string>&Redo</string> + </property> + <property name="shortcut"> + <string>Ctrl+Y</string> + </property> + </action> + <action name="actionEditCut"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/edit-cut.png</normaloff>:/images/edit-cut.png</iconset> + </property> + <property name="text"> + <string>Cu&t</string> + </property> + <property name="shortcut"> + <string>Ctrl+X</string> + </property> + </action> + <action name="actionEditCopy"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/edit-copy.png</normaloff>:/images/edit-copy.png</iconset> + </property> + <property name="text"> + <string>&Copy</string> + </property> + <property name="shortcut"> + <string>Ctrl+C</string> + </property> + </action> + <action name="actionEditPaste"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/edit-paste.png</normaloff>:/images/edit-paste.png</iconset> + </property> + <property name="text"> + <string>&Paste</string> + </property> + <property name="shortcut"> + <string>Ctrl+V</string> + </property> + </action> + <action name="actionEditSelectAll"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/edit-select-all.png</normaloff>:/images/edit-select-all.png</iconset> + </property> + <property name="text"> + <string>Select A&ll</string> + </property> + <property name="shortcut"> + <string>Ctrl+A</string> + </property> + </action> + <action name="actionFormatBold"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/format-text-bold.png</normaloff>:/images/format-text-bold.png</iconset> + </property> + <property name="text"> + <string>&Bold</string> + </property> + <property name="shortcut"> + <string>Ctrl+B</string> + </property> + </action> + <action name="actionFormatItalic"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/format-text-italic.png</normaloff>:/images/format-text-italic.png</iconset> + </property> + <property name="text"> + <string>&Italic</string> + </property> + <property name="shortcut"> + <string>Ctrl+I</string> + </property> + </action> + <action name="actionFormatUnderline"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/format-text-underline.png</normaloff>:/images/format-text-underline.png</iconset> + </property> + <property name="text"> + <string>&Underline</string> + </property> + <property name="shortcut"> + <string>Ctrl+U</string> + </property> + </action> + <action name="actionFormatStrikethrough"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/format-text-strikethrough.png</normaloff>:/images/format-text-strikethrough.png</iconset> + </property> + <property name="text"> + <string>&Strikethrough</string> + </property> + </action> + <action name="actionFormatAlignLeft"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/format-justify-left.png</normaloff>:/images/format-justify-left.png</iconset> + </property> + <property name="text"> + <string>Align &Left</string> + </property> + </action> + <action name="actionFormatAlignCenter"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/format-justify-center.png</normaloff>:/images/format-justify-center.png</iconset> + </property> + <property name="text"> + <string>Align &Center</string> + </property> + </action> + <action name="actionFormatAlignRight"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/format-justify-right.png</normaloff>:/images/format-justify-right.png</iconset> + </property> + <property name="text"> + <string>Align &Right</string> + </property> + </action> + <action name="actionFormatAlignJustify"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/format-justify-fill.png</normaloff>:/images/format-justify-fill.png</iconset> + </property> + <property name="text"> + <string>Align &Justify</string> + </property> + </action> + <action name="actionFormatIncreaseIndent"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/format-indent-more.png</normaloff>:/images/format-indent-more.png</iconset> + </property> + <property name="text"> + <string>I&ncrease Indent</string> + </property> + </action> + <action name="actionFormatDecreaseIndent"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/format-indent-less.png</normaloff>:/images/format-indent-less.png</iconset> + </property> + <property name="text"> + <string>&Decrease Indent</string> + </property> + </action> + <action name="actionFormatBulletedList"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/bulleted-list.png</normaloff>:/images/bulleted-list.png</iconset> + </property> + <property name="text"> + <string>Bulle&ted List</string> + </property> + </action> + <action name="actionFormatNumberedList"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/numbered-list.png</normaloff>:/images/numbered-list.png</iconset> + </property> + <property name="text"> + <string>&Numbered List</string> + </property> + </action> + <action name="actionInsertImage"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/image-x-generic.png</normaloff>:/images/image-x-generic.png</iconset> + </property> + <property name="text"> + <string>Insert &Image...</string> + </property> + </action> + <action name="actionCreateLink"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/text-html.png</normaloff>:/images/text-html.png</iconset> + </property> + <property name="text"> + <string>Create Link...</string> + </property> + </action> + <action name="actionZoomOut"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/list-remove.png</normaloff>:/images/list-remove.png</iconset> + </property> + <property name="text"> + <string>Zoom Out</string> + </property> + </action> + <action name="actionZoomIn"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/list-add.png</normaloff>:/images/list-add.png</iconset> + </property> + <property name="text"> + <string>Zoom In</string> + </property> + </action> + <action name="actionExit"> + <property name="text"> + <string>E&xit</string> + </property> + <property name="shortcut"> + <string>Ctrl+Q</string> + </property> + </action> + <action name="actionStyleParagraph"> + <property name="text"> + <string>&Paragraph</string> + </property> + </action> + <action name="actionStyleHeading1"> + <property name="text"> + <string>Heading &1</string> + </property> + </action> + <action name="actionStyleHeading2"> + <property name="text"> + <string>Heading &2</string> + </property> + </action> + <action name="actionStyleHeading3"> + <property name="text"> + <string>Heading &3</string> + </property> + </action> + <action name="actionStyleHeading4"> + <property name="text"> + <string>Heading &4</string> + </property> + </action> + <action name="actionStyleHeading5"> + <property name="text"> + <string>Heading &5</string> + </property> + </action> + <action name="actionStyleHeading6"> + <property name="text"> + <string>Heading &6</string> + </property> + </action> + <action name="actionStylePreformatted"> + <property name="text"> + <string>Pre&formatted</string> + </property> + </action> + <action name="actionStyleAddress"> + <property name="text"> + <string>&Address</string> + </property> + </action> + <action name="actionFormatFontName"> + <property name="text"> + <string>&Font Name...</string> + </property> + </action> + <action name="actionFormatTextColor"> + <property name="text"> + <string>Text &Color...</string> + </property> + </action> + <action name="actionFormatBackgroundColor"> + <property name="text"> + <string>Bac&kground Color...</string> + </property> + </action> + <action name="actionFormatFontSize"> + <property name="text"> + <string>Font Si&ze...</string> + </property> + </action> + <action name="actionInsertHtml"> + <property name="icon"> + <iconset resource="htmleditor.qrc"> + <normaloff>:/images/insert-html.png</normaloff>:/images/insert-html.png</iconset> + </property> + <property name="text"> + <string>Insert HTML...</string> + </property> + <property name="toolTip"> + <string>Insert HTML</string> + </property> + </action> + </widget> + <customwidgets> + <customwidget> + <class>QWebView</class> + <extends>QWidget</extends> + <header>QtWebKit/QWebView</header> + </customwidget> + </customwidgets> + <resources> + <include location="htmleditor.qrc"/> + </resources> + <connections/> +</ui> diff --git a/htmleditor/images/bulleted-list.png b/htmleditor/images/bulleted-list.png Binary files differnew file mode 100644 index 0000000..69708f1 --- /dev/null +++ b/htmleditor/images/bulleted-list.png diff --git a/htmleditor/images/document-new.png b/htmleditor/images/document-new.png Binary files differnew file mode 100644 index 0000000..e3808a1 --- /dev/null +++ b/htmleditor/images/document-new.png diff --git a/htmleditor/images/document-open.png b/htmleditor/images/document-open.png Binary files differnew file mode 100644 index 0000000..254a6b8 --- /dev/null +++ b/htmleditor/images/document-open.png diff --git a/htmleditor/images/document-save-as.png b/htmleditor/images/document-save-as.png Binary files differnew file mode 100644 index 0000000..340a87e --- /dev/null +++ b/htmleditor/images/document-save-as.png diff --git a/htmleditor/images/document-save.png b/htmleditor/images/document-save.png Binary files differnew file mode 100644 index 0000000..a94e0ea --- /dev/null +++ b/htmleditor/images/document-save.png diff --git a/htmleditor/images/edit-copy.png b/htmleditor/images/edit-copy.png Binary files differnew file mode 100644 index 0000000..345b2f1 --- /dev/null +++ b/htmleditor/images/edit-copy.png diff --git a/htmleditor/images/edit-cut.png b/htmleditor/images/edit-cut.png Binary files differnew file mode 100644 index 0000000..7017d1b --- /dev/null +++ b/htmleditor/images/edit-cut.png diff --git a/htmleditor/images/edit-paste.png b/htmleditor/images/edit-paste.png Binary files differnew file mode 100644 index 0000000..f6a625c --- /dev/null +++ b/htmleditor/images/edit-paste.png diff --git a/htmleditor/images/edit-redo.png b/htmleditor/images/edit-redo.png Binary files differnew file mode 100644 index 0000000..576cfc7 --- /dev/null +++ b/htmleditor/images/edit-redo.png diff --git a/htmleditor/images/edit-select-all.png b/htmleditor/images/edit-select-all.png Binary files differnew file mode 100644 index 0000000..e6331c6 --- /dev/null +++ b/htmleditor/images/edit-select-all.png diff --git a/htmleditor/images/edit-undo.png b/htmleditor/images/edit-undo.png Binary files differnew file mode 100644 index 0000000..f37c696 --- /dev/null +++ b/htmleditor/images/edit-undo.png diff --git a/htmleditor/images/format-indent-less.png b/htmleditor/images/format-indent-less.png Binary files differnew file mode 100644 index 0000000..5292012 --- /dev/null +++ b/htmleditor/images/format-indent-less.png diff --git a/htmleditor/images/format-indent-more.png b/htmleditor/images/format-indent-more.png Binary files differnew file mode 100644 index 0000000..ad2b527 --- /dev/null +++ b/htmleditor/images/format-indent-more.png diff --git a/htmleditor/images/format-justify-center.png b/htmleditor/images/format-justify-center.png Binary files differnew file mode 100644 index 0000000..0777a9a --- /dev/null +++ b/htmleditor/images/format-justify-center.png diff --git a/htmleditor/images/format-justify-fill.png b/htmleditor/images/format-justify-fill.png Binary files differnew file mode 100644 index 0000000..0ce4013 --- /dev/null +++ b/htmleditor/images/format-justify-fill.png diff --git a/htmleditor/images/format-justify-left.png b/htmleditor/images/format-justify-left.png Binary files differnew file mode 100644 index 0000000..a8e1ca8 --- /dev/null +++ b/htmleditor/images/format-justify-left.png diff --git a/htmleditor/images/format-justify-right.png b/htmleditor/images/format-justify-right.png Binary files differnew file mode 100644 index 0000000..8228d81 --- /dev/null +++ b/htmleditor/images/format-justify-right.png diff --git a/htmleditor/images/format-text-bold.png b/htmleditor/images/format-text-bold.png Binary files differnew file mode 100644 index 0000000..7166e3d --- /dev/null +++ b/htmleditor/images/format-text-bold.png diff --git a/htmleditor/images/format-text-italic.png b/htmleditor/images/format-text-italic.png Binary files differnew file mode 100644 index 0000000..ef68fb3 --- /dev/null +++ b/htmleditor/images/format-text-italic.png diff --git a/htmleditor/images/format-text-strikethrough.png b/htmleditor/images/format-text-strikethrough.png Binary files differnew file mode 100644 index 0000000..e4ca573 --- /dev/null +++ b/htmleditor/images/format-text-strikethrough.png diff --git a/htmleditor/images/format-text-underline.png b/htmleditor/images/format-text-underline.png Binary files differnew file mode 100644 index 0000000..d33422b --- /dev/null +++ b/htmleditor/images/format-text-underline.png diff --git a/htmleditor/images/image-x-generic.png b/htmleditor/images/image-x-generic.png Binary files differnew file mode 100644 index 0000000..10f4671 --- /dev/null +++ b/htmleditor/images/image-x-generic.png diff --git a/htmleditor/images/insert-html.png b/htmleditor/images/insert-html.png Binary files differnew file mode 100644 index 0000000..72c7e9c --- /dev/null +++ b/htmleditor/images/insert-html.png diff --git a/htmleditor/images/list-add.png b/htmleditor/images/list-add.png Binary files differnew file mode 100644 index 0000000..306d3d8 --- /dev/null +++ b/htmleditor/images/list-add.png diff --git a/htmleditor/images/list-remove.png b/htmleditor/images/list-remove.png Binary files differnew file mode 100644 index 0000000..45e5c2a --- /dev/null +++ b/htmleditor/images/list-remove.png diff --git a/htmleditor/images/numbered-list.png b/htmleditor/images/numbered-list.png Binary files differnew file mode 100644 index 0000000..e9f4001 --- /dev/null +++ b/htmleditor/images/numbered-list.png diff --git a/htmleditor/images/text-html.png b/htmleditor/images/text-html.png Binary files differnew file mode 100644 index 0000000..51beaff --- /dev/null +++ b/htmleditor/images/text-html.png diff --git a/htmleditor/inserthtmldialog.ui b/htmleditor/inserthtmldialog.ui new file mode 100644 index 0000000..9f7cec1 --- /dev/null +++ b/htmleditor/inserthtmldialog.ui @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Dialog</class> + <widget class="QDialog" name="Dialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>426</width> + <height>288</height> + </rect> + </property> + <property name="windowTitle"> + <string>Insert HTML</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>HTML Code:</string> + </property> + </widget> + </item> + <item> + <widget class="QPlainTextEdit" name="plainTextEdit"/> + </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/> +</ui> diff --git a/htmleditor/main.cpp b/htmleditor/main.cpp new file mode 100644 index 0000000..f98d35f --- /dev/null +++ b/htmleditor/main.cpp @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Graphics Dojo project on Qt Labs. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 or 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + + +#include "htmleditor.h" +#include <QApplication> + +int main(int argc, char ** argv) +{ + Q_INIT_RESOURCE(htmleditor); + + QApplication a(argc, argv); + HtmlEditor editor; + editor.show(); + return a.exec(); +} diff --git a/htmleditor/qtlogo.png b/htmleditor/qtlogo.png Binary files differnew file mode 100644 index 0000000..1e7ed4c --- /dev/null +++ b/htmleditor/qtlogo.png |