aboutsummaryrefslogtreecommitdiff
path: root/browsertab.cpp
diff options
context:
space:
mode:
authorFelix (xq) Queißner <git@mq32.de>2020-06-06 14:22:53 +0200
committerFelix (xq) Queißner <git@mq32.de>2020-06-06 14:22:53 +0200
commitbcda97a2e17f6e1366cfe5b03bd0b407d4484255 (patch)
tree2f485e8ff94e26a4c8e1b2e0310c396dbb23c5a0 /browsertab.cpp
parent7e7ac47308d88aa3a67836937a6888b7b3d90d56 (diff)
downloadkristall-bcda97a2e17f6e1366cfe5b03bd0b407d4484255.tar.gz
Reworks document rendering: Now generates QTextDocument directly instead of using HTML inbetween.
Diffstat (limited to 'browsertab.cpp')
-rw-r--r--browsertab.cpp279
1 files changed, 172 insertions, 107 deletions
diff --git a/browsertab.cpp b/browsertab.cpp
index 005926d..153e19f 100644
--- a/browsertab.cpp
+++ b/browsertab.cpp
@@ -9,6 +9,8 @@
#include <QDockWidget>
#include <QImage>
#include <QPixmap>
+#include <QTextList>
+#include <QTextBlock>
#include <QGraphicsPixmapItem>
#include <QGraphicsTextItem>
@@ -34,28 +36,11 @@ BrowserTab::BrowserTab(MainWindow * mainWindow) :
this->updateUI();
+ this->ui->graphics_browser->setVisible(false);
+ this->ui->text_browser->setVisible(false);
+
this->ui->graphics_browser->setScene(&graphics_scene);
- this->ui->text_browser->document()->setDocumentMargin(55.0);
- this->ui->text_browser->document()->setDefaultStyleSheet(
- R"css(
- h1 {
- color: red;
- }
- h2 {
- color: green;
- }
- h3 {
- color: gold;
- }
- a {
- color: blue;
- }
- ul {
- -qt-list-indent: 1;
- type: square;
- }
- )css");
}
BrowserTab::~BrowserTab()
@@ -119,27 +104,6 @@ void BrowserTab::on_url_bar_returnPressed()
this->navigateTo(this->ui->url_bar->text());
}
-void BrowserTab::on_content_titleChanged(const QString &title)
-{
- this->setWindowTitle(title);
-}
-
-void BrowserTab::on_content_loadStarted()
-{
- this->ui->refresh_button->setEnabled(false);
-}
-
-void BrowserTab::on_content_loadFinished(bool ok)
-{
- this->ui->refresh_button->setEnabled(true);
-}
-
-void BrowserTab::on_content_urlChanged(const QUrl &url)
-{
- // qDebug() << "url changed to" << url;
- // this->ui->url_bar->setText(url.toString());
-}
-
void BrowserTab::on_refresh_button_clicked()
{
if(current_location.isValid())
@@ -157,32 +121,42 @@ void BrowserTab::on_gemini_complete(const QByteArray &data, const QString &mime)
this->ui->text_browser->setVisible(mime.startsWith("text/"));
this->ui->graphics_browser->setVisible(mime.startsWith("image/"));
+ std::unique_ptr<QTextDocument> document;
+
+ this->outline.clear();
+
if(mime.startsWith("text/gemini")) {
- auto html = translateGeminiToHtml(data, this->outline);
- this->ui->text_browser->setHtml(html);
+ document = translateGemini(data, this->current_location, this->outline);
}
else if(mime.startsWith("text/html")) {
- this->ui->text_browser->setHtml(QString::fromUtf8(data));
+ document = std::make_unique<QTextDocument>();
+ document->setHtml(QString::fromUtf8(data));
}
#if QT_CONFIG(textmarkdownreader)
else if(mime.startsWith("text/markdown")) {
- this->ui->text_browser->setMarkdown(QString::fromUtf8(data));
+ document = std::make_unique<QTextDocument>();
+ document->setMarkdown(QString::fromUtf8(data));
}
#endif
else if(mime.startsWith("text/")) {
- this->ui->text_browser->setPlainText(QString::fromUtf8(data));
+ QFont monospace;
+ monospace.setFamily("monospace");
+
+ document = std::make_unique<QTextDocument>();
+ document->setDefaultFont(monospace);
+ document->setPlainText(QString::fromUtf8(data));
}
else if(mime.startsWith("image/")) {
QImage img;
if(img.loadFromData(data, nullptr))
{
- auto * item = this->graphics_scene.addPixmap(QPixmap::fromImage(img));
+ this->graphics_scene.addPixmap(QPixmap::fromImage(img));
}
else
{
- auto * item = this->graphics_scene.addText("Failed to load picture!");
+ this->graphics_scene.addText("Failed to load picture!");
}
this->ui->graphics_browser->fitInView(graphics_scene.sceneRect(), Qt::KeepAspectRatio);
@@ -193,8 +167,16 @@ void BrowserTab::on_gemini_complete(const QByteArray &data, const QString &mime)
this->ui->text_browser->setText(QString("Unsupported Mime: %1").arg(mime));
}
+ this->ui->text_browser->setDocument(document.get());
+ this->current_document = std::move(document);
+
this->pushToHistory(this->current_location);
+ emit this->locationChanged(this->current_location);
+
+ QString title = this->current_location.toString();
+ emit this->titleChanged(title);
+
this->successfully_loaded = true;
this->updateUI();
}
@@ -386,30 +368,105 @@ void BrowserTab::on_text_browser_highlighted(const QUrl &url)
this->mainWindow->setUrlPreview(real_url);
}
+void BrowserTab::on_back_button_clicked()
+{
+
+}
+
+void BrowserTab::on_forward_button_clicked()
+{
+
+}
+
void BrowserTab::updateUI()
{
this->ui->back_button->setEnabled(this->history.canGoBack());
this->ui->forward_button->setEnabled(this->history.canGoForward());
- this->ui->refresh_button->setEnabled(this->successfully_loaded);
+ this->ui->refresh_button->setVisible(not this->gemini_client.isInProgress());
+ this->ui->stop_button->setVisible(this->gemini_client.isInProgress());
this->ui->fav_button->setEnabled(this->successfully_loaded);
this->ui->fav_button->setChecked(this->mainWindow->favourites.contains(this->current_location));
}
-QByteArray BrowserTab::translateGeminiToHtml(const QByteArray &input, DocumentOutlineModel & outline)
+QByteArray trim_whitespace(QByteArray items)
{
- QByteArray result;
- result.append(QString(R"html(<!doctype html>
-<html>
- <head>
- <meta charset="UTF-8">
- </head>
- <body>
-)html").toUtf8());
+ int start = 0;
+ while(start < items.size() and isspace(items.at(start))) {
+ start += 1;
+ }
+ int end = items.size() - 1;
+ while(end > 0 and isspace(items.at(end))) {
+ end -= 1;
+ }
+ return items.mid(start, end - start + 1);
+}
+
+std::unique_ptr<QTextDocument> BrowserTab::translateGemini(const QByteArray &input, QUrl const & root_url, DocumentOutlineModel &outline)
+{
+ QFont preformatted_font;
+ preformatted_font.setFamily("monospace");
+ preformatted_font.setPointSizeF(10.0);
+
+ QFont standard_font;
+ standard_font.setFamily("sans");
+ standard_font.setPointSizeF(10.0);
+
+ QFont h1_font;
+ h1_font.setFamily("sans");
+ h1_font.setBold(true);
+ h1_font.setPointSizeF(20.0);
+
+ QFont h2_font;
+ h2_font.setFamily("sans");
+ h2_font.setBold(true);
+ h2_font.setPointSizeF(15.0);
+
+ QFont h3_font;
+ h3_font.setFamily("sans");
+ h3_font.setBold(true);
+ h3_font.setPointSizeF(12.0);
+
+ QTextCharFormat preformatted;
+ preformatted.setFont(preformatted_font);
+
+ QTextCharFormat standard;
+ standard.setFont(standard_font);
+
+ QTextCharFormat standard_link;
+ standard_link.setFont(standard_font);
+ standard_link.setForeground(QBrush(QColor(0,128,255)));
+
+ QTextCharFormat external_link;
+ external_link.setFont(standard_font);
+ external_link.setForeground(QBrush(QColor(0,0,255)));
+
+ QTextCharFormat cross_protocol_link;
+ cross_protocol_link.setFont(standard_font);
+ cross_protocol_link.setForeground(QBrush(QColor(128,0,255)));
+
+ QTextCharFormat standard_h1;
+ standard_h1.setFont(h1_font);
+ standard_h1.setForeground(QBrush(QColor(255,0,0)));
+
+ QTextCharFormat standard_h2;
+ standard_h2.setFont(h2_font);
+ standard_h2.setForeground(QBrush(QColor(0,128,0)));
+
+ QTextCharFormat standard_h3;
+ standard_h3.setFont(h3_font);
+ standard_h3.setForeground(QBrush(QColor(32,255,0)));
+
+ std::unique_ptr<QTextDocument> result = std::make_unique<QTextDocument>();
+ result->setDocumentMargin(55.0);
+
+ QTextCursor cursor { result.get() };
+
+ QTextBlockFormat non_list_format = cursor.blockFormat();
bool verbatim = false;
- bool listing = false;
+ QTextList * current_list = nullptr;
outline.beginBuild();
@@ -417,54 +474,53 @@ QByteArray BrowserTab::translateGeminiToHtml(const QByteArray &input, DocumentOu
for(auto const & line : lines)
{
if(verbatim) {
- if(listing) {
- result.append("</ul>\n");
- }
- listing = false;
-
if(line.startsWith("```")) {
verbatim = false;
- result.append("</pre><br>\n");
}
else {
- result.append(line);
- result.append("\n");
+ cursor.setCharFormat(preformatted);
+ cursor.insertText(line + "\n");
}
} else {
if(line.startsWith("*")) {
- if(not listing) {
- result.append("<ul>\n");
+ if(current_list == nullptr) {
+ cursor.deletePreviousChar();
+ current_list = cursor.insertList(QTextListFormat::ListDisc);
+ } else {
+ cursor.insertBlock();
}
- listing = true;
- result.append("<li>");
- result.append(line.mid(1).trimmed());
- result.append("</li>");
+ QString item = trim_whitespace(line.mid(1));
+
+ cursor.insertText(item, standard);
continue;
} else {
- if(listing) {
- result.append("</ul>\n");
+ if(current_list != nullptr) {
+ cursor.insertBlock();
+ cursor.setBlockFormat(non_list_format);
}
- listing = false;
+ current_list = nullptr;
}
if(line.startsWith("###")) {
- result.append("<h3>");
- outline.appendH3(line.mid(3).trimmed());
- result.append(line.mid(3).trimmed());
- result.append("</h3>");
+ auto heading = trim_whitespace(line.mid(3));
+
+ cursor.insertText(heading, standard_h3);
+ cursor.insertBlock();
+ outline.appendH3(heading);
}
else if(line.startsWith("##")) {
- result.append("<h2>");
- outline.appendH2(line.mid(2).trimmed());
- result.append(line.mid(2).trimmed());
- result.append("</h2>");
+ auto heading = trim_whitespace(line.mid(2));
+
+ cursor.insertText(heading, standard_h2);
+ cursor.insertBlock();
+ outline.appendH2(heading);
}
else if(line.startsWith("#")) {
- result.append("<h1>");
- outline.appendH1(line.mid(1).trimmed());
- result.append(line.mid(1).trimmed());
- result.append("</h1>");
+ auto heading = trim_whitespace(line.mid(1));
+
+ cursor.insertText(heading, standard_h1);
+ outline.appendH1(heading);
}
else if(line.startsWith("=>")) {
auto const part = line.mid(2).trimmed();
@@ -480,39 +536,48 @@ QByteArray BrowserTab::translateGeminiToHtml(const QByteArray &input, DocumentOu
}
if(index > 0) {
- link = part.mid(0, index);
- title = part.mid(index + 1);
+ link = trim_whitespace(part.mid(0, index));
+ title = trim_whitespace(part.mid(index + 1));
} else {
- link = part;
- title = part;
+ link = trim_whitespace(part);
+ title = trim_whitespace(part);
}
+ auto local_url = QUrl(link);
+
+ auto absolute_url = root_url.resolved(QUrl(link));
+
// qDebug() << link << title;
- result.append("<a href=\"");
- result.append(link);
- result.append("\">");
- result.append(title);
- result.append("</a><br>\n");
+ auto fmt = standard_link;
+ if(not local_url.isRelative()) {
+ fmt = external_link;
+ }
+
+ QString suffix = "";
+ if(absolute_url.scheme() != root_url.scheme()) {
+ suffix = " [" + absolute_url.scheme().toUpper() + "]";
+ fmt = cross_protocol_link;
+ }
+
+ fmt.setAnchor(true);
+ fmt.setAnchorHref(absolute_url.toString());
+
+ if(local_url.isRelative()) {
+ cursor.insertText("→ " + title + suffix + "\n", fmt);
+ } else {
+ cursor.insertText("⇒ " + title + suffix + "\n", fmt);
+ }
}
else if(line.startsWith("```")) {
verbatim = true;
- result.append("<pre>");
}
else {
- result.append(line);
- result.append("<br>\n");
+ cursor.insertText(line + "\n", standard);
}
}
}
outline.endBuild();
-
- result.append(QString(R"html(
- </body>
-</html>
-)html").toUtf8());
return result;
}
-
-