Compare commits
10 Commits
3ed7c1b412
...
c757102256
| Author | SHA1 | Date | |
|---|---|---|---|
| c757102256 | |||
| 7b31b2a1b1 | |||
| e63912fac5 | |||
| e7a37a7cee | |||
| df4a86216b | |||
| efb32eb0f7 | |||
| a4d7484952 | |||
| b999efe016 | |||
| fd405bd9fd | |||
| e93cb69c55 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -11,6 +11,9 @@ CTestTestfile.cmake
|
||||
_deps
|
||||
CMakeUserPresets.json
|
||||
build/
|
||||
.vs/
|
||||
CMakeSettings.json
|
||||
.DS_STORE
|
||||
|
||||
# CLion
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
|
||||
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"editor.formatOnSave": true
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 4.2.1)
|
||||
cmake_minimum_required(VERSION 4.1.1)
|
||||
|
||||
project(CrabCrawler VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
@@ -6,14 +6,27 @@ set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Widgets)
|
||||
find_package(CURL REQUIRED)
|
||||
|
||||
qt_standard_project_setup()
|
||||
qt_add_resources(RESOURCES resources.qrc)
|
||||
|
||||
add_executable(CrabCrawler
|
||||
set(SOURCES
|
||||
src/main.cpp
|
||||
|
||||
src/ui/navbar.cpp
|
||||
src/ui/content.cpp
|
||||
|
||||
${RESOURCES}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
add_executable(CrabCrawler WIN32 ${SOURCES})
|
||||
else()
|
||||
add_executable(CrabCrawler ${SOURCES})
|
||||
endif()
|
||||
|
||||
target_link_libraries(CrabCrawler
|
||||
PRIVATE Qt6::Widgets
|
||||
${CURL_LIBRARIES}
|
||||
)
|
||||
|
||||
34
debug-build.sh
Executable file
34
debug-build.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
# This has only been tested on Linux Mint
|
||||
#!/bin/bash
|
||||
|
||||
CLEAR_BUILD=false
|
||||
RUN_PROGRAM=false
|
||||
|
||||
# Checks flags
|
||||
# Idk why case statements look so weird in bash but it works lol
|
||||
# Use -r to run the program after building and use -c to clear the build folder after running
|
||||
while getopts "cr" opt; do
|
||||
case "$opt" in
|
||||
c)
|
||||
CLEAR_BUILD=true
|
||||
;;
|
||||
r)
|
||||
RUN_PROGRAM=true
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Builds Crab Crawler
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -S ./ -B ./build
|
||||
cmake --build ./build
|
||||
|
||||
# Runs the program if the -r flag is provided
|
||||
if $RUN_PROGRAM; then
|
||||
echo "Running the Build..."
|
||||
./build/CrabCrawler
|
||||
fi
|
||||
|
||||
if $CLEAR_BUILD; then
|
||||
echo "Clearing build folder..."
|
||||
rm -rf build
|
||||
fi
|
||||
1
icons/angle-left-solid-full.svg
Normal file
1
icons/angle-left-solid-full.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path fill="#ffffff" d="M201.4 297.4C188.9 309.9 188.9 330.2 201.4 342.7L361.4 502.7C373.9 515.2 394.2 515.2 406.7 502.7C419.2 490.2 419.2 469.9 406.7 457.4L269.3 320L406.6 182.6C419.1 170.1 419.1 149.8 406.6 137.3C394.1 124.8 373.8 124.8 361.3 137.3L201.3 297.3z"/></svg>
|
||||
|
After Width: | Height: | Size: 485 B |
1
icons/angle-right-solid-full.svg
Normal file
1
icons/angle-right-solid-full.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path fill="#ffffff" d="M439.1 297.4C451.6 309.9 451.6 330.2 439.1 342.7L279.1 502.7C266.6 515.2 246.3 515.2 233.8 502.7C221.3 490.2 221.3 469.9 233.8 457.4L371.2 320L233.9 182.6C221.4 170.1 221.4 149.8 233.9 137.3C246.4 124.8 266.7 124.8 279.2 137.3L439.2 297.3z"/></svg>
|
||||
|
After Width: | Height: | Size: 485 B |
1
icons/arrows-rotate-solid-full.svg
Normal file
1
icons/arrows-rotate-solid-full.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path fill="#ffffff" d="M129.9 292.5C143.2 199.5 223.3 128 320 128C373 128 421 149.5 455.8 184.2C456 184.4 456.2 184.6 456.4 184.8L464 192L416.1 192C398.4 192 384.1 206.3 384.1 224C384.1 241.7 398.4 256 416.1 256L544.1 256C561.8 256 576.1 241.7 576.1 224L576.1 96C576.1 78.3 561.8 64 544.1 64C526.4 64 512.1 78.3 512.1 96L512.1 149.4L500.8 138.7C454.5 92.6 390.5 64 320 64C191 64 84.3 159.4 66.6 283.5C64.1 301 76.2 317.2 93.7 319.7C111.2 322.2 127.4 310 129.9 292.6zM573.4 356.5C575.9 339 563.7 322.8 546.3 320.3C528.9 317.8 512.6 330 510.1 347.4C496.8 440.4 416.7 511.9 320 511.9C267 511.9 219 490.4 184.2 455.7C184 455.5 183.8 455.3 183.6 455.1L176 447.9L223.9 447.9C241.6 447.9 255.9 433.6 255.9 415.9C255.9 398.2 241.6 383.9 223.9 383.9L96 384C87.5 384 79.3 387.4 73.3 393.5C67.3 399.6 63.9 407.7 64 416.3L65 543.3C65.1 561 79.6 575.2 97.3 575C115 574.8 129.2 560.4 129 542.7L128.6 491.2L139.3 501.3C185.6 547.4 249.5 576 320 576C449 576 555.7 480.6 573.4 356.5z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
7
resources.qrc
Normal file
7
resources.qrc
Normal file
@@ -0,0 +1,7 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>icons/angle-left-solid-full.svg</file>
|
||||
<file>icons/angle-right-solid-full.svg</file>
|
||||
<file>icons/arrows-rotate-solid-full.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
15
src/main.cpp
15
src/main.cpp
@@ -4,13 +4,17 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "ui/navbar.h"
|
||||
#include "ui/content.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
app.setStyle("fusion");
|
||||
|
||||
QWidget window;
|
||||
window.resize(800, 500);
|
||||
window.setWindowTitle("Crab Crawler");
|
||||
window.setMinimumSize(800, 600);
|
||||
window.resize(800, 600);
|
||||
|
||||
auto *layout = new QVBoxLayout(&window);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
@@ -18,11 +22,12 @@ int main(int argc, char *argv[])
|
||||
|
||||
auto *navBar = new NavBar(&window);
|
||||
layout->addWidget(navBar);
|
||||
layout->addStretch();
|
||||
|
||||
QObject::connect(navBar, &NavBar::addressEntered, [](const QString &text) {
|
||||
qDebug() << "navigate to:" << text;
|
||||
});
|
||||
auto *content = new Content(&window);
|
||||
layout->addWidget(content, 1);
|
||||
|
||||
QObject::connect(navBar, &NavBar::addressEntered, [content](const QString &text)
|
||||
{ qDebug() << "navigate to:" << text; });
|
||||
|
||||
window.show();
|
||||
return app.exec();
|
||||
|
||||
31
src/ui/content.cpp
Normal file
31
src/ui/content.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "content.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QDebug>
|
||||
|
||||
Content::Content(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
auto *layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
display = new QTextEdit(this);
|
||||
display->setReadOnly(true);
|
||||
|
||||
layout->addWidget(display);
|
||||
}
|
||||
|
||||
void Content::parseCrabcontent(const QString &input)
|
||||
{
|
||||
QStringList lines = input.split('\n', Qt::SkipEmptyParts);
|
||||
QString result;
|
||||
|
||||
for (const QString &line : lines)
|
||||
{
|
||||
if (line.startsWith("text:"))
|
||||
{
|
||||
result += "<p>" + line.mid(5).trimmed().toHtmlEscaped() + "</p>\n";
|
||||
}
|
||||
}
|
||||
|
||||
display->setHtml(result);
|
||||
}
|
||||
17
src/ui/content.h
Normal file
17
src/ui/content.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QString>
|
||||
#include <QTextEdit>
|
||||
|
||||
class Content : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Content(QWidget *parent = nullptr);
|
||||
|
||||
void parseCrabcontent(const QString &input);
|
||||
|
||||
private:
|
||||
QTextEdit *display;
|
||||
};
|
||||
@@ -9,19 +9,22 @@ NavBar::NavBar(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
auto *layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(6, 6, 6, 6);
|
||||
layout->setSpacing(6);
|
||||
layout->setContentsMargins(2, 6, 6, 6);
|
||||
layout->setSpacing(2);
|
||||
|
||||
m_back = new QToolButton(this);
|
||||
m_back->setIcon(style()->standardIcon(QStyle::SP_ArrowBack));
|
||||
m_back->setIcon(QIcon(":/icons/angle-left-solid-full.svg"));
|
||||
m_back->setIconSize(QSize(24, 24));
|
||||
m_back->setAutoRaise(true);
|
||||
|
||||
m_forward = new QToolButton(this);
|
||||
m_forward->setIcon(style()->standardIcon(QStyle::SP_ArrowForward));
|
||||
m_forward->setIcon(QIcon(":/icons/angle-right-solid-full.svg"));
|
||||
m_forward->setIconSize(QSize(24, 24));
|
||||
m_forward->setAutoRaise(true);
|
||||
|
||||
m_refresh = new QToolButton(this);
|
||||
m_refresh->setIcon(style()->standardIcon(QStyle::SP_BrowserReload));
|
||||
m_refresh->setIcon(QIcon(":/icons/arrows-rotate-solid-full.svg"));
|
||||
m_refresh->setIconSize(QSize(24, 24));
|
||||
m_refresh->setAutoRaise(true);
|
||||
|
||||
m_address = new QLineEdit(this);
|
||||
@@ -37,9 +40,8 @@ NavBar::NavBar(QWidget *parent)
|
||||
connect(m_forward, &QToolButton::clicked, this, &NavBar::forwardClicked);
|
||||
connect(m_refresh, &QToolButton::clicked, this, &NavBar::refreshClicked);
|
||||
|
||||
connect(m_address, &QLineEdit::returnPressed, this, [this] {
|
||||
emit addressEntered(m_address->text());
|
||||
});
|
||||
connect(m_address, &QLineEdit::returnPressed, this, [this]
|
||||
{ emit addressEntered(m_address->text()); });
|
||||
}
|
||||
|
||||
QLineEdit *NavBar::addressBar() const
|
||||
|
||||
@@ -24,5 +24,5 @@ private:
|
||||
QToolButton *m_back;
|
||||
QToolButton *m_forward;
|
||||
QToolButton *m_refresh;
|
||||
QLineEdit *m_address;
|
||||
QLineEdit *m_address;
|
||||
};
|
||||
|
||||
46
src/util/http.c
Normal file
46
src/util/http.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <curl/curl.h>
|
||||
|
||||
struct HttpResponse
|
||||
{
|
||||
long status;
|
||||
char *body;
|
||||
};
|
||||
|
||||
static size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userdata)
|
||||
{
|
||||
size_t total = size * nmemb;
|
||||
struct HttpResponse *resp = (struct HttpResponse *)userdata;
|
||||
|
||||
size_t old_len = resp->body ? strlen(resp->body) : 0;
|
||||
char *new_body = (char *)realloc(resp->body, old_len + total + 1);
|
||||
if (!new_body)
|
||||
return 0;
|
||||
|
||||
resp->body = new_body;
|
||||
memcpy(resp->body + old_len, ptr, total);
|
||||
resp->body[old_len + total] = '\0';
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
struct HttpResponse get(const char *url)
|
||||
{
|
||||
struct HttpResponse resp = {0, NULL};
|
||||
|
||||
CURL *curl = curl_easy_init();
|
||||
if (!curl)
|
||||
return resp;
|
||||
|
||||
resp.body = (char *)malloc(1);
|
||||
resp.body[0] = '\0';
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
|
||||
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &resp.status);
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
return resp;
|
||||
}
|
||||
Reference in New Issue
Block a user