From e8b06cb33e6fbe6c614cd52575dd1514a4a00781 Mon Sep 17 00:00:00 2001 From: Aleks Kissinger Date: Tue, 30 Oct 2018 17:31:58 +0100 Subject: started popple --- src/gui/previewwindow.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/gui/previewwindow.h (limited to 'src/gui/previewwindow.h') diff --git a/src/gui/previewwindow.h b/src/gui/previewwindow.h new file mode 100644 index 0000000..5c4a384 --- /dev/null +++ b/src/gui/previewwindow.h @@ -0,0 +1,22 @@ +#ifndef PREVIEWWINDOW_H +#define PREVIEWWINDOW_H + +#include + +namespace Ui { +class PreviewWindow; +} + +class PreviewWindow : public QDialog +{ + Q_OBJECT + +public: + explicit PreviewWindow(QWidget *parent = nullptr); + ~PreviewWindow(); + +private: + Ui::PreviewWindow *ui; +}; + +#endif // PREVIEWWINDOW_H -- cgit v1.2.3 From a991943e59bc4341ceef55313642b85565454d86 Mon Sep 17 00:00:00 2001 From: Aleks Kissinger Date: Sun, 16 Dec 2018 16:04:02 +0100 Subject: added dummy preview window, linked to poppler --- CMakeLists.txt | 12 ++++++++- src/gui/previewwindow.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++++ src/gui/previewwindow.h | 7 ++++++ src/gui/previewwindow.ui | 63 +++++++++++++++++++++++++++++++++++++++++++++-- src/tikzit.cpp | 4 +++ 5 files changed, 144 insertions(+), 3 deletions(-) (limited to 'src/gui/previewwindow.h') diff --git a/CMakeLists.txt b/CMakeLists.txt index ba0eee5..311dac4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,11 @@ find_package(Qt5 REQUIRED COMPONENTS Core Gui Widgets Network) find_package(BISON) find_package(FLEX) +# use extra-cmake-modules to find poppler library +find_package(ECM REQUIRED NO_MODULE) +set(CMAKE_MODULE_PATH ${ECM_FIND_MODULE_DIR}) +find_package(Poppler REQUIRED COMPONENTS Core Qt5) + include_directories( ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/src @@ -38,6 +43,7 @@ set(SOURCES src/gui/mainmenu.cpp src/gui/mainwindow.cpp src/gui/nodeitem.cpp + src/gui/previewwindow.cpp src/gui/propertypalette.cpp src/gui/styleeditor.cpp src/gui/stylepalette.cpp @@ -67,6 +73,7 @@ set(HEADERS src/gui/mainmenu.h src/gui/mainwindow.h src/gui/nodeitem.h + src/gui/previewwindow.h src/gui/propertypalette.h src/gui/styleeditor.h src/gui/stylepalette.h @@ -81,6 +88,7 @@ set(HEADERS set(FORMS src/gui/mainmenu.ui src/gui/mainwindow.ui + src/gui/previewwindow.ui src/gui/propertypalette.ui src/gui/styleeditor.ui src/gui/stylepalette.ui @@ -99,4 +107,6 @@ add_executable(tikzit ${BISON_PARSER_OUTPUTS} ${QT_RESOURCES}) -target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Network) +target_link_libraries(${PROJECT_NAME} + Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Network + ${Poppler_LIBRARIES}) diff --git a/src/gui/previewwindow.cpp b/src/gui/previewwindow.cpp index 945c77e..bca28e3 100644 --- a/src/gui/previewwindow.cpp +++ b/src/gui/previewwindow.cpp @@ -1,14 +1,75 @@ #include "previewwindow.h" #include "ui_previewwindow.h" +#include +#include +#include +#include +#include +#include +#include + PreviewWindow::PreviewWindow(QWidget *parent) : QDialog(parent), ui(new Ui::PreviewWindow) { + QSettings settings("tikzit", "tikzit"); ui->setupUi(this); + + QVariant geom = settings.value("geometry-preview"); + + if (geom.isValid()) { + restoreGeometry(geom.toByteArray()); + } + + _doc = Poppler::Document::load("/home/aleks/ak-algebras.pdf"); + _doc->setRenderHint(Poppler::Document::Antialiasing); + _doc->setRenderHint(Poppler::Document::TextAntialiasing); + _doc->setRenderHint(Poppler::Document::TextHinting ); + _page = _doc->page(0); + + render(); } PreviewWindow::~PreviewWindow() { delete ui; } + +void PreviewWindow::closeEvent(QCloseEvent *e) { + QSettings settings("tikzit", "tikzit"); + settings.setValue("geometry-preview", saveGeometry()); +} + +void PreviewWindow::resizeEvent(QResizeEvent *e) { + render(); + QDialog::resizeEvent(e); +} + +void PreviewWindow::showEvent(QShowEvent *e) { + render(); + QDialog::showEvent(e); +} + +void PreviewWindow::render() { + QSizeF size = _page->pageSizeF(); + + QRect rect = ui->scrollArea->visibleRegion().boundingRect(); + int w = rect.width(); + int h = rect.height(); + qreal scale = fmin(static_cast(w) / size.width(), + static_cast(h) / size.height()); + int dpi = static_cast(scale * 72.0); + int w1 = static_cast(scale * size.width()); + int h1 = static_cast(scale * size.height()); + + // qDebug() << "visible width:" << w; + // qDebug() << "visible height:" << h; + // qDebug() << "doc width:" << size.width(); + // qDebug() << "doc height:" << size.height(); + // qDebug() << "scale:" << scale; + // qDebug() << "dpi:" << dpi; + + QImage img = _page->renderToImage(dpi,dpi, (w1 - w)/2, (h1 - h)/2, w, h); + ui->pdf->setPixmap(QPixmap::fromImage(img)); +} diff --git a/src/gui/previewwindow.h b/src/gui/previewwindow.h index 5c4a384..f2366d6 100644 --- a/src/gui/previewwindow.h +++ b/src/gui/previewwindow.h @@ -2,6 +2,7 @@ #define PREVIEWWINDOW_H #include +#include namespace Ui { class PreviewWindow; @@ -14,9 +15,15 @@ class PreviewWindow : public QDialog public: explicit PreviewWindow(QWidget *parent = nullptr); ~PreviewWindow(); + void resizeEvent(QResizeEvent *e); + void showEvent(QShowEvent *e); + void closeEvent(QCloseEvent *e); private: Ui::PreviewWindow *ui; + void render(); + Poppler::Document *_doc; + Poppler::Page *_page; }; #endif // PREVIEWWINDOW_H diff --git a/src/gui/previewwindow.ui b/src/gui/previewwindow.ui index 59224aa..6bb993a 100644 --- a/src/gui/previewwindow.ui +++ b/src/gui/previewwindow.ui @@ -1,6 +1,7 @@ + PreviewWindow - + 0 @@ -10,8 +11,66 @@ - Dialog + Preview + + + + + 0 + + + + PDF + + + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 358 + 233 + + + + + + + + + + + + + + + + + + + Output + + + + + + + + + + diff --git a/src/tikzit.cpp b/src/tikzit.cpp index 1c3ba23..d69f4a8 100644 --- a/src/tikzit.cpp +++ b/src/tikzit.cpp @@ -19,6 +19,7 @@ #include "tikzit.h" #include "tikzassembler.h" #include "tikzstyles.h" +#include "previewwindow.h" #include #include @@ -126,6 +127,9 @@ void Tikzit::init() if (check.toBool()) { checkForUpdates(); } + + PreviewWindow *preview = new PreviewWindow(); + preview->show(); } //QMenuBar *Tikzit::mainMenu() const -- cgit v1.2.3 From 6121b486e168334db70cbbe7a67afe56c0272748 Mon Sep 17 00:00:00 2001 From: Aleks Kissinger Date: Mon, 17 Dec 2018 12:37:15 +0100 Subject: preview almost works --- src/gui/latexprocess.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++++++ src/gui/latexprocess.h | 33 ++++++++++++++++ src/gui/mainmenu.cpp | 5 +++ src/gui/mainmenu.h | 1 + src/gui/mainmenu.ui | 9 +++++ src/gui/previewwindow.cpp | 37 +++++++++++++++--- src/gui/previewwindow.h | 6 +++ src/gui/previewwindow.ui | 8 ++-- src/tikzit.cpp | 33 +++++++++++++++- src/tikzit.h | 6 +++ tex/sample/tikzit.sty | 2 +- tikzit.pro | 6 ++- tikzit.qrc | 1 + 13 files changed, 231 insertions(+), 14 deletions(-) create mode 100644 src/gui/latexprocess.cpp create mode 100644 src/gui/latexprocess.h (limited to 'src/gui/previewwindow.h') diff --git a/src/gui/latexprocess.cpp b/src/gui/latexprocess.cpp new file mode 100644 index 0000000..f81e883 --- /dev/null +++ b/src/gui/latexprocess.cpp @@ -0,0 +1,98 @@ +#include "latexprocess.h" +#include "tikzit.h" + +#include +#include +#include + +LatexProcess::LatexProcess(PreviewWindow *preview, QObject *parent) : QObject(parent) +{ + _preview = preview; + _output = preview->outputTextEdit(); + + _proc = new QProcess(this); + _proc->setProcessChannelMode(QProcess::MergedChannels); + _proc->setWorkingDirectory(_workingDir.path()); + + connect(_proc, SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput())); + connect(_proc, SIGNAL(finished(int)), this, SLOT(finished(int))); + + // for debug purposes + _workingDir.setAutoRemove(false); +} + +void LatexProcess::makePreview(QString tikz) +{ + _output->clear(); + + if (!_workingDir.isValid()) { + _output->appendPlainText("COULD NOT WRITE TO TEMP DIR: " + _workingDir.path() + "\n"); + return; + } + + _output->appendPlainText("USING TEMP DIR: " + _workingDir.path() + "\n"); + _output->appendPlainText("SEARCHING FOR pdflatex IN:"); + _output->appendPlainText(qgetenv("PATH")); + _output->appendPlainText("\n"); + + + QString pdflatex = QStandardPaths::findExecutable("pdflatex"); + if (pdflatex.isEmpty()) { + _output->appendPlainText("pdflatex NOT FOUND, ABORTING.\n"); + return; + } + + _output->appendPlainText("FOUND: " + pdflatex + "\n"); + + // copy active *.tikzstyles file to preview dir + if (!tikzit->styleFile().isEmpty() && QFile::exists(tikzit->styleFilePath())) { + QFile::copy(tikzit->styleFilePath(), _workingDir.path() + "/" + tikzit->styleFile()); + } + + // copy tikzit.sty to preview dir + QFile::copy(":/tex/sample/tikzit.sty", _workingDir.path() + "/tikzit.sty"); + + // write out the file containing the tikz picture + QFile f(_workingDir.path() + "/preview.tex"); + f.open(QIODevice::WriteOnly); + QTextStream tex(&f); + tex << "\\documentclass{article}\n"; + tex << "\\usepackage[active,tightpage]{preview}\n"; + tex << "\\PreviewEnvironment{tikzpicture}\n"; + tex << "\\usepackage{tikzit}\n"; + tex << "\\input{" + tikzit->styleFile() + "}\n"; + tex << "\\begin{document}\n\n"; + tex << tikz; + tex << "\n\n\\end{document}\n"; + + f.close(); + _proc->start(pdflatex, QStringList() << "preview.tex"); + +} + +void LatexProcess::kill() +{ + if (_proc->state() == QProcess::Running) _proc->kill(); +} + +void LatexProcess::readyReadStandardOutput() +{ + QByteArray s = _proc->readAllStandardOutput(); + _output->appendPlainText(s); +} + +void LatexProcess::finished(int exitCode) +{ + QByteArray s = _proc->readAllStandardOutput(); + _output->appendPlainText(s); + + if (exitCode == 0) { + QString pdf = _workingDir.path() + "/preview.pdf"; + _output->appendPlainText("\n\nSUCCESSFULLY GENERATED: " + pdf + "\n"); + //_preview->setPdf(pdf); + emit previewFinished(); + } else { + _output->appendPlainText("\n\npdflatex RETURNED AN ERROR\n"); + emit previewFinished(); + } +} diff --git a/src/gui/latexprocess.h b/src/gui/latexprocess.h new file mode 100644 index 0000000..dc815f2 --- /dev/null +++ b/src/gui/latexprocess.h @@ -0,0 +1,33 @@ +#ifndef LATEXPROCESS_H +#define LATEXPROCESS_H + +#include "previewwindow.h" + +#include +#include +#include +#include + +class LatexProcess : public QObject +{ + Q_OBJECT +public: + explicit LatexProcess(PreviewWindow *preview, QObject *parent = nullptr); + void makePreview(QString tikz); + void kill(); + +private: + QTemporaryDir _workingDir; + PreviewWindow *_preview; + QPlainTextEdit *_output; + QProcess *_proc; + +public slots: + void readyReadStandardOutput(); + void finished(int exitCode); + +signals: + void previewFinished(); +}; + +#endif // LATEXPROCESS_H diff --git a/src/gui/mainmenu.cpp b/src/gui/mainmenu.cpp index 8166c59..ab1b898 100644 --- a/src/gui/mainmenu.cpp +++ b/src/gui/mainmenu.cpp @@ -228,6 +228,11 @@ void MainMenu::on_actionJump_to_Selection_triggered() } } +void MainMenu::on_actionRun_LaTeX_triggered() +{ + tikzit->makePreview(); +} + // View void MainMenu::on_actionZoom_In_triggered() diff --git a/src/gui/mainmenu.h b/src/gui/mainmenu.h index c14a284..e1477b4 100644 --- a/src/gui/mainmenu.h +++ b/src/gui/mainmenu.h @@ -67,6 +67,7 @@ public slots: void on_actionParse_triggered(); void on_actionRevert_triggered(); void on_actionJump_to_Selection_triggered(); + void on_actionRun_LaTeX_triggered(); // View void on_actionZoom_In_triggered(); diff --git a/src/gui/mainmenu.ui b/src/gui/mainmenu.ui index 0481c1d..58a2ff0 100644 --- a/src/gui/mainmenu.ui +++ b/src/gui/mainmenu.ui @@ -74,6 +74,7 @@ + @@ -335,6 +336,14 @@ About + + + Run LaTeX + + + Ctrl+R + + diff --git a/src/gui/previewwindow.cpp b/src/gui/previewwindow.cpp index bca28e3..0a37e1b 100644 --- a/src/gui/previewwindow.cpp +++ b/src/gui/previewwindow.cpp @@ -1,12 +1,18 @@ #include "previewwindow.h" #include "ui_previewwindow.h" +#include "tikzit.h" +#include "latexprocess.h" + #include #include #include #include -#include #include +#include +#include +#include +#include #include PreviewWindow::PreviewWindow(QWidget *parent) : @@ -22,23 +28,42 @@ PreviewWindow::PreviewWindow(QWidget *parent) : restoreGeometry(geom.toByteArray()); } - _doc = Poppler::Document::load("/home/aleks/ak-algebras.pdf"); + _doc = nullptr; + _page = nullptr; + //setPdf("/home/aleks/ak-algebras.pdf"); + + //qDebug() << "preview dir:" << preparePreview("foo"); + + render(); +} + +PreviewWindow::~PreviewWindow() +{ + delete ui; +} + +void PreviewWindow::setPdf(QString file) +{ + Poppler::Document *oldDoc = _doc; + _doc = Poppler::Document::load(file); _doc->setRenderHint(Poppler::Document::Antialiasing); _doc->setRenderHint(Poppler::Document::TextAntialiasing); _doc->setRenderHint(Poppler::Document::TextHinting ); _page = _doc->page(0); - render(); + + if (oldDoc != nullptr) delete oldDoc; } -PreviewWindow::~PreviewWindow() +QPlainTextEdit *PreviewWindow::outputTextEdit() { - delete ui; + return ui->output; } void PreviewWindow::closeEvent(QCloseEvent *e) { QSettings settings("tikzit", "tikzit"); settings.setValue("geometry-preview", saveGeometry()); + QDialog::closeEvent(e); } void PreviewWindow::resizeEvent(QResizeEvent *e) { @@ -52,6 +77,8 @@ void PreviewWindow::showEvent(QShowEvent *e) { } void PreviewWindow::render() { + if (_page == nullptr) return; + QSizeF size = _page->pageSizeF(); QRect rect = ui->scrollArea->visibleRegion().boundingRect(); diff --git a/src/gui/previewwindow.h b/src/gui/previewwindow.h index f2366d6..c850ce9 100644 --- a/src/gui/previewwindow.h +++ b/src/gui/previewwindow.h @@ -2,6 +2,7 @@ #define PREVIEWWINDOW_H #include +#include #include namespace Ui { @@ -15,6 +16,11 @@ class PreviewWindow : public QDialog public: explicit PreviewWindow(QWidget *parent = nullptr); ~PreviewWindow(); + void setPdf(QString file); + QString preparePreview(QString tikz); + QPlainTextEdit *outputTextEdit(); + +protected: void resizeEvent(QResizeEvent *e); void showEvent(QShowEvent *e); void closeEvent(QCloseEvent *e); diff --git a/src/gui/previewwindow.ui b/src/gui/previewwindow.ui index 6bb993a..394fc41 100644 --- a/src/gui/previewwindow.ui +++ b/src/gui/previewwindow.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 300 + 603 + 480 @@ -40,8 +40,8 @@ 0 0 - 358 - 233 + 561 + 413 diff --git a/src/tikzit.cpp b/src/tikzit.cpp index d69f4a8..5f74d0b 100644 --- a/src/tikzit.cpp +++ b/src/tikzit.cpp @@ -20,6 +20,7 @@ #include "tikzassembler.h" #include "tikzstyles.h" #include "previewwindow.h" +#include "latexprocess.h" #include #include @@ -30,6 +31,7 @@ #include #include + // application-level instance of Tikzit Tikzit *tikzit; @@ -107,6 +109,8 @@ void Tikzit::init() _windows << new MainWindow(); _windows[0]->show(); + _styleFile = ""; + _styleFilePath = ""; QString styleFile = settings.value("previous-tikzstyles-file").toString(); if (!styleFile.isEmpty()) loadStyles(styleFile); @@ -128,8 +132,8 @@ void Tikzit::init() checkForUpdates(); } - PreviewWindow *preview = new PreviewWindow(); - preview->show(); + _preview = new PreviewWindow(); + _latex = nullptr; } //QMenuBar *Tikzit::mainMenu() const @@ -415,6 +419,31 @@ void Tikzit::updateReply(QNetworkReply *reply) } } +void Tikzit::makePreview() +{ + if (activeWindow()) { + LatexProcess *oldProc = _latex; + _latex = new LatexProcess(_preview, this); + if (oldProc != nullptr) { + oldProc->kill(); + oldProc->deleteLater(); + } + + connect(_latex, SIGNAL(previewFinished()), this, SLOT(cleanupLatex())); + _latex->makePreview(activeWindow()->tikzSource()); + _preview->show(); + } +} + +void Tikzit::cleanupLatex() +{ + LatexProcess *oldProc = _latex; + _latex = nullptr; + if (oldProc != nullptr) { + oldProc->deleteLater(); + } +} + //StylePalette *Tikzit::stylePalette() const //{ // return _stylePalette; diff --git a/src/tikzit.h b/src/tikzit.h index 5fed22c..3d4847d 100644 --- a/src/tikzit.h +++ b/src/tikzit.h @@ -60,6 +60,8 @@ #include "propertypalette.h" #include "stylepalette.h" #include "tikzstyles.h" +#include "latexprocess.h" +#include "previewwindow.h" #include #include @@ -137,6 +139,8 @@ public slots: void setCheckForUpdates(bool check); void checkForUpdates(); void updateReply(QNetworkReply *reply); + void makePreview(); + void cleanupLatex(); private: // void createMenu(); @@ -153,6 +157,8 @@ private: StyleEditor *_styleEditor; QStringList _colNames; QVector _cols; + LatexProcess *_latex; + PreviewWindow *_preview; }; extern Tikzit *tikzit; diff --git a/tex/sample/tikzit.sty b/tex/sample/tikzit.sty index b893a4a..9c51148 100644 --- a/tex/sample/tikzit.sty +++ b/tex/sample/tikzit.sty @@ -29,4 +29,4 @@ \pgfsetlayers{background,edgelayer,nodelayer,main} \tikzstyle{none}=[inner sep=0mm] \tikzstyle{every loop}=[] -\tikzstyle{mark coordinate}=[inner sep=0pt,outer sep=0pt,minimum size=3pt,fill=black,circle] \ No newline at end of file +\tikzstyle{mark coordinate}=[inner sep=0pt,outer sep=0pt,minimum size=3pt,fill=black,circle] diff --git a/tikzit.pro b/tikzit.pro index e1e07b4..82b4032 100644 --- a/tikzit.pro +++ b/tikzit.pro @@ -72,7 +72,8 @@ SOURCES += src/gui/mainwindow.cpp \ src/data/style.cpp \ src/gui/styleeditor.cpp \ src/data/stylelist.cpp \ - src/gui/previewwindow.cpp + src/gui/previewwindow.cpp \ + src/gui/latexprocess.cpp HEADERS += src/gui/mainwindow.h \ src/gui/toolpalette.h \ @@ -99,7 +100,8 @@ HEADERS += src/gui/mainwindow.h \ src/data/style.h \ src/gui/styleeditor.h \ src/data/stylelist.h \ - src/gui/previewwindow.h + src/gui/previewwindow.h \ + src/gui/latexprocess.h FORMS += src/gui/mainwindow.ui \ src/gui/propertypalette.ui \ diff --git a/tikzit.qrc b/tikzit.qrc index 0484c2d..32bdfc8 100644 --- a/tikzit.qrc +++ b/tikzit.qrc @@ -8,6 +8,7 @@ images/refresh.svg images/tikzit.png images/text-x-generic_with_pencil.svg + tex/sample/tikzit.sty qt.conf -- cgit v1.2.3 From c93f003ce683fca7896cbbadb6375b929d22fe6d Mon Sep 17 00:00:00 2001 From: Aleks Kissinger Date: Sat, 22 Dec 2018 18:06:26 +0100 Subject: latex running feedback and better search for pdflatex --- images/dialog-accept.svg | 63 +++++++++ images/dialog-error.svg | 316 ++++++++++++++++++++++++++++++++++++++++++++++ images/loader.gif | Bin 0 -> 1456 bytes images/loader@2x.gif | Bin 0 -> 1456 bytes src/gui/latexprocess.cpp | 30 ++++- src/gui/previewwindow.cpp | 41 +++++- src/gui/previewwindow.h | 11 +- src/gui/previewwindow.ui | 34 ++++- src/tikzit.cpp | 18 +-- tikzit.qrc | 4 + 10 files changed, 500 insertions(+), 17 deletions(-) create mode 100644 images/dialog-accept.svg create mode 100644 images/dialog-error.svg create mode 100644 images/loader.gif create mode 100644 images/loader@2x.gif (limited to 'src/gui/previewwindow.h') diff --git a/images/dialog-accept.svg b/images/dialog-accept.svg new file mode 100644 index 0000000..287b11e --- /dev/null +++ b/images/dialog-accept.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Rodney Dawes + + + + + Jakub Steiner, Garrett LeSage + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/dialog-error.svg b/images/dialog-error.svg new file mode 100644 index 0000000..9071b53 --- /dev/null +++ b/images/dialog-error.svg @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Rodney Dawes + + + + + Jakub Steiner, Garrett LeSage + + + + Dialog Error + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/loader.gif b/images/loader.gif new file mode 100644 index 0000000..078b55f Binary files /dev/null and b/images/loader.gif differ diff --git a/images/loader@2x.gif b/images/loader@2x.gif new file mode 100644 index 0000000..078b55f Binary files /dev/null and b/images/loader@2x.gif differ diff --git a/src/gui/latexprocess.cpp b/src/gui/latexprocess.cpp index 20b22a4..82c1c5b 100644 --- a/src/gui/latexprocess.cpp +++ b/src/gui/latexprocess.cpp @@ -4,6 +4,7 @@ #include #include #include +#include LatexProcess::LatexProcess(PreviewWindow *preview, QObject *parent) : QObject(parent) { @@ -23,6 +24,7 @@ LatexProcess::LatexProcess(PreviewWindow *preview, QObject *parent) : QObject(pa void LatexProcess::makePreview(QString tikz) { + _preview->setStatus(PreviewWindow::Running); _output->clear(); if (!_workingDir.isValid()) { @@ -38,8 +40,28 @@ void LatexProcess::makePreview(QString tikz) QString pdflatex = QStandardPaths::findExecutable("pdflatex"); if (pdflatex.isEmpty()) { - _output->appendPlainText("pdflatex NOT FOUND, ABORTING.\n"); - return; + // if pdflatex is not in PATH, we are probably on mac or windows, so try common + // install directories. + _output->appendPlainText("NOT FOUND IN PATH, TRYING:"); + + QStringList texDirs; + // common macOS tex directories: + texDirs << "/Library/TeX/texbin"; + texDirs << "/usr/texbin"; + texDirs << "/usr/local/bin"; + texDirs << "/sw/bin"; + + // common windows tex directories + texDirs << "C:\\Program Files\\MiKTeX 2.9\\miktex\\bin"; + texDirs << "C:\\Program Files\\MiKTeX 2.9\\miktex\\bin\\x64"; + + _output->appendPlainText(texDirs.join(":")); + pdflatex = QStandardPaths::findExecutable("pdflatex", texDirs); + + if (pdflatex.isEmpty()) { + _output->appendPlainText("pdflatex NOT FOUND, ABORTING.\n"); + return; + } } _output->appendPlainText("FOUND: " + pdflatex + "\n"); @@ -66,7 +88,7 @@ void LatexProcess::makePreview(QString tikz) tex << "\n\n\\end{document}\n"; f.close(); - _proc->start(pdflatex, QStringList() << "preview.tex"); + _proc->start(pdflatex, QStringList() << "-interaction=nonstopmode" << "preview.tex"); } @@ -90,9 +112,11 @@ void LatexProcess::finished(int exitCode) QString pdf = _workingDir.path() + "/preview.pdf"; _output->appendPlainText("\n\nSUCCESSFULLY GENERATED: " + pdf + "\n"); _preview->setPdf(pdf); + _preview->setStatus(PreviewWindow::Success); emit previewFinished(); } else { _output->appendPlainText("\n\npdflatex RETURNED AN ERROR\n"); + _preview->setStatus(PreviewWindow::Failed); emit previewFinished(); } } diff --git a/src/gui/previewwindow.cpp b/src/gui/previewwindow.cpp index 724a951..726ec8a 100644 --- a/src/gui/previewwindow.cpp +++ b/src/gui/previewwindow.cpp @@ -15,6 +15,7 @@ #include #include #include +#include PreviewWindow::PreviewWindow(QWidget *parent) : QDialog(parent), @@ -31,10 +32,15 @@ PreviewWindow::PreviewWindow(QWidget *parent) : _doc = nullptr; _page = nullptr; - //setPdf("/home/aleks/ak-algebras.pdf"); - //qDebug() << "preview dir:" << preparePreview("foo"); + _loader = new QLabel(this); + _loader->setMinimumSize(QSize(16,16)); + _loader->setMaximumSize(QSize(16,16)); + ui->tabWidget->tabBar()->setTabButton(1, QTabBar::RightSide, _loader); + connect(ui->tabWidget, SIGNAL(currentChanged(int)), + this, SLOT(render())); + render(); } @@ -76,6 +82,37 @@ QPlainTextEdit *PreviewWindow::outputTextEdit() return ui->output; } +void PreviewWindow::setStatus(PreviewWindow::Status status) +{ + QMovie *oldMovie = _loader->movie(); + if (status == PreviewWindow::Running) { + // loader.gif and loader@2x.gif derived from: + // https://commons.wikimedia.org/wiki/Throbbers#/media/File:Linux_Ubuntu_Loader.gif + // licensed GNU Free Documentation License v1.2 + QMovie *movie = new QMovie( + (devicePixelRatioF() > 1.0) ? ":images/loader@2x.gif" : ":images/loader.gif", + QByteArray(), _loader); + _loader->setPixmap(QPixmap()); + _loader->setMovie(movie); + movie->start(); + } else if (status == PreviewWindow::Success) { + _loader->setMovie(nullptr); + QPixmap accept(":images/dialog-accept.svg"); + accept.setDevicePixelRatio(devicePixelRatio()); + _loader->setPixmap(accept); + } else if (status == PreviewWindow::Failed) { + _loader->setMovie(nullptr); + QPixmap error(":images/dialog-error.svg"); + error.setDevicePixelRatio(devicePixelRatio()); + _loader->setPixmap(error); + } + + if (oldMovie != nullptr) oldMovie->deleteLater(); + + + _loader->repaint(); +} + void PreviewWindow::closeEvent(QCloseEvent *e) { QSettings settings("tikzit", "tikzit"); settings.setValue("geometry-preview", saveGeometry()); diff --git a/src/gui/previewwindow.h b/src/gui/previewwindow.h index c850ce9..a937263 100644 --- a/src/gui/previewwindow.h +++ b/src/gui/previewwindow.h @@ -1,7 +1,9 @@ #ifndef PREVIEWWINDOW_H #define PREVIEWWINDOW_H + #include +#include #include #include @@ -14,11 +16,18 @@ class PreviewWindow : public QDialog Q_OBJECT public: + enum Status { + Running, Success, Failed + }; explicit PreviewWindow(QWidget *parent = nullptr); ~PreviewWindow(); void setPdf(QString file); QString preparePreview(QString tikz); QPlainTextEdit *outputTextEdit(); + void setStatus(Status status); + +public slots: + void render(); protected: void resizeEvent(QResizeEvent *e); @@ -27,9 +36,9 @@ protected: private: Ui::PreviewWindow *ui; - void render(); Poppler::Document *_doc; Poppler::Page *_page; + QLabel *_loader; }; #endif // PREVIEWWINDOW_H diff --git a/src/gui/previewwindow.ui b/src/gui/previewwindow.ui index 394fc41..7da886a 100644 --- a/src/gui/previewwindow.ui +++ b/src/gui/previewwindow.ui @@ -14,16 +14,46 @@ Preview + + 3 + + + 3 + + + 3 + + + 3 + 0 + + false + + + false + PDF + + 0 + + + 0 + + + 0 + + + 0 + @@ -40,8 +70,8 @@ 0 0 - 561 - 413 + 591 + 448 diff --git a/src/tikzit.cpp b/src/tikzit.cpp index 39a2924..e12053b 100644 --- a/src/tikzit.cpp +++ b/src/tikzit.cpp @@ -31,14 +31,13 @@ #include #include - // application-level instance of Tikzit Tikzit *tikzit; // font to use for node labels QFont Tikzit::LABEL_FONT("Courrier", 9); -Tikzit::Tikzit() : _styleFile("[no styles]"), _activeWindow(0) +Tikzit::Tikzit() : _styleFile("[no styles]"), _activeWindow(nullptr) { } @@ -116,7 +115,7 @@ void Tikzit::init() QVariant check = settings.value("check-for-updates"); if (check.isNull()) { - int resp = QMessageBox::question(0, + int resp = QMessageBox::question(nullptr, tr("Check for updates"), tr("Would you like TikZiT to check for updates automatically?" " (You can always change this later in the Help menu.)"), @@ -213,7 +212,7 @@ void Tikzit::newTikzStyles() w->tikzScene()->reloadStyles(); } } else { - QMessageBox::warning(0, + QMessageBox::warning(nullptr, "Could not write to style file.", "Could not write to: '" + fileName + "'. Check file permissions or choose a new location."); } @@ -252,7 +251,7 @@ void Tikzit::removeWindow(MainWindow *w) _windows.removeAll(w); if (_activeWindow == w) { if (_windows.isEmpty()) { - _activeWindow = 0; + _activeWindow = nullptr; // TODO: check if we should quit when last window closed quit(); } else _activeWindow = _windows[0]; @@ -262,7 +261,7 @@ void Tikzit::removeWindow(MainWindow *w) void Tikzit::open() { QSettings settings("tikzit", "tikzit"); - QString fileName = QFileDialog::getOpenFileName(0, + QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open File"), settings.value("previous-file-path").toString(), tr("TiKZ Files (*.tikz)"), @@ -293,7 +292,7 @@ void Tikzit::open(QString fileName) void Tikzit::openTikzStyles() { QSettings settings("tikzit", "tikzit"); - QString fileName = QFileDialog::getOpenFileName(0, + QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open File"), settings.value("previous-tikzstyles-path").toString(), tr("TiKZ Style Files (*.tikzstyles)"), @@ -326,7 +325,7 @@ bool Tikzit::loadStyles(QString fileName) } return true; } else { - QMessageBox::warning(0, + QMessageBox::warning(nullptr, "Bad style file.", "Bad style file: '" + fileName + "'. Check the file is properly formatted and try to load it again."); return false; @@ -334,7 +333,8 @@ bool Tikzit::loadStyles(QString fileName) } else { //settings.setValue("previous-tikzstyles-file", ""); - QMessageBox::warning(0, "Style file not found.", "Could not open style file: '" + fileName + "'."); + QMessageBox::warning(nullptr, + "Style file not found.", "Could not open style file: '" + fileName + "'."); return false; } } diff --git a/tikzit.qrc b/tikzit.qrc index 32bdfc8..4b4defb 100644 --- a/tikzit.qrc +++ b/tikzit.qrc @@ -9,6 +9,10 @@ images/tikzit.png images/text-x-generic_with_pencil.svg tex/sample/tikzit.sty + images/loader.gif + images/loader@2x.gif + images/dialog-accept.svg + images/dialog-error.svg qt.conf -- cgit v1.2.3 From c5fedfb1ec79b97edec4a82b70f082fba93a5b5d Mon Sep 17 00:00:00 2001 From: Aleks Kissinger Date: Mon, 31 Dec 2018 12:56:32 +0100 Subject: image export in progress --- src/data/pdfdocument.cpp | 132 +++++++++++++++++++++++++++++++++++++ src/data/pdfdocument.h | 28 ++++++++ src/gui/exportdialog.cpp | 80 +++++++++++++++++++++++ src/gui/exportdialog.h | 34 ++++++++++ src/gui/exportdialog.ui | 162 ++++++++++++++++++++++++++++++++++++++++++++++ src/gui/latexprocess.cpp | 2 +- src/gui/previewwindow.cpp | 100 ++++++++++++++++------------ src/gui/previewwindow.h | 19 ++++-- src/tikzit.cpp | 5 ++ src/tikzit.h | 2 + tikzit.pro | 13 ++-- 11 files changed, 522 insertions(+), 55 deletions(-) create mode 100644 src/data/pdfdocument.cpp create mode 100644 src/data/pdfdocument.h create mode 100644 src/gui/exportdialog.cpp create mode 100644 src/gui/exportdialog.h create mode 100644 src/gui/exportdialog.ui (limited to 'src/gui/previewwindow.h') diff --git a/src/data/pdfdocument.cpp b/src/data/pdfdocument.cpp new file mode 100644 index 0000000..bfedeca --- /dev/null +++ b/src/data/pdfdocument.cpp @@ -0,0 +1,132 @@ +#include "pdfdocument.h" + +#include +#include +#include +#include +#include +#include +#include + +PdfDocument::PdfDocument(QString file, QObject *parent) : QObject(parent) +{ + // use loadFromData to avoid holding a lock on the PDF file in windows + QFile f(file); + if (f.open(QFile::ReadOnly)) { + QByteArray data = f.readAll(); + f.close(); + _doc = Poppler::Document::loadFromData(data); + } else { + _doc = nullptr; + } + + if (!_doc) { + _doc = nullptr; + _page = nullptr; + } else { + _doc->setRenderHint(Poppler::Document::Antialiasing); + _doc->setRenderHint(Poppler::Document::TextAntialiasing); + _doc->setRenderHint(Poppler::Document::TextHinting); + _page = _doc->page(0); + } +} + +void PdfDocument::renderTo(QLabel *label, QRect rect) +{ + if (!isValid()) return; + + QSizeF pageSize = _page->pageSizeF(); + + qreal ratio = label->devicePixelRatioF(); + //QRect rect = ui->scrollArea->visibleRegion().boundingRect(); + int w = static_cast(ratio * (rect.width() - 20)); + int h = static_cast(ratio * (rect.height() - 20)); + qreal scale = fmin(static_cast(w) / pageSize.width(), + static_cast(h) / pageSize.height()); + + + int dpi = static_cast(scale * 72.0); + int w1 = static_cast(scale * pageSize.width()); + int h1 = static_cast(scale * pageSize.height()); + + //qDebug() << "hidpi ratio:" << ratio; + //qDebug() << "visible width:" << w; + //qDebug() << "visible height:" << h; + //qDebug() << "doc width:" << pageSize.width(); + //qDebug() << "doc height:" << pageSize.height(); + //qDebug() << "scale:" << scale; + //qDebug() << "dpi:" << dpi; + + QPixmap pm = QPixmap::fromImage(_page->renderToImage(dpi, dpi, (w1 - w)/2, (h1 - h)/2, w, h)); + pm.setDevicePixelRatio(ratio); + label->setPixmap(pm); +} + +bool PdfDocument::isValid() +{ + return (_page != nullptr); +} + +bool PdfDocument::exportImage(QString file, const char *format, QSize outputSize) +{ + QImage img = asImage(outputSize); + if (!img.isNull()) return img.save(file, format); + else return false; +} + +bool PdfDocument::exportPdf(QString file) +{ + if (!isValid()) return false; + Poppler::PDFConverter *conv = _doc->pdfConverter(); + conv->setOutputFileName(file); + bool success = conv->convert(); + delete conv; + return success; +} + +void PdfDocument::copyImageToClipboard(QSize outputSize) +{ + QImage img = asImage(outputSize); + if (!img.isNull()) { + QApplication::clipboard()->setImage(img, QClipboard::Clipboard); + } +} + +QImage PdfDocument::asImage(QSize outputSize) +{ + if (!isValid()) return QImage(); + if (outputSize.isNull()) outputSize = size(); + QSize pageSize = _page->pageSize(); + int dpix = (72 * outputSize.width()) / pageSize.width(); + int dpiy = (72 * outputSize.width()) / pageSize.width(); + QImage img = _page->renderToImage(dpix, dpiy, 0, 0, + outputSize.width(), outputSize.height()); + return img; +} + +// CRASHES TikZiT when figures contain text, due to limitations of Arthur backend +//void PdfDocument::exportToSvg(QString file, QSize size) { +// QSvgGenerator gen; +// gen.setFileName(file); +// gen.setSize(size); +// gen.setViewBox(QRect(0,0,size.width(),size.height())); +// gen.setDescription("SVG generated from PDF by TikZiT"); +// QPainter painter; + +// // set the backend to Qt for renderToPainter() support +// Poppler::Document::RenderBackend backend = _doc->renderBackend(); +// _doc->setRenderBackend(Poppler::Document::ArthurBackend); +// painter.begin(&gen); +// _page->renderToPainter(&painter); +// painter.end(); +// _doc->setRenderBackend(backend); +//} + +QSize PdfDocument::size() +{ + if (isValid()) { + return _page->pageSize(); + } +} + + diff --git a/src/data/pdfdocument.h b/src/data/pdfdocument.h new file mode 100644 index 0000000..ebd33e9 --- /dev/null +++ b/src/data/pdfdocument.h @@ -0,0 +1,28 @@ +#ifndef PDFDOCUMENT_H +#define PDFDOCUMENT_H + +#include +#include +#include + +#include + +class PdfDocument : public QObject +{ + Q_OBJECT +public: + explicit PdfDocument(QString file, QObject *parent = nullptr); + void renderTo(QLabel *label, QRect rect); + bool isValid(); +// void exportToSvg(QString file, QSize size); + bool exportImage(QString file, const char *format, QSize outputSize=QSize()); + bool exportPdf(QString file); + void copyImageToClipboard(QSize outputSize=QSize()); + QImage asImage(QSize outputSize=QSize()); + QSize size(); +private: + Poppler::Document *_doc; + Poppler::Page *_page; +}; + +#endif // PDFDOCUMENT_H diff --git a/src/gui/exportdialog.cpp b/src/gui/exportdialog.cpp new file mode 100644 index 0000000..2d0d8a0 --- /dev/null +++ b/src/gui/exportdialog.cpp @@ -0,0 +1,80 @@ +#include "exportdialog.h" +#include "ui_exportdialog.h" + +#include "tikzit.h" + +ExportDialog::ExportDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::ExportDialog) +{ + ui->setupUi(this); + + QIntValidator *v = new QIntValidator(this); + v->setBottom(1); + ui->width->setValidator(v); + ui->height->setValidator(v); + connect(ui->width, SIGNAL(editingFinished()), + this, SLOT(setHeightFromWidth())); + connect(ui->height, SIGNAL(editingFinished()), + this, SLOT(setWidthFromHeight())); + + PdfDocument *doc = tikzit->previewWindow()->doc(); + if (doc) { + QSize size = doc->size() * 4; + ui->width->blockSignals(true); + ui->height->blockSignals(true); + ui->width->setText(QString::number(size.width())); + ui->height->setText(QString::number(size.height())); + ui->width->blockSignals(false); + ui->height->blockSignals(false); + } +} + +ExportDialog::~ExportDialog() +{ + delete ui; +} + +void ExportDialog::setHeightFromWidth() +{ + if (ui->keepAspect->isChecked()) { + PdfDocument *doc = tikzit->previewWindow()->doc(); + if (doc == nullptr || doc->size().width() == 0 || doc->size().height() == 0) return; + int w = ui->width->text().toInt(); + int h = (w * doc->size().height()) / doc->size().width(); + + ui->height->blockSignals(true); + ui->height->setText(QString::number(h)); + ui->height->blockSignals(false); + } +} + +void ExportDialog::setWidthFromHeight() +{ + if (ui->keepAspect->isChecked()) { + PdfDocument *doc = tikzit->previewWindow()->doc(); + if (doc == nullptr || doc->size().width() == 0 || doc->size().height() == 0) return; + int h = ui->height->text().toInt(); + int w = (h * doc->size().width()) / doc->size().height(); + + ui->width->blockSignals(true); + ui->width->setText(QString::number(w)); + ui->width->blockSignals(false); + } +} + +void ExportDialog::on_keepAspect_stateChanged(int state) +{ + if (state == Qt::Checked) setHeightFromWidth(); +} + +void ExportDialog::on_browseButton_clicked() +{ + +} + +void ExportDialog::on_fileFormat_currentIndexChanged(int f) +{ + ui->width->setEnabled(f != PDF); + ui->height->setEnabled(f != PDF); +} diff --git a/src/gui/exportdialog.h b/src/gui/exportdialog.h new file mode 100644 index 0000000..064c968 --- /dev/null +++ b/src/gui/exportdialog.h @@ -0,0 +1,34 @@ +#ifndef EXPORTDIALOG_H +#define EXPORTDIALOG_H + +#include + +namespace Ui { +class ExportDialog; +} + +class ExportDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ExportDialog(QWidget *parent = nullptr); + ~ExportDialog(); + enum Format { + PNG = 0, + JPG = 1, + PDF = 2 + }; + +protected slots: + void setHeightFromWidth(); + void setWidthFromHeight(); + void on_keepAspect_stateChanged(int state); + void on_browseButton_clicked(); + void on_fileFormat_currentIndexChanged(int f); + +private: + Ui::ExportDialog *ui; +}; + +#endif // EXPORTDIALOG_H diff --git a/src/gui/exportdialog.ui b/src/gui/exportdialog.ui new file mode 100644 index 0000000..69e2a22 --- /dev/null +++ b/src/gui/exportdialog.ui @@ -0,0 +1,162 @@ + + + ExportDialog + + + + 0 + 0 + 394 + 119 + + + + + 0 + 0 + + + + Dialog + + + + + + + + File + + + + + + + Format + + + + + + + + + + + + ... + + + + + + + + + + Portable Network Graphics (PNG) + + + + + Jpeg Image (JPG) + + + + + Original (PDF) + + + + + + + + Dimensions + + + + + + + + + + + + X + + + + + + + + + + + + + + + + + + + Keep aspect ratio + + + true + + + + + + + + + Qt::Vertical + + + QDialogButtonBox::Cancel|QDialogButtonBox::Save + + + + + + + + + buttonBox + accepted() + ExportDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + ExportDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/gui/latexprocess.cpp b/src/gui/latexprocess.cpp index 39a7a51..0e2185a 100644 --- a/src/gui/latexprocess.cpp +++ b/src/gui/latexprocess.cpp @@ -19,7 +19,7 @@ LatexProcess::LatexProcess(PreviewWindow *preview, QObject *parent) : QObject(pa connect(_proc, SIGNAL(finished(int)), this, SLOT(finished(int))); // for debug purposes - // _workingDir.setAutoRemove(false); + _workingDir.setAutoRemove(false); } void LatexProcess::makePreview(QString tikz) diff --git a/src/gui/previewwindow.cpp b/src/gui/previewwindow.cpp index 7fd6376..d9d22c2 100644 --- a/src/gui/previewwindow.cpp +++ b/src/gui/previewwindow.cpp @@ -3,6 +3,7 @@ #include "tikzit.h" #include "latexprocess.h" +#include "exportdialog.h" #include #include @@ -16,6 +17,7 @@ #include #include #include +#include PreviewWindow::PreviewWindow(QWidget *parent) : QDialog(parent), @@ -31,7 +33,6 @@ PreviewWindow::PreviewWindow(QWidget *parent) : } _doc = nullptr; - _page = nullptr; _loader = new QLabel(ui->tabWidget->tabBar()); _loader->setMinimumSize(QSize(16,16)); @@ -44,6 +45,27 @@ PreviewWindow::PreviewWindow(QWidget *parent) : render(); } +void PreviewWindow::contextMenuEvent(QContextMenuEvent *event) +{ + QMenu menu(this); + QAction *act; + + act = new QAction("Export Image..."); + connect(act, SIGNAL(triggered()), this, SLOT(exportImage())); + menu.addAction(act); + + act = new QAction("Copy to Clipboard"); + connect(act, SIGNAL(triggered()), this, SLOT(copyImageToClipboard())); + menu.addAction(act); + + menu.exec(event->globalPos()); +} + +PdfDocument *PreviewWindow::doc() const +{ + return _doc; +} + PreviewWindow::~PreviewWindow() { delete ui; @@ -51,30 +73,24 @@ PreviewWindow::~PreviewWindow() void PreviewWindow::setPdf(QString file) { - Poppler::Document *oldDoc = _doc; - // use loadFromData to avoid holding a lock on the PDF file in windows - QFile f(file); - f.open(QFile::ReadOnly); - QByteArray data = f.readAll(); - f.close(); - Poppler::Document *newDoc = Poppler::Document::loadFromData(data); - - if (!newDoc) { + //QFile f(file); + //f.open(QFile::ReadOnly); + //QByteArray data = f.readAll(); + //f.close(); + PdfDocument *newDoc = new PdfDocument(file, this); + + if (newDoc->isValid()) { + PdfDocument *oldDoc = _doc; + _doc = newDoc; + if (oldDoc != nullptr) delete oldDoc; + render(); + } else { QMessageBox::warning(nullptr, "Could not read PDF", "Could not read: '" + file + "'."); - return; + delete newDoc; } - - _doc = newDoc; - _doc->setRenderHint(Poppler::Document::Antialiasing); - _doc->setRenderHint(Poppler::Document::TextAntialiasing); - _doc->setRenderHint(Poppler::Document::TextHinting ); - _page = _doc->page(0); - render(); - - if (oldDoc != nullptr) delete oldDoc; } QPlainTextEdit *PreviewWindow::outputTextEdit() @@ -130,30 +146,28 @@ void PreviewWindow::showEvent(QShowEvent *e) { } void PreviewWindow::render() { - if (_page == nullptr) return; - - QSizeF size = _page->pageSizeF(); - - qreal ratio = devicePixelRatioF(); - QRect rect = ui->scrollArea->visibleRegion().boundingRect(); - int w = static_cast(ratio * (rect.width() - 20)); - int h = static_cast(ratio * (rect.height() - 20)); - qreal scale = fmin(static_cast(w) / size.width(), - static_cast(h) / size.height()); + if (_doc != nullptr) { + _doc->renderTo(ui->pdf, + ui->scrollArea->visibleRegion().boundingRect()); + ui->pdf->repaint(); + } +} +void PreviewWindow::exportImage() +{ + if (_doc == nullptr) return; + ExportDialog *d = new ExportDialog(this); + int ret = d->exec(); + if (ret == QDialog::Accepted) { + qDebug() << "save accepted"; + } +} - int dpi = static_cast(scale * 72.0); - int w1 = static_cast(scale * size.width()); - int h1 = static_cast(scale * size.height()); +void PreviewWindow::copyImageToClipboard() +{ + if (_doc != nullptr) { + _doc->copyImageToClipboard(_doc->size() * 4); + } +} - // qDebug() << "visible width:" << w; - // qDebug() << "visible height:" << h; - // qDebug() << "doc width:" << size.width(); - // qDebug() << "doc height:" << size.height(); - // qDebug() << "scale:" << scale; - // qDebug() << "dpi:" << dpi; - QPixmap pm = QPixmap::fromImage(_page->renderToImage(dpi, dpi, (w1 - w)/2, (h1 - h)/2, w, h)); - pm.setDevicePixelRatio(ratio); - ui->pdf->setPixmap(pm); -} diff --git a/src/gui/previewwindow.h b/src/gui/previewwindow.h index a937263..20dd042 100644 --- a/src/gui/previewwindow.h +++ b/src/gui/previewwindow.h @@ -1,10 +1,12 @@ #ifndef PREVIEWWINDOW_H #define PREVIEWWINDOW_H +#include "pdfdocument.h" #include #include #include +#include #include namespace Ui { @@ -20,24 +22,27 @@ public: Running, Success, Failed }; explicit PreviewWindow(QWidget *parent = nullptr); - ~PreviewWindow(); + ~PreviewWindow() override; void setPdf(QString file); QString preparePreview(QString tikz); QPlainTextEdit *outputTextEdit(); void setStatus(Status status); + PdfDocument *doc() const; + public slots: void render(); + void exportImage(); + void copyImageToClipboard(); protected: - void resizeEvent(QResizeEvent *e); - void showEvent(QShowEvent *e); - void closeEvent(QCloseEvent *e); - + void resizeEvent(QResizeEvent *e) override; + void showEvent(QShowEvent *e) override; + void closeEvent(QCloseEvent *e) override; + void contextMenuEvent(QContextMenuEvent *event) override; private: Ui::PreviewWindow *ui; - Poppler::Document *_doc; - Poppler::Page *_page; + PdfDocument *_doc; QLabel *_loader; }; diff --git a/src/tikzit.cpp b/src/tikzit.cpp index e81706c..2e36b21 100644 --- a/src/tikzit.cpp +++ b/src/tikzit.cpp @@ -489,6 +489,11 @@ void Tikzit::cleanupLatex() } } +PreviewWindow *Tikzit::previewWindow() const +{ + return _preview; +} + //StylePalette *Tikzit::stylePalette() const //{ // return _stylePalette; diff --git a/src/tikzit.h b/src/tikzit.h index 24bf56b..15f0b46 100644 --- a/src/tikzit.h +++ b/src/tikzit.h @@ -136,6 +136,8 @@ public: QString styleFilePath() const; void updateRecentFiles(); + PreviewWindow *previewWindow() const; + public slots: void clearRecentFiles(); void setCheckForUpdates(bool check); diff --git a/tikzit.pro b/tikzit.pro index 3d3b12d..d8abd30 100644 --- a/tikzit.pro +++ b/tikzit.pro @@ -1,6 +1,6 @@ # CONFIG += debug -QT += core gui widgets network +QT += core gui widgets network svg test { CONFIG += testcase @@ -73,7 +73,9 @@ SOURCES += src/gui/mainwindow.cpp \ src/gui/styleeditor.cpp \ src/data/stylelist.cpp \ src/gui/previewwindow.cpp \ - src/gui/latexprocess.cpp + src/gui/latexprocess.cpp \ + src/data/pdfdocument.cpp \ + src/gui/exportdialog.cpp HEADERS += src/gui/mainwindow.h \ src/gui/toolpalette.h \ @@ -101,14 +103,17 @@ HEADERS += src/gui/mainwindow.h \ src/gui/styleeditor.h \ src/data/stylelist.h \ src/gui/previewwindow.h \ - src/gui/latexprocess.h + src/gui/latexprocess.h \ + src/data/pdfdocument.h \ + src/gui/exportdialog.h FORMS += src/gui/mainwindow.ui \ src/gui/propertypalette.ui \ src/gui/mainmenu.ui \ src/gui/stylepalette.ui \ src/gui/styleeditor.ui \ - src/gui/previewwindow.ui + src/gui/previewwindow.ui \ + src/gui/exportdialog.ui INCLUDEPATH += src src/gui src/data -- cgit v1.2.3 From e090751ebb8e4c7c6a9075587e1017d4ac95cd05 Mon Sep 17 00:00:00 2001 From: Aleks Kissinger Date: Wed, 2 Jan 2019 17:14:58 +0100 Subject: added GPL to some files where it was missing --- src/gui/exportdialog.cpp | 18 ++++++++++++++++++ src/gui/exportdialog.h | 18 ++++++++++++++++++ src/gui/latexprocess.cpp | 18 ++++++++++++++++++ src/gui/latexprocess.h | 18 ++++++++++++++++++ src/gui/previewwindow.cpp | 18 ++++++++++++++++++ src/gui/previewwindow.h | 18 ++++++++++++++++++ src/gui/styleeditor.cpp | 18 ++++++++++++++++++ src/gui/styleeditor.h | 18 ++++++++++++++++++ 8 files changed, 144 insertions(+) (limited to 'src/gui/previewwindow.h') diff --git a/src/gui/exportdialog.cpp b/src/gui/exportdialog.cpp index cc0be7b..bd1ef53 100644 --- a/src/gui/exportdialog.cpp +++ b/src/gui/exportdialog.cpp @@ -1,3 +1,21 @@ +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + #include "exportdialog.h" #include "ui_exportdialog.h" diff --git a/src/gui/exportdialog.h b/src/gui/exportdialog.h index 6788560..0f6940b 100644 --- a/src/gui/exportdialog.h +++ b/src/gui/exportdialog.h @@ -1,3 +1,21 @@ +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + #ifndef EXPORTDIALOG_H #define EXPORTDIALOG_H diff --git a/src/gui/latexprocess.cpp b/src/gui/latexprocess.cpp index cad8575..0bda54f 100644 --- a/src/gui/latexprocess.cpp +++ b/src/gui/latexprocess.cpp @@ -1,3 +1,21 @@ +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + #include "latexprocess.h" #include "tikzit.h" diff --git a/src/gui/latexprocess.h b/src/gui/latexprocess.h index dc815f2..4fe9987 100644 --- a/src/gui/latexprocess.h +++ b/src/gui/latexprocess.h @@ -1,3 +1,21 @@ +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + #ifndef LATEXPROCESS_H #define LATEXPROCESS_H diff --git a/src/gui/previewwindow.cpp b/src/gui/previewwindow.cpp index ec66f81..2f47efd 100644 --- a/src/gui/previewwindow.cpp +++ b/src/gui/previewwindow.cpp @@ -1,3 +1,21 @@ +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + #include "previewwindow.h" #include "ui_previewwindow.h" diff --git a/src/gui/previewwindow.h b/src/gui/previewwindow.h index 20dd042..cf2ffd8 100644 --- a/src/gui/previewwindow.h +++ b/src/gui/previewwindow.h @@ -1,3 +1,21 @@ +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + #ifndef PREVIEWWINDOW_H #define PREVIEWWINDOW_H diff --git a/src/gui/styleeditor.cpp b/src/gui/styleeditor.cpp index 804a12b..17929da 100644 --- a/src/gui/styleeditor.cpp +++ b/src/gui/styleeditor.cpp @@ -1,3 +1,21 @@ +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + #include #include #include diff --git a/src/gui/styleeditor.h b/src/gui/styleeditor.h index 4bae7db..e9a8a89 100644 --- a/src/gui/styleeditor.h +++ b/src/gui/styleeditor.h @@ -1,3 +1,21 @@ +/* + TikZiT - a GUI diagram editor for TikZ + Copyright (C) 2018 Aleks Kissinger + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + #ifndef STYLEEDITOR_H #define STYLEEDITOR_H -- cgit v1.2.3 From 904e73cbfa571377ab1860ba7d5a54119ab909e0 Mon Sep 17 00:00:00 2001 From: Aleks Kissinger Date: Wed, 2 Jan 2019 17:38:38 +0100 Subject: added some documentation to the source code --- src/data/delimitedstringvalidator.h | 14 ++++++++++++++ src/data/edge.h | 8 ++++++-- src/data/graphelementdata.h | 6 ++++++ src/data/graphelementproperty.h | 37 ++++++++++++++++++++++++++++++++++--- src/gui/exportdialog.h | 4 ++++ src/gui/latexprocess.h | 5 +++++ src/gui/previewwindow.h | 5 +++++ src/gui/styleeditor.h | 8 ++++++-- 8 files changed, 80 insertions(+), 7 deletions(-) (limited to 'src/gui/previewwindow.h') diff --git a/src/data/delimitedstringvalidator.h b/src/data/delimitedstringvalidator.h index 654e4ab..b4ed3bd 100644 --- a/src/data/delimitedstringvalidator.h +++ b/src/data/delimitedstringvalidator.h @@ -19,6 +19,10 @@ /*! * A string validator which keeps curly braces matched. Used in various places * to ensure the user doesn't make non-parseable .tikz or .tikzstyles files. + * + * Its validation function will return Acceptable if all curly braces are matched + * properly, Intermediate if all braces are matched except for possibly some opening + * curly braces, and Invalid if there are unmatched closing curly braces. */ #ifndef DELIMITEDSTRINGVALIDATOR_H @@ -34,8 +38,18 @@ class DelimitedStringValidator : public QValidator public: DelimitedStringValidator(QObject *parent); QValidator::State validate(QString &input, int &/*pos*/) const override; + + /*! + * \brief fixup adds curly braces until all braces are matched (if possible) + * \param input + */ void fixup(QString &input) const override; private: + /*! + * \brief braceDepth computes the final (non-escaped) curly-brace depth of a given string + * \param input a string + * \return the final brace depth, or -1 if the depth *ever* drops below 0 + */ int braceDepth(QString input) const; }; diff --git a/src/data/edge.h b/src/data/edge.h index 5d26b3e..27d5bef 100644 --- a/src/data/edge.h +++ b/src/data/edge.h @@ -16,6 +16,10 @@ along with this program. If not, see . */ +/*! + * Class representing an edge in a Graph. + */ + #ifndef EDGE_H #define EDGE_H @@ -30,8 +34,8 @@ class Edge : public QObject { Q_OBJECT public: - explicit Edge(Node *s, Node *t, QObject *parent = 0); - Edge *copy(QMap *nodeTable = 0); + explicit Edge(Node *s, Node *t, QObject *parent = nullptr); + Edge *copy(QMap *nodeTable = nullptr); Node *source() const; Node *target() const; diff --git a/src/data/graphelementdata.h b/src/data/graphelementdata.h index b1311d7..dce0d46 100644 --- a/src/data/graphelementdata.h +++ b/src/data/graphelementdata.h @@ -16,6 +16,12 @@ along with this program. If not, see . */ +/*! + * A list of GraphElementProperty objects, which convenience methods + * for lookup, deletion, re-ordering, etc. It inherits QAbstractItemModel + * so it can be used as the model for a QTreeView in the StyleEditor. + */ + #ifndef GRAPHELEMENTDATA_H #define GRAPHELEMENTDATA_H diff --git a/src/data/graphelementproperty.h b/src/data/graphelementproperty.h index 4ebe104..5777c18 100644 --- a/src/data/graphelementproperty.h +++ b/src/data/graphelementproperty.h @@ -16,6 +16,11 @@ along with this program. If not, see . */ +/*! + * A class which holds either a single key/value pair (i.e. a proper property) + * or simply a key with no value (i.e. an atom). + */ + #ifndef GRAPHELEMENTPROPERTY_H #define GRAPHELEMENTPROPERTY_H @@ -26,13 +31,19 @@ class GraphElementProperty public: GraphElementProperty(); - // full constructor GraphElementProperty(QString key, QString value, bool atom); - // construct a proper property + /*! + * \brief GraphElementProperty constructs a proper property with the given key/value + * \param key + * \param value + */ GraphElementProperty(QString key, QString value); - // construct an atom + /*! + * \brief GraphElementProperty constructs an atom with the given key + * \param key + */ GraphElementProperty(QString key); QString key() const; @@ -40,9 +51,29 @@ public: QString value() const; void setValue(const QString &value); bool atom() const; + + /*! + * \brief operator == returns true for atoms if the keys match and for properties + * if the keys and values match. Note a property is never equal to an atom. + * \param p + * \return + */ bool operator==(const GraphElementProperty &p); + /*! + * \brief tikzEscape prepares a property key or value for export to tikz code. If + * the property only contains numbers, letters, whitespace, or the characters (<,>,-) + * this method does nothing. Otherwise, wrap the property in curly braces. + * \param str + * \return + */ static QString tikzEscape(QString str); + + /*! + * \brief tikz escapes the key/value of a propery or atom and outputs it as "key=value" + * for properties and "key" for atoms. + * \return + */ QString tikz(); signals: diff --git a/src/gui/exportdialog.h b/src/gui/exportdialog.h index 0f6940b..bcb6879 100644 --- a/src/gui/exportdialog.h +++ b/src/gui/exportdialog.h @@ -16,6 +16,10 @@ along with this program. If not, see . */ +/*! + * A dialog for exporting a LaTeX-generated preview to PNG, JPG, or PDF. + */ + #ifndef EXPORTDIALOG_H #define EXPORTDIALOG_H diff --git a/src/gui/latexprocess.h b/src/gui/latexprocess.h index 4fe9987..9853883 100644 --- a/src/gui/latexprocess.h +++ b/src/gui/latexprocess.h @@ -16,6 +16,11 @@ along with this program. If not, see . */ +/*! + * Run pdflatex and dump its output to the appropriate tab of + * the PreviewWindow. + */ + #ifndef LATEXPROCESS_H #define LATEXPROCESS_H diff --git a/src/gui/previewwindow.h b/src/gui/previewwindow.h index cf2ffd8..a14303b 100644 --- a/src/gui/previewwindow.h +++ b/src/gui/previewwindow.h @@ -16,6 +16,11 @@ along with this program. If not, see . */ +/*! + * Displays a LaTeX-generated PDF preview using Poppler. The right-click + * menu has options for exporting to file or clipboard. + */ + #ifndef PREVIEWWINDOW_H #define PREVIEWWINDOW_H diff --git a/src/gui/styleeditor.h b/src/gui/styleeditor.h index e9a8a89..2c35d56 100644 --- a/src/gui/styleeditor.h +++ b/src/gui/styleeditor.h @@ -16,6 +16,10 @@ along with this program. If not, see . */ +/*! + * A GUI editor for .tikzstyles files. + */ + #ifndef STYLEEDITOR_H #define STYLEEDITOR_H @@ -35,8 +39,8 @@ class StyleEditor : public QMainWindow Q_OBJECT public: - explicit StyleEditor(QWidget *parent = 0); - ~StyleEditor(); + explicit StyleEditor(QWidget *parent = nullptr); + ~StyleEditor() override; void open(); void save(); -- cgit v1.2.3