1313#include < QTemporaryFile>
1414#include < QFile>
1515#include < iostream>
16+ #include < string>
17+ #include < thread>
18+ #include < chrono>
1619
1720#include < QtCore/QDebug>
1821#undef QT_NO_DEBUG
1922#include < kdebug.h>
2023
24+ QString getFilePath (QTemporaryDir* dir, const char * file) {
25+ QString path (dir->path ());
26+ path.append (" /" );
27+ path.append (file);
28+ return path;
29+ }
2130
2231void MainWindow::textChanged (KTextEditor::Document *document) {
2332 (void )document;
2433 refreshTimer->start (1000 );
34+ watchme (texdir.path ());
35+ }
36+
37+ void MainWindow::documentSaved (KTextEditor::Document *document, bool saveas) {
38+ (void )document;
39+ (void )saveas;
40+ std::cout << " Document saved" << std::endl;
41+ usersaved = true ;
2542}
2643
2744void MainWindow::render () { render (display->getScale ()); }
@@ -57,39 +74,54 @@ void MainWindow::render(double scale) {
5774}
5875
5976void MainWindow::compile () {
77+ usersaved = false ;
6078 QSettings settings;
6179 QString program = settings.value (" compiler" , " pdflatex" ).toString ();
80+
6281 QStringList arguments;
6382 QTemporaryDir tmpdir;
6483 tmpdir.setAutoRemove (true );
6584
6685 if (program == " pdflatex" ) {
6786 arguments << " -halt-on-error" ;
6887 }
69- if (dir->path () == " " ) {
88+ if (!dir || dir->path () == " " ) {
7089 return ;
7190 }
7291 if (texdir.absolutePath () == " " ) {
7392 std::cout << " need a temporary directory" << std::endl;
7493 texdir = QFileInfo (tmpdir.path ());
7594 }
76-
77- arguments << dir->filePath (" _livetikz_preview.tex" );
95+ QFileInfo templateDir = QFileInfo (templateFile.path ());
96+ if (templateDir.absolutePath () == " " ) {
97+ workdir = texdir;
98+ } else {
99+ workdir = templateDir;
100+ }
101+
102+ QString odir (" --output-directory=" );
103+ odir.append (dir->path ());
104+ arguments << odir;
105+
106+ arguments << getFilePath (dir, " _livetikz_preview.tex" );
107+
108+ std::cout << " Compiler arguments: " << arguments.join (QChar (' ' )).toStdString () << std::endl;
109+ std::cout << " Compiler workdir: " << workdir.absolutePath ().toStdString () << std::endl;
78110
79- std::cout << " Arguments: " << dir->filePath (" _livetikz_preview.tex" ).toStdString () << std::endl;
80- std::cout << " WD: " << texdir.absolutePath ().toStdString () << std::endl;
81-
82111 renderProcess = new QProcess (this );
83- renderProcess->setWorkingDirectory (texdir.absolutePath ());
112+ // ~ renderProcess->setWorkingDirectory(texdir.absolutePath());
113+ renderProcess->setWorkingDirectory (workdir.absolutePath ());
114+ clearLog ();
84115 renderProcess->start (program, arguments);
85116
86117 log->setText (" Compiling..." );
87118 renderOutput = " " ;
88119 connect (renderProcess, SIGNAL (finished (int )), this , SLOT (renderFinished (int )));
89- connect (renderProcess, SIGNAL (errorOccurred (QProcess::ProcessError)), this , SLOT (renderFailed (QProcess::ProcessError)));
120+ // connect(renderProcess, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(renderFailed(QProcess::ProcessError)));
90121 connect (renderProcess, SIGNAL (readyReadStandardError ()), this , SLOT (updateLog ()));
91122 connect (renderProcess, SIGNAL (readyReadStandardOutput ()), this , SLOT (updateLog ()));
92-
123+ connect (&templateWatcher, SIGNAL (fileChanged (const QString&)), this , SLOT (handleTemplateChanged (const QString&)));
124+
93125 connect (killButton, SIGNAL (clicked ()), renderProcess, SLOT (kill ()));
94126 killButton->setVisible (true );
95127}
@@ -101,7 +133,8 @@ void MainWindow::refresh() {
101133 }
102134
103135 if (dir->isValid ()) {
104- QFile file (dir->filePath (" _livetikz_preview.tex" ));
136+ // ~ QFile file(dir->filePath("_livetikz_preview.tex"));
137+ QFile file (getFilePath (dir, " _livetikz_preview.tex" ));
105138
106139 if (file.open (QIODevice::ReadWrite | QIODevice::Text)) {
107140 QTextStream out (&file);
@@ -148,11 +181,16 @@ void MainWindow::refresh() {
148181 }
149182 }
150183 } else if (dir) {
184+ std::cout << " Deleting invalid dir" << dir->path ().toStdString () << std::endl;
151185 delete dir;
152186 dir = NULL ;
153187 }
154188}
155189
190+ void MainWindow::clearLog () {
191+ renderOutput = QString ();
192+ }
193+
156194void MainWindow::appendLog (QString str) {
157195 renderOutput += str;
158196 log->setText (renderOutput);
@@ -165,6 +203,7 @@ void MainWindow::appendLog(QString str) {
165203void MainWindow::updateLog () {
166204 if (renderProcess) {
167205 appendLog (renderProcess->readAllStandardOutput ());
206+ appendLog (renderProcess->readAllStandardError ());
168207 }
169208}
170209
@@ -188,24 +227,24 @@ void MainWindow::renderFinished(int code) {
188227 delete currentDoc;
189228 currentDoc = NULL ;
190229
191- QFile pdf_file (QDir::cleanPath (texdir.absolutePath () + QDir::separator () + " _livetikz_preview.pdf" ));
192- if (pdf_file.exists ()) {
193- QFile::rename (QDir::cleanPath (texdir.absolutePath () + QDir::separator () + " _livetikz_preview.pdf" ), dir->filePath (" _livetikz_preview.pdf" ));
194- currentDoc = Poppler::Document::load (dir->filePath (" _livetikz_preview.pdf" ));
230+ // ~ QFile pdf_file(QDir::cleanPath(getFilePworkdir.absolutePath() + QDir::separator() + "_livetikz_preview.pdf"));
231+ // ~ if (pdf_file.exists()) {
232+ // ~ QFile::rename(QDir::cleanPath(texdir.absolutePath() + QDir::separator() + "_livetikz_preview.pdf"), dir->filePath("_livetikz_preview.pdf"));
233+ // ~ QFile::rename(QDir::cleanPath(workdir.absolutePath() + QDir::separator() + "_livetikz_preview.pdf"), getFilePath(dir, "_livetikz_preview.pdf"));
234+ // ~ currentDoc = Poppler::Document::load(dir->filePath("_livetikz_preview.pdf"));
235+ QFile::remove (getFilePath (dir, " livetikz_preview.pdf" ));
236+ QFile::rename (getFilePath (dir, " _livetikz_preview.pdf" ), getFilePath (dir, " livetikz_preview.pdf" ));
237+
238+ currentDoc = Poppler::Document::load (getFilePath (dir, " livetikz_preview.pdf" ));
195239 if (currentDoc) {
196240 currentDoc->setRenderHint (Poppler::Document::TextAntialiasing);
197241 currentDoc->setRenderHint (Poppler::Document::Antialiasing);
198242 currentDoc->setRenderHint (Poppler::Document::TextHinting);
199243 currentDoc->setRenderHint (Poppler::Document::TextSlightHinting);
200244 currentDoc->setRenderHint (Poppler::Document::ThinLineSolid);
201-
202245 render ();
203246 }
204- }
205-
206- dir->remove ();
207- delete dir;
208- dir = NULL ;
247+ // ~ }
209248
210249 renderProcess = NULL ;
211250}
@@ -220,6 +259,7 @@ MainWindow::MainWindow() : currentDoc(NULL), renderProcess(NULL), currentPage(0)
220259
221260 dir = NULL ;
222261 templateFile = QUrl (settings.value (" template" , " " ).toString ());
262+ updateTemplate (templateFile.path ());
223263 templateLabel->setText (templateFile.url (QUrl::PreferLocalFile));
224264
225265 doc->setHighlightingMode (" Latex" );
@@ -237,7 +277,10 @@ MainWindow::MainWindow() : currentDoc(NULL), renderProcess(NULL), currentPage(0)
237277
238278 connect ((QObject *)doc, SIGNAL (textChanged (KTextEditor::Document *)), this ,
239279 SLOT (textChanged (KTextEditor::Document *)));
240- connect (templateLabel, SIGNAL (textEdited (const QString&)), this , SLOT (updateTemplate (const QString&)));
280+ connect (templateLabel, SIGNAL (textEdited (const QString&)), this ,
281+ SLOT (updateTemplate (const QString&)));
282+ connect ((QObject *)doc, SIGNAL (documentSavedOrUploaded (KTextEditor::Document *, bool )), this ,
283+ SLOT (documentSaved (KTextEditor::Document *, bool )));
241284}
242285
243286void MainWindow::showCompilerSelection () {
@@ -252,15 +295,51 @@ void MainWindow::showCompilerSelection() {
252295 }
253296}
254297
255- MainWindow::~MainWindow () {}
298+ MainWindow::~MainWindow () {
299+ /* remove temp dir */
300+ if (dir) {
301+ dir->remove ();
302+ delete dir;
303+ dir = NULL ;
304+ }
305+ if (texfileWatcher) {
306+ delete texfileWatcher;
307+ texfileWatcher = NULL ;
308+ }
309+ }
310+
311+ void MainWindow::watchme (const QString& filename) {
312+ if (texfileWatcher) {
313+ /* We're already watching */
314+ return ;
315+ }
316+ /* Some editors delete and re-create files on save.
317+ * This somehow breaks our watcher. On re-watching, the event is
318+ * fired twice, then three times ...
319+ * To avoid this, completely destroy and re-connect the watcher.
320+ */
321+ texfileWatcher = new QFileSystemWatcher ();
322+ connect (texfileWatcher, SIGNAL (fileChanged (const QString&)), this , SLOT (handleTexfileChanged (const QString&)));
323+
324+ std::cout << " Watching " << filename.toStdString () << std::endl;
325+ int retry_count = 10 ;
326+ while (!texfileWatcher->addPath (filename) && retry_count--) {
327+ /* If the file has not been re-created yet, wait some time */
328+ std::this_thread::sleep_for (std::chrono::milliseconds (100 ));
329+ std::cout << " Retrying to watch..." << std::endl;
330+ }
331+ }
256332
257333void MainWindow::load (const QUrl &url) {
258- texdir = QFileInfo (url.toLocalFile ());
259- katePart->openUrl (url);
334+ std::cout << " Loading " << url.toString ().toStdString () << std::endl;
335+ texdir = QFileInfo (url.toLocalFile ());
336+ watchme (url.toLocalFile ());
337+ katePart->openUrl (url);
260338}
261339
262340void MainWindow::setupActions () {
263341 KStandardAction::open (this , SLOT (load ()), actionCollection ());
342+ // KStandardAction::save(this, SLOT(save()), actionCollection());
264343 KStandardAction::quit (qApp, SLOT (closeAllWindows ()), actionCollection ());
265344}
266345
@@ -350,9 +429,33 @@ void MainWindow::setupEditor() {
350429
351430void MainWindow::load () { load (QFileDialog::getOpenFileUrl ()); }
352431
432+ void MainWindow::handleTemplateChanged (const QString& filename) {
433+ std::cout << filename.toStdString () << " changed." << std::endl;
434+ updateTemplate (filename);
435+ }
436+
437+ void MainWindow::handleTexfileChanged (const QString& filename) {
438+ if (!usersaved) {
439+ std::cout << " Texfile " << filename.toStdString () << " externally changed." << std::endl;
440+ /* Reloading */
441+ katePart->openUrl (QUrl (QUrl::fromUserInput (filename)));
442+ }
443+ /* Always re-watch file */
444+ if (texfileWatcher) {
445+ delete texfileWatcher;
446+ texfileWatcher = NULL ;
447+ }
448+ watchme (filename);
449+ }
450+
353451void MainWindow::updateTemplate (const QString& filename) {
354452 QSettings settings;
453+ QUrl oldTemplateFile = QUrl (settings.value (" template" , " " ).toString ());
454+ templateWatcher.removePath (oldTemplateFile.path ());
455+
355456 templateFile = QUrl::fromUserInput (filename);
457+ std::cout << " Loading template " << templateFile.path ().toStdString () << std::endl;
458+ templateWatcher.addPath (templateFile.path ());
356459 settings.setValue (" template" , filename);
357460 refresh ();
358461}
0 commit comments