Some refactoring

master
Melroy van den Berg 2020-12-14 19:40:08 +01:00
parent 40b4856797
commit d272b0b28f
12 changed files with 218 additions and 225 deletions

View File

@ -1,7 +1,8 @@
#include "file.h"
#include <cmark-gfm.h>
#include <stdexcept>
#include <fstream>
#include <sstream>
#include <iostream>
File::File() {}
@ -11,9 +12,14 @@ File::File() {}
* \param path File path
* \return AST model of markdown file (cmark_node)
*/
cmark_node * File::read(const std::string& path)
std::string const File::read(const std::string& path)
{
return parser.parseFile(path);
std::ifstream inFile;
inFile.open(path, std::ifstream::in);
std::stringstream strStream;
strStream << inFile.rdbuf();
return strStream.str();
}
/**
@ -22,22 +28,9 @@ cmark_node * File::read(const std::string& path)
* \throw runtime error when something goes wrong
* \return AST model of markdown file (cmark_node)
*/
cmark_node * File::fetch(const std::string& path)
std::string const File::fetch(const std::string& path)
{
std::stringstream contents;
network.fetchFile(path, &contents);
return parser.parseStream(contents);
}
std::string const File::getSource(cmark_node *node)
{
return parser.getSource(node);
}
/**
* Free AST cmark_node memory, to avoid memory leaks
*/
void File::free(cmark_node *node)
{
cmark_node_free(node);
return contents.str();
}

View File

@ -1,26 +1,22 @@
#ifndef FILE_H
#define FILE_H
#include "md-parser.h"
#include "network.h"
#include <string>
/**
* \class File
* \brief Fetch markdown file from disk or IPFS network and parse to AST
* \brief Fetch markdown file from disk or IPFS network
*/
class File
{
public:
File();
File();
cmark_node * read(const std::string& path); /*!< Read file from disk */
cmark_node * fetch(const std::string& path); /*!< Fetch file from IPFS network */
std::string const getSource(cmark_node *node); /*!< Get source code from AST */
void free(cmark_node *node); /*!< Free pointer */
std::string const read(const std::string& path); /*!< Read file from disk */
std::string const fetch(const std::string& path); /*!< Fetch file from IPFS network */
private:
Parser parser;
Network network;
Network network;
};
#endif

View File

@ -2,26 +2,49 @@
#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <iostream>
#include <string.h>
#ifdef LEGACY_CXX
#include <experimental/filesystem>
namespace n_fs = ::std::experimental::filesystem;
#else
#include <filesystem>
namespace n_fs = ::std::filesystem;
#endif
int IPFS::startIPFSDaemon()
{
// Be sure to kill any running daemons
std::system("killall -q ipfs");
// Be sure to kill any running daemons
std::system("killall -q ipfs");
/// open /dev/null for writing
int fd = open("/dev/null", O_WRONLY);
/// open /dev/null for writing
int fd = open("/dev/null", O_WRONLY);
dup2(fd, 1); // make stdout a copy of fd (> /dev/null)
dup2(fd, 2); // ..and same with stderr
close(fd); // close fd
dup2(fd, 1); // make stdout a copy of fd (> /dev/null)
dup2(fd, 2); // ..and same with stderr
close(fd); // close fd
// Ignore ISO C++ forbids converting a string constant to char*
// This is valid in C.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wwrite-strings"
// stdout and stderr now write to /dev/null
// Ready to call exec to start IPFS Daemon
constexpr char *proc[] = { "../../go-ipfs/ipfs", "daemon", "--init", "--migrate", NULL};
#pragma GCC diagnostic pop
return execv(proc[0], proc);
}
// stdout and stderr now write to /dev/null
// Ready to call exec to start IPFS Daemon
std::string currentPath = n_fs::current_path().string();
std::string executable = currentPath.append("/../../go-ipfs/ipfs");
const char* exe = executable.c_str();
std::cout << "Info: Starting IPFS Daemon from: " << exe << std::endl;
char *proc[] = { strdup(exe), strdup("daemon"), strdup("--init"), strdup("--migrate"), NULL};
return execv(exe, proc);
}
/*
std::string IPFS::getExecutablePath() {
char buff[PATH_MAX];
ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
if (len != -1) {
buff[len] = '\0';
return std::string(buff);
}
else {
return "";
}
}*/

View File

