Improves gopher map rendering with icons and monospace font, adds status bar with more infos, fixes file dialog for older qt versions.

This commit is contained in:
Felix (xq) Queißner 2020-06-08 18:36:35 +02:00
parent 75deaa0c85
commit 8c9480f6fc
24 changed files with 159 additions and 52 deletions

View File

@ -11,6 +11,7 @@ Kristall Changelog
- Added "go to home" menu icogin
- Added support for video/* and audio/* via QMediaPlayer
- Added support for file:// scheme
- Added status bar with loading time, file size and mime type
== 0.1
- Initial release

BIN
screenshots/mac/rp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

View File

@ -4,6 +4,8 @@
#include "geminirenderer.hpp"
#include "settingsdialog.hpp"
#include "gophermaprenderer.hpp"
#include "ioutil.hpp"
#include <cassert>
#include <QTabWidget>
#include <QMenu>
@ -67,6 +69,8 @@ void BrowserTab::navigateTo(const QUrl &url, PushToHistory mode)
return;
}
this->timer.start();
this->current_location = url;
this->ui->url_bar->setText(url.toString());
@ -233,23 +237,6 @@ void BrowserTab::on_requestFailed(const QString &reason)
this->setErrorMessage(QString("Request failed:\n%1").arg(reason));
}
QString size_human(int size)
{
float num = size;
QStringList list;
list << "KB" << "MB" << "GB" << "TB";
QStringListIterator i(list);
QString unit("bytes");
while(num >= 1024.0 && i.hasNext())
{
unit = i.next();
num /= 1024.0;
}
return QString().setNum(num,'f',2)+" "+unit;
}
void BrowserTab::on_requestComplete(const QByteArray &data, const QString &mime)
{
qDebug() << "Loaded" << data.length() << "bytes of type" << mime;
@ -339,7 +326,7 @@ Use the *File* menu to save the file to your local disk or navigate somewhere el
Info:
MIME Type: %1
File Size: %2
)md").arg(mime).arg(size_human(data.size())));
)md").arg(mime).arg(IoUtil::size_human(data.size())));
}
assert((document != nullptr) == (doc_type == Text));
@ -356,6 +343,8 @@ File Size: %2
QString title = this->current_location.toString();
emit this->titleChanged(title);
emit this->fileLoaded(data.size(), mime, this->timer.elapsed());
this->successfully_loaded = true;
if(this->push_to_history_after_load) {
@ -520,10 +509,15 @@ void BrowserTab::on_text_browser_anchorClicked(const QUrl &url)
void BrowserTab::on_text_browser_highlighted(const QUrl &url)
{
QUrl real_url = url;
if(real_url.isRelative())
real_url = this->current_location.resolved(url);
this->mainWindow->setUrlPreview(real_url);
if(url.isValid()) {
QUrl real_url = url;
if(real_url.isRelative())
real_url = this->current_location.resolved(url);
this->mainWindow->setUrlPreview(real_url);
}
else {
this->mainWindow->setUrlPreview(QUrl { });
}
}
void BrowserTab::on_stop_button_clicked()

View File

@ -7,6 +7,7 @@
#include <QGraphicsScene>
#include <QTextDocument>
#include <QNetworkAccessManager>
#include <QElapsedTimer>
#include "geminiclient.hpp"
#include "documentoutlinemodel.hpp"
@ -54,6 +55,7 @@ public:
signals:
void titleChanged(QString const & title);
void locationChanged(QUrl const & url);
void fileLoaded(qint64 fileSize, QString const & mime, int msec);
private slots:
void on_url_bar_returnPressed();
@ -123,6 +125,7 @@ public:
QByteArray current_buffer;
QString current_mime;
QElapsedTimer timer;
};
#endif // BROWSERTAB_HPP

View File

@ -7,6 +7,7 @@
#include <QTextImageFormat>
#include <QDebug>
#include <QImage>
//Canonical Types
//0 Text File
@ -31,11 +32,11 @@
std::unique_ptr<QTextDocument> GophermapRenderer::render(const QByteArray &input, const QUrl &root_url, const DocumentStyle &themed_style)
{
QTextCharFormat standard;
standard.setFont(themed_style.standard_font);
standard.setForeground(themed_style.standard_color);
standard.setFont(themed_style.preformatted_font);
standard.setForeground(themed_style.preformatted_color);
QTextCharFormat standard_link;
standard_link.setFont(themed_style.standard_font);
standard_link.setFont(themed_style.preformatted_font);
standard_link.setForeground(QBrush(themed_style.internal_link_color));
QTextCharFormat external_link;
@ -45,21 +46,34 @@ std::unique_ptr<QTextDocument> GophermapRenderer::render(const QByteArray &input
std::unique_ptr<QTextDocument> result = std::make_unique<QTextDocument>();
result->setDocumentMargin(themed_style.margin);
result->addResource(QTextDocument::ImageResource, QUrl("gopher/binary"), QVariant::fromValue(QImage(":/icons/gopher/binary.svg")));
result->addResource(QTextDocument::ImageResource, QUrl("gopher/directory"), QVariant::fromValue(QImage(":/icons/gopher/directory.svg")));
result->addResource(QTextDocument::ImageResource, QUrl("gopher/dns"), QVariant::fromValue(QImage(":/icons/gopher/dns.svg")));
result->addResource(QTextDocument::ImageResource, QUrl("gopher/error"), QVariant::fromValue(QImage(":/icons/gopher/error.svg")));
result->addResource(QTextDocument::ImageResource, QUrl("gopher/gif"), QVariant::fromValue(QImage(":/icons/gopher/gif.svg")));
result->addResource(QTextDocument::ImageResource, QUrl("gopher/html"), QVariant::fromValue(QImage(":/icons/gopher/html.svg")));
result->addResource(QTextDocument::ImageResource, QUrl("gopher/image"), QVariant::fromValue(QImage(":/icons/gopher/image.svg")));
result->addResource(QTextDocument::ImageResource, QUrl("gopher/mirror"), QVariant::fromValue(QImage(":/icons/gopher/mirror.svg")));
result->addResource(QTextDocument::ImageResource, QUrl("gopher/search"), QVariant::fromValue(QImage(":/icons/gopher/search.svg")));
result->addResource(QTextDocument::ImageResource, QUrl("gopher/sound"), QVariant::fromValue(QImage(":/icons/gopher/sound.svg")));
result->addResource(QTextDocument::ImageResource, QUrl("gopher/telnet"), QVariant::fromValue(QImage(":/icons/gopher/telnet.svg")));
result->addResource(QTextDocument::ImageResource, QUrl("gopher/text"), QVariant::fromValue(QImage(":/icons/gopher/text.svg")));
QTextCursor cursor{result.get()};
QTextBlockFormat non_list_format = cursor.blockFormat();
QList<QByteArray> lines = input.split('\n');
for (auto const & line : lines)
for (auto const &line : lines)
{
if (line.length() < 2) // skip lines without
continue;
if(line[line.size() - 1] != '\r')
if (line[line.size() - 1] != '\r')
continue;
auto items = line.mid(1, line.length() - 2).split('\t');
if(items.size() < 2) // invalid
if (items.size() < 2) // invalid
continue;
QString icon;
@ -72,22 +86,22 @@ std::unique_ptr<QTextDocument> GophermapRenderer::render(const QByteArray &input
icon = "directory";
break;
case '2': // CCSO Nameserver
icon = "ns";
icon = "dns";
break;
case '3': // Error code returned by a Gopher server to indicate failure
icon = "error";
break;
case '4': // BinHex-encoded file (primarily for Macintosh computers)
icon = "binhex";
icon = "binary";
break;
case '5': // DOS file
icon = "dos";
icon = "binary";
break;
case '6': // uuencoded file
icon = "uuencoded";
icon = "binary";
break;
case '7': // Gopher full-text search
icon = "full-text";
icon = "search";
break;
case '8': // Telnet
icon = "telnet";
@ -117,7 +131,7 @@ std::unique_ptr<QTextDocument> GophermapRenderer::render(const QByteArray &input
case 's': // Sound file
icon = "sound";
break;
default: // unknown
default: // unknown
continue;
}
@ -125,34 +139,46 @@ std::unique_ptr<QTextDocument> GophermapRenderer::render(const QByteArray &input
// 1Phlog /phlog octotherp.org 70 +
if(line.at(0) == 'i')
if (line.at(0) == 'i')
{
cursor.insertText(title + "\n", standard);
}
else
{
QString dst_url;
switch(items.size())
switch (items.size())
{
case 0: assert(false);
case 1: assert(false);
case 0:
assert(false);
case 1:
assert(false);
case 2:
dst_url = root_url.resolved(QUrl(items.at(1))).toString();
break;
case 3:
dst_url = "gopher://" + items.at(2) + "/" + line.mid(0,1) + items.at(1);
dst_url = "gopher://" + items.at(2) + "/" + line.mid(0, 1) + items.at(1);
break;
default:
dst_url = "gopher://" + items.at(2) + ":" + items.at(3) + "/" + line.mid(0,1) + items.at(1);
dst_url = "gopher://" + items.at(2) + ":" + items.at(3) + "/" + line.mid(0, 1) + items.at(1);
break;
}
if(not QUrl(dst_url).isValid()) {
if (not QUrl(dst_url).isValid())
{
// invlaid URL generated
qDebug() << line << dst_url;
}
cursor.insertText("[" + icon + "] ", standard);
QTextImageFormat icon_fmt;
icon_fmt.setName(QString("gopher/%1").arg(icon));
icon_fmt.setVerticalAlignment(QTextImageFormat::AlignTop);
cursor.insertImage(icon_fmt);
// cursor.insertImage(QImage(QString(":/icons/gopher/%1.svg").arg(icon)));
cursor.insertText(" ");
// cursor.insertText("[" + icon + "] ", standard);
QTextCharFormat fmt = standard_link;
fmt.setAnchor(true);

View File

@ -21,5 +21,17 @@
<file>icons/volume-off.svg</file>
<file>icons/play.svg</file>
<file>icons/pause.svg</file>
<file>icons/gopher/binary.svg</file>
<file>icons/gopher/directory.svg</file>
<file>icons/gopher/dns.svg</file>
<file>icons/gopher/error.svg</file>
<file>icons/gopher/gif.svg</file>
<file>icons/gopher/html.svg</file>
<file>icons/gopher/image.svg</file>
<file>icons/gopher/mirror.svg</file>
<file>icons/gopher/search.svg</file>
<file>icons/gopher/sound.svg</file>
<file>icons/gopher/telnet.svg</file>
<file>icons/gopher/text.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M5.12,5H18.87L17.93,4H5.93L5.12,5M20.54,5.23C20.83,5.57 21,6 21,6.5V19A2,2 0 0,1 19,21H5A2,2 0 0,1 3,19V6.5C3,6 3.17,5.57 3.46,5.23L4.84,3.55C5.12,3.21 5.53,3 6,3H18C18.47,3 18.88,3.21 19.15,3.55L20.54,5.23M6,18H12V15H6V18Z" /></svg>

After

Width:  |  Height:  |  Size: 518 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z" /></svg>

After

Width:  |  Height:  |  Size: 431 B

1
src/icons/gopher/dns.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M7,9A2,2 0 0,1 5,7A2,2 0 0,1 7,5A2,2 0 0,1 9,7A2,2 0 0,1 7,9M20,3H4A1,1 0 0,0 3,4V10A1,1 0 0,0 4,11H20A1,1 0 0,0 21,10V4A1,1 0 0,0 20,3M7,19A2,2 0 0,1 5,17A2,2 0 0,1 7,15A2,2 0 0,1 9,17A2,2 0 0,1 7,19M20,13H4A1,1 0 0,0 3,14V20A1,1 0 0,0 4,21H20A1,1 0 0,0 21,20V14A1,1 0 0,0 20,13Z" /></svg>

After

Width:  |  Height:  |  Size: 575 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M13,13H11V7H13M13,17H11V15H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" /></svg>

After

Width:  |  Height:  |  Size: 400 B

1
src/icons/gopher/gif.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M11,8H13V16H11V8M7.67,8H4.33C3.53,8 3,8.67 3,9.33V14.67C3,15.33 3.53,16 4.33,16H7.67C8.47,16 9,15.33 9,14.67V12H7V14H5V10H9V9.33C9,8.67 8.47,8 7.67,8M21,10V8H15V16H17V14H19.5V12H17V10H21Z" /></svg>

After

Width:  |  Height:  |  Size: 482 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M16.36,14C16.44,13.34 16.5,12.68 16.5,12C16.5,11.32 16.44,10.66 16.36,10H19.74C19.9,10.64 20,11.31 20,12C20,12.69 19.9,13.36 19.74,14M14.59,19.56C15.19,18.45 15.65,17.25 15.97,16H18.92C17.96,17.65 16.43,18.93 14.59,19.56M14.34,14H9.66C9.56,13.34 9.5,12.68 9.5,12C9.5,11.32 9.56,10.65 9.66,10H14.34C14.43,10.65 14.5,11.32 14.5,12C14.5,12.68 14.43,13.34 14.34,14M12,19.96C11.17,18.76 10.5,17.43 10.09,16H13.91C13.5,17.43 12.83,18.76 12,19.96M8,8H5.08C6.03,6.34 7.57,5.06 9.4,4.44C8.8,5.55 8.35,6.75 8,8M5.08,16H8C8.35,17.25 8.8,18.45 9.4,19.56C7.57,18.93 6.03,17.65 5.08,16M4.26,14C4.1,13.36 4,12.69 4,12C4,11.31 4.1,10.64 4.26,10H7.64C7.56,10.66 7.5,11.32 7.5,12C7.5,12.68 7.56,13.34 7.64,14M12,4.03C12.83,5.23 13.5,6.57 13.91,8H10.09C10.5,6.57 11.17,5.23 12,4.03M18.92,8H15.97C15.65,6.75 15.19,5.55 14.59,4.44C16.43,5.07 17.96,6.34 18.92,8M12,2C6.47,2 2,6.5 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" /></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M8.5,13.5L11,16.5L14.5,12L19,18H5M21,19V5C21,3.89 20.1,3 19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19Z" /></svg>

After

Width:  |  Height:  |  Size: 410 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M12 1C16.69 1 20.5 5.93 20.5 12C20.5 18.08 16.69 23 12 23C7.31 23 3.5 18.08 3.5 12C3.5 5.93 7.31 1 12 1M12 3C8.41 3 5.5 7.03 5.5 12C5.5 16.97 8.41 21 12 21C15.59 21 18.5 16.97 18.5 12C18.5 7.03 15.59 3 12 3M8.29 10.28L11.53 7.03L12.59 8.09L9.35 11.34L8.29 10.28M8.7 14.61L14.36 8.95L15.42 10L9.76 15.67L8.7 14.61Z" /></svg>

After

Width:  |  Height:  |  Size: 608 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" /></svg>

After

Width:  |  Height:  |  Size: 552 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M21,3V15.5A3.5,3.5 0 0,1 17.5,19A3.5,3.5 0 0,1 14,15.5A3.5,3.5 0 0,1 17.5,12C18.04,12 18.55,12.12 19,12.34V6.47L9,8.6V17.5A3.5,3.5 0 0,1 5.5,21A3.5,3.5 0 0,1 2,17.5A3.5,3.5 0 0,1 5.5,14C6.04,14 6.55,14.12 7,14.34V6L21,3Z" /></svg>

After

Width:  |  Height:  |  Size: 515 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M20,19V7H4V19H20M20,3A2,2 0 0,1 22,5V19A2,2 0 0,1 20,21H4A2,2 0 0,1 2,19V5C2,3.89 2.9,3 4,3H20M13,17V15H18V17H13M9.58,13L5.57,9H8.4L11.7,12.3C12.09,12.69 12.09,13.33 11.7,13.72L8.42,17H5.59L9.58,13Z" /></svg>

After

Width:  |  Height:  |  Size: 493 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M13,9H18.5L13,3.5V9M6,2H14L20,8V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V4C4,2.89 4.89,2 6,2M15,18V16H6V18H15M18,14V12H6V14H18Z" /></svg>

After

Width:  |  Height:  |  Size: 422 B

View File

@ -14,3 +14,23 @@ bool IoUtil::writeAll(QIODevice &dst, QByteArray const & src)
return true;
}
QString IoUtil::size_human(qint64 size)
{
if(size < 1024)
return QString("%1 B").arg(size);
float num = size;
QStringList list;
list << "KB" << "MB" << "GB" << "TB";
QStringListIterator i(list);
QString unit("B");
while(num >= 1024.0 && i.hasNext())
{
unit = i.next();
num /= 1024.0;
}
return QString().setNum(num,'f',2)+" "+unit;
}

View File

@ -6,6 +6,8 @@
struct IoUtil
{
static bool writeAll(QIODevice & dst, QByteArray const & src);
static QString size_human(qint64 size);
};
#endif // IOUTIL_HPP

View File

@ -10,13 +10,17 @@
#include <QFile>
#include <QTextStream>
#include <QFileDialog>
#include "ioutil.hpp"
MainWindow::MainWindow(QApplication * app, QWidget *parent) :
QMainWindow(parent),
application(app),
settings("xqTechnologies", "Kristall"),
ui(new Ui::MainWindow),
url_status(new QLabel())
url_status(new QLabel(this)),
file_size(new QLabel(this)),
file_mime(new QLabel(this)),
load_time(new QLabel(this))
{
if(not this->settings.contains("start_page")) {
this->settings.setValue("start_page", "about:favourites");
@ -25,6 +29,9 @@ MainWindow::MainWindow(QApplication * app, QWidget *parent) :
ui->setupUi(this);
this->statusBar()->addWidget(this->url_status);
this->statusBar()->addPermanentWidget(this->file_mime);
this->statusBar()->addPermanentWidget(this->file_size);
this->statusBar()->addPermanentWidget(this->load_time);
this->favourites.load(settings);
this->current_style.load(settings);
@ -87,6 +94,7 @@ BrowserTab * MainWindow::addEmptyTab(bool focus_new, bool load_default)
BrowserTab * tab = new BrowserTab(this);
connect(tab, &BrowserTab::titleChanged, this, &MainWindow::on_tab_titleChanged);
connect(tab, &BrowserTab::fileLoaded, this, &MainWindow::on_tab_fileLoaded);
int index = this->ui->browser_tabs->addTab(tab, "Page");
@ -322,15 +330,25 @@ void MainWindow::on_actionSave_as_triggered()
{
BrowserTab * tab = qobject_cast<BrowserTab*>(this->ui->browser_tabs->currentWidget());
if(tab != nullptr) {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QFileDialog::saveFileContent(
tab->current_buffer,
tab->current_location.fileName()
);
#else
// TODO: Implement without saveFileContent
QMessageBox::warning(this, "Kristall", "Not support in your Qt version.");
#endif
QFileDialog dialog { this };
dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.selectFile(tab->current_location.fileName());
if(dialog.exec() !=QFileDialog::Accepted)
return;
QString fileName = dialog.selectedFiles().at(0);
QFile file { fileName };
if(file.open(QFile::WriteOnly))
{
IoUtil::writeAll(file, tab->current_buffer);
}
else
{
QMessageBox::warning(this, "Kristall", QString("Could not save file:\r\n%1").arg(file.errorString()));
}
}
}
@ -349,3 +367,17 @@ void MainWindow::on_actionAdd_to_favourites_triggered()
tab->toggleIsFavourite();
}
}
void MainWindow::on_tab_fileLoaded(qint64 fileSize, const QString &mime, int msec)
{
auto * tab = qobject_cast<BrowserTab*>(sender());
if(tab != nullptr) {
int index = this->ui->browser_tabs->indexOf(tab);
assert(index >= 0);
if(index == this->ui->browser_tabs->currentIndex()) {
this->file_size->setText(IoUtil::size_human(fileSize));
this->file_mime->setText(mime);
this->load_time->setText(QString("%1 ms").arg(msec));
}
}
}

View File

@ -73,6 +73,8 @@ private slots:
void on_actionAdd_to_favourites_triggered();
void on_tab_fileLoaded(qint64 fileSize, QString const & mime, int msec);
private:
void reloadTheme();
@ -86,5 +88,8 @@ private:
Ui::MainWindow *ui;
QLabel * url_status;
QLabel * file_size;
QLabel * file_mime;
QLabel * load_time;
};
#endif // MAINWINDOW_HPP