Compare commits
13 Commits
659a144814
...
b2fac23783
Author | SHA1 | Date |
---|---|---|
Dima Krasner | b2fac23783 | |
Dima Krasner | b84f4ba5dd | |
Dima Krasner | e18f9e4ecb | |
Dima Krasner | 64fd9d7484 | |
Dima Krasner | 1a45619461 | |
Felix Yan | 40448d458c | |
Xavier Del Campo Romero | 6d97b7f198 | |
Xavier Del Campo Romero | 8cb79ee671 | |
Xavier Del Campo Romero | 42022bdfd2 | |
Xavier Del Campo Romero | 317bdbad5b | |
Xavier Del Campo Romero | 505723e9df | |
Michael Steenbeek | 3709c3d6bd | |
Michael Steenbeek | 10a9c4ccfa |
|
@ -33,7 +33,27 @@ jobs:
|
|||
|
||||
- name: make
|
||||
run: make build/kristall
|
||||
|
||||
|
||||
build_cmake:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: jurplel/install-qt-action@v2
|
||||
with:
|
||||
version: "5.12.8"
|
||||
|
||||
- name: Install OpenSSL
|
||||
run: sudo apt install -y libssl-dev
|
||||
|
||||
- name: Configure the project
|
||||
uses: threeal/cmake-action@v1.3.0
|
||||
with:
|
||||
build-dir: build
|
||||
|
||||
- name: Build the project
|
||||
run: cmake --build build
|
||||
|
||||
# Disabled until both aqinstall and install-qt-action support the fixes…
|
||||
# build_windows:
|
||||
# runs-on: windows-latest
|
||||
|
|
|
@ -113,7 +113,7 @@ Install Qt via the Qt installer. Install the following components:
|
|||
|
||||
If you didn't istall Qt to `C:\Qt`, you have to adjust the paths in `src/kristall.pro` for the `win32-g++` adjustments to the path you used.
|
||||
|
||||
Then open `src/kristall.pro` with Qt creator to compile the project. Alternativly you can use `ci\build-and-deploy.bat`, but note that this script tries to deploy the file to `random-projects.net`, so this will fail in the end.
|
||||
Then open `src/kristall.pro` with Qt creator to compile the project. Alternatively you can use `ci\build-and-deploy.bat`, but note that this script tries to deploy the file to `random-projects.net`, so this will fail in the end.
|
||||
|
||||
**Troubleshouting:**
|
||||
If you get an error message that `MSVCR100.dll` is missing, you may need to install the [Microsoft C++ Runtime](https://www.microsoft.com/en-us/download/details.aspx?id=14632).
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
if(NOT KRISTALL_VERSION)
|
||||
execute_process(COMMAND git describe --tags --abbrev=0
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
OUTPUT_VARIABLE KRISTALL_CMAKE_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
if(NOT KRISTALL_CMAKE_VERSION)
|
||||
set(KRISTALL_CMAKE_VERSION "0.0.0")
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND git describe --tags
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
OUTPUT_VARIABLE KRISTALL_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
if(NOT KRISTALL_VERSION)
|
||||
set(KRISTALL_VERSION "development")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# CMake requires the following format for versions:
|
||||
# <major>[.<minor>[.<patch>[.<tweak>]]]]
|
||||
string(REPLACE "V" "" KRISTALL_CMAKE_VERSION ${KRISTALL_CMAKE_VERSION})
|
||||
project(kristall VERSION ${KRISTALL_CMAKE_VERSION} LANGUAGES CXX)
|
||||
|
||||
set(QT_VERSION_MAJOR 5)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
# QXmpp requires C++17.
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS
|
||||
Multimedia MultimediaWidgets Network Widgets REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS
|
||||
Multimedia MultimediaWidgets Network Widgets REQUIRED)
|
||||
|
||||
set(PROJECT_SOURCES
|
||||
src/browsertab.cpp
|
||||
src/certificatehelper.cpp
|
||||
src/cryptoidentity.cpp
|
||||
src/dialogs/certificateiodialog.cpp
|
||||
src/dialogs/certificatemanagementdialog.cpp
|
||||
src/dialogs/certificateselectiondialog.cpp
|
||||
src/dialogs/newidentitiydialog.cpp
|
||||
src/dialogs/settingsdialog.cpp
|
||||
src/documentoutlinemodel.cpp
|
||||
src/documentstyle.cpp
|
||||
src/favouritecollection.cpp
|
||||
src/identitycollection.cpp
|
||||
src/ioutil.cpp
|
||||
src/localization.cpp
|
||||
src/main.cpp
|
||||
src/mainwindow.cpp
|
||||
src/renderers/htmlrenderer.cpp
|
||||
src/renderers/markdownrenderer.cpp
|
||||
src/renderers/renderhelpers.cpp
|
||||
src/renderers/textstyleinstance.cpp
|
||||
src/widgets/browsertabbar.cpp
|
||||
src/widgets/browsertabwidget.cpp
|
||||
src/widgets/kristalltextbrowser.cpp
|
||||
src/widgets/mediaplayer.cpp
|
||||
src/mimeparser.cpp
|
||||
src/protocolhandler.cpp
|
||||
src/protocols/abouthandler.cpp
|
||||
src/protocols/filehandler.cpp
|
||||
src/protocols/fingerclient.cpp
|
||||
src/protocols/geminiclient.cpp
|
||||
src/protocols/gopherclient.cpp
|
||||
src/protocols/guppyclient.cpp
|
||||
src/protocols/webclient.cpp
|
||||
src/protocolsetup.cpp
|
||||
src/renderers/geminirenderer.cpp
|
||||
src/renderers/gophermaprenderer.cpp
|
||||
src/renderers/plaintextrenderer.cpp
|
||||
src/ssltrust.cpp
|
||||
src/tabbrowsinghistory.cpp
|
||||
src/trustedhost.cpp
|
||||
src/trustedhostcollection.cpp
|
||||
src/widgets/elidelabel.cpp
|
||||
src/widgets/searchbar.cpp
|
||||
src/widgets/ssltrusteditor.cpp
|
||||
src/widgets/favouritepopup.cpp
|
||||
src/widgets/favouritebutton.cpp
|
||||
src/widgets/querydialog.ui
|
||||
src/widgets/querydialog.cpp
|
||||
src/cachehandler.cpp
|
||||
src/widgets/searchbox.cpp
|
||||
src/browsertab.ui
|
||||
src/dialogs/certificateiodialog.ui
|
||||
src/dialogs/certificatemanagementdialog.ui
|
||||
src/dialogs/certificateselectiondialog.ui
|
||||
src/dialogs/newidentitiydialog.ui
|
||||
src/dialogs/settingsdialog.ui
|
||||
src/mainwindow.ui
|
||||
src/widgets/mediaplayer.ui
|
||||
src/widgets/ssltrusteditor.ui
|
||||
src/fonts.qrc
|
||||
lib/BreezeStyleSheets/breeze.qrc
|
||||
src/builtins.qrc
|
||||
src/icons.qrc
|
||||
)
|
||||
|
||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
qt_add_executable(${PROJECT_NAME}
|
||||
MANUAL_FINALIZATION
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
# Define target properties for Android with Qt 6 as:
|
||||
# set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/android)
|
||||
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
|
||||
else()
|
||||
if(ANDROID)
|
||||
add_library(${PROJECT_NAME} SHARED
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
# Define properties for Android with Qt 5 after find_package() calls as:
|
||||
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
|
||||
else()
|
||||
add_executable(${PROJECT_NAME}
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "Building Kristall ${KRISTALL_VERSION}")
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC
|
||||
KRISTALL_VERSION=${KRISTALL_VERSION})
|
||||
|
||||
add_subdirectory(lib/luis-l-gist)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE luis-l-gist)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(cmark IMPORTED_TARGET cmark)
|
||||
|
||||
if(cmark_FOUND)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::cmark)
|
||||
else()
|
||||
message(STATUS "Using in-tree cmark")
|
||||
add_subdirectory(lib/cmark)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE cmark)
|
||||
endif()
|
||||
|
||||
pkg_check_modules(gumbo-parser IMPORTED_TARGET gumbo)
|
||||
|
||||
if(gumbo_FOUND)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::gumbo-parser)
|
||||
else()
|
||||
message(STATUS "Using in-tree gumbo-parser")
|
||||
add_subdirectory(lib/gumbo-parser)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE gumbo-parser)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Multimedia
|
||||
Qt${QT_VERSION_MAJOR}::MultimediaWidgets
|
||||
Qt${QT_VERSION_MAJOR}::Network
|
||||
Qt${QT_VERSION_MAJOR}::Widgets)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE src)
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
if(QT_VERSION_MAJOR EQUAL 6)
|
||||
qt_finalize_executable(${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
find_package(OpenSSL 1.1 REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE OpenSSL::SSL)
|
||||
|
||||
if(NOT UNIX)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE iconv)
|
||||
endif()
|
|
@ -0,0 +1,24 @@
|
|||
cmake_minimum_required(VERSION 3.13)
|
||||
project(cmark C)
|
||||
|
||||
set(sources
|
||||
src/blocks.c
|
||||
src/buffer.c
|
||||
src/cmark.c
|
||||
src/cmark_ctype.c
|
||||
src/commonmark.c
|
||||
src/houdini_href_e.c
|
||||
src/houdini_html_e.c
|
||||
src/houdini_html_u.c
|
||||
src/inlines.c
|
||||
src/iterator.c
|
||||
src/node.c
|
||||
src/references.c
|
||||
src/render.c
|
||||
src/scanners.c
|
||||
src/utf8.c
|
||||
src/html.c
|
||||
src/xml.c)
|
||||
|
||||
add_library(${PROJECT_NAME} ${sources})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC src)
|
|
@ -0,0 +1,17 @@
|
|||
cmake_minimum_required(VERSION 3.13)
|
||||
project(gumbo-parser C)
|
||||
set(sources
|
||||
attribute.c
|
||||
char_ref.c
|
||||
error.c
|
||||
gumbo-utf8.c
|
||||
parser.c
|
||||
string_buffer.c
|
||||
string_piece.c
|
||||
tag.c
|
||||
tokenizer.c
|
||||
util.c
|
||||
vector.c
|
||||
)
|
||||
add_library(${PROJECT_NAME} ${sources})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC include PRIVATE .)
|
|
@ -0,0 +1,7 @@
|
|||
cmake_minimum_required(VERSION 3.13)
|
||||
project(luis-l-gist CXX)
|
||||
add_library(${PROJECT_NAME} interactiveview.cpp)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC .)
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Qt${QT_VERSION_MAJOR}::Widgets)
|
|
@ -17,6 +17,7 @@
|
|||
#include "protocols/geminiclient.hpp"
|
||||
#include "protocols/webclient.hpp"
|
||||
#include "protocols/gopherclient.hpp"
|
||||
#include "protocols/guppyclient.hpp"
|
||||
#include "protocols/fingerclient.hpp"
|
||||
#include "protocols/abouthandler.hpp"
|
||||
#include "protocols/filehandler.hpp"
|
||||
|
@ -25,6 +26,7 @@
|
|||
#include "kristall.hpp"
|
||||
#include "widgets/favouritepopup.hpp"
|
||||
#include "widgets/searchbox.hpp"
|
||||
#include "widgets/querydialog.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <QTabWidget>
|
||||
|
@ -76,6 +78,7 @@ BrowserTab::BrowserTab(MainWindow *mainWindow) : QWidget(nullptr),
|
|||
addProtocolHandler<GeminiClient>();
|
||||
addProtocolHandler<FingerClient>();
|
||||
addProtocolHandler<GopherClient>();
|
||||
addProtocolHandler<GuppyClient>();
|
||||
addProtocolHandler<WebClient>();
|
||||
addProtocolHandler<AboutHandler>();
|
||||
addProtocolHandler<FileHandler>();
|
||||
|
@ -867,9 +870,8 @@ void BrowserTab::on_inputRequired(const QString &query, const bool is_sensitive)
|
|||
{
|
||||
this->network_timeout_timer.stop();
|
||||
|
||||
QInputDialog dialog{this};
|
||||
QueryDialog dialog(this);
|
||||
|
||||
dialog.setInputMode(QInputDialog::TextInput);
|
||||
dialog.setLabelText(query);
|
||||
if (is_sensitive) dialog.setTextEchoMode(QLineEdit::Password);
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1100</width>
|
||||
<height>737</height>
|
||||
<width>496</width>
|
||||
<height>404</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -32,281 +32,313 @@
|
|||
<string>Generic</string>
|
||||
</attribute>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Start Page:</string>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="start_page">
|
||||
<property name="placeholderText">
|
||||
<string>about://blank</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_40">
|
||||
<property name="text">
|
||||
<string>Search engine:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="search_engine">
|
||||
<property name="editable">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>585</width>
|
||||
<height>490</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_44">
|
||||
<property name="text">
|
||||
<string>Language</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="selected_language"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Start Page:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="start_page">
|
||||
<property name="placeholderText">
|
||||
<string>about://blank</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_40">
|
||||
<property name="text">
|
||||
<string>Search engine:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="search_engine">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_29">
|
||||
<property name="text">
|
||||
<string>Additional toolbar buttons</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_99">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_home_btn">
|
||||
<property name="text">
|
||||
<string>Home</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_newtab_btn">
|
||||
<property name="text">
|
||||
<string>New tab</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_root_btn">
|
||||
<property name="text">
|
||||
<string>Root (/)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_parent_btn">
|
||||
<property name="text">
|
||||
<string>Parent (..)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>Startup Behaviour</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="session_restore_behaviour"/>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>UI Theme</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="ui_theme"/>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_34">
|
||||
<property name="text">
|
||||
<string>Icon Theme</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="icon_theme"/>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_1">
|
||||
<property name="text">
|
||||
<string>UI Density</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QComboBox" name="ui_density"/>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Enabled Protocols</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_gemini">
|
||||
<property name="text">
|
||||
<string>Gemini</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_gopher">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Gopher</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_guppy">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Guppy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_finger">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Finger</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_http">
|
||||
<property name="text">
|
||||
<string>HTTP</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_https">
|
||||
<property name="text">
|
||||
<string>HTTPS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>Unknown Scheme</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="scheme_os_default">
|
||||
<property name="text">
|
||||
<string>Use OS default handler</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="scheme_error">
|
||||
<property name="text">
|
||||
<string>Display error message</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_26">
|
||||
<property name="text">
|
||||
<string>Max. Number of Redirections</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QSpinBox" name="max_redirects">
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_27">
|
||||
<property name="text">
|
||||
<string>Redirection Handling</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QComboBox" name="redirection_mode"/>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="text">
|
||||
<string>Network Timeout</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QSpinBox" name="network_timeout">
|
||||
<property name="suffix">
|
||||
<string> ms</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>90000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="label_45">
|
||||
<property name="text">
|
||||
<string>Tab close behaviour</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="tab_keep_window">
|
||||
<property name="text">
|
||||
<string>Keep window open</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">buttonGroup_10</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="tab_close_window">
|
||||
<property name="text">
|
||||
<string>Close window</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">buttonGroup_10</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_29">
|
||||
<property name="text">
|
||||
<string>Additional toolbar buttons</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_99">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_home_btn">
|
||||
<property name="text">
|
||||
<string>Home</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_newtab_btn">
|
||||
<property name="text">
|
||||
<string>New tab</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_root_btn">
|
||||
<property name="text">
|
||||
<string>Root (/)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_parent_btn">
|
||||
<property name="text">
|
||||
<string>Parent (..)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>Startup Behaviour</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="session_restore_behaviour"/>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>UI Theme</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="ui_theme"/>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_34">
|
||||
<property name="text">
|
||||
<string>Icon Theme</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="icon_theme"/>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_1">
|
||||
<property name="text">
|
||||
<string>UI Density</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QComboBox" name="ui_density"/>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Enabled Protocols</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_gemini">
|
||||
<property name="text">
|
||||
<string>Gemini</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_gopher">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Gopher</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_finger">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Finger</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_http">
|
||||
<property name="text">
|
||||
<string>HTTP</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_https">
|
||||
<property name="text">
|
||||
<string>HTTPS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>Unknown Scheme</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="scheme_os_default">
|
||||
<property name="text">
|
||||
<string>Use OS default handler</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="scheme_error">
|
||||
<property name="text">
|
||||
<string>Display error message</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_26">
|
||||
<property name="text">
|
||||
<string>Max. Number of Redirections</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QSpinBox" name="max_redirects">
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_27">
|
||||
<property name="text">
|
||||
<string>Redirection Handling</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QComboBox" name="redirection_mode"/>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="text">
|
||||
<string>Network Timeout</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QSpinBox" name="network_timeout">
|
||||
<property name="suffix">
|
||||
<string> ms</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>90000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_44">
|
||||
<property name="text">
|
||||
<string>Language</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="selected_language"/>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="label_45">
|
||||
<property name="text">
|
||||
<string>Tab close behaviour</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="tab_keep_window">
|
||||
<property name="text">
|
||||
<string>Keep window open</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">buttonGroup_10</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="tab_close_window">
|
||||
<property name="text">
|
||||
<string>Close window</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">buttonGroup_10</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="display_tab">
|
||||
|
@ -705,9 +737,9 @@
|
|||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>530</width>
|
||||
<height>712</height>
|
||||
<y>-351</y>
|
||||
<width>570</width>
|
||||
<height>783</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="style_scroll_layout">
|
||||
|
@ -1619,19 +1651,14 @@
|
|||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>ui_theme</tabstop>
|
||||
<tabstop>icon_theme</tabstop>
|
||||
<tabstop>ui_density</tabstop>
|
||||
<tabstop>enable_gemini</tabstop>
|
||||
<tabstop>enable_gopher</tabstop>
|
||||
<tabstop>enable_guppy</tabstop>
|
||||
<tabstop>enable_finger</tabstop>
|
||||
<tabstop>enable_http</tabstop>
|
||||
<tabstop>enable_https</tabstop>
|
||||
<tabstop>scheme_os_default</tabstop>
|
||||
<tabstop>scheme_error</tabstop>
|
||||
<tabstop>max_redirects</tabstop>
|
||||
<tabstop>redirection_mode</tabstop>
|
||||
<tabstop>network_timeout</tabstop>
|
||||
<tabstop>enable_home_btn</tabstop>
|
||||
<tabstop>enable_newtab_btn</tabstop>
|
||||
<tabstop>enable_root_btn</tabstop>
|
||||
|
@ -1714,15 +1741,15 @@
|
|||
</connection>
|
||||
</connections>
|
||||
<buttongroups>
|
||||
<buttongroup name="buttonGroup_2"/>
|
||||
<buttongroup name="buttonGroup_7"/>
|
||||
<buttongroup name="buttonGroup_5"/>
|
||||
<buttongroup name="buttonGroup"/>
|
||||
<buttongroup name="buttonGroup_6"/>
|
||||
<buttongroup name="buttonGroup_8"/>
|
||||
<buttongroup name="buttonGroup_3"/>
|
||||
<buttongroup name="buttonGroup_7"/>
|
||||
<buttongroup name="buttonGroup_4"/>
|
||||
<buttongroup name="buttonGroup_9"/>
|
||||
<buttongroup name="buttonGroup_10"/>
|
||||
<buttongroup name="buttonGroup_8"/>
|
||||
<buttongroup name="buttonGroup_2"/>
|
||||
<buttongroup name="buttonGroup_6"/>
|
||||
<buttongroup name="buttonGroup_9"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
|
|
@ -143,6 +143,7 @@ SOURCES += \
|
|||
protocols/fingerclient.cpp \
|
||||
protocols/geminiclient.cpp \
|
||||
protocols/gopherclient.cpp \
|
||||
protocols/guppyclient.cpp \
|
||||
protocols/webclient.cpp \
|
||||
protocolsetup.cpp \
|
||||
renderers/geminirenderer.cpp \
|
||||
|
@ -158,7 +159,8 @@ SOURCES += \
|
|||
widgets/favouritepopup.cpp \
|
||||
widgets/favouritebutton.cpp \
|
||||
cachehandler.cpp \
|
||||
widgets/searchbox.cpp
|
||||
widgets/searchbox.cpp \
|
||||
widgets/querydialog.cpp
|
||||
|
||||
HEADERS += \
|
||||
../lib/luis-l-gist/interactiveview.hpp \
|
||||
|
@ -192,6 +194,7 @@ HEADERS += \
|
|||
protocols/fingerclient.hpp \
|
||||
protocols/geminiclient.hpp \
|
||||
protocols/gopherclient.hpp \
|
||||
protocols/guppyclient.hpp \
|
||||
protocols/webclient.hpp \
|
||||
protocolsetup.hpp \
|
||||
renderers/geminirenderer.hpp \
|
||||
|
@ -206,6 +209,7 @@ HEADERS += \
|
|||
widgets/ssltrusteditor.hpp \
|
||||
widgets/favouritepopup.hpp \
|
||||
widgets/favouritebutton.hpp \
|
||||
widgets/querydialog.hpp \
|
||||
cachehandler.hpp \
|
||||
widgets/searchbox.hpp
|
||||
|
||||
|
@ -218,7 +222,8 @@ FORMS += \
|
|||
dialogs/settingsdialog.ui \
|
||||
mainwindow.ui \
|
||||
widgets/mediaplayer.ui \
|
||||
widgets/ssltrusteditor.ui
|
||||
widgets/ssltrusteditor.ui \
|
||||
widgets/querydialog.ui
|
||||
|
||||
CONFIG += lrelease embed_translations
|
||||
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
#include "guppyclient.hpp"
|
||||
#include "ioutil.hpp"
|
||||
#include "kristall.hpp"
|
||||
|
||||
GuppyClient::GuppyClient(QObject *parent) : ProtocolHandler(parent)
|
||||
{
|
||||
connect(&socket, &QUdpSocket::connected, this, &GuppyClient::on_connected);
|
||||
connect(&socket, &QUdpSocket::readyRead, this, &GuppyClient::on_readRead);
|
||||
connect(&timer, &QTimer::timeout, this, &GuppyClient::on_timerTick);
|
||||
|
||||
connect(&socket, &QAbstractSocket::hostFound, this, [this]() {
|
||||
emit this->requestStateChange(RequestState::HostFound);
|
||||
});
|
||||
emit this->requestStateChange(RequestState::None);
|
||||
}
|
||||
|
||||
GuppyClient::~GuppyClient()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool GuppyClient::supportsScheme(const QString &scheme) const
|
||||
{
|
||||
return (scheme == "guppy");
|
||||
}
|
||||
|
||||
bool GuppyClient::startRequest(const QUrl &url, RequestOptions options)
|
||||
{
|
||||
Q_UNUSED(options)
|
||||
|
||||
if(this->isInProgress())
|
||||
return false;
|
||||
|
||||
if(url.scheme() != "guppy")
|
||||
return false;
|
||||
|
||||
emit this->requestStateChange(RequestState::Started);
|
||||
|
||||
this->requested_url = url;
|
||||
this->was_cancelled = false;
|
||||
this->prev_seq = 0;
|
||||
this->first_seq = 0;
|
||||
this->last_seq = 0;
|
||||
this->socket.connectToHost(url.host(), url.port(6775));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GuppyClient::isInProgress() const
|
||||
{
|
||||
return this->socket.isOpen();
|
||||
}
|
||||
|
||||
bool GuppyClient::cancelRequest()
|
||||
{
|
||||
was_cancelled = true;
|
||||
this->socket.close();
|
||||
this->timer.stop();
|
||||
this->body.clear();
|
||||
this->chunks.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuppyClient::on_connected()
|
||||
{
|
||||
request = (this->requested_url.toString(QUrl::FormattingOptions(QUrl::FullyEncoded)) + "\r\n").toUtf8();
|
||||
if(this->socket.write(request.constData(), request.size()) <= 0)
|
||||
{
|
||||
this->socket.close();
|
||||
return;
|
||||
}
|
||||
|
||||
this->timer.start(2000);
|
||||
|
||||
emit this->requestStateChange(RequestState::Connected);
|
||||
}
|
||||
|
||||
void GuppyClient::on_readRead()
|
||||
{
|
||||
QByteArray chunk = this->socket.read(65535);
|
||||
|
||||
if(int crlf = chunk.indexOf("\r\n"); crlf > 0) {
|
||||
QByteArray header = chunk.left(crlf);
|
||||
|
||||
// first response packet (success, error or redirect) header should contain a space
|
||||
int seq = -1;
|
||||
if(int space = header.indexOf(' '); space > 0) {
|
||||
QByteArray meta = header.mid(space + 1);
|
||||
seq = chunk.left(space).toInt();
|
||||
|
||||
if(seq < 6 || seq > 2147483647) {
|
||||
this->timer.stop();
|
||||
this->body.clear();
|
||||
this->chunks.clear();
|
||||
emit this->requestStateChange(RequestState::None);
|
||||
|
||||
if(seq == 4) {
|
||||
emit networkError(UnknownError, meta); // error
|
||||
}
|
||||
else if(seq == 3) { // redirect
|
||||
QUrl new_url(meta);
|
||||
|
||||
if(new_url.isRelative()) new_url = this->requested_url.resolved(new_url);
|
||||
assert(not new_url.isRelative());
|
||||
|
||||
this->socket.close();
|
||||
this->timer.stop();
|
||||
this->body.clear();
|
||||
this->chunks.clear();
|
||||
emit this->requestStateChange(RequestState::None);
|
||||
|
||||
emit redirected(new_url, false);
|
||||
}
|
||||
else if(seq == 1) { // input prompt
|
||||
this->socket.close();
|
||||
this->timer.stop();
|
||||
this->body.clear();
|
||||
this->chunks.clear();
|
||||
|
||||
emit this->requestStateChange(RequestState::None);
|
||||
|
||||
emit inputRequired(meta, false);
|
||||
}
|
||||
else {
|
||||
emit networkError(ProtocolViolation, QObject::tr("invalid seq"));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this->first_seq = seq; // success
|
||||
this->mime = meta;
|
||||
}
|
||||
else {
|
||||
seq = header.toInt();
|
||||
}
|
||||
|
||||
if(seq < this->first_seq) {
|
||||
return;
|
||||
}
|
||||
if(chunk.size() == crlf + 2) { // eof
|
||||
last_seq = seq;
|
||||
}
|
||||
else if(seq >= first_seq) { // success or continuation
|
||||
if(!this->prev_seq || seq >= this->prev_seq) {
|
||||
this->chunks[seq] = chunk.mid(crlf + 2, chunk.size() - crlf - 2);
|
||||
}
|
||||
|
||||
// postpone the timer when we receive the next packet
|
||||
if(seq == this->prev_seq + 1) {
|
||||
this->timer.start();
|
||||
}
|
||||
}
|
||||
// acknowledge every valid packet we receive
|
||||
QByteArray ack = QString("%1\r\n").arg(seq).toUtf8();
|
||||
socket.write(ack.constData(), ack.size());
|
||||
}
|
||||
else {
|
||||
emitNetworkError(this->socket.error(), this->socket.errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
// append all consequent chunks we have
|
||||
int next_seq = this->prev_seq ? this->prev_seq + 1 : this->first_seq;
|
||||
while(next_seq != last_seq) {
|
||||
QByteArray next = this->chunks.take(next_seq);
|
||||
if(next.isNull()) {
|
||||
break;
|
||||
}
|
||||
body.append(next.constData(), next.size());
|
||||
this->prev_seq = next_seq++;
|
||||
}
|
||||
|
||||
if(not this->was_cancelled) {
|
||||
emit this->requestProgress(body.size());
|
||||
}
|
||||
|
||||
// we're done when the last appended chunk is the one before the eof chunk
|
||||
if(this->last_seq && next_seq == this->last_seq) {
|
||||
if(not this->was_cancelled) {
|
||||
emit this->requestComplete(this->body, this->mime);
|
||||
this->was_cancelled = true;
|
||||
}
|
||||
this->socket.close();
|
||||
this->timer.stop();
|
||||
this->body.clear();
|
||||
this->chunks.clear();
|
||||
|
||||
emit this->requestStateChange(RequestState::None);
|
||||
}
|
||||
}
|
||||
|
||||
void GuppyClient::on_timerTick()
|
||||
{
|
||||
QByteArray pkt;
|
||||
if(this->prev_seq) { // resend the last ack
|
||||
pkt = QString("%1\r\n").arg(this->prev_seq).toUtf8();
|
||||
}
|
||||
else if(this->chunks.empty()) { // resend the request
|
||||
pkt = request;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
this->socket.write(pkt.constData(), pkt.size());
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef GUPPYCLIENT_HPP
|
||||
#define GUPPYCLIENT_HPP
|
||||
|
||||
#include <QObject>
|
||||
#include <QUdpSocket>
|
||||
#include <QUrl>
|
||||
#include <QTimer>
|
||||
|
||||
#include "protocolhandler.hpp"
|
||||
|
||||
class GuppyClient : public ProtocolHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GuppyClient(QObject *parent = nullptr);
|
||||
|
||||
~GuppyClient() override;
|
||||
|
||||
bool supportsScheme(QString const & scheme) const override;
|
||||
|
||||
bool startRequest(QUrl const & url, RequestOptions options) override;
|
||||
|
||||
bool isInProgress() const override;
|
||||
|
||||
bool cancelRequest() override;
|
||||
|
||||
private: // slots
|
||||
void on_connected();
|
||||
void on_readRead();
|
||||
void on_finished();
|
||||
void on_timerTick();
|
||||
void on_socketError(QAbstractSocket::SocketError errorCode);
|
||||
|
||||
|
||||
private:
|
||||
QUdpSocket socket;
|
||||
QHash<long, QByteArray> chunks;
|
||||
QByteArray body;
|
||||
QUrl requested_url;
|
||||
QByteArray request;
|
||||
bool was_cancelled;
|
||||
int prev_seq, first_seq, last_seq;
|
||||
QString mime;
|
||||
QTimer timer;
|
||||
};
|
||||
|
||||
#endif // GUPPYCLIENT_HPP
|
|
@ -7,6 +7,7 @@
|
|||
MAC(http) \
|
||||
MAC(https) \
|
||||
MAC(gopher) \
|
||||
MAC(guppy) \
|
||||
MAC(gemini) \
|
||||
MAC(finger)
|
||||
|
||||
|
|
|
@ -156,21 +156,32 @@ std::unique_ptr<QTextDocument> GophermapRenderer::render(const QByteArray &input
|
|||
else
|
||||
{
|
||||
QString dst_url;
|
||||
switch (items.size())
|
||||
|
||||
// If a resource’s path starts with “URL:”, it is a direct link (to HTTP or another protocol), rather than a file or directory on this server.
|
||||
if (items.size() >= 2 && items.at(1).startsWith("URL:"))
|
||||
{
|
||||
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 = scheme + "://" + items.at(2) + "/" + QString(type) + items.at(1);
|
||||
break;
|
||||
default:
|
||||
dst_url = scheme + "://" + items.at(2) + ":" + items.at(3) + "/" + QString(type) + items.at(1);
|
||||
break;
|
||||
auto item1 = QString(items.at(1));
|
||||
item1.remove(0, 4);
|
||||
dst_url = item1;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (items.size())
|
||||
{
|
||||
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 = scheme + "://" + items.at(2) + "/" + QString(type) + items.at(1);
|
||||
break;
|
||||
default:
|
||||
dst_url = scheme + "://" + items.at(2) + ":" + items.at(3) + "/" + QString(type) + items.at(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (not QUrl(dst_url).isValid())
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#include "widgets/querydialog.hpp"
|
||||
|
||||
QueryDialog::QueryDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
mode(QLineEdit::Normal)
|
||||
{
|
||||
ui.setupUi(this);
|
||||
ui.lineEdit->setVisible(false);
|
||||
}
|
||||
|
||||
void QueryDialog::setLabelText(const QString &text)
|
||||
{
|
||||
ui.query->setText(text);
|
||||
}
|
||||
|
||||
void QueryDialog::setTextEchoMode(QLineEdit::EchoMode mode)
|
||||
{
|
||||
ui.text->setVisible(mode == QLineEdit::Normal);
|
||||
ui.lineEdit->setVisible(mode != QLineEdit::Normal);
|
||||
ui.lineEdit->setEchoMode(mode);
|
||||
this->mode = mode;
|
||||
}
|
||||
|
||||
QString QueryDialog::textValue()
|
||||
{
|
||||
if (mode == QLineEdit::Normal)
|
||||
return ui.text->toPlainText();
|
||||
|
||||
return ui.lineEdit->text();
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef QUERYDIALOG_H
|
||||
#define QUERYDIALOG_H
|
||||
|
||||
#include "ui_querydialog.h"
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QString>
|
||||
|
||||
class QueryDialog : public QDialog {
|
||||
public:
|
||||
QueryDialog(QWidget *parent);
|
||||
void setLabelText(const QString &text);
|
||||
void setTextEchoMode(QLineEdit::EchoMode mode);
|
||||
QString textValue();
|
||||
private:
|
||||
Ui_QueryDialog ui;
|
||||
QLineEdit::EchoMode mode;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,77 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QueryDialog</class>
|
||||
<widget class="QDialog" name="QueryDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>480</width>
|
||||
<height>240</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="query">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="text"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>QueryDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>QueryDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Loading…
Reference in New Issue