1 /***************************************************************************
2 * copyright : (C) 2003-2007 by Pascal Brachet *
3 * addons by Frederic Devernay <frederic.devernay@m4x.org> *
4 * http://www.xm1math.net/texmaker/ *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 ***************************************************************************/
12
13 #include "webpublishdialog.h"
14 #include "webpublishdialog_config.h"
15 #include "smallUsefulFunctions.h"
16 #include "utilsUI.h"
17 #include "filedialog.h"
18
WebPublishDialog(QWidget * parent,WebPublishDialogConfig * aConfig,BuildManager * aBuildManager,QTextCodec * input_codec)19 WebPublishDialog::WebPublishDialog(QWidget *parent, WebPublishDialogConfig *aConfig, BuildManager *aBuildManager, QTextCodec *input_codec)
20 : QDialog(parent), config(aConfig), buildManager(aBuildManager), codec (input_codec)
21 {
22 Q_ASSERT(aConfig);
23 Q_ASSERT(aBuildManager);
24 //Q_ASSERT(input_codec);
25 setWindowTitle(tr("Convert to Html"));
26 setModal(true);
27 ui.setupUi(this);
28 UtilsUi::resizeInFontHeight(this, 65, 35);
29
30 ui.alignmentcomboBox->insertItem(0, tr("Left"));
31 ui.alignmentcomboBox->insertItem(1, tr("Center"));
32 ui.alignmentcomboBox->insertItem(2, tr("Right"));
33 ui.navigationBox->insertItem(0, tr("Icons"));
34 ui.navigationBox->insertItem(1, tr("Page numbers"));
35 ui.indexcomboBox->insertItem(0, tr("Yes"));
36 ui.indexcomboBox->insertItem(1, tr("No"));
37 connect(ui.quitButton, SIGNAL(clicked()), this, SLOT(accept()));
38 connect(ui.LaunchButton, SIGNAL(clicked()), this, SLOT(proceedSlot()));
39 connect(ui.inputfileButton, SIGNAL(clicked()), this, SLOT(browseSlot()));
40 init();
41 }
42
~WebPublishDialog()43 WebPublishDialog::~WebPublishDialog()
44 {
45 }
46
accept()47 void WebPublishDialog::accept()
48 {
49 applyusersettings();
50 if (proc && proc->state() == QProcess::Running) {
51 proc->kill();
52 delete proc ;
53 }
54 QDialog::accept();
55 }
56
init()57 void WebPublishDialog::init()
58 {
59 ui.titleEdit->setText(config->title);
60 ui.footnoteEdit->setText(config->address);
61 ui.browserEdit->setText(config->browser);
62 ui.contentEdit->setText(config->contentname);
63 if (config->noindex) ui.indexcomboBox->setCurrentIndex(1);
64 else ui.indexcomboBox->setCurrentIndex(0);
65 if (config->align == "left") ui.alignmentcomboBox->setCurrentIndex(0);
66 if (config->align == "center") ui.alignmentcomboBox->setCurrentIndex(1);
67 if (config->align == "right") ui.alignmentcomboBox->setCurrentIndex(2);
68 if (config->navigation == 1) ui.navigationBox->setCurrentIndex(0);
69 else ui.navigationBox->setCurrentIndex(1);
70 ui.widthspinBox->setValue(config->userwidth);
71 ui.compilationspinBox->setValue(config->compil);
72 ui.tocdepthspinBox->setValue(config->tocdepth);
73 ui.startindexspinBox->setValue(config->startindex);
74 maxwidth = 0;
75 colorlink = "1 0 0";
76 nb_pages = 0;
77 nb_content_pages = 0;
78 id_page = 1;
79 depth = "\\{part\\}|\\{chapter\\}|\\{section\\}";
80 }
81
convert(const QString & fileName)82 void WebPublishDialog::convert(const QString &fileName)
83 {
84 ttwperr = false;
85 errprocess = false;
86 ui.messagetextEdit->clear();
87 QString firstpage;
88 QFileInfo fi(fileName);
89 if (fi.exists() && fi.isReadable()) {
90 workdir = fi.absolutePath();
91 config->lastdir = workdir;
92 base = fi.completeBaseName();
93 if (workdir.endsWith("/")) htmldir = workdir + base + "_html";
94 else htmldir = workdir + "/" + base + "_html";
95 QDir HDir(htmldir);
96 if (HDir.exists()) {
97 QFileInfoList files = HDir.entryInfoList();
98 if (!files.empty()) {
99 for (int i = 0; i < files.size(); ++i) {
100 QString fn = files.at(i).filePath();
101 QFile f(fn);
102 f.remove();
103 }
104 }
105 } else {
106 HDir.mkdir(htmldir);
107 }
108 copyDataFile("style.css", htmldir + "/style.css");
109 copyDataFile("up.gif", htmldir + "/up.gif");
110 copyDataFile("up_d.gif", htmldir + "/up_d.gif");
111 copyDataFile("psheader.txt", workdir + "/psheader.txt");
112 if (config->navigation == 1) {
113 copyDataFile("next.gif", htmldir + "/next.gif");
114 copyDataFile("next_d.gif", htmldir + "/next_d.gif");
115 copyDataFile("prev.gif", htmldir + "/prev.gif");
116 copyDataFile("prev_d.gif", htmldir + "/prev_d.gif");
117 }
118 if (config->title == "") config->title = base;
119 if (config->tocdepth == 2) {
120 depth = depth + "|\\{subsection\\}";
121 } else if (config->tocdepth == 3) {
122 depth = depth + "|\\{subsection\\}|\\{subsubsection\\}";
123 }
124 writepages("content");
125 if (ttwperr || errprocess) return;
126 if (!config->noindex) writepages("index");
127 if (ttwperr || errprocess) return;
128 clean();
129 ui.messagetextEdit->append(tr("Conversion done.\nThe html files are located in the %1 directory.").arg(htmldir));
130 if (!config->noindex) firstpage = htmldir + "/index.html";
131 else firstpage = htmldir + "/page1.html";
132 QFileInfo fip(firstpage);
133 if (fip.exists() && fip.isReadable() && (!config->browser.isEmpty()) && (!errprocess)) {
134 ui.messagetextEdit->append(tr("Running browser ."));
135 proc = new QProcess(this);
136 connect(proc, SIGNAL(finished(int,QProcess::ExitStatus)), proc, SLOT(deleteLater())); //will free proc after the process has ended
137 proc->setWorkingDirectory(workdir);
138
139 proc->start(config->browser,QStringList(firstpage));
140 if (!proc->waitForStarted(1000)) {
141 ui.messagetextEdit->append(tr("Error") + " : " + tr("could not start the command"));
142 errprocess = true;
143 }
144 }
145 } else {
146 ui.messagetextEdit->append(tr("Input file not found."));
147 }
148 }
149
closeEvent(QCloseEvent * ce)150 void WebPublishDialog::closeEvent(QCloseEvent *ce)
151 {
152 if (proc && proc->state() == QProcess::Running) {
153 proc->kill();
154 delete proc ;
155 }
156 applyusersettings();
157 ce->accept();
158 }
159
160 //************************************
RunCommand(const QString & cmd,const QString & file,const bool waitendprocess,const char * stdErrSlot)161 void WebPublishDialog::RunCommand(const QString &cmd, const QString &file, const bool waitendprocess, const char *stdErrSlot)
162 {
163 ProcessX *proc = buildManager->firstProcessOfDirectExpansion(cmd, QFileInfo(file));
164 this->proc = proc;
165 ui.messagetextEdit->append(tr(" Running this command: ") + proc->getCommandLine());
166 curLog = "";
167 proc->setWorkingDirectory(workdir);
168 if (stdErrSlot) connect(proc, SIGNAL(readyReadStandardError()), this, stdErrSlot);
169 else connect(proc, SIGNAL(readyReadStandardError()), this, SLOT(readOutputForLog()));
170 connect(proc, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(SlotEndProcess(int)));
171 proc->startCommand();
172 if (!proc->waitForStarted(1000)) {
173 ui.messagetextEdit->append(tr("Error") + " : " + tr("could not start the command"));
174 errprocess = true;
175 }
176 procfinished = false;
177 if (waitendprocess) {
178 while (!procfinished) { //be carefully when changing this, its duplicated in imgProcess
179 qApp->instance()->processEvents(QEventLoop::ExcludeUserInputEvents);
180 }
181 }
182 }
183
SlotEndProcess(int err)184 void WebPublishDialog::SlotEndProcess(int err)
185 {
186 if (err) {
187 ui.messagetextEdit->append(tr("Error") + " : " + tr("a process has failed"));
188 if (curLog != "") ui.messagetextEdit->append(curLog);
189 errprocess = true;
190 }
191 procfinished = true;
192 }
193
bboxProcess()194 void WebPublishDialog::bboxProcess()
195 {
196 RunCommand("txs:///gs/[-q][-dBATCH][-dNOPAUSE][-sDEVICE=bbox]", workdir + "/page.ps", true, SLOT(readBboxOutput()));
197 }
198
readBboxOutput()199 void WebPublishDialog::readBboxOutput()
200 {
201 QRegExp rxbbox("%%BoundingBox:\\s*([0-9eE\\.\\-]+)\\s+([0-9eE\\.\\-]+)\\s+([0-9eE\\.\\-]+)\\s+([0-9eE\\.\\-]+)");
202 QString line;
203 QByteArray result = proc->readAllStandardError();
204 QTextStream bbox(&result);
205 while (!bbox.atEnd()) {
206 line = bbox.readLine();
207 if (rxbbox.indexIn(line) > -1) {
208 QFile bboxf(workdir + "/bbox.txt");
209 if (!bboxf.open(QIODevice::WriteOnly)) {
210 fatalerror(workdir + "/bbox.txt" + " not found.");
211 return;
212 } else {
213 QTextStream bboxts(&bboxf);
214 bboxts << line;
215 bboxf.close();
216 }
217 }
218 }
219 }
220
imgProcess(const QString & params,const QString & psFile)221 void WebPublishDialog::imgProcess(const QString ¶ms, const QString &psFile)
222 {
223 procfinished = false;
224 RunCommand("txs:///gs/" + params, psFile, false, SLOT(readImgOutput())); //don't wait here, proceed until wait loop below
225 QFile linkf(workdir + "/link.txt");
226 if (!linkf.open(QIODevice::WriteOnly)) {
227 fatalerror(workdir + "/link.txt" + " not found.");
228 return;
229 } else {
230 QTextStream linkts(&linkf);
231 linkts << "";
232 linkf.close();
233 }
234 while (!procfinished) {
235 qApp->instance()->processEvents(QEventLoop::ExcludeUserInputEvents);
236 }
237 }
238
readImgOutput()239 void WebPublishDialog::readImgOutput()
240 {
241 QString line = QString(proc->readAllStandardOutput());
242 QFile linkf(workdir + "/link.txt");
243 if (!linkf.open(QIODevice::WriteOnly)) {
244 fatalerror(workdir + "/link.txt" + " not found.");
245 return;
246 } else {
247 QTextStream linkts(&linkf);
248 linkts << line;
249 linkf.close();
250 }
251 }
252
readOutputForLog()253 void WebPublishDialog::readOutputForLog()
254 {
255 QByteArray result = proc->readAllStandardError();
256 QString t = QString(result);
257 t = t.simplified();
258 if (!t.isEmpty()) curLog.append(t + "\n");
259 }
260
copyDataFile(QString fileNameWithoutDir,QString to_file)261 void WebPublishDialog::copyDataFile(QString fileNameWithoutDir, QString to_file)
262 {
263 QString fiName = findResourceFile(fileNameWithoutDir);
264 if (fiName == "") return;
265 QFile::remove(to_file);
266 QFile::copy(fiName, to_file);
267 }
268
removeFile(QString file)269 void WebPublishDialog::removeFile(QString file)
270 {
271 if (QFile::exists(file)) {
272 QFile fi(file);
273 fi.remove();
274 }
275 }
276
277 //******************************************
header()278 QString WebPublishDialog::header()
279 {
280 QString result = "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'> \n";
281 result += "<html>\n";
282 result += "<head>\n";
283 result += "<META NAME='Generator' CONTENT='TeXstudio (http://texstudio.sourceforge.net/)'>\n";
284 result += "<title>" + config->title + "</title>\n";
285 result += "<link rel=StyleSheet href='style.css' type='text/css'>\n";
286 result += "</head>\n";
287 result += "<body bgcolor='white'>\n";
288 return result;
289 }
290
footer()291 QString WebPublishDialog::footer()
292 {
293 QString result = "<div align='" + config->align + "' id='address'> " + config->address + " </div>\n";
294 result += "</body>\n";
295 result += "</html>";
296 return result;
297 }
298
content_navigation(int page,int numpages,QString up_page)299 QString WebPublishDialog::content_navigation(int page, int numpages, QString up_page)
300 {
301 QString result;
302 QString leftcode = "";
303 QString rightcode = "";
304 QString upcode = "";
305 int prev_page = page - 1;
306 int next_page = page + 1;
307 if (config->navigation == 1) {
308 if (page > 1) {
309 leftcode = "<A HREF='page" + QString::number(prev_page) + ".html'><IMG src='prev.gif' align='middle' border='0'></A>";
310 } else {
311 leftcode = "<IMG src='prev_d.gif' align='middle' border='0'>";
312 }
313
314 if (page < numpages) {
315 rightcode = "<A HREF='page" + QString::number(next_page) + ".html'><IMG src='next.gif' align='middle' border='0'></A>";
316 } else {
317 rightcode = "<IMG src='next_d.gif' align='middle' border='0'>" ;
318 }
319 } else {
320 if (page > 1) {
321 leftcode = "<A HREF='page" + QString::number(prev_page) + ".html'> " + QString::number(prev_page) + "/" + QString::number(nb_content_pages) + " <</A>" ;
322 } else {
323 leftcode = " ";
324 }
325 if (page < numpages) {
326 rightcode = "<A HREF='page" + QString::number(next_page) + ".html'>> " + QString::number(next_page) + "/" + QString::number(nb_content_pages) + " </A>" ;
327 } else {
328 rightcode = " ";
329 }
330 }
331 if (page > 0) {
332 upcode = "<A HREF='" + up_page + "'><IMG src='up.gif' align='middle' border='0'></A>" ;
333 } else {
334 upcode = "<IMG src='up_d.gif' align='middle' border='0'>";
335 }
336 result = "<div id='navigation'>\n <table border=0 cellpadding=2 cellspacing=0 width='100%'>\n ";
337 result += "<tr valign='middle'>\n ";
338 result += "<td align='left' valign='middle' width='33%'>" + leftcode + "</td>\n";
339 result += "<td align='center' valign='middle' width='34%'>" + upcode + "</td>\n";
340 result += "<td align='right' valign='middle' width='33%'>" + rightcode + "</td>\n";
341 result += "</tr>\n";
342 result += "</table>\n";
343 result += "</div>\n";
344 return result;
345 }
346
nbpagesps(QString psfile)347 int WebPublishDialog:: nbpagesps(QString psfile)
348 {
349 QString line;
350 QString captured = "0";
351 bool ok;
352 QFile f(psfile);
353 QRegExp rx("^%%Pages:\\s+(-?\\d+)");
354 if (!f.open(QIODevice::ReadOnly)) {
355 fatalerror(psfile + " not found.");
356 return 0;
357 } else {
358 QTextStream psts(&f);
359 while (!psts.atEnd()) {
360 line = psts.readLine();
361 if (rx.indexIn(line) > -1) {
362 captured = rx.cap(1);
363 break;
364 }
365 }
366 f.close();
367 int result = captured.toInt(&ok);
368 if (ok && (result > 0)) {
369 return result;
370 } else {
371 return 0;
372 }
373 }
374 }
375
extractpage(QString psfile,int page)376 void WebPublishDialog::extractpage(QString psfile, int page)
377 {
378 QString line;
379
380 QFile f(workdir + "/" + psfile);
381 QRegExp rxpage("^%%Page:\\s+(-?\\d+)");
382 QRegExp rxtrailer("^%%Trailer");
383 QRegExp rx("^%%Pages:\\s+(-?\\d+)");
384 if (!f.open(QIODevice::ReadOnly)) {
385 fatalerror(psfile + " not found.");
386 return;
387 } else {
388 QTextStream psts(&f);
389 QFile outf(workdir + "/page.ps");
390 if (!outf.open(QIODevice::WriteOnly)) {
391 fatalerror("Can't open " + workdir + "/page.ps");
392 return;
393 } else {
394 QTextStream outts(&outf);
395 bool go = true;
396 while (!psts.atEnd()) {
397 line = psts.readLine();
398 if (rxpage.indexIn(line) > -1) {
399 int numpage = rxpage.cap(1).toInt();
400 if (numpage == page) {
401 line = "%%Page: 1 1";
402 go = true;
403 } else go = false;
404 }
405 if (rxtrailer.indexIn(line) > -1) go = true;
406 if (rx.indexIn(line) > -1) line = "%%Pages: 1 0";
407 if (go) outts << line + "\n";
408 }
409 outf.close();
410 }
411 f.close();
412 }
413 }
414
codepic(QString pic_name,QString map_name)415 QString WebPublishDialog::codepic(QString pic_name, QString map_name)
416 {
417 QString result = "<div id='content' align='" + config->align + "'><IMG src='" + pic_name + "' align='middle' border='0'";
418 if (map_name != "") result += " usemap='#" + map_name + "'";
419 result += "></div>\n";
420 return result;
421 }
422
ps2gif(QString input,QString output,int id_page,int w,int h,int maxw)423 void WebPublishDialog::ps2gif(QString input, QString output, int id_page, int w, int h, int maxw)
424 {
425 if (!errprocess) extractpage(input, id_page);
426 if (ttwperr || errprocess) return;
427 float resolution = float(72 * config->userwidth) / maxw;
428 float scale = float(config->userwidth) / maxw;
429 int gx = int(w * resolution / 72 + 0.5);
430 int gy = int(h * resolution / 72 + 0.5);
431 QFile psf(workdir + "/page.ps");
432 if (!psf.open(QIODevice::ReadOnly)) {
433 fatalerror(workdir + "/page.ps" + " not found.");
434 return;
435 } else {
436 QTextStream psts(&psf);
437 QFile outf(workdir + "/tmp.ps");
438 if (!outf.open(QIODevice::WriteOnly)) {
439 fatalerror("Can't open " + workdir + "/tmp.ps");
440 return;
441 } else {
442 QTextStream outts(&outf);
443 bool flag = false;
444 QString line;
445 while (!psts.atEnd()) {
446 line = psts.readLine();
447 if (line.indexOf(QRegularExpression("^%%BoundingBox:\\s(\\d+)\\s(\\d+)\\s(\\d+)\\s(\\d+)/)"), 0) != -1) {
448 outts << "%%BoundingBox: 0 0 " + QString::number(w) + " " + QString::number(h) + "\n";
449 } else if ((!flag) && ((line.indexOf(QRegularExpression("^%%EndSetup"), 0) > -1) || (line.indexOf(QRegularExpression("^%%Page:"), 0) > -1))) {
450 outts << line + "\n";
451 outts << QString::number(x1) + " neg " + QString::number(y1) + " neg translate\n";
452 flag = true;
453 } else if (line.indexOf(QRegularExpression("/uscale\\s+([0-9eE\\.\\-]+)\\s+N"), 0) != -1) {
454 outts << "/uscale " + QString::number(scale) + " N\n";
455 } else {
456 outts << line + "\n";
457 }
458 }
459 psf.close();
460 outf.close();
461 if (w != 0) {
462 if (!errprocess) imgProcess("[-q][-dSAFER -dBATCH -dNOPAUSE][-sDEVICE=png16m][-g" + QString::number(gx) + "x" + QString::number(gy) + "][-r" + QString::number(resolution) + "][-dTextAlphaBits=4][-dGraphicsAlphaBits=4][-sOutputFile=\"" + output + QString::number(id_page) + ".png\"]", workdir + "/tmp.ps");
463 if (ttwperr || errprocess) return;
464 } else {
465 copyDataFile("blank.png", htmldir + "/" + output + QString::number(id_page) + ".png");
466 }
467 removeFile(workdir + "/page.ps");
468 removeFile(workdir + "/tmp.ps");
469 removeFile(workdir + "/tmp.ppm");
470 }
471 }
472 }
473
writepages(QString mode)474 void WebPublishDialog::writepages(QString mode)
475 {
476 bool match = false;
477 bool ok;
478 maxwidth = 1;
479 QString line;
480 QString captured1, captured2, captured3, captured4;
481 x1box.clear();
482 y1box.clear();
483 x2box.clear();
484 y2box.clear();
485
486 if (mode == "content") {
487 QFile outf(workdir + "/" + base + "_" + mode + ".tex");
488 if (!outf.open(QIODevice::WriteOnly)) {
489 fatalerror(tr("Can't open") + " " + workdir + "/" + base + "_" + mode + ".tex");
490 return;
491 } else {
492 QTextStream outts(&outf);
493 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
494 outts.setCodec(codec);
495 #endif
496
497 QFile texf(workdir + "/" + base + ".tex");
498 if (!texf.open(QIODevice::ReadOnly)) {
499 fatalerror(workdir + "/" + base + ".tex " + tr("not found") + ".");
500 return;
501 } else {
502 QTextStream texts(&texf);
503 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
504 texts.setCodec(codec);
505 #endif
506 while (!texts.atEnd()) {
507 line = texts.readLine();
508 if (!match && (line.indexOf(QRegularExpression("^\\\\begin\\{document\\}"), 0) != -1)) {
509 outts << "\\newbox\\bwk\\edef\\tempd#1pt{#1\\string p\\string t}\\tempd\\def\\nbextr#1pt{#1}\n";
510 outts << "\\def\\npts#1{\\expandafter\\nbextr\\the#1\\space}\n";
511 outts << "\\def\\ttwplink#1#2{\\special{ps:" + colorlink + " setrgbcolor}#2\\special{ps:0 0 0 setrgbcolor}\\setbox\\bwk=\\hbox{#2}\\special{ps:( linkto #1)\\space\\npts{\\wd\\bwk} \\npts{\\dp\\bwk} -\\npts{\\ht\\bwk} true\\space Cpos}}\n";
512 match = true;
513 }
514 outts << line + "\n";
515 }
516 texf.close();
517 outf.close();
518 ui.messagetextEdit->append(tr("Compiling input file. Please wait..."));
519 int counter = 1;
520 while (counter <= config->compil) {
521 if (!errprocess)
522 RunCommand(BuildManager::CMD_LATEX, workdir + "/" + base + "_" + mode + ".tex", true);
523 //RunCommand("latex -interaction=nonstopmode "+base+"_"+mode+".tex",true);
524
525 latexerror(workdir + "/" + base + "_" + mode + ".log");
526 if (ttwperr || errprocess) break;
527 counter++;
528 }
529 if (ttwperr || errprocess) return;
530 QFile auxf(workdir + "/" + base + "_content.aux");
531 if (!auxf.open(QIODevice::ReadOnly)) {
532 fatalerror(mode + workdir + "/" + base + "_content.aux " + tr("not found") + ".");
533 return;
534 } else {
535 QTextStream auxts(&auxf);
536 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
537 auxts.setCodec(codec);
538 #endif
539 QRegExp rx("\\\\newlabel\\{(.*)\\}\\{\\{.*\\}\\{(\\d+)\\}\\}");
540 while (!auxts.atEnd()) {
541 QString line = auxts.readLine();
542 if (rx.indexIn(line) != -1) {
543 QString captured1 = rx.cap(1);
544 QString captured2 = rx.cap(2);
545 loc[captured1] = "page" + captured2 + ".html";
546 }
547 }
548 auxf.close();
549 }
550 }
551 }
552 } else if (mode == "index") {
553 QFile outf(workdir + "/" + base + "_" + mode + ".tex");
554 if (!outf.open(QIODevice::WriteOnly)) {
555 fatalerror(tr("Can't open") + " " + workdir + "/" + base + "_" + mode + ".tex");
556 return;
557 } else {
558 QTextStream outts(&outf);
559 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
560 outts.setCodec(codec);
561 #endif
562 QFile texf(workdir + "/" + base + ".tex");
563 if (!texf.open(QIODevice::ReadOnly)) {
564 fatalerror(workdir + "/" + base + ".tex " + tr("not found") + ".");
565 return;
566 } else {
567 QTextStream texts(&texf);
568 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
569 texts.setCodec(codec);
570 #endif
571 match = false;
572 while (!texts.atEnd()) {
573 line = texts.readLine();
574 if (line.indexOf(QRegularExpression("^\\\\begin\\{document\\}"), 0) > -1) {
575 match = true;
576 }
577 if (!match) {
578 outts << line + "\n";
579 }
580 }
581 texf.close();
582 outts << "\\pagestyle{empty}\n";
583 outts << "\\setcounter{tocdepth}{" + QString::number(config->tocdepth) + "} \n";
584 outts << "\\newbox\\bwk\\edef\\tempd#1pt{#1\\string p\\string t}\\tempd\\def\\nbextr#1pt{#1}\n";
585 outts << "\\def\\npts#1{\\expandafter\\nbextr\\the#1\\space}\n";
586 outts << "\\def\\ttwplink#1#2{#2\\setbox\\bwk=\\vbox{#2}\\special{ps:( linkto #1)\\space\\npts{\\wd\\bwk} \\npts{\\dp\\bwk} -\\npts{\\ht\\bwk} false\\space Cpos}}\n";
587 outts << "\\begin{document}\n";
588 outts << "\\section*{" + config->contentname + "}\n";
589 outts << "\\makeatletter\n\\parindent = 0.0 in\n";
590 QFile auxf(workdir + "/" + base + "_content.aux");
591 if (!auxf.open(QIODevice::ReadOnly)) {
592 fatalerror(mode + workdir + "/" + base + "_content.aux " + tr("not found") + ".");
593 return;
594 } else {
595 QTextStream auxts(&auxf);
596 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
597 auxts.setCodec(codec);
598 #endif
599 QRegExp rx("\\\\@writefile\\{toc\\}.*(" + depth + ").*\\{(\\d+)\\}\\}");
600 while (!auxts.atEnd()) {
601 line = auxts.readLine();
602 if (rx.indexIn(line) > -1) {
603 captured2 = rx.cap(2);
604 id_page = captured2.toInt(&ok);
605 line.remove(QRegularExpression("\\\\@writefile\\{toc\\}"));
606 if (line.indexOf(QRegularExpression("\\\\numberline"), 0) > -1) {
607 id_page = id_page + config->startindex - 1;
608 outts << "\\ttwplink{page" + QString::number(id_page) + ".html}";
609 } else {
610 outts << "\\ttwplink{none}";
611 }
612 outts << line + "\n\n";
613 }
614 }
615 auxf.close();
616 outts << "\\end{document}" ;
617 outf.close();
618 if (!errprocess)
619 RunCommand(BuildManager::CMD_LATEX, workdir + "/" + base + "_" + mode + ".tex", true);
620 latexerror(workdir + "/" + base + "_" + mode + ".log");
621 if (ttwperr || errprocess) return;
622 }
623 }
624 }
625 }
626 if (!errprocess)
627 RunCommand("txs:///dvips/[-q " + config->dviopt + " -h psheader.txt]", workdir + "/" + base + "_" + mode + ".tex", true);
628 //RunCommand("dvips -q "+dviopt+" -h psheader.txt -o "+base+"_"+mode+".ps "+base+"_"+mode+".dvi",true) ;
629
630 if (ttwperr || errprocess) return;
631 QString link = "none";
632 int nb_link = 0;
633 int W, H;
634 nb_pages = nbpagesps(workdir + "/" + base + "_" + mode + ".ps");
635 if (ttwperr || errprocess) return;
636 id_page = 1;
637 ui.messagetextEdit->append(tr("Scanning files. Please wait..."));
638 while (id_page <= nb_pages) {
639 if (!errprocess) extractpage(base + "_" + mode + ".ps", id_page);
640 if (ttwperr || errprocess) return;
641 if (!errprocess) bboxProcess();
642 if (ttwperr || errprocess) return;
643 QFile bboxf(workdir + "/bbox.txt");
644 if (!bboxf.open(QIODevice::ReadOnly)) {
645 fatalerror(workdir + "/bbox.txt " + tr("not found") + ".");
646 return;
647 } else {
648 QTextStream bboxts(&bboxf);
649 QRegExp rx("%%BoundingBox:\\s*([0-9eE\\.\\-]+)\\s+([0-9eE\\.\\-]+)\\s+([0-9eE\\.\\-]+)\\s+([0-9eE\\.\\-]+)");
650 while (!bboxts.atEnd()) {
651 QString line = bboxts.readLine();
652 if (rx.indexIn(line) != -1) {
653 captured1 = rx.cap(1);
654 x1 = captured1.toInt(&ok);
655 captured2 = rx.cap(2);
656 y1 = captured2.toInt(&ok);
657 captured3 = rx.cap(3);
658 x2 = captured3.toInt(&ok);
659 captured4 = rx.cap(4);
660 y2 = captured4.toInt(&ok);
661 }
662 }
663 bboxf.close();
664 x1box.append(x1);
665 y1box.append(y1);
666 x2box.append(x2);
667 y2box.append(y2);
668 W = x2 - x1;
669 if (W > maxwidth) {
670 maxwidth = W ;
671 }
672 }
673 removeFile(workdir + "/page.ps");
674 removeFile(workdir + "/bbox.txt");
675 id_page++;
676 }
677 if (mode == "content") {
678 id_page = 1;
679 nb_content_pages = nb_pages;
680 while (id_page <= nb_pages) {
681 ui.messagetextEdit->append(tr("Writing page") + " " + QString::number(id_page) + " " + tr("of") + " " + QString::number(nb_pages));
682 x1 = x1box[id_page - 1];
683 y1 = y1box[id_page - 1];
684 x2 = x2box[id_page - 1];
685 y2 = y2box[id_page - 1];
686 W = x2 - x1;
687 H = y2 - y1;
688 ps2gif(base + "_" + mode + ".ps", htmldir + "/image", id_page, W, H, maxwidth);
689 if (ttwperr || errprocess) return;
690 QFile htmf(htmldir + "/page" + QString::number(id_page) + ".html");
691 if (!htmf.open(QIODevice::WriteOnly)) {
692 fatalerror(tr("Can't open") + " " + htmldir + "/page" + QString::number(id_page) + ".html");
693 return;
694 } else {
695 QTextStream htmts(&htmf);
696 htmts << header();
697 if (config->noindex) {
698 htmts << content_navigation(id_page, nb_pages, "page1.html");
699 } else {
700 htmts << content_navigation(id_page, nb_pages, "index.html");
701 }
702 QFile linkf(workdir + "/link.txt");
703 if (!linkf.open(QIODevice::ReadOnly)) {
704 fatalerror(workdir + "/link.txt" + " " + tr("not found") + ".");
705 return;
706 } else {
707 QTextStream LINK(&linkf);
708 QRegExp rx("x1=([0-9eE\\.\\-]+)\\s+y1=([0-9eE\\.\\-]+)\\s+x2=([0-9eE\\.\\-]+)\\s+y2=([0-9eE\\.\\-]+)\\s+linkto\\s+(.*)$");
709 nb_link = 0 ;
710 htmts << "<map name='carte" + QString::number(id_page) + "'>\n" ;
711 while (!LINK.atEnd()) {
712 line = LINK.readLine();
713 if (rx.indexIn(line) > -1) {
714 captured1 = rx.cap(1);
715 x1 = int(captured1.toFloat(&ok) + 0.5);
716 captured2 = rx.cap(2);
717 y1 = int(captured2.toFloat(&ok) + 0.5);
718 captured3 = rx.cap(3);
719 x2 = int(captured3.toFloat(&ok) + 0.5);
720 captured4 = rx.cap(4);
721 y2 = int(captured4.toFloat(&ok) + 0.5);
722 link = rx.cap(5);
723 if (link != "none") {
724 LinkMap::Iterator it = loc.find(link);
725 if (it != loc.end()) {
726 htmts << "<area shape='rect' coords='" + QString::number(x1) + "," + QString::number(y1) + "," + QString::number(x2) + "," + QString::number(y2) + "' href='" + it.value() + "' >\n" ;
727 } else {
728 htmts << "<area shape='rect' coords='" + QString::number(x1) + "," + QString::number(y1) + "," + QString::number(x2) + "," + QString::number(y2) + "' href='" + link + "' >\n" ;
729 }
730 }
731 nb_link++;
732 }
733 }
734 linkf.close();
735 htmts << "</map>\n" ;
736 if (nb_link > 0) {
737 htmts << codepic("image" + QString::number(id_page) + ".png", "carte" + QString::number(id_page));
738 } else {
739 htmts << codepic("image" + QString::number(id_page) + ".png", "");
740 }
741 if (config->noindex) {
742 htmts << content_navigation(id_page, nb_pages, "page1.html");
743 } else {
744 htmts << content_navigation(id_page, nb_pages, "index.html");
745 }
746 htmts << footer();
747 htmf.close() ;
748
749 }
750 }
751 id_page++;
752 }
753 } else if (mode == "index") {
754 ui.messagetextEdit->append(tr("Writing index page"));
755 QFile htmf(htmldir + "/index.html");
756 if (!htmf.open(QIODevice::WriteOnly)) {
757 fatalerror(tr("Can't open") + " " + htmldir + "/index.html");
758 return;
759 } else {
760 QTextStream htmts(&htmf);
761 htmts << header();
762 htmts << content_navigation(0, 1, "");
763 id_page = 1;
764 while (id_page <= nb_pages) {
765 x1 = x1box[id_page - 1];
766 y1 = y1box[id_page - 1];
767 x2 = x2box[id_page - 1];
768 y2 = y2box[id_page - 1];
769 W = x2 - x1;
770 H = y2 - y1;
771 ps2gif(base + "_" + mode + ".ps", htmldir + "/" + mode + "image", id_page, W, H, maxwidth);
772 if (ttwperr || errprocess) return;
773 QFile linkf(workdir + "/link.txt");
774 if (!linkf.open(QIODevice::ReadOnly)) {
775 fatalerror(workdir + "/link.txt " + tr("not found") + ".");
776 return;
777 } else {
778 QTextStream LINK(&linkf);
779 QRegExp rx("x1=([0-9eE\\.\\-]+)\\s+y1=([0-9eE\\.\\-]+)\\s+x2=([0-9eE\\.\\-]+)\\s+y2=([0-9eE\\.\\-]+)\\s+linkto\\s+(.*)$");
780 nb_link = 0 ;
781 htmts << "<map name='carte" + QString::number(id_page) + "'>\n" ;
782 while (!LINK.atEnd()) {
783 line = LINK.readLine();
784 if (rx.indexIn(line) > -1) {
785 captured1 = rx.cap(1);
786 x1 = int(captured1.toFloat(&ok) + 0.5);
787 captured2 = rx.cap(2);
788 y1 = int(captured2.toFloat(&ok) + 0.5);
789 captured3 = rx.cap(3);
790 x2 = int(captured3.toFloat(&ok) + 0.5);
791 captured4 = rx.cap(4);
792 y2 = int(captured4.toFloat(&ok) + 0.5);
793 link = rx.cap(5);
794 if (link != "none") {
795 htmts << "<area shape='rect' coords='" + QString::number(x1) + "," + QString::number(y1) + "," + QString::number(x2) + "," + QString::number(y2) + "' href='" + link + "' >\n" ;
796 }
797 nb_link++;
798 }
799 }
800 linkf.close();
801 htmts << "</map>\n" ;
802 }
803 id_page++;
804 }
805 id_page = 1;
806 while (id_page <= nb_pages) {
807 htmts << codepic(mode + "image" + QString::number(id_page) + ".png", "carte" + QString::number(id_page));
808 id_page++;
809 }
810 htmts << content_navigation(0, 1, "");
811 htmts << footer();
812 htmf.close();
813 }
814 }
815 }
816
fatalerror(QString msg)817 void WebPublishDialog::fatalerror(QString msg)
818 {
819 clean();
820 ui.messagetextEdit->append(tr("Fatal error : ") + msg);
821 ttwperr = true;
822 }
823
clean()824 void WebPublishDialog::clean()
825 {
826 removeFile(workdir + "/psheader.txt");
827 removeFile(workdir + "/link.txt");
828 QStringList extension = QString(".tex,.log,.aux,.dvi,.lof,.lot,.bit,.idx,.glo,.bbl,.ilg,.toc,.ind,.ps").split(",");
829 for (QStringList::Iterator it = extension.begin(); it != extension.end(); ++it) {
830 removeFile(workdir + "/" + base + "_content" + *it);
831 removeFile(workdir + "/" + base + "_index" + *it);
832 }
833 }
834
latexerror(QString logfile)835 void WebPublishDialog::latexerror(QString logfile)
836 {
837 QRegExp rx("^!");
838 QString line;
839 QFile logf(logfile);
840 if (!logf.open(QIODevice::ReadOnly)) {
841 fatalerror(logfile + " " + tr("not found") + ".");
842 } else {
843 QTextStream LOG(&logf);
844 bool ok = true;
845 while (!LOG.atEnd()) {
846 line = LOG.readLine();
847 if (rx.indexIn(line) > -1) {
848 ok = false;
849 }
850 }
851 logf.close();
852 if (!ok) fatalerror(tr("LaTeX errors detected."));
853 }
854 }
855
proceedSlot()856 void WebPublishDialog::proceedSlot()
857 {
858 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
859 ui.messagetextEdit->clear();
860 applyusersettings();
861 convert(ui.inputfileEdit->text());
862 QApplication::restoreOverrideCursor();
863 }
864
browseSlot()865 void WebPublishDialog::browseSlot()
866 {
867 QString fn = FileDialog::getOpenFileName(this, tr("Open File"), config->lastdir, tr("TeX files (*.tex);;All files (*.*)"));
868 if (!fn.isEmpty()) {
869 ui.inputfileEdit->setText(fn);
870 }
871 }
872
applyusersettings()873 void WebPublishDialog::applyusersettings()
874 {
875 config->title = ui.titleEdit->text();
876 config->address = ui.footnoteEdit->text();
877 config->browser = ui.browserEdit->text();
878 config->contentname = ui.contentEdit->text();
879 if (ui.indexcomboBox->currentIndex() == 0) config->noindex = false;
880 else config->noindex = true;
881 if (ui.alignmentcomboBox->currentIndex() == 0) config->align = "left";
882 if (ui.alignmentcomboBox->currentIndex() == 1) config->align = "center";
883 if (ui.alignmentcomboBox->currentIndex() == 2) config->align = "right";
884 if (ui.navigationBox->currentIndex() == 0) config->navigation = 1;
885 else config->navigation = 0;
886 config->userwidth = ui.widthspinBox->value();
887 config->compil = ui.compilationspinBox->value();
888 config->tocdepth = ui.tocdepthspinBox->value();
889 config->startindex = ui.startindexspinBox->value();
890 }
891
892
893
894
895 //===================================================
896 // Config Management
897 //===================================================
898
899
readSettings(QSettings & settings)900 void WebPublishDialogConfig::readSettings(QSettings &settings)
901 {
902 settings.beginGroup("qttwp");
903 userwidth = settings.value("/userwidth", 700).toInt();
904 compil = settings.value("/compil", 1).toInt();
905 tocdepth = settings.value("/tocdepth", 2).toInt();
906 startindex = settings.value("/startindex", 1).toInt();
907 navigation = settings.value("/navigation", 1).toInt();
908 noindex = settings.value("/noindex", false).toBool();
909 title = settings.value("/title", "").toString();
910 address = settings.value("/address", "").toString();
911 #if defined Q_WS_X11 || defined Q_OS_LINUX
912 QString kdesession = ::getenv("KDE_FULL_SESSION");
913 if (!kdesession.isEmpty()) browser = settings.value("/browser", "konqueror").toString();
914 else browser = settings.value("/browser", "firefox").toString();
915 //programdir=PREFIX"/share/texstudio";
916 #endif
917 #ifdef Q_OS_MAC
918 browser = settings.value("/browser", "open").toString();
919 //programdir="/Applications/texstudio.app/Contents/Resources";
920 #endif
921 #ifdef Q_OS_WIN32
922 browser = settings.value("/browser", "\"C:/Program Files/Internet Explorer/IEXPLORE.EXE\"").toString();
923 //programdir=QCoreApplication::applicationDirPath();
924 #endif
925 contentname = settings.value("/contentname", "\\contentsname").toString();
926 align = settings.value("/align", "center").toString();
927 lastdir = settings.value("/lastdir", QDir::homePath()).toString();
928 dviopt = settings.value("/dviopt", " -Ppk -V").toString();
929
930 settings.endGroup();
931 }
932
933 // applyusersettings();
saveSettings(QSettings & settings)934 void WebPublishDialogConfig::saveSettings(QSettings &settings)
935 {
936 settings.beginGroup("qttwp");
937 settings.setValue("userwidth", userwidth);
938 settings.setValue("compil", compil);
939 settings.setValue("tocdepth", tocdepth);
940 settings.setValue("startindex", startindex);
941 settings.setValue("navigation", navigation);
942 settings.setValue("noindex", noindex);
943 settings.setValue("title", title);
944 settings.setValue("address", address);
945 settings.setValue("browser", browser);
946 settings.setValue("contentname", contentname);
947 settings.setValue("align", align);
948 settings.setValue("lastdir", lastdir);
949 settings.setValue("dviopt", dviopt);
950 settings.endGroup();
951 }
952
953