diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/MdiWindow.h b/MdiWindow.h index 76d7f1b..35ef9c3 100644 --- a/MdiWindow.h +++ b/MdiWindow.h @@ -4,78 +4,19 @@ #include #include +#include "Objects.h" +#include "MdiChild.h" -class MdiChild; class QAction; class QMenu; class QMdiArea; class QMdiSubWindow; class QSignalMapper; +class QTcpServer; class Ui_MainWindow; -class MdiChild : public QTextEdit -{ - Q_OBJECT -public: - MdiChild(); - ~MdiChild(); - - void newFile(); - bool loadFile(const QString &fileName); - bool save(); - bool saveAs(); - bool saveFile(const QString &fileName); - QString userFriendlyCurrentFile(); - QString currentFile() { return curFile; } - - void markdownSelection(const char* preText, const char* postText); - - void bold(); - void italic(); - void quote(); - void code(); - void heading1(); - void heading2(); - void heading3(); - void heading4(); - void hyperlink(); - void image(); - void unorderedList(); - void orderedList(); - void horizontalRule(); - void timestamp(); - void pageNumber(); - void pageCount(); - void del(); - void undo(); - void redo(); - void find(); - void findNext(); - void findPrevious(); - void goToLine(); - -signals: - void closing(); - void documentContentsChanged(); - -private slots: - void documentWasModified(); - -protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - -private: - bool maybeSave(); - void setCurrentFile(const QString &fileName); - QString strippedName(const QString &fullFileName); - - QString curFile; - bool isUntitled; -}; - - /* class MdiOptions { @@ -109,8 +50,12 @@ void save(); void saveAs(); + void handleRequest(); void updatePreview(); + void setWebPreviewURL(); + void refreshWebPreview(); + // Edit menu actions #ifndef QT_NO_CLIPBOARD void cut(); @@ -159,12 +104,26 @@ void switchLayoutDirection(); void setActiveSubWindow(QWidget *window); + void changeRootObject(const QModelIndex &index); + void changePropertiesObject(const QModelIndex &index); + + // Dialog events + void upgradeClicked(); + private: + void changeProjectTree(QObject *rootObject); + void updateObjectTree(QObject *rootObject); + void updatePropertiesView(QObject *object); + void setupServer(); void readSettings(); + void readLicense(); void writeSettings(); MdiChild *activeMdiChild(); QMdiSubWindow *findMdiChild(const QString &fileName); + //Solution solution; + QByteArray pdfContents; + QTcpServer *server; QMdiArea *mdiArea; QSignalMapper *windowMapper; Ui_MainWindow *appWindow; diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/MdiWindow.h b/MdiWindow.h index 76d7f1b..35ef9c3 100644 --- a/MdiWindow.h +++ b/MdiWindow.h @@ -4,78 +4,19 @@ #include #include +#include "Objects.h" +#include "MdiChild.h" -class MdiChild; class QAction; class QMenu; class QMdiArea; class QMdiSubWindow; class QSignalMapper; +class QTcpServer; class Ui_MainWindow; -class MdiChild : public QTextEdit -{ - Q_OBJECT -public: - MdiChild(); - ~MdiChild(); - - void newFile(); - bool loadFile(const QString &fileName); - bool save(); - bool saveAs(); - bool saveFile(const QString &fileName); - QString userFriendlyCurrentFile(); - QString currentFile() { return curFile; } - - void markdownSelection(const char* preText, const char* postText); - - void bold(); - void italic(); - void quote(); - void code(); - void heading1(); - void heading2(); - void heading3(); - void heading4(); - void hyperlink(); - void image(); - void unorderedList(); - void orderedList(); - void horizontalRule(); - void timestamp(); - void pageNumber(); - void pageCount(); - void del(); - void undo(); - void redo(); - void find(); - void findNext(); - void findPrevious(); - void goToLine(); - -signals: - void closing(); - void documentContentsChanged(); - -private slots: - void documentWasModified(); - -protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - -private: - bool maybeSave(); - void setCurrentFile(const QString &fileName); - QString strippedName(const QString &fullFileName); - - QString curFile; - bool isUntitled; -}; - - /* class MdiOptions { @@ -109,8 +50,12 @@ void save(); void saveAs(); + void handleRequest(); void updatePreview(); + void setWebPreviewURL(); + void refreshWebPreview(); + // Edit menu actions #ifndef QT_NO_CLIPBOARD void cut(); @@ -159,12 +104,26 @@ void switchLayoutDirection(); void setActiveSubWindow(QWidget *window); + void changeRootObject(const QModelIndex &index); + void changePropertiesObject(const QModelIndex &index); + + // Dialog events + void upgradeClicked(); + private: + void changeProjectTree(QObject *rootObject); + void updateObjectTree(QObject *rootObject); + void updatePropertiesView(QObject *object); + void setupServer(); void readSettings(); + void readLicense(); void writeSettings(); MdiChild *activeMdiChild(); QMdiSubWindow *findMdiChild(const QString &fileName); + //Solution solution; + QByteArray pdfContents; + QTcpServer *server; QMdiArea *mdiArea; QSignalMapper *windowMapper; Ui_MainWindow *appWindow; diff --git a/ObjectVisitor.h b/ObjectVisitor.h new file mode 100644 index 0000000..12cf25f --- /dev/null +++ b/ObjectVisitor.h @@ -0,0 +1,59 @@ +#ifndef OBJECTVISITOR_H +#define OBJECTVISITOR_H + + +#include +#include +#include +#include + + +class Visitor +{ +public: + Visitor() {} + virtual ~Visitor() {} + + virtual void enterObject(const char* className, const char* objectName) = 0; + virtual void leaveObject(const char* className, const char* objectName) = 0; + + // Reads or writes a property value + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) = 0; + + // By default, it is a reader, but implementing this enables a visitor that sets values + virtual bool isWriting() { return false; } +}; + + +void Visit(Visitor& visitor, QObject* object) +{ + std::string objectName = object->objectName().toLocal8Bit().data(); + if (objectName.size() <= 1) { + objectName = std::to_string((uint64_t)(void*)object); + } + visitor.enterObject(object->metaObject()->className(), objectName.c_str()); + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + if (visitor.isWriting()) { + QVariant value; + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + property.write(object, value); + + } else { + QVariant value = property.read(object); + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + } + } + for (int i = 0; i < object->children().count(); i++) + { + Visit(visitor, object->children()[i]); + } + visitor.leaveObject(object->metaObject()->className(), objectName.c_str()); +} + + +#endif // OBJECTVISITOR_H diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/MdiWindow.h b/MdiWindow.h index 76d7f1b..35ef9c3 100644 --- a/MdiWindow.h +++ b/MdiWindow.h @@ -4,78 +4,19 @@ #include #include +#include "Objects.h" +#include "MdiChild.h" -class MdiChild; class QAction; class QMenu; class QMdiArea; class QMdiSubWindow; class QSignalMapper; +class QTcpServer; class Ui_MainWindow; -class MdiChild : public QTextEdit -{ - Q_OBJECT -public: - MdiChild(); - ~MdiChild(); - - void newFile(); - bool loadFile(const QString &fileName); - bool save(); - bool saveAs(); - bool saveFile(const QString &fileName); - QString userFriendlyCurrentFile(); - QString currentFile() { return curFile; } - - void markdownSelection(const char* preText, const char* postText); - - void bold(); - void italic(); - void quote(); - void code(); - void heading1(); - void heading2(); - void heading3(); - void heading4(); - void hyperlink(); - void image(); - void unorderedList(); - void orderedList(); - void horizontalRule(); - void timestamp(); - void pageNumber(); - void pageCount(); - void del(); - void undo(); - void redo(); - void find(); - void findNext(); - void findPrevious(); - void goToLine(); - -signals: - void closing(); - void documentContentsChanged(); - -private slots: - void documentWasModified(); - -protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - -private: - bool maybeSave(); - void setCurrentFile(const QString &fileName); - QString strippedName(const QString &fullFileName); - - QString curFile; - bool isUntitled; -}; - - /* class MdiOptions { @@ -109,8 +50,12 @@ void save(); void saveAs(); + void handleRequest(); void updatePreview(); + void setWebPreviewURL(); + void refreshWebPreview(); + // Edit menu actions #ifndef QT_NO_CLIPBOARD void cut(); @@ -159,12 +104,26 @@ void switchLayoutDirection(); void setActiveSubWindow(QWidget *window); + void changeRootObject(const QModelIndex &index); + void changePropertiesObject(const QModelIndex &index); + + // Dialog events + void upgradeClicked(); + private: + void changeProjectTree(QObject *rootObject); + void updateObjectTree(QObject *rootObject); + void updatePropertiesView(QObject *object); + void setupServer(); void readSettings(); + void readLicense(); void writeSettings(); MdiChild *activeMdiChild(); QMdiSubWindow *findMdiChild(const QString &fileName); + //Solution solution; + QByteArray pdfContents; + QTcpServer *server; QMdiArea *mdiArea; QSignalMapper *windowMapper; Ui_MainWindow *appWindow; diff --git a/ObjectVisitor.h b/ObjectVisitor.h new file mode 100644 index 0000000..12cf25f --- /dev/null +++ b/ObjectVisitor.h @@ -0,0 +1,59 @@ +#ifndef OBJECTVISITOR_H +#define OBJECTVISITOR_H + + +#include +#include +#include +#include + + +class Visitor +{ +public: + Visitor() {} + virtual ~Visitor() {} + + virtual void enterObject(const char* className, const char* objectName) = 0; + virtual void leaveObject(const char* className, const char* objectName) = 0; + + // Reads or writes a property value + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) = 0; + + // By default, it is a reader, but implementing this enables a visitor that sets values + virtual bool isWriting() { return false; } +}; + + +void Visit(Visitor& visitor, QObject* object) +{ + std::string objectName = object->objectName().toLocal8Bit().data(); + if (objectName.size() <= 1) { + objectName = std::to_string((uint64_t)(void*)object); + } + visitor.enterObject(object->metaObject()->className(), objectName.c_str()); + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + if (visitor.isWriting()) { + QVariant value; + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + property.write(object, value); + + } else { + QVariant value = property.read(object); + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + } + } + for (int i = 0; i < object->children().count(); i++) + { + Visit(visitor, object->children()[i]); + } + visitor.leaveObject(object->metaObject()->className(), objectName.c_str()); +} + + +#endif // OBJECTVISITOR_H diff --git a/Objects.h b/Objects.h new file mode 100644 index 0000000..90e7bb1 --- /dev/null +++ b/Objects.h @@ -0,0 +1,167 @@ +#ifndef OBJECTS_H +#define OBJECTS_H + + +#include +#include +#include +#include +#include +#include +#include + + +class EnumEditor : public QWidget +{ + Q_OBJECT +public slots: + void ListSelectionChanged(); + void ComboSelectionChanged(); +public: + EnumEditor(QMetaEnum metaEnum); +private: + QListWidget* lw; + QComboBox* cb; + QSpinBox* sb; + QLabel* str; + QMetaEnum m_metaEnum; +}; + + +// Property Manager Supported types: +// int, bool, double, enums, flags +// QString, QDate, QTime, QDateTime, QKeySequence +// QChar, QLocale, QPoint, QPointF, QSize, QSizeF +// QRect, QRectF, QSizePolicy, QFont, QColor, QCursor + + +#define PROP_WRAP(type, name) \ + Q_PROPERTY(type name READ get##name WRITE set##name) \ + type get##name() const { return m_##name; } \ + void set##name(type val) { m_##name = val; } \ + type m_##name; + +#define CHILD_PTR_PROP_WRAP(type, name) \ + Q_PROPERTY(type* name READ get##name WRITE set##name) \ + type* get##name() const { return m_##name; } \ + void set##name(type* val) { \ + /* if (m_##name) children().removeAll((QObject*)m_##name); */ \ + val->setParent(this); \ + m_##name = val; \ + } \ + type* m_##name = nullptr; + + +class MyObjectTest : public QObject +{ + Q_OBJECT + Q_ENUMS(AnotherEnum) + Q_ENUMS(TestEnum) + Q_FLAGS(TestFlags) +public: + enum TestFlags { FlagValue1 = 1, AnotherFlagValue = 2, FlagEtc = 4, FlagBlah = 8 }; + enum TestEnum { EnumValue1, AnotherValue, Etc, Blah }; + enum AnotherEnum { AEnumValue1, AnAnotherValue, Etc2 }; + + explicit MyObjectTest() : QObject() { + m_An_Int_Value = 10; + m_A_Double = 11.0; + //m_An_Enum = EnumValue1; + //memset(this, 0, sizeof(MyObjectTest)); + } + ~MyObjectTest() { + } + + PROP_WRAP(int, An_Int_Value) + PROP_WRAP(bool, A_Bool) + PROP_WRAP(double, A_Double) + PROP_WRAP(TestEnum,An_Enum1) + PROP_WRAP(TestEnum,An_Enum2) + PROP_WRAP(QFlags,A_Flags) + PROP_WRAP(QString, A_String) + PROP_WRAP(QDate, A_Date) + PROP_WRAP(QTime, A_Time) + PROP_WRAP(QDateTime, A_Date_and_Time) + PROP_WRAP(QKeySequence, A_Key_Sequence) + PROP_WRAP(QChar, A_Char) + PROP_WRAP(QLocale, A_Locale) + PROP_WRAP(QPoint, A_Point) + PROP_WRAP(QPointF, A_PointF) + PROP_WRAP(QSize, A_Size) + PROP_WRAP(QSizeF, A_SizeF) + PROP_WRAP(QRect, A_Rect) + PROP_WRAP(QRectF, A_RectF) + //PROP_WRAP(QSizePolicy, A_SizePolicy) + //PROP_WRAP(QFont, A_Font) + PROP_WRAP(QColor, A_Color) + //PROP_WRAP(QCursor, A_Cursor) + // flags +}; + + + +class Template : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) + PROP_WRAP(QColor, Color) +}; + + +class Output : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + PROP_WRAP(QString, Title) + PROP_WRAP(QString, Filename) + PROP_WRAP(FileTypes, FileType) +}; + + +class Input : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) +}; + + +class Project : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + //PROP_WRAP(QString, Name) + PROP_WRAP(QString, Author) + //PROP_WRAP(Template*, Template) + //PROP_WRAP(QList, Inputs) + //PROP_WRAP(Output*, Output) + + //CHILD_PTR_PROP_WRAP(Output, Output) + //CHILD_PTR_PROP_WRAP(Template, Template) + + PROP_WRAP(QString, Title) + PROP_WRAP(QString, OutputFilename) + PROP_WRAP(FileTypes, OutputFileType) + + PROP_WRAP(QString, Template) + PROP_WRAP(QColor, Color) + + void AddInput(Input* in) { in->setParent(this); } +}; + + +class Solution : public QObject +{ + Q_OBJECT +public: + //PROP_WRAP(QList, Projects) + void AddProject(Project* proj) { proj->setParent(this); } +}; + + +#endif // OBJECTS_H diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/MdiWindow.h b/MdiWindow.h index 76d7f1b..35ef9c3 100644 --- a/MdiWindow.h +++ b/MdiWindow.h @@ -4,78 +4,19 @@ #include #include +#include "Objects.h" +#include "MdiChild.h" -class MdiChild; class QAction; class QMenu; class QMdiArea; class QMdiSubWindow; class QSignalMapper; +class QTcpServer; class Ui_MainWindow; -class MdiChild : public QTextEdit -{ - Q_OBJECT -public: - MdiChild(); - ~MdiChild(); - - void newFile(); - bool loadFile(const QString &fileName); - bool save(); - bool saveAs(); - bool saveFile(const QString &fileName); - QString userFriendlyCurrentFile(); - QString currentFile() { return curFile; } - - void markdownSelection(const char* preText, const char* postText); - - void bold(); - void italic(); - void quote(); - void code(); - void heading1(); - void heading2(); - void heading3(); - void heading4(); - void hyperlink(); - void image(); - void unorderedList(); - void orderedList(); - void horizontalRule(); - void timestamp(); - void pageNumber(); - void pageCount(); - void del(); - void undo(); - void redo(); - void find(); - void findNext(); - void findPrevious(); - void goToLine(); - -signals: - void closing(); - void documentContentsChanged(); - -private slots: - void documentWasModified(); - -protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - -private: - bool maybeSave(); - void setCurrentFile(const QString &fileName); - QString strippedName(const QString &fullFileName); - - QString curFile; - bool isUntitled; -}; - - /* class MdiOptions { @@ -109,8 +50,12 @@ void save(); void saveAs(); + void handleRequest(); void updatePreview(); + void setWebPreviewURL(); + void refreshWebPreview(); + // Edit menu actions #ifndef QT_NO_CLIPBOARD void cut(); @@ -159,12 +104,26 @@ void switchLayoutDirection(); void setActiveSubWindow(QWidget *window); + void changeRootObject(const QModelIndex &index); + void changePropertiesObject(const QModelIndex &index); + + // Dialog events + void upgradeClicked(); + private: + void changeProjectTree(QObject *rootObject); + void updateObjectTree(QObject *rootObject); + void updatePropertiesView(QObject *object); + void setupServer(); void readSettings(); + void readLicense(); void writeSettings(); MdiChild *activeMdiChild(); QMdiSubWindow *findMdiChild(const QString &fileName); + //Solution solution; + QByteArray pdfContents; + QTcpServer *server; QMdiArea *mdiArea; QSignalMapper *windowMapper; Ui_MainWindow *appWindow; diff --git a/ObjectVisitor.h b/ObjectVisitor.h new file mode 100644 index 0000000..12cf25f --- /dev/null +++ b/ObjectVisitor.h @@ -0,0 +1,59 @@ +#ifndef OBJECTVISITOR_H +#define OBJECTVISITOR_H + + +#include +#include +#include +#include + + +class Visitor +{ +public: + Visitor() {} + virtual ~Visitor() {} + + virtual void enterObject(const char* className, const char* objectName) = 0; + virtual void leaveObject(const char* className, const char* objectName) = 0; + + // Reads or writes a property value + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) = 0; + + // By default, it is a reader, but implementing this enables a visitor that sets values + virtual bool isWriting() { return false; } +}; + + +void Visit(Visitor& visitor, QObject* object) +{ + std::string objectName = object->objectName().toLocal8Bit().data(); + if (objectName.size() <= 1) { + objectName = std::to_string((uint64_t)(void*)object); + } + visitor.enterObject(object->metaObject()->className(), objectName.c_str()); + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + if (visitor.isWriting()) { + QVariant value; + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + property.write(object, value); + + } else { + QVariant value = property.read(object); + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + } + } + for (int i = 0; i < object->children().count(); i++) + { + Visit(visitor, object->children()[i]); + } + visitor.leaveObject(object->metaObject()->className(), objectName.c_str()); +} + + +#endif // OBJECTVISITOR_H diff --git a/Objects.h b/Objects.h new file mode 100644 index 0000000..90e7bb1 --- /dev/null +++ b/Objects.h @@ -0,0 +1,167 @@ +#ifndef OBJECTS_H +#define OBJECTS_H + + +#include +#include +#include +#include +#include +#include +#include + + +class EnumEditor : public QWidget +{ + Q_OBJECT +public slots: + void ListSelectionChanged(); + void ComboSelectionChanged(); +public: + EnumEditor(QMetaEnum metaEnum); +private: + QListWidget* lw; + QComboBox* cb; + QSpinBox* sb; + QLabel* str; + QMetaEnum m_metaEnum; +}; + + +// Property Manager Supported types: +// int, bool, double, enums, flags +// QString, QDate, QTime, QDateTime, QKeySequence +// QChar, QLocale, QPoint, QPointF, QSize, QSizeF +// QRect, QRectF, QSizePolicy, QFont, QColor, QCursor + + +#define PROP_WRAP(type, name) \ + Q_PROPERTY(type name READ get##name WRITE set##name) \ + type get##name() const { return m_##name; } \ + void set##name(type val) { m_##name = val; } \ + type m_##name; + +#define CHILD_PTR_PROP_WRAP(type, name) \ + Q_PROPERTY(type* name READ get##name WRITE set##name) \ + type* get##name() const { return m_##name; } \ + void set##name(type* val) { \ + /* if (m_##name) children().removeAll((QObject*)m_##name); */ \ + val->setParent(this); \ + m_##name = val; \ + } \ + type* m_##name = nullptr; + + +class MyObjectTest : public QObject +{ + Q_OBJECT + Q_ENUMS(AnotherEnum) + Q_ENUMS(TestEnum) + Q_FLAGS(TestFlags) +public: + enum TestFlags { FlagValue1 = 1, AnotherFlagValue = 2, FlagEtc = 4, FlagBlah = 8 }; + enum TestEnum { EnumValue1, AnotherValue, Etc, Blah }; + enum AnotherEnum { AEnumValue1, AnAnotherValue, Etc2 }; + + explicit MyObjectTest() : QObject() { + m_An_Int_Value = 10; + m_A_Double = 11.0; + //m_An_Enum = EnumValue1; + //memset(this, 0, sizeof(MyObjectTest)); + } + ~MyObjectTest() { + } + + PROP_WRAP(int, An_Int_Value) + PROP_WRAP(bool, A_Bool) + PROP_WRAP(double, A_Double) + PROP_WRAP(TestEnum,An_Enum1) + PROP_WRAP(TestEnum,An_Enum2) + PROP_WRAP(QFlags,A_Flags) + PROP_WRAP(QString, A_String) + PROP_WRAP(QDate, A_Date) + PROP_WRAP(QTime, A_Time) + PROP_WRAP(QDateTime, A_Date_and_Time) + PROP_WRAP(QKeySequence, A_Key_Sequence) + PROP_WRAP(QChar, A_Char) + PROP_WRAP(QLocale, A_Locale) + PROP_WRAP(QPoint, A_Point) + PROP_WRAP(QPointF, A_PointF) + PROP_WRAP(QSize, A_Size) + PROP_WRAP(QSizeF, A_SizeF) + PROP_WRAP(QRect, A_Rect) + PROP_WRAP(QRectF, A_RectF) + //PROP_WRAP(QSizePolicy, A_SizePolicy) + //PROP_WRAP(QFont, A_Font) + PROP_WRAP(QColor, A_Color) + //PROP_WRAP(QCursor, A_Cursor) + // flags +}; + + + +class Template : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) + PROP_WRAP(QColor, Color) +}; + + +class Output : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + PROP_WRAP(QString, Title) + PROP_WRAP(QString, Filename) + PROP_WRAP(FileTypes, FileType) +}; + + +class Input : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) +}; + + +class Project : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + //PROP_WRAP(QString, Name) + PROP_WRAP(QString, Author) + //PROP_WRAP(Template*, Template) + //PROP_WRAP(QList, Inputs) + //PROP_WRAP(Output*, Output) + + //CHILD_PTR_PROP_WRAP(Output, Output) + //CHILD_PTR_PROP_WRAP(Template, Template) + + PROP_WRAP(QString, Title) + PROP_WRAP(QString, OutputFilename) + PROP_WRAP(FileTypes, OutputFileType) + + PROP_WRAP(QString, Template) + PROP_WRAP(QColor, Color) + + void AddInput(Input* in) { in->setParent(this); } +}; + + +class Solution : public QObject +{ + Q_OBJECT +public: + //PROP_WRAP(QList, Projects) + void AddProject(Project* proj) { proj->setParent(this); } +}; + + +#endif // OBJECTS_H diff --git a/QtProject/MakePDF.pro b/QtProject/MakePDF.pro index f4e410c..4026759 100644 --- a/QtProject/MakePDF.pro +++ b/QtProject/MakePDF.pro @@ -1,21 +1,24 @@ -QT += core gui widgets +# QT += webkitwidgets network widgets +CONFIG += qt +QT += core gui widgets webkitwidgets +#QT += svg CONFIG -= flat TARGET = MakePDF DEFINES += \ - GUI_APP=1 + GUI_APP=1 RESOURCES += \ - ../Resources/resources.qrc + ../Resources/resources.qrc FORMS += \ - ../Resources/forms/About.ui \ - ../Resources/forms/NewProjectWizard.ui \ - ../Resources/forms/ExtensibleObjectModelUI.ui \ - ../Resources/forms/SendBugReport.ui \ + ../Resources/forms/About.ui \ + ../Resources/forms/NewProjectWizard.ui \ + ../Resources/forms/ExtensibleObjectModelUI.ui \ + ../Resources/forms/SendBugReport.ui \ ../Resources/forms/Help.ui \ ../Resources/forms/CheckUpdates.ui \ ../Resources/forms/LicenseUpgrade.ui \ @@ -23,136 +26,174 @@ ../Resources/forms/PaletteEditor.ui INCLUDEPATH += \ - ../Framework \ - ../3rdParty/hoedown \ - ../3rdParty/libharu/include \ - ../3rdParty/TinyXML++ + ../Framework \ + ../3rdParty/hoedown \ + ../3rdParty/libharu/include \ + ../3rdParty/TinyXML++ \ + ../3rdParty/qtpropertybrowser/src HEADERS += \ - ../Framework/EventLog.h \ - ../Framework/Expected.h \ - ../Framework/Final.h \ - ../Framework/Finally.h \ - ../Framework/GenericTable.h \ - ../Framework/GenericTableUI.h \ - ../Framework/NonCopyable.h \ - ../Framework/Utilities.h \ + ../Framework/EventLog.h \ + ../Framework/Expected.h \ + ../Framework/Final.h \ + ../Framework/Finally.h \ + ../Framework/GenericTable.h \ + ../Framework/GenericTableUI.h \ + ../Framework/NonCopyable.h \ + ../Framework/Utilities.h \ + ../Framework/SystemInfomation.h \ + ../Framework/Array.h \ + ../Framework/Macros.h \ + ../Framework/ObjectTreeModel.h \ + ../Version.h \ + ../Util.h \ ../ui.h \ + ../MdiChild.h \ ../MdiWindow.h \ ../ColorPicker.h \ - ../Version.h + ../DocConvert.h \ + ../Objects.h \ + ../ObjectVisitor.h HEADERS += \ - ../DocOutput.h \ - ../DocProject.h \ - ../DocStyle.h \ - ../DocTemplate.h \ - ../DocVisitor.h \ - ../DocSVG.h + ../DocOutput.h \ + ../DocProject.h \ + ../DocStyle.h \ + ../DocTemplate.h \ + ../DocVisitor.h \ + ../DocSVG.h SOURCES += \ - ../Framework/Tests.cpp \ - ../Framework/Utilities.cpp \ - ../Framework/EventLog.cpp \ + ../Framework/Tests.cpp \ + ../Framework/Utilities.cpp \ + ../Framework/EventLog.cpp \ + ../MdiChild.cpp \ ../MdiWindow.cpp \ ../ColorPicker.cpp \ - ../Version.cpp + ../Version.cpp \ + ../Framework/SystemInfomation.cpp \ + ../DocConvert.cpp \ + ../Framework/ObjectTreeModel.cpp SOURCES += \ - ../DocOutput.cpp \ - ../DocProject.cpp \ - ../DocStyle.cpp \ - ../DocTemplate.cpp \ - ../DocVisitor.cpp \ - ../DocSVG.cpp \ - ../main.cpp + ../DocOutput.cpp \ + ../DocProject.cpp \ + ../DocStyle.cpp \ + ../DocTemplate.cpp \ + ../DocVisitor.cpp \ + ../DocSVG.cpp \ + ../main.cpp SOURCES += \ - ../3rdParty/hoedown/autolink.c \ - ../3rdParty/hoedown/buffer.c \ - ../3rdParty/hoedown/document.c \ - ../3rdParty/hoedown/escape.c \ - ../3rdParty/hoedown/html.c \ - ../3rdParty/hoedown/html_blocks.c \ - ../3rdParty/hoedown/stack.c + ../3rdParty/hoedown/autolink.c \ + ../3rdParty/hoedown/buffer.c \ + ../3rdParty/hoedown/document.c \ + ../3rdParty/hoedown/escape.c \ + ../3rdParty/hoedown/html.c \ + ../3rdParty/hoedown/html_blocks.c \ + ../3rdParty/hoedown/stack.c SOURCES += \ - ../3rdParty/libharu/src/hpdf_3dmeasure.c \ - ../3rdParty/libharu/src/hpdf_annotation.c \ - ../3rdParty/libharu/src/hpdf_array.c \ - ../3rdParty/libharu/src/hpdf_binary.c \ - ../3rdParty/libharu/src/hpdf_boolean.c \ - ../3rdParty/libharu/src/hpdf_catalog.c \ - ../3rdParty/libharu/src/hpdf_destination.c \ - ../3rdParty/libharu/src/hpdf_dict.c \ - ../3rdParty/libharu/src/hpdf_doc.c \ - ../3rdParty/libharu/src/hpdf_doc_png.c \ - ../3rdParty/libharu/src/hpdf_encoder.c \ - ../3rdParty/libharu/src/hpdf_encoder_utf.c \ - ../3rdParty/libharu/src/hpdf_encrypt.c \ - ../3rdParty/libharu/src/hpdf_encryptdict.c \ - ../3rdParty/libharu/src/hpdf_error.c \ - ../3rdParty/libharu/src/hpdf_exdata.c \ - ../3rdParty/libharu/src/hpdf_ext_gstate.c \ - ../3rdParty/libharu/src/hpdf_font.c \ - ../3rdParty/libharu/src/hpdf_fontdef.c \ - ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ - ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ - ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ - ../3rdParty/libharu/src/hpdf_font_cid.c \ - ../3rdParty/libharu/src/hpdf_font_tt.c \ - ../3rdParty/libharu/src/hpdf_font_type1.c \ - ../3rdParty/libharu/src/hpdf_gstate.c \ - ../3rdParty/libharu/src/hpdf_image.c \ - ../3rdParty/libharu/src/hpdf_image_png.c \ - ../3rdParty/libharu/src/hpdf_info.c \ - ../3rdParty/libharu/src/hpdf_list.c \ - ../3rdParty/libharu/src/hpdf_mmgr.c \ - ../3rdParty/libharu/src/hpdf_name.c \ - ../3rdParty/libharu/src/hpdf_namedict.c \ - ../3rdParty/libharu/src/hpdf_null.c \ - ../3rdParty/libharu/src/hpdf_number.c \ - ../3rdParty/libharu/src/hpdf_objects.c \ - ../3rdParty/libharu/src/hpdf_outline.c \ - ../3rdParty/libharu/src/hpdf_pages.c \ - ../3rdParty/libharu/src/hpdf_page_label.c \ - ../3rdParty/libharu/src/hpdf_page_operator.c \ - ../3rdParty/libharu/src/hpdf_pdfa.c \ - ../3rdParty/libharu/src/hpdf_real.c \ - ../3rdParty/libharu/src/hpdf_streams.c \ - ../3rdParty/libharu/src/hpdf_string.c \ - ../3rdParty/libharu/src/hpdf_u3d.c \ - ../3rdParty/libharu/src/hpdf_utils.c \ - ../3rdParty/libharu/src/hpdf_xref.c + ../3rdParty/libharu/src/hpdf_3dmeasure.c \ + ../3rdParty/libharu/src/hpdf_annotation.c \ + ../3rdParty/libharu/src/hpdf_array.c \ + ../3rdParty/libharu/src/hpdf_binary.c \ + ../3rdParty/libharu/src/hpdf_boolean.c \ + ../3rdParty/libharu/src/hpdf_catalog.c \ + ../3rdParty/libharu/src/hpdf_destination.c \ + ../3rdParty/libharu/src/hpdf_dict.c \ + ../3rdParty/libharu/src/hpdf_doc.c \ + ../3rdParty/libharu/src/hpdf_doc_png.c \ + ../3rdParty/libharu/src/hpdf_encoder.c \ + ../3rdParty/libharu/src/hpdf_encoder_utf.c \ + ../3rdParty/libharu/src/hpdf_encrypt.c \ + ../3rdParty/libharu/src/hpdf_encryptdict.c \ + ../3rdParty/libharu/src/hpdf_error.c \ + ../3rdParty/libharu/src/hpdf_exdata.c \ + ../3rdParty/libharu/src/hpdf_ext_gstate.c \ + ../3rdParty/libharu/src/hpdf_font.c \ + ../3rdParty/libharu/src/hpdf_fontdef.c \ + ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ + ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ + ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ + ../3rdParty/libharu/src/hpdf_font_cid.c \ + ../3rdParty/libharu/src/hpdf_font_tt.c \ + ../3rdParty/libharu/src/hpdf_font_type1.c \ + ../3rdParty/libharu/src/hpdf_gstate.c \ + ../3rdParty/libharu/src/hpdf_image.c \ + ../3rdParty/libharu/src/hpdf_image_png.c \ + ../3rdParty/libharu/src/hpdf_info.c \ + ../3rdParty/libharu/src/hpdf_list.c \ + ../3rdParty/libharu/src/hpdf_mmgr.c \ + ../3rdParty/libharu/src/hpdf_name.c \ + ../3rdParty/libharu/src/hpdf_namedict.c \ + ../3rdParty/libharu/src/hpdf_null.c \ + ../3rdParty/libharu/src/hpdf_number.c \ + ../3rdParty/libharu/src/hpdf_objects.c \ + ../3rdParty/libharu/src/hpdf_outline.c \ + ../3rdParty/libharu/src/hpdf_pages.c \ + ../3rdParty/libharu/src/hpdf_page_label.c \ + ../3rdParty/libharu/src/hpdf_page_operator.c \ + ../3rdParty/libharu/src/hpdf_pdfa.c \ + ../3rdParty/libharu/src/hpdf_real.c \ + ../3rdParty/libharu/src/hpdf_streams.c \ + ../3rdParty/libharu/src/hpdf_string.c \ + ../3rdParty/libharu/src/hpdf_u3d.c \ + ../3rdParty/libharu/src/hpdf_utils.c \ + ../3rdParty/libharu/src/hpdf_xref.c SOURCES += \ - ../3rdParty/TinyXML++/ticpp.cpp \ - ../3rdParty/TinyXML++/tinystr.cpp \ - ../3rdParty/TinyXML++/tinyxml.cpp \ - ../3rdParty/TinyXML++/tinyxmlerror.cpp \ - ../3rdParty/TinyXML++/tinyxmlparser.cpp + ../3rdParty/TinyXML++/ticpp.cpp \ + ../3rdParty/TinyXML++/tinystr.cpp \ + ../3rdParty/TinyXML++/tinyxml.cpp \ + ../3rdParty/TinyXML++/tinyxmlerror.cpp \ + ../3rdParty/TinyXML++/tinyxmlparser.cpp + + +SOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.cpp \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.cpp \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.cpp \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils.cpp + +HEADERS += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.h \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.h \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.h \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils_p.h + +RESOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.qrc # As a note to what was removed REMOVED_SOURCES = \ - ../3rdParty/hoedown/html_smartypants.c \ - ../3rdParty/hoedown/version.c \ - ../3rdParty/libharu/src/hpdf_image_ccitt.c + ../3rdParty/hoedown/html_smartypants.c \ + ../3rdParty/hoedown/version.c \ + ../3rdParty/libharu/src/hpdf_image_ccitt.c # Linux specific settings unix { - QMAKE_CXXFLAGS += --std=gnu++11 - # QMAKE_CXXFLAGS -= -Wall - QMAKE_CXXFLAGS_WARN_ON=-w - QMAKE_CFLAGS_WARN_ON=-w - LIBS += -lpng -lz + QMAKE_CXXFLAGS += --std=gnu++11 + # QMAKE_CXXFLAGS -= -Wall + QMAKE_CXXFLAGS_WARN_ON=-w + QMAKE_CFLAGS_WARN_ON=-w + LIBS += -lpng -lz } @@ -160,77 +201,82 @@ # Windows specific. Note we compile in libpng and zlib statically on Windows win32 { - # Supress annoying warnings - QMAKE_CXXFLAGS += /wd"4996;4100" - QMAKE_CXXFLAGS_WARN_ON -= -w34100 + # Supress annoying warnings + QMAKE_CXXFLAGS += /wd"4996;4100" + QMAKE_CXXFLAGS_WARN_ON -= -w34100 - # Release mode debugging - QMAKE_CXXFLAGS += /Zi - QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF + # Release mode debugging + QMAKE_CXXFLAGS += /Zi + QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF - # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything - Project.target = $${TARGET}.vcxproj - Project.output = $${TARGET}.vcxproj - Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 - Project.depends = '"$${_PRO_FILE_}"' - Project.input = _PRO_FILE_ - QMAKE_EXTRA_COMPILERS += Project + # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything + Project.target = $${TARGET}.vcxproj + Project.output = $${TARGET}.vcxproj + Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 + Project.depends = '"$${_PRO_FILE_}"' + Project.input = _PRO_FILE_ + QMAKE_EXTRA_COMPILERS += Project - # This makes the documentation - MARKDOWN_FILES = \ - test.md \ - test2.md + # This makes the documentation + MARKDOWN_FILES = \ + test.md \ + test2.md - Documentation.target = test.pdf - Documentation.output = test.pdf - Documentation.commands = echo ' ' > test.pdf - Documentation.depends = '"$${MARKDOWN_FILES}"' - Documentation.input = MARKDOWN_FILES - QMAKE_EXTRA_COMPILERS += Documentation + Documentation.target = test.pdf + Documentation.output = test.pdf + Documentation.commands = echo ' ' > test.pdf + Documentation.depends = '"$${MARKDOWN_FILES}"' + Documentation.input = MARKDOWN_FILES + QMAKE_EXTRA_COMPILERS += Documentation - INCLUDEPATH += \ - ../3rdParty/libpng \ - ../3rdParty/zlib + INCLUDEPATH += \ + ../3rdParty/libpng \ + ../3rdParty/zlib - SOURCES += \ - ../3rdParty/libpng/png.c \ - ../3rdParty/libpng/pngerror.c \ - ../3rdParty/libpng/pngget.c \ - ../3rdParty/libpng/pngmem.c \ - ../3rdParty/libpng/pngpread.c \ - ../3rdParty/libpng/pngread.c \ - ../3rdParty/libpng/pngrio.c \ - ../3rdParty/libpng/pngrtran.c \ - ../3rdParty/libpng/pngrutil.c \ - ../3rdParty/libpng/pngset.c \ - ../3rdParty/libpng/pngtrans.c \ - ../3rdParty/libpng/pngwio.c \ - ../3rdParty/libpng/pngwrite.c \ - ../3rdParty/libpng/pngwtran.c \ - ../3rdParty/libpng/pngwutil.c + SOURCES += \ + ../3rdParty/libpng/png.c \ + ../3rdParty/libpng/pngerror.c \ + ../3rdParty/libpng/pngget.c \ + ../3rdParty/libpng/pngmem.c \ + ../3rdParty/libpng/pngpread.c \ + ../3rdParty/libpng/pngread.c \ + ../3rdParty/libpng/pngrio.c \ + ../3rdParty/libpng/pngrtran.c \ + ../3rdParty/libpng/pngrutil.c \ + ../3rdParty/libpng/pngset.c \ + ../3rdParty/libpng/pngtrans.c \ + ../3rdParty/libpng/pngwio.c \ + ../3rdParty/libpng/pngwrite.c \ + ../3rdParty/libpng/pngwtran.c \ + ../3rdParty/libpng/pngwutil.c - SOURCES += \ - ../3rdParty/zlib/inftrees.c \ - ../3rdParty/zlib/trees.c \ - ../3rdParty/zlib/uncompr.c \ - ../3rdParty/zlib/zutil.c \ - ../3rdParty/zlib/adler32.c \ - ../3rdParty/zlib/compress.c \ - ../3rdParty/zlib/crc32.c \ - ../3rdParty/zlib/deflate.c \ - ../3rdParty/zlib/gzclose.c \ - ../3rdParty/zlib/gzlib.c \ - ../3rdParty/zlib/gzread.c \ - ../3rdParty/zlib/gzwrite.c \ - ../3rdParty/zlib/infback.c \ - ../3rdParty/zlib/inffast.c \ - ../3rdParty/zlib/inflate.c + SOURCES += \ + ../3rdParty/zlib/inftrees.c \ + ../3rdParty/zlib/trees.c \ + ../3rdParty/zlib/uncompr.c \ + ../3rdParty/zlib/zutil.c \ + ../3rdParty/zlib/adler32.c \ + ../3rdParty/zlib/compress.c \ + ../3rdParty/zlib/crc32.c \ + ../3rdParty/zlib/deflate.c \ + ../3rdParty/zlib/gzclose.c \ + ../3rdParty/zlib/gzlib.c \ + ../3rdParty/zlib/gzread.c \ + ../3rdParty/zlib/gzwrite.c \ + ../3rdParty/zlib/infback.c \ + ../3rdParty/zlib/inffast.c \ + ../3rdParty/zlib/inflate.c } +OTHER_FILES += \ + ../Website/about.html \ + ../Website/register.html \ + ../Website/support.html + diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/MdiWindow.h b/MdiWindow.h index 76d7f1b..35ef9c3 100644 --- a/MdiWindow.h +++ b/MdiWindow.h @@ -4,78 +4,19 @@ #include #include +#include "Objects.h" +#include "MdiChild.h" -class MdiChild; class QAction; class QMenu; class QMdiArea; class QMdiSubWindow; class QSignalMapper; +class QTcpServer; class Ui_MainWindow; -class MdiChild : public QTextEdit -{ - Q_OBJECT -public: - MdiChild(); - ~MdiChild(); - - void newFile(); - bool loadFile(const QString &fileName); - bool save(); - bool saveAs(); - bool saveFile(const QString &fileName); - QString userFriendlyCurrentFile(); - QString currentFile() { return curFile; } - - void markdownSelection(const char* preText, const char* postText); - - void bold(); - void italic(); - void quote(); - void code(); - void heading1(); - void heading2(); - void heading3(); - void heading4(); - void hyperlink(); - void image(); - void unorderedList(); - void orderedList(); - void horizontalRule(); - void timestamp(); - void pageNumber(); - void pageCount(); - void del(); - void undo(); - void redo(); - void find(); - void findNext(); - void findPrevious(); - void goToLine(); - -signals: - void closing(); - void documentContentsChanged(); - -private slots: - void documentWasModified(); - -protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - -private: - bool maybeSave(); - void setCurrentFile(const QString &fileName); - QString strippedName(const QString &fullFileName); - - QString curFile; - bool isUntitled; -}; - - /* class MdiOptions { @@ -109,8 +50,12 @@ void save(); void saveAs(); + void handleRequest(); void updatePreview(); + void setWebPreviewURL(); + void refreshWebPreview(); + // Edit menu actions #ifndef QT_NO_CLIPBOARD void cut(); @@ -159,12 +104,26 @@ void switchLayoutDirection(); void setActiveSubWindow(QWidget *window); + void changeRootObject(const QModelIndex &index); + void changePropertiesObject(const QModelIndex &index); + + // Dialog events + void upgradeClicked(); + private: + void changeProjectTree(QObject *rootObject); + void updateObjectTree(QObject *rootObject); + void updatePropertiesView(QObject *object); + void setupServer(); void readSettings(); + void readLicense(); void writeSettings(); MdiChild *activeMdiChild(); QMdiSubWindow *findMdiChild(const QString &fileName); + //Solution solution; + QByteArray pdfContents; + QTcpServer *server; QMdiArea *mdiArea; QSignalMapper *windowMapper; Ui_MainWindow *appWindow; diff --git a/ObjectVisitor.h b/ObjectVisitor.h new file mode 100644 index 0000000..12cf25f --- /dev/null +++ b/ObjectVisitor.h @@ -0,0 +1,59 @@ +#ifndef OBJECTVISITOR_H +#define OBJECTVISITOR_H + + +#include +#include +#include +#include + + +class Visitor +{ +public: + Visitor() {} + virtual ~Visitor() {} + + virtual void enterObject(const char* className, const char* objectName) = 0; + virtual void leaveObject(const char* className, const char* objectName) = 0; + + // Reads or writes a property value + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) = 0; + + // By default, it is a reader, but implementing this enables a visitor that sets values + virtual bool isWriting() { return false; } +}; + + +void Visit(Visitor& visitor, QObject* object) +{ + std::string objectName = object->objectName().toLocal8Bit().data(); + if (objectName.size() <= 1) { + objectName = std::to_string((uint64_t)(void*)object); + } + visitor.enterObject(object->metaObject()->className(), objectName.c_str()); + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + if (visitor.isWriting()) { + QVariant value; + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + property.write(object, value); + + } else { + QVariant value = property.read(object); + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + } + } + for (int i = 0; i < object->children().count(); i++) + { + Visit(visitor, object->children()[i]); + } + visitor.leaveObject(object->metaObject()->className(), objectName.c_str()); +} + + +#endif // OBJECTVISITOR_H diff --git a/Objects.h b/Objects.h new file mode 100644 index 0000000..90e7bb1 --- /dev/null +++ b/Objects.h @@ -0,0 +1,167 @@ +#ifndef OBJECTS_H +#define OBJECTS_H + + +#include +#include +#include +#include +#include +#include +#include + + +class EnumEditor : public QWidget +{ + Q_OBJECT +public slots: + void ListSelectionChanged(); + void ComboSelectionChanged(); +public: + EnumEditor(QMetaEnum metaEnum); +private: + QListWidget* lw; + QComboBox* cb; + QSpinBox* sb; + QLabel* str; + QMetaEnum m_metaEnum; +}; + + +// Property Manager Supported types: +// int, bool, double, enums, flags +// QString, QDate, QTime, QDateTime, QKeySequence +// QChar, QLocale, QPoint, QPointF, QSize, QSizeF +// QRect, QRectF, QSizePolicy, QFont, QColor, QCursor + + +#define PROP_WRAP(type, name) \ + Q_PROPERTY(type name READ get##name WRITE set##name) \ + type get##name() const { return m_##name; } \ + void set##name(type val) { m_##name = val; } \ + type m_##name; + +#define CHILD_PTR_PROP_WRAP(type, name) \ + Q_PROPERTY(type* name READ get##name WRITE set##name) \ + type* get##name() const { return m_##name; } \ + void set##name(type* val) { \ + /* if (m_##name) children().removeAll((QObject*)m_##name); */ \ + val->setParent(this); \ + m_##name = val; \ + } \ + type* m_##name = nullptr; + + +class MyObjectTest : public QObject +{ + Q_OBJECT + Q_ENUMS(AnotherEnum) + Q_ENUMS(TestEnum) + Q_FLAGS(TestFlags) +public: + enum TestFlags { FlagValue1 = 1, AnotherFlagValue = 2, FlagEtc = 4, FlagBlah = 8 }; + enum TestEnum { EnumValue1, AnotherValue, Etc, Blah }; + enum AnotherEnum { AEnumValue1, AnAnotherValue, Etc2 }; + + explicit MyObjectTest() : QObject() { + m_An_Int_Value = 10; + m_A_Double = 11.0; + //m_An_Enum = EnumValue1; + //memset(this, 0, sizeof(MyObjectTest)); + } + ~MyObjectTest() { + } + + PROP_WRAP(int, An_Int_Value) + PROP_WRAP(bool, A_Bool) + PROP_WRAP(double, A_Double) + PROP_WRAP(TestEnum,An_Enum1) + PROP_WRAP(TestEnum,An_Enum2) + PROP_WRAP(QFlags,A_Flags) + PROP_WRAP(QString, A_String) + PROP_WRAP(QDate, A_Date) + PROP_WRAP(QTime, A_Time) + PROP_WRAP(QDateTime, A_Date_and_Time) + PROP_WRAP(QKeySequence, A_Key_Sequence) + PROP_WRAP(QChar, A_Char) + PROP_WRAP(QLocale, A_Locale) + PROP_WRAP(QPoint, A_Point) + PROP_WRAP(QPointF, A_PointF) + PROP_WRAP(QSize, A_Size) + PROP_WRAP(QSizeF, A_SizeF) + PROP_WRAP(QRect, A_Rect) + PROP_WRAP(QRectF, A_RectF) + //PROP_WRAP(QSizePolicy, A_SizePolicy) + //PROP_WRAP(QFont, A_Font) + PROP_WRAP(QColor, A_Color) + //PROP_WRAP(QCursor, A_Cursor) + // flags +}; + + + +class Template : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) + PROP_WRAP(QColor, Color) +}; + + +class Output : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + PROP_WRAP(QString, Title) + PROP_WRAP(QString, Filename) + PROP_WRAP(FileTypes, FileType) +}; + + +class Input : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) +}; + + +class Project : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + //PROP_WRAP(QString, Name) + PROP_WRAP(QString, Author) + //PROP_WRAP(Template*, Template) + //PROP_WRAP(QList, Inputs) + //PROP_WRAP(Output*, Output) + + //CHILD_PTR_PROP_WRAP(Output, Output) + //CHILD_PTR_PROP_WRAP(Template, Template) + + PROP_WRAP(QString, Title) + PROP_WRAP(QString, OutputFilename) + PROP_WRAP(FileTypes, OutputFileType) + + PROP_WRAP(QString, Template) + PROP_WRAP(QColor, Color) + + void AddInput(Input* in) { in->setParent(this); } +}; + + +class Solution : public QObject +{ + Q_OBJECT +public: + //PROP_WRAP(QList, Projects) + void AddProject(Project* proj) { proj->setParent(this); } +}; + + +#endif // OBJECTS_H diff --git a/QtProject/MakePDF.pro b/QtProject/MakePDF.pro index f4e410c..4026759 100644 --- a/QtProject/MakePDF.pro +++ b/QtProject/MakePDF.pro @@ -1,21 +1,24 @@ -QT += core gui widgets +# QT += webkitwidgets network widgets +CONFIG += qt +QT += core gui widgets webkitwidgets +#QT += svg CONFIG -= flat TARGET = MakePDF DEFINES += \ - GUI_APP=1 + GUI_APP=1 RESOURCES += \ - ../Resources/resources.qrc + ../Resources/resources.qrc FORMS += \ - ../Resources/forms/About.ui \ - ../Resources/forms/NewProjectWizard.ui \ - ../Resources/forms/ExtensibleObjectModelUI.ui \ - ../Resources/forms/SendBugReport.ui \ + ../Resources/forms/About.ui \ + ../Resources/forms/NewProjectWizard.ui \ + ../Resources/forms/ExtensibleObjectModelUI.ui \ + ../Resources/forms/SendBugReport.ui \ ../Resources/forms/Help.ui \ ../Resources/forms/CheckUpdates.ui \ ../Resources/forms/LicenseUpgrade.ui \ @@ -23,136 +26,174 @@ ../Resources/forms/PaletteEditor.ui INCLUDEPATH += \ - ../Framework \ - ../3rdParty/hoedown \ - ../3rdParty/libharu/include \ - ../3rdParty/TinyXML++ + ../Framework \ + ../3rdParty/hoedown \ + ../3rdParty/libharu/include \ + ../3rdParty/TinyXML++ \ + ../3rdParty/qtpropertybrowser/src HEADERS += \ - ../Framework/EventLog.h \ - ../Framework/Expected.h \ - ../Framework/Final.h \ - ../Framework/Finally.h \ - ../Framework/GenericTable.h \ - ../Framework/GenericTableUI.h \ - ../Framework/NonCopyable.h \ - ../Framework/Utilities.h \ + ../Framework/EventLog.h \ + ../Framework/Expected.h \ + ../Framework/Final.h \ + ../Framework/Finally.h \ + ../Framework/GenericTable.h \ + ../Framework/GenericTableUI.h \ + ../Framework/NonCopyable.h \ + ../Framework/Utilities.h \ + ../Framework/SystemInfomation.h \ + ../Framework/Array.h \ + ../Framework/Macros.h \ + ../Framework/ObjectTreeModel.h \ + ../Version.h \ + ../Util.h \ ../ui.h \ + ../MdiChild.h \ ../MdiWindow.h \ ../ColorPicker.h \ - ../Version.h + ../DocConvert.h \ + ../Objects.h \ + ../ObjectVisitor.h HEADERS += \ - ../DocOutput.h \ - ../DocProject.h \ - ../DocStyle.h \ - ../DocTemplate.h \ - ../DocVisitor.h \ - ../DocSVG.h + ../DocOutput.h \ + ../DocProject.h \ + ../DocStyle.h \ + ../DocTemplate.h \ + ../DocVisitor.h \ + ../DocSVG.h SOURCES += \ - ../Framework/Tests.cpp \ - ../Framework/Utilities.cpp \ - ../Framework/EventLog.cpp \ + ../Framework/Tests.cpp \ + ../Framework/Utilities.cpp \ + ../Framework/EventLog.cpp \ + ../MdiChild.cpp \ ../MdiWindow.cpp \ ../ColorPicker.cpp \ - ../Version.cpp + ../Version.cpp \ + ../Framework/SystemInfomation.cpp \ + ../DocConvert.cpp \ + ../Framework/ObjectTreeModel.cpp SOURCES += \ - ../DocOutput.cpp \ - ../DocProject.cpp \ - ../DocStyle.cpp \ - ../DocTemplate.cpp \ - ../DocVisitor.cpp \ - ../DocSVG.cpp \ - ../main.cpp + ../DocOutput.cpp \ + ../DocProject.cpp \ + ../DocStyle.cpp \ + ../DocTemplate.cpp \ + ../DocVisitor.cpp \ + ../DocSVG.cpp \ + ../main.cpp SOURCES += \ - ../3rdParty/hoedown/autolink.c \ - ../3rdParty/hoedown/buffer.c \ - ../3rdParty/hoedown/document.c \ - ../3rdParty/hoedown/escape.c \ - ../3rdParty/hoedown/html.c \ - ../3rdParty/hoedown/html_blocks.c \ - ../3rdParty/hoedown/stack.c + ../3rdParty/hoedown/autolink.c \ + ../3rdParty/hoedown/buffer.c \ + ../3rdParty/hoedown/document.c \ + ../3rdParty/hoedown/escape.c \ + ../3rdParty/hoedown/html.c \ + ../3rdParty/hoedown/html_blocks.c \ + ../3rdParty/hoedown/stack.c SOURCES += \ - ../3rdParty/libharu/src/hpdf_3dmeasure.c \ - ../3rdParty/libharu/src/hpdf_annotation.c \ - ../3rdParty/libharu/src/hpdf_array.c \ - ../3rdParty/libharu/src/hpdf_binary.c \ - ../3rdParty/libharu/src/hpdf_boolean.c \ - ../3rdParty/libharu/src/hpdf_catalog.c \ - ../3rdParty/libharu/src/hpdf_destination.c \ - ../3rdParty/libharu/src/hpdf_dict.c \ - ../3rdParty/libharu/src/hpdf_doc.c \ - ../3rdParty/libharu/src/hpdf_doc_png.c \ - ../3rdParty/libharu/src/hpdf_encoder.c \ - ../3rdParty/libharu/src/hpdf_encoder_utf.c \ - ../3rdParty/libharu/src/hpdf_encrypt.c \ - ../3rdParty/libharu/src/hpdf_encryptdict.c \ - ../3rdParty/libharu/src/hpdf_error.c \ - ../3rdParty/libharu/src/hpdf_exdata.c \ - ../3rdParty/libharu/src/hpdf_ext_gstate.c \ - ../3rdParty/libharu/src/hpdf_font.c \ - ../3rdParty/libharu/src/hpdf_fontdef.c \ - ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ - ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ - ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ - ../3rdParty/libharu/src/hpdf_font_cid.c \ - ../3rdParty/libharu/src/hpdf_font_tt.c \ - ../3rdParty/libharu/src/hpdf_font_type1.c \ - ../3rdParty/libharu/src/hpdf_gstate.c \ - ../3rdParty/libharu/src/hpdf_image.c \ - ../3rdParty/libharu/src/hpdf_image_png.c \ - ../3rdParty/libharu/src/hpdf_info.c \ - ../3rdParty/libharu/src/hpdf_list.c \ - ../3rdParty/libharu/src/hpdf_mmgr.c \ - ../3rdParty/libharu/src/hpdf_name.c \ - ../3rdParty/libharu/src/hpdf_namedict.c \ - ../3rdParty/libharu/src/hpdf_null.c \ - ../3rdParty/libharu/src/hpdf_number.c \ - ../3rdParty/libharu/src/hpdf_objects.c \ - ../3rdParty/libharu/src/hpdf_outline.c \ - ../3rdParty/libharu/src/hpdf_pages.c \ - ../3rdParty/libharu/src/hpdf_page_label.c \ - ../3rdParty/libharu/src/hpdf_page_operator.c \ - ../3rdParty/libharu/src/hpdf_pdfa.c \ - ../3rdParty/libharu/src/hpdf_real.c \ - ../3rdParty/libharu/src/hpdf_streams.c \ - ../3rdParty/libharu/src/hpdf_string.c \ - ../3rdParty/libharu/src/hpdf_u3d.c \ - ../3rdParty/libharu/src/hpdf_utils.c \ - ../3rdParty/libharu/src/hpdf_xref.c + ../3rdParty/libharu/src/hpdf_3dmeasure.c \ + ../3rdParty/libharu/src/hpdf_annotation.c \ + ../3rdParty/libharu/src/hpdf_array.c \ + ../3rdParty/libharu/src/hpdf_binary.c \ + ../3rdParty/libharu/src/hpdf_boolean.c \ + ../3rdParty/libharu/src/hpdf_catalog.c \ + ../3rdParty/libharu/src/hpdf_destination.c \ + ../3rdParty/libharu/src/hpdf_dict.c \ + ../3rdParty/libharu/src/hpdf_doc.c \ + ../3rdParty/libharu/src/hpdf_doc_png.c \ + ../3rdParty/libharu/src/hpdf_encoder.c \ + ../3rdParty/libharu/src/hpdf_encoder_utf.c \ + ../3rdParty/libharu/src/hpdf_encrypt.c \ + ../3rdParty/libharu/src/hpdf_encryptdict.c \ + ../3rdParty/libharu/src/hpdf_error.c \ + ../3rdParty/libharu/src/hpdf_exdata.c \ + ../3rdParty/libharu/src/hpdf_ext_gstate.c \ + ../3rdParty/libharu/src/hpdf_font.c \ + ../3rdParty/libharu/src/hpdf_fontdef.c \ + ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ + ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ + ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ + ../3rdParty/libharu/src/hpdf_font_cid.c \ + ../3rdParty/libharu/src/hpdf_font_tt.c \ + ../3rdParty/libharu/src/hpdf_font_type1.c \ + ../3rdParty/libharu/src/hpdf_gstate.c \ + ../3rdParty/libharu/src/hpdf_image.c \ + ../3rdParty/libharu/src/hpdf_image_png.c \ + ../3rdParty/libharu/src/hpdf_info.c \ + ../3rdParty/libharu/src/hpdf_list.c \ + ../3rdParty/libharu/src/hpdf_mmgr.c \ + ../3rdParty/libharu/src/hpdf_name.c \ + ../3rdParty/libharu/src/hpdf_namedict.c \ + ../3rdParty/libharu/src/hpdf_null.c \ + ../3rdParty/libharu/src/hpdf_number.c \ + ../3rdParty/libharu/src/hpdf_objects.c \ + ../3rdParty/libharu/src/hpdf_outline.c \ + ../3rdParty/libharu/src/hpdf_pages.c \ + ../3rdParty/libharu/src/hpdf_page_label.c \ + ../3rdParty/libharu/src/hpdf_page_operator.c \ + ../3rdParty/libharu/src/hpdf_pdfa.c \ + ../3rdParty/libharu/src/hpdf_real.c \ + ../3rdParty/libharu/src/hpdf_streams.c \ + ../3rdParty/libharu/src/hpdf_string.c \ + ../3rdParty/libharu/src/hpdf_u3d.c \ + ../3rdParty/libharu/src/hpdf_utils.c \ + ../3rdParty/libharu/src/hpdf_xref.c SOURCES += \ - ../3rdParty/TinyXML++/ticpp.cpp \ - ../3rdParty/TinyXML++/tinystr.cpp \ - ../3rdParty/TinyXML++/tinyxml.cpp \ - ../3rdParty/TinyXML++/tinyxmlerror.cpp \ - ../3rdParty/TinyXML++/tinyxmlparser.cpp + ../3rdParty/TinyXML++/ticpp.cpp \ + ../3rdParty/TinyXML++/tinystr.cpp \ + ../3rdParty/TinyXML++/tinyxml.cpp \ + ../3rdParty/TinyXML++/tinyxmlerror.cpp \ + ../3rdParty/TinyXML++/tinyxmlparser.cpp + + +SOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.cpp \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.cpp \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.cpp \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils.cpp + +HEADERS += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.h \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.h \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.h \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils_p.h + +RESOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.qrc # As a note to what was removed REMOVED_SOURCES = \ - ../3rdParty/hoedown/html_smartypants.c \ - ../3rdParty/hoedown/version.c \ - ../3rdParty/libharu/src/hpdf_image_ccitt.c + ../3rdParty/hoedown/html_smartypants.c \ + ../3rdParty/hoedown/version.c \ + ../3rdParty/libharu/src/hpdf_image_ccitt.c # Linux specific settings unix { - QMAKE_CXXFLAGS += --std=gnu++11 - # QMAKE_CXXFLAGS -= -Wall - QMAKE_CXXFLAGS_WARN_ON=-w - QMAKE_CFLAGS_WARN_ON=-w - LIBS += -lpng -lz + QMAKE_CXXFLAGS += --std=gnu++11 + # QMAKE_CXXFLAGS -= -Wall + QMAKE_CXXFLAGS_WARN_ON=-w + QMAKE_CFLAGS_WARN_ON=-w + LIBS += -lpng -lz } @@ -160,77 +201,82 @@ # Windows specific. Note we compile in libpng and zlib statically on Windows win32 { - # Supress annoying warnings - QMAKE_CXXFLAGS += /wd"4996;4100" - QMAKE_CXXFLAGS_WARN_ON -= -w34100 + # Supress annoying warnings + QMAKE_CXXFLAGS += /wd"4996;4100" + QMAKE_CXXFLAGS_WARN_ON -= -w34100 - # Release mode debugging - QMAKE_CXXFLAGS += /Zi - QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF + # Release mode debugging + QMAKE_CXXFLAGS += /Zi + QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF - # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything - Project.target = $${TARGET}.vcxproj - Project.output = $${TARGET}.vcxproj - Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 - Project.depends = '"$${_PRO_FILE_}"' - Project.input = _PRO_FILE_ - QMAKE_EXTRA_COMPILERS += Project + # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything + Project.target = $${TARGET}.vcxproj + Project.output = $${TARGET}.vcxproj + Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 + Project.depends = '"$${_PRO_FILE_}"' + Project.input = _PRO_FILE_ + QMAKE_EXTRA_COMPILERS += Project - # This makes the documentation - MARKDOWN_FILES = \ - test.md \ - test2.md + # This makes the documentation + MARKDOWN_FILES = \ + test.md \ + test2.md - Documentation.target = test.pdf - Documentation.output = test.pdf - Documentation.commands = echo ' ' > test.pdf - Documentation.depends = '"$${MARKDOWN_FILES}"' - Documentation.input = MARKDOWN_FILES - QMAKE_EXTRA_COMPILERS += Documentation + Documentation.target = test.pdf + Documentation.output = test.pdf + Documentation.commands = echo ' ' > test.pdf + Documentation.depends = '"$${MARKDOWN_FILES}"' + Documentation.input = MARKDOWN_FILES + QMAKE_EXTRA_COMPILERS += Documentation - INCLUDEPATH += \ - ../3rdParty/libpng \ - ../3rdParty/zlib + INCLUDEPATH += \ + ../3rdParty/libpng \ + ../3rdParty/zlib - SOURCES += \ - ../3rdParty/libpng/png.c \ - ../3rdParty/libpng/pngerror.c \ - ../3rdParty/libpng/pngget.c \ - ../3rdParty/libpng/pngmem.c \ - ../3rdParty/libpng/pngpread.c \ - ../3rdParty/libpng/pngread.c \ - ../3rdParty/libpng/pngrio.c \ - ../3rdParty/libpng/pngrtran.c \ - ../3rdParty/libpng/pngrutil.c \ - ../3rdParty/libpng/pngset.c \ - ../3rdParty/libpng/pngtrans.c \ - ../3rdParty/libpng/pngwio.c \ - ../3rdParty/libpng/pngwrite.c \ - ../3rdParty/libpng/pngwtran.c \ - ../3rdParty/libpng/pngwutil.c + SOURCES += \ + ../3rdParty/libpng/png.c \ + ../3rdParty/libpng/pngerror.c \ + ../3rdParty/libpng/pngget.c \ + ../3rdParty/libpng/pngmem.c \ + ../3rdParty/libpng/pngpread.c \ + ../3rdParty/libpng/pngread.c \ + ../3rdParty/libpng/pngrio.c \ + ../3rdParty/libpng/pngrtran.c \ + ../3rdParty/libpng/pngrutil.c \ + ../3rdParty/libpng/pngset.c \ + ../3rdParty/libpng/pngtrans.c \ + ../3rdParty/libpng/pngwio.c \ + ../3rdParty/libpng/pngwrite.c \ + ../3rdParty/libpng/pngwtran.c \ + ../3rdParty/libpng/pngwutil.c - SOURCES += \ - ../3rdParty/zlib/inftrees.c \ - ../3rdParty/zlib/trees.c \ - ../3rdParty/zlib/uncompr.c \ - ../3rdParty/zlib/zutil.c \ - ../3rdParty/zlib/adler32.c \ - ../3rdParty/zlib/compress.c \ - ../3rdParty/zlib/crc32.c \ - ../3rdParty/zlib/deflate.c \ - ../3rdParty/zlib/gzclose.c \ - ../3rdParty/zlib/gzlib.c \ - ../3rdParty/zlib/gzread.c \ - ../3rdParty/zlib/gzwrite.c \ - ../3rdParty/zlib/infback.c \ - ../3rdParty/zlib/inffast.c \ - ../3rdParty/zlib/inflate.c + SOURCES += \ + ../3rdParty/zlib/inftrees.c \ + ../3rdParty/zlib/trees.c \ + ../3rdParty/zlib/uncompr.c \ + ../3rdParty/zlib/zutil.c \ + ../3rdParty/zlib/adler32.c \ + ../3rdParty/zlib/compress.c \ + ../3rdParty/zlib/crc32.c \ + ../3rdParty/zlib/deflate.c \ + ../3rdParty/zlib/gzclose.c \ + ../3rdParty/zlib/gzlib.c \ + ../3rdParty/zlib/gzread.c \ + ../3rdParty/zlib/gzwrite.c \ + ../3rdParty/zlib/infback.c \ + ../3rdParty/zlib/inffast.c \ + ../3rdParty/zlib/inflate.c } +OTHER_FILES += \ + ../Website/about.html \ + ../Website/register.html \ + ../Website/support.html + diff --git a/Resources/forms/About.ui b/Resources/forms/About.ui index bd6bdf3..3265d89 100644 --- a/Resources/forms/About.ui +++ b/Resources/forms/About.ui @@ -152,7 +152,7 @@ QFrame::Plain - + 20 @@ -165,7 +165,7 @@ <html><head/><body><p><a href="http://url.to.application/"><span style=" text-decoration: underline; color:#0000ff;">http://url.to.application/</span></a></p></body></html> - + 360 @@ -175,16 +175,16 @@ - - - - :/images/images/logo.svg + AppIcon true + + Qt::AlignCenter + - + 20 @@ -193,11 +193,18 @@ 31 + + + 20 + 75 + true + + - <html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Wicked Docs</span></p></body></html> + AppName - + 20 @@ -207,7 +214,7 @@ - <html><head/><body><p>Version 1.0.0.0001</p></body></html> + AppVer @@ -337,7 +344,7 @@ - <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://blah/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements / LicensesEULA</span></a></p></body></html> + <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br/><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://sdfdsf/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements &amp; Licenses</span></a>&nbsp;&nbsp;<a href="http://sfsdf/"><span style=" text-decoration: underline; color:#0000ff;">EULA</span></a></p></body></html> label_5 @@ -346,9 +353,7 @@ - - - + okayButton diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/MdiWindow.h b/MdiWindow.h index 76d7f1b..35ef9c3 100644 --- a/MdiWindow.h +++ b/MdiWindow.h @@ -4,78 +4,19 @@ #include #include +#include "Objects.h" +#include "MdiChild.h" -class MdiChild; class QAction; class QMenu; class QMdiArea; class QMdiSubWindow; class QSignalMapper; +class QTcpServer; class Ui_MainWindow; -class MdiChild : public QTextEdit -{ - Q_OBJECT -public: - MdiChild(); - ~MdiChild(); - - void newFile(); - bool loadFile(const QString &fileName); - bool save(); - bool saveAs(); - bool saveFile(const QString &fileName); - QString userFriendlyCurrentFile(); - QString currentFile() { return curFile; } - - void markdownSelection(const char* preText, const char* postText); - - void bold(); - void italic(); - void quote(); - void code(); - void heading1(); - void heading2(); - void heading3(); - void heading4(); - void hyperlink(); - void image(); - void unorderedList(); - void orderedList(); - void horizontalRule(); - void timestamp(); - void pageNumber(); - void pageCount(); - void del(); - void undo(); - void redo(); - void find(); - void findNext(); - void findPrevious(); - void goToLine(); - -signals: - void closing(); - void documentContentsChanged(); - -private slots: - void documentWasModified(); - -protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - -private: - bool maybeSave(); - void setCurrentFile(const QString &fileName); - QString strippedName(const QString &fullFileName); - - QString curFile; - bool isUntitled; -}; - - /* class MdiOptions { @@ -109,8 +50,12 @@ void save(); void saveAs(); + void handleRequest(); void updatePreview(); + void setWebPreviewURL(); + void refreshWebPreview(); + // Edit menu actions #ifndef QT_NO_CLIPBOARD void cut(); @@ -159,12 +104,26 @@ void switchLayoutDirection(); void setActiveSubWindow(QWidget *window); + void changeRootObject(const QModelIndex &index); + void changePropertiesObject(const QModelIndex &index); + + // Dialog events + void upgradeClicked(); + private: + void changeProjectTree(QObject *rootObject); + void updateObjectTree(QObject *rootObject); + void updatePropertiesView(QObject *object); + void setupServer(); void readSettings(); + void readLicense(); void writeSettings(); MdiChild *activeMdiChild(); QMdiSubWindow *findMdiChild(const QString &fileName); + //Solution solution; + QByteArray pdfContents; + QTcpServer *server; QMdiArea *mdiArea; QSignalMapper *windowMapper; Ui_MainWindow *appWindow; diff --git a/ObjectVisitor.h b/ObjectVisitor.h new file mode 100644 index 0000000..12cf25f --- /dev/null +++ b/ObjectVisitor.h @@ -0,0 +1,59 @@ +#ifndef OBJECTVISITOR_H +#define OBJECTVISITOR_H + + +#include +#include +#include +#include + + +class Visitor +{ +public: + Visitor() {} + virtual ~Visitor() {} + + virtual void enterObject(const char* className, const char* objectName) = 0; + virtual void leaveObject(const char* className, const char* objectName) = 0; + + // Reads or writes a property value + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) = 0; + + // By default, it is a reader, but implementing this enables a visitor that sets values + virtual bool isWriting() { return false; } +}; + + +void Visit(Visitor& visitor, QObject* object) +{ + std::string objectName = object->objectName().toLocal8Bit().data(); + if (objectName.size() <= 1) { + objectName = std::to_string((uint64_t)(void*)object); + } + visitor.enterObject(object->metaObject()->className(), objectName.c_str()); + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + if (visitor.isWriting()) { + QVariant value; + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + property.write(object, value); + + } else { + QVariant value = property.read(object); + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + } + } + for (int i = 0; i < object->children().count(); i++) + { + Visit(visitor, object->children()[i]); + } + visitor.leaveObject(object->metaObject()->className(), objectName.c_str()); +} + + +#endif // OBJECTVISITOR_H diff --git a/Objects.h b/Objects.h new file mode 100644 index 0000000..90e7bb1 --- /dev/null +++ b/Objects.h @@ -0,0 +1,167 @@ +#ifndef OBJECTS_H +#define OBJECTS_H + + +#include +#include +#include +#include +#include +#include +#include + + +class EnumEditor : public QWidget +{ + Q_OBJECT +public slots: + void ListSelectionChanged(); + void ComboSelectionChanged(); +public: + EnumEditor(QMetaEnum metaEnum); +private: + QListWidget* lw; + QComboBox* cb; + QSpinBox* sb; + QLabel* str; + QMetaEnum m_metaEnum; +}; + + +// Property Manager Supported types: +// int, bool, double, enums, flags +// QString, QDate, QTime, QDateTime, QKeySequence +// QChar, QLocale, QPoint, QPointF, QSize, QSizeF +// QRect, QRectF, QSizePolicy, QFont, QColor, QCursor + + +#define PROP_WRAP(type, name) \ + Q_PROPERTY(type name READ get##name WRITE set##name) \ + type get##name() const { return m_##name; } \ + void set##name(type val) { m_##name = val; } \ + type m_##name; + +#define CHILD_PTR_PROP_WRAP(type, name) \ + Q_PROPERTY(type* name READ get##name WRITE set##name) \ + type* get##name() const { return m_##name; } \ + void set##name(type* val) { \ + /* if (m_##name) children().removeAll((QObject*)m_##name); */ \ + val->setParent(this); \ + m_##name = val; \ + } \ + type* m_##name = nullptr; + + +class MyObjectTest : public QObject +{ + Q_OBJECT + Q_ENUMS(AnotherEnum) + Q_ENUMS(TestEnum) + Q_FLAGS(TestFlags) +public: + enum TestFlags { FlagValue1 = 1, AnotherFlagValue = 2, FlagEtc = 4, FlagBlah = 8 }; + enum TestEnum { EnumValue1, AnotherValue, Etc, Blah }; + enum AnotherEnum { AEnumValue1, AnAnotherValue, Etc2 }; + + explicit MyObjectTest() : QObject() { + m_An_Int_Value = 10; + m_A_Double = 11.0; + //m_An_Enum = EnumValue1; + //memset(this, 0, sizeof(MyObjectTest)); + } + ~MyObjectTest() { + } + + PROP_WRAP(int, An_Int_Value) + PROP_WRAP(bool, A_Bool) + PROP_WRAP(double, A_Double) + PROP_WRAP(TestEnum,An_Enum1) + PROP_WRAP(TestEnum,An_Enum2) + PROP_WRAP(QFlags,A_Flags) + PROP_WRAP(QString, A_String) + PROP_WRAP(QDate, A_Date) + PROP_WRAP(QTime, A_Time) + PROP_WRAP(QDateTime, A_Date_and_Time) + PROP_WRAP(QKeySequence, A_Key_Sequence) + PROP_WRAP(QChar, A_Char) + PROP_WRAP(QLocale, A_Locale) + PROP_WRAP(QPoint, A_Point) + PROP_WRAP(QPointF, A_PointF) + PROP_WRAP(QSize, A_Size) + PROP_WRAP(QSizeF, A_SizeF) + PROP_WRAP(QRect, A_Rect) + PROP_WRAP(QRectF, A_RectF) + //PROP_WRAP(QSizePolicy, A_SizePolicy) + //PROP_WRAP(QFont, A_Font) + PROP_WRAP(QColor, A_Color) + //PROP_WRAP(QCursor, A_Cursor) + // flags +}; + + + +class Template : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) + PROP_WRAP(QColor, Color) +}; + + +class Output : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + PROP_WRAP(QString, Title) + PROP_WRAP(QString, Filename) + PROP_WRAP(FileTypes, FileType) +}; + + +class Input : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) +}; + + +class Project : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + //PROP_WRAP(QString, Name) + PROP_WRAP(QString, Author) + //PROP_WRAP(Template*, Template) + //PROP_WRAP(QList, Inputs) + //PROP_WRAP(Output*, Output) + + //CHILD_PTR_PROP_WRAP(Output, Output) + //CHILD_PTR_PROP_WRAP(Template, Template) + + PROP_WRAP(QString, Title) + PROP_WRAP(QString, OutputFilename) + PROP_WRAP(FileTypes, OutputFileType) + + PROP_WRAP(QString, Template) + PROP_WRAP(QColor, Color) + + void AddInput(Input* in) { in->setParent(this); } +}; + + +class Solution : public QObject +{ + Q_OBJECT +public: + //PROP_WRAP(QList, Projects) + void AddProject(Project* proj) { proj->setParent(this); } +}; + + +#endif // OBJECTS_H diff --git a/QtProject/MakePDF.pro b/QtProject/MakePDF.pro index f4e410c..4026759 100644 --- a/QtProject/MakePDF.pro +++ b/QtProject/MakePDF.pro @@ -1,21 +1,24 @@ -QT += core gui widgets +# QT += webkitwidgets network widgets +CONFIG += qt +QT += core gui widgets webkitwidgets +#QT += svg CONFIG -= flat TARGET = MakePDF DEFINES += \ - GUI_APP=1 + GUI_APP=1 RESOURCES += \ - ../Resources/resources.qrc + ../Resources/resources.qrc FORMS += \ - ../Resources/forms/About.ui \ - ../Resources/forms/NewProjectWizard.ui \ - ../Resources/forms/ExtensibleObjectModelUI.ui \ - ../Resources/forms/SendBugReport.ui \ + ../Resources/forms/About.ui \ + ../Resources/forms/NewProjectWizard.ui \ + ../Resources/forms/ExtensibleObjectModelUI.ui \ + ../Resources/forms/SendBugReport.ui \ ../Resources/forms/Help.ui \ ../Resources/forms/CheckUpdates.ui \ ../Resources/forms/LicenseUpgrade.ui \ @@ -23,136 +26,174 @@ ../Resources/forms/PaletteEditor.ui INCLUDEPATH += \ - ../Framework \ - ../3rdParty/hoedown \ - ../3rdParty/libharu/include \ - ../3rdParty/TinyXML++ + ../Framework \ + ../3rdParty/hoedown \ + ../3rdParty/libharu/include \ + ../3rdParty/TinyXML++ \ + ../3rdParty/qtpropertybrowser/src HEADERS += \ - ../Framework/EventLog.h \ - ../Framework/Expected.h \ - ../Framework/Final.h \ - ../Framework/Finally.h \ - ../Framework/GenericTable.h \ - ../Framework/GenericTableUI.h \ - ../Framework/NonCopyable.h \ - ../Framework/Utilities.h \ + ../Framework/EventLog.h \ + ../Framework/Expected.h \ + ../Framework/Final.h \ + ../Framework/Finally.h \ + ../Framework/GenericTable.h \ + ../Framework/GenericTableUI.h \ + ../Framework/NonCopyable.h \ + ../Framework/Utilities.h \ + ../Framework/SystemInfomation.h \ + ../Framework/Array.h \ + ../Framework/Macros.h \ + ../Framework/ObjectTreeModel.h \ + ../Version.h \ + ../Util.h \ ../ui.h \ + ../MdiChild.h \ ../MdiWindow.h \ ../ColorPicker.h \ - ../Version.h + ../DocConvert.h \ + ../Objects.h \ + ../ObjectVisitor.h HEADERS += \ - ../DocOutput.h \ - ../DocProject.h \ - ../DocStyle.h \ - ../DocTemplate.h \ - ../DocVisitor.h \ - ../DocSVG.h + ../DocOutput.h \ + ../DocProject.h \ + ../DocStyle.h \ + ../DocTemplate.h \ + ../DocVisitor.h \ + ../DocSVG.h SOURCES += \ - ../Framework/Tests.cpp \ - ../Framework/Utilities.cpp \ - ../Framework/EventLog.cpp \ + ../Framework/Tests.cpp \ + ../Framework/Utilities.cpp \ + ../Framework/EventLog.cpp \ + ../MdiChild.cpp \ ../MdiWindow.cpp \ ../ColorPicker.cpp \ - ../Version.cpp + ../Version.cpp \ + ../Framework/SystemInfomation.cpp \ + ../DocConvert.cpp \ + ../Framework/ObjectTreeModel.cpp SOURCES += \ - ../DocOutput.cpp \ - ../DocProject.cpp \ - ../DocStyle.cpp \ - ../DocTemplate.cpp \ - ../DocVisitor.cpp \ - ../DocSVG.cpp \ - ../main.cpp + ../DocOutput.cpp \ + ../DocProject.cpp \ + ../DocStyle.cpp \ + ../DocTemplate.cpp \ + ../DocVisitor.cpp \ + ../DocSVG.cpp \ + ../main.cpp SOURCES += \ - ../3rdParty/hoedown/autolink.c \ - ../3rdParty/hoedown/buffer.c \ - ../3rdParty/hoedown/document.c \ - ../3rdParty/hoedown/escape.c \ - ../3rdParty/hoedown/html.c \ - ../3rdParty/hoedown/html_blocks.c \ - ../3rdParty/hoedown/stack.c + ../3rdParty/hoedown/autolink.c \ + ../3rdParty/hoedown/buffer.c \ + ../3rdParty/hoedown/document.c \ + ../3rdParty/hoedown/escape.c \ + ../3rdParty/hoedown/html.c \ + ../3rdParty/hoedown/html_blocks.c \ + ../3rdParty/hoedown/stack.c SOURCES += \ - ../3rdParty/libharu/src/hpdf_3dmeasure.c \ - ../3rdParty/libharu/src/hpdf_annotation.c \ - ../3rdParty/libharu/src/hpdf_array.c \ - ../3rdParty/libharu/src/hpdf_binary.c \ - ../3rdParty/libharu/src/hpdf_boolean.c \ - ../3rdParty/libharu/src/hpdf_catalog.c \ - ../3rdParty/libharu/src/hpdf_destination.c \ - ../3rdParty/libharu/src/hpdf_dict.c \ - ../3rdParty/libharu/src/hpdf_doc.c \ - ../3rdParty/libharu/src/hpdf_doc_png.c \ - ../3rdParty/libharu/src/hpdf_encoder.c \ - ../3rdParty/libharu/src/hpdf_encoder_utf.c \ - ../3rdParty/libharu/src/hpdf_encrypt.c \ - ../3rdParty/libharu/src/hpdf_encryptdict.c \ - ../3rdParty/libharu/src/hpdf_error.c \ - ../3rdParty/libharu/src/hpdf_exdata.c \ - ../3rdParty/libharu/src/hpdf_ext_gstate.c \ - ../3rdParty/libharu/src/hpdf_font.c \ - ../3rdParty/libharu/src/hpdf_fontdef.c \ - ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ - ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ - ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ - ../3rdParty/libharu/src/hpdf_font_cid.c \ - ../3rdParty/libharu/src/hpdf_font_tt.c \ - ../3rdParty/libharu/src/hpdf_font_type1.c \ - ../3rdParty/libharu/src/hpdf_gstate.c \ - ../3rdParty/libharu/src/hpdf_image.c \ - ../3rdParty/libharu/src/hpdf_image_png.c \ - ../3rdParty/libharu/src/hpdf_info.c \ - ../3rdParty/libharu/src/hpdf_list.c \ - ../3rdParty/libharu/src/hpdf_mmgr.c \ - ../3rdParty/libharu/src/hpdf_name.c \ - ../3rdParty/libharu/src/hpdf_namedict.c \ - ../3rdParty/libharu/src/hpdf_null.c \ - ../3rdParty/libharu/src/hpdf_number.c \ - ../3rdParty/libharu/src/hpdf_objects.c \ - ../3rdParty/libharu/src/hpdf_outline.c \ - ../3rdParty/libharu/src/hpdf_pages.c \ - ../3rdParty/libharu/src/hpdf_page_label.c \ - ../3rdParty/libharu/src/hpdf_page_operator.c \ - ../3rdParty/libharu/src/hpdf_pdfa.c \ - ../3rdParty/libharu/src/hpdf_real.c \ - ../3rdParty/libharu/src/hpdf_streams.c \ - ../3rdParty/libharu/src/hpdf_string.c \ - ../3rdParty/libharu/src/hpdf_u3d.c \ - ../3rdParty/libharu/src/hpdf_utils.c \ - ../3rdParty/libharu/src/hpdf_xref.c + ../3rdParty/libharu/src/hpdf_3dmeasure.c \ + ../3rdParty/libharu/src/hpdf_annotation.c \ + ../3rdParty/libharu/src/hpdf_array.c \ + ../3rdParty/libharu/src/hpdf_binary.c \ + ../3rdParty/libharu/src/hpdf_boolean.c \ + ../3rdParty/libharu/src/hpdf_catalog.c \ + ../3rdParty/libharu/src/hpdf_destination.c \ + ../3rdParty/libharu/src/hpdf_dict.c \ + ../3rdParty/libharu/src/hpdf_doc.c \ + ../3rdParty/libharu/src/hpdf_doc_png.c \ + ../3rdParty/libharu/src/hpdf_encoder.c \ + ../3rdParty/libharu/src/hpdf_encoder_utf.c \ + ../3rdParty/libharu/src/hpdf_encrypt.c \ + ../3rdParty/libharu/src/hpdf_encryptdict.c \ + ../3rdParty/libharu/src/hpdf_error.c \ + ../3rdParty/libharu/src/hpdf_exdata.c \ + ../3rdParty/libharu/src/hpdf_ext_gstate.c \ + ../3rdParty/libharu/src/hpdf_font.c \ + ../3rdParty/libharu/src/hpdf_fontdef.c \ + ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ + ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ + ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ + ../3rdParty/libharu/src/hpdf_font_cid.c \ + ../3rdParty/libharu/src/hpdf_font_tt.c \ + ../3rdParty/libharu/src/hpdf_font_type1.c \ + ../3rdParty/libharu/src/hpdf_gstate.c \ + ../3rdParty/libharu/src/hpdf_image.c \ + ../3rdParty/libharu/src/hpdf_image_png.c \ + ../3rdParty/libharu/src/hpdf_info.c \ + ../3rdParty/libharu/src/hpdf_list.c \ + ../3rdParty/libharu/src/hpdf_mmgr.c \ + ../3rdParty/libharu/src/hpdf_name.c \ + ../3rdParty/libharu/src/hpdf_namedict.c \ + ../3rdParty/libharu/src/hpdf_null.c \ + ../3rdParty/libharu/src/hpdf_number.c \ + ../3rdParty/libharu/src/hpdf_objects.c \ + ../3rdParty/libharu/src/hpdf_outline.c \ + ../3rdParty/libharu/src/hpdf_pages.c \ + ../3rdParty/libharu/src/hpdf_page_label.c \ + ../3rdParty/libharu/src/hpdf_page_operator.c \ + ../3rdParty/libharu/src/hpdf_pdfa.c \ + ../3rdParty/libharu/src/hpdf_real.c \ + ../3rdParty/libharu/src/hpdf_streams.c \ + ../3rdParty/libharu/src/hpdf_string.c \ + ../3rdParty/libharu/src/hpdf_u3d.c \ + ../3rdParty/libharu/src/hpdf_utils.c \ + ../3rdParty/libharu/src/hpdf_xref.c SOURCES += \ - ../3rdParty/TinyXML++/ticpp.cpp \ - ../3rdParty/TinyXML++/tinystr.cpp \ - ../3rdParty/TinyXML++/tinyxml.cpp \ - ../3rdParty/TinyXML++/tinyxmlerror.cpp \ - ../3rdParty/TinyXML++/tinyxmlparser.cpp + ../3rdParty/TinyXML++/ticpp.cpp \ + ../3rdParty/TinyXML++/tinystr.cpp \ + ../3rdParty/TinyXML++/tinyxml.cpp \ + ../3rdParty/TinyXML++/tinyxmlerror.cpp \ + ../3rdParty/TinyXML++/tinyxmlparser.cpp + + +SOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.cpp \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.cpp \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.cpp \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils.cpp + +HEADERS += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.h \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.h \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.h \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils_p.h + +RESOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.qrc # As a note to what was removed REMOVED_SOURCES = \ - ../3rdParty/hoedown/html_smartypants.c \ - ../3rdParty/hoedown/version.c \ - ../3rdParty/libharu/src/hpdf_image_ccitt.c + ../3rdParty/hoedown/html_smartypants.c \ + ../3rdParty/hoedown/version.c \ + ../3rdParty/libharu/src/hpdf_image_ccitt.c # Linux specific settings unix { - QMAKE_CXXFLAGS += --std=gnu++11 - # QMAKE_CXXFLAGS -= -Wall - QMAKE_CXXFLAGS_WARN_ON=-w - QMAKE_CFLAGS_WARN_ON=-w - LIBS += -lpng -lz + QMAKE_CXXFLAGS += --std=gnu++11 + # QMAKE_CXXFLAGS -= -Wall + QMAKE_CXXFLAGS_WARN_ON=-w + QMAKE_CFLAGS_WARN_ON=-w + LIBS += -lpng -lz } @@ -160,77 +201,82 @@ # Windows specific. Note we compile in libpng and zlib statically on Windows win32 { - # Supress annoying warnings - QMAKE_CXXFLAGS += /wd"4996;4100" - QMAKE_CXXFLAGS_WARN_ON -= -w34100 + # Supress annoying warnings + QMAKE_CXXFLAGS += /wd"4996;4100" + QMAKE_CXXFLAGS_WARN_ON -= -w34100 - # Release mode debugging - QMAKE_CXXFLAGS += /Zi - QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF + # Release mode debugging + QMAKE_CXXFLAGS += /Zi + QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF - # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything - Project.target = $${TARGET}.vcxproj - Project.output = $${TARGET}.vcxproj - Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 - Project.depends = '"$${_PRO_FILE_}"' - Project.input = _PRO_FILE_ - QMAKE_EXTRA_COMPILERS += Project + # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything + Project.target = $${TARGET}.vcxproj + Project.output = $${TARGET}.vcxproj + Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 + Project.depends = '"$${_PRO_FILE_}"' + Project.input = _PRO_FILE_ + QMAKE_EXTRA_COMPILERS += Project - # This makes the documentation - MARKDOWN_FILES = \ - test.md \ - test2.md + # This makes the documentation + MARKDOWN_FILES = \ + test.md \ + test2.md - Documentation.target = test.pdf - Documentation.output = test.pdf - Documentation.commands = echo ' ' > test.pdf - Documentation.depends = '"$${MARKDOWN_FILES}"' - Documentation.input = MARKDOWN_FILES - QMAKE_EXTRA_COMPILERS += Documentation + Documentation.target = test.pdf + Documentation.output = test.pdf + Documentation.commands = echo ' ' > test.pdf + Documentation.depends = '"$${MARKDOWN_FILES}"' + Documentation.input = MARKDOWN_FILES + QMAKE_EXTRA_COMPILERS += Documentation - INCLUDEPATH += \ - ../3rdParty/libpng \ - ../3rdParty/zlib + INCLUDEPATH += \ + ../3rdParty/libpng \ + ../3rdParty/zlib - SOURCES += \ - ../3rdParty/libpng/png.c \ - ../3rdParty/libpng/pngerror.c \ - ../3rdParty/libpng/pngget.c \ - ../3rdParty/libpng/pngmem.c \ - ../3rdParty/libpng/pngpread.c \ - ../3rdParty/libpng/pngread.c \ - ../3rdParty/libpng/pngrio.c \ - ../3rdParty/libpng/pngrtran.c \ - ../3rdParty/libpng/pngrutil.c \ - ../3rdParty/libpng/pngset.c \ - ../3rdParty/libpng/pngtrans.c \ - ../3rdParty/libpng/pngwio.c \ - ../3rdParty/libpng/pngwrite.c \ - ../3rdParty/libpng/pngwtran.c \ - ../3rdParty/libpng/pngwutil.c + SOURCES += \ + ../3rdParty/libpng/png.c \ + ../3rdParty/libpng/pngerror.c \ + ../3rdParty/libpng/pngget.c \ + ../3rdParty/libpng/pngmem.c \ + ../3rdParty/libpng/pngpread.c \ + ../3rdParty/libpng/pngread.c \ + ../3rdParty/libpng/pngrio.c \ + ../3rdParty/libpng/pngrtran.c \ + ../3rdParty/libpng/pngrutil.c \ + ../3rdParty/libpng/pngset.c \ + ../3rdParty/libpng/pngtrans.c \ + ../3rdParty/libpng/pngwio.c \ + ../3rdParty/libpng/pngwrite.c \ + ../3rdParty/libpng/pngwtran.c \ + ../3rdParty/libpng/pngwutil.c - SOURCES += \ - ../3rdParty/zlib/inftrees.c \ - ../3rdParty/zlib/trees.c \ - ../3rdParty/zlib/uncompr.c \ - ../3rdParty/zlib/zutil.c \ - ../3rdParty/zlib/adler32.c \ - ../3rdParty/zlib/compress.c \ - ../3rdParty/zlib/crc32.c \ - ../3rdParty/zlib/deflate.c \ - ../3rdParty/zlib/gzclose.c \ - ../3rdParty/zlib/gzlib.c \ - ../3rdParty/zlib/gzread.c \ - ../3rdParty/zlib/gzwrite.c \ - ../3rdParty/zlib/infback.c \ - ../3rdParty/zlib/inffast.c \ - ../3rdParty/zlib/inflate.c + SOURCES += \ + ../3rdParty/zlib/inftrees.c \ + ../3rdParty/zlib/trees.c \ + ../3rdParty/zlib/uncompr.c \ + ../3rdParty/zlib/zutil.c \ + ../3rdParty/zlib/adler32.c \ + ../3rdParty/zlib/compress.c \ + ../3rdParty/zlib/crc32.c \ + ../3rdParty/zlib/deflate.c \ + ../3rdParty/zlib/gzclose.c \ + ../3rdParty/zlib/gzlib.c \ + ../3rdParty/zlib/gzread.c \ + ../3rdParty/zlib/gzwrite.c \ + ../3rdParty/zlib/infback.c \ + ../3rdParty/zlib/inffast.c \ + ../3rdParty/zlib/inflate.c } +OTHER_FILES += \ + ../Website/about.html \ + ../Website/register.html \ + ../Website/support.html + diff --git a/Resources/forms/About.ui b/Resources/forms/About.ui index bd6bdf3..3265d89 100644 --- a/Resources/forms/About.ui +++ b/Resources/forms/About.ui @@ -152,7 +152,7 @@ QFrame::Plain - + 20 @@ -165,7 +165,7 @@ <html><head/><body><p><a href="http://url.to.application/"><span style=" text-decoration: underline; color:#0000ff;">http://url.to.application/</span></a></p></body></html> - + 360 @@ -175,16 +175,16 @@ - - - - :/images/images/logo.svg + AppIcon true + + Qt::AlignCenter + - + 20 @@ -193,11 +193,18 @@ 31 + + + 20 + 75 + true + + - <html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Wicked Docs</span></p></body></html> + AppName - + 20 @@ -207,7 +214,7 @@ - <html><head/><body><p>Version 1.0.0.0001</p></body></html> + AppVer @@ -337,7 +344,7 @@ - <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://blah/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements / LicensesEULA</span></a></p></body></html> + <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br/><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://sdfdsf/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements &amp; Licenses</span></a>&nbsp;&nbsp;<a href="http://sfsdf/"><span style=" text-decoration: underline; color:#0000ff;">EULA</span></a></p></body></html> label_5 @@ -346,9 +353,7 @@ - - - + okayButton diff --git a/Resources/forms/ExtensibleObjectModelUI.ui b/Resources/forms/ExtensibleObjectModelUI.ui index 4a794d4..c3fcbc4 100644 --- a/Resources/forms/ExtensibleObjectModelUI.ui +++ b/Resources/forms/ExtensibleObjectModelUI.ui @@ -250,7 +250,7 @@ 0 - + @@ -347,7 +347,7 @@
- + @@ -478,6 +478,16 @@ + + + + + 0 + 200 + + + + @@ -921,6 +931,14 @@ + + + QWebView + QWidget +
QWebView
+ 1 +
+
diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/MdiWindow.h b/MdiWindow.h index 76d7f1b..35ef9c3 100644 --- a/MdiWindow.h +++ b/MdiWindow.h @@ -4,78 +4,19 @@ #include #include +#include "Objects.h" +#include "MdiChild.h" -class MdiChild; class QAction; class QMenu; class QMdiArea; class QMdiSubWindow; class QSignalMapper; +class QTcpServer; class Ui_MainWindow; -class MdiChild : public QTextEdit -{ - Q_OBJECT -public: - MdiChild(); - ~MdiChild(); - - void newFile(); - bool loadFile(const QString &fileName); - bool save(); - bool saveAs(); - bool saveFile(const QString &fileName); - QString userFriendlyCurrentFile(); - QString currentFile() { return curFile; } - - void markdownSelection(const char* preText, const char* postText); - - void bold(); - void italic(); - void quote(); - void code(); - void heading1(); - void heading2(); - void heading3(); - void heading4(); - void hyperlink(); - void image(); - void unorderedList(); - void orderedList(); - void horizontalRule(); - void timestamp(); - void pageNumber(); - void pageCount(); - void del(); - void undo(); - void redo(); - void find(); - void findNext(); - void findPrevious(); - void goToLine(); - -signals: - void closing(); - void documentContentsChanged(); - -private slots: - void documentWasModified(); - -protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - -private: - bool maybeSave(); - void setCurrentFile(const QString &fileName); - QString strippedName(const QString &fullFileName); - - QString curFile; - bool isUntitled; -}; - - /* class MdiOptions { @@ -109,8 +50,12 @@ void save(); void saveAs(); + void handleRequest(); void updatePreview(); + void setWebPreviewURL(); + void refreshWebPreview(); + // Edit menu actions #ifndef QT_NO_CLIPBOARD void cut(); @@ -159,12 +104,26 @@ void switchLayoutDirection(); void setActiveSubWindow(QWidget *window); + void changeRootObject(const QModelIndex &index); + void changePropertiesObject(const QModelIndex &index); + + // Dialog events + void upgradeClicked(); + private: + void changeProjectTree(QObject *rootObject); + void updateObjectTree(QObject *rootObject); + void updatePropertiesView(QObject *object); + void setupServer(); void readSettings(); + void readLicense(); void writeSettings(); MdiChild *activeMdiChild(); QMdiSubWindow *findMdiChild(const QString &fileName); + //Solution solution; + QByteArray pdfContents; + QTcpServer *server; QMdiArea *mdiArea; QSignalMapper *windowMapper; Ui_MainWindow *appWindow; diff --git a/ObjectVisitor.h b/ObjectVisitor.h new file mode 100644 index 0000000..12cf25f --- /dev/null +++ b/ObjectVisitor.h @@ -0,0 +1,59 @@ +#ifndef OBJECTVISITOR_H +#define OBJECTVISITOR_H + + +#include +#include +#include +#include + + +class Visitor +{ +public: + Visitor() {} + virtual ~Visitor() {} + + virtual void enterObject(const char* className, const char* objectName) = 0; + virtual void leaveObject(const char* className, const char* objectName) = 0; + + // Reads or writes a property value + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) = 0; + + // By default, it is a reader, but implementing this enables a visitor that sets values + virtual bool isWriting() { return false; } +}; + + +void Visit(Visitor& visitor, QObject* object) +{ + std::string objectName = object->objectName().toLocal8Bit().data(); + if (objectName.size() <= 1) { + objectName = std::to_string((uint64_t)(void*)object); + } + visitor.enterObject(object->metaObject()->className(), objectName.c_str()); + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + if (visitor.isWriting()) { + QVariant value; + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + property.write(object, value); + + } else { + QVariant value = property.read(object); + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + } + } + for (int i = 0; i < object->children().count(); i++) + { + Visit(visitor, object->children()[i]); + } + visitor.leaveObject(object->metaObject()->className(), objectName.c_str()); +} + + +#endif // OBJECTVISITOR_H diff --git a/Objects.h b/Objects.h new file mode 100644 index 0000000..90e7bb1 --- /dev/null +++ b/Objects.h @@ -0,0 +1,167 @@ +#ifndef OBJECTS_H +#define OBJECTS_H + + +#include +#include +#include +#include +#include +#include +#include + + +class EnumEditor : public QWidget +{ + Q_OBJECT +public slots: + void ListSelectionChanged(); + void ComboSelectionChanged(); +public: + EnumEditor(QMetaEnum metaEnum); +private: + QListWidget* lw; + QComboBox* cb; + QSpinBox* sb; + QLabel* str; + QMetaEnum m_metaEnum; +}; + + +// Property Manager Supported types: +// int, bool, double, enums, flags +// QString, QDate, QTime, QDateTime, QKeySequence +// QChar, QLocale, QPoint, QPointF, QSize, QSizeF +// QRect, QRectF, QSizePolicy, QFont, QColor, QCursor + + +#define PROP_WRAP(type, name) \ + Q_PROPERTY(type name READ get##name WRITE set##name) \ + type get##name() const { return m_##name; } \ + void set##name(type val) { m_##name = val; } \ + type m_##name; + +#define CHILD_PTR_PROP_WRAP(type, name) \ + Q_PROPERTY(type* name READ get##name WRITE set##name) \ + type* get##name() const { return m_##name; } \ + void set##name(type* val) { \ + /* if (m_##name) children().removeAll((QObject*)m_##name); */ \ + val->setParent(this); \ + m_##name = val; \ + } \ + type* m_##name = nullptr; + + +class MyObjectTest : public QObject +{ + Q_OBJECT + Q_ENUMS(AnotherEnum) + Q_ENUMS(TestEnum) + Q_FLAGS(TestFlags) +public: + enum TestFlags { FlagValue1 = 1, AnotherFlagValue = 2, FlagEtc = 4, FlagBlah = 8 }; + enum TestEnum { EnumValue1, AnotherValue, Etc, Blah }; + enum AnotherEnum { AEnumValue1, AnAnotherValue, Etc2 }; + + explicit MyObjectTest() : QObject() { + m_An_Int_Value = 10; + m_A_Double = 11.0; + //m_An_Enum = EnumValue1; + //memset(this, 0, sizeof(MyObjectTest)); + } + ~MyObjectTest() { + } + + PROP_WRAP(int, An_Int_Value) + PROP_WRAP(bool, A_Bool) + PROP_WRAP(double, A_Double) + PROP_WRAP(TestEnum,An_Enum1) + PROP_WRAP(TestEnum,An_Enum2) + PROP_WRAP(QFlags,A_Flags) + PROP_WRAP(QString, A_String) + PROP_WRAP(QDate, A_Date) + PROP_WRAP(QTime, A_Time) + PROP_WRAP(QDateTime, A_Date_and_Time) + PROP_WRAP(QKeySequence, A_Key_Sequence) + PROP_WRAP(QChar, A_Char) + PROP_WRAP(QLocale, A_Locale) + PROP_WRAP(QPoint, A_Point) + PROP_WRAP(QPointF, A_PointF) + PROP_WRAP(QSize, A_Size) + PROP_WRAP(QSizeF, A_SizeF) + PROP_WRAP(QRect, A_Rect) + PROP_WRAP(QRectF, A_RectF) + //PROP_WRAP(QSizePolicy, A_SizePolicy) + //PROP_WRAP(QFont, A_Font) + PROP_WRAP(QColor, A_Color) + //PROP_WRAP(QCursor, A_Cursor) + // flags +}; + + + +class Template : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) + PROP_WRAP(QColor, Color) +}; + + +class Output : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + PROP_WRAP(QString, Title) + PROP_WRAP(QString, Filename) + PROP_WRAP(FileTypes, FileType) +}; + + +class Input : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) +}; + + +class Project : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + //PROP_WRAP(QString, Name) + PROP_WRAP(QString, Author) + //PROP_WRAP(Template*, Template) + //PROP_WRAP(QList, Inputs) + //PROP_WRAP(Output*, Output) + + //CHILD_PTR_PROP_WRAP(Output, Output) + //CHILD_PTR_PROP_WRAP(Template, Template) + + PROP_WRAP(QString, Title) + PROP_WRAP(QString, OutputFilename) + PROP_WRAP(FileTypes, OutputFileType) + + PROP_WRAP(QString, Template) + PROP_WRAP(QColor, Color) + + void AddInput(Input* in) { in->setParent(this); } +}; + + +class Solution : public QObject +{ + Q_OBJECT +public: + //PROP_WRAP(QList, Projects) + void AddProject(Project* proj) { proj->setParent(this); } +}; + + +#endif // OBJECTS_H diff --git a/QtProject/MakePDF.pro b/QtProject/MakePDF.pro index f4e410c..4026759 100644 --- a/QtProject/MakePDF.pro +++ b/QtProject/MakePDF.pro @@ -1,21 +1,24 @@ -QT += core gui widgets +# QT += webkitwidgets network widgets +CONFIG += qt +QT += core gui widgets webkitwidgets +#QT += svg CONFIG -= flat TARGET = MakePDF DEFINES += \ - GUI_APP=1 + GUI_APP=1 RESOURCES += \ - ../Resources/resources.qrc + ../Resources/resources.qrc FORMS += \ - ../Resources/forms/About.ui \ - ../Resources/forms/NewProjectWizard.ui \ - ../Resources/forms/ExtensibleObjectModelUI.ui \ - ../Resources/forms/SendBugReport.ui \ + ../Resources/forms/About.ui \ + ../Resources/forms/NewProjectWizard.ui \ + ../Resources/forms/ExtensibleObjectModelUI.ui \ + ../Resources/forms/SendBugReport.ui \ ../Resources/forms/Help.ui \ ../Resources/forms/CheckUpdates.ui \ ../Resources/forms/LicenseUpgrade.ui \ @@ -23,136 +26,174 @@ ../Resources/forms/PaletteEditor.ui INCLUDEPATH += \ - ../Framework \ - ../3rdParty/hoedown \ - ../3rdParty/libharu/include \ - ../3rdParty/TinyXML++ + ../Framework \ + ../3rdParty/hoedown \ + ../3rdParty/libharu/include \ + ../3rdParty/TinyXML++ \ + ../3rdParty/qtpropertybrowser/src HEADERS += \ - ../Framework/EventLog.h \ - ../Framework/Expected.h \ - ../Framework/Final.h \ - ../Framework/Finally.h \ - ../Framework/GenericTable.h \ - ../Framework/GenericTableUI.h \ - ../Framework/NonCopyable.h \ - ../Framework/Utilities.h \ + ../Framework/EventLog.h \ + ../Framework/Expected.h \ + ../Framework/Final.h \ + ../Framework/Finally.h \ + ../Framework/GenericTable.h \ + ../Framework/GenericTableUI.h \ + ../Framework/NonCopyable.h \ + ../Framework/Utilities.h \ + ../Framework/SystemInfomation.h \ + ../Framework/Array.h \ + ../Framework/Macros.h \ + ../Framework/ObjectTreeModel.h \ + ../Version.h \ + ../Util.h \ ../ui.h \ + ../MdiChild.h \ ../MdiWindow.h \ ../ColorPicker.h \ - ../Version.h + ../DocConvert.h \ + ../Objects.h \ + ../ObjectVisitor.h HEADERS += \ - ../DocOutput.h \ - ../DocProject.h \ - ../DocStyle.h \ - ../DocTemplate.h \ - ../DocVisitor.h \ - ../DocSVG.h + ../DocOutput.h \ + ../DocProject.h \ + ../DocStyle.h \ + ../DocTemplate.h \ + ../DocVisitor.h \ + ../DocSVG.h SOURCES += \ - ../Framework/Tests.cpp \ - ../Framework/Utilities.cpp \ - ../Framework/EventLog.cpp \ + ../Framework/Tests.cpp \ + ../Framework/Utilities.cpp \ + ../Framework/EventLog.cpp \ + ../MdiChild.cpp \ ../MdiWindow.cpp \ ../ColorPicker.cpp \ - ../Version.cpp + ../Version.cpp \ + ../Framework/SystemInfomation.cpp \ + ../DocConvert.cpp \ + ../Framework/ObjectTreeModel.cpp SOURCES += \ - ../DocOutput.cpp \ - ../DocProject.cpp \ - ../DocStyle.cpp \ - ../DocTemplate.cpp \ - ../DocVisitor.cpp \ - ../DocSVG.cpp \ - ../main.cpp + ../DocOutput.cpp \ + ../DocProject.cpp \ + ../DocStyle.cpp \ + ../DocTemplate.cpp \ + ../DocVisitor.cpp \ + ../DocSVG.cpp \ + ../main.cpp SOURCES += \ - ../3rdParty/hoedown/autolink.c \ - ../3rdParty/hoedown/buffer.c \ - ../3rdParty/hoedown/document.c \ - ../3rdParty/hoedown/escape.c \ - ../3rdParty/hoedown/html.c \ - ../3rdParty/hoedown/html_blocks.c \ - ../3rdParty/hoedown/stack.c + ../3rdParty/hoedown/autolink.c \ + ../3rdParty/hoedown/buffer.c \ + ../3rdParty/hoedown/document.c \ + ../3rdParty/hoedown/escape.c \ + ../3rdParty/hoedown/html.c \ + ../3rdParty/hoedown/html_blocks.c \ + ../3rdParty/hoedown/stack.c SOURCES += \ - ../3rdParty/libharu/src/hpdf_3dmeasure.c \ - ../3rdParty/libharu/src/hpdf_annotation.c \ - ../3rdParty/libharu/src/hpdf_array.c \ - ../3rdParty/libharu/src/hpdf_binary.c \ - ../3rdParty/libharu/src/hpdf_boolean.c \ - ../3rdParty/libharu/src/hpdf_catalog.c \ - ../3rdParty/libharu/src/hpdf_destination.c \ - ../3rdParty/libharu/src/hpdf_dict.c \ - ../3rdParty/libharu/src/hpdf_doc.c \ - ../3rdParty/libharu/src/hpdf_doc_png.c \ - ../3rdParty/libharu/src/hpdf_encoder.c \ - ../3rdParty/libharu/src/hpdf_encoder_utf.c \ - ../3rdParty/libharu/src/hpdf_encrypt.c \ - ../3rdParty/libharu/src/hpdf_encryptdict.c \ - ../3rdParty/libharu/src/hpdf_error.c \ - ../3rdParty/libharu/src/hpdf_exdata.c \ - ../3rdParty/libharu/src/hpdf_ext_gstate.c \ - ../3rdParty/libharu/src/hpdf_font.c \ - ../3rdParty/libharu/src/hpdf_fontdef.c \ - ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ - ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ - ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ - ../3rdParty/libharu/src/hpdf_font_cid.c \ - ../3rdParty/libharu/src/hpdf_font_tt.c \ - ../3rdParty/libharu/src/hpdf_font_type1.c \ - ../3rdParty/libharu/src/hpdf_gstate.c \ - ../3rdParty/libharu/src/hpdf_image.c \ - ../3rdParty/libharu/src/hpdf_image_png.c \ - ../3rdParty/libharu/src/hpdf_info.c \ - ../3rdParty/libharu/src/hpdf_list.c \ - ../3rdParty/libharu/src/hpdf_mmgr.c \ - ../3rdParty/libharu/src/hpdf_name.c \ - ../3rdParty/libharu/src/hpdf_namedict.c \ - ../3rdParty/libharu/src/hpdf_null.c \ - ../3rdParty/libharu/src/hpdf_number.c \ - ../3rdParty/libharu/src/hpdf_objects.c \ - ../3rdParty/libharu/src/hpdf_outline.c \ - ../3rdParty/libharu/src/hpdf_pages.c \ - ../3rdParty/libharu/src/hpdf_page_label.c \ - ../3rdParty/libharu/src/hpdf_page_operator.c \ - ../3rdParty/libharu/src/hpdf_pdfa.c \ - ../3rdParty/libharu/src/hpdf_real.c \ - ../3rdParty/libharu/src/hpdf_streams.c \ - ../3rdParty/libharu/src/hpdf_string.c \ - ../3rdParty/libharu/src/hpdf_u3d.c \ - ../3rdParty/libharu/src/hpdf_utils.c \ - ../3rdParty/libharu/src/hpdf_xref.c + ../3rdParty/libharu/src/hpdf_3dmeasure.c \ + ../3rdParty/libharu/src/hpdf_annotation.c \ + ../3rdParty/libharu/src/hpdf_array.c \ + ../3rdParty/libharu/src/hpdf_binary.c \ + ../3rdParty/libharu/src/hpdf_boolean.c \ + ../3rdParty/libharu/src/hpdf_catalog.c \ + ../3rdParty/libharu/src/hpdf_destination.c \ + ../3rdParty/libharu/src/hpdf_dict.c \ + ../3rdParty/libharu/src/hpdf_doc.c \ + ../3rdParty/libharu/src/hpdf_doc_png.c \ + ../3rdParty/libharu/src/hpdf_encoder.c \ + ../3rdParty/libharu/src/hpdf_encoder_utf.c \ + ../3rdParty/libharu/src/hpdf_encrypt.c \ + ../3rdParty/libharu/src/hpdf_encryptdict.c \ + ../3rdParty/libharu/src/hpdf_error.c \ + ../3rdParty/libharu/src/hpdf_exdata.c \ + ../3rdParty/libharu/src/hpdf_ext_gstate.c \ + ../3rdParty/libharu/src/hpdf_font.c \ + ../3rdParty/libharu/src/hpdf_fontdef.c \ + ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ + ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ + ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ + ../3rdParty/libharu/src/hpdf_font_cid.c \ + ../3rdParty/libharu/src/hpdf_font_tt.c \ + ../3rdParty/libharu/src/hpdf_font_type1.c \ + ../3rdParty/libharu/src/hpdf_gstate.c \ + ../3rdParty/libharu/src/hpdf_image.c \ + ../3rdParty/libharu/src/hpdf_image_png.c \ + ../3rdParty/libharu/src/hpdf_info.c \ + ../3rdParty/libharu/src/hpdf_list.c \ + ../3rdParty/libharu/src/hpdf_mmgr.c \ + ../3rdParty/libharu/src/hpdf_name.c \ + ../3rdParty/libharu/src/hpdf_namedict.c \ + ../3rdParty/libharu/src/hpdf_null.c \ + ../3rdParty/libharu/src/hpdf_number.c \ + ../3rdParty/libharu/src/hpdf_objects.c \ + ../3rdParty/libharu/src/hpdf_outline.c \ + ../3rdParty/libharu/src/hpdf_pages.c \ + ../3rdParty/libharu/src/hpdf_page_label.c \ + ../3rdParty/libharu/src/hpdf_page_operator.c \ + ../3rdParty/libharu/src/hpdf_pdfa.c \ + ../3rdParty/libharu/src/hpdf_real.c \ + ../3rdParty/libharu/src/hpdf_streams.c \ + ../3rdParty/libharu/src/hpdf_string.c \ + ../3rdParty/libharu/src/hpdf_u3d.c \ + ../3rdParty/libharu/src/hpdf_utils.c \ + ../3rdParty/libharu/src/hpdf_xref.c SOURCES += \ - ../3rdParty/TinyXML++/ticpp.cpp \ - ../3rdParty/TinyXML++/tinystr.cpp \ - ../3rdParty/TinyXML++/tinyxml.cpp \ - ../3rdParty/TinyXML++/tinyxmlerror.cpp \ - ../3rdParty/TinyXML++/tinyxmlparser.cpp + ../3rdParty/TinyXML++/ticpp.cpp \ + ../3rdParty/TinyXML++/tinystr.cpp \ + ../3rdParty/TinyXML++/tinyxml.cpp \ + ../3rdParty/TinyXML++/tinyxmlerror.cpp \ + ../3rdParty/TinyXML++/tinyxmlparser.cpp + + +SOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.cpp \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.cpp \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.cpp \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils.cpp + +HEADERS += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.h \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.h \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.h \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils_p.h + +RESOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.qrc # As a note to what was removed REMOVED_SOURCES = \ - ../3rdParty/hoedown/html_smartypants.c \ - ../3rdParty/hoedown/version.c \ - ../3rdParty/libharu/src/hpdf_image_ccitt.c + ../3rdParty/hoedown/html_smartypants.c \ + ../3rdParty/hoedown/version.c \ + ../3rdParty/libharu/src/hpdf_image_ccitt.c # Linux specific settings unix { - QMAKE_CXXFLAGS += --std=gnu++11 - # QMAKE_CXXFLAGS -= -Wall - QMAKE_CXXFLAGS_WARN_ON=-w - QMAKE_CFLAGS_WARN_ON=-w - LIBS += -lpng -lz + QMAKE_CXXFLAGS += --std=gnu++11 + # QMAKE_CXXFLAGS -= -Wall + QMAKE_CXXFLAGS_WARN_ON=-w + QMAKE_CFLAGS_WARN_ON=-w + LIBS += -lpng -lz } @@ -160,77 +201,82 @@ # Windows specific. Note we compile in libpng and zlib statically on Windows win32 { - # Supress annoying warnings - QMAKE_CXXFLAGS += /wd"4996;4100" - QMAKE_CXXFLAGS_WARN_ON -= -w34100 + # Supress annoying warnings + QMAKE_CXXFLAGS += /wd"4996;4100" + QMAKE_CXXFLAGS_WARN_ON -= -w34100 - # Release mode debugging - QMAKE_CXXFLAGS += /Zi - QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF + # Release mode debugging + QMAKE_CXXFLAGS += /Zi + QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF - # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything - Project.target = $${TARGET}.vcxproj - Project.output = $${TARGET}.vcxproj - Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 - Project.depends = '"$${_PRO_FILE_}"' - Project.input = _PRO_FILE_ - QMAKE_EXTRA_COMPILERS += Project + # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything + Project.target = $${TARGET}.vcxproj + Project.output = $${TARGET}.vcxproj + Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 + Project.depends = '"$${_PRO_FILE_}"' + Project.input = _PRO_FILE_ + QMAKE_EXTRA_COMPILERS += Project - # This makes the documentation - MARKDOWN_FILES = \ - test.md \ - test2.md + # This makes the documentation + MARKDOWN_FILES = \ + test.md \ + test2.md - Documentation.target = test.pdf - Documentation.output = test.pdf - Documentation.commands = echo ' ' > test.pdf - Documentation.depends = '"$${MARKDOWN_FILES}"' - Documentation.input = MARKDOWN_FILES - QMAKE_EXTRA_COMPILERS += Documentation + Documentation.target = test.pdf + Documentation.output = test.pdf + Documentation.commands = echo ' ' > test.pdf + Documentation.depends = '"$${MARKDOWN_FILES}"' + Documentation.input = MARKDOWN_FILES + QMAKE_EXTRA_COMPILERS += Documentation - INCLUDEPATH += \ - ../3rdParty/libpng \ - ../3rdParty/zlib + INCLUDEPATH += \ + ../3rdParty/libpng \ + ../3rdParty/zlib - SOURCES += \ - ../3rdParty/libpng/png.c \ - ../3rdParty/libpng/pngerror.c \ - ../3rdParty/libpng/pngget.c \ - ../3rdParty/libpng/pngmem.c \ - ../3rdParty/libpng/pngpread.c \ - ../3rdParty/libpng/pngread.c \ - ../3rdParty/libpng/pngrio.c \ - ../3rdParty/libpng/pngrtran.c \ - ../3rdParty/libpng/pngrutil.c \ - ../3rdParty/libpng/pngset.c \ - ../3rdParty/libpng/pngtrans.c \ - ../3rdParty/libpng/pngwio.c \ - ../3rdParty/libpng/pngwrite.c \ - ../3rdParty/libpng/pngwtran.c \ - ../3rdParty/libpng/pngwutil.c + SOURCES += \ + ../3rdParty/libpng/png.c \ + ../3rdParty/libpng/pngerror.c \ + ../3rdParty/libpng/pngget.c \ + ../3rdParty/libpng/pngmem.c \ + ../3rdParty/libpng/pngpread.c \ + ../3rdParty/libpng/pngread.c \ + ../3rdParty/libpng/pngrio.c \ + ../3rdParty/libpng/pngrtran.c \ + ../3rdParty/libpng/pngrutil.c \ + ../3rdParty/libpng/pngset.c \ + ../3rdParty/libpng/pngtrans.c \ + ../3rdParty/libpng/pngwio.c \ + ../3rdParty/libpng/pngwrite.c \ + ../3rdParty/libpng/pngwtran.c \ + ../3rdParty/libpng/pngwutil.c - SOURCES += \ - ../3rdParty/zlib/inftrees.c \ - ../3rdParty/zlib/trees.c \ - ../3rdParty/zlib/uncompr.c \ - ../3rdParty/zlib/zutil.c \ - ../3rdParty/zlib/adler32.c \ - ../3rdParty/zlib/compress.c \ - ../3rdParty/zlib/crc32.c \ - ../3rdParty/zlib/deflate.c \ - ../3rdParty/zlib/gzclose.c \ - ../3rdParty/zlib/gzlib.c \ - ../3rdParty/zlib/gzread.c \ - ../3rdParty/zlib/gzwrite.c \ - ../3rdParty/zlib/infback.c \ - ../3rdParty/zlib/inffast.c \ - ../3rdParty/zlib/inflate.c + SOURCES += \ + ../3rdParty/zlib/inftrees.c \ + ../3rdParty/zlib/trees.c \ + ../3rdParty/zlib/uncompr.c \ + ../3rdParty/zlib/zutil.c \ + ../3rdParty/zlib/adler32.c \ + ../3rdParty/zlib/compress.c \ + ../3rdParty/zlib/crc32.c \ + ../3rdParty/zlib/deflate.c \ + ../3rdParty/zlib/gzclose.c \ + ../3rdParty/zlib/gzlib.c \ + ../3rdParty/zlib/gzread.c \ + ../3rdParty/zlib/gzwrite.c \ + ../3rdParty/zlib/infback.c \ + ../3rdParty/zlib/inffast.c \ + ../3rdParty/zlib/inflate.c } +OTHER_FILES += \ + ../Website/about.html \ + ../Website/register.html \ + ../Website/support.html + diff --git a/Resources/forms/About.ui b/Resources/forms/About.ui index bd6bdf3..3265d89 100644 --- a/Resources/forms/About.ui +++ b/Resources/forms/About.ui @@ -152,7 +152,7 @@ QFrame::Plain - + 20 @@ -165,7 +165,7 @@ <html><head/><body><p><a href="http://url.to.application/"><span style=" text-decoration: underline; color:#0000ff;">http://url.to.application/</span></a></p></body></html> - + 360 @@ -175,16 +175,16 @@ - - - - :/images/images/logo.svg + AppIcon true + + Qt::AlignCenter + - + 20 @@ -193,11 +193,18 @@ 31 + + + 20 + 75 + true + + - <html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Wicked Docs</span></p></body></html> + AppName - + 20 @@ -207,7 +214,7 @@ - <html><head/><body><p>Version 1.0.0.0001</p></body></html> + AppVer @@ -337,7 +344,7 @@ - <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://blah/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements / LicensesEULA</span></a></p></body></html> + <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br/><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://sdfdsf/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements &amp; Licenses</span></a>&nbsp;&nbsp;<a href="http://sfsdf/"><span style=" text-decoration: underline; color:#0000ff;">EULA</span></a></p></body></html> label_5 @@ -346,9 +353,7 @@ - - - + okayButton diff --git a/Resources/forms/ExtensibleObjectModelUI.ui b/Resources/forms/ExtensibleObjectModelUI.ui index 4a794d4..c3fcbc4 100644 --- a/Resources/forms/ExtensibleObjectModelUI.ui +++ b/Resources/forms/ExtensibleObjectModelUI.ui @@ -250,7 +250,7 @@ 0 - + @@ -347,7 +347,7 @@ - + @@ -478,6 +478,16 @@ + + + + + 0 + 200 + + + + @@ -921,6 +931,14 @@ + + + QWebView + QWidget +
QWebView
+ 1 +
+
diff --git a/Resources/forms/LicenseUpgrade.ui b/Resources/forms/LicenseUpgrade.ui index 69b55ad..4ce2ac1 100644 --- a/Resources/forms/LicenseUpgrade.ui +++ b/Resources/forms/LicenseUpgrade.ui @@ -42,7 +42,7 @@ Upgrade license - + 290 diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/MdiWindow.h b/MdiWindow.h index 76d7f1b..35ef9c3 100644 --- a/MdiWindow.h +++ b/MdiWindow.h @@ -4,78 +4,19 @@ #include #include +#include "Objects.h" +#include "MdiChild.h" -class MdiChild; class QAction; class QMenu; class QMdiArea; class QMdiSubWindow; class QSignalMapper; +class QTcpServer; class Ui_MainWindow; -class MdiChild : public QTextEdit -{ - Q_OBJECT -public: - MdiChild(); - ~MdiChild(); - - void newFile(); - bool loadFile(const QString &fileName); - bool save(); - bool saveAs(); - bool saveFile(const QString &fileName); - QString userFriendlyCurrentFile(); - QString currentFile() { return curFile; } - - void markdownSelection(const char* preText, const char* postText); - - void bold(); - void italic(); - void quote(); - void code(); - void heading1(); - void heading2(); - void heading3(); - void heading4(); - void hyperlink(); - void image(); - void unorderedList(); - void orderedList(); - void horizontalRule(); - void timestamp(); - void pageNumber(); - void pageCount(); - void del(); - void undo(); - void redo(); - void find(); - void findNext(); - void findPrevious(); - void goToLine(); - -signals: - void closing(); - void documentContentsChanged(); - -private slots: - void documentWasModified(); - -protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - -private: - bool maybeSave(); - void setCurrentFile(const QString &fileName); - QString strippedName(const QString &fullFileName); - - QString curFile; - bool isUntitled; -}; - - /* class MdiOptions { @@ -109,8 +50,12 @@ void save(); void saveAs(); + void handleRequest(); void updatePreview(); + void setWebPreviewURL(); + void refreshWebPreview(); + // Edit menu actions #ifndef QT_NO_CLIPBOARD void cut(); @@ -159,12 +104,26 @@ void switchLayoutDirection(); void setActiveSubWindow(QWidget *window); + void changeRootObject(const QModelIndex &index); + void changePropertiesObject(const QModelIndex &index); + + // Dialog events + void upgradeClicked(); + private: + void changeProjectTree(QObject *rootObject); + void updateObjectTree(QObject *rootObject); + void updatePropertiesView(QObject *object); + void setupServer(); void readSettings(); + void readLicense(); void writeSettings(); MdiChild *activeMdiChild(); QMdiSubWindow *findMdiChild(const QString &fileName); + //Solution solution; + QByteArray pdfContents; + QTcpServer *server; QMdiArea *mdiArea; QSignalMapper *windowMapper; Ui_MainWindow *appWindow; diff --git a/ObjectVisitor.h b/ObjectVisitor.h new file mode 100644 index 0000000..12cf25f --- /dev/null +++ b/ObjectVisitor.h @@ -0,0 +1,59 @@ +#ifndef OBJECTVISITOR_H +#define OBJECTVISITOR_H + + +#include +#include +#include +#include + + +class Visitor +{ +public: + Visitor() {} + virtual ~Visitor() {} + + virtual void enterObject(const char* className, const char* objectName) = 0; + virtual void leaveObject(const char* className, const char* objectName) = 0; + + // Reads or writes a property value + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) = 0; + + // By default, it is a reader, but implementing this enables a visitor that sets values + virtual bool isWriting() { return false; } +}; + + +void Visit(Visitor& visitor, QObject* object) +{ + std::string objectName = object->objectName().toLocal8Bit().data(); + if (objectName.size() <= 1) { + objectName = std::to_string((uint64_t)(void*)object); + } + visitor.enterObject(object->metaObject()->className(), objectName.c_str()); + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + if (visitor.isWriting()) { + QVariant value; + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + property.write(object, value); + + } else { + QVariant value = property.read(object); + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + } + } + for (int i = 0; i < object->children().count(); i++) + { + Visit(visitor, object->children()[i]); + } + visitor.leaveObject(object->metaObject()->className(), objectName.c_str()); +} + + +#endif // OBJECTVISITOR_H diff --git a/Objects.h b/Objects.h new file mode 100644 index 0000000..90e7bb1 --- /dev/null +++ b/Objects.h @@ -0,0 +1,167 @@ +#ifndef OBJECTS_H +#define OBJECTS_H + + +#include +#include +#include +#include +#include +#include +#include + + +class EnumEditor : public QWidget +{ + Q_OBJECT +public slots: + void ListSelectionChanged(); + void ComboSelectionChanged(); +public: + EnumEditor(QMetaEnum metaEnum); +private: + QListWidget* lw; + QComboBox* cb; + QSpinBox* sb; + QLabel* str; + QMetaEnum m_metaEnum; +}; + + +// Property Manager Supported types: +// int, bool, double, enums, flags +// QString, QDate, QTime, QDateTime, QKeySequence +// QChar, QLocale, QPoint, QPointF, QSize, QSizeF +// QRect, QRectF, QSizePolicy, QFont, QColor, QCursor + + +#define PROP_WRAP(type, name) \ + Q_PROPERTY(type name READ get##name WRITE set##name) \ + type get##name() const { return m_##name; } \ + void set##name(type val) { m_##name = val; } \ + type m_##name; + +#define CHILD_PTR_PROP_WRAP(type, name) \ + Q_PROPERTY(type* name READ get##name WRITE set##name) \ + type* get##name() const { return m_##name; } \ + void set##name(type* val) { \ + /* if (m_##name) children().removeAll((QObject*)m_##name); */ \ + val->setParent(this); \ + m_##name = val; \ + } \ + type* m_##name = nullptr; + + +class MyObjectTest : public QObject +{ + Q_OBJECT + Q_ENUMS(AnotherEnum) + Q_ENUMS(TestEnum) + Q_FLAGS(TestFlags) +public: + enum TestFlags { FlagValue1 = 1, AnotherFlagValue = 2, FlagEtc = 4, FlagBlah = 8 }; + enum TestEnum { EnumValue1, AnotherValue, Etc, Blah }; + enum AnotherEnum { AEnumValue1, AnAnotherValue, Etc2 }; + + explicit MyObjectTest() : QObject() { + m_An_Int_Value = 10; + m_A_Double = 11.0; + //m_An_Enum = EnumValue1; + //memset(this, 0, sizeof(MyObjectTest)); + } + ~MyObjectTest() { + } + + PROP_WRAP(int, An_Int_Value) + PROP_WRAP(bool, A_Bool) + PROP_WRAP(double, A_Double) + PROP_WRAP(TestEnum,An_Enum1) + PROP_WRAP(TestEnum,An_Enum2) + PROP_WRAP(QFlags,A_Flags) + PROP_WRAP(QString, A_String) + PROP_WRAP(QDate, A_Date) + PROP_WRAP(QTime, A_Time) + PROP_WRAP(QDateTime, A_Date_and_Time) + PROP_WRAP(QKeySequence, A_Key_Sequence) + PROP_WRAP(QChar, A_Char) + PROP_WRAP(QLocale, A_Locale) + PROP_WRAP(QPoint, A_Point) + PROP_WRAP(QPointF, A_PointF) + PROP_WRAP(QSize, A_Size) + PROP_WRAP(QSizeF, A_SizeF) + PROP_WRAP(QRect, A_Rect) + PROP_WRAP(QRectF, A_RectF) + //PROP_WRAP(QSizePolicy, A_SizePolicy) + //PROP_WRAP(QFont, A_Font) + PROP_WRAP(QColor, A_Color) + //PROP_WRAP(QCursor, A_Cursor) + // flags +}; + + + +class Template : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) + PROP_WRAP(QColor, Color) +}; + + +class Output : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + PROP_WRAP(QString, Title) + PROP_WRAP(QString, Filename) + PROP_WRAP(FileTypes, FileType) +}; + + +class Input : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) +}; + + +class Project : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + //PROP_WRAP(QString, Name) + PROP_WRAP(QString, Author) + //PROP_WRAP(Template*, Template) + //PROP_WRAP(QList, Inputs) + //PROP_WRAP(Output*, Output) + + //CHILD_PTR_PROP_WRAP(Output, Output) + //CHILD_PTR_PROP_WRAP(Template, Template) + + PROP_WRAP(QString, Title) + PROP_WRAP(QString, OutputFilename) + PROP_WRAP(FileTypes, OutputFileType) + + PROP_WRAP(QString, Template) + PROP_WRAP(QColor, Color) + + void AddInput(Input* in) { in->setParent(this); } +}; + + +class Solution : public QObject +{ + Q_OBJECT +public: + //PROP_WRAP(QList, Projects) + void AddProject(Project* proj) { proj->setParent(this); } +}; + + +#endif // OBJECTS_H diff --git a/QtProject/MakePDF.pro b/QtProject/MakePDF.pro index f4e410c..4026759 100644 --- a/QtProject/MakePDF.pro +++ b/QtProject/MakePDF.pro @@ -1,21 +1,24 @@ -QT += core gui widgets +# QT += webkitwidgets network widgets +CONFIG += qt +QT += core gui widgets webkitwidgets +#QT += svg CONFIG -= flat TARGET = MakePDF DEFINES += \ - GUI_APP=1 + GUI_APP=1 RESOURCES += \ - ../Resources/resources.qrc + ../Resources/resources.qrc FORMS += \ - ../Resources/forms/About.ui \ - ../Resources/forms/NewProjectWizard.ui \ - ../Resources/forms/ExtensibleObjectModelUI.ui \ - ../Resources/forms/SendBugReport.ui \ + ../Resources/forms/About.ui \ + ../Resources/forms/NewProjectWizard.ui \ + ../Resources/forms/ExtensibleObjectModelUI.ui \ + ../Resources/forms/SendBugReport.ui \ ../Resources/forms/Help.ui \ ../Resources/forms/CheckUpdates.ui \ ../Resources/forms/LicenseUpgrade.ui \ @@ -23,136 +26,174 @@ ../Resources/forms/PaletteEditor.ui INCLUDEPATH += \ - ../Framework \ - ../3rdParty/hoedown \ - ../3rdParty/libharu/include \ - ../3rdParty/TinyXML++ + ../Framework \ + ../3rdParty/hoedown \ + ../3rdParty/libharu/include \ + ../3rdParty/TinyXML++ \ + ../3rdParty/qtpropertybrowser/src HEADERS += \ - ../Framework/EventLog.h \ - ../Framework/Expected.h \ - ../Framework/Final.h \ - ../Framework/Finally.h \ - ../Framework/GenericTable.h \ - ../Framework/GenericTableUI.h \ - ../Framework/NonCopyable.h \ - ../Framework/Utilities.h \ + ../Framework/EventLog.h \ + ../Framework/Expected.h \ + ../Framework/Final.h \ + ../Framework/Finally.h \ + ../Framework/GenericTable.h \ + ../Framework/GenericTableUI.h \ + ../Framework/NonCopyable.h \ + ../Framework/Utilities.h \ + ../Framework/SystemInfomation.h \ + ../Framework/Array.h \ + ../Framework/Macros.h \ + ../Framework/ObjectTreeModel.h \ + ../Version.h \ + ../Util.h \ ../ui.h \ + ../MdiChild.h \ ../MdiWindow.h \ ../ColorPicker.h \ - ../Version.h + ../DocConvert.h \ + ../Objects.h \ + ../ObjectVisitor.h HEADERS += \ - ../DocOutput.h \ - ../DocProject.h \ - ../DocStyle.h \ - ../DocTemplate.h \ - ../DocVisitor.h \ - ../DocSVG.h + ../DocOutput.h \ + ../DocProject.h \ + ../DocStyle.h \ + ../DocTemplate.h \ + ../DocVisitor.h \ + ../DocSVG.h SOURCES += \ - ../Framework/Tests.cpp \ - ../Framework/Utilities.cpp \ - ../Framework/EventLog.cpp \ + ../Framework/Tests.cpp \ + ../Framework/Utilities.cpp \ + ../Framework/EventLog.cpp \ + ../MdiChild.cpp \ ../MdiWindow.cpp \ ../ColorPicker.cpp \ - ../Version.cpp + ../Version.cpp \ + ../Framework/SystemInfomation.cpp \ + ../DocConvert.cpp \ + ../Framework/ObjectTreeModel.cpp SOURCES += \ - ../DocOutput.cpp \ - ../DocProject.cpp \ - ../DocStyle.cpp \ - ../DocTemplate.cpp \ - ../DocVisitor.cpp \ - ../DocSVG.cpp \ - ../main.cpp + ../DocOutput.cpp \ + ../DocProject.cpp \ + ../DocStyle.cpp \ + ../DocTemplate.cpp \ + ../DocVisitor.cpp \ + ../DocSVG.cpp \ + ../main.cpp SOURCES += \ - ../3rdParty/hoedown/autolink.c \ - ../3rdParty/hoedown/buffer.c \ - ../3rdParty/hoedown/document.c \ - ../3rdParty/hoedown/escape.c \ - ../3rdParty/hoedown/html.c \ - ../3rdParty/hoedown/html_blocks.c \ - ../3rdParty/hoedown/stack.c + ../3rdParty/hoedown/autolink.c \ + ../3rdParty/hoedown/buffer.c \ + ../3rdParty/hoedown/document.c \ + ../3rdParty/hoedown/escape.c \ + ../3rdParty/hoedown/html.c \ + ../3rdParty/hoedown/html_blocks.c \ + ../3rdParty/hoedown/stack.c SOURCES += \ - ../3rdParty/libharu/src/hpdf_3dmeasure.c \ - ../3rdParty/libharu/src/hpdf_annotation.c \ - ../3rdParty/libharu/src/hpdf_array.c \ - ../3rdParty/libharu/src/hpdf_binary.c \ - ../3rdParty/libharu/src/hpdf_boolean.c \ - ../3rdParty/libharu/src/hpdf_catalog.c \ - ../3rdParty/libharu/src/hpdf_destination.c \ - ../3rdParty/libharu/src/hpdf_dict.c \ - ../3rdParty/libharu/src/hpdf_doc.c \ - ../3rdParty/libharu/src/hpdf_doc_png.c \ - ../3rdParty/libharu/src/hpdf_encoder.c \ - ../3rdParty/libharu/src/hpdf_encoder_utf.c \ - ../3rdParty/libharu/src/hpdf_encrypt.c \ - ../3rdParty/libharu/src/hpdf_encryptdict.c \ - ../3rdParty/libharu/src/hpdf_error.c \ - ../3rdParty/libharu/src/hpdf_exdata.c \ - ../3rdParty/libharu/src/hpdf_ext_gstate.c \ - ../3rdParty/libharu/src/hpdf_font.c \ - ../3rdParty/libharu/src/hpdf_fontdef.c \ - ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ - ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ - ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ - ../3rdParty/libharu/src/hpdf_font_cid.c \ - ../3rdParty/libharu/src/hpdf_font_tt.c \ - ../3rdParty/libharu/src/hpdf_font_type1.c \ - ../3rdParty/libharu/src/hpdf_gstate.c \ - ../3rdParty/libharu/src/hpdf_image.c \ - ../3rdParty/libharu/src/hpdf_image_png.c \ - ../3rdParty/libharu/src/hpdf_info.c \ - ../3rdParty/libharu/src/hpdf_list.c \ - ../3rdParty/libharu/src/hpdf_mmgr.c \ - ../3rdParty/libharu/src/hpdf_name.c \ - ../3rdParty/libharu/src/hpdf_namedict.c \ - ../3rdParty/libharu/src/hpdf_null.c \ - ../3rdParty/libharu/src/hpdf_number.c \ - ../3rdParty/libharu/src/hpdf_objects.c \ - ../3rdParty/libharu/src/hpdf_outline.c \ - ../3rdParty/libharu/src/hpdf_pages.c \ - ../3rdParty/libharu/src/hpdf_page_label.c \ - ../3rdParty/libharu/src/hpdf_page_operator.c \ - ../3rdParty/libharu/src/hpdf_pdfa.c \ - ../3rdParty/libharu/src/hpdf_real.c \ - ../3rdParty/libharu/src/hpdf_streams.c \ - ../3rdParty/libharu/src/hpdf_string.c \ - ../3rdParty/libharu/src/hpdf_u3d.c \ - ../3rdParty/libharu/src/hpdf_utils.c \ - ../3rdParty/libharu/src/hpdf_xref.c + ../3rdParty/libharu/src/hpdf_3dmeasure.c \ + ../3rdParty/libharu/src/hpdf_annotation.c \ + ../3rdParty/libharu/src/hpdf_array.c \ + ../3rdParty/libharu/src/hpdf_binary.c \ + ../3rdParty/libharu/src/hpdf_boolean.c \ + ../3rdParty/libharu/src/hpdf_catalog.c \ + ../3rdParty/libharu/src/hpdf_destination.c \ + ../3rdParty/libharu/src/hpdf_dict.c \ + ../3rdParty/libharu/src/hpdf_doc.c \ + ../3rdParty/libharu/src/hpdf_doc_png.c \ + ../3rdParty/libharu/src/hpdf_encoder.c \ + ../3rdParty/libharu/src/hpdf_encoder_utf.c \ + ../3rdParty/libharu/src/hpdf_encrypt.c \ + ../3rdParty/libharu/src/hpdf_encryptdict.c \ + ../3rdParty/libharu/src/hpdf_error.c \ + ../3rdParty/libharu/src/hpdf_exdata.c \ + ../3rdParty/libharu/src/hpdf_ext_gstate.c \ + ../3rdParty/libharu/src/hpdf_font.c \ + ../3rdParty/libharu/src/hpdf_fontdef.c \ + ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ + ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ + ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ + ../3rdParty/libharu/src/hpdf_font_cid.c \ + ../3rdParty/libharu/src/hpdf_font_tt.c \ + ../3rdParty/libharu/src/hpdf_font_type1.c \ + ../3rdParty/libharu/src/hpdf_gstate.c \ + ../3rdParty/libharu/src/hpdf_image.c \ + ../3rdParty/libharu/src/hpdf_image_png.c \ + ../3rdParty/libharu/src/hpdf_info.c \ + ../3rdParty/libharu/src/hpdf_list.c \ + ../3rdParty/libharu/src/hpdf_mmgr.c \ + ../3rdParty/libharu/src/hpdf_name.c \ + ../3rdParty/libharu/src/hpdf_namedict.c \ + ../3rdParty/libharu/src/hpdf_null.c \ + ../3rdParty/libharu/src/hpdf_number.c \ + ../3rdParty/libharu/src/hpdf_objects.c \ + ../3rdParty/libharu/src/hpdf_outline.c \ + ../3rdParty/libharu/src/hpdf_pages.c \ + ../3rdParty/libharu/src/hpdf_page_label.c \ + ../3rdParty/libharu/src/hpdf_page_operator.c \ + ../3rdParty/libharu/src/hpdf_pdfa.c \ + ../3rdParty/libharu/src/hpdf_real.c \ + ../3rdParty/libharu/src/hpdf_streams.c \ + ../3rdParty/libharu/src/hpdf_string.c \ + ../3rdParty/libharu/src/hpdf_u3d.c \ + ../3rdParty/libharu/src/hpdf_utils.c \ + ../3rdParty/libharu/src/hpdf_xref.c SOURCES += \ - ../3rdParty/TinyXML++/ticpp.cpp \ - ../3rdParty/TinyXML++/tinystr.cpp \ - ../3rdParty/TinyXML++/tinyxml.cpp \ - ../3rdParty/TinyXML++/tinyxmlerror.cpp \ - ../3rdParty/TinyXML++/tinyxmlparser.cpp + ../3rdParty/TinyXML++/ticpp.cpp \ + ../3rdParty/TinyXML++/tinystr.cpp \ + ../3rdParty/TinyXML++/tinyxml.cpp \ + ../3rdParty/TinyXML++/tinyxmlerror.cpp \ + ../3rdParty/TinyXML++/tinyxmlparser.cpp + + +SOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.cpp \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.cpp \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.cpp \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils.cpp + +HEADERS += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.h \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.h \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.h \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils_p.h + +RESOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.qrc # As a note to what was removed REMOVED_SOURCES = \ - ../3rdParty/hoedown/html_smartypants.c \ - ../3rdParty/hoedown/version.c \ - ../3rdParty/libharu/src/hpdf_image_ccitt.c + ../3rdParty/hoedown/html_smartypants.c \ + ../3rdParty/hoedown/version.c \ + ../3rdParty/libharu/src/hpdf_image_ccitt.c # Linux specific settings unix { - QMAKE_CXXFLAGS += --std=gnu++11 - # QMAKE_CXXFLAGS -= -Wall - QMAKE_CXXFLAGS_WARN_ON=-w - QMAKE_CFLAGS_WARN_ON=-w - LIBS += -lpng -lz + QMAKE_CXXFLAGS += --std=gnu++11 + # QMAKE_CXXFLAGS -= -Wall + QMAKE_CXXFLAGS_WARN_ON=-w + QMAKE_CFLAGS_WARN_ON=-w + LIBS += -lpng -lz } @@ -160,77 +201,82 @@ # Windows specific. Note we compile in libpng and zlib statically on Windows win32 { - # Supress annoying warnings - QMAKE_CXXFLAGS += /wd"4996;4100" - QMAKE_CXXFLAGS_WARN_ON -= -w34100 + # Supress annoying warnings + QMAKE_CXXFLAGS += /wd"4996;4100" + QMAKE_CXXFLAGS_WARN_ON -= -w34100 - # Release mode debugging - QMAKE_CXXFLAGS += /Zi - QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF + # Release mode debugging + QMAKE_CXXFLAGS += /Zi + QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF - # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything - Project.target = $${TARGET}.vcxproj - Project.output = $${TARGET}.vcxproj - Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 - Project.depends = '"$${_PRO_FILE_}"' - Project.input = _PRO_FILE_ - QMAKE_EXTRA_COMPILERS += Project + # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything + Project.target = $${TARGET}.vcxproj + Project.output = $${TARGET}.vcxproj + Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 + Project.depends = '"$${_PRO_FILE_}"' + Project.input = _PRO_FILE_ + QMAKE_EXTRA_COMPILERS += Project - # This makes the documentation - MARKDOWN_FILES = \ - test.md \ - test2.md + # This makes the documentation + MARKDOWN_FILES = \ + test.md \ + test2.md - Documentation.target = test.pdf - Documentation.output = test.pdf - Documentation.commands = echo ' ' > test.pdf - Documentation.depends = '"$${MARKDOWN_FILES}"' - Documentation.input = MARKDOWN_FILES - QMAKE_EXTRA_COMPILERS += Documentation + Documentation.target = test.pdf + Documentation.output = test.pdf + Documentation.commands = echo ' ' > test.pdf + Documentation.depends = '"$${MARKDOWN_FILES}"' + Documentation.input = MARKDOWN_FILES + QMAKE_EXTRA_COMPILERS += Documentation - INCLUDEPATH += \ - ../3rdParty/libpng \ - ../3rdParty/zlib + INCLUDEPATH += \ + ../3rdParty/libpng \ + ../3rdParty/zlib - SOURCES += \ - ../3rdParty/libpng/png.c \ - ../3rdParty/libpng/pngerror.c \ - ../3rdParty/libpng/pngget.c \ - ../3rdParty/libpng/pngmem.c \ - ../3rdParty/libpng/pngpread.c \ - ../3rdParty/libpng/pngread.c \ - ../3rdParty/libpng/pngrio.c \ - ../3rdParty/libpng/pngrtran.c \ - ../3rdParty/libpng/pngrutil.c \ - ../3rdParty/libpng/pngset.c \ - ../3rdParty/libpng/pngtrans.c \ - ../3rdParty/libpng/pngwio.c \ - ../3rdParty/libpng/pngwrite.c \ - ../3rdParty/libpng/pngwtran.c \ - ../3rdParty/libpng/pngwutil.c + SOURCES += \ + ../3rdParty/libpng/png.c \ + ../3rdParty/libpng/pngerror.c \ + ../3rdParty/libpng/pngget.c \ + ../3rdParty/libpng/pngmem.c \ + ../3rdParty/libpng/pngpread.c \ + ../3rdParty/libpng/pngread.c \ + ../3rdParty/libpng/pngrio.c \ + ../3rdParty/libpng/pngrtran.c \ + ../3rdParty/libpng/pngrutil.c \ + ../3rdParty/libpng/pngset.c \ + ../3rdParty/libpng/pngtrans.c \ + ../3rdParty/libpng/pngwio.c \ + ../3rdParty/libpng/pngwrite.c \ + ../3rdParty/libpng/pngwtran.c \ + ../3rdParty/libpng/pngwutil.c - SOURCES += \ - ../3rdParty/zlib/inftrees.c \ - ../3rdParty/zlib/trees.c \ - ../3rdParty/zlib/uncompr.c \ - ../3rdParty/zlib/zutil.c \ - ../3rdParty/zlib/adler32.c \ - ../3rdParty/zlib/compress.c \ - ../3rdParty/zlib/crc32.c \ - ../3rdParty/zlib/deflate.c \ - ../3rdParty/zlib/gzclose.c \ - ../3rdParty/zlib/gzlib.c \ - ../3rdParty/zlib/gzread.c \ - ../3rdParty/zlib/gzwrite.c \ - ../3rdParty/zlib/infback.c \ - ../3rdParty/zlib/inffast.c \ - ../3rdParty/zlib/inflate.c + SOURCES += \ + ../3rdParty/zlib/inftrees.c \ + ../3rdParty/zlib/trees.c \ + ../3rdParty/zlib/uncompr.c \ + ../3rdParty/zlib/zutil.c \ + ../3rdParty/zlib/adler32.c \ + ../3rdParty/zlib/compress.c \ + ../3rdParty/zlib/crc32.c \ + ../3rdParty/zlib/deflate.c \ + ../3rdParty/zlib/gzclose.c \ + ../3rdParty/zlib/gzlib.c \ + ../3rdParty/zlib/gzread.c \ + ../3rdParty/zlib/gzwrite.c \ + ../3rdParty/zlib/infback.c \ + ../3rdParty/zlib/inffast.c \ + ../3rdParty/zlib/inflate.c } +OTHER_FILES += \ + ../Website/about.html \ + ../Website/register.html \ + ../Website/support.html + diff --git a/Resources/forms/About.ui b/Resources/forms/About.ui index bd6bdf3..3265d89 100644 --- a/Resources/forms/About.ui +++ b/Resources/forms/About.ui @@ -152,7 +152,7 @@ QFrame::Plain - + 20 @@ -165,7 +165,7 @@ <html><head/><body><p><a href="http://url.to.application/"><span style=" text-decoration: underline; color:#0000ff;">http://url.to.application/</span></a></p></body></html> - + 360 @@ -175,16 +175,16 @@ - - - - :/images/images/logo.svg + AppIcon true + + Qt::AlignCenter + - + 20 @@ -193,11 +193,18 @@ 31 + + + 20 + 75 + true + + - <html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Wicked Docs</span></p></body></html> + AppName - + 20 @@ -207,7 +214,7 @@ - <html><head/><body><p>Version 1.0.0.0001</p></body></html> + AppVer @@ -337,7 +344,7 @@
- <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://blah/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements / LicensesEULA</span></a></p></body></html> + <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br/><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://sdfdsf/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements &amp; Licenses</span></a>&nbsp;&nbsp;<a href="http://sfsdf/"><span style=" text-decoration: underline; color:#0000ff;">EULA</span></a></p></body></html>
label_5 @@ -346,9 +353,7 @@
- - - + okayButton diff --git a/Resources/forms/ExtensibleObjectModelUI.ui b/Resources/forms/ExtensibleObjectModelUI.ui index 4a794d4..c3fcbc4 100644 --- a/Resources/forms/ExtensibleObjectModelUI.ui +++ b/Resources/forms/ExtensibleObjectModelUI.ui @@ -250,7 +250,7 @@ 0 - + @@ -347,7 +347,7 @@ - + @@ -478,6 +478,16 @@ + + + + + 0 + 200 + + + + @@ -921,6 +931,14 @@ + + + QWebView + QWidget +
QWebView
+ 1 +
+
diff --git a/Resources/forms/LicenseUpgrade.ui b/Resources/forms/LicenseUpgrade.ui index 69b55ad..4ce2ac1 100644 --- a/Resources/forms/LicenseUpgrade.ui +++ b/Resources/forms/LicenseUpgrade.ui @@ -42,7 +42,7 @@ Upgrade license - + 290 diff --git a/Resources/forms/SendBugReport.ui b/Resources/forms/SendBugReport.ui index 1a7d910..70e177e 100644 --- a/Resources/forms/SendBugReport.ui +++ b/Resources/forms/SendBugReport.ui @@ -6,8 +6,8 @@ 0 0 - 489 - 420 + 525 + 421 @@ -17,49 +17,49 @@ - Software information + System information 15 - + - Version: + Application: - + unknown - + OS Platform: - + unknown - + - Date/Time: + Version: - + unknown @@ -79,74 +79,83 @@ - - - - - - - System information - - - - 15 - - - - - Include system info in report - - - true - - - - - - - RAM: - - - - - - - unknown - - - - + CPU: - + unknown - + Resolution: - + unknown + + + + RAM: + + + + + + + unknown + + + + + + + Date/Time: + + + + + + + unknown + + + + + + Short description: + + + + + + + + + + Short text description of problem + + + + Bug description: @@ -154,14 +163,18 @@ - + + + Detailed description of the issue, such as the type of issue, (eg an improvement, bug, crash, usability problem) and the steps needed to reproduce the problem. Add any notes that you think may be relevant. + + - Email address: + Email address (optional): @@ -238,7 +251,6 @@ desc email - sendSysInfo diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/MdiWindow.h b/MdiWindow.h index 76d7f1b..35ef9c3 100644 --- a/MdiWindow.h +++ b/MdiWindow.h @@ -4,78 +4,19 @@ #include #include +#include "Objects.h" +#include "MdiChild.h" -class MdiChild; class QAction; class QMenu; class QMdiArea; class QMdiSubWindow; class QSignalMapper; +class QTcpServer; class Ui_MainWindow; -class MdiChild : public QTextEdit -{ - Q_OBJECT -public: - MdiChild(); - ~MdiChild(); - - void newFile(); - bool loadFile(const QString &fileName); - bool save(); - bool saveAs(); - bool saveFile(const QString &fileName); - QString userFriendlyCurrentFile(); - QString currentFile() { return curFile; } - - void markdownSelection(const char* preText, const char* postText); - - void bold(); - void italic(); - void quote(); - void code(); - void heading1(); - void heading2(); - void heading3(); - void heading4(); - void hyperlink(); - void image(); - void unorderedList(); - void orderedList(); - void horizontalRule(); - void timestamp(); - void pageNumber(); - void pageCount(); - void del(); - void undo(); - void redo(); - void find(); - void findNext(); - void findPrevious(); - void goToLine(); - -signals: - void closing(); - void documentContentsChanged(); - -private slots: - void documentWasModified(); - -protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - -private: - bool maybeSave(); - void setCurrentFile(const QString &fileName); - QString strippedName(const QString &fullFileName); - - QString curFile; - bool isUntitled; -}; - - /* class MdiOptions { @@ -109,8 +50,12 @@ void save(); void saveAs(); + void handleRequest(); void updatePreview(); + void setWebPreviewURL(); + void refreshWebPreview(); + // Edit menu actions #ifndef QT_NO_CLIPBOARD void cut(); @@ -159,12 +104,26 @@ void switchLayoutDirection(); void setActiveSubWindow(QWidget *window); + void changeRootObject(const QModelIndex &index); + void changePropertiesObject(const QModelIndex &index); + + // Dialog events + void upgradeClicked(); + private: + void changeProjectTree(QObject *rootObject); + void updateObjectTree(QObject *rootObject); + void updatePropertiesView(QObject *object); + void setupServer(); void readSettings(); + void readLicense(); void writeSettings(); MdiChild *activeMdiChild(); QMdiSubWindow *findMdiChild(const QString &fileName); + //Solution solution; + QByteArray pdfContents; + QTcpServer *server; QMdiArea *mdiArea; QSignalMapper *windowMapper; Ui_MainWindow *appWindow; diff --git a/ObjectVisitor.h b/ObjectVisitor.h new file mode 100644 index 0000000..12cf25f --- /dev/null +++ b/ObjectVisitor.h @@ -0,0 +1,59 @@ +#ifndef OBJECTVISITOR_H +#define OBJECTVISITOR_H + + +#include +#include +#include +#include + + +class Visitor +{ +public: + Visitor() {} + virtual ~Visitor() {} + + virtual void enterObject(const char* className, const char* objectName) = 0; + virtual void leaveObject(const char* className, const char* objectName) = 0; + + // Reads or writes a property value + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) = 0; + + // By default, it is a reader, but implementing this enables a visitor that sets values + virtual bool isWriting() { return false; } +}; + + +void Visit(Visitor& visitor, QObject* object) +{ + std::string objectName = object->objectName().toLocal8Bit().data(); + if (objectName.size() <= 1) { + objectName = std::to_string((uint64_t)(void*)object); + } + visitor.enterObject(object->metaObject()->className(), objectName.c_str()); + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + if (visitor.isWriting()) { + QVariant value; + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + property.write(object, value); + + } else { + QVariant value = property.read(object); + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + } + } + for (int i = 0; i < object->children().count(); i++) + { + Visit(visitor, object->children()[i]); + } + visitor.leaveObject(object->metaObject()->className(), objectName.c_str()); +} + + +#endif // OBJECTVISITOR_H diff --git a/Objects.h b/Objects.h new file mode 100644 index 0000000..90e7bb1 --- /dev/null +++ b/Objects.h @@ -0,0 +1,167 @@ +#ifndef OBJECTS_H +#define OBJECTS_H + + +#include +#include +#include +#include +#include +#include +#include + + +class EnumEditor : public QWidget +{ + Q_OBJECT +public slots: + void ListSelectionChanged(); + void ComboSelectionChanged(); +public: + EnumEditor(QMetaEnum metaEnum); +private: + QListWidget* lw; + QComboBox* cb; + QSpinBox* sb; + QLabel* str; + QMetaEnum m_metaEnum; +}; + + +// Property Manager Supported types: +// int, bool, double, enums, flags +// QString, QDate, QTime, QDateTime, QKeySequence +// QChar, QLocale, QPoint, QPointF, QSize, QSizeF +// QRect, QRectF, QSizePolicy, QFont, QColor, QCursor + + +#define PROP_WRAP(type, name) \ + Q_PROPERTY(type name READ get##name WRITE set##name) \ + type get##name() const { return m_##name; } \ + void set##name(type val) { m_##name = val; } \ + type m_##name; + +#define CHILD_PTR_PROP_WRAP(type, name) \ + Q_PROPERTY(type* name READ get##name WRITE set##name) \ + type* get##name() const { return m_##name; } \ + void set##name(type* val) { \ + /* if (m_##name) children().removeAll((QObject*)m_##name); */ \ + val->setParent(this); \ + m_##name = val; \ + } \ + type* m_##name = nullptr; + + +class MyObjectTest : public QObject +{ + Q_OBJECT + Q_ENUMS(AnotherEnum) + Q_ENUMS(TestEnum) + Q_FLAGS(TestFlags) +public: + enum TestFlags { FlagValue1 = 1, AnotherFlagValue = 2, FlagEtc = 4, FlagBlah = 8 }; + enum TestEnum { EnumValue1, AnotherValue, Etc, Blah }; + enum AnotherEnum { AEnumValue1, AnAnotherValue, Etc2 }; + + explicit MyObjectTest() : QObject() { + m_An_Int_Value = 10; + m_A_Double = 11.0; + //m_An_Enum = EnumValue1; + //memset(this, 0, sizeof(MyObjectTest)); + } + ~MyObjectTest() { + } + + PROP_WRAP(int, An_Int_Value) + PROP_WRAP(bool, A_Bool) + PROP_WRAP(double, A_Double) + PROP_WRAP(TestEnum,An_Enum1) + PROP_WRAP(TestEnum,An_Enum2) + PROP_WRAP(QFlags,A_Flags) + PROP_WRAP(QString, A_String) + PROP_WRAP(QDate, A_Date) + PROP_WRAP(QTime, A_Time) + PROP_WRAP(QDateTime, A_Date_and_Time) + PROP_WRAP(QKeySequence, A_Key_Sequence) + PROP_WRAP(QChar, A_Char) + PROP_WRAP(QLocale, A_Locale) + PROP_WRAP(QPoint, A_Point) + PROP_WRAP(QPointF, A_PointF) + PROP_WRAP(QSize, A_Size) + PROP_WRAP(QSizeF, A_SizeF) + PROP_WRAP(QRect, A_Rect) + PROP_WRAP(QRectF, A_RectF) + //PROP_WRAP(QSizePolicy, A_SizePolicy) + //PROP_WRAP(QFont, A_Font) + PROP_WRAP(QColor, A_Color) + //PROP_WRAP(QCursor, A_Cursor) + // flags +}; + + + +class Template : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) + PROP_WRAP(QColor, Color) +}; + + +class Output : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + PROP_WRAP(QString, Title) + PROP_WRAP(QString, Filename) + PROP_WRAP(FileTypes, FileType) +}; + + +class Input : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) +}; + + +class Project : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + //PROP_WRAP(QString, Name) + PROP_WRAP(QString, Author) + //PROP_WRAP(Template*, Template) + //PROP_WRAP(QList, Inputs) + //PROP_WRAP(Output*, Output) + + //CHILD_PTR_PROP_WRAP(Output, Output) + //CHILD_PTR_PROP_WRAP(Template, Template) + + PROP_WRAP(QString, Title) + PROP_WRAP(QString, OutputFilename) + PROP_WRAP(FileTypes, OutputFileType) + + PROP_WRAP(QString, Template) + PROP_WRAP(QColor, Color) + + void AddInput(Input* in) { in->setParent(this); } +}; + + +class Solution : public QObject +{ + Q_OBJECT +public: + //PROP_WRAP(QList, Projects) + void AddProject(Project* proj) { proj->setParent(this); } +}; + + +#endif // OBJECTS_H diff --git a/QtProject/MakePDF.pro b/QtProject/MakePDF.pro index f4e410c..4026759 100644 --- a/QtProject/MakePDF.pro +++ b/QtProject/MakePDF.pro @@ -1,21 +1,24 @@ -QT += core gui widgets +# QT += webkitwidgets network widgets +CONFIG += qt +QT += core gui widgets webkitwidgets +#QT += svg CONFIG -= flat TARGET = MakePDF DEFINES += \ - GUI_APP=1 + GUI_APP=1 RESOURCES += \ - ../Resources/resources.qrc + ../Resources/resources.qrc FORMS += \ - ../Resources/forms/About.ui \ - ../Resources/forms/NewProjectWizard.ui \ - ../Resources/forms/ExtensibleObjectModelUI.ui \ - ../Resources/forms/SendBugReport.ui \ + ../Resources/forms/About.ui \ + ../Resources/forms/NewProjectWizard.ui \ + ../Resources/forms/ExtensibleObjectModelUI.ui \ + ../Resources/forms/SendBugReport.ui \ ../Resources/forms/Help.ui \ ../Resources/forms/CheckUpdates.ui \ ../Resources/forms/LicenseUpgrade.ui \ @@ -23,136 +26,174 @@ ../Resources/forms/PaletteEditor.ui INCLUDEPATH += \ - ../Framework \ - ../3rdParty/hoedown \ - ../3rdParty/libharu/include \ - ../3rdParty/TinyXML++ + ../Framework \ + ../3rdParty/hoedown \ + ../3rdParty/libharu/include \ + ../3rdParty/TinyXML++ \ + ../3rdParty/qtpropertybrowser/src HEADERS += \ - ../Framework/EventLog.h \ - ../Framework/Expected.h \ - ../Framework/Final.h \ - ../Framework/Finally.h \ - ../Framework/GenericTable.h \ - ../Framework/GenericTableUI.h \ - ../Framework/NonCopyable.h \ - ../Framework/Utilities.h \ + ../Framework/EventLog.h \ + ../Framework/Expected.h \ + ../Framework/Final.h \ + ../Framework/Finally.h \ + ../Framework/GenericTable.h \ + ../Framework/GenericTableUI.h \ + ../Framework/NonCopyable.h \ + ../Framework/Utilities.h \ + ../Framework/SystemInfomation.h \ + ../Framework/Array.h \ + ../Framework/Macros.h \ + ../Framework/ObjectTreeModel.h \ + ../Version.h \ + ../Util.h \ ../ui.h \ + ../MdiChild.h \ ../MdiWindow.h \ ../ColorPicker.h \ - ../Version.h + ../DocConvert.h \ + ../Objects.h \ + ../ObjectVisitor.h HEADERS += \ - ../DocOutput.h \ - ../DocProject.h \ - ../DocStyle.h \ - ../DocTemplate.h \ - ../DocVisitor.h \ - ../DocSVG.h + ../DocOutput.h \ + ../DocProject.h \ + ../DocStyle.h \ + ../DocTemplate.h \ + ../DocVisitor.h \ + ../DocSVG.h SOURCES += \ - ../Framework/Tests.cpp \ - ../Framework/Utilities.cpp \ - ../Framework/EventLog.cpp \ + ../Framework/Tests.cpp \ + ../Framework/Utilities.cpp \ + ../Framework/EventLog.cpp \ + ../MdiChild.cpp \ ../MdiWindow.cpp \ ../ColorPicker.cpp \ - ../Version.cpp + ../Version.cpp \ + ../Framework/SystemInfomation.cpp \ + ../DocConvert.cpp \ + ../Framework/ObjectTreeModel.cpp SOURCES += \ - ../DocOutput.cpp \ - ../DocProject.cpp \ - ../DocStyle.cpp \ - ../DocTemplate.cpp \ - ../DocVisitor.cpp \ - ../DocSVG.cpp \ - ../main.cpp + ../DocOutput.cpp \ + ../DocProject.cpp \ + ../DocStyle.cpp \ + ../DocTemplate.cpp \ + ../DocVisitor.cpp \ + ../DocSVG.cpp \ + ../main.cpp SOURCES += \ - ../3rdParty/hoedown/autolink.c \ - ../3rdParty/hoedown/buffer.c \ - ../3rdParty/hoedown/document.c \ - ../3rdParty/hoedown/escape.c \ - ../3rdParty/hoedown/html.c \ - ../3rdParty/hoedown/html_blocks.c \ - ../3rdParty/hoedown/stack.c + ../3rdParty/hoedown/autolink.c \ + ../3rdParty/hoedown/buffer.c \ + ../3rdParty/hoedown/document.c \ + ../3rdParty/hoedown/escape.c \ + ../3rdParty/hoedown/html.c \ + ../3rdParty/hoedown/html_blocks.c \ + ../3rdParty/hoedown/stack.c SOURCES += \ - ../3rdParty/libharu/src/hpdf_3dmeasure.c \ - ../3rdParty/libharu/src/hpdf_annotation.c \ - ../3rdParty/libharu/src/hpdf_array.c \ - ../3rdParty/libharu/src/hpdf_binary.c \ - ../3rdParty/libharu/src/hpdf_boolean.c \ - ../3rdParty/libharu/src/hpdf_catalog.c \ - ../3rdParty/libharu/src/hpdf_destination.c \ - ../3rdParty/libharu/src/hpdf_dict.c \ - ../3rdParty/libharu/src/hpdf_doc.c \ - ../3rdParty/libharu/src/hpdf_doc_png.c \ - ../3rdParty/libharu/src/hpdf_encoder.c \ - ../3rdParty/libharu/src/hpdf_encoder_utf.c \ - ../3rdParty/libharu/src/hpdf_encrypt.c \ - ../3rdParty/libharu/src/hpdf_encryptdict.c \ - ../3rdParty/libharu/src/hpdf_error.c \ - ../3rdParty/libharu/src/hpdf_exdata.c \ - ../3rdParty/libharu/src/hpdf_ext_gstate.c \ - ../3rdParty/libharu/src/hpdf_font.c \ - ../3rdParty/libharu/src/hpdf_fontdef.c \ - ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ - ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ - ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ - ../3rdParty/libharu/src/hpdf_font_cid.c \ - ../3rdParty/libharu/src/hpdf_font_tt.c \ - ../3rdParty/libharu/src/hpdf_font_type1.c \ - ../3rdParty/libharu/src/hpdf_gstate.c \ - ../3rdParty/libharu/src/hpdf_image.c \ - ../3rdParty/libharu/src/hpdf_image_png.c \ - ../3rdParty/libharu/src/hpdf_info.c \ - ../3rdParty/libharu/src/hpdf_list.c \ - ../3rdParty/libharu/src/hpdf_mmgr.c \ - ../3rdParty/libharu/src/hpdf_name.c \ - ../3rdParty/libharu/src/hpdf_namedict.c \ - ../3rdParty/libharu/src/hpdf_null.c \ - ../3rdParty/libharu/src/hpdf_number.c \ - ../3rdParty/libharu/src/hpdf_objects.c \ - ../3rdParty/libharu/src/hpdf_outline.c \ - ../3rdParty/libharu/src/hpdf_pages.c \ - ../3rdParty/libharu/src/hpdf_page_label.c \ - ../3rdParty/libharu/src/hpdf_page_operator.c \ - ../3rdParty/libharu/src/hpdf_pdfa.c \ - ../3rdParty/libharu/src/hpdf_real.c \ - ../3rdParty/libharu/src/hpdf_streams.c \ - ../3rdParty/libharu/src/hpdf_string.c \ - ../3rdParty/libharu/src/hpdf_u3d.c \ - ../3rdParty/libharu/src/hpdf_utils.c \ - ../3rdParty/libharu/src/hpdf_xref.c + ../3rdParty/libharu/src/hpdf_3dmeasure.c \ + ../3rdParty/libharu/src/hpdf_annotation.c \ + ../3rdParty/libharu/src/hpdf_array.c \ + ../3rdParty/libharu/src/hpdf_binary.c \ + ../3rdParty/libharu/src/hpdf_boolean.c \ + ../3rdParty/libharu/src/hpdf_catalog.c \ + ../3rdParty/libharu/src/hpdf_destination.c \ + ../3rdParty/libharu/src/hpdf_dict.c \ + ../3rdParty/libharu/src/hpdf_doc.c \ + ../3rdParty/libharu/src/hpdf_doc_png.c \ + ../3rdParty/libharu/src/hpdf_encoder.c \ + ../3rdParty/libharu/src/hpdf_encoder_utf.c \ + ../3rdParty/libharu/src/hpdf_encrypt.c \ + ../3rdParty/libharu/src/hpdf_encryptdict.c \ + ../3rdParty/libharu/src/hpdf_error.c \ + ../3rdParty/libharu/src/hpdf_exdata.c \ + ../3rdParty/libharu/src/hpdf_ext_gstate.c \ + ../3rdParty/libharu/src/hpdf_font.c \ + ../3rdParty/libharu/src/hpdf_fontdef.c \ + ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ + ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ + ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ + ../3rdParty/libharu/src/hpdf_font_cid.c \ + ../3rdParty/libharu/src/hpdf_font_tt.c \ + ../3rdParty/libharu/src/hpdf_font_type1.c \ + ../3rdParty/libharu/src/hpdf_gstate.c \ + ../3rdParty/libharu/src/hpdf_image.c \ + ../3rdParty/libharu/src/hpdf_image_png.c \ + ../3rdParty/libharu/src/hpdf_info.c \ + ../3rdParty/libharu/src/hpdf_list.c \ + ../3rdParty/libharu/src/hpdf_mmgr.c \ + ../3rdParty/libharu/src/hpdf_name.c \ + ../3rdParty/libharu/src/hpdf_namedict.c \ + ../3rdParty/libharu/src/hpdf_null.c \ + ../3rdParty/libharu/src/hpdf_number.c \ + ../3rdParty/libharu/src/hpdf_objects.c \ + ../3rdParty/libharu/src/hpdf_outline.c \ + ../3rdParty/libharu/src/hpdf_pages.c \ + ../3rdParty/libharu/src/hpdf_page_label.c \ + ../3rdParty/libharu/src/hpdf_page_operator.c \ + ../3rdParty/libharu/src/hpdf_pdfa.c \ + ../3rdParty/libharu/src/hpdf_real.c \ + ../3rdParty/libharu/src/hpdf_streams.c \ + ../3rdParty/libharu/src/hpdf_string.c \ + ../3rdParty/libharu/src/hpdf_u3d.c \ + ../3rdParty/libharu/src/hpdf_utils.c \ + ../3rdParty/libharu/src/hpdf_xref.c SOURCES += \ - ../3rdParty/TinyXML++/ticpp.cpp \ - ../3rdParty/TinyXML++/tinystr.cpp \ - ../3rdParty/TinyXML++/tinyxml.cpp \ - ../3rdParty/TinyXML++/tinyxmlerror.cpp \ - ../3rdParty/TinyXML++/tinyxmlparser.cpp + ../3rdParty/TinyXML++/ticpp.cpp \ + ../3rdParty/TinyXML++/tinystr.cpp \ + ../3rdParty/TinyXML++/tinyxml.cpp \ + ../3rdParty/TinyXML++/tinyxmlerror.cpp \ + ../3rdParty/TinyXML++/tinyxmlparser.cpp + + +SOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.cpp \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.cpp \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.cpp \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils.cpp + +HEADERS += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.h \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.h \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.h \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils_p.h + +RESOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.qrc # As a note to what was removed REMOVED_SOURCES = \ - ../3rdParty/hoedown/html_smartypants.c \ - ../3rdParty/hoedown/version.c \ - ../3rdParty/libharu/src/hpdf_image_ccitt.c + ../3rdParty/hoedown/html_smartypants.c \ + ../3rdParty/hoedown/version.c \ + ../3rdParty/libharu/src/hpdf_image_ccitt.c # Linux specific settings unix { - QMAKE_CXXFLAGS += --std=gnu++11 - # QMAKE_CXXFLAGS -= -Wall - QMAKE_CXXFLAGS_WARN_ON=-w - QMAKE_CFLAGS_WARN_ON=-w - LIBS += -lpng -lz + QMAKE_CXXFLAGS += --std=gnu++11 + # QMAKE_CXXFLAGS -= -Wall + QMAKE_CXXFLAGS_WARN_ON=-w + QMAKE_CFLAGS_WARN_ON=-w + LIBS += -lpng -lz } @@ -160,77 +201,82 @@ # Windows specific. Note we compile in libpng and zlib statically on Windows win32 { - # Supress annoying warnings - QMAKE_CXXFLAGS += /wd"4996;4100" - QMAKE_CXXFLAGS_WARN_ON -= -w34100 + # Supress annoying warnings + QMAKE_CXXFLAGS += /wd"4996;4100" + QMAKE_CXXFLAGS_WARN_ON -= -w34100 - # Release mode debugging - QMAKE_CXXFLAGS += /Zi - QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF + # Release mode debugging + QMAKE_CXXFLAGS += /Zi + QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF - # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything - Project.target = $${TARGET}.vcxproj - Project.output = $${TARGET}.vcxproj - Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 - Project.depends = '"$${_PRO_FILE_}"' - Project.input = _PRO_FILE_ - QMAKE_EXTRA_COMPILERS += Project + # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything + Project.target = $${TARGET}.vcxproj + Project.output = $${TARGET}.vcxproj + Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 + Project.depends = '"$${_PRO_FILE_}"' + Project.input = _PRO_FILE_ + QMAKE_EXTRA_COMPILERS += Project - # This makes the documentation - MARKDOWN_FILES = \ - test.md \ - test2.md + # This makes the documentation + MARKDOWN_FILES = \ + test.md \ + test2.md - Documentation.target = test.pdf - Documentation.output = test.pdf - Documentation.commands = echo ' ' > test.pdf - Documentation.depends = '"$${MARKDOWN_FILES}"' - Documentation.input = MARKDOWN_FILES - QMAKE_EXTRA_COMPILERS += Documentation + Documentation.target = test.pdf + Documentation.output = test.pdf + Documentation.commands = echo ' ' > test.pdf + Documentation.depends = '"$${MARKDOWN_FILES}"' + Documentation.input = MARKDOWN_FILES + QMAKE_EXTRA_COMPILERS += Documentation - INCLUDEPATH += \ - ../3rdParty/libpng \ - ../3rdParty/zlib + INCLUDEPATH += \ + ../3rdParty/libpng \ + ../3rdParty/zlib - SOURCES += \ - ../3rdParty/libpng/png.c \ - ../3rdParty/libpng/pngerror.c \ - ../3rdParty/libpng/pngget.c \ - ../3rdParty/libpng/pngmem.c \ - ../3rdParty/libpng/pngpread.c \ - ../3rdParty/libpng/pngread.c \ - ../3rdParty/libpng/pngrio.c \ - ../3rdParty/libpng/pngrtran.c \ - ../3rdParty/libpng/pngrutil.c \ - ../3rdParty/libpng/pngset.c \ - ../3rdParty/libpng/pngtrans.c \ - ../3rdParty/libpng/pngwio.c \ - ../3rdParty/libpng/pngwrite.c \ - ../3rdParty/libpng/pngwtran.c \ - ../3rdParty/libpng/pngwutil.c + SOURCES += \ + ../3rdParty/libpng/png.c \ + ../3rdParty/libpng/pngerror.c \ + ../3rdParty/libpng/pngget.c \ + ../3rdParty/libpng/pngmem.c \ + ../3rdParty/libpng/pngpread.c \ + ../3rdParty/libpng/pngread.c \ + ../3rdParty/libpng/pngrio.c \ + ../3rdParty/libpng/pngrtran.c \ + ../3rdParty/libpng/pngrutil.c \ + ../3rdParty/libpng/pngset.c \ + ../3rdParty/libpng/pngtrans.c \ + ../3rdParty/libpng/pngwio.c \ + ../3rdParty/libpng/pngwrite.c \ + ../3rdParty/libpng/pngwtran.c \ + ../3rdParty/libpng/pngwutil.c - SOURCES += \ - ../3rdParty/zlib/inftrees.c \ - ../3rdParty/zlib/trees.c \ - ../3rdParty/zlib/uncompr.c \ - ../3rdParty/zlib/zutil.c \ - ../3rdParty/zlib/adler32.c \ - ../3rdParty/zlib/compress.c \ - ../3rdParty/zlib/crc32.c \ - ../3rdParty/zlib/deflate.c \ - ../3rdParty/zlib/gzclose.c \ - ../3rdParty/zlib/gzlib.c \ - ../3rdParty/zlib/gzread.c \ - ../3rdParty/zlib/gzwrite.c \ - ../3rdParty/zlib/infback.c \ - ../3rdParty/zlib/inffast.c \ - ../3rdParty/zlib/inflate.c + SOURCES += \ + ../3rdParty/zlib/inftrees.c \ + ../3rdParty/zlib/trees.c \ + ../3rdParty/zlib/uncompr.c \ + ../3rdParty/zlib/zutil.c \ + ../3rdParty/zlib/adler32.c \ + ../3rdParty/zlib/compress.c \ + ../3rdParty/zlib/crc32.c \ + ../3rdParty/zlib/deflate.c \ + ../3rdParty/zlib/gzclose.c \ + ../3rdParty/zlib/gzlib.c \ + ../3rdParty/zlib/gzread.c \ + ../3rdParty/zlib/gzwrite.c \ + ../3rdParty/zlib/infback.c \ + ../3rdParty/zlib/inffast.c \ + ../3rdParty/zlib/inflate.c } +OTHER_FILES += \ + ../Website/about.html \ + ../Website/register.html \ + ../Website/support.html + diff --git a/Resources/forms/About.ui b/Resources/forms/About.ui index bd6bdf3..3265d89 100644 --- a/Resources/forms/About.ui +++ b/Resources/forms/About.ui @@ -152,7 +152,7 @@ QFrame::Plain - + 20 @@ -165,7 +165,7 @@ <html><head/><body><p><a href="http://url.to.application/"><span style=" text-decoration: underline; color:#0000ff;">http://url.to.application/</span></a></p></body></html> - + 360 @@ -175,16 +175,16 @@ - - - - :/images/images/logo.svg + AppIcon true + + Qt::AlignCenter + - + 20 @@ -193,11 +193,18 @@ 31 + + + 20 + 75 + true + + - <html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Wicked Docs</span></p></body></html> + AppName - + 20 @@ -207,7 +214,7 @@ - <html><head/><body><p>Version 1.0.0.0001</p></body></html> + AppVer @@ -337,7 +344,7 @@ - <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://blah/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements / LicensesEULA</span></a></p></body></html> + <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br/><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://sdfdsf/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements &amp; Licenses</span></a>&nbsp;&nbsp;<a href="http://sfsdf/"><span style=" text-decoration: underline; color:#0000ff;">EULA</span></a></p></body></html> label_5 @@ -346,9 +353,7 @@
- - - + okayButton diff --git a/Resources/forms/ExtensibleObjectModelUI.ui b/Resources/forms/ExtensibleObjectModelUI.ui index 4a794d4..c3fcbc4 100644 --- a/Resources/forms/ExtensibleObjectModelUI.ui +++ b/Resources/forms/ExtensibleObjectModelUI.ui @@ -250,7 +250,7 @@ 0 - + @@ -347,7 +347,7 @@ - + @@ -478,6 +478,16 @@ + + + + + 0 + 200 + + + + @@ -921,6 +931,14 @@ + + + QWebView + QWidget +
QWebView
+ 1 +
+
diff --git a/Resources/forms/LicenseUpgrade.ui b/Resources/forms/LicenseUpgrade.ui index 69b55ad..4ce2ac1 100644 --- a/Resources/forms/LicenseUpgrade.ui +++ b/Resources/forms/LicenseUpgrade.ui @@ -42,7 +42,7 @@ Upgrade license - + 290 diff --git a/Resources/forms/SendBugReport.ui b/Resources/forms/SendBugReport.ui index 1a7d910..70e177e 100644 --- a/Resources/forms/SendBugReport.ui +++ b/Resources/forms/SendBugReport.ui @@ -6,8 +6,8 @@ 0 0 - 489 - 420 + 525 + 421 @@ -17,49 +17,49 @@ - Software information + System information 15 - + - Version: + Application: - + unknown - + OS Platform: - + unknown - + - Date/Time: + Version: - + unknown @@ -79,74 +79,83 @@ - - - - - - - System information - - - - 15 - - - - - Include system info in report - - - true - - - - - - - RAM: - - - - - - - unknown - - - - + CPU: - + unknown - + Resolution: - + unknown + + + + RAM: + + + + + + + unknown + + + + + + + Date/Time: + + + + + + + unknown + + + + + + Short description: + + + + + + + + + + Short text description of problem + + + + Bug description: @@ -154,14 +163,18 @@ - + + + Detailed description of the issue, such as the type of issue, (eg an improvement, bug, crash, usability problem) and the steps needed to reproduce the problem. Add any notes that you think may be relevant. + + - Email address: + Email address (optional): @@ -238,7 +251,6 @@ desc email - sendSysInfo diff --git a/Util.h b/Util.h index 1dfc996..25da56e 100644 --- a/Util.h +++ b/Util.h @@ -12,7 +12,7 @@ { return std::unique_ptr( new T( std::forward(args)... ) ); } -}; +} inline int fopen_s(FILE** a_file, const char* a_fileName, const char* a_mode) { diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/MdiWindow.h b/MdiWindow.h index 76d7f1b..35ef9c3 100644 --- a/MdiWindow.h +++ b/MdiWindow.h @@ -4,78 +4,19 @@ #include #include +#include "Objects.h" +#include "MdiChild.h" -class MdiChild; class QAction; class QMenu; class QMdiArea; class QMdiSubWindow; class QSignalMapper; +class QTcpServer; class Ui_MainWindow; -class MdiChild : public QTextEdit -{ - Q_OBJECT -public: - MdiChild(); - ~MdiChild(); - - void newFile(); - bool loadFile(const QString &fileName); - bool save(); - bool saveAs(); - bool saveFile(const QString &fileName); - QString userFriendlyCurrentFile(); - QString currentFile() { return curFile; } - - void markdownSelection(const char* preText, const char* postText); - - void bold(); - void italic(); - void quote(); - void code(); - void heading1(); - void heading2(); - void heading3(); - void heading4(); - void hyperlink(); - void image(); - void unorderedList(); - void orderedList(); - void horizontalRule(); - void timestamp(); - void pageNumber(); - void pageCount(); - void del(); - void undo(); - void redo(); - void find(); - void findNext(); - void findPrevious(); - void goToLine(); - -signals: - void closing(); - void documentContentsChanged(); - -private slots: - void documentWasModified(); - -protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - -private: - bool maybeSave(); - void setCurrentFile(const QString &fileName); - QString strippedName(const QString &fullFileName); - - QString curFile; - bool isUntitled; -}; - - /* class MdiOptions { @@ -109,8 +50,12 @@ void save(); void saveAs(); + void handleRequest(); void updatePreview(); + void setWebPreviewURL(); + void refreshWebPreview(); + // Edit menu actions #ifndef QT_NO_CLIPBOARD void cut(); @@ -159,12 +104,26 @@ void switchLayoutDirection(); void setActiveSubWindow(QWidget *window); + void changeRootObject(const QModelIndex &index); + void changePropertiesObject(const QModelIndex &index); + + // Dialog events + void upgradeClicked(); + private: + void changeProjectTree(QObject *rootObject); + void updateObjectTree(QObject *rootObject); + void updatePropertiesView(QObject *object); + void setupServer(); void readSettings(); + void readLicense(); void writeSettings(); MdiChild *activeMdiChild(); QMdiSubWindow *findMdiChild(const QString &fileName); + //Solution solution; + QByteArray pdfContents; + QTcpServer *server; QMdiArea *mdiArea; QSignalMapper *windowMapper; Ui_MainWindow *appWindow; diff --git a/ObjectVisitor.h b/ObjectVisitor.h new file mode 100644 index 0000000..12cf25f --- /dev/null +++ b/ObjectVisitor.h @@ -0,0 +1,59 @@ +#ifndef OBJECTVISITOR_H +#define OBJECTVISITOR_H + + +#include +#include +#include +#include + + +class Visitor +{ +public: + Visitor() {} + virtual ~Visitor() {} + + virtual void enterObject(const char* className, const char* objectName) = 0; + virtual void leaveObject(const char* className, const char* objectName) = 0; + + // Reads or writes a property value + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) = 0; + + // By default, it is a reader, but implementing this enables a visitor that sets values + virtual bool isWriting() { return false; } +}; + + +void Visit(Visitor& visitor, QObject* object) +{ + std::string objectName = object->objectName().toLocal8Bit().data(); + if (objectName.size() <= 1) { + objectName = std::to_string((uint64_t)(void*)object); + } + visitor.enterObject(object->metaObject()->className(), objectName.c_str()); + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + if (visitor.isWriting()) { + QVariant value; + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + property.write(object, value); + + } else { + QVariant value = property.read(object); + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + } + } + for (int i = 0; i < object->children().count(); i++) + { + Visit(visitor, object->children()[i]); + } + visitor.leaveObject(object->metaObject()->className(), objectName.c_str()); +} + + +#endif // OBJECTVISITOR_H diff --git a/Objects.h b/Objects.h new file mode 100644 index 0000000..90e7bb1 --- /dev/null +++ b/Objects.h @@ -0,0 +1,167 @@ +#ifndef OBJECTS_H +#define OBJECTS_H + + +#include +#include +#include +#include +#include +#include +#include + + +class EnumEditor : public QWidget +{ + Q_OBJECT +public slots: + void ListSelectionChanged(); + void ComboSelectionChanged(); +public: + EnumEditor(QMetaEnum metaEnum); +private: + QListWidget* lw; + QComboBox* cb; + QSpinBox* sb; + QLabel* str; + QMetaEnum m_metaEnum; +}; + + +// Property Manager Supported types: +// int, bool, double, enums, flags +// QString, QDate, QTime, QDateTime, QKeySequence +// QChar, QLocale, QPoint, QPointF, QSize, QSizeF +// QRect, QRectF, QSizePolicy, QFont, QColor, QCursor + + +#define PROP_WRAP(type, name) \ + Q_PROPERTY(type name READ get##name WRITE set##name) \ + type get##name() const { return m_##name; } \ + void set##name(type val) { m_##name = val; } \ + type m_##name; + +#define CHILD_PTR_PROP_WRAP(type, name) \ + Q_PROPERTY(type* name READ get##name WRITE set##name) \ + type* get##name() const { return m_##name; } \ + void set##name(type* val) { \ + /* if (m_##name) children().removeAll((QObject*)m_##name); */ \ + val->setParent(this); \ + m_##name = val; \ + } \ + type* m_##name = nullptr; + + +class MyObjectTest : public QObject +{ + Q_OBJECT + Q_ENUMS(AnotherEnum) + Q_ENUMS(TestEnum) + Q_FLAGS(TestFlags) +public: + enum TestFlags { FlagValue1 = 1, AnotherFlagValue = 2, FlagEtc = 4, FlagBlah = 8 }; + enum TestEnum { EnumValue1, AnotherValue, Etc, Blah }; + enum AnotherEnum { AEnumValue1, AnAnotherValue, Etc2 }; + + explicit MyObjectTest() : QObject() { + m_An_Int_Value = 10; + m_A_Double = 11.0; + //m_An_Enum = EnumValue1; + //memset(this, 0, sizeof(MyObjectTest)); + } + ~MyObjectTest() { + } + + PROP_WRAP(int, An_Int_Value) + PROP_WRAP(bool, A_Bool) + PROP_WRAP(double, A_Double) + PROP_WRAP(TestEnum,An_Enum1) + PROP_WRAP(TestEnum,An_Enum2) + PROP_WRAP(QFlags,A_Flags) + PROP_WRAP(QString, A_String) + PROP_WRAP(QDate, A_Date) + PROP_WRAP(QTime, A_Time) + PROP_WRAP(QDateTime, A_Date_and_Time) + PROP_WRAP(QKeySequence, A_Key_Sequence) + PROP_WRAP(QChar, A_Char) + PROP_WRAP(QLocale, A_Locale) + PROP_WRAP(QPoint, A_Point) + PROP_WRAP(QPointF, A_PointF) + PROP_WRAP(QSize, A_Size) + PROP_WRAP(QSizeF, A_SizeF) + PROP_WRAP(QRect, A_Rect) + PROP_WRAP(QRectF, A_RectF) + //PROP_WRAP(QSizePolicy, A_SizePolicy) + //PROP_WRAP(QFont, A_Font) + PROP_WRAP(QColor, A_Color) + //PROP_WRAP(QCursor, A_Cursor) + // flags +}; + + + +class Template : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) + PROP_WRAP(QColor, Color) +}; + + +class Output : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + PROP_WRAP(QString, Title) + PROP_WRAP(QString, Filename) + PROP_WRAP(FileTypes, FileType) +}; + + +class Input : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) +}; + + +class Project : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + //PROP_WRAP(QString, Name) + PROP_WRAP(QString, Author) + //PROP_WRAP(Template*, Template) + //PROP_WRAP(QList, Inputs) + //PROP_WRAP(Output*, Output) + + //CHILD_PTR_PROP_WRAP(Output, Output) + //CHILD_PTR_PROP_WRAP(Template, Template) + + PROP_WRAP(QString, Title) + PROP_WRAP(QString, OutputFilename) + PROP_WRAP(FileTypes, OutputFileType) + + PROP_WRAP(QString, Template) + PROP_WRAP(QColor, Color) + + void AddInput(Input* in) { in->setParent(this); } +}; + + +class Solution : public QObject +{ + Q_OBJECT +public: + //PROP_WRAP(QList, Projects) + void AddProject(Project* proj) { proj->setParent(this); } +}; + + +#endif // OBJECTS_H diff --git a/QtProject/MakePDF.pro b/QtProject/MakePDF.pro index f4e410c..4026759 100644 --- a/QtProject/MakePDF.pro +++ b/QtProject/MakePDF.pro @@ -1,21 +1,24 @@ -QT += core gui widgets +# QT += webkitwidgets network widgets +CONFIG += qt +QT += core gui widgets webkitwidgets +#QT += svg CONFIG -= flat TARGET = MakePDF DEFINES += \ - GUI_APP=1 + GUI_APP=1 RESOURCES += \ - ../Resources/resources.qrc + ../Resources/resources.qrc FORMS += \ - ../Resources/forms/About.ui \ - ../Resources/forms/NewProjectWizard.ui \ - ../Resources/forms/ExtensibleObjectModelUI.ui \ - ../Resources/forms/SendBugReport.ui \ + ../Resources/forms/About.ui \ + ../Resources/forms/NewProjectWizard.ui \ + ../Resources/forms/ExtensibleObjectModelUI.ui \ + ../Resources/forms/SendBugReport.ui \ ../Resources/forms/Help.ui \ ../Resources/forms/CheckUpdates.ui \ ../Resources/forms/LicenseUpgrade.ui \ @@ -23,136 +26,174 @@ ../Resources/forms/PaletteEditor.ui INCLUDEPATH += \ - ../Framework \ - ../3rdParty/hoedown \ - ../3rdParty/libharu/include \ - ../3rdParty/TinyXML++ + ../Framework \ + ../3rdParty/hoedown \ + ../3rdParty/libharu/include \ + ../3rdParty/TinyXML++ \ + ../3rdParty/qtpropertybrowser/src HEADERS += \ - ../Framework/EventLog.h \ - ../Framework/Expected.h \ - ../Framework/Final.h \ - ../Framework/Finally.h \ - ../Framework/GenericTable.h \ - ../Framework/GenericTableUI.h \ - ../Framework/NonCopyable.h \ - ../Framework/Utilities.h \ + ../Framework/EventLog.h \ + ../Framework/Expected.h \ + ../Framework/Final.h \ + ../Framework/Finally.h \ + ../Framework/GenericTable.h \ + ../Framework/GenericTableUI.h \ + ../Framework/NonCopyable.h \ + ../Framework/Utilities.h \ + ../Framework/SystemInfomation.h \ + ../Framework/Array.h \ + ../Framework/Macros.h \ + ../Framework/ObjectTreeModel.h \ + ../Version.h \ + ../Util.h \ ../ui.h \ + ../MdiChild.h \ ../MdiWindow.h \ ../ColorPicker.h \ - ../Version.h + ../DocConvert.h \ + ../Objects.h \ + ../ObjectVisitor.h HEADERS += \ - ../DocOutput.h \ - ../DocProject.h \ - ../DocStyle.h \ - ../DocTemplate.h \ - ../DocVisitor.h \ - ../DocSVG.h + ../DocOutput.h \ + ../DocProject.h \ + ../DocStyle.h \ + ../DocTemplate.h \ + ../DocVisitor.h \ + ../DocSVG.h SOURCES += \ - ../Framework/Tests.cpp \ - ../Framework/Utilities.cpp \ - ../Framework/EventLog.cpp \ + ../Framework/Tests.cpp \ + ../Framework/Utilities.cpp \ + ../Framework/EventLog.cpp \ + ../MdiChild.cpp \ ../MdiWindow.cpp \ ../ColorPicker.cpp \ - ../Version.cpp + ../Version.cpp \ + ../Framework/SystemInfomation.cpp \ + ../DocConvert.cpp \ + ../Framework/ObjectTreeModel.cpp SOURCES += \ - ../DocOutput.cpp \ - ../DocProject.cpp \ - ../DocStyle.cpp \ - ../DocTemplate.cpp \ - ../DocVisitor.cpp \ - ../DocSVG.cpp \ - ../main.cpp + ../DocOutput.cpp \ + ../DocProject.cpp \ + ../DocStyle.cpp \ + ../DocTemplate.cpp \ + ../DocVisitor.cpp \ + ../DocSVG.cpp \ + ../main.cpp SOURCES += \ - ../3rdParty/hoedown/autolink.c \ - ../3rdParty/hoedown/buffer.c \ - ../3rdParty/hoedown/document.c \ - ../3rdParty/hoedown/escape.c \ - ../3rdParty/hoedown/html.c \ - ../3rdParty/hoedown/html_blocks.c \ - ../3rdParty/hoedown/stack.c + ../3rdParty/hoedown/autolink.c \ + ../3rdParty/hoedown/buffer.c \ + ../3rdParty/hoedown/document.c \ + ../3rdParty/hoedown/escape.c \ + ../3rdParty/hoedown/html.c \ + ../3rdParty/hoedown/html_blocks.c \ + ../3rdParty/hoedown/stack.c SOURCES += \ - ../3rdParty/libharu/src/hpdf_3dmeasure.c \ - ../3rdParty/libharu/src/hpdf_annotation.c \ - ../3rdParty/libharu/src/hpdf_array.c \ - ../3rdParty/libharu/src/hpdf_binary.c \ - ../3rdParty/libharu/src/hpdf_boolean.c \ - ../3rdParty/libharu/src/hpdf_catalog.c \ - ../3rdParty/libharu/src/hpdf_destination.c \ - ../3rdParty/libharu/src/hpdf_dict.c \ - ../3rdParty/libharu/src/hpdf_doc.c \ - ../3rdParty/libharu/src/hpdf_doc_png.c \ - ../3rdParty/libharu/src/hpdf_encoder.c \ - ../3rdParty/libharu/src/hpdf_encoder_utf.c \ - ../3rdParty/libharu/src/hpdf_encrypt.c \ - ../3rdParty/libharu/src/hpdf_encryptdict.c \ - ../3rdParty/libharu/src/hpdf_error.c \ - ../3rdParty/libharu/src/hpdf_exdata.c \ - ../3rdParty/libharu/src/hpdf_ext_gstate.c \ - ../3rdParty/libharu/src/hpdf_font.c \ - ../3rdParty/libharu/src/hpdf_fontdef.c \ - ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ - ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ - ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ - ../3rdParty/libharu/src/hpdf_font_cid.c \ - ../3rdParty/libharu/src/hpdf_font_tt.c \ - ../3rdParty/libharu/src/hpdf_font_type1.c \ - ../3rdParty/libharu/src/hpdf_gstate.c \ - ../3rdParty/libharu/src/hpdf_image.c \ - ../3rdParty/libharu/src/hpdf_image_png.c \ - ../3rdParty/libharu/src/hpdf_info.c \ - ../3rdParty/libharu/src/hpdf_list.c \ - ../3rdParty/libharu/src/hpdf_mmgr.c \ - ../3rdParty/libharu/src/hpdf_name.c \ - ../3rdParty/libharu/src/hpdf_namedict.c \ - ../3rdParty/libharu/src/hpdf_null.c \ - ../3rdParty/libharu/src/hpdf_number.c \ - ../3rdParty/libharu/src/hpdf_objects.c \ - ../3rdParty/libharu/src/hpdf_outline.c \ - ../3rdParty/libharu/src/hpdf_pages.c \ - ../3rdParty/libharu/src/hpdf_page_label.c \ - ../3rdParty/libharu/src/hpdf_page_operator.c \ - ../3rdParty/libharu/src/hpdf_pdfa.c \ - ../3rdParty/libharu/src/hpdf_real.c \ - ../3rdParty/libharu/src/hpdf_streams.c \ - ../3rdParty/libharu/src/hpdf_string.c \ - ../3rdParty/libharu/src/hpdf_u3d.c \ - ../3rdParty/libharu/src/hpdf_utils.c \ - ../3rdParty/libharu/src/hpdf_xref.c + ../3rdParty/libharu/src/hpdf_3dmeasure.c \ + ../3rdParty/libharu/src/hpdf_annotation.c \ + ../3rdParty/libharu/src/hpdf_array.c \ + ../3rdParty/libharu/src/hpdf_binary.c \ + ../3rdParty/libharu/src/hpdf_boolean.c \ + ../3rdParty/libharu/src/hpdf_catalog.c \ + ../3rdParty/libharu/src/hpdf_destination.c \ + ../3rdParty/libharu/src/hpdf_dict.c \ + ../3rdParty/libharu/src/hpdf_doc.c \ + ../3rdParty/libharu/src/hpdf_doc_png.c \ + ../3rdParty/libharu/src/hpdf_encoder.c \ + ../3rdParty/libharu/src/hpdf_encoder_utf.c \ + ../3rdParty/libharu/src/hpdf_encrypt.c \ + ../3rdParty/libharu/src/hpdf_encryptdict.c \ + ../3rdParty/libharu/src/hpdf_error.c \ + ../3rdParty/libharu/src/hpdf_exdata.c \ + ../3rdParty/libharu/src/hpdf_ext_gstate.c \ + ../3rdParty/libharu/src/hpdf_font.c \ + ../3rdParty/libharu/src/hpdf_fontdef.c \ + ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ + ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ + ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ + ../3rdParty/libharu/src/hpdf_font_cid.c \ + ../3rdParty/libharu/src/hpdf_font_tt.c \ + ../3rdParty/libharu/src/hpdf_font_type1.c \ + ../3rdParty/libharu/src/hpdf_gstate.c \ + ../3rdParty/libharu/src/hpdf_image.c \ + ../3rdParty/libharu/src/hpdf_image_png.c \ + ../3rdParty/libharu/src/hpdf_info.c \ + ../3rdParty/libharu/src/hpdf_list.c \ + ../3rdParty/libharu/src/hpdf_mmgr.c \ + ../3rdParty/libharu/src/hpdf_name.c \ + ../3rdParty/libharu/src/hpdf_namedict.c \ + ../3rdParty/libharu/src/hpdf_null.c \ + ../3rdParty/libharu/src/hpdf_number.c \ + ../3rdParty/libharu/src/hpdf_objects.c \ + ../3rdParty/libharu/src/hpdf_outline.c \ + ../3rdParty/libharu/src/hpdf_pages.c \ + ../3rdParty/libharu/src/hpdf_page_label.c \ + ../3rdParty/libharu/src/hpdf_page_operator.c \ + ../3rdParty/libharu/src/hpdf_pdfa.c \ + ../3rdParty/libharu/src/hpdf_real.c \ + ../3rdParty/libharu/src/hpdf_streams.c \ + ../3rdParty/libharu/src/hpdf_string.c \ + ../3rdParty/libharu/src/hpdf_u3d.c \ + ../3rdParty/libharu/src/hpdf_utils.c \ + ../3rdParty/libharu/src/hpdf_xref.c SOURCES += \ - ../3rdParty/TinyXML++/ticpp.cpp \ - ../3rdParty/TinyXML++/tinystr.cpp \ - ../3rdParty/TinyXML++/tinyxml.cpp \ - ../3rdParty/TinyXML++/tinyxmlerror.cpp \ - ../3rdParty/TinyXML++/tinyxmlparser.cpp + ../3rdParty/TinyXML++/ticpp.cpp \ + ../3rdParty/TinyXML++/tinystr.cpp \ + ../3rdParty/TinyXML++/tinyxml.cpp \ + ../3rdParty/TinyXML++/tinyxmlerror.cpp \ + ../3rdParty/TinyXML++/tinyxmlparser.cpp + + +SOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.cpp \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.cpp \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.cpp \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils.cpp + +HEADERS += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.h \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.h \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.h \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils_p.h + +RESOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.qrc # As a note to what was removed REMOVED_SOURCES = \ - ../3rdParty/hoedown/html_smartypants.c \ - ../3rdParty/hoedown/version.c \ - ../3rdParty/libharu/src/hpdf_image_ccitt.c + ../3rdParty/hoedown/html_smartypants.c \ + ../3rdParty/hoedown/version.c \ + ../3rdParty/libharu/src/hpdf_image_ccitt.c # Linux specific settings unix { - QMAKE_CXXFLAGS += --std=gnu++11 - # QMAKE_CXXFLAGS -= -Wall - QMAKE_CXXFLAGS_WARN_ON=-w - QMAKE_CFLAGS_WARN_ON=-w - LIBS += -lpng -lz + QMAKE_CXXFLAGS += --std=gnu++11 + # QMAKE_CXXFLAGS -= -Wall + QMAKE_CXXFLAGS_WARN_ON=-w + QMAKE_CFLAGS_WARN_ON=-w + LIBS += -lpng -lz } @@ -160,77 +201,82 @@ # Windows specific. Note we compile in libpng and zlib statically on Windows win32 { - # Supress annoying warnings - QMAKE_CXXFLAGS += /wd"4996;4100" - QMAKE_CXXFLAGS_WARN_ON -= -w34100 + # Supress annoying warnings + QMAKE_CXXFLAGS += /wd"4996;4100" + QMAKE_CXXFLAGS_WARN_ON -= -w34100 - # Release mode debugging - QMAKE_CXXFLAGS += /Zi - QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF + # Release mode debugging + QMAKE_CXXFLAGS += /Zi + QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF - # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything - Project.target = $${TARGET}.vcxproj - Project.output = $${TARGET}.vcxproj - Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 - Project.depends = '"$${_PRO_FILE_}"' - Project.input = _PRO_FILE_ - QMAKE_EXTRA_COMPILERS += Project + # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything + Project.target = $${TARGET}.vcxproj + Project.output = $${TARGET}.vcxproj + Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 + Project.depends = '"$${_PRO_FILE_}"' + Project.input = _PRO_FILE_ + QMAKE_EXTRA_COMPILERS += Project - # This makes the documentation - MARKDOWN_FILES = \ - test.md \ - test2.md + # This makes the documentation + MARKDOWN_FILES = \ + test.md \ + test2.md - Documentation.target = test.pdf - Documentation.output = test.pdf - Documentation.commands = echo ' ' > test.pdf - Documentation.depends = '"$${MARKDOWN_FILES}"' - Documentation.input = MARKDOWN_FILES - QMAKE_EXTRA_COMPILERS += Documentation + Documentation.target = test.pdf + Documentation.output = test.pdf + Documentation.commands = echo ' ' > test.pdf + Documentation.depends = '"$${MARKDOWN_FILES}"' + Documentation.input = MARKDOWN_FILES + QMAKE_EXTRA_COMPILERS += Documentation - INCLUDEPATH += \ - ../3rdParty/libpng \ - ../3rdParty/zlib + INCLUDEPATH += \ + ../3rdParty/libpng \ + ../3rdParty/zlib - SOURCES += \ - ../3rdParty/libpng/png.c \ - ../3rdParty/libpng/pngerror.c \ - ../3rdParty/libpng/pngget.c \ - ../3rdParty/libpng/pngmem.c \ - ../3rdParty/libpng/pngpread.c \ - ../3rdParty/libpng/pngread.c \ - ../3rdParty/libpng/pngrio.c \ - ../3rdParty/libpng/pngrtran.c \ - ../3rdParty/libpng/pngrutil.c \ - ../3rdParty/libpng/pngset.c \ - ../3rdParty/libpng/pngtrans.c \ - ../3rdParty/libpng/pngwio.c \ - ../3rdParty/libpng/pngwrite.c \ - ../3rdParty/libpng/pngwtran.c \ - ../3rdParty/libpng/pngwutil.c + SOURCES += \ + ../3rdParty/libpng/png.c \ + ../3rdParty/libpng/pngerror.c \ + ../3rdParty/libpng/pngget.c \ + ../3rdParty/libpng/pngmem.c \ + ../3rdParty/libpng/pngpread.c \ + ../3rdParty/libpng/pngread.c \ + ../3rdParty/libpng/pngrio.c \ + ../3rdParty/libpng/pngrtran.c \ + ../3rdParty/libpng/pngrutil.c \ + ../3rdParty/libpng/pngset.c \ + ../3rdParty/libpng/pngtrans.c \ + ../3rdParty/libpng/pngwio.c \ + ../3rdParty/libpng/pngwrite.c \ + ../3rdParty/libpng/pngwtran.c \ + ../3rdParty/libpng/pngwutil.c - SOURCES += \ - ../3rdParty/zlib/inftrees.c \ - ../3rdParty/zlib/trees.c \ - ../3rdParty/zlib/uncompr.c \ - ../3rdParty/zlib/zutil.c \ - ../3rdParty/zlib/adler32.c \ - ../3rdParty/zlib/compress.c \ - ../3rdParty/zlib/crc32.c \ - ../3rdParty/zlib/deflate.c \ - ../3rdParty/zlib/gzclose.c \ - ../3rdParty/zlib/gzlib.c \ - ../3rdParty/zlib/gzread.c \ - ../3rdParty/zlib/gzwrite.c \ - ../3rdParty/zlib/infback.c \ - ../3rdParty/zlib/inffast.c \ - ../3rdParty/zlib/inflate.c + SOURCES += \ + ../3rdParty/zlib/inftrees.c \ + ../3rdParty/zlib/trees.c \ + ../3rdParty/zlib/uncompr.c \ + ../3rdParty/zlib/zutil.c \ + ../3rdParty/zlib/adler32.c \ + ../3rdParty/zlib/compress.c \ + ../3rdParty/zlib/crc32.c \ + ../3rdParty/zlib/deflate.c \ + ../3rdParty/zlib/gzclose.c \ + ../3rdParty/zlib/gzlib.c \ + ../3rdParty/zlib/gzread.c \ + ../3rdParty/zlib/gzwrite.c \ + ../3rdParty/zlib/infback.c \ + ../3rdParty/zlib/inffast.c \ + ../3rdParty/zlib/inflate.c } +OTHER_FILES += \ + ../Website/about.html \ + ../Website/register.html \ + ../Website/support.html + diff --git a/Resources/forms/About.ui b/Resources/forms/About.ui index bd6bdf3..3265d89 100644 --- a/Resources/forms/About.ui +++ b/Resources/forms/About.ui @@ -152,7 +152,7 @@ QFrame::Plain - + 20 @@ -165,7 +165,7 @@ <html><head/><body><p><a href="http://url.to.application/"><span style=" text-decoration: underline; color:#0000ff;">http://url.to.application/</span></a></p></body></html> - + 360 @@ -175,16 +175,16 @@ - - - - :/images/images/logo.svg + AppIcon true + + Qt::AlignCenter + - + 20 @@ -193,11 +193,18 @@ 31 + + + 20 + 75 + true + + - <html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Wicked Docs</span></p></body></html> + AppName - + 20 @@ -207,7 +214,7 @@ - <html><head/><body><p>Version 1.0.0.0001</p></body></html> + AppVer @@ -337,7 +344,7 @@ - <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://blah/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements / LicensesEULA</span></a></p></body></html> + <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br/><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://sdfdsf/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements &amp; Licenses</span></a>&nbsp;&nbsp;<a href="http://sfsdf/"><span style=" text-decoration: underline; color:#0000ff;">EULA</span></a></p></body></html> label_5 @@ -346,9 +353,7 @@
- - - + okayButton diff --git a/Resources/forms/ExtensibleObjectModelUI.ui b/Resources/forms/ExtensibleObjectModelUI.ui index 4a794d4..c3fcbc4 100644 --- a/Resources/forms/ExtensibleObjectModelUI.ui +++ b/Resources/forms/ExtensibleObjectModelUI.ui @@ -250,7 +250,7 @@ 0 - + @@ -347,7 +347,7 @@ - + @@ -478,6 +478,16 @@ + + + + + 0 + 200 + + + + @@ -921,6 +931,14 @@ + + + QWebView + QWidget +
QWebView
+ 1 +
+
diff --git a/Resources/forms/LicenseUpgrade.ui b/Resources/forms/LicenseUpgrade.ui index 69b55ad..4ce2ac1 100644 --- a/Resources/forms/LicenseUpgrade.ui +++ b/Resources/forms/LicenseUpgrade.ui @@ -42,7 +42,7 @@ Upgrade license - + 290 diff --git a/Resources/forms/SendBugReport.ui b/Resources/forms/SendBugReport.ui index 1a7d910..70e177e 100644 --- a/Resources/forms/SendBugReport.ui +++ b/Resources/forms/SendBugReport.ui @@ -6,8 +6,8 @@ 0 0 - 489 - 420 + 525 + 421 @@ -17,49 +17,49 @@ - Software information + System information 15 - + - Version: + Application: - + unknown - + OS Platform: - + unknown - + - Date/Time: + Version: - + unknown @@ -79,74 +79,83 @@ - - - - - - - System information - - - - 15 - - - - - Include system info in report - - - true - - - - - - - RAM: - - - - - - - unknown - - - - + CPU: - + unknown - + Resolution: - + unknown + + + + RAM: + + + + + + + unknown + + + + + + + Date/Time: + + + + + + + unknown + + + + + + Short description: + + + + + + + + + + Short text description of problem + + + + Bug description: @@ -154,14 +163,18 @@ - + + + Detailed description of the issue, such as the type of issue, (eg an improvement, bug, crash, usability problem) and the steps needed to reproduce the problem. Add any notes that you think may be relevant. + + - Email address: + Email address (optional): @@ -238,7 +251,6 @@ desc email - sendSysInfo diff --git a/Util.h b/Util.h index 1dfc996..25da56e 100644 --- a/Util.h +++ b/Util.h @@ -12,7 +12,7 @@ { return std::unique_ptr( new T( std::forward(args)... ) ); } -}; +} inline int fopen_s(FILE** a_file, const char* a_fileName, const char* a_mode) { diff --git a/Version.cpp b/Version.cpp index fb913ae..86e6110 100644 --- a/Version.cpp +++ b/Version.cpp @@ -1,131 +1,2 @@ #include "Version.h" -#include "Util.h" -#include -#include -#include - -#ifdef __APPLE__ -# include "TargetConditionals.h" -#elif defined(_WIN32) -# include -#else -# include -# include -# include -# include -#endif - - -void getSystemInfo(SystemInfo& a_info) -{ - a_info.m_cpuType = "unknown"; - a_info.m_osType = "unknown"; - a_info.m_osVersion = "unknown"; - -#ifdef _WIN32 - a_info.m_osType = "Windows"; - - // Get RAM size - MEMORYSTATUSEX status; - status.dwLength = sizeof(status); - GlobalMemoryStatusEx(&status); - a_info.m_ramSize = status.ullTotalPhys; - - // Get OS version - const OSVERSIONINFO osver = winOsVersion(); - a_info.m_osVersion.reserve(512); - snprintf(a_info.m_osVersion.data(), "%i.%i.%i", osver.dwMajorVersion, osver.dwMinorVersion, osver.dwBuildNumber); - - // Get OS arch - SYSTEM_INFO info; - GetNativeSystemInfo(&info); -# ifdef _WIN64 - //if (info.wProcessorArchitecture == ???) - a_info.m_cpuType = "x86_64"; -# else - a_info.m_cpuType = "x86"; -# endif -#else - long pages = sysconf(_SC_PHYS_PAGES); - long page_size = sysconf(_SC_PAGE_SIZE); - a_info.m_ramSize = pages * page_size; - struct utsname u; - long ret = uname(&u); - if (ret != -1) - { - a_info.m_cpuType = u.machine; - a_info.m_osVersion = u.sysname + std::string(" ") + u.release; - } -# ifdef __APPLE__ - // Get RAM Size - int mib[2] = { CTL_HW, HW_MEMSIZE }; - size_t len = sizeof(uint64_t); - sysctl(mib, sizeof(mib) / sizeof(mib[0]), &u.ramSize, &len, NULL, 0); -# if TARGET_OS_IPHONE - a_info.m_osType = "iOS"; -# elif TARGET_OS_MAC - const char *macCodeName = ""; - switch (int(MacintoshVersion)) { - case MV_CHEETAH: macCodeName = " Cheetah"; break; - case MV_PUMA: macCodeName = " Puma"; break; - case MV_JAGUAR: macCodeName = " Jaguar"; break; - case MV_PANTHER: macCodeName = " Panther"; break; - case MV_TIGER: macCodeName = " Tiger"; break; - case MV_LEOPARD: macCodeName = " Leopard"; break; - case MV_SNOWLEOPARD: macCodeName = " Snow Leopard"; break; - case MV_LION: macCodeName = " Lion"; break; - case MV_MOUNTAINLION:macCodeName = " Mountain Lion"; break; - case MV_MAVERICKS: macCodeName = " Mavericks"; break; - case MV_YOSEMITE: macCodeName = " Yosemite"; break; - } - a_info.m_osType = "Mac OS X" + std::string(macCodeName); -# endif -# elif __ANDROID__ - a_info.m_osType = "Android"; -# elif __linux - // system("lsb_release -sd"); - FILE* f = fopen("/etc/lsb-release", "rt"); - char dist[64] = { 0 }; - if (f) { - char buf[128]; - while (fgets(buf, 128, f) != 0) - if (sscanf(buf, "DISTRIB_DESCRIPTION=%64c", dist) == 1) - break; - if (dist[0]) { - std::vector strBits = split(dist, '"'); - a_info.m_osType = strBits[(strBits.size()==3)?1:0]; - } else { - a_info.m_osType = "non-specific LSB"; - } - fclose(f); - } else { - a_info.m_osType = "non-LSB"; - } -# else - a_info.m_osType = "Generic UNIX"; -# endif -#endif - - // TODO: improve the CPU detection using libcpuid - - // Make human readable RAM size string - const char* humanUnitStrings[] = { " bytes", " KB", " MB", " GB", " TB" }; - int ramUnit = 0; - uint64_t ramSize = a_info.m_ramSize; - while (ramSize > 1024 && ramUnit < (YQ_ARRAY_SIZE(humanUnitStrings)-1)) - ramUnit++, ramSize /= 1000; - a_info.m_ramSizeStr = std::to_string(ramSize) + humanUnitStrings[ramUnit]; - - // Obtain the screen properties - QScreen *s = QApplication::screens()[0]; - int refreshRate = (s) ? s->refreshRate() : 0; - int depth = (s) ? s->depth() : 0; - a_info.m_resolutionWidth = (s) ? s->geometry().width() : 0; - a_info.m_resolutionHeight = (s) ? s->geometry().height() : 0; - a_info.m_resolutionStr = std::to_string(a_info.m_resolutionWidth) + "x" - + std::to_string(a_info.m_resolutionHeight) + " " - + std::to_string(depth) + "bit " - + "@" + std::to_string(refreshRate) + "Hz"; - ; -} diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/MdiWindow.h b/MdiWindow.h index 76d7f1b..35ef9c3 100644 --- a/MdiWindow.h +++ b/MdiWindow.h @@ -4,78 +4,19 @@ #include #include +#include "Objects.h" +#include "MdiChild.h" -class MdiChild; class QAction; class QMenu; class QMdiArea; class QMdiSubWindow; class QSignalMapper; +class QTcpServer; class Ui_MainWindow; -class MdiChild : public QTextEdit -{ - Q_OBJECT -public: - MdiChild(); - ~MdiChild(); - - void newFile(); - bool loadFile(const QString &fileName); - bool save(); - bool saveAs(); - bool saveFile(const QString &fileName); - QString userFriendlyCurrentFile(); - QString currentFile() { return curFile; } - - void markdownSelection(const char* preText, const char* postText); - - void bold(); - void italic(); - void quote(); - void code(); - void heading1(); - void heading2(); - void heading3(); - void heading4(); - void hyperlink(); - void image(); - void unorderedList(); - void orderedList(); - void horizontalRule(); - void timestamp(); - void pageNumber(); - void pageCount(); - void del(); - void undo(); - void redo(); - void find(); - void findNext(); - void findPrevious(); - void goToLine(); - -signals: - void closing(); - void documentContentsChanged(); - -private slots: - void documentWasModified(); - -protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - -private: - bool maybeSave(); - void setCurrentFile(const QString &fileName); - QString strippedName(const QString &fullFileName); - - QString curFile; - bool isUntitled; -}; - - /* class MdiOptions { @@ -109,8 +50,12 @@ void save(); void saveAs(); + void handleRequest(); void updatePreview(); + void setWebPreviewURL(); + void refreshWebPreview(); + // Edit menu actions #ifndef QT_NO_CLIPBOARD void cut(); @@ -159,12 +104,26 @@ void switchLayoutDirection(); void setActiveSubWindow(QWidget *window); + void changeRootObject(const QModelIndex &index); + void changePropertiesObject(const QModelIndex &index); + + // Dialog events + void upgradeClicked(); + private: + void changeProjectTree(QObject *rootObject); + void updateObjectTree(QObject *rootObject); + void updatePropertiesView(QObject *object); + void setupServer(); void readSettings(); + void readLicense(); void writeSettings(); MdiChild *activeMdiChild(); QMdiSubWindow *findMdiChild(const QString &fileName); + //Solution solution; + QByteArray pdfContents; + QTcpServer *server; QMdiArea *mdiArea; QSignalMapper *windowMapper; Ui_MainWindow *appWindow; diff --git a/ObjectVisitor.h b/ObjectVisitor.h new file mode 100644 index 0000000..12cf25f --- /dev/null +++ b/ObjectVisitor.h @@ -0,0 +1,59 @@ +#ifndef OBJECTVISITOR_H +#define OBJECTVISITOR_H + + +#include +#include +#include +#include + + +class Visitor +{ +public: + Visitor() {} + virtual ~Visitor() {} + + virtual void enterObject(const char* className, const char* objectName) = 0; + virtual void leaveObject(const char* className, const char* objectName) = 0; + + // Reads or writes a property value + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) = 0; + + // By default, it is a reader, but implementing this enables a visitor that sets values + virtual bool isWriting() { return false; } +}; + + +void Visit(Visitor& visitor, QObject* object) +{ + std::string objectName = object->objectName().toLocal8Bit().data(); + if (objectName.size() <= 1) { + objectName = std::to_string((uint64_t)(void*)object); + } + visitor.enterObject(object->metaObject()->className(), objectName.c_str()); + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + if (visitor.isWriting()) { + QVariant value; + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + property.write(object, value); + + } else { + QVariant value = property.read(object); + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + } + } + for (int i = 0; i < object->children().count(); i++) + { + Visit(visitor, object->children()[i]); + } + visitor.leaveObject(object->metaObject()->className(), objectName.c_str()); +} + + +#endif // OBJECTVISITOR_H diff --git a/Objects.h b/Objects.h new file mode 100644 index 0000000..90e7bb1 --- /dev/null +++ b/Objects.h @@ -0,0 +1,167 @@ +#ifndef OBJECTS_H +#define OBJECTS_H + + +#include +#include +#include +#include +#include +#include +#include + + +class EnumEditor : public QWidget +{ + Q_OBJECT +public slots: + void ListSelectionChanged(); + void ComboSelectionChanged(); +public: + EnumEditor(QMetaEnum metaEnum); +private: + QListWidget* lw; + QComboBox* cb; + QSpinBox* sb; + QLabel* str; + QMetaEnum m_metaEnum; +}; + + +// Property Manager Supported types: +// int, bool, double, enums, flags +// QString, QDate, QTime, QDateTime, QKeySequence +// QChar, QLocale, QPoint, QPointF, QSize, QSizeF +// QRect, QRectF, QSizePolicy, QFont, QColor, QCursor + + +#define PROP_WRAP(type, name) \ + Q_PROPERTY(type name READ get##name WRITE set##name) \ + type get##name() const { return m_##name; } \ + void set##name(type val) { m_##name = val; } \ + type m_##name; + +#define CHILD_PTR_PROP_WRAP(type, name) \ + Q_PROPERTY(type* name READ get##name WRITE set##name) \ + type* get##name() const { return m_##name; } \ + void set##name(type* val) { \ + /* if (m_##name) children().removeAll((QObject*)m_##name); */ \ + val->setParent(this); \ + m_##name = val; \ + } \ + type* m_##name = nullptr; + + +class MyObjectTest : public QObject +{ + Q_OBJECT + Q_ENUMS(AnotherEnum) + Q_ENUMS(TestEnum) + Q_FLAGS(TestFlags) +public: + enum TestFlags { FlagValue1 = 1, AnotherFlagValue = 2, FlagEtc = 4, FlagBlah = 8 }; + enum TestEnum { EnumValue1, AnotherValue, Etc, Blah }; + enum AnotherEnum { AEnumValue1, AnAnotherValue, Etc2 }; + + explicit MyObjectTest() : QObject() { + m_An_Int_Value = 10; + m_A_Double = 11.0; + //m_An_Enum = EnumValue1; + //memset(this, 0, sizeof(MyObjectTest)); + } + ~MyObjectTest() { + } + + PROP_WRAP(int, An_Int_Value) + PROP_WRAP(bool, A_Bool) + PROP_WRAP(double, A_Double) + PROP_WRAP(TestEnum,An_Enum1) + PROP_WRAP(TestEnum,An_Enum2) + PROP_WRAP(QFlags,A_Flags) + PROP_WRAP(QString, A_String) + PROP_WRAP(QDate, A_Date) + PROP_WRAP(QTime, A_Time) + PROP_WRAP(QDateTime, A_Date_and_Time) + PROP_WRAP(QKeySequence, A_Key_Sequence) + PROP_WRAP(QChar, A_Char) + PROP_WRAP(QLocale, A_Locale) + PROP_WRAP(QPoint, A_Point) + PROP_WRAP(QPointF, A_PointF) + PROP_WRAP(QSize, A_Size) + PROP_WRAP(QSizeF, A_SizeF) + PROP_WRAP(QRect, A_Rect) + PROP_WRAP(QRectF, A_RectF) + //PROP_WRAP(QSizePolicy, A_SizePolicy) + //PROP_WRAP(QFont, A_Font) + PROP_WRAP(QColor, A_Color) + //PROP_WRAP(QCursor, A_Cursor) + // flags +}; + + + +class Template : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) + PROP_WRAP(QColor, Color) +}; + + +class Output : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + PROP_WRAP(QString, Title) + PROP_WRAP(QString, Filename) + PROP_WRAP(FileTypes, FileType) +}; + + +class Input : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) +}; + + +class Project : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + //PROP_WRAP(QString, Name) + PROP_WRAP(QString, Author) + //PROP_WRAP(Template*, Template) + //PROP_WRAP(QList, Inputs) + //PROP_WRAP(Output*, Output) + + //CHILD_PTR_PROP_WRAP(Output, Output) + //CHILD_PTR_PROP_WRAP(Template, Template) + + PROP_WRAP(QString, Title) + PROP_WRAP(QString, OutputFilename) + PROP_WRAP(FileTypes, OutputFileType) + + PROP_WRAP(QString, Template) + PROP_WRAP(QColor, Color) + + void AddInput(Input* in) { in->setParent(this); } +}; + + +class Solution : public QObject +{ + Q_OBJECT +public: + //PROP_WRAP(QList, Projects) + void AddProject(Project* proj) { proj->setParent(this); } +}; + + +#endif // OBJECTS_H diff --git a/QtProject/MakePDF.pro b/QtProject/MakePDF.pro index f4e410c..4026759 100644 --- a/QtProject/MakePDF.pro +++ b/QtProject/MakePDF.pro @@ -1,21 +1,24 @@ -QT += core gui widgets +# QT += webkitwidgets network widgets +CONFIG += qt +QT += core gui widgets webkitwidgets +#QT += svg CONFIG -= flat TARGET = MakePDF DEFINES += \ - GUI_APP=1 + GUI_APP=1 RESOURCES += \ - ../Resources/resources.qrc + ../Resources/resources.qrc FORMS += \ - ../Resources/forms/About.ui \ - ../Resources/forms/NewProjectWizard.ui \ - ../Resources/forms/ExtensibleObjectModelUI.ui \ - ../Resources/forms/SendBugReport.ui \ + ../Resources/forms/About.ui \ + ../Resources/forms/NewProjectWizard.ui \ + ../Resources/forms/ExtensibleObjectModelUI.ui \ + ../Resources/forms/SendBugReport.ui \ ../Resources/forms/Help.ui \ ../Resources/forms/CheckUpdates.ui \ ../Resources/forms/LicenseUpgrade.ui \ @@ -23,136 +26,174 @@ ../Resources/forms/PaletteEditor.ui INCLUDEPATH += \ - ../Framework \ - ../3rdParty/hoedown \ - ../3rdParty/libharu/include \ - ../3rdParty/TinyXML++ + ../Framework \ + ../3rdParty/hoedown \ + ../3rdParty/libharu/include \ + ../3rdParty/TinyXML++ \ + ../3rdParty/qtpropertybrowser/src HEADERS += \ - ../Framework/EventLog.h \ - ../Framework/Expected.h \ - ../Framework/Final.h \ - ../Framework/Finally.h \ - ../Framework/GenericTable.h \ - ../Framework/GenericTableUI.h \ - ../Framework/NonCopyable.h \ - ../Framework/Utilities.h \ + ../Framework/EventLog.h \ + ../Framework/Expected.h \ + ../Framework/Final.h \ + ../Framework/Finally.h \ + ../Framework/GenericTable.h \ + ../Framework/GenericTableUI.h \ + ../Framework/NonCopyable.h \ + ../Framework/Utilities.h \ + ../Framework/SystemInfomation.h \ + ../Framework/Array.h \ + ../Framework/Macros.h \ + ../Framework/ObjectTreeModel.h \ + ../Version.h \ + ../Util.h \ ../ui.h \ + ../MdiChild.h \ ../MdiWindow.h \ ../ColorPicker.h \ - ../Version.h + ../DocConvert.h \ + ../Objects.h \ + ../ObjectVisitor.h HEADERS += \ - ../DocOutput.h \ - ../DocProject.h \ - ../DocStyle.h \ - ../DocTemplate.h \ - ../DocVisitor.h \ - ../DocSVG.h + ../DocOutput.h \ + ../DocProject.h \ + ../DocStyle.h \ + ../DocTemplate.h \ + ../DocVisitor.h \ + ../DocSVG.h SOURCES += \ - ../Framework/Tests.cpp \ - ../Framework/Utilities.cpp \ - ../Framework/EventLog.cpp \ + ../Framework/Tests.cpp \ + ../Framework/Utilities.cpp \ + ../Framework/EventLog.cpp \ + ../MdiChild.cpp \ ../MdiWindow.cpp \ ../ColorPicker.cpp \ - ../Version.cpp + ../Version.cpp \ + ../Framework/SystemInfomation.cpp \ + ../DocConvert.cpp \ + ../Framework/ObjectTreeModel.cpp SOURCES += \ - ../DocOutput.cpp \ - ../DocProject.cpp \ - ../DocStyle.cpp \ - ../DocTemplate.cpp \ - ../DocVisitor.cpp \ - ../DocSVG.cpp \ - ../main.cpp + ../DocOutput.cpp \ + ../DocProject.cpp \ + ../DocStyle.cpp \ + ../DocTemplate.cpp \ + ../DocVisitor.cpp \ + ../DocSVG.cpp \ + ../main.cpp SOURCES += \ - ../3rdParty/hoedown/autolink.c \ - ../3rdParty/hoedown/buffer.c \ - ../3rdParty/hoedown/document.c \ - ../3rdParty/hoedown/escape.c \ - ../3rdParty/hoedown/html.c \ - ../3rdParty/hoedown/html_blocks.c \ - ../3rdParty/hoedown/stack.c + ../3rdParty/hoedown/autolink.c \ + ../3rdParty/hoedown/buffer.c \ + ../3rdParty/hoedown/document.c \ + ../3rdParty/hoedown/escape.c \ + ../3rdParty/hoedown/html.c \ + ../3rdParty/hoedown/html_blocks.c \ + ../3rdParty/hoedown/stack.c SOURCES += \ - ../3rdParty/libharu/src/hpdf_3dmeasure.c \ - ../3rdParty/libharu/src/hpdf_annotation.c \ - ../3rdParty/libharu/src/hpdf_array.c \ - ../3rdParty/libharu/src/hpdf_binary.c \ - ../3rdParty/libharu/src/hpdf_boolean.c \ - ../3rdParty/libharu/src/hpdf_catalog.c \ - ../3rdParty/libharu/src/hpdf_destination.c \ - ../3rdParty/libharu/src/hpdf_dict.c \ - ../3rdParty/libharu/src/hpdf_doc.c \ - ../3rdParty/libharu/src/hpdf_doc_png.c \ - ../3rdParty/libharu/src/hpdf_encoder.c \ - ../3rdParty/libharu/src/hpdf_encoder_utf.c \ - ../3rdParty/libharu/src/hpdf_encrypt.c \ - ../3rdParty/libharu/src/hpdf_encryptdict.c \ - ../3rdParty/libharu/src/hpdf_error.c \ - ../3rdParty/libharu/src/hpdf_exdata.c \ - ../3rdParty/libharu/src/hpdf_ext_gstate.c \ - ../3rdParty/libharu/src/hpdf_font.c \ - ../3rdParty/libharu/src/hpdf_fontdef.c \ - ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ - ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ - ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ - ../3rdParty/libharu/src/hpdf_font_cid.c \ - ../3rdParty/libharu/src/hpdf_font_tt.c \ - ../3rdParty/libharu/src/hpdf_font_type1.c \ - ../3rdParty/libharu/src/hpdf_gstate.c \ - ../3rdParty/libharu/src/hpdf_image.c \ - ../3rdParty/libharu/src/hpdf_image_png.c \ - ../3rdParty/libharu/src/hpdf_info.c \ - ../3rdParty/libharu/src/hpdf_list.c \ - ../3rdParty/libharu/src/hpdf_mmgr.c \ - ../3rdParty/libharu/src/hpdf_name.c \ - ../3rdParty/libharu/src/hpdf_namedict.c \ - ../3rdParty/libharu/src/hpdf_null.c \ - ../3rdParty/libharu/src/hpdf_number.c \ - ../3rdParty/libharu/src/hpdf_objects.c \ - ../3rdParty/libharu/src/hpdf_outline.c \ - ../3rdParty/libharu/src/hpdf_pages.c \ - ../3rdParty/libharu/src/hpdf_page_label.c \ - ../3rdParty/libharu/src/hpdf_page_operator.c \ - ../3rdParty/libharu/src/hpdf_pdfa.c \ - ../3rdParty/libharu/src/hpdf_real.c \ - ../3rdParty/libharu/src/hpdf_streams.c \ - ../3rdParty/libharu/src/hpdf_string.c \ - ../3rdParty/libharu/src/hpdf_u3d.c \ - ../3rdParty/libharu/src/hpdf_utils.c \ - ../3rdParty/libharu/src/hpdf_xref.c + ../3rdParty/libharu/src/hpdf_3dmeasure.c \ + ../3rdParty/libharu/src/hpdf_annotation.c \ + ../3rdParty/libharu/src/hpdf_array.c \ + ../3rdParty/libharu/src/hpdf_binary.c \ + ../3rdParty/libharu/src/hpdf_boolean.c \ + ../3rdParty/libharu/src/hpdf_catalog.c \ + ../3rdParty/libharu/src/hpdf_destination.c \ + ../3rdParty/libharu/src/hpdf_dict.c \ + ../3rdParty/libharu/src/hpdf_doc.c \ + ../3rdParty/libharu/src/hpdf_doc_png.c \ + ../3rdParty/libharu/src/hpdf_encoder.c \ + ../3rdParty/libharu/src/hpdf_encoder_utf.c \ + ../3rdParty/libharu/src/hpdf_encrypt.c \ + ../3rdParty/libharu/src/hpdf_encryptdict.c \ + ../3rdParty/libharu/src/hpdf_error.c \ + ../3rdParty/libharu/src/hpdf_exdata.c \ + ../3rdParty/libharu/src/hpdf_ext_gstate.c \ + ../3rdParty/libharu/src/hpdf_font.c \ + ../3rdParty/libharu/src/hpdf_fontdef.c \ + ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ + ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ + ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ + ../3rdParty/libharu/src/hpdf_font_cid.c \ + ../3rdParty/libharu/src/hpdf_font_tt.c \ + ../3rdParty/libharu/src/hpdf_font_type1.c \ + ../3rdParty/libharu/src/hpdf_gstate.c \ + ../3rdParty/libharu/src/hpdf_image.c \ + ../3rdParty/libharu/src/hpdf_image_png.c \ + ../3rdParty/libharu/src/hpdf_info.c \ + ../3rdParty/libharu/src/hpdf_list.c \ + ../3rdParty/libharu/src/hpdf_mmgr.c \ + ../3rdParty/libharu/src/hpdf_name.c \ + ../3rdParty/libharu/src/hpdf_namedict.c \ + ../3rdParty/libharu/src/hpdf_null.c \ + ../3rdParty/libharu/src/hpdf_number.c \ + ../3rdParty/libharu/src/hpdf_objects.c \ + ../3rdParty/libharu/src/hpdf_outline.c \ + ../3rdParty/libharu/src/hpdf_pages.c \ + ../3rdParty/libharu/src/hpdf_page_label.c \ + ../3rdParty/libharu/src/hpdf_page_operator.c \ + ../3rdParty/libharu/src/hpdf_pdfa.c \ + ../3rdParty/libharu/src/hpdf_real.c \ + ../3rdParty/libharu/src/hpdf_streams.c \ + ../3rdParty/libharu/src/hpdf_string.c \ + ../3rdParty/libharu/src/hpdf_u3d.c \ + ../3rdParty/libharu/src/hpdf_utils.c \ + ../3rdParty/libharu/src/hpdf_xref.c SOURCES += \ - ../3rdParty/TinyXML++/ticpp.cpp \ - ../3rdParty/TinyXML++/tinystr.cpp \ - ../3rdParty/TinyXML++/tinyxml.cpp \ - ../3rdParty/TinyXML++/tinyxmlerror.cpp \ - ../3rdParty/TinyXML++/tinyxmlparser.cpp + ../3rdParty/TinyXML++/ticpp.cpp \ + ../3rdParty/TinyXML++/tinystr.cpp \ + ../3rdParty/TinyXML++/tinyxml.cpp \ + ../3rdParty/TinyXML++/tinyxmlerror.cpp \ + ../3rdParty/TinyXML++/tinyxmlparser.cpp + + +SOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.cpp \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.cpp \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.cpp \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils.cpp + +HEADERS += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.h \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.h \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.h \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils_p.h + +RESOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.qrc # As a note to what was removed REMOVED_SOURCES = \ - ../3rdParty/hoedown/html_smartypants.c \ - ../3rdParty/hoedown/version.c \ - ../3rdParty/libharu/src/hpdf_image_ccitt.c + ../3rdParty/hoedown/html_smartypants.c \ + ../3rdParty/hoedown/version.c \ + ../3rdParty/libharu/src/hpdf_image_ccitt.c # Linux specific settings unix { - QMAKE_CXXFLAGS += --std=gnu++11 - # QMAKE_CXXFLAGS -= -Wall - QMAKE_CXXFLAGS_WARN_ON=-w - QMAKE_CFLAGS_WARN_ON=-w - LIBS += -lpng -lz + QMAKE_CXXFLAGS += --std=gnu++11 + # QMAKE_CXXFLAGS -= -Wall + QMAKE_CXXFLAGS_WARN_ON=-w + QMAKE_CFLAGS_WARN_ON=-w + LIBS += -lpng -lz } @@ -160,77 +201,82 @@ # Windows specific. Note we compile in libpng and zlib statically on Windows win32 { - # Supress annoying warnings - QMAKE_CXXFLAGS += /wd"4996;4100" - QMAKE_CXXFLAGS_WARN_ON -= -w34100 + # Supress annoying warnings + QMAKE_CXXFLAGS += /wd"4996;4100" + QMAKE_CXXFLAGS_WARN_ON -= -w34100 - # Release mode debugging - QMAKE_CXXFLAGS += /Zi - QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF + # Release mode debugging + QMAKE_CXXFLAGS += /Zi + QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF - # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything - Project.target = $${TARGET}.vcxproj - Project.output = $${TARGET}.vcxproj - Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 - Project.depends = '"$${_PRO_FILE_}"' - Project.input = _PRO_FILE_ - QMAKE_EXTRA_COMPILERS += Project + # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything + Project.target = $${TARGET}.vcxproj + Project.output = $${TARGET}.vcxproj + Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 + Project.depends = '"$${_PRO_FILE_}"' + Project.input = _PRO_FILE_ + QMAKE_EXTRA_COMPILERS += Project - # This makes the documentation - MARKDOWN_FILES = \ - test.md \ - test2.md + # This makes the documentation + MARKDOWN_FILES = \ + test.md \ + test2.md - Documentation.target = test.pdf - Documentation.output = test.pdf - Documentation.commands = echo ' ' > test.pdf - Documentation.depends = '"$${MARKDOWN_FILES}"' - Documentation.input = MARKDOWN_FILES - QMAKE_EXTRA_COMPILERS += Documentation + Documentation.target = test.pdf + Documentation.output = test.pdf + Documentation.commands = echo ' ' > test.pdf + Documentation.depends = '"$${MARKDOWN_FILES}"' + Documentation.input = MARKDOWN_FILES + QMAKE_EXTRA_COMPILERS += Documentation - INCLUDEPATH += \ - ../3rdParty/libpng \ - ../3rdParty/zlib + INCLUDEPATH += \ + ../3rdParty/libpng \ + ../3rdParty/zlib - SOURCES += \ - ../3rdParty/libpng/png.c \ - ../3rdParty/libpng/pngerror.c \ - ../3rdParty/libpng/pngget.c \ - ../3rdParty/libpng/pngmem.c \ - ../3rdParty/libpng/pngpread.c \ - ../3rdParty/libpng/pngread.c \ - ../3rdParty/libpng/pngrio.c \ - ../3rdParty/libpng/pngrtran.c \ - ../3rdParty/libpng/pngrutil.c \ - ../3rdParty/libpng/pngset.c \ - ../3rdParty/libpng/pngtrans.c \ - ../3rdParty/libpng/pngwio.c \ - ../3rdParty/libpng/pngwrite.c \ - ../3rdParty/libpng/pngwtran.c \ - ../3rdParty/libpng/pngwutil.c + SOURCES += \ + ../3rdParty/libpng/png.c \ + ../3rdParty/libpng/pngerror.c \ + ../3rdParty/libpng/pngget.c \ + ../3rdParty/libpng/pngmem.c \ + ../3rdParty/libpng/pngpread.c \ + ../3rdParty/libpng/pngread.c \ + ../3rdParty/libpng/pngrio.c \ + ../3rdParty/libpng/pngrtran.c \ + ../3rdParty/libpng/pngrutil.c \ + ../3rdParty/libpng/pngset.c \ + ../3rdParty/libpng/pngtrans.c \ + ../3rdParty/libpng/pngwio.c \ + ../3rdParty/libpng/pngwrite.c \ + ../3rdParty/libpng/pngwtran.c \ + ../3rdParty/libpng/pngwutil.c - SOURCES += \ - ../3rdParty/zlib/inftrees.c \ - ../3rdParty/zlib/trees.c \ - ../3rdParty/zlib/uncompr.c \ - ../3rdParty/zlib/zutil.c \ - ../3rdParty/zlib/adler32.c \ - ../3rdParty/zlib/compress.c \ - ../3rdParty/zlib/crc32.c \ - ../3rdParty/zlib/deflate.c \ - ../3rdParty/zlib/gzclose.c \ - ../3rdParty/zlib/gzlib.c \ - ../3rdParty/zlib/gzread.c \ - ../3rdParty/zlib/gzwrite.c \ - ../3rdParty/zlib/infback.c \ - ../3rdParty/zlib/inffast.c \ - ../3rdParty/zlib/inflate.c + SOURCES += \ + ../3rdParty/zlib/inftrees.c \ + ../3rdParty/zlib/trees.c \ + ../3rdParty/zlib/uncompr.c \ + ../3rdParty/zlib/zutil.c \ + ../3rdParty/zlib/adler32.c \ + ../3rdParty/zlib/compress.c \ + ../3rdParty/zlib/crc32.c \ + ../3rdParty/zlib/deflate.c \ + ../3rdParty/zlib/gzclose.c \ + ../3rdParty/zlib/gzlib.c \ + ../3rdParty/zlib/gzread.c \ + ../3rdParty/zlib/gzwrite.c \ + ../3rdParty/zlib/infback.c \ + ../3rdParty/zlib/inffast.c \ + ../3rdParty/zlib/inflate.c } +OTHER_FILES += \ + ../Website/about.html \ + ../Website/register.html \ + ../Website/support.html + diff --git a/Resources/forms/About.ui b/Resources/forms/About.ui index bd6bdf3..3265d89 100644 --- a/Resources/forms/About.ui +++ b/Resources/forms/About.ui @@ -152,7 +152,7 @@ QFrame::Plain - + 20 @@ -165,7 +165,7 @@ <html><head/><body><p><a href="http://url.to.application/"><span style=" text-decoration: underline; color:#0000ff;">http://url.to.application/</span></a></p></body></html> - + 360 @@ -175,16 +175,16 @@ - - - - :/images/images/logo.svg + AppIcon true + + Qt::AlignCenter + - + 20 @@ -193,11 +193,18 @@ 31 + + + 20 + 75 + true + + - <html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Wicked Docs</span></p></body></html> + AppName - + 20 @@ -207,7 +214,7 @@ - <html><head/><body><p>Version 1.0.0.0001</p></body></html> + AppVer @@ -337,7 +344,7 @@ - <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://blah/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements / LicensesEULA</span></a></p></body></html> + <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br/><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://sdfdsf/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements &amp; Licenses</span></a>&nbsp;&nbsp;<a href="http://sfsdf/"><span style=" text-decoration: underline; color:#0000ff;">EULA</span></a></p></body></html> label_5 @@ -346,9 +353,7 @@
- - - + okayButton diff --git a/Resources/forms/ExtensibleObjectModelUI.ui b/Resources/forms/ExtensibleObjectModelUI.ui index 4a794d4..c3fcbc4 100644 --- a/Resources/forms/ExtensibleObjectModelUI.ui +++ b/Resources/forms/ExtensibleObjectModelUI.ui @@ -250,7 +250,7 @@ 0 - + @@ -347,7 +347,7 @@ - + @@ -478,6 +478,16 @@ + + + + + 0 + 200 + + + + @@ -921,6 +931,14 @@ + + + QWebView + QWidget +
QWebView
+ 1 +
+
diff --git a/Resources/forms/LicenseUpgrade.ui b/Resources/forms/LicenseUpgrade.ui index 69b55ad..4ce2ac1 100644 --- a/Resources/forms/LicenseUpgrade.ui +++ b/Resources/forms/LicenseUpgrade.ui @@ -42,7 +42,7 @@ Upgrade license - + 290 diff --git a/Resources/forms/SendBugReport.ui b/Resources/forms/SendBugReport.ui index 1a7d910..70e177e 100644 --- a/Resources/forms/SendBugReport.ui +++ b/Resources/forms/SendBugReport.ui @@ -6,8 +6,8 @@ 0 0 - 489 - 420 + 525 + 421 @@ -17,49 +17,49 @@ - Software information + System information 15 - + - Version: + Application: - + unknown - + OS Platform: - + unknown - + - Date/Time: + Version: - + unknown @@ -79,74 +79,83 @@ - - - - - - - System information - - - - 15 - - - - - Include system info in report - - - true - - - - - - - RAM: - - - - - - - unknown - - - - + CPU: - + unknown - + Resolution: - + unknown + + + + RAM: + + + + + + + unknown + + + + + + + Date/Time: + + + + + + + unknown + + + + + + Short description: + + + + + + + + + + Short text description of problem + + + + Bug description: @@ -154,14 +163,18 @@ - + + + Detailed description of the issue, such as the type of issue, (eg an improvement, bug, crash, usability problem) and the steps needed to reproduce the problem. Add any notes that you think may be relevant. + + - Email address: + Email address (optional): @@ -238,7 +251,6 @@ desc email - sendSysInfo diff --git a/Util.h b/Util.h index 1dfc996..25da56e 100644 --- a/Util.h +++ b/Util.h @@ -12,7 +12,7 @@ { return std::unique_ptr( new T( std::forward(args)... ) ); } -}; +} inline int fopen_s(FILE** a_file, const char* a_fileName, const char* a_mode) { diff --git a/Version.cpp b/Version.cpp index fb913ae..86e6110 100644 --- a/Version.cpp +++ b/Version.cpp @@ -1,131 +1,2 @@ #include "Version.h" -#include "Util.h" -#include -#include -#include - -#ifdef __APPLE__ -# include "TargetConditionals.h" -#elif defined(_WIN32) -# include -#else -# include -# include -# include -# include -#endif - - -void getSystemInfo(SystemInfo& a_info) -{ - a_info.m_cpuType = "unknown"; - a_info.m_osType = "unknown"; - a_info.m_osVersion = "unknown"; - -#ifdef _WIN32 - a_info.m_osType = "Windows"; - - // Get RAM size - MEMORYSTATUSEX status; - status.dwLength = sizeof(status); - GlobalMemoryStatusEx(&status); - a_info.m_ramSize = status.ullTotalPhys; - - // Get OS version - const OSVERSIONINFO osver = winOsVersion(); - a_info.m_osVersion.reserve(512); - snprintf(a_info.m_osVersion.data(), "%i.%i.%i", osver.dwMajorVersion, osver.dwMinorVersion, osver.dwBuildNumber); - - // Get OS arch - SYSTEM_INFO info; - GetNativeSystemInfo(&info); -# ifdef _WIN64 - //if (info.wProcessorArchitecture == ???) - a_info.m_cpuType = "x86_64"; -# else - a_info.m_cpuType = "x86"; -# endif -#else - long pages = sysconf(_SC_PHYS_PAGES); - long page_size = sysconf(_SC_PAGE_SIZE); - a_info.m_ramSize = pages * page_size; - struct utsname u; - long ret = uname(&u); - if (ret != -1) - { - a_info.m_cpuType = u.machine; - a_info.m_osVersion = u.sysname + std::string(" ") + u.release; - } -# ifdef __APPLE__ - // Get RAM Size - int mib[2] = { CTL_HW, HW_MEMSIZE }; - size_t len = sizeof(uint64_t); - sysctl(mib, sizeof(mib) / sizeof(mib[0]), &u.ramSize, &len, NULL, 0); -# if TARGET_OS_IPHONE - a_info.m_osType = "iOS"; -# elif TARGET_OS_MAC - const char *macCodeName = ""; - switch (int(MacintoshVersion)) { - case MV_CHEETAH: macCodeName = " Cheetah"; break; - case MV_PUMA: macCodeName = " Puma"; break; - case MV_JAGUAR: macCodeName = " Jaguar"; break; - case MV_PANTHER: macCodeName = " Panther"; break; - case MV_TIGER: macCodeName = " Tiger"; break; - case MV_LEOPARD: macCodeName = " Leopard"; break; - case MV_SNOWLEOPARD: macCodeName = " Snow Leopard"; break; - case MV_LION: macCodeName = " Lion"; break; - case MV_MOUNTAINLION:macCodeName = " Mountain Lion"; break; - case MV_MAVERICKS: macCodeName = " Mavericks"; break; - case MV_YOSEMITE: macCodeName = " Yosemite"; break; - } - a_info.m_osType = "Mac OS X" + std::string(macCodeName); -# endif -# elif __ANDROID__ - a_info.m_osType = "Android"; -# elif __linux - // system("lsb_release -sd"); - FILE* f = fopen("/etc/lsb-release", "rt"); - char dist[64] = { 0 }; - if (f) { - char buf[128]; - while (fgets(buf, 128, f) != 0) - if (sscanf(buf, "DISTRIB_DESCRIPTION=%64c", dist) == 1) - break; - if (dist[0]) { - std::vector strBits = split(dist, '"'); - a_info.m_osType = strBits[(strBits.size()==3)?1:0]; - } else { - a_info.m_osType = "non-specific LSB"; - } - fclose(f); - } else { - a_info.m_osType = "non-LSB"; - } -# else - a_info.m_osType = "Generic UNIX"; -# endif -#endif - - // TODO: improve the CPU detection using libcpuid - - // Make human readable RAM size string - const char* humanUnitStrings[] = { " bytes", " KB", " MB", " GB", " TB" }; - int ramUnit = 0; - uint64_t ramSize = a_info.m_ramSize; - while (ramSize > 1024 && ramUnit < (YQ_ARRAY_SIZE(humanUnitStrings)-1)) - ramUnit++, ramSize /= 1000; - a_info.m_ramSizeStr = std::to_string(ramSize) + humanUnitStrings[ramUnit]; - - // Obtain the screen properties - QScreen *s = QApplication::screens()[0]; - int refreshRate = (s) ? s->refreshRate() : 0; - int depth = (s) ? s->depth() : 0; - a_info.m_resolutionWidth = (s) ? s->geometry().width() : 0; - a_info.m_resolutionHeight = (s) ? s->geometry().height() : 0; - a_info.m_resolutionStr = std::to_string(a_info.m_resolutionWidth) + "x" - + std::to_string(a_info.m_resolutionHeight) + " " - + std::to_string(depth) + "bit " - + "@" + std::to_string(refreshRate) + "Hz"; - ; -} diff --git a/Version.h b/Version.h index 5dd615c..143467f 100644 --- a/Version.h +++ b/Version.h @@ -7,26 +7,12 @@ #include +#define APP_NAME "Wicked Docs" +#define APP_ICON ":/images/images/logo.svg" #define APP_VERSION 1.00 #define APP_BUILD 0001 #define APP_VER_STR YQ_STRINGIZE(APP_VERSION) "." YQ_STRINGIZE(APP_BUILD) -#define APP_VER_STR_LONG "Version " YQ_STRINGIZE(APP_VERSION) ", Build" YQ_STRINGIZE(APP_BUILD) - - -struct SystemInfo -{ - std::string m_cpuType; - std::string m_osType; - std::string m_osVersion; - std::string m_ramSizeStr; // Human friendly string, eg: "4 GB" - std::string m_resolutionStr; - uint64_t m_ramSize; - uint32_t m_resolutionWidth; - uint32_t m_resolutionHeight; -}; - - -void getSystemInfo(SystemInfo& a_info); +#define APP_VER_STR_LONG "Version " YQ_STRINGIZE(APP_VERSION) ", Build " YQ_STRINGIZE(APP_BUILD) #endif // VERSION_H diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/MdiWindow.h b/MdiWindow.h index 76d7f1b..35ef9c3 100644 --- a/MdiWindow.h +++ b/MdiWindow.h @@ -4,78 +4,19 @@ #include #include +#include "Objects.h" +#include "MdiChild.h" -class MdiChild; class QAction; class QMenu; class QMdiArea; class QMdiSubWindow; class QSignalMapper; +class QTcpServer; class Ui_MainWindow; -class MdiChild : public QTextEdit -{ - Q_OBJECT -public: - MdiChild(); - ~MdiChild(); - - void newFile(); - bool loadFile(const QString &fileName); - bool save(); - bool saveAs(); - bool saveFile(const QString &fileName); - QString userFriendlyCurrentFile(); - QString currentFile() { return curFile; } - - void markdownSelection(const char* preText, const char* postText); - - void bold(); - void italic(); - void quote(); - void code(); - void heading1(); - void heading2(); - void heading3(); - void heading4(); - void hyperlink(); - void image(); - void unorderedList(); - void orderedList(); - void horizontalRule(); - void timestamp(); - void pageNumber(); - void pageCount(); - void del(); - void undo(); - void redo(); - void find(); - void findNext(); - void findPrevious(); - void goToLine(); - -signals: - void closing(); - void documentContentsChanged(); - -private slots: - void documentWasModified(); - -protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - -private: - bool maybeSave(); - void setCurrentFile(const QString &fileName); - QString strippedName(const QString &fullFileName); - - QString curFile; - bool isUntitled; -}; - - /* class MdiOptions { @@ -109,8 +50,12 @@ void save(); void saveAs(); + void handleRequest(); void updatePreview(); + void setWebPreviewURL(); + void refreshWebPreview(); + // Edit menu actions #ifndef QT_NO_CLIPBOARD void cut(); @@ -159,12 +104,26 @@ void switchLayoutDirection(); void setActiveSubWindow(QWidget *window); + void changeRootObject(const QModelIndex &index); + void changePropertiesObject(const QModelIndex &index); + + // Dialog events + void upgradeClicked(); + private: + void changeProjectTree(QObject *rootObject); + void updateObjectTree(QObject *rootObject); + void updatePropertiesView(QObject *object); + void setupServer(); void readSettings(); + void readLicense(); void writeSettings(); MdiChild *activeMdiChild(); QMdiSubWindow *findMdiChild(const QString &fileName); + //Solution solution; + QByteArray pdfContents; + QTcpServer *server; QMdiArea *mdiArea; QSignalMapper *windowMapper; Ui_MainWindow *appWindow; diff --git a/ObjectVisitor.h b/ObjectVisitor.h new file mode 100644 index 0000000..12cf25f --- /dev/null +++ b/ObjectVisitor.h @@ -0,0 +1,59 @@ +#ifndef OBJECTVISITOR_H +#define OBJECTVISITOR_H + + +#include +#include +#include +#include + + +class Visitor +{ +public: + Visitor() {} + virtual ~Visitor() {} + + virtual void enterObject(const char* className, const char* objectName) = 0; + virtual void leaveObject(const char* className, const char* objectName) = 0; + + // Reads or writes a property value + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) = 0; + + // By default, it is a reader, but implementing this enables a visitor that sets values + virtual bool isWriting() { return false; } +}; + + +void Visit(Visitor& visitor, QObject* object) +{ + std::string objectName = object->objectName().toLocal8Bit().data(); + if (objectName.size() <= 1) { + objectName = std::to_string((uint64_t)(void*)object); + } + visitor.enterObject(object->metaObject()->className(), objectName.c_str()); + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + if (visitor.isWriting()) { + QVariant value; + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + property.write(object, value); + + } else { + QVariant value = property.read(object); + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + } + } + for (int i = 0; i < object->children().count(); i++) + { + Visit(visitor, object->children()[i]); + } + visitor.leaveObject(object->metaObject()->className(), objectName.c_str()); +} + + +#endif // OBJECTVISITOR_H diff --git a/Objects.h b/Objects.h new file mode 100644 index 0000000..90e7bb1 --- /dev/null +++ b/Objects.h @@ -0,0 +1,167 @@ +#ifndef OBJECTS_H +#define OBJECTS_H + + +#include +#include +#include +#include +#include +#include +#include + + +class EnumEditor : public QWidget +{ + Q_OBJECT +public slots: + void ListSelectionChanged(); + void ComboSelectionChanged(); +public: + EnumEditor(QMetaEnum metaEnum); +private: + QListWidget* lw; + QComboBox* cb; + QSpinBox* sb; + QLabel* str; + QMetaEnum m_metaEnum; +}; + + +// Property Manager Supported types: +// int, bool, double, enums, flags +// QString, QDate, QTime, QDateTime, QKeySequence +// QChar, QLocale, QPoint, QPointF, QSize, QSizeF +// QRect, QRectF, QSizePolicy, QFont, QColor, QCursor + + +#define PROP_WRAP(type, name) \ + Q_PROPERTY(type name READ get##name WRITE set##name) \ + type get##name() const { return m_##name; } \ + void set##name(type val) { m_##name = val; } \ + type m_##name; + +#define CHILD_PTR_PROP_WRAP(type, name) \ + Q_PROPERTY(type* name READ get##name WRITE set##name) \ + type* get##name() const { return m_##name; } \ + void set##name(type* val) { \ + /* if (m_##name) children().removeAll((QObject*)m_##name); */ \ + val->setParent(this); \ + m_##name = val; \ + } \ + type* m_##name = nullptr; + + +class MyObjectTest : public QObject +{ + Q_OBJECT + Q_ENUMS(AnotherEnum) + Q_ENUMS(TestEnum) + Q_FLAGS(TestFlags) +public: + enum TestFlags { FlagValue1 = 1, AnotherFlagValue = 2, FlagEtc = 4, FlagBlah = 8 }; + enum TestEnum { EnumValue1, AnotherValue, Etc, Blah }; + enum AnotherEnum { AEnumValue1, AnAnotherValue, Etc2 }; + + explicit MyObjectTest() : QObject() { + m_An_Int_Value = 10; + m_A_Double = 11.0; + //m_An_Enum = EnumValue1; + //memset(this, 0, sizeof(MyObjectTest)); + } + ~MyObjectTest() { + } + + PROP_WRAP(int, An_Int_Value) + PROP_WRAP(bool, A_Bool) + PROP_WRAP(double, A_Double) + PROP_WRAP(TestEnum,An_Enum1) + PROP_WRAP(TestEnum,An_Enum2) + PROP_WRAP(QFlags,A_Flags) + PROP_WRAP(QString, A_String) + PROP_WRAP(QDate, A_Date) + PROP_WRAP(QTime, A_Time) + PROP_WRAP(QDateTime, A_Date_and_Time) + PROP_WRAP(QKeySequence, A_Key_Sequence) + PROP_WRAP(QChar, A_Char) + PROP_WRAP(QLocale, A_Locale) + PROP_WRAP(QPoint, A_Point) + PROP_WRAP(QPointF, A_PointF) + PROP_WRAP(QSize, A_Size) + PROP_WRAP(QSizeF, A_SizeF) + PROP_WRAP(QRect, A_Rect) + PROP_WRAP(QRectF, A_RectF) + //PROP_WRAP(QSizePolicy, A_SizePolicy) + //PROP_WRAP(QFont, A_Font) + PROP_WRAP(QColor, A_Color) + //PROP_WRAP(QCursor, A_Cursor) + // flags +}; + + + +class Template : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) + PROP_WRAP(QColor, Color) +}; + + +class Output : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + PROP_WRAP(QString, Title) + PROP_WRAP(QString, Filename) + PROP_WRAP(FileTypes, FileType) +}; + + +class Input : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) +}; + + +class Project : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + //PROP_WRAP(QString, Name) + PROP_WRAP(QString, Author) + //PROP_WRAP(Template*, Template) + //PROP_WRAP(QList, Inputs) + //PROP_WRAP(Output*, Output) + + //CHILD_PTR_PROP_WRAP(Output, Output) + //CHILD_PTR_PROP_WRAP(Template, Template) + + PROP_WRAP(QString, Title) + PROP_WRAP(QString, OutputFilename) + PROP_WRAP(FileTypes, OutputFileType) + + PROP_WRAP(QString, Template) + PROP_WRAP(QColor, Color) + + void AddInput(Input* in) { in->setParent(this); } +}; + + +class Solution : public QObject +{ + Q_OBJECT +public: + //PROP_WRAP(QList, Projects) + void AddProject(Project* proj) { proj->setParent(this); } +}; + + +#endif // OBJECTS_H diff --git a/QtProject/MakePDF.pro b/QtProject/MakePDF.pro index f4e410c..4026759 100644 --- a/QtProject/MakePDF.pro +++ b/QtProject/MakePDF.pro @@ -1,21 +1,24 @@ -QT += core gui widgets +# QT += webkitwidgets network widgets +CONFIG += qt +QT += core gui widgets webkitwidgets +#QT += svg CONFIG -= flat TARGET = MakePDF DEFINES += \ - GUI_APP=1 + GUI_APP=1 RESOURCES += \ - ../Resources/resources.qrc + ../Resources/resources.qrc FORMS += \ - ../Resources/forms/About.ui \ - ../Resources/forms/NewProjectWizard.ui \ - ../Resources/forms/ExtensibleObjectModelUI.ui \ - ../Resources/forms/SendBugReport.ui \ + ../Resources/forms/About.ui \ + ../Resources/forms/NewProjectWizard.ui \ + ../Resources/forms/ExtensibleObjectModelUI.ui \ + ../Resources/forms/SendBugReport.ui \ ../Resources/forms/Help.ui \ ../Resources/forms/CheckUpdates.ui \ ../Resources/forms/LicenseUpgrade.ui \ @@ -23,136 +26,174 @@ ../Resources/forms/PaletteEditor.ui INCLUDEPATH += \ - ../Framework \ - ../3rdParty/hoedown \ - ../3rdParty/libharu/include \ - ../3rdParty/TinyXML++ + ../Framework \ + ../3rdParty/hoedown \ + ../3rdParty/libharu/include \ + ../3rdParty/TinyXML++ \ + ../3rdParty/qtpropertybrowser/src HEADERS += \ - ../Framework/EventLog.h \ - ../Framework/Expected.h \ - ../Framework/Final.h \ - ../Framework/Finally.h \ - ../Framework/GenericTable.h \ - ../Framework/GenericTableUI.h \ - ../Framework/NonCopyable.h \ - ../Framework/Utilities.h \ + ../Framework/EventLog.h \ + ../Framework/Expected.h \ + ../Framework/Final.h \ + ../Framework/Finally.h \ + ../Framework/GenericTable.h \ + ../Framework/GenericTableUI.h \ + ../Framework/NonCopyable.h \ + ../Framework/Utilities.h \ + ../Framework/SystemInfomation.h \ + ../Framework/Array.h \ + ../Framework/Macros.h \ + ../Framework/ObjectTreeModel.h \ + ../Version.h \ + ../Util.h \ ../ui.h \ + ../MdiChild.h \ ../MdiWindow.h \ ../ColorPicker.h \ - ../Version.h + ../DocConvert.h \ + ../Objects.h \ + ../ObjectVisitor.h HEADERS += \ - ../DocOutput.h \ - ../DocProject.h \ - ../DocStyle.h \ - ../DocTemplate.h \ - ../DocVisitor.h \ - ../DocSVG.h + ../DocOutput.h \ + ../DocProject.h \ + ../DocStyle.h \ + ../DocTemplate.h \ + ../DocVisitor.h \ + ../DocSVG.h SOURCES += \ - ../Framework/Tests.cpp \ - ../Framework/Utilities.cpp \ - ../Framework/EventLog.cpp \ + ../Framework/Tests.cpp \ + ../Framework/Utilities.cpp \ + ../Framework/EventLog.cpp \ + ../MdiChild.cpp \ ../MdiWindow.cpp \ ../ColorPicker.cpp \ - ../Version.cpp + ../Version.cpp \ + ../Framework/SystemInfomation.cpp \ + ../DocConvert.cpp \ + ../Framework/ObjectTreeModel.cpp SOURCES += \ - ../DocOutput.cpp \ - ../DocProject.cpp \ - ../DocStyle.cpp \ - ../DocTemplate.cpp \ - ../DocVisitor.cpp \ - ../DocSVG.cpp \ - ../main.cpp + ../DocOutput.cpp \ + ../DocProject.cpp \ + ../DocStyle.cpp \ + ../DocTemplate.cpp \ + ../DocVisitor.cpp \ + ../DocSVG.cpp \ + ../main.cpp SOURCES += \ - ../3rdParty/hoedown/autolink.c \ - ../3rdParty/hoedown/buffer.c \ - ../3rdParty/hoedown/document.c \ - ../3rdParty/hoedown/escape.c \ - ../3rdParty/hoedown/html.c \ - ../3rdParty/hoedown/html_blocks.c \ - ../3rdParty/hoedown/stack.c + ../3rdParty/hoedown/autolink.c \ + ../3rdParty/hoedown/buffer.c \ + ../3rdParty/hoedown/document.c \ + ../3rdParty/hoedown/escape.c \ + ../3rdParty/hoedown/html.c \ + ../3rdParty/hoedown/html_blocks.c \ + ../3rdParty/hoedown/stack.c SOURCES += \ - ../3rdParty/libharu/src/hpdf_3dmeasure.c \ - ../3rdParty/libharu/src/hpdf_annotation.c \ - ../3rdParty/libharu/src/hpdf_array.c \ - ../3rdParty/libharu/src/hpdf_binary.c \ - ../3rdParty/libharu/src/hpdf_boolean.c \ - ../3rdParty/libharu/src/hpdf_catalog.c \ - ../3rdParty/libharu/src/hpdf_destination.c \ - ../3rdParty/libharu/src/hpdf_dict.c \ - ../3rdParty/libharu/src/hpdf_doc.c \ - ../3rdParty/libharu/src/hpdf_doc_png.c \ - ../3rdParty/libharu/src/hpdf_encoder.c \ - ../3rdParty/libharu/src/hpdf_encoder_utf.c \ - ../3rdParty/libharu/src/hpdf_encrypt.c \ - ../3rdParty/libharu/src/hpdf_encryptdict.c \ - ../3rdParty/libharu/src/hpdf_error.c \ - ../3rdParty/libharu/src/hpdf_exdata.c \ - ../3rdParty/libharu/src/hpdf_ext_gstate.c \ - ../3rdParty/libharu/src/hpdf_font.c \ - ../3rdParty/libharu/src/hpdf_fontdef.c \ - ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ - ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ - ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ - ../3rdParty/libharu/src/hpdf_font_cid.c \ - ../3rdParty/libharu/src/hpdf_font_tt.c \ - ../3rdParty/libharu/src/hpdf_font_type1.c \ - ../3rdParty/libharu/src/hpdf_gstate.c \ - ../3rdParty/libharu/src/hpdf_image.c \ - ../3rdParty/libharu/src/hpdf_image_png.c \ - ../3rdParty/libharu/src/hpdf_info.c \ - ../3rdParty/libharu/src/hpdf_list.c \ - ../3rdParty/libharu/src/hpdf_mmgr.c \ - ../3rdParty/libharu/src/hpdf_name.c \ - ../3rdParty/libharu/src/hpdf_namedict.c \ - ../3rdParty/libharu/src/hpdf_null.c \ - ../3rdParty/libharu/src/hpdf_number.c \ - ../3rdParty/libharu/src/hpdf_objects.c \ - ../3rdParty/libharu/src/hpdf_outline.c \ - ../3rdParty/libharu/src/hpdf_pages.c \ - ../3rdParty/libharu/src/hpdf_page_label.c \ - ../3rdParty/libharu/src/hpdf_page_operator.c \ - ../3rdParty/libharu/src/hpdf_pdfa.c \ - ../3rdParty/libharu/src/hpdf_real.c \ - ../3rdParty/libharu/src/hpdf_streams.c \ - ../3rdParty/libharu/src/hpdf_string.c \ - ../3rdParty/libharu/src/hpdf_u3d.c \ - ../3rdParty/libharu/src/hpdf_utils.c \ - ../3rdParty/libharu/src/hpdf_xref.c + ../3rdParty/libharu/src/hpdf_3dmeasure.c \ + ../3rdParty/libharu/src/hpdf_annotation.c \ + ../3rdParty/libharu/src/hpdf_array.c \ + ../3rdParty/libharu/src/hpdf_binary.c \ + ../3rdParty/libharu/src/hpdf_boolean.c \ + ../3rdParty/libharu/src/hpdf_catalog.c \ + ../3rdParty/libharu/src/hpdf_destination.c \ + ../3rdParty/libharu/src/hpdf_dict.c \ + ../3rdParty/libharu/src/hpdf_doc.c \ + ../3rdParty/libharu/src/hpdf_doc_png.c \ + ../3rdParty/libharu/src/hpdf_encoder.c \ + ../3rdParty/libharu/src/hpdf_encoder_utf.c \ + ../3rdParty/libharu/src/hpdf_encrypt.c \ + ../3rdParty/libharu/src/hpdf_encryptdict.c \ + ../3rdParty/libharu/src/hpdf_error.c \ + ../3rdParty/libharu/src/hpdf_exdata.c \ + ../3rdParty/libharu/src/hpdf_ext_gstate.c \ + ../3rdParty/libharu/src/hpdf_font.c \ + ../3rdParty/libharu/src/hpdf_fontdef.c \ + ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ + ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ + ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ + ../3rdParty/libharu/src/hpdf_font_cid.c \ + ../3rdParty/libharu/src/hpdf_font_tt.c \ + ../3rdParty/libharu/src/hpdf_font_type1.c \ + ../3rdParty/libharu/src/hpdf_gstate.c \ + ../3rdParty/libharu/src/hpdf_image.c \ + ../3rdParty/libharu/src/hpdf_image_png.c \ + ../3rdParty/libharu/src/hpdf_info.c \ + ../3rdParty/libharu/src/hpdf_list.c \ + ../3rdParty/libharu/src/hpdf_mmgr.c \ + ../3rdParty/libharu/src/hpdf_name.c \ + ../3rdParty/libharu/src/hpdf_namedict.c \ + ../3rdParty/libharu/src/hpdf_null.c \ + ../3rdParty/libharu/src/hpdf_number.c \ + ../3rdParty/libharu/src/hpdf_objects.c \ + ../3rdParty/libharu/src/hpdf_outline.c \ + ../3rdParty/libharu/src/hpdf_pages.c \ + ../3rdParty/libharu/src/hpdf_page_label.c \ + ../3rdParty/libharu/src/hpdf_page_operator.c \ + ../3rdParty/libharu/src/hpdf_pdfa.c \ + ../3rdParty/libharu/src/hpdf_real.c \ + ../3rdParty/libharu/src/hpdf_streams.c \ + ../3rdParty/libharu/src/hpdf_string.c \ + ../3rdParty/libharu/src/hpdf_u3d.c \ + ../3rdParty/libharu/src/hpdf_utils.c \ + ../3rdParty/libharu/src/hpdf_xref.c SOURCES += \ - ../3rdParty/TinyXML++/ticpp.cpp \ - ../3rdParty/TinyXML++/tinystr.cpp \ - ../3rdParty/TinyXML++/tinyxml.cpp \ - ../3rdParty/TinyXML++/tinyxmlerror.cpp \ - ../3rdParty/TinyXML++/tinyxmlparser.cpp + ../3rdParty/TinyXML++/ticpp.cpp \ + ../3rdParty/TinyXML++/tinystr.cpp \ + ../3rdParty/TinyXML++/tinyxml.cpp \ + ../3rdParty/TinyXML++/tinyxmlerror.cpp \ + ../3rdParty/TinyXML++/tinyxmlparser.cpp + + +SOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.cpp \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.cpp \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.cpp \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils.cpp + +HEADERS += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.h \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.h \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.h \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils_p.h + +RESOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.qrc # As a note to what was removed REMOVED_SOURCES = \ - ../3rdParty/hoedown/html_smartypants.c \ - ../3rdParty/hoedown/version.c \ - ../3rdParty/libharu/src/hpdf_image_ccitt.c + ../3rdParty/hoedown/html_smartypants.c \ + ../3rdParty/hoedown/version.c \ + ../3rdParty/libharu/src/hpdf_image_ccitt.c # Linux specific settings unix { - QMAKE_CXXFLAGS += --std=gnu++11 - # QMAKE_CXXFLAGS -= -Wall - QMAKE_CXXFLAGS_WARN_ON=-w - QMAKE_CFLAGS_WARN_ON=-w - LIBS += -lpng -lz + QMAKE_CXXFLAGS += --std=gnu++11 + # QMAKE_CXXFLAGS -= -Wall + QMAKE_CXXFLAGS_WARN_ON=-w + QMAKE_CFLAGS_WARN_ON=-w + LIBS += -lpng -lz } @@ -160,77 +201,82 @@ # Windows specific. Note we compile in libpng and zlib statically on Windows win32 { - # Supress annoying warnings - QMAKE_CXXFLAGS += /wd"4996;4100" - QMAKE_CXXFLAGS_WARN_ON -= -w34100 + # Supress annoying warnings + QMAKE_CXXFLAGS += /wd"4996;4100" + QMAKE_CXXFLAGS_WARN_ON -= -w34100 - # Release mode debugging - QMAKE_CXXFLAGS += /Zi - QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF + # Release mode debugging + QMAKE_CXXFLAGS += /Zi + QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF - # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything - Project.target = $${TARGET}.vcxproj - Project.output = $${TARGET}.vcxproj - Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 - Project.depends = '"$${_PRO_FILE_}"' - Project.input = _PRO_FILE_ - QMAKE_EXTRA_COMPILERS += Project + # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything + Project.target = $${TARGET}.vcxproj + Project.output = $${TARGET}.vcxproj + Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 + Project.depends = '"$${_PRO_FILE_}"' + Project.input = _PRO_FILE_ + QMAKE_EXTRA_COMPILERS += Project - # This makes the documentation - MARKDOWN_FILES = \ - test.md \ - test2.md + # This makes the documentation + MARKDOWN_FILES = \ + test.md \ + test2.md - Documentation.target = test.pdf - Documentation.output = test.pdf - Documentation.commands = echo ' ' > test.pdf - Documentation.depends = '"$${MARKDOWN_FILES}"' - Documentation.input = MARKDOWN_FILES - QMAKE_EXTRA_COMPILERS += Documentation + Documentation.target = test.pdf + Documentation.output = test.pdf + Documentation.commands = echo ' ' > test.pdf + Documentation.depends = '"$${MARKDOWN_FILES}"' + Documentation.input = MARKDOWN_FILES + QMAKE_EXTRA_COMPILERS += Documentation - INCLUDEPATH += \ - ../3rdParty/libpng \ - ../3rdParty/zlib + INCLUDEPATH += \ + ../3rdParty/libpng \ + ../3rdParty/zlib - SOURCES += \ - ../3rdParty/libpng/png.c \ - ../3rdParty/libpng/pngerror.c \ - ../3rdParty/libpng/pngget.c \ - ../3rdParty/libpng/pngmem.c \ - ../3rdParty/libpng/pngpread.c \ - ../3rdParty/libpng/pngread.c \ - ../3rdParty/libpng/pngrio.c \ - ../3rdParty/libpng/pngrtran.c \ - ../3rdParty/libpng/pngrutil.c \ - ../3rdParty/libpng/pngset.c \ - ../3rdParty/libpng/pngtrans.c \ - ../3rdParty/libpng/pngwio.c \ - ../3rdParty/libpng/pngwrite.c \ - ../3rdParty/libpng/pngwtran.c \ - ../3rdParty/libpng/pngwutil.c + SOURCES += \ + ../3rdParty/libpng/png.c \ + ../3rdParty/libpng/pngerror.c \ + ../3rdParty/libpng/pngget.c \ + ../3rdParty/libpng/pngmem.c \ + ../3rdParty/libpng/pngpread.c \ + ../3rdParty/libpng/pngread.c \ + ../3rdParty/libpng/pngrio.c \ + ../3rdParty/libpng/pngrtran.c \ + ../3rdParty/libpng/pngrutil.c \ + ../3rdParty/libpng/pngset.c \ + ../3rdParty/libpng/pngtrans.c \ + ../3rdParty/libpng/pngwio.c \ + ../3rdParty/libpng/pngwrite.c \ + ../3rdParty/libpng/pngwtran.c \ + ../3rdParty/libpng/pngwutil.c - SOURCES += \ - ../3rdParty/zlib/inftrees.c \ - ../3rdParty/zlib/trees.c \ - ../3rdParty/zlib/uncompr.c \ - ../3rdParty/zlib/zutil.c \ - ../3rdParty/zlib/adler32.c \ - ../3rdParty/zlib/compress.c \ - ../3rdParty/zlib/crc32.c \ - ../3rdParty/zlib/deflate.c \ - ../3rdParty/zlib/gzclose.c \ - ../3rdParty/zlib/gzlib.c \ - ../3rdParty/zlib/gzread.c \ - ../3rdParty/zlib/gzwrite.c \ - ../3rdParty/zlib/infback.c \ - ../3rdParty/zlib/inffast.c \ - ../3rdParty/zlib/inflate.c + SOURCES += \ + ../3rdParty/zlib/inftrees.c \ + ../3rdParty/zlib/trees.c \ + ../3rdParty/zlib/uncompr.c \ + ../3rdParty/zlib/zutil.c \ + ../3rdParty/zlib/adler32.c \ + ../3rdParty/zlib/compress.c \ + ../3rdParty/zlib/crc32.c \ + ../3rdParty/zlib/deflate.c \ + ../3rdParty/zlib/gzclose.c \ + ../3rdParty/zlib/gzlib.c \ + ../3rdParty/zlib/gzread.c \ + ../3rdParty/zlib/gzwrite.c \ + ../3rdParty/zlib/infback.c \ + ../3rdParty/zlib/inffast.c \ + ../3rdParty/zlib/inflate.c } +OTHER_FILES += \ + ../Website/about.html \ + ../Website/register.html \ + ../Website/support.html + diff --git a/Resources/forms/About.ui b/Resources/forms/About.ui index bd6bdf3..3265d89 100644 --- a/Resources/forms/About.ui +++ b/Resources/forms/About.ui @@ -152,7 +152,7 @@ QFrame::Plain - + 20 @@ -165,7 +165,7 @@ <html><head/><body><p><a href="http://url.to.application/"><span style=" text-decoration: underline; color:#0000ff;">http://url.to.application/</span></a></p></body></html> - + 360 @@ -175,16 +175,16 @@ - - - - :/images/images/logo.svg + AppIcon true + + Qt::AlignCenter + - + 20 @@ -193,11 +193,18 @@ 31 + + + 20 + 75 + true + + - <html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Wicked Docs</span></p></body></html> + AppName - + 20 @@ -207,7 +214,7 @@ - <html><head/><body><p>Version 1.0.0.0001</p></body></html> + AppVer @@ -337,7 +344,7 @@ - <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://blah/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements / LicensesEULA</span></a></p></body></html> + <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br/><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://sdfdsf/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements &amp; Licenses</span></a>&nbsp;&nbsp;<a href="http://sfsdf/"><span style=" text-decoration: underline; color:#0000ff;">EULA</span></a></p></body></html> label_5 @@ -346,9 +353,7 @@
- - - + okayButton diff --git a/Resources/forms/ExtensibleObjectModelUI.ui b/Resources/forms/ExtensibleObjectModelUI.ui index 4a794d4..c3fcbc4 100644 --- a/Resources/forms/ExtensibleObjectModelUI.ui +++ b/Resources/forms/ExtensibleObjectModelUI.ui @@ -250,7 +250,7 @@ 0 - + @@ -347,7 +347,7 @@ - + @@ -478,6 +478,16 @@ + + + + + 0 + 200 + + + + @@ -921,6 +931,14 @@ + + + QWebView + QWidget +
QWebView
+ 1 +
+
diff --git a/Resources/forms/LicenseUpgrade.ui b/Resources/forms/LicenseUpgrade.ui index 69b55ad..4ce2ac1 100644 --- a/Resources/forms/LicenseUpgrade.ui +++ b/Resources/forms/LicenseUpgrade.ui @@ -42,7 +42,7 @@ Upgrade license - + 290 diff --git a/Resources/forms/SendBugReport.ui b/Resources/forms/SendBugReport.ui index 1a7d910..70e177e 100644 --- a/Resources/forms/SendBugReport.ui +++ b/Resources/forms/SendBugReport.ui @@ -6,8 +6,8 @@ 0 0 - 489 - 420 + 525 + 421 @@ -17,49 +17,49 @@ - Software information + System information 15 - + - Version: + Application: - + unknown - + OS Platform: - + unknown - + - Date/Time: + Version: - + unknown @@ -79,74 +79,83 @@ - - - - - - - System information - - - - 15 - - - - - Include system info in report - - - true - - - - - - - RAM: - - - - - - - unknown - - - - + CPU: - + unknown - + Resolution: - + unknown + + + + RAM: + + + + + + + unknown + + + + + + + Date/Time: + + + + + + + unknown + + + + + + Short description: + + + + + + + + + + Short text description of problem + + + + Bug description: @@ -154,14 +163,18 @@ - + + + Detailed description of the issue, such as the type of issue, (eg an improvement, bug, crash, usability problem) and the steps needed to reproduce the problem. Add any notes that you think may be relevant. + + - Email address: + Email address (optional): @@ -238,7 +251,6 @@ desc email - sendSysInfo diff --git a/Util.h b/Util.h index 1dfc996..25da56e 100644 --- a/Util.h +++ b/Util.h @@ -12,7 +12,7 @@ { return std::unique_ptr( new T( std::forward(args)... ) ); } -}; +} inline int fopen_s(FILE** a_file, const char* a_fileName, const char* a_mode) { diff --git a/Version.cpp b/Version.cpp index fb913ae..86e6110 100644 --- a/Version.cpp +++ b/Version.cpp @@ -1,131 +1,2 @@ #include "Version.h" -#include "Util.h" -#include -#include -#include - -#ifdef __APPLE__ -# include "TargetConditionals.h" -#elif defined(_WIN32) -# include -#else -# include -# include -# include -# include -#endif - - -void getSystemInfo(SystemInfo& a_info) -{ - a_info.m_cpuType = "unknown"; - a_info.m_osType = "unknown"; - a_info.m_osVersion = "unknown"; - -#ifdef _WIN32 - a_info.m_osType = "Windows"; - - // Get RAM size - MEMORYSTATUSEX status; - status.dwLength = sizeof(status); - GlobalMemoryStatusEx(&status); - a_info.m_ramSize = status.ullTotalPhys; - - // Get OS version - const OSVERSIONINFO osver = winOsVersion(); - a_info.m_osVersion.reserve(512); - snprintf(a_info.m_osVersion.data(), "%i.%i.%i", osver.dwMajorVersion, osver.dwMinorVersion, osver.dwBuildNumber); - - // Get OS arch - SYSTEM_INFO info; - GetNativeSystemInfo(&info); -# ifdef _WIN64 - //if (info.wProcessorArchitecture == ???) - a_info.m_cpuType = "x86_64"; -# else - a_info.m_cpuType = "x86"; -# endif -#else - long pages = sysconf(_SC_PHYS_PAGES); - long page_size = sysconf(_SC_PAGE_SIZE); - a_info.m_ramSize = pages * page_size; - struct utsname u; - long ret = uname(&u); - if (ret != -1) - { - a_info.m_cpuType = u.machine; - a_info.m_osVersion = u.sysname + std::string(" ") + u.release; - } -# ifdef __APPLE__ - // Get RAM Size - int mib[2] = { CTL_HW, HW_MEMSIZE }; - size_t len = sizeof(uint64_t); - sysctl(mib, sizeof(mib) / sizeof(mib[0]), &u.ramSize, &len, NULL, 0); -# if TARGET_OS_IPHONE - a_info.m_osType = "iOS"; -# elif TARGET_OS_MAC - const char *macCodeName = ""; - switch (int(MacintoshVersion)) { - case MV_CHEETAH: macCodeName = " Cheetah"; break; - case MV_PUMA: macCodeName = " Puma"; break; - case MV_JAGUAR: macCodeName = " Jaguar"; break; - case MV_PANTHER: macCodeName = " Panther"; break; - case MV_TIGER: macCodeName = " Tiger"; break; - case MV_LEOPARD: macCodeName = " Leopard"; break; - case MV_SNOWLEOPARD: macCodeName = " Snow Leopard"; break; - case MV_LION: macCodeName = " Lion"; break; - case MV_MOUNTAINLION:macCodeName = " Mountain Lion"; break; - case MV_MAVERICKS: macCodeName = " Mavericks"; break; - case MV_YOSEMITE: macCodeName = " Yosemite"; break; - } - a_info.m_osType = "Mac OS X" + std::string(macCodeName); -# endif -# elif __ANDROID__ - a_info.m_osType = "Android"; -# elif __linux - // system("lsb_release -sd"); - FILE* f = fopen("/etc/lsb-release", "rt"); - char dist[64] = { 0 }; - if (f) { - char buf[128]; - while (fgets(buf, 128, f) != 0) - if (sscanf(buf, "DISTRIB_DESCRIPTION=%64c", dist) == 1) - break; - if (dist[0]) { - std::vector strBits = split(dist, '"'); - a_info.m_osType = strBits[(strBits.size()==3)?1:0]; - } else { - a_info.m_osType = "non-specific LSB"; - } - fclose(f); - } else { - a_info.m_osType = "non-LSB"; - } -# else - a_info.m_osType = "Generic UNIX"; -# endif -#endif - - // TODO: improve the CPU detection using libcpuid - - // Make human readable RAM size string - const char* humanUnitStrings[] = { " bytes", " KB", " MB", " GB", " TB" }; - int ramUnit = 0; - uint64_t ramSize = a_info.m_ramSize; - while (ramSize > 1024 && ramUnit < (YQ_ARRAY_SIZE(humanUnitStrings)-1)) - ramUnit++, ramSize /= 1000; - a_info.m_ramSizeStr = std::to_string(ramSize) + humanUnitStrings[ramUnit]; - - // Obtain the screen properties - QScreen *s = QApplication::screens()[0]; - int refreshRate = (s) ? s->refreshRate() : 0; - int depth = (s) ? s->depth() : 0; - a_info.m_resolutionWidth = (s) ? s->geometry().width() : 0; - a_info.m_resolutionHeight = (s) ? s->geometry().height() : 0; - a_info.m_resolutionStr = std::to_string(a_info.m_resolutionWidth) + "x" - + std::to_string(a_info.m_resolutionHeight) + " " - + std::to_string(depth) + "bit " - + "@" + std::to_string(refreshRate) + "Hz"; - ; -} diff --git a/Version.h b/Version.h index 5dd615c..143467f 100644 --- a/Version.h +++ b/Version.h @@ -7,26 +7,12 @@ #include +#define APP_NAME "Wicked Docs" +#define APP_ICON ":/images/images/logo.svg" #define APP_VERSION 1.00 #define APP_BUILD 0001 #define APP_VER_STR YQ_STRINGIZE(APP_VERSION) "." YQ_STRINGIZE(APP_BUILD) -#define APP_VER_STR_LONG "Version " YQ_STRINGIZE(APP_VERSION) ", Build" YQ_STRINGIZE(APP_BUILD) - - -struct SystemInfo -{ - std::string m_cpuType; - std::string m_osType; - std::string m_osVersion; - std::string m_ramSizeStr; // Human friendly string, eg: "4 GB" - std::string m_resolutionStr; - uint64_t m_ramSize; - uint32_t m_resolutionWidth; - uint32_t m_resolutionHeight; -}; - - -void getSystemInfo(SystemInfo& a_info); +#define APP_VER_STR_LONG "Version " YQ_STRINGIZE(APP_VERSION) ", Build " YQ_STRINGIZE(APP_BUILD) #endif // VERSION_H diff --git a/main.cpp b/main.cpp index a4a0bd4..372f0bf 100644 --- a/main.cpp +++ b/main.cpp @@ -1,198 +1,17 @@ -// MakePDF.cpp : Defines the entry point for the console application. -// - -#define _CRT_SECURE_NO_WARNINGS -#include -#include -#include -#include - -#include "DocVisitor.h" -#include "DocTemplate.h" -#include "DocOutput.h" -#include "DocSVG.h" -#include "Util.h" - -//#include "document.h" -#include "html.h" -#include "tinyxml.h" - - -#ifndef _WIN32 -# include -//# define __cdecl -#else - extern "C" void __stdcall Sleep(unsigned int); -#endif - - #ifdef GUI_APP # include "ui.h" +#else +# include "DocConvert.h" #endif -#define DEF_IUNIT 1024 -#define DEF_OUNIT 64 -#define DEF_MAX_NESTING 16 - - extern void runTests(); -struct Context -{ - const char* title; - const char* inFileName; - const char* outFileName_PDF; - const char* outFileName_HTML; - DocOutputDevice* doc; - hoedown_buffer *inputBuffer; - hoedown_buffer *outputBuffer; -}; - - -static void RemoveFile(const char* fileName) -{ -#ifdef _WIN32 - FILE* tmpF = 0; - bool first = true; - do - { - fopen_s(&tmpF, fileName, "rb"); - if (tmpF) - { - fclose(tmpF); - _unlink(fileName); - ::Sleep(100); - if (first) - printf("waiting for output file to be removed."); - else - printf("."); - first = false; - fflush(stdout); - } - } while (tmpF != 0); -#else - unlink(fileName); -#endif -} - - -hoedown_buffer *ReadInWholeFile(const char* inputFileName) -{ - // Read in the markdown file - FILE* f = 0; - fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? - if (!f) - return 0; - /* - fseek(f, 0L, SEEK_END); - long fileSize = ftell(f); - fseek(f, 0L, SEEK_SET); - uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); - size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); - */ - hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); - if (hoedown_buffer_putf(ib, f)) - fprintf(stderr, "I/O errors found while reading input.\n"); - - fclose(f); - return ib; -} - - -hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) -{ - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); - hoedown_document_render(document, ob, inputBuffer, inputBufferSize); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - return ob; -} - - -void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) -{ - hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); - if (!inputBuffer) - return; - // SVG xml parse - TiXmlDocument parser; - parser.Parse((char*)inputBuffer->data); - DocSVG visitor(scale); - parser.Accept(&visitor); - visitor.DumpOperations(); - visitor.WriteTo(outputDoc); - hoedown_buffer_free(inputBuffer); -} - - -void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) -{ - // xml parse - DocStyle style; - DocTemplate templ; - TiXmlDocument parser; - - templ.ReadTemplateFile("test.tmpl"); - parser.Parse((char*)inputBuffer); - DocVisitor visitor(outputDoc, &style, &templ); - parser.Accept(&visitor); - - //SVGTest("test/triangle.svg", 0.02, outputDoc); - //SVGTest("test/ArcTest.svg", 1.0, outputDoc); -} - - -void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) -{ - RemoveFile(fileName); - FILE* f = 0; - fopen_s(&f, fileName, "wb"); - if (!f) - return; - const char *CSSText = "test"; - fwrite(CSSText, 1, strlen(CSSText), f); - fwrite(data, 1, dataSize, f); - fclose(f); -} - - -int ProcessConversionContext(Context* context) -{ - context->inputBuffer = ReadInWholeFile(context->inFileName); - if (!context->inputBuffer) - return -1; - context->outputBuffer = ConvertMarkdownToHTML(context->inputBuffer->data, context->inputBuffer->size); - //free(inputBuffer); - hoedown_buffer_free(context->inputBuffer); - ConvertHTMLToPDF(context->outputBuffer->data, context->doc); - SaveHTML(context->outFileName_HTML, context->outputBuffer->data, context->outputBuffer->size); - hoedown_buffer_free(context->outputBuffer); - RemoveFile(context->outFileName_PDF); - context->doc->finalize(context->outFileName_PDF); - return 0; -} - - int main(int argc, char* argv[]) { - DocOutputDevice outputDoc; - Context context = { - "Test Markdown to PDF", - "test/test.md", - "test/test.pdf", - "test/test.html", - &outputDoc - }; - ProcessConversionContext(&context); - /* // Qt MDI Example does this: - Q_INIT_RESOURCE(mdi); QApplication app(argc, argv); QCoreApplication::setApplicationVersion(QT_VERSION_STR); @@ -217,9 +36,14 @@ //YQ_LOG_DEBUG("This is a test message"); //runTests(); app.exec(); +#else + DocConvert convertor; + convertor.SetTitle("Test Markdown to PDF"); + convertor.SetSource("test/test.md"); + convertor.OutputHTML("test/test.html"); + convertor.OutputPDF("test/test.pdf"); #endif - /* fprintf(stderr, "HERE!\n\n\n"); QApplication app2(argc, argv); @@ -229,7 +53,6 @@ app2.exec(); */ - return 0; } diff --git a/DocConvert.cpp b/DocConvert.cpp new file mode 100644 index 0000000..36938f5 --- /dev/null +++ b/DocConvert.cpp @@ -0,0 +1,223 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#include "DocConvert.h" +#include "DocVisitor.h" +#include "DocTemplate.h" +#include "DocOutput.h" +#include "DocSVG.h" +#include "Util.h" + +#include "html.h" +#include "tinyxml.h" + +#ifndef _WIN32 +# include +#else + extern "C" void __stdcall Sleep(unsigned int); +#endif + + +#define DEF_IUNIT 1024 +#define DEF_OUNIT 64 +#define DEF_MAX_NESTING 16 + + +static void RemoveFile(const char* fileName) +{ +#ifdef _WIN32 + FILE* tmpF = 0; + bool first = true; + do + { + fopen_s(&tmpF, fileName, "rb"); + if (tmpF) + { + fclose(tmpF); + _unlink(fileName); + ::Sleep(100); + if (first) + printf("waiting for output file to be removed."); + else + printf("."); + first = false; + fflush(stdout); + } + } while (tmpF != 0); +#else + unlink(fileName); +#endif +} + + +/* +fseek(f, 0L, SEEK_END); +long fileSize = ftell(f); +fseek(f, 0L, SEEK_SET); +uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); +size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); +*/ + + +hoedown_buffer *ReadInWholeFile(const char* inputFileName) +{ + // Read in the markdown file + FILE* f = 0; + fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? + if (!f) + return 0; + hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); + if (hoedown_buffer_putf(ib, f)) + fprintf(stderr, "I/O errors found while reading input.\n"); + fclose(f); + return ib; +} + + +hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) +{ + hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); + hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); + hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); + hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); + hoedown_document_render(document, ob, inputBuffer, inputBufferSize); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return ob; +} + + +void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) +{ + hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); + if (!inputBuffer) + return; + // SVG xml parse + TiXmlDocument parser; + parser.Parse((char*)inputBuffer->data); + DocSVG visitor(scale); + parser.Accept(&visitor); + visitor.DumpOperations(); + visitor.WriteTo(outputDoc); + hoedown_buffer_free(inputBuffer); +} + + +void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) +{ + // xml parse + DocStyle style; + DocTemplate templ; + TiXmlDocument parser; + + templ.ReadTemplateFile("test.tmpl"); + parser.Parse((char*)inputBuffer); + DocVisitor visitor(outputDoc, &style, &templ); + parser.Accept(&visitor); + + //SVGTest("test/triangle.svg", 0.02, outputDoc); + //SVGTest("test/ArcTest.svg", 1.0, outputDoc); +} + + +void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) +{ + RemoveFile(fileName); + FILE* f = 0; + fopen_s(&f, fileName, "wb"); + if (!f) + return; + const char *CSSText = "test"; + fwrite(CSSText, 1, strlen(CSSText), f); + fwrite(data, 1, dataSize, f); + fclose(f); +} + + +struct DocConvert::Pimpl +{ + ~Pimpl() { + if (inputBuffer) + hoedown_buffer_free(inputBuffer); + if (outputBuffer) + hoedown_buffer_free(outputBuffer); + } + DocOutputDevice doc; + hoedown_buffer *inputBuffer; + hoedown_buffer *outputBuffer; + std::string m_title; +}; + + +DocConvert::DocConvert() : m_pimpl(std::make_unique()) +{ + m_pimpl->inputBuffer = 0; + m_pimpl->outputBuffer = 0; +} + + +DocConvert::~DocConvert() +{ +} + + +void DocConvert::SetTitle(const char* title) +{ + m_pimpl->m_title = title; +} + + +void DocConvert::SetSource(const char* inFileName) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = ReadInWholeFile(inFileName); +} + + +void DocConvert::SetSourceData(const char* inData, size_t a_size) +{ + if (m_pimpl->inputBuffer) + hoedown_buffer_free(m_pimpl->inputBuffer); + m_pimpl->inputBuffer = hoedown_buffer_new(DEF_IUNIT); + hoedown_buffer_put(m_pimpl->inputBuffer, (const uint8_t*)inData, a_size); +} + + +void DocConvert::Convert() +{ + if (!m_pimpl->inputBuffer) + return; + m_pimpl->outputBuffer = ConvertMarkdownToHTML(m_pimpl->inputBuffer->data, m_pimpl->inputBuffer->size); + ConvertHTMLToPDF(m_pimpl->outputBuffer->data, &m_pimpl->doc); +} + + +void DocConvert::GetHTMLData(char** data, size_t* size) +{ + *data = (char*)m_pimpl->outputBuffer->data; + *size = m_pimpl->outputBuffer->size; +} + + +void DocConvert::OutputHTML(const char* outFileName) +{ + SaveHTML(outFileName, m_pimpl->outputBuffer->data, m_pimpl->outputBuffer->size); +} + + +void DocConvert::OutputPDF(const char* outFileName) +{ + //RemoveFile(outFileName); + m_pimpl->doc.finalize(outFileName); +} + + +void DocConvert::GetPDFData(char* data, size_t* size) +{ + m_pimpl->doc.finalize(data, size); +} + diff --git a/DocConvert.h b/DocConvert.h new file mode 100644 index 0000000..e9c34e9 --- /dev/null +++ b/DocConvert.h @@ -0,0 +1,39 @@ +#ifndef DOCCONVERT_H +#define DOCCONVERT_H + + +#include + + +class DocConvert +{ +public: + DocConvert(); + ~DocConvert(); + + void SetTitle(const char* title); + void SetSource(const char* inFileName); + void SetSourceData(const char* inData, size_t a_size); + + void Convert(); + + void OutputHTML(const char* outFileName); + void OutputPDF(const char* outFileName); + + // data is allocated + void GetHTMLData(char** data, size_t* size); + + // data is not-allocated, you need to pass in and the size of it + void GetPDFData(char* data, size_t* size); + + //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF); + //void ConvertToHTML(std::vector& outputData); + //void ConvertToPDF(std::vector& outputData); + +private: + struct Pimpl; + std::unique_ptr m_pimpl; +}; + + +#endif // DOCCONVERT_H diff --git a/DocOutput.cpp b/DocOutput.cpp index fa532b7..f0d537b 100644 --- a/DocOutput.cpp +++ b/DocOutput.cpp @@ -212,8 +212,16 @@ } +void DocOutputDevice::finalize(char* outputBuffer, size_t* size) +{ + HPDF_UINT32 siz = *size; + HPDF_GetContents(m_pimpl->pdf, (HPDF_BYTE*)outputBuffer, &siz); + *size = siz; +} + + void DocOutputDevice::finalize(const char* outputFileName) { - HPDF_SaveToFile(m_pimpl->pdf, outputFileName); + HPDF_SaveToFile(m_pimpl->pdf, outputFileName); } diff --git a/DocOutput.h b/DocOutput.h index 61885e4..8ae18ef 100644 --- a/DocOutput.h +++ b/DocOutput.h @@ -52,7 +52,8 @@ DocOutputPage* newPage(); - void finalize(const char* outputFileName); + void finalize(char* outputBuffer, size_t* size); + void finalize(const char* outputFileName); private: struct Pimpl; diff --git a/MdiChild.cpp b/MdiChild.cpp new file mode 100644 index 0000000..9285c16 --- /dev/null +++ b/MdiChild.cpp @@ -0,0 +1,242 @@ +#include +#include "Utilities.h" +#include "MdiChild.h" +#include "ui_ExtensibleObjectModelUI.h" + + +MdiChild::MdiChild() +{ + setAttribute(Qt::WA_DeleteOnClose); + isUntitled = true; + connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); +} + +MdiChild::~MdiChild() +{ + closing(); +} + +void MdiChild::newFile() +{ + static int sequenceNumber = 1; + isUntitled = true; + curFile = tr("document%1.txt").arg(sequenceNumber++); + setWindowTitle(curFile + "[*]"); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); +} + +bool MdiChild::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream in(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + setPlainText(in.readAll()); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); + return true; +} + +bool MdiChild::save() +{ + return (isUntitled) ? saveAs() : saveFile(curFile); +} + +bool MdiChild::saveAs() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); + if (fileName.isEmpty()) + return false; + return saveFile(fileName); +} + +bool MdiChild::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("MDI"), + tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); + return false; + } + QTextStream out(&file); + QApplication::setOverrideCursor(Qt::WaitCursor); + out << toPlainText(); + QApplication::restoreOverrideCursor(); + + setCurrentFile(fileName); + return true; +} + +QString MdiChild::userFriendlyCurrentFile() +{ + return strippedName(curFile); +} + +void MdiChild::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} + +void MdiChild::documentWasModified() +{ + setWindowModified(document()->isModified()); +} + +bool MdiChild::maybeSave() +{ + if (document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("MDI"), + tr("'%1' has been modified.\n" + "Do you want to save your changes?") + .arg(userFriendlyCurrentFile()), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return save(); + else if (ret == QMessageBox::Cancel) + return false; + } + return true; +} + +void MdiChild::setCurrentFile(const QString &fileName) +{ + curFile = QFileInfo(fileName).canonicalFilePath(); + isUntitled = false; + document()->setModified(false); + setWindowModified(false); + setWindowTitle(userFriendlyCurrentFile() + "[*]"); +} + +QString MdiChild::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} + + + +void MdiChild::markdownSelection(const char* preText, const char* postText) +{ + QTextCursor cur = textCursor(); + cur.beginEditBlock(); + QString selectedText = cur.selection().toPlainText(); + cur.removeSelectedText(); + cur.insertText(preText + selectedText + postText); + cur.endEditBlock(); +} + + + +void MdiChild::bold() +{ + markdownSelection("**", "**"); +} + +void MdiChild::italic() +{ + markdownSelection("*", "*"); +} + +void MdiChild::quote() +{ + markdownSelection("`", "`"); +} + +void MdiChild::code() +{ + //markdownSelection("*", "*"); + // Need to add indentation of text with 4 spaces each line +} + +void MdiChild::heading1() +{ + markdownSelection("# ", " #"); +} + +void MdiChild::heading2() +{ + markdownSelection("## ", " ##"); +} + +void MdiChild::heading3() +{ + markdownSelection("### ", " ###"); +} + +void MdiChild::heading4() +{ + markdownSelection("#### ", " ####"); +} + +void MdiChild::hyperlink() +{ +} + +void MdiChild::image() +{ +} + +void MdiChild::unorderedList() +{ +} + +void MdiChild::orderedList() +{ +} + +void MdiChild::horizontalRule() +{ +} + +void MdiChild::timestamp() +{ +} + +void MdiChild::pageNumber() +{ +} + +void MdiChild::pageCount() +{ +} + +void MdiChild::del() +{ + //QTextEdit::cursor().pos() +} + +void MdiChild::undo() +{ +} + +void MdiChild::redo() +{ +} + +void MdiChild::find() +{ +} + +void MdiChild::findNext() +{ +} + +void MdiChild::findPrevious() +{ +} + +void MdiChild::goToLine() +{ +} + diff --git a/MdiChild.h b/MdiChild.h new file mode 100644 index 0000000..0f7e3e8 --- /dev/null +++ b/MdiChild.h @@ -0,0 +1,69 @@ +#ifndef MDI_CHILD_H +#define MDI_CHILD_H + + +#include + + +class MdiChild : public QTextEdit +{ + Q_OBJECT +public: + MdiChild(); + ~MdiChild(); + + void newFile(); + bool loadFile(const QString &fileName); + bool save(); + bool saveAs(); + bool saveFile(const QString &fileName); + QString userFriendlyCurrentFile(); + QString currentFile() { return curFile; } + + void markdownSelection(const char* preText, const char* postText); + + void bold(); + void italic(); + void quote(); + void code(); + void heading1(); + void heading2(); + void heading3(); + void heading4(); + void hyperlink(); + void image(); + void unorderedList(); + void orderedList(); + void horizontalRule(); + void timestamp(); + void pageNumber(); + void pageCount(); + void del(); + void undo(); + void redo(); + void find(); + void findNext(); + void findPrevious(); + void goToLine(); + +signals: + void closing(); + void documentContentsChanged(); + +private slots: + void documentWasModified(); + +protected: + void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + +private: + bool maybeSave(); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QString curFile; + bool isUntitled; +}; + + +#endif // MDI_CHILD_H diff --git a/MdiWindow.cpp b/MdiWindow.cpp index 2713c0d..acf90fb 100644 --- a/MdiWindow.cpp +++ b/MdiWindow.cpp @@ -4,233 +4,18 @@ #include "ui_ExtensibleObjectModelUI.h" -MdiChild::MdiChild() -{ - setAttribute(Qt::WA_DeleteOnClose); - isUntitled = true; - connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged())); -} - -MdiChild::~MdiChild() -{ - closing(); -} - -void MdiChild::newFile() -{ - static int sequenceNumber = 1; - isUntitled = true; - curFile = tr("document%1.txt").arg(sequenceNumber++); - setWindowTitle(curFile + "[*]"); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); -} - -bool MdiChild::loadFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream in(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - setPlainText(in.readAll()); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); - return true; -} - -bool MdiChild::save() -{ - return (isUntitled) ? saveAs() : saveFile(curFile); -} - -bool MdiChild::saveAs() -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile); - if (fileName.isEmpty()) - return false; - return saveFile(fileName); -} - -bool MdiChild::saveFile(const QString &fileName) -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("MDI"), - tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); - return false; - } - QTextStream out(&file); - QApplication::setOverrideCursor(Qt::WaitCursor); - out << toPlainText(); - QApplication::restoreOverrideCursor(); - - setCurrentFile(fileName); - return true; -} - -QString MdiChild::userFriendlyCurrentFile() -{ - return strippedName(curFile); -} - -void MdiChild::closeEvent(QCloseEvent *event) -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} - -void MdiChild::documentWasModified() -{ - setWindowModified(document()->isModified()); -} - -bool MdiChild::maybeSave() -{ - if (document()->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("MDI"), - tr("'%1' has been modified.\n" - "Do you want to save your changes?") - .arg(userFriendlyCurrentFile()), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) - return save(); - else if (ret == QMessageBox::Cancel) - return false; - } - return true; -} - -void MdiChild::setCurrentFile(const QString &fileName) -{ - curFile = QFileInfo(fileName).canonicalFilePath(); - isUntitled = false; - document()->setModified(false); - setWindowModified(false); - setWindowTitle(userFriendlyCurrentFile() + "[*]"); -} - -QString MdiChild::strippedName(const QString &fullFileName) -{ - return QFileInfo(fullFileName).fileName(); -} - - - -void MdiChild::markdownSelection(const char* preText, const char* postText) -{ - QTextCursor cur = textCursor(); - cur.beginEditBlock(); - QString selectedText = cur.selection().toPlainText(); - cur.removeSelectedText(); - cur.insertText(preText + selectedText + postText); - cur.endEditBlock(); -} - - - -void MdiChild::bold() -{ - markdownSelection("**", "**"); -} -void MdiChild::italic() -{ - markdownSelection("*", "*"); -} -void MdiChild::quote() -{ - markdownSelection("`", "`"); -} -void MdiChild::code() -{ - //markdownSelection("*", "*"); - // Need to add indentation of text with 4 spaces each line -} -void MdiChild::heading1() -{ - markdownSelection("# ", " #"); -} -void MdiChild::heading2() -{ - markdownSelection("## ", " ##"); -} -void MdiChild::heading3() -{ - markdownSelection("### ", " ###"); -} -void MdiChild::heading4() -{ - markdownSelection("#### ", " ####"); -} -void MdiChild::hyperlink() -{ -} -void MdiChild::image() -{ -} -void MdiChild::unorderedList() -{ -} -void MdiChild::orderedList() -{ -} -void MdiChild::horizontalRule() -{ -} -void MdiChild::timestamp() -{ -} -void MdiChild::pageNumber() -{ -} -void MdiChild::pageCount() -{ -} -void MdiChild::del() -{ - //QTextEdit::cursor().pos() -} -void MdiChild::undo() -{ -} -void MdiChild::redo() -{ -} -void MdiChild::find() -{ -} -void MdiChild::findNext() -{ -} -void MdiChild::findPrevious() -{ -} -void MdiChild::goToLine() -{ -} - - - - - - MdiWindow::MdiWindow(QWidget *parent) : QMainWindow(parent), appWindow(nullptr) { + //setupServer(); } +QObject* MakeTestObjectTree(); +void EnumPropertyEditorTest(); void MdiWindow::init(Ui_MainWindow* ui) { + server = 0; appWindow = ui; mdiArea = ui->mdiArea;//new QMdiArea; connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(updateActions())); @@ -288,16 +73,79 @@ statusBar()->showMessage(tr("Ready")); updateActions(); - readSettings(); + setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= 0x050000 menuBar()->setNativeMenuBar(false); #endif - tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); - tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); + +/* + EnumPropertyEditorTest(); + updateObjectTree(MakeTestObjectTree()); + //changeProjectTree(this); +*/ + + Project *p = new Project; + p->setObjectName("P1"); + p->m_Author = "John"; + //p->m_Name = "Project Name"; + +/* + Output *out = new Output; + out->m_Title = "Title"; + out->m_Filename = "OutFile.pdf"; + out->m_FileType = Output::PDF; + p->setOutput(out); + + Template *tmpl = new Template; + tmpl->m_Filename = "Templ.tmpl"; + tmpl->m_Color = QColor(1,2,3); + p->setTemplate(tmpl); +*/ + + p->setTitle("Title"); + p->setOutputFilename("OutFile.pdf"); + p->setOutputFileType(Project::PDF); + p->setTemplate("Templ.tmpl"); + p->setColor(QColor(1,2,3)); + + + Input *in = new Input; + in->setObjectName("InFile1"); + in->m_Filename = "InFile1.md"; + p->AddInput(in); + + Input *in2 = new Input; + in2->setObjectName("InFile2"); + in2->m_Filename = "InFile2.md"; + p->AddInput(in2); + /* + in.m_Filename = "InFile2.md"; + p.m_Inputs.append(in); + in.m_Filename = "InFile3.md"; + p.m_Inputs.append(in); + */ + + //solution.m_Projects.append(p); + + //solution.AddProject(p); + + /* + p.m_Name = "Project Name 2"; + p.m_Output.m_Title = "Title 2"; + p.m_Output.m_Filename = "OutFile2.pdf"; + solution.m_Projects.append(p); + */ + + //changeProjectTree(&solution); + + //tabifyDockWidget(appWindow->projectDock, appWindow->objectsDock); + //tabifyDockWidget(appWindow->projectDock, appWindow->propertiesDock); appWindow->projectDock->raise(); appWindow->eventLogDock->hide(); appWindow->consoleDock->hide(); + + readSettings(); } @@ -396,13 +244,20 @@ void MdiWindow::support() { - QDesktopServices::openUrl(QUrl("http://stackoverflow.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/support.html")); + lower(); } void MdiWindow::website() { - QDesktopServices::openUrl(QUrl("http://slashdot.org/")); + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/about.html")); +} + + +void MdiWindow::upgradeClicked() +{ + QDesktopServices::openUrl(QUrl("http://www.subflexion.com/MakePDF/register.html")); } @@ -512,26 +367,139 @@ #include "html.h" #include "document.h" +#include "DocConvert.h" +#include +#include + + +void MdiWindow::handleRequest() +{ + if (server->hasPendingConnections()) + { + QTcpSocket* sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + QByteArray ba = sock->readAll(); + //if (sock->canReadLine()) + { + QString str(ba); + QStringList tokens = str.split(QRegExp("[ \r\n][ \r\n]*")); + bool haveGet = false; + bool haveDoc = false; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i] == "GET") + haveGet = true; + if (tokens[i].contains(QString("pdf"), Qt::CaseInsensitive)) + haveDoc = true; + } + if (haveGet && haveDoc) //tokens[0] == "GET" && tokens[1].contains(QString("pdf"), Qt::CaseInsensitive )) + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: application/pdf; charset=\"utf-8\"\r\n" + "Content-Length: " << pdfContents.size() << + "\r\n" + "\r\n"; + //os << pdfContents.data(); + //"

Nothing to see here

\n" + //<< QDateTime::currentDateTime().toString() << "\n"; + os.flush(); + sock->flush(); + sock->write(pdfContents.data(), pdfContents.size()); + sock->flush(); + //sock->write(ba); + } + else + { + QTextStream os(sock); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 404 Ok\r\n" + "\r\n" + "\r\n"; + } + } + sock->waitForBytesWritten(); + sock->waitForDisconnected(); + sock->close(); + delete sock; + } +} + + +void MdiWindow::setupServer() +{ + // setup the web server + server = new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 12345)) + { + qFatal("Failed to open web socket server."); + } + connect(server, SIGNAL(newConnection()), this, SLOT(handleRequest())); +/* + + // open a browser window with the client HTML page + QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); + url.setQuery(QStringLiteral("webChannelBaseUrl=") + server.serverUrl().toString()); + QDesktopServices::openUrl(url); + dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); +*/ +} + void MdiWindow::updatePreview() { MdiChild* child = activeMdiChild(); if (child) { + static int ver = 0; + //char fileName[1024]; + //sprintf(fileName, "test/test-%i.pdf", ver); + ver++; + const char *fileName = "test/test.pdf"; QByteArray text = child->toPlainText().toLatin1(); - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(1024); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, 64); - hoedown_document_render(document, ob, (uint8_t*)text.data(), text.size()); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - appWindow->previewText->setText(QString(QLatin1String((char*)ob->data, ob->size))); - hoedown_buffer_free(ob); + char* data; + size_t size; + + DocConvert converter; + converter.SetSourceData(text.data(), text.size()); + converter.Convert(); + converter.GetHTMLData(&data, &size); + + converter.OutputPDF(fileName); + + appWindow->previewText->setText(QString(QLatin1String(data, size))); + + pdfContents.resize(5*1024*1024); + size = 5*1024*1024; + converter.GetPDFData(pdfContents.data(), &size); + pdfContents.resize(size); + //pdfContents = QByteArray(data, size); + + //QTimer::singleShot(100, this, SLOT(setWebPreviewURL())); + // ../../../build-MakePDF-Desktop-Debug/ + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=http://localhost:12345/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("http://localhost:12345/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); } } +void MdiWindow::setWebPreviewURL() +{ + const char *fileName = "test/test.pdf"; + appWindow->webPreview->setUpdatesEnabled(false); + //appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/3rdParty/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + appWindow->webPreview->setUrl(QUrl(QString("file:///home/jryland/Code/applications/MakePDF/build-MakePDF-Desktop-Debug/pdf.js/web/viewer.html?file=../../../build-MakePDF-Desktop-Debug/") + fileName)); + QTimer::singleShot(1000, this, SLOT(refreshWebPreview())); +} + + +void MdiWindow::refreshWebPreview() +{ + appWindow->webPreview->setUpdatesEnabled(true); +} + + void MdiWindow::updateActions() { bool hasMdiChild = (activeMdiChild() != 0); @@ -639,23 +607,38 @@ } +void MdiWindow::readLicense() +{ + YQ_LOG_DEBUG("Reading license"); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); +} + + void MdiWindow::readSettings() { YQ_LOG_DEBUG("Reading settings"); - QSettings settings("QtProject", "MDI Example"); - QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); - QSize size = settings.value("size", QSize(400, 400)).toSize(); - move(pos); - resize(size); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + restoreState(settings.value("DockLayout").toByteArray()); + move(settings.value("Position", QPoint(200, 200)).toPoint()); + resize(settings.value("Size", QSize(400, 400)).toSize()); + settings.endGroup(); + settings.beginGroup("License"); + QString user = settings.value("User").toString(); + QString licenseType = settings.value("Type").toString(); + settings.endGroup(); } void MdiWindow::writeSettings() { YQ_LOG_DEBUG("Saving settings"); - QSettings settings("QtProject", "MDI Example"); - settings.setValue("pos", pos()); - settings.setValue("size", size()); + QSettings settings(QSettings::NativeFormat, QSettings::UserScope, "Subflexion", "MakePDF"); + settings.beginGroup("MainWindow"); + settings.setValue("DockLayout", saveState()); + settings.setValue("Position", pos()); + settings.setValue("Size", size()); + settings.endGroup(); } @@ -695,3 +678,323 @@ return; mdiArea->setActiveSubWindow(qobject_cast(window)); } + + + +#include "Objects.h" +QObject* MakeTestObjectTree() +{ + QObject* o = new MyObjectTest; + return o; +} + + +void EnumEditor::ListSelectionChanged() +{ + QList items = lw->selectedItems(); + if (!items.count()) + return; + QString combinedString = items.at(0)->text(); + for (int i = 1; i < items.count(); i++) + combinedString += " | " + items.at(i)->text(); + int value = m_metaEnum.keysToValue(combinedString.toLocal8Bit().data()); + sb->setValue(value); + str->setText(m_metaEnum.valueToKeys(value).data()); +} + + +void EnumEditor::ComboSelectionChanged() +{ + QString combinedString = cb->currentText(); + sb->setValue(m_metaEnum.keysToValue(combinedString.toLocal8Bit().data())); + str->setText(combinedString); +} + + +EnumEditor::EnumEditor(QMetaEnum metaEnum) +{ + m_metaEnum = metaEnum; + QGridLayout* grid = new QGridLayout(); + QLabel* l1 = new QLabel("Name"); + QLabel* l2 = new QLabel("Enum"); + QLabel* l3 = new QLabel("Value"); + QLabel* l4 = new QLabel("String"); + grid->addWidget(l1, 0, 0); + grid->addWidget(l2, 1, 0); + grid->addWidget(l3, 2, 0); + grid->addWidget(l4, 3, 0); + QLabel* v1 = new QLabel(metaEnum.name()); + + QWidget* v2 = 0; + if (metaEnum.isFlag()) + { + lw = new QListWidget(); + lw->setSelectionMode(QAbstractItemView::MultiSelection); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + lw->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + v2 = lw; + connect(lw, SIGNAL(itemSelectionChanged()), this, SLOT(ListSelectionChanged())); + } + else + { + cb = new QComboBox(); + for (int i = 0; i < metaEnum.keyCount(); i++) + { + cb->addItem(metaEnum.valueToKey(metaEnum.value(i))); + } + connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(ComboSelectionChanged())); + v2 = cb; + } + + sb = new QSpinBox(); + str = new QLabel(); + grid->addWidget(v1, 0, 1); + grid->addWidget(v2, 1, 1); + grid->addWidget(sb, 2, 1); + grid->addWidget(str, 3, 1); + setLayout(grid); + show(); +} + + +void EnumPropertyEditorTest() +{ + MyObjectTest* o = new MyObjectTest; + for (int i = 0; i < o->metaObject()->enumeratorCount(); i++) + new EnumEditor(o->metaObject()->enumerator(i)); +} + + + +#include "ObjectVisitor.h" + + +class SerializeVisitor : public Visitor +{ +public: + SerializeVisitor(const char* fileName) { file = fopen(fileName, "wb"); } + virtual ~SerializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } +private: + FILE* file; + std::vector path; +}; + + +#include +#include +#include +#include + +#define CLASS_FACTORY(ClassName, ...) \ + else if (strcmp(className, #ClassName) == 0) return new ClassName(__VA_ARGS__) + +QObject* classObjectFactory(const char* className) +{ + if (false) {} + CLASS_FACTORY(QObject); + CLASS_FACTORY(QWidget); + CLASS_FACTORY(QTableView); + CLASS_FACTORY(QTableWidget); + CLASS_FACTORY(QLabel); + CLASS_FACTORY(QPushButton); + CLASS_FACTORY(QVBoxLayout); + CLASS_FACTORY(QHBoxLayout); + CLASS_FACTORY(QAction, nullptr); + CLASS_FACTORY(QActionGroup, nullptr); + CLASS_FACTORY(QButtonGroup); + CLASS_FACTORY(QFileSelector); + //CLASS_FACTORY(QPdfWriter); + //CLASS_FACTORY(QSound); + CLASS_FACTORY(QThread); + CLASS_FACTORY(QTimer); + printf("Unrecognized class name, ignoring\n"); + return 0; +} + + +class DeserializeVisitor : public Visitor +{ +public: + DeserializeVisitor(const char* fileName) { file = fopen(fileName, "rb"); } + virtual ~DeserializeVisitor() { fclose(file); } + virtual void enterObject(const char* className, const char* objectName) + { + std::string p = (path.size()) ? path.back() + "/" : ""; + path.push_back(p + objectName); + fprintf(file, "[%s]\n", path.back().c_str()); + fprintf(file, "class=%s\n", className); + } + virtual void leaveObject(const char* className, const char* objectName) + { + fprintf(file, "; end of %s\n\n", objectName); + path.pop_back(); + //fprintf(file, "--Leaving %s (%s)\n", objectName, className); + } + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) + { + //fprintf(file, "----Property: %s %s::%s = %s\n", QVariant::typeToName(typ), + // className, propertyName, value.toString().toLocal8Bit().data()); + fprintf(file, "%s=%s\n", propertyName, value.toString().toLocal8Bit().data()); + } + virtual bool isWriting() + { + return true; + } +private: + FILE* file; + std::vector path; +}; + +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qttreepropertybrowser.h" +#include "QtGroupBoxPropertyBrowser" +#include "ObjectTreeModel.h" + + +static QWidget *WrapWidgetInLayout(QWidget* wrapper, QWidget* w) +{ + QVBoxLayout *layout = new QVBoxLayout; + wrapper->setLayout(layout); + layout->addWidget(w); + layout->setMargin(0); + layout->setSpacing(0); + layout->setContentsMargins(0,0,0,0); + return wrapper; +} + + +void MdiWindow::updatePropertiesView(QObject *object) +{ + // Dynamically build the properties UI elements for the given object's properties + QtVariantPropertyManager *variantManager = new QtVariantPropertyManager(); + QtVariantEditorFactory *variantFactory = new QtVariantEditorFactory(); + QtAbstractPropertyBrowser *groupEditor = new QtGroupBoxPropertyBrowser(); + groupEditor->setFactoryForManager(variantManager, variantFactory); + QtTreePropertyBrowser *variantEditor = new QtTreePropertyBrowser(); + variantEditor->setFactoryForManager(variantManager, variantFactory); + std::map pmap; + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + std::string className = property.enclosingMetaObject()->className(); + QtProperty *parentItem = nullptr; + if (pmap.find(className) == pmap.end()) { + parentItem = variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), className.c_str()); + pmap.insert(std::make_pair(className, parentItem)); + groupEditor->addProperty(parentItem); + variantEditor->addProperty(parentItem); + } else { + parentItem = pmap[className]; + } + QtVariantProperty *item = variantManager->addProperty(property.type(), property.name()); + if ( item ) { + item->setValue(property.read(object)); + parentItem->addSubProperty(item); + } + } + variantEditor->setIndentation(30); + variantEditor->setPropertiesWithoutValueMarked(true); + variantEditor->setRootIsDecorated(false); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(groupEditor); + + QTabWidget *tabs = new QTabWidget; + tabs->addTab(WrapWidgetInLayout(new QWidget, variantEditor), "Property List"); + tabs->addTab(WrapWidgetInLayout(new QWidget, scrollArea), "Grouped"); + + foreach (QObject* child, appWindow->propertiesView->children()) + if (child->isWidgetType()) + delete child; + + QLayout* lo = appWindow->propertiesView->layout(); + if (lo) { + lo->addWidget(tabs); + } else { + WrapWidgetInLayout(appWindow->propertiesView, tabs); + } + //QObject::connect(variantManager, SIGNAL(propertyChanged(QtProperty*)), &blah, SLOT(updateProp(QtProperty*))); +} + + +void MdiWindow::changePropertiesObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updatePropertiesView(ptr); +} + + +void MdiWindow::changeRootObject(const QModelIndex &index) +{ + QObject* ptr = (QObject*)index.internalPointer(); + if (ptr) + updateObjectTree(ptr); +} + + +void MdiWindow::changeProjectTree(QObject *rootObject) +{ + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->projectsView->model()) { + ((ObjectTreeModel *)appWindow->projectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->projectsView); + objectTree->setRootObjects(list); + appWindow->projectsView->setModel(objectTree); + } + + appWindow->projectsView->header()->hide(); + QObject::connect(appWindow->projectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); +} + + +void MdiWindow::updateObjectTree(QObject *rootObject) +{ + SerializeVisitor visitor("/tmp/object-dump.txt"); + Visit(visitor, rootObject); + + QList list; + list.append(ObjPtr(rootObject)); + + if (appWindow->objectsView->model()) { + ((ObjectTreeModel *)appWindow->objectsView->model())->setRootObjects(list); + } else { + ObjectTreeModel *objectTree = new ObjectTreeModel(appWindow->objectsView); + objectTree->setRootObjects(list); + appWindow->objectsView->setModel(objectTree); + } + + appWindow->objectsView->header()->hide(); + QObject::connect(appWindow->objectsView, SIGNAL(doubleClicked(const QModelIndex &)), + this, SLOT(changeRootObject(const QModelIndex &))); + QObject::connect(appWindow->objectsView, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(changePropertiesObject(const QModelIndex &))); +} diff --git a/MdiWindow.h b/MdiWindow.h index 76d7f1b..35ef9c3 100644 --- a/MdiWindow.h +++ b/MdiWindow.h @@ -4,78 +4,19 @@ #include #include +#include "Objects.h" +#include "MdiChild.h" -class MdiChild; class QAction; class QMenu; class QMdiArea; class QMdiSubWindow; class QSignalMapper; +class QTcpServer; class Ui_MainWindow; -class MdiChild : public QTextEdit -{ - Q_OBJECT -public: - MdiChild(); - ~MdiChild(); - - void newFile(); - bool loadFile(const QString &fileName); - bool save(); - bool saveAs(); - bool saveFile(const QString &fileName); - QString userFriendlyCurrentFile(); - QString currentFile() { return curFile; } - - void markdownSelection(const char* preText, const char* postText); - - void bold(); - void italic(); - void quote(); - void code(); - void heading1(); - void heading2(); - void heading3(); - void heading4(); - void hyperlink(); - void image(); - void unorderedList(); - void orderedList(); - void horizontalRule(); - void timestamp(); - void pageNumber(); - void pageCount(); - void del(); - void undo(); - void redo(); - void find(); - void findNext(); - void findPrevious(); - void goToLine(); - -signals: - void closing(); - void documentContentsChanged(); - -private slots: - void documentWasModified(); - -protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - -private: - bool maybeSave(); - void setCurrentFile(const QString &fileName); - QString strippedName(const QString &fullFileName); - - QString curFile; - bool isUntitled; -}; - - /* class MdiOptions { @@ -109,8 +50,12 @@ void save(); void saveAs(); + void handleRequest(); void updatePreview(); + void setWebPreviewURL(); + void refreshWebPreview(); + // Edit menu actions #ifndef QT_NO_CLIPBOARD void cut(); @@ -159,12 +104,26 @@ void switchLayoutDirection(); void setActiveSubWindow(QWidget *window); + void changeRootObject(const QModelIndex &index); + void changePropertiesObject(const QModelIndex &index); + + // Dialog events + void upgradeClicked(); + private: + void changeProjectTree(QObject *rootObject); + void updateObjectTree(QObject *rootObject); + void updatePropertiesView(QObject *object); + void setupServer(); void readSettings(); + void readLicense(); void writeSettings(); MdiChild *activeMdiChild(); QMdiSubWindow *findMdiChild(const QString &fileName); + //Solution solution; + QByteArray pdfContents; + QTcpServer *server; QMdiArea *mdiArea; QSignalMapper *windowMapper; Ui_MainWindow *appWindow; diff --git a/ObjectVisitor.h b/ObjectVisitor.h new file mode 100644 index 0000000..12cf25f --- /dev/null +++ b/ObjectVisitor.h @@ -0,0 +1,59 @@ +#ifndef OBJECTVISITOR_H +#define OBJECTVISITOR_H + + +#include +#include +#include +#include + + +class Visitor +{ +public: + Visitor() {} + virtual ~Visitor() {} + + virtual void enterObject(const char* className, const char* objectName) = 0; + virtual void leaveObject(const char* className, const char* objectName) = 0; + + // Reads or writes a property value + virtual void visit(const char* className, + const char* propertyName, QVariant::Type typ, QVariant& value) = 0; + + // By default, it is a reader, but implementing this enables a visitor that sets values + virtual bool isWriting() { return false; } +}; + + +void Visit(Visitor& visitor, QObject* object) +{ + std::string objectName = object->objectName().toLocal8Bit().data(); + if (objectName.size() <= 1) { + objectName = std::to_string((uint64_t)(void*)object); + } + visitor.enterObject(object->metaObject()->className(), objectName.c_str()); + for (int i = 0; i < object->metaObject()->propertyCount(); i++) + { + const QMetaProperty& property = object->metaObject()->property(i); + if (visitor.isWriting()) { + QVariant value; + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + property.write(object, value); + + } else { + QVariant value = property.read(object); + visitor.visit(property.enclosingMetaObject()->className(), + property.name(), property.type(), value); + } + } + for (int i = 0; i < object->children().count(); i++) + { + Visit(visitor, object->children()[i]); + } + visitor.leaveObject(object->metaObject()->className(), objectName.c_str()); +} + + +#endif // OBJECTVISITOR_H diff --git a/Objects.h b/Objects.h new file mode 100644 index 0000000..90e7bb1 --- /dev/null +++ b/Objects.h @@ -0,0 +1,167 @@ +#ifndef OBJECTS_H +#define OBJECTS_H + + +#include +#include +#include +#include +#include +#include +#include + + +class EnumEditor : public QWidget +{ + Q_OBJECT +public slots: + void ListSelectionChanged(); + void ComboSelectionChanged(); +public: + EnumEditor(QMetaEnum metaEnum); +private: + QListWidget* lw; + QComboBox* cb; + QSpinBox* sb; + QLabel* str; + QMetaEnum m_metaEnum; +}; + + +// Property Manager Supported types: +// int, bool, double, enums, flags +// QString, QDate, QTime, QDateTime, QKeySequence +// QChar, QLocale, QPoint, QPointF, QSize, QSizeF +// QRect, QRectF, QSizePolicy, QFont, QColor, QCursor + + +#define PROP_WRAP(type, name) \ + Q_PROPERTY(type name READ get##name WRITE set##name) \ + type get##name() const { return m_##name; } \ + void set##name(type val) { m_##name = val; } \ + type m_##name; + +#define CHILD_PTR_PROP_WRAP(type, name) \ + Q_PROPERTY(type* name READ get##name WRITE set##name) \ + type* get##name() const { return m_##name; } \ + void set##name(type* val) { \ + /* if (m_##name) children().removeAll((QObject*)m_##name); */ \ + val->setParent(this); \ + m_##name = val; \ + } \ + type* m_##name = nullptr; + + +class MyObjectTest : public QObject +{ + Q_OBJECT + Q_ENUMS(AnotherEnum) + Q_ENUMS(TestEnum) + Q_FLAGS(TestFlags) +public: + enum TestFlags { FlagValue1 = 1, AnotherFlagValue = 2, FlagEtc = 4, FlagBlah = 8 }; + enum TestEnum { EnumValue1, AnotherValue, Etc, Blah }; + enum AnotherEnum { AEnumValue1, AnAnotherValue, Etc2 }; + + explicit MyObjectTest() : QObject() { + m_An_Int_Value = 10; + m_A_Double = 11.0; + //m_An_Enum = EnumValue1; + //memset(this, 0, sizeof(MyObjectTest)); + } + ~MyObjectTest() { + } + + PROP_WRAP(int, An_Int_Value) + PROP_WRAP(bool, A_Bool) + PROP_WRAP(double, A_Double) + PROP_WRAP(TestEnum,An_Enum1) + PROP_WRAP(TestEnum,An_Enum2) + PROP_WRAP(QFlags,A_Flags) + PROP_WRAP(QString, A_String) + PROP_WRAP(QDate, A_Date) + PROP_WRAP(QTime, A_Time) + PROP_WRAP(QDateTime, A_Date_and_Time) + PROP_WRAP(QKeySequence, A_Key_Sequence) + PROP_WRAP(QChar, A_Char) + PROP_WRAP(QLocale, A_Locale) + PROP_WRAP(QPoint, A_Point) + PROP_WRAP(QPointF, A_PointF) + PROP_WRAP(QSize, A_Size) + PROP_WRAP(QSizeF, A_SizeF) + PROP_WRAP(QRect, A_Rect) + PROP_WRAP(QRectF, A_RectF) + //PROP_WRAP(QSizePolicy, A_SizePolicy) + //PROP_WRAP(QFont, A_Font) + PROP_WRAP(QColor, A_Color) + //PROP_WRAP(QCursor, A_Cursor) + // flags +}; + + + +class Template : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) + PROP_WRAP(QColor, Color) +}; + + +class Output : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + PROP_WRAP(QString, Title) + PROP_WRAP(QString, Filename) + PROP_WRAP(FileTypes, FileType) +}; + + +class Input : public QObject +{ + Q_OBJECT +public: + PROP_WRAP(QString, Filename) +}; + + +class Project : public QObject +{ + Q_OBJECT + Q_ENUMS(FileTypes) +public: + enum FileTypes { HTML, PDF, Markdown }; + //PROP_WRAP(QString, Name) + PROP_WRAP(QString, Author) + //PROP_WRAP(Template*, Template) + //PROP_WRAP(QList, Inputs) + //PROP_WRAP(Output*, Output) + + //CHILD_PTR_PROP_WRAP(Output, Output) + //CHILD_PTR_PROP_WRAP(Template, Template) + + PROP_WRAP(QString, Title) + PROP_WRAP(QString, OutputFilename) + PROP_WRAP(FileTypes, OutputFileType) + + PROP_WRAP(QString, Template) + PROP_WRAP(QColor, Color) + + void AddInput(Input* in) { in->setParent(this); } +}; + + +class Solution : public QObject +{ + Q_OBJECT +public: + //PROP_WRAP(QList, Projects) + void AddProject(Project* proj) { proj->setParent(this); } +}; + + +#endif // OBJECTS_H diff --git a/QtProject/MakePDF.pro b/QtProject/MakePDF.pro index f4e410c..4026759 100644 --- a/QtProject/MakePDF.pro +++ b/QtProject/MakePDF.pro @@ -1,21 +1,24 @@ -QT += core gui widgets +# QT += webkitwidgets network widgets +CONFIG += qt +QT += core gui widgets webkitwidgets +#QT += svg CONFIG -= flat TARGET = MakePDF DEFINES += \ - GUI_APP=1 + GUI_APP=1 RESOURCES += \ - ../Resources/resources.qrc + ../Resources/resources.qrc FORMS += \ - ../Resources/forms/About.ui \ - ../Resources/forms/NewProjectWizard.ui \ - ../Resources/forms/ExtensibleObjectModelUI.ui \ - ../Resources/forms/SendBugReport.ui \ + ../Resources/forms/About.ui \ + ../Resources/forms/NewProjectWizard.ui \ + ../Resources/forms/ExtensibleObjectModelUI.ui \ + ../Resources/forms/SendBugReport.ui \ ../Resources/forms/Help.ui \ ../Resources/forms/CheckUpdates.ui \ ../Resources/forms/LicenseUpgrade.ui \ @@ -23,136 +26,174 @@ ../Resources/forms/PaletteEditor.ui INCLUDEPATH += \ - ../Framework \ - ../3rdParty/hoedown \ - ../3rdParty/libharu/include \ - ../3rdParty/TinyXML++ + ../Framework \ + ../3rdParty/hoedown \ + ../3rdParty/libharu/include \ + ../3rdParty/TinyXML++ \ + ../3rdParty/qtpropertybrowser/src HEADERS += \ - ../Framework/EventLog.h \ - ../Framework/Expected.h \ - ../Framework/Final.h \ - ../Framework/Finally.h \ - ../Framework/GenericTable.h \ - ../Framework/GenericTableUI.h \ - ../Framework/NonCopyable.h \ - ../Framework/Utilities.h \ + ../Framework/EventLog.h \ + ../Framework/Expected.h \ + ../Framework/Final.h \ + ../Framework/Finally.h \ + ../Framework/GenericTable.h \ + ../Framework/GenericTableUI.h \ + ../Framework/NonCopyable.h \ + ../Framework/Utilities.h \ + ../Framework/SystemInfomation.h \ + ../Framework/Array.h \ + ../Framework/Macros.h \ + ../Framework/ObjectTreeModel.h \ + ../Version.h \ + ../Util.h \ ../ui.h \ + ../MdiChild.h \ ../MdiWindow.h \ ../ColorPicker.h \ - ../Version.h + ../DocConvert.h \ + ../Objects.h \ + ../ObjectVisitor.h HEADERS += \ - ../DocOutput.h \ - ../DocProject.h \ - ../DocStyle.h \ - ../DocTemplate.h \ - ../DocVisitor.h \ - ../DocSVG.h + ../DocOutput.h \ + ../DocProject.h \ + ../DocStyle.h \ + ../DocTemplate.h \ + ../DocVisitor.h \ + ../DocSVG.h SOURCES += \ - ../Framework/Tests.cpp \ - ../Framework/Utilities.cpp \ - ../Framework/EventLog.cpp \ + ../Framework/Tests.cpp \ + ../Framework/Utilities.cpp \ + ../Framework/EventLog.cpp \ + ../MdiChild.cpp \ ../MdiWindow.cpp \ ../ColorPicker.cpp \ - ../Version.cpp + ../Version.cpp \ + ../Framework/SystemInfomation.cpp \ + ../DocConvert.cpp \ + ../Framework/ObjectTreeModel.cpp SOURCES += \ - ../DocOutput.cpp \ - ../DocProject.cpp \ - ../DocStyle.cpp \ - ../DocTemplate.cpp \ - ../DocVisitor.cpp \ - ../DocSVG.cpp \ - ../main.cpp + ../DocOutput.cpp \ + ../DocProject.cpp \ + ../DocStyle.cpp \ + ../DocTemplate.cpp \ + ../DocVisitor.cpp \ + ../DocSVG.cpp \ + ../main.cpp SOURCES += \ - ../3rdParty/hoedown/autolink.c \ - ../3rdParty/hoedown/buffer.c \ - ../3rdParty/hoedown/document.c \ - ../3rdParty/hoedown/escape.c \ - ../3rdParty/hoedown/html.c \ - ../3rdParty/hoedown/html_blocks.c \ - ../3rdParty/hoedown/stack.c + ../3rdParty/hoedown/autolink.c \ + ../3rdParty/hoedown/buffer.c \ + ../3rdParty/hoedown/document.c \ + ../3rdParty/hoedown/escape.c \ + ../3rdParty/hoedown/html.c \ + ../3rdParty/hoedown/html_blocks.c \ + ../3rdParty/hoedown/stack.c SOURCES += \ - ../3rdParty/libharu/src/hpdf_3dmeasure.c \ - ../3rdParty/libharu/src/hpdf_annotation.c \ - ../3rdParty/libharu/src/hpdf_array.c \ - ../3rdParty/libharu/src/hpdf_binary.c \ - ../3rdParty/libharu/src/hpdf_boolean.c \ - ../3rdParty/libharu/src/hpdf_catalog.c \ - ../3rdParty/libharu/src/hpdf_destination.c \ - ../3rdParty/libharu/src/hpdf_dict.c \ - ../3rdParty/libharu/src/hpdf_doc.c \ - ../3rdParty/libharu/src/hpdf_doc_png.c \ - ../3rdParty/libharu/src/hpdf_encoder.c \ - ../3rdParty/libharu/src/hpdf_encoder_utf.c \ - ../3rdParty/libharu/src/hpdf_encrypt.c \ - ../3rdParty/libharu/src/hpdf_encryptdict.c \ - ../3rdParty/libharu/src/hpdf_error.c \ - ../3rdParty/libharu/src/hpdf_exdata.c \ - ../3rdParty/libharu/src/hpdf_ext_gstate.c \ - ../3rdParty/libharu/src/hpdf_font.c \ - ../3rdParty/libharu/src/hpdf_fontdef.c \ - ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ - ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ - ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ - ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ - ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ - ../3rdParty/libharu/src/hpdf_font_cid.c \ - ../3rdParty/libharu/src/hpdf_font_tt.c \ - ../3rdParty/libharu/src/hpdf_font_type1.c \ - ../3rdParty/libharu/src/hpdf_gstate.c \ - ../3rdParty/libharu/src/hpdf_image.c \ - ../3rdParty/libharu/src/hpdf_image_png.c \ - ../3rdParty/libharu/src/hpdf_info.c \ - ../3rdParty/libharu/src/hpdf_list.c \ - ../3rdParty/libharu/src/hpdf_mmgr.c \ - ../3rdParty/libharu/src/hpdf_name.c \ - ../3rdParty/libharu/src/hpdf_namedict.c \ - ../3rdParty/libharu/src/hpdf_null.c \ - ../3rdParty/libharu/src/hpdf_number.c \ - ../3rdParty/libharu/src/hpdf_objects.c \ - ../3rdParty/libharu/src/hpdf_outline.c \ - ../3rdParty/libharu/src/hpdf_pages.c \ - ../3rdParty/libharu/src/hpdf_page_label.c \ - ../3rdParty/libharu/src/hpdf_page_operator.c \ - ../3rdParty/libharu/src/hpdf_pdfa.c \ - ../3rdParty/libharu/src/hpdf_real.c \ - ../3rdParty/libharu/src/hpdf_streams.c \ - ../3rdParty/libharu/src/hpdf_string.c \ - ../3rdParty/libharu/src/hpdf_u3d.c \ - ../3rdParty/libharu/src/hpdf_utils.c \ - ../3rdParty/libharu/src/hpdf_xref.c + ../3rdParty/libharu/src/hpdf_3dmeasure.c \ + ../3rdParty/libharu/src/hpdf_annotation.c \ + ../3rdParty/libharu/src/hpdf_array.c \ + ../3rdParty/libharu/src/hpdf_binary.c \ + ../3rdParty/libharu/src/hpdf_boolean.c \ + ../3rdParty/libharu/src/hpdf_catalog.c \ + ../3rdParty/libharu/src/hpdf_destination.c \ + ../3rdParty/libharu/src/hpdf_dict.c \ + ../3rdParty/libharu/src/hpdf_doc.c \ + ../3rdParty/libharu/src/hpdf_doc_png.c \ + ../3rdParty/libharu/src/hpdf_encoder.c \ + ../3rdParty/libharu/src/hpdf_encoder_utf.c \ + ../3rdParty/libharu/src/hpdf_encrypt.c \ + ../3rdParty/libharu/src/hpdf_encryptdict.c \ + ../3rdParty/libharu/src/hpdf_error.c \ + ../3rdParty/libharu/src/hpdf_exdata.c \ + ../3rdParty/libharu/src/hpdf_ext_gstate.c \ + ../3rdParty/libharu/src/hpdf_font.c \ + ../3rdParty/libharu/src/hpdf_fontdef.c \ + ../3rdParty/libharu/src/hpdf_fontdef_base14.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cid.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cns.c \ + ../3rdParty/libharu/src/hpdf_fontdef_cnt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_jp.c \ + ../3rdParty/libharu/src/hpdf_fontdef_kr.c \ + ../3rdParty/libharu/src/hpdf_fontdef_tt.c \ + ../3rdParty/libharu/src/hpdf_fontdef_type1.c \ + ../3rdParty/libharu/src/hpdf_font_cid.c \ + ../3rdParty/libharu/src/hpdf_font_tt.c \ + ../3rdParty/libharu/src/hpdf_font_type1.c \ + ../3rdParty/libharu/src/hpdf_gstate.c \ + ../3rdParty/libharu/src/hpdf_image.c \ + ../3rdParty/libharu/src/hpdf_image_png.c \ + ../3rdParty/libharu/src/hpdf_info.c \ + ../3rdParty/libharu/src/hpdf_list.c \ + ../3rdParty/libharu/src/hpdf_mmgr.c \ + ../3rdParty/libharu/src/hpdf_name.c \ + ../3rdParty/libharu/src/hpdf_namedict.c \ + ../3rdParty/libharu/src/hpdf_null.c \ + ../3rdParty/libharu/src/hpdf_number.c \ + ../3rdParty/libharu/src/hpdf_objects.c \ + ../3rdParty/libharu/src/hpdf_outline.c \ + ../3rdParty/libharu/src/hpdf_pages.c \ + ../3rdParty/libharu/src/hpdf_page_label.c \ + ../3rdParty/libharu/src/hpdf_page_operator.c \ + ../3rdParty/libharu/src/hpdf_pdfa.c \ + ../3rdParty/libharu/src/hpdf_real.c \ + ../3rdParty/libharu/src/hpdf_streams.c \ + ../3rdParty/libharu/src/hpdf_string.c \ + ../3rdParty/libharu/src/hpdf_u3d.c \ + ../3rdParty/libharu/src/hpdf_utils.c \ + ../3rdParty/libharu/src/hpdf_xref.c SOURCES += \ - ../3rdParty/TinyXML++/ticpp.cpp \ - ../3rdParty/TinyXML++/tinystr.cpp \ - ../3rdParty/TinyXML++/tinyxml.cpp \ - ../3rdParty/TinyXML++/tinyxmlerror.cpp \ - ../3rdParty/TinyXML++/tinyxmlparser.cpp + ../3rdParty/TinyXML++/ticpp.cpp \ + ../3rdParty/TinyXML++/tinystr.cpp \ + ../3rdParty/TinyXML++/tinyxml.cpp \ + ../3rdParty/TinyXML++/tinyxmlerror.cpp \ + ../3rdParty/TinyXML++/tinyxmlparser.cpp + + +SOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.cpp \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.cpp \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.cpp \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils.cpp + +HEADERS += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertymanager.h \ + ../3rdParty/qtpropertybrowser/src/qteditorfactory.h \ + ../3rdParty/qtpropertybrowser/src/qtvariantproperty.h \ + ../3rdParty/qtpropertybrowser/src/qttreepropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtbuttonpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtgroupboxpropertybrowser.h \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowserutils_p.h + +RESOURCES += \ + ../3rdParty/qtpropertybrowser/src/qtpropertybrowser.qrc # As a note to what was removed REMOVED_SOURCES = \ - ../3rdParty/hoedown/html_smartypants.c \ - ../3rdParty/hoedown/version.c \ - ../3rdParty/libharu/src/hpdf_image_ccitt.c + ../3rdParty/hoedown/html_smartypants.c \ + ../3rdParty/hoedown/version.c \ + ../3rdParty/libharu/src/hpdf_image_ccitt.c # Linux specific settings unix { - QMAKE_CXXFLAGS += --std=gnu++11 - # QMAKE_CXXFLAGS -= -Wall - QMAKE_CXXFLAGS_WARN_ON=-w - QMAKE_CFLAGS_WARN_ON=-w - LIBS += -lpng -lz + QMAKE_CXXFLAGS += --std=gnu++11 + # QMAKE_CXXFLAGS -= -Wall + QMAKE_CXXFLAGS_WARN_ON=-w + QMAKE_CFLAGS_WARN_ON=-w + LIBS += -lpng -lz } @@ -160,77 +201,82 @@ # Windows specific. Note we compile in libpng and zlib statically on Windows win32 { - # Supress annoying warnings - QMAKE_CXXFLAGS += /wd"4996;4100" - QMAKE_CXXFLAGS_WARN_ON -= -w34100 + # Supress annoying warnings + QMAKE_CXXFLAGS += /wd"4996;4100" + QMAKE_CXXFLAGS_WARN_ON -= -w34100 - # Release mode debugging - QMAKE_CXXFLAGS += /Zi - QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF + # Release mode debugging + QMAKE_CXXFLAGS += /Zi + QMAKE_LFLAGS += /DEBUG /OPT:REF /OPT:ICF - # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything - Project.target = $${TARGET}.vcxproj - Project.output = $${TARGET}.vcxproj - Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 - Project.depends = '"$${_PRO_FILE_}"' - Project.input = _PRO_FILE_ - QMAKE_EXTRA_COMPILERS += Project + # This makes the .vcxproj depend on the .pro file, so editing the .pro file will update everything + Project.target = $${TARGET}.vcxproj + Project.output = $${TARGET}.vcxproj + Project.commands = c:\qt\qt5.4.1\5.4\msvc2013_64_opengl\bin\qmake -tp vc '"$${_PRO_FILE_}"' -spec win32-msvc2013 + Project.depends = '"$${_PRO_FILE_}"' + Project.input = _PRO_FILE_ + QMAKE_EXTRA_COMPILERS += Project - # This makes the documentation - MARKDOWN_FILES = \ - test.md \ - test2.md + # This makes the documentation + MARKDOWN_FILES = \ + test.md \ + test2.md - Documentation.target = test.pdf - Documentation.output = test.pdf - Documentation.commands = echo ' ' > test.pdf - Documentation.depends = '"$${MARKDOWN_FILES}"' - Documentation.input = MARKDOWN_FILES - QMAKE_EXTRA_COMPILERS += Documentation + Documentation.target = test.pdf + Documentation.output = test.pdf + Documentation.commands = echo ' ' > test.pdf + Documentation.depends = '"$${MARKDOWN_FILES}"' + Documentation.input = MARKDOWN_FILES + QMAKE_EXTRA_COMPILERS += Documentation - INCLUDEPATH += \ - ../3rdParty/libpng \ - ../3rdParty/zlib + INCLUDEPATH += \ + ../3rdParty/libpng \ + ../3rdParty/zlib - SOURCES += \ - ../3rdParty/libpng/png.c \ - ../3rdParty/libpng/pngerror.c \ - ../3rdParty/libpng/pngget.c \ - ../3rdParty/libpng/pngmem.c \ - ../3rdParty/libpng/pngpread.c \ - ../3rdParty/libpng/pngread.c \ - ../3rdParty/libpng/pngrio.c \ - ../3rdParty/libpng/pngrtran.c \ - ../3rdParty/libpng/pngrutil.c \ - ../3rdParty/libpng/pngset.c \ - ../3rdParty/libpng/pngtrans.c \ - ../3rdParty/libpng/pngwio.c \ - ../3rdParty/libpng/pngwrite.c \ - ../3rdParty/libpng/pngwtran.c \ - ../3rdParty/libpng/pngwutil.c + SOURCES += \ + ../3rdParty/libpng/png.c \ + ../3rdParty/libpng/pngerror.c \ + ../3rdParty/libpng/pngget.c \ + ../3rdParty/libpng/pngmem.c \ + ../3rdParty/libpng/pngpread.c \ + ../3rdParty/libpng/pngread.c \ + ../3rdParty/libpng/pngrio.c \ + ../3rdParty/libpng/pngrtran.c \ + ../3rdParty/libpng/pngrutil.c \ + ../3rdParty/libpng/pngset.c \ + ../3rdParty/libpng/pngtrans.c \ + ../3rdParty/libpng/pngwio.c \ + ../3rdParty/libpng/pngwrite.c \ + ../3rdParty/libpng/pngwtran.c \ + ../3rdParty/libpng/pngwutil.c - SOURCES += \ - ../3rdParty/zlib/inftrees.c \ - ../3rdParty/zlib/trees.c \ - ../3rdParty/zlib/uncompr.c \ - ../3rdParty/zlib/zutil.c \ - ../3rdParty/zlib/adler32.c \ - ../3rdParty/zlib/compress.c \ - ../3rdParty/zlib/crc32.c \ - ../3rdParty/zlib/deflate.c \ - ../3rdParty/zlib/gzclose.c \ - ../3rdParty/zlib/gzlib.c \ - ../3rdParty/zlib/gzread.c \ - ../3rdParty/zlib/gzwrite.c \ - ../3rdParty/zlib/infback.c \ - ../3rdParty/zlib/inffast.c \ - ../3rdParty/zlib/inflate.c + SOURCES += \ + ../3rdParty/zlib/inftrees.c \ + ../3rdParty/zlib/trees.c \ + ../3rdParty/zlib/uncompr.c \ + ../3rdParty/zlib/zutil.c \ + ../3rdParty/zlib/adler32.c \ + ../3rdParty/zlib/compress.c \ + ../3rdParty/zlib/crc32.c \ + ../3rdParty/zlib/deflate.c \ + ../3rdParty/zlib/gzclose.c \ + ../3rdParty/zlib/gzlib.c \ + ../3rdParty/zlib/gzread.c \ + ../3rdParty/zlib/gzwrite.c \ + ../3rdParty/zlib/infback.c \ + ../3rdParty/zlib/inffast.c \ + ../3rdParty/zlib/inflate.c } +OTHER_FILES += \ + ../Website/about.html \ + ../Website/register.html \ + ../Website/support.html + diff --git a/Resources/forms/About.ui b/Resources/forms/About.ui index bd6bdf3..3265d89 100644 --- a/Resources/forms/About.ui +++ b/Resources/forms/About.ui @@ -152,7 +152,7 @@ QFrame::Plain - + 20 @@ -165,7 +165,7 @@ <html><head/><body><p><a href="http://url.to.application/"><span style=" text-decoration: underline; color:#0000ff;">http://url.to.application/</span></a></p></body></html> - + 360 @@ -175,16 +175,16 @@ - - - - :/images/images/logo.svg + AppIcon true + + Qt::AlignCenter + - + 20 @@ -193,11 +193,18 @@ 31 + + + 20 + 75 + true + + - <html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Wicked Docs</span></p></body></html> + AppName - + 20 @@ -207,7 +214,7 @@ - <html><head/><body><p>Version 1.0.0.0001</p></body></html> + AppVer @@ -337,7 +344,7 @@ - <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://blah/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements / LicensesEULA</span></a></p></body></html> + <html><head/><body><p>Copyright (c) 2015 John Ryland / Subflexion. All Rights Reserved.</p><p><span style=" color:#5a5a5a;">This software is protected by copyright law and international treaties.</span></p><p><span style=" color:#5a5a5a;">By using this software you agree to the terms and conditions specified in</span><br/><span style=" color:#5a5a5a;">the License Agreement.</span></p><p><a href="http://sdfdsf/"><span style=" text-decoration: underline; color:#0000ff;">Acknowledgements &amp; Licenses</span></a>&nbsp;&nbsp;<a href="http://sfsdf/"><span style=" text-decoration: underline; color:#0000ff;">EULA</span></a></p></body></html> label_5 @@ -346,9 +353,7 @@
- - - + okayButton diff --git a/Resources/forms/ExtensibleObjectModelUI.ui b/Resources/forms/ExtensibleObjectModelUI.ui index 4a794d4..c3fcbc4 100644 --- a/Resources/forms/ExtensibleObjectModelUI.ui +++ b/Resources/forms/ExtensibleObjectModelUI.ui @@ -250,7 +250,7 @@ 0 - + @@ -347,7 +347,7 @@ - + @@ -478,6 +478,16 @@ + + + + + 0 + 200 + + + + @@ -921,6 +931,14 @@ + + + QWebView + QWidget +
QWebView
+ 1 +
+
diff --git a/Resources/forms/LicenseUpgrade.ui b/Resources/forms/LicenseUpgrade.ui index 69b55ad..4ce2ac1 100644 --- a/Resources/forms/LicenseUpgrade.ui +++ b/Resources/forms/LicenseUpgrade.ui @@ -42,7 +42,7 @@ Upgrade license - + 290 diff --git a/Resources/forms/SendBugReport.ui b/Resources/forms/SendBugReport.ui index 1a7d910..70e177e 100644 --- a/Resources/forms/SendBugReport.ui +++ b/Resources/forms/SendBugReport.ui @@ -6,8 +6,8 @@ 0 0 - 489 - 420 + 525 + 421 @@ -17,49 +17,49 @@ - Software information + System information 15 - + - Version: + Application: - + unknown - + OS Platform: - + unknown - + - Date/Time: + Version: - + unknown @@ -79,74 +79,83 @@ - - - - - - - System information - - - - 15 - - - - - Include system info in report - - - true - - - - - - - RAM: - - - - - - - unknown - - - - + CPU: - + unknown - + Resolution: - + unknown + + + + RAM: + + + + + + + unknown + + + + + + + Date/Time: + + + + + + + unknown + + + + + + Short description: + + + + + + + + + + Short text description of problem + + + + Bug description: @@ -154,14 +163,18 @@ - + + + Detailed description of the issue, such as the type of issue, (eg an improvement, bug, crash, usability problem) and the steps needed to reproduce the problem. Add any notes that you think may be relevant. + + - Email address: + Email address (optional): @@ -238,7 +251,6 @@ desc email - sendSysInfo diff --git a/Util.h b/Util.h index 1dfc996..25da56e 100644 --- a/Util.h +++ b/Util.h @@ -12,7 +12,7 @@ { return std::unique_ptr( new T( std::forward(args)... ) ); } -}; +} inline int fopen_s(FILE** a_file, const char* a_fileName, const char* a_mode) { diff --git a/Version.cpp b/Version.cpp index fb913ae..86e6110 100644 --- a/Version.cpp +++ b/Version.cpp @@ -1,131 +1,2 @@ #include "Version.h" -#include "Util.h" -#include -#include -#include - -#ifdef __APPLE__ -# include "TargetConditionals.h" -#elif defined(_WIN32) -# include -#else -# include -# include -# include -# include -#endif - - -void getSystemInfo(SystemInfo& a_info) -{ - a_info.m_cpuType = "unknown"; - a_info.m_osType = "unknown"; - a_info.m_osVersion = "unknown"; - -#ifdef _WIN32 - a_info.m_osType = "Windows"; - - // Get RAM size - MEMORYSTATUSEX status; - status.dwLength = sizeof(status); - GlobalMemoryStatusEx(&status); - a_info.m_ramSize = status.ullTotalPhys; - - // Get OS version - const OSVERSIONINFO osver = winOsVersion(); - a_info.m_osVersion.reserve(512); - snprintf(a_info.m_osVersion.data(), "%i.%i.%i", osver.dwMajorVersion, osver.dwMinorVersion, osver.dwBuildNumber); - - // Get OS arch - SYSTEM_INFO info; - GetNativeSystemInfo(&info); -# ifdef _WIN64 - //if (info.wProcessorArchitecture == ???) - a_info.m_cpuType = "x86_64"; -# else - a_info.m_cpuType = "x86"; -# endif -#else - long pages = sysconf(_SC_PHYS_PAGES); - long page_size = sysconf(_SC_PAGE_SIZE); - a_info.m_ramSize = pages * page_size; - struct utsname u; - long ret = uname(&u); - if (ret != -1) - { - a_info.m_cpuType = u.machine; - a_info.m_osVersion = u.sysname + std::string(" ") + u.release; - } -# ifdef __APPLE__ - // Get RAM Size - int mib[2] = { CTL_HW, HW_MEMSIZE }; - size_t len = sizeof(uint64_t); - sysctl(mib, sizeof(mib) / sizeof(mib[0]), &u.ramSize, &len, NULL, 0); -# if TARGET_OS_IPHONE - a_info.m_osType = "iOS"; -# elif TARGET_OS_MAC - const char *macCodeName = ""; - switch (int(MacintoshVersion)) { - case MV_CHEETAH: macCodeName = " Cheetah"; break; - case MV_PUMA: macCodeName = " Puma"; break; - case MV_JAGUAR: macCodeName = " Jaguar"; break; - case MV_PANTHER: macCodeName = " Panther"; break; - case MV_TIGER: macCodeName = " Tiger"; break; - case MV_LEOPARD: macCodeName = " Leopard"; break; - case MV_SNOWLEOPARD: macCodeName = " Snow Leopard"; break; - case MV_LION: macCodeName = " Lion"; break; - case MV_MOUNTAINLION:macCodeName = " Mountain Lion"; break; - case MV_MAVERICKS: macCodeName = " Mavericks"; break; - case MV_YOSEMITE: macCodeName = " Yosemite"; break; - } - a_info.m_osType = "Mac OS X" + std::string(macCodeName); -# endif -# elif __ANDROID__ - a_info.m_osType = "Android"; -# elif __linux - // system("lsb_release -sd"); - FILE* f = fopen("/etc/lsb-release", "rt"); - char dist[64] = { 0 }; - if (f) { - char buf[128]; - while (fgets(buf, 128, f) != 0) - if (sscanf(buf, "DISTRIB_DESCRIPTION=%64c", dist) == 1) - break; - if (dist[0]) { - std::vector strBits = split(dist, '"'); - a_info.m_osType = strBits[(strBits.size()==3)?1:0]; - } else { - a_info.m_osType = "non-specific LSB"; - } - fclose(f); - } else { - a_info.m_osType = "non-LSB"; - } -# else - a_info.m_osType = "Generic UNIX"; -# endif -#endif - - // TODO: improve the CPU detection using libcpuid - - // Make human readable RAM size string - const char* humanUnitStrings[] = { " bytes", " KB", " MB", " GB", " TB" }; - int ramUnit = 0; - uint64_t ramSize = a_info.m_ramSize; - while (ramSize > 1024 && ramUnit < (YQ_ARRAY_SIZE(humanUnitStrings)-1)) - ramUnit++, ramSize /= 1000; - a_info.m_ramSizeStr = std::to_string(ramSize) + humanUnitStrings[ramUnit]; - - // Obtain the screen properties - QScreen *s = QApplication::screens()[0]; - int refreshRate = (s) ? s->refreshRate() : 0; - int depth = (s) ? s->depth() : 0; - a_info.m_resolutionWidth = (s) ? s->geometry().width() : 0; - a_info.m_resolutionHeight = (s) ? s->geometry().height() : 0; - a_info.m_resolutionStr = std::to_string(a_info.m_resolutionWidth) + "x" - + std::to_string(a_info.m_resolutionHeight) + " " - + std::to_string(depth) + "bit " - + "@" + std::to_string(refreshRate) + "Hz"; - ; -} diff --git a/Version.h b/Version.h index 5dd615c..143467f 100644 --- a/Version.h +++ b/Version.h @@ -7,26 +7,12 @@ #include +#define APP_NAME "Wicked Docs" +#define APP_ICON ":/images/images/logo.svg" #define APP_VERSION 1.00 #define APP_BUILD 0001 #define APP_VER_STR YQ_STRINGIZE(APP_VERSION) "." YQ_STRINGIZE(APP_BUILD) -#define APP_VER_STR_LONG "Version " YQ_STRINGIZE(APP_VERSION) ", Build" YQ_STRINGIZE(APP_BUILD) - - -struct SystemInfo -{ - std::string m_cpuType; - std::string m_osType; - std::string m_osVersion; - std::string m_ramSizeStr; // Human friendly string, eg: "4 GB" - std::string m_resolutionStr; - uint64_t m_ramSize; - uint32_t m_resolutionWidth; - uint32_t m_resolutionHeight; -}; - - -void getSystemInfo(SystemInfo& a_info); +#define APP_VER_STR_LONG "Version " YQ_STRINGIZE(APP_VERSION) ", Build " YQ_STRINGIZE(APP_BUILD) #endif // VERSION_H diff --git a/main.cpp b/main.cpp index a4a0bd4..372f0bf 100644 --- a/main.cpp +++ b/main.cpp @@ -1,198 +1,17 @@ -// MakePDF.cpp : Defines the entry point for the console application. -// - -#define _CRT_SECURE_NO_WARNINGS -#include -#include -#include -#include - -#include "DocVisitor.h" -#include "DocTemplate.h" -#include "DocOutput.h" -#include "DocSVG.h" -#include "Util.h" - -//#include "document.h" -#include "html.h" -#include "tinyxml.h" - - -#ifndef _WIN32 -# include -//# define __cdecl -#else - extern "C" void __stdcall Sleep(unsigned int); -#endif - - #ifdef GUI_APP # include "ui.h" +#else +# include "DocConvert.h" #endif -#define DEF_IUNIT 1024 -#define DEF_OUNIT 64 -#define DEF_MAX_NESTING 16 - - extern void runTests(); -struct Context -{ - const char* title; - const char* inFileName; - const char* outFileName_PDF; - const char* outFileName_HTML; - DocOutputDevice* doc; - hoedown_buffer *inputBuffer; - hoedown_buffer *outputBuffer; -}; - - -static void RemoveFile(const char* fileName) -{ -#ifdef _WIN32 - FILE* tmpF = 0; - bool first = true; - do - { - fopen_s(&tmpF, fileName, "rb"); - if (tmpF) - { - fclose(tmpF); - _unlink(fileName); - ::Sleep(100); - if (first) - printf("waiting for output file to be removed."); - else - printf("."); - first = false; - fflush(stdout); - } - } while (tmpF != 0); -#else - unlink(fileName); -#endif -} - - -hoedown_buffer *ReadInWholeFile(const char* inputFileName) -{ - // Read in the markdown file - FILE* f = 0; - fopen_s(&f, inputFileName, "rt"); // text or binary? Can it be utf8, and if so, do I need to read in binary mode? - if (!f) - return 0; - /* - fseek(f, 0L, SEEK_END); - long fileSize = ftell(f); - fseek(f, 0L, SEEK_SET); - uint8_t* inputBuffer = (uint8_t*)malloc(fileSize); - size_t inputBufferSize = fread(inputBuffer, 1, fileSize, f); - */ - hoedown_buffer *ib = hoedown_buffer_new(DEF_IUNIT); - if (hoedown_buffer_putf(ib, f)) - fprintf(stderr, "I/O errors found while reading input.\n"); - - fclose(f); - return ib; -} - - -hoedown_buffer *ConvertMarkdownToHTML(uint8_t* inputBuffer, size_t inputBufferSize) -{ - hoedown_html_flags flags = (hoedown_html_flags)(HOEDOWN_HTML_ESCAPE | HOEDOWN_HTML_HARD_WRAP | HOEDOWN_HTML_USE_XHTML); - hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0); - hoedown_buffer *ob = hoedown_buffer_new(DEF_OUNIT); - hoedown_document *document = hoedown_document_new(renderer, HOEDOWN_EXT_SPACE_HEADERS, DEF_MAX_NESTING); - hoedown_document_render(document, ob, inputBuffer, inputBufferSize); - hoedown_document_free(document); - hoedown_html_renderer_free(renderer); - return ob; -} - - -void SVGTest(const char* a_fileName, double scale, DocOutputDevice* outputDoc) -{ - hoedown_buffer* inputBuffer = ReadInWholeFile(a_fileName); - if (!inputBuffer) - return; - // SVG xml parse - TiXmlDocument parser; - parser.Parse((char*)inputBuffer->data); - DocSVG visitor(scale); - parser.Accept(&visitor); - visitor.DumpOperations(); - visitor.WriteTo(outputDoc); - hoedown_buffer_free(inputBuffer); -} - - -void ConvertHTMLToPDF(uint8_t* inputBuffer, DocOutputDevice* outputDoc) -{ - // xml parse - DocStyle style; - DocTemplate templ; - TiXmlDocument parser; - - templ.ReadTemplateFile("test.tmpl"); - parser.Parse((char*)inputBuffer); - DocVisitor visitor(outputDoc, &style, &templ); - parser.Accept(&visitor); - - //SVGTest("test/triangle.svg", 0.02, outputDoc); - //SVGTest("test/ArcTest.svg", 1.0, outputDoc); -} - - -void SaveHTML(const char* fileName, const uint8_t* data, size_t dataSize) -{ - RemoveFile(fileName); - FILE* f = 0; - fopen_s(&f, fileName, "wb"); - if (!f) - return; - const char *CSSText = "test"; - fwrite(CSSText, 1, strlen(CSSText), f); - fwrite(data, 1, dataSize, f); - fclose(f); -} - - -int ProcessConversionContext(Context* context) -{ - context->inputBuffer = ReadInWholeFile(context->inFileName); - if (!context->inputBuffer) - return -1; - context->outputBuffer = ConvertMarkdownToHTML(context->inputBuffer->data, context->inputBuffer->size); - //free(inputBuffer); - hoedown_buffer_free(context->inputBuffer); - ConvertHTMLToPDF(context->outputBuffer->data, context->doc); - SaveHTML(context->outFileName_HTML, context->outputBuffer->data, context->outputBuffer->size); - hoedown_buffer_free(context->outputBuffer); - RemoveFile(context->outFileName_PDF); - context->doc->finalize(context->outFileName_PDF); - return 0; -} - - int main(int argc, char* argv[]) { - DocOutputDevice outputDoc; - Context context = { - "Test Markdown to PDF", - "test/test.md", - "test/test.pdf", - "test/test.html", - &outputDoc - }; - ProcessConversionContext(&context); - /* // Qt MDI Example does this: - Q_INIT_RESOURCE(mdi); QApplication app(argc, argv); QCoreApplication::setApplicationVersion(QT_VERSION_STR); @@ -217,9 +36,14 @@ //YQ_LOG_DEBUG("This is a test message"); //runTests(); app.exec(); +#else + DocConvert convertor; + convertor.SetTitle("Test Markdown to PDF"); + convertor.SetSource("test/test.md"); + convertor.OutputHTML("test/test.html"); + convertor.OutputPDF("test/test.pdf"); #endif - /* fprintf(stderr, "HERE!\n\n\n"); QApplication app2(argc, argv); @@ -229,7 +53,6 @@ app2.exec(); */ - return 0; } diff --git a/ui.h b/ui.h index c27187f..368df3f 100644 --- a/ui.h +++ b/ui.h @@ -13,7 +13,9 @@ #include "GenericTableUI.h" #include "MdiWindow.h" #include "Version.h" +#include "SystemInfomation.h" #include +#include class UiLogger : public Logger @@ -86,14 +88,19 @@ // Fill-in details SystemInfo sysInfo; getSystemInfo(sysInfo); - sendBugReport.ver->setText(APP_VER_STR); - sendBugReport.plat->setText(sysInfo.m_osType.c_str()); + sendBugReport.appName->setText(APP_NAME); + sendBugReport.appVer->setText(APP_VER_STR); + sendBugReport.platName->setText(sysInfo.m_osType.c_str()); sendBugReport.platVer->setText(sysInfo.m_osVersion.c_str()); sendBugReport.cpu->setText(sysInfo.m_cpuType.c_str()); sendBugReport.dateTime->setText(QDateTime::currentDateTime().toString()); sendBugReport.ram->setText(sysInfo.m_ramSizeStr.c_str()); sendBugReport.res->setText(sysInfo.m_resolutionStr.c_str()); + about.appName->setText(APP_NAME); + about.appVer->setText(APP_VER_STR_LONG); + about.appIcon->setPixmap(QPixmap(APP_ICON)); + // Setup standard keyboard short cuts appWindow.actionNew->setShortcuts(QKeySequence::New); appWindow.actionOpen->setShortcuts(QKeySequence::Open); @@ -118,6 +125,8 @@ appWindow.actionNext->setShortcuts(QKeySequence::NextChild); appWindow.actionPrevious->setShortcuts(QKeySequence::PreviousChild); + QObject::connect(licenseUpgrade.upgradeButton, SIGNAL(clicked()), &mainWindow, SLOT(upgradeClicked())); + QObject::connect(appWindow.actionExit, SIGNAL(triggered(bool)), qApp, SLOT(closeAllWindows())); QObject::connect(appWindow.actionAbout, SIGNAL(triggered(bool)), &aboutDialog, SLOT(exec())); QObject::connect(appWindow.actionCheck_for_Updates, SIGNAL(triggered(bool)), &checkUpdatesDialog, SLOT(exec()));