@ -1,6 +1,8 @@
#ifndef IPFS_H
#define IPFS_H
#include <string>
/**
* \class IPFS
* \brief Helper class to start/stop IPFS deamon
@ -8,6 +10,6 @@
class IPFS
{
public:
static int startIPFSDaemon();
static int startIPFSDaemon();
};
#endif

View File

@ -4,25 +4,25 @@
int main(int argc, char *argv[])
{
pid_t child_pid = fork();
if (child_pid == 0)
{
// Run by child process
return IPFS::startIPFSDaemon();
}
else if (child_pid > 0 )
{
// Parent process (child_pid is PID of child)
auto app = Gtk::Application::create(argc, argv, "org.melroy.browser");
pid_t child_pid = fork();
if (child_pid == 0)
{
// Run by child process
return IPFS::startIPFSDaemon();
}
else if (child_pid > 0 )
{
// Parent process (child_pid is PID of child)
auto app = Gtk::Application::create(argc, argv, "org.melroy.browser");
MainWindow window;
int exitCode = app->run(window);
// Kill also the child
kill(child_pid, SIGTERM);
return exitCode;
}
else // PID < 0, error
{
printf("ERROR: fork failed.\n");
}
MainWindow window;
int exitCode = app->run(window);
// Kill also the child
kill(child_pid, SIGTERM);
return exitCode;
}
else // PID < 0, error
{
printf("ERROR: fork failed.\n");
}
}

View File

@ -2,6 +2,8 @@
#include <gtkmm/menuitem.h>
#include <gtkmm/image.h>
#include <cmark-gfm.h>
#include "md-parser.h"
#ifdef LEGACY_CXX
#include <experimental/filesystem>
@ -16,7 +18,7 @@ MainWindow::MainWindow()
m_hbox_bar(Gtk::ORIENTATION_HORIZONTAL, 0),
requestPath(""),
finalRequestPath(""),
currentSourceCode("")
currentContent("")
{
set_title("DBrowser");
set_default_size(1000, 800);
@ -34,10 +36,6 @@ MainWindow::MainWindow()
m_vbox.pack_start(m_menu, false, false, 0);
m_sourceCodeDialog.setText("Hallo!?");
m_sourceCodeDialog.setText("123");
// Horizontal bar
auto styleBack = m_backButton.get_style_context();
styleBack->add_class("circular");
@ -86,7 +84,7 @@ void MainWindow::go_home()
{
this->requestPath = "";
this->finalRequestPath = "";
this->currentSourceCode = "";
this->currentContent = "";
this->m_inputField.set_text("");
m_renderArea.showStartPage();
}
@ -99,12 +97,12 @@ void MainWindow::input_activate()
void MainWindow::doRequest(const std::string &path)
{
currentSourceCode = "";
currentContent = "";
if (!path.empty()) {
requestPath = path;
}
if (requestPath.empty()) {
std::cerr << "Empty request path." << std::endl;
std::cerr << "Info: Empty request path." << std::endl;
} else {
// Check if CID
if (requestPath.rfind("ipfs://", 0) == 0) {
@ -143,12 +141,12 @@ void MainWindow::fetchFromIPFS()
// TODO: In a seperate thread/process?
// Since otherwise this may block the UI.
try {
cmark_node *fetchDoc = m_file.fetch(finalRequestPath);
m_renderArea.processDocument(fetchDoc);
currentSourceCode = m_file.getSource(fetchDoc);
m_file.free(fetchDoc);
currentContent = m_file.fetch(finalRequestPath);
cmark_node* doc = Parser::parseContent(currentContent);
m_renderArea.processDocument(doc);
cmark_node_free(doc);
} catch (const std::runtime_error &error) {
std::cerr << "IPFS Deamon is most likely down: " << error.what() << std::endl;
std::cerr << "Error: IPFS Deamon is most likely down: " << error.what() << std::endl;
// Not found (or any other issue)
m_renderArea.showMessage("Page not found!", "Detailed error message: " + std::string(error.what()));
}
@ -162,10 +160,10 @@ void MainWindow::openFromDisk()
// std::string exePath = n_fs::current_path().string();
// std::string filePath = exePath.append("/../../test.md");
try {
cmark_node *readDoc = m_file.read(finalRequestPath);
m_renderArea.processDocument(readDoc);
currentSourceCode = m_file.getSource(readDoc);
m_file.free(readDoc);
currentContent = m_file.read(finalRequestPath);
cmark_node *doc = Parser::parseContent(currentContent);
m_renderArea.processDocument(doc);
cmark_node_free(doc);
} catch (const std::runtime_error &error) {
m_renderArea.showMessage("Page not found!", "Detailed error message: " + std::string(error.what()));
}
@ -173,6 +171,6 @@ void MainWindow::openFromDisk()
void MainWindow::show_source_code_dialog()
{
m_sourceCodeDialog.setText(currentSourceCode);
m_sourceCodeDialog.setText(currentContent);
m_sourceCodeDialog.run();
}

View File

@ -16,45 +16,45 @@
class MainWindow : public Gtk::Window
{
public:
MainWindow();
MainWindow();
protected:
// Signal handlers:
// Our new improved on_button_clicked(). (see below)
void go_home();
void input_activate();
void on_button_clicked(Glib::ustring data);
void show_about();
void hide_about(int response);
void show_source_code_dialog();
// Signal handlers:
// Our new improved on_button_clicked(). (see below)
void go_home();
void input_activate();
void on_button_clicked(Glib::ustring data);
void show_about();
void hide_about(int response);
void show_source_code_dialog();
// Child widgets
Menu m_menu;
Gtk::Box m_vbox;
Gtk::Box m_hbox_bar;
Gtk::Button m_backButton;
Gtk::Button m_forwardButton;
Gtk::Button m_refreshButton;
Gtk::Button m_homeButton;
Gtk::Entry m_inputField;
Gtk::Image backIcon;
Gtk::Image forwardIcon;
Gtk::Image refreshIcon;
Gtk::Image homeIcon;
Gtk::ScrolledWindow m_scrolledWindow;
RenderArea m_renderArea;
SourceCodeDialog m_sourceCodeDialog;
About m_about;
// Child widgets
Menu m_menu;
Gtk::Box m_vbox;
Gtk::Box m_hbox_bar;
Gtk::Button m_backButton;
Gtk::Button m_forwardButton;
Gtk::Button m_refreshButton;
Gtk::Button m_homeButton;
Gtk::Entry m_inputField;
Gtk::Image backIcon;
Gtk::Image forwardIcon;
Gtk::Image refreshIcon;
Gtk::Image homeIcon;
Gtk::ScrolledWindow m_scrolledWindow;
RenderArea m_renderArea;
SourceCodeDialog m_sourceCodeDialog;
About m_about;
private:
File m_file;
std::string requestPath;
std::string finalRequestPath;
std::string currentSourceCode;
File m_file;
std::string requestPath;
std::string finalRequestPath;
std::string currentContent;
void doRequest(const std::string &path = "");
void refresh();
void fetchFromIPFS();
void openFromDisk();
void doRequest(const std::string &path = "");
void refresh();
void fetchFromIPFS();
void openFromDisk();
};
#endif

View File

@ -7,50 +7,39 @@
#include <syntax_extension.h>
#include <filesystem>
Parser::Parser(): options(CMARK_OPT_DEFAULT) {}
static const int OPTIONS = CMARK_OPT_DEFAULT;
/// Meyers Singleton
Parser::Parser()= default;
/// Destructor
Parser::~Parser()= default;
/**
* Parse markdown by file path
* @return AST structure (of type cmark_node)
* \brief Get singleton instance
* \return Helper reference (singleton)
*/
cmark_node * Parser::parseFile(const std::string &filePath)
{
// Parse to AST with cmark
FILE *file;
if (!std::filesystem::exists(filePath.c_str())) {
throw std::runtime_error("File not found.");
}
if( ( file = fopen(filePath.c_str(), "r" ) ) != NULL )
{
cmark_node *doc;
// TODO: Copy/paste cmark_parse_file() content to here, allowing me to add extensions to the parser.
doc = cmark_parse_file(file, options);
fclose(file);
return doc;
} else {
throw std::runtime_error("File open failed.");
}
Parser& Parser::getInstance() {
static Parser instance;
return instance;
}
/**
* Parse markdown file by stringstream
* Parse markdown file from string content
* @return AST structure (of type cmark_node)
*/
cmark_node * Parser::parseStream(const std::stringstream &stream)
cmark_node * Parser::parseContent(const std::string &content)
{
//cmark_node *doc;
// Parse to AST with cmark
// mark_parser *parser = cmark_parser_new(options);
// mark_parser *parser = cmark_parser_new(OPTIONS);
// Add extensions
//addMarkdownExtension(parser, "strikethrough");
//addMarkdownExtension(parser, "table");
const std::string tmp = stream.str();
const char *data = tmp.c_str();
const char *data = content.c_str();
// TODO: Copy cmark_parse_document() to be able to add extensions to the parser
return cmark_parse_document(data, strlen(data), options);
return cmark_parse_document(data, strlen(data), OPTIONS);
}
/**
@ -58,18 +47,7 @@ cmark_node * Parser::parseStream(const std::stringstream &stream)
*/
std::string const Parser::renderHTML(cmark_node *node)
{
char *tmp = cmark_render_html(node, options, NULL);
std::string output = std::string(tmp);
free(tmp);
return output;
}
/**
* Get just the plain text
*/
std::string const Parser::getSource(cmark_node *node)
{
char *tmp = cmark_render_commonmark(node, options, 0);
char *tmp = cmark_render_html(node, OPTIONS, NULL);
std::string output = std::string(tmp);
free(tmp);
return output;

View File

@ -11,14 +11,18 @@
class Parser
{
public:
Parser();
cmark_node * parseFile(const std::string &filePath);
cmark_node * parseStream(const std::stringstream &stream);
std::string const renderHTML(cmark_node *node);
std::string const getSource(cmark_node *node);
// Singleton
static Parser& getInstance();
static cmark_node * parseContent(const std::string &content);
static std::string const renderHTML(cmark_node *node);
private:
int options;
void addMarkdownExtension(cmark_parser *parser, const char *extName);
Parser();
~Parser();
Parser(const Parser&)= delete;
Parser& operator=(const Parser&)= delete;
static void addMarkdownExtension(cmark_parser *parser, const char *extName);
};
#endif

View File

@ -16,6 +16,6 @@ public:
void fetchFile(const std::string& path, std::iostream* response);
private:
ipfs::Client m_client;
ipfs::Client m_client;
};
#endif

View File

@ -6,81 +6,81 @@
#include <cmark-gfm.h>
struct text_struct {
int x;
int y;
Glib::RefPtr<Pango::Layout> layout;
int x;
int y;
Glib::RefPtr<Pango::Layout> layout;
};
struct line_struct {
int start_x;
int start_y;
int end_x; // -1 means auto-size
int end_y;
int margin_end_x;
double height;
std::string hex_color;
Cairo::LineCap cap;
int start_x;
int start_y;
int end_x; // -1 means auto-size
int end_y;
int margin_end_x;
double height;
std::string hex_color;
Cairo::LineCap cap;
};
class RenderArea : public Gtk::DrawingArea
{
public:
RenderArea();
virtual ~RenderArea();
RenderArea();
virtual ~RenderArea();
void processDocument(cmark_node *root_node);
void showMessage(const std::string &message, const std::string &detailed_info = "");
void showStartPage();
void processDocument(cmark_node *root_node);
void showMessage(const std::string &message, const std::string &detailed_info = "");
void showStartPage();
protected:
std::list<text_struct> m_textList;
std::list<line_struct> m_lines;
std::list<text_struct> m_textList;
std::list<line_struct> m_lines;
// Override default signal handler:
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
// Override default signal handler:
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
private:
int currentX;
int currentY;
int sceneMarginX;
int sceneMarginY;
int currentXList;
int headingLevel;
int listLevel;
int wordSpacing;
int highestWidth;
int highestHeight;
int paragraphMargin;
int headingMargin;
int listMargin;
int horizontalLineMargin;
int listXOffset;
bool isBold;
bool isItalic;
int bulletListLevel;
int orderedListLevel;
bool isOrderedList;
std::map<int,int> orderedListCounters;
int fontSize;
std::string fontFamily;
int pageWidth;
int pageHeight;
int currentX;
int currentY;
int sceneMarginX;
int sceneMarginY;
int currentXList;
int headingLevel;
int listLevel;
int wordSpacing;
int highestWidth;
int highestHeight;
int paragraphMargin;
int headingMargin;
int listMargin;
int horizontalLineMargin;
int listXOffset;
bool isBold;
bool isItalic;
int bulletListLevel;
int orderedListLevel;
bool isOrderedList;
std::map<int,int> orderedListCounters;
int fontSize;
std::string fontFamily;
int pageWidth;
int pageHeight;
Pango::FontDescription defaultFont;
Pango::FontDescription boldFont;
Pango::FontDescription italicFont;
Pango::FontDescription boldItalicFont;
Pango::FontDescription heading1Font;
Pango::FontDescription heading2Font;
Pango::FontDescription heading3Font;
Pango::FontDescription heading4Font;
Pango::FontDescription defaultFont;
Pango::FontDescription boldFont;
Pango::FontDescription italicFont;
Pango::FontDescription boldItalicFont;
Pango::FontDescription heading1Font;
Pango::FontDescription heading2Font;
Pango::FontDescription heading3Font;
Pango::FontDescription heading4Font;
void createPangoContexts();
void clear();
void processNode(cmark_node *node, cmark_event_type ev_type);
void redraw();
std::string const intToRoman(int num);
void hexToRGB(const std::string& hex, double &r, double &g, double &b);
void createPangoContexts();
void clear();
void processNode(cmark_node *node, cmark_event_type ev_type);
void redraw();
std::string const intToRoman(int num);
void hexToRGB(const std::string& hex, double &r, double &g, double &b);
};
#endif

View File

@ -1,4 +1,3 @@
missingIncludeSystem
missingInclude:lib/*
unusedFunction
unusedPrivateFunction
unusedFunction