diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/latexprocess.cpp | 98 | ||||
-rw-r--r-- | src/gui/latexprocess.h | 33 | ||||
-rw-r--r-- | src/gui/mainmenu.cpp | 7 | ||||
-rw-r--r-- | src/gui/mainmenu.h | 1 | ||||
-rw-r--r-- | src/gui/mainmenu.ui | 9 | ||||
-rw-r--r-- | src/gui/previewwindow.cpp | 122 | ||||
-rw-r--r-- | src/gui/previewwindow.h | 35 | ||||
-rw-r--r-- | src/gui/previewwindow.ui | 77 | ||||
-rw-r--r-- | src/tikzit.cpp | 66 | ||||
-rw-r--r-- | src/tikzit.h | 12 |
10 files changed, 450 insertions, 10 deletions
diff --git a/src/gui/latexprocess.cpp b/src/gui/latexprocess.cpp new file mode 100644 index 0000000..20b22a4 --- /dev/null +++ b/src/gui/latexprocess.cpp @@ -0,0 +1,98 @@ +#include "latexprocess.h" +#include "tikzit.h" + +#include <QDebug> +#include <QStandardPaths> +#include <QTemporaryDir> + +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{tikzit}\n"; + tex << "\\usepackage[graphics,active,tightpage]{preview}\n"; + tex << "\\PreviewEnvironment{tikzpicture}\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 <QObject> +#include <QProcess> +#include <QTemporaryDir> +#include <QPlainTextEdit> + +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..6f6ab00 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() @@ -260,5 +265,5 @@ void MainMenu::on_actionCheck_for_updates_automatically_triggered() void MainMenu::on_actionCheck_now_triggered() { - tikzit->checkForUpdates(); + tikzit->checkForUpdates(true); } 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 @@ <addaction name="actionParse"/> <addaction name="actionRevert"/> <addaction name="actionJump_to_Selection"/> + <addaction name="actionRun_LaTeX"/> </widget> <widget class="QMenu" name="menuView"> <property name="title"> @@ -335,6 +336,14 @@ <string>About</string> </property> </action> + <action name="actionRun_LaTeX"> + <property name="text"> + <string>Run LaTeX</string> + </property> + <property name="shortcut"> + <string>Ctrl+R</string> + </property> + </action> <addaction name="menuFile"/> <addaction name="menuEdit"/> <addaction name="menuView"/> diff --git a/src/gui/previewwindow.cpp b/src/gui/previewwindow.cpp new file mode 100644 index 0000000..724a951 --- /dev/null +++ b/src/gui/previewwindow.cpp @@ -0,0 +1,122 @@ +#include "previewwindow.h" +#include "ui_previewwindow.h" + +#include "tikzit.h" +#include "latexprocess.h" + +#include <QLabel> +#include <QImage> +#include <QPixmap> +#include <QDebug> +#include <QSettings> +#include <QTemporaryDir> +#include <QFile> +#include <QTextStream> +#include <QStandardPaths> +#include <QMessageBox> +#include <cmath> + +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 = 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; + + // 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) { + QMessageBox::warning(nullptr, + "Could not read PDF", + "Could not read: '" + file + "'."); + return; + } + + _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() +{ + 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) { + render(); + QDialog::resizeEvent(e); +} + +void PreviewWindow::showEvent(QShowEvent *e) { + render(); + QDialog::showEvent(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<int>(ratio * (rect.width() - 20)); + int h = static_cast<int>(ratio * (rect.height() - 20)); + qreal scale = fmin(static_cast<qreal>(w) / size.width(), + static_cast<qreal>(h) / size.height()); + + + int dpi = static_cast<int>(scale * 72.0); + int w1 = static_cast<int>(scale * size.width()); + int h1 = static_cast<int>(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; + + 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 new file mode 100644 index 0000000..c850ce9 --- /dev/null +++ b/src/gui/previewwindow.h @@ -0,0 +1,35 @@ +#ifndef PREVIEWWINDOW_H +#define PREVIEWWINDOW_H + +#include <QDialog> +#include <QPlainTextEdit> +#include <poppler/qt5/poppler-qt5.h> + +namespace Ui { +class PreviewWindow; +} + +class PreviewWindow : public QDialog +{ + Q_OBJECT + +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); + +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 new file mode 100644 index 0000000..394fc41 --- /dev/null +++ b/src/gui/previewwindow.ui @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PreviewWindow</class> + <widget class="QDialog" name="PreviewWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>603</width> + <height>480</height> + </rect> + </property> + <property name="windowTitle"> + <string>Preview</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="pdfTab"> + <attribute name="title"> + <string>PDF</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QScrollArea" name="scrollArea"> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QWidget" name="scrollAreaWidgetContents"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>561</width> + <height>413</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QLabel" name="pdf"> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="outputTab"> + <attribute name="title"> + <string>Output</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QPlainTextEdit" name="output"/> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/tikzit.cpp b/src/tikzit.cpp index 1c3ba23..39a2924 100644 --- a/src/tikzit.cpp +++ b/src/tikzit.cpp @@ -19,6 +19,8 @@ #include "tikzit.h" #include "tikzassembler.h" #include "tikzstyles.h" +#include "previewwindow.h" +#include "latexprocess.h" #include <QFile> #include <QFileDialog> @@ -29,6 +31,7 @@ #include <QVersionNumber> #include <QNetworkAccessManager> + // application-level instance of Tikzit Tikzit *tikzit; @@ -106,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); @@ -124,8 +129,11 @@ void Tikzit::init() setCheckForUpdates(check.toBool()); if (check.toBool()) { - checkForUpdates(); + checkForUpdates(false); } + + _preview = new PreviewWindow(); + _latex = nullptr; } //QMenuBar *Tikzit::mainMenu() const @@ -357,16 +365,32 @@ void Tikzit::setCheckForUpdates(bool check) } } -void Tikzit::checkForUpdates() +void Tikzit::checkForUpdates(bool manual) { QNetworkAccessManager *manager = new QNetworkAccessManager(this); - connect(manager, SIGNAL(finished(QNetworkReply*)), - this, SLOT(updateReply(QNetworkReply*))); + + if (manual) { + connect(manager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(updateManual(QNetworkReply*))); + } else { + connect(manager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(updateAuto(QNetworkReply*))); + } manager->get(QNetworkRequest(QUrl("https://tikzit.github.io/latest-version.txt"))); } -void Tikzit::updateReply(QNetworkReply *reply) +void Tikzit::updateAuto(QNetworkReply *reply) +{ + updateReply(reply, false); +} + +void Tikzit::updateManual(QNetworkReply *reply) +{ + updateReply(reply, true); +} + +void Tikzit::updateReply(QNetworkReply *reply, bool manual) { if (!reply->isReadable()) return; @@ -395,7 +419,7 @@ void Tikzit::updateReply(QNetworkReply *reply) QString::number(latest.minorVersion()) + "." + QString::number(latest.microVersion()); if (rcLatest != 1000) strLatest += "-rc" + QString::number(rcLatest); - QMessageBox::information(0, + QMessageBox::information(nullptr, tr("Update available"), "<p><b>A new version of TikZiT is available!</b></p>" "<p><i>current version: " TIKZIT_VERSION "<br />" @@ -404,10 +428,38 @@ void Tikzit::updateReply(QNetworkReply *reply) "<a href=\"https://tikzit.github.io\">tikzit.github.io</a>.</p>"); } } else { - QMessageBox::warning(0, + // don't complain of invalid response for auto update check + if (manual) { + QMessageBox::warning(nullptr, tr("Invalid response"), "<p>Got invalid version response from " "<a href=\"https://tikzit.github.io\">tikzit.github.io</a>.</p>"); + } + } +} + +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(); } } diff --git a/src/tikzit.h b/src/tikzit.h index 5fed22c..9011cc3 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 <QObject> #include <QVector> @@ -135,8 +137,12 @@ public: public slots: void setCheckForUpdates(bool check); - void checkForUpdates(); - void updateReply(QNetworkReply *reply); + void checkForUpdates(bool manual); + void updateAuto(QNetworkReply *reply); + void updateManual(QNetworkReply *reply); + void updateReply(QNetworkReply *reply, bool manual); + void makePreview(); + void cleanupLatex(); private: // void createMenu(); @@ -153,6 +159,8 @@ private: StyleEditor *_styleEditor; QStringList _colNames; QVector<QColor> _cols; + LatexProcess *_latex; + PreviewWindow *_preview; }; extern Tikzit *tikzit; |