1 /*
2 This is part of TeXworks, an environment for working with TeX documents
3 Copyright (C) 2007-2016 Jonathan Kew, Stefan Löffler, Charlie Sharpsteen
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 For links to further information, or to contact the authors,
19 see <http://www.tug.org/texworks/>.
20 */
21
22 #include "PrefsDialog.h"
23 #include "DefaultPrefs.h"
24 #include "TWApp.h"
25 #include "PDFDocument.h"
26 #include "TeXHighlighter.h"
27 #include "CompletingEdit.h"
28
29 #include <QFontDatabase>
30 #include <QTextCodec>
31 #include <QSet>
32 #include <QFileDialog>
33 #include <QMainWindow>
34 #include <QToolBar>
35 #include <QDesktopWidget>
36 //#include <QtAlgorithms>
37 #include <QMessageBox>
38
PrefsDialog(QWidget * parent)39 PrefsDialog::PrefsDialog(QWidget *parent)
40 : QDialog(parent)
41 {
42 init();
43 }
44
init()45 void PrefsDialog::init()
46 {
47 setupUi(this);
48
49 connect(buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(buttonClicked(QAbstractButton*)));
50
51 connect(binPathList, SIGNAL(itemSelectionChanged()), this, SLOT(updatePathButtons()));
52 connect(pathUp, SIGNAL(clicked()), this, SLOT(movePathUp()));
53 connect(pathDown, SIGNAL(clicked()), this, SLOT(movePathDown()));
54 connect(pathAdd, SIGNAL(clicked()), this, SLOT(addPath()));
55 connect(pathRemove, SIGNAL(clicked()), this, SLOT(removePath()));
56
57 connect(toolList, SIGNAL(itemSelectionChanged()), this, SLOT(updateToolButtons()));
58 connect(toolList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(editTool(QListWidgetItem*)));
59 connect(toolUp, SIGNAL(clicked()), this, SLOT(moveToolUp()));
60 connect(toolDown, SIGNAL(clicked()), this, SLOT(moveToolDown()));
61 connect(toolAdd, SIGNAL(clicked()), this, SLOT(addTool()));
62 connect(toolRemove, SIGNAL(clicked()), this, SLOT(removeTool()));
63 connect(toolEdit, SIGNAL(clicked()), this, SLOT(editTool()));
64
65 connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(changedTabPanel(int)));
66
67 pathsChanged = toolsChanged = false;
68 }
69
changedTabPanel(int index)70 void PrefsDialog::changedTabPanel(int index)
71 {
72 // this all feels a bit hacky, but seems to keep things tidy on Mac OS X at least
73 QWidget *page = tabWidget->widget(index);
74 page->clearFocus();
75 switch (index) {
76 case 0: // General
77 if (page->focusWidget() != NULL)
78 page->focusWidget()->clearFocus();
79 break;
80 case 1: // Editor
81 editorFont->setFocus();
82 editorFont->lineEdit()->selectAll();
83 break;
84 case 2: // Preview
85 scale->setFocus();
86 scale->selectAll();
87 break;
88 case 3: // Typesetting
89 binPathList->setFocus();
90 break;
91 case 4: // Script
92 if (page->focusWidget() != NULL)
93 page->focusWidget()->clearFocus();
94 break;
95 }
96 }
97
updatePathButtons()98 void PrefsDialog::updatePathButtons()
99 {
100 int selRow = -1;
101 if (binPathList->selectedItems().count() > 0)
102 selRow = binPathList->currentRow();
103 pathRemove->setEnabled(selRow != -1);
104 pathUp->setEnabled(selRow > 0);
105 pathDown->setEnabled(selRow != -1 && selRow < binPathList->count() - 1);
106 }
107
movePathUp()108 void PrefsDialog::movePathUp()
109 {
110 int selRow = -1;
111 if (binPathList->selectedItems().count() > 0)
112 selRow = binPathList->currentRow();
113 if (selRow > 0) {
114 QListWidgetItem *item = binPathList->takeItem(selRow);
115 binPathList->insertItem(selRow - 1, item);
116 binPathList->setCurrentItem(binPathList->item(selRow - 1));
117 pathsChanged = true;
118 }
119 }
120
movePathDown()121 void PrefsDialog::movePathDown()
122 {
123 int selRow = -1;
124 if (binPathList->selectedItems().count() > 0)
125 selRow = binPathList->currentRow();
126 if (selRow != -1 && selRow < binPathList->count() - 1) {
127 QListWidgetItem *item = binPathList->takeItem(selRow);
128 binPathList->insertItem(selRow + 1, item);
129 binPathList->setCurrentItem(binPathList->item(selRow + 1));
130 pathsChanged = true;
131 }
132 }
133
addPath()134 void PrefsDialog::addPath()
135 {
136 QString dir = QFileDialog::getExistingDirectory(this, tr("Choose Directory"),
137 "/usr", /*0*/ /*QFileDialog::DontUseNativeDialog*/
138 QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
139 // remove the trailing / (if any)
140 dir = QDir::fromNativeSeparators(dir);
141 #if defined(Q_OS_WIN)
142 if (dir.length() > 2)
143 #else
144 if (dir.length() > 1)
145 #endif
146 if (dir.at(dir.length() - 1) == '/')
147 dir.chop(1);
148 if (dir != "") {
149 binPathList->addItem(dir);
150 binPathList->setCurrentItem(binPathList->item(binPathList->count() - 1));
151 pathsChanged = true;
152 }
153 }
154
removePath()155 void PrefsDialog::removePath()
156 {
157 if (binPathList->currentRow() > -1)
158 if (binPathList->currentItem()->isSelected()) {
159 binPathList->takeItem(binPathList->currentRow());
160 pathsChanged = true;
161 }
162 }
163
updateToolButtons()164 void PrefsDialog::updateToolButtons()
165 {
166 int selRow = -1;
167 if (toolList->selectedItems().count() > 0)
168 selRow = toolList->currentRow();
169 toolEdit->setEnabled(selRow != -1);
170 toolRemove->setEnabled(selRow != -1);
171 toolUp->setEnabled(selRow > 0);
172 toolDown->setEnabled(selRow != -1 && selRow < toolList->count() - 1);
173 }
174
moveToolUp()175 void PrefsDialog::moveToolUp()
176 {
177 int selRow = -1;
178 if (toolList->selectedItems().count() > 0)
179 selRow = toolList->currentRow();
180 if (selRow > 0) {
181 QListWidgetItem *item = toolList->takeItem(selRow);
182 toolList->insertItem(selRow - 1, item);
183 toolList->setCurrentItem(toolList->item(selRow - 1));
184 Engine e = engineList.takeAt(selRow);
185 engineList.insert(selRow - 1, e);
186 refreshDefaultTool();
187 toolsChanged = true;
188 }
189 }
190
moveToolDown()191 void PrefsDialog::moveToolDown()
192 {
193 int selRow = -1;
194 if (toolList->selectedItems().count() > 0)
195 selRow = toolList->currentRow();
196 if (selRow != -1 && selRow < toolList->count() - 1) {
197 QListWidgetItem *item = toolList->takeItem(selRow);
198 toolList->insertItem(selRow + 1, item);
199 toolList->setCurrentItem(toolList->item(selRow + 1));
200 Engine e = engineList.takeAt(selRow);
201 engineList.insert(selRow + 1, e);
202 refreshDefaultTool();
203 toolsChanged = true;
204 }
205 }
206
addTool()207 void PrefsDialog::addTool()
208 {
209 Engine e;
210 e.setName(tr("New Tool"));
211 e.setShowPdf(true);
212 if (ToolConfig::doToolConfig(this, e) == QDialog::Accepted) {
213 engineList.append(e);
214 toolList->addItem(e.name());
215 refreshDefaultTool();
216 toolsChanged = true;
217 }
218 }
219
removeTool()220 void PrefsDialog::removeTool()
221 {
222 if (toolList->currentRow() > -1)
223 if (toolList->currentItem()->isSelected()) {
224 engineList.removeAt(toolList->currentRow());
225 toolList->takeItem(toolList->currentRow());
226 refreshDefaultTool();
227 toolsChanged = true;
228 }
229 }
230
editTool(QListWidgetItem * item)231 void PrefsDialog::editTool(QListWidgetItem* item)
232 {
233 int row = -1;
234 if (item)
235 row = toolList->row(item);
236 else if (toolList->currentRow() > -1 && toolList->currentItem()->isSelected())
237 row = toolList->currentRow();
238 if (row > -1) {
239 Engine e = engineList[toolList->currentRow()];
240 if (ToolConfig::doToolConfig(this, e) == QDialog::Accepted) {
241 engineList[toolList->currentRow()] = e;
242 toolList->currentItem()->setText(e.name());
243 toolsChanged = true;
244 }
245 }
246 }
247
refreshDefaultTool()248 void PrefsDialog::refreshDefaultTool()
249 {
250 QString val;
251 int toolIndex = -1, defaultIndex = -1;
252
253 if (defaultTool->count() > 0)
254 val = defaultTool->currentText();
255 defaultTool->clear();
256 foreach (Engine e, engineList) {
257 defaultTool->addItem(e.name());
258 if (e.name() == val)
259 toolIndex = defaultTool->count() - 1;
260 if (e.name() == DEFAULT_ENGINE_NAME)
261 defaultIndex = defaultTool->count() - 1;
262 }
263
264 if (toolIndex >= 0)
265 defaultTool->setCurrentIndex(toolIndex);
266 else if (defaultIndex >= 0)
267 defaultTool->setCurrentIndex(defaultIndex);
268 }
269
buttonClicked(QAbstractButton * whichButton)270 void PrefsDialog::buttonClicked(QAbstractButton *whichButton)
271 {
272 if (buttonBox->buttonRole(whichButton) == QDialogButtonBox::ResetRole)
273 restoreDefaults();
274 }
275
restoreDefaults()276 void PrefsDialog::restoreDefaults()
277 {
278 switch (tabWidget->currentIndex()) {
279 case 0:
280 // General
281 switch (kDefault_ToolBarIcons) {
282 case 1:
283 smallIcons->setChecked(true);
284 break;
285 case 2:
286 mediumIcons->setChecked(true);
287 break;
288 case 3:
289 largeIcons->setChecked(true);
290 break;
291 }
292 showText->setChecked(kDefault_ToolBarText);
293 switch (kDefault_LaunchOption) {
294 case 1:
295 default:
296 blankDocument->setChecked(true);
297 break;
298 case 2:
299 templateDialog->setChecked(true);
300 break;
301 case 3:
302 openDialog->setChecked(true);
303 break;
304 }
305 localePopup->setCurrentIndex(kDefault_Locale);
306 openPDFwithTeX->setChecked(kDefault_OpenPDFwithTeX);
307 break;
308
309 case 1:
310 // Editor
311 {
312 QFont font;
313 editorFont->setEditText(font.family());
314 fontSize->setValue(font.pointSize());
315 }
316 tabWidth->setValue(kDefault_TabWidth);
317 lineNumbers->setChecked(kDefault_LineNumbers);
318 wrapLines->setChecked(kDefault_WrapLines);
319 syntaxColoring->setCurrentIndex(kDefault_SyntaxColoring);
320 autoIndent->setCurrentIndex(kDefault_IndentMode);
321 smartQuotes->setCurrentIndex(kDefault_QuotesMode);
322 language->setCurrentIndex(kDefault_SpellcheckLanguage);
323 encoding->setCurrentIndex(encoding->findText("UTF-8"));
324 highlightCurrentLine->setChecked(kDefault_HighlightCurrentLine);
325 autocompleteEnabled->setChecked(kDefault_AutocompleteEnabled);
326 break;
327
328 case 2:
329 // Preview
330 switch (kDefault_PreviewScaleOption) {
331 default:
332 actualSize->setChecked(true);
333 break;
334 case 2:
335 fitWidth->setChecked(true);
336 break;
337 case 3:
338 fitWindow->setChecked(true);
339 break;
340 case 4:
341 fixedScale->setChecked(true);
342 break;
343 }
344 scale->setValue(kDefault_PreviewScale);
345 switch (kDefault_PDFPageMode) {
346 case QtPDF::PDFDocumentView::PageMode_SinglePage:
347 pdfPageMode->setCurrentIndex(0);
348 break;
349 case QtPDF::PDFDocumentView::PageMode_OneColumnContinuous:
350 default:
351 pdfPageMode->setCurrentIndex(1);
352 break;
353 case QtPDF::PDFDocumentView::PageMode_TwoColumnContinuous:
354 pdfPageMode->setCurrentIndex(2);
355 break;
356 }
357
358 resolution->setDpi(QApplication::desktop()->physicalDpiX());
359
360 switch (kDefault_MagnifierSize) {
361 case 1:
362 smallMag->setChecked(true);
363 break;
364 default:
365 mediumMag->setChecked(true);
366 break;
367 case 3:
368 largeMag->setChecked(true);
369 break;
370 }
371 circularMag->setChecked(kDefault_CircularMagnifier);
372 break;
373
374 case 3:
375 // Typesetting
376 TWApp::instance()->setDefaultEngineList();
377 TWApp::instance()->setDefaultPaths();
378 initPathAndToolLists();
379 autoHideOutput->setCurrentIndex(kDefault_HideConsole);
380 pathsChanged = true;
381 toolsChanged = true;
382 break;
383
384 case 4:
385 // Scripts
386 allowScriptFileReading->setChecked(kDefault_AllowScriptFileReading);
387 allowScriptFileWriting->setChecked(kDefault_AllowScriptFileWriting);
388 enableScriptingPlugins->setChecked(kDefault_EnableScriptingPlugins);
389 allowSystemCommands->setChecked(kDefault_AllowSystemCommands);
390 scriptDebugger->setChecked(kDefault_ScriptDebugger);
391 break;
392 }
393 }
394
initPathAndToolLists()395 void PrefsDialog::initPathAndToolLists()
396 {
397 binPathList->clear();
398 toolList->clear();
399 binPathList->addItems(TWApp::instance()->getPrefsBinaryPaths());
400 engineList = TWApp::instance()->getEngineList();
401 foreach (Engine e, engineList) {
402 toolList->addItem(e.name());
403 defaultTool->addItem(e.name());
404 if (e.name() == TWApp::instance()->getDefaultEngine().name())
405 defaultTool->setCurrentIndex(defaultTool->count() - 1);
406 }
407 if (binPathList->count() > 0)
408 binPathList->setCurrentItem(binPathList->item(0));
409 if (toolList->count() > 0)
410 toolList->setCurrentItem(toolList->item(0));
411 updatePathButtons();
412 updateToolButtons();
413 }
414
415 const int kSystemLocaleIndex = 0;
416 const int kEnglishLocaleIndex = 1;
417 const int kFirstTranslationIndex = 1;
418
419 typedef QPair<QString, QString> DictPair;
420
dictPairLessThan(const DictPair & d1,const DictPair & d2)421 static bool dictPairLessThan(const DictPair& d1, const DictPair& d2)
422 {
423 return d1.first.toLower() < d2.first.toLower();
424 }
425
doPrefsDialog(QWidget * parent)426 QDialog::DialogCode PrefsDialog::doPrefsDialog(QWidget *parent)
427 {
428 PrefsDialog dlg(NULL);
429
430 QStringList nameList;
431 foreach (QTextCodec *codec, *TWUtils::findCodecs())
432 nameList.append(codec->name());
433 dlg.encoding->addItems(nameList);
434
435 QStringList syntaxOptions = TeXHighlighter::syntaxOptions();
436 dlg.syntaxColoring->addItems(syntaxOptions);
437
438 QStringList indentModes = CompletingEdit::autoIndentModes();
439 dlg.autoIndent->addItems(indentModes);
440
441 QStringList quotesModes = CompletingEdit::smartQuotesModes();
442 dlg.smartQuotes->addItems(quotesModes);
443
444 QList< DictPair > dictList;
445 foreach (const QString& dictKey, TWUtils::getDictionaryList()->uniqueKeys()) {
446 QString dict, label;
447 QLocale loc;
448
449 foreach (dict, TWUtils::getDictionaryList()->values(dictKey)) {
450 loc = QLocale(dict);
451 if (loc.language() != QLocale::C) break;
452 }
453
454 if (loc.language() == QLocale::C)
455 label = dict;
456 else {
457 label = QLocale::languageToString(loc.language());
458 QLocale::Country country = loc.country();
459 if (country != QLocale::AnyCountry)
460 label += " - " + QLocale::countryToString(country);
461 label += " (" + dict + ")";
462 }
463
464 dictList << qMakePair(label, dict);
465 }
466 qSort(dictList.begin(), dictList.end(), dictPairLessThan);
467 foreach (const DictPair& dict, dictList)
468 dlg.language->addItem(dict.first, dict.second);
469
470 QSETTINGS_OBJECT(settings);
471 // initialize controls based on the current settings
472
473 // General
474 int oldIconSize = settings.value("toolBarIconSize", kDefault_ToolBarIcons).toInt();
475 switch (oldIconSize) {
476 case 1:
477 dlg.smallIcons->setChecked(true);
478 break;
479 case 3:
480 dlg.largeIcons->setChecked(true);
481 break;
482 default:
483 dlg.mediumIcons->setChecked(true);
484 break;
485 }
486 bool oldShowText = settings.value("toolBarShowText", kDefault_ToolBarText).toBool();
487 dlg.showText->setChecked(oldShowText);
488
489 switch (settings.value("launchOption", kDefault_LaunchOption).toInt()) {
490 default:
491 dlg.blankDocument->setChecked(true);
492 break;
493 case 2:
494 dlg.templateDialog->setChecked(true);
495 break;
496 case 3:
497 dlg.openDialog->setChecked(true);
498 break;
499 }
500 dlg.openPDFwithTeX->setChecked(settings.value("openPDFwithTeX", kDefault_OpenPDFwithTeX).toBool());
501
502 QString oldLocale = settings.value("locale").toString();
503 // System and English are predefined at index 0 and 1 (see constants above)
504 dlg.localePopup->addItem(tr("System default [%1]").arg(QLocale::languageToString(QLocale(QLocale::system().name()).language())));
505 int oldLocaleIndex = oldLocale.isEmpty() ? kSystemLocaleIndex : kEnglishLocaleIndex;
506 QStringList *trList = TWUtils::getTranslationList();
507 QStringList::ConstIterator iter;
508 for (iter = trList->constBegin(); iter != trList->constEnd(); ++iter) {
509 QLocale loc(*iter);
510 QLocale::Language language = loc.language();
511 QString locName;
512 if (language == QLocale::C)
513 locName = *iter;
514 else {
515 locName = QLocale::languageToString(language);
516 if (iter->contains('_')) {
517 QLocale::Country country = loc.country();
518 if (country != QLocale::AnyCountry)
519 locName += " (" + QLocale::countryToString(country) + ")";
520 }
521 }
522 dlg.localePopup->addItem(locName);
523 if (*iter == oldLocale)
524 oldLocaleIndex = dlg.localePopup->count() - 1;
525 }
526 dlg.localePopup->setCurrentIndex(oldLocaleIndex);
527
528 // Editor
529 dlg.syntaxColoring->setCurrentIndex(settings.contains("syntaxColoring")
530 ? 1 + syntaxOptions.indexOf(settings.value("syntaxColoring").toString())
531 : 1 + kDefault_SyntaxColoring);
532 dlg.autoIndent->setCurrentIndex(settings.contains("autoIndent")
533 ? 1 + indentModes.indexOf(settings.value("autoIndent").toString())
534 : 1 + kDefault_IndentMode);
535 dlg.smartQuotes->setCurrentIndex(settings.contains("smartQuotes")
536 ? 1 + quotesModes.indexOf(settings.value("smartQuotes").toString())
537 : 1 + kDefault_QuotesMode);
538 dlg.lineNumbers->setChecked(settings.value("lineNumbers", kDefault_LineNumbers).toBool());
539 dlg.wrapLines->setChecked(settings.value("wrapLines", kDefault_WrapLines).toBool());
540 dlg.tabWidth->setValue(settings.value("tabWidth", kDefault_TabWidth).toInt());
541 QFontDatabase fdb;
542 dlg.editorFont->addItems(fdb.families());
543 QString fontString = settings.value("font").toString();
544 QFont font;
545 if (fontString != "")
546 font.fromString(fontString);
547 dlg.editorFont->setCurrentIndex(fdb.families().indexOf(font.family()));
548 dlg.fontSize->setValue(font.pointSize());
549 dlg.encoding->setCurrentIndex(nameList.indexOf(TWApp::instance()->getDefaultCodec()->name()));
550 dlg.highlightCurrentLine->setChecked(settings.value("highlightCurrentLine", kDefault_HighlightCurrentLine).toBool());
551 dlg.autocompleteEnabled->setChecked(settings.value("autocompleteEnabled", kDefault_AutocompleteEnabled).toBool());
552
553 QString defDict = settings.value("language", "None").toString();
554 int i = dlg.language->findData(defDict);
555 if (i >= 0)
556 dlg.language->setCurrentIndex(i);
557
558 // Preview
559 switch (settings.value("scaleOption", kDefault_PreviewScaleOption).toInt()) {
560 default:
561 dlg.actualSize->setChecked(true);
562 break;
563 case 2:
564 dlg.fitWidth->setChecked(true);
565 break;
566 case 3:
567 dlg.fitWindow->setChecked(true);
568 break;
569 case 4:
570 dlg.fixedScale->setChecked(true);
571 break;
572 }
573 dlg.scale->setValue(settings.value("previewScale", kDefault_PreviewScale).toInt());
574 switch (settings.value("pdfPageMode", kDefault_PDFPageMode).toInt()) {
575 case QtPDF::PDFDocumentView::PageMode_SinglePage:
576 dlg.pdfPageMode->setCurrentIndex(0);
577 break;
578 case QtPDF::PDFDocumentView::PageMode_OneColumnContinuous:
579 default:
580 dlg.pdfPageMode->setCurrentIndex(1);
581 break;
582 case QtPDF::PDFDocumentView::PageMode_TwoColumnContinuous:
583 dlg.pdfPageMode->setCurrentIndex(2);
584 break;
585 }
586
587 double oldResolution = settings.value("previewResolution", QApplication::desktop()->physicalDpiX()).toDouble();
588 dlg.resolution->setDpi(oldResolution);
589
590 int oldMagSize = settings.value("magnifierSize", kDefault_MagnifierSize).toInt();
591 switch (oldMagSize) {
592 case 1:
593 dlg.smallMag->setChecked(true);
594 break;
595 default:
596 dlg.mediumMag->setChecked(true);
597 break;
598 case 3:
599 dlg.largeMag->setChecked(true);
600 break;
601 }
602 bool oldCircular = settings.value("circularMagnifier", kDefault_CircularMagnifier).toBool();
603 dlg.circularMag->setChecked(oldCircular);
604
605 // Typesetting
606 dlg.initPathAndToolLists();
607 QVariant hideConsoleSetting = settings.value("autoHideConsole", kDefault_HideConsole);
608 // Backwards compatibility to Tw 0.4.0 and before
609 if (hideConsoleSetting.toString() == "true" || hideConsoleSetting.toString() == "false")
610 hideConsoleSetting = (hideConsoleSetting.toBool() ? kDefault_HideConsole : 0);
611 dlg.autoHideOutput->setCurrentIndex(hideConsoleSetting.toInt());
612
613 // Scripts
614 dlg.allowScriptFileReading->setChecked(settings.value("allowScriptFileReading", kDefault_AllowScriptFileReading).toBool());
615 dlg.allowScriptFileWriting->setChecked(settings.value("allowScriptFileWriting", kDefault_AllowScriptFileWriting).toBool());
616 dlg.allowSystemCommands->setChecked(settings.value("allowSystemCommands", kDefault_AllowSystemCommands).toBool());
617 dlg.enableScriptingPlugins->setChecked(settings.value("enableScriptingPlugins", kDefault_EnableScriptingPlugins).toBool());
618 // there is always at least JSScriptInterface
619 if (TWApp::instance()->getScriptManager()->languages().size() <= 1)
620 dlg.enableScriptingPlugins->setEnabled(false);
621 dlg.scriptDebugger->setChecked(settings.value("scriptDebugger", kDefault_ScriptDebugger).toBool());
622 #if QT_VERSION < 0x040500
623 dlg.scriptDebugger->setEnabled(false);
624 #endif
625
626 // Decide which tab to select initially
627 if (sCurrentTab == -1) {
628 if (parent && parent->inherits("TeXDocument"))
629 sCurrentTab = 1;
630 else if (parent && parent->inherits("PDFDocument"))
631 sCurrentTab = 2;
632 else
633 sCurrentTab = 0;
634 }
635 if (sCurrentTab != dlg.tabWidget->currentIndex())
636 dlg.tabWidget->setCurrentIndex(sCurrentTab);
637
638 dlg.show();
639
640 DialogCode result = (DialogCode)dlg.exec();
641
642 if (result == Accepted) {
643 sCurrentTab = dlg.tabWidget->currentIndex();
644
645 // General
646 int iconSize = 2;
647 if (dlg.smallIcons->isChecked())
648 iconSize = 1;
649 else if (dlg.largeIcons->isChecked())
650 iconSize = 3;
651 bool showText = dlg.showText->isChecked();
652 if (iconSize != oldIconSize || showText != oldShowText) {
653 settings.setValue("toolBarIconSize", iconSize);
654 settings.setValue("toolBarShowText", showText);
655 foreach (QWidget *widget, qApp->topLevelWidgets()) {
656 QMainWindow *theWindow = qobject_cast<QMainWindow*>(widget);
657 if (theWindow != NULL)
658 TWUtils::applyToolbarOptions(theWindow, iconSize, showText);
659 }
660 }
661
662 int launchOption = 1;
663 if (dlg.templateDialog->isChecked())
664 launchOption = 2;
665 else if (dlg.openDialog->isChecked())
666 launchOption = 3;
667 settings.setValue("launchOption", launchOption);
668
669 settings.setValue("openPDFwithTeX", dlg.openPDFwithTeX->isChecked());
670
671 if (dlg.localePopup->currentIndex() != oldLocaleIndex) {
672 switch (dlg.localePopup->currentIndex()) {
673 case kSystemLocaleIndex: // system locale
674 {
675 QString locale = QLocale::system().name();
676 TWApp::instance()->applyTranslation(locale);
677 settings.remove("locale");
678 }
679 break;
680 default:
681 {
682 QString locale = trList->at(dlg.localePopup->currentIndex() - kFirstTranslationIndex);
683 TWApp::instance()->applyTranslation(locale);
684 settings.setValue("locale", locale);
685 }
686 break;
687 }
688 }
689
690 // Editor
691 settings.setValue("syntaxColoring", dlg.syntaxColoring->currentText());
692 settings.setValue("autoIndent", dlg.autoIndent->currentText());
693 settings.setValue("smartQuotes", dlg.smartQuotes->currentText());
694 settings.setValue("lineNumbers", dlg.lineNumbers->isChecked());
695 settings.setValue("wrapLines", dlg.wrapLines->isChecked());
696 settings.setValue("tabWidth", dlg.tabWidth->value());
697 font = QFont(dlg.editorFont->currentText());
698 font.setPointSize(dlg.fontSize->value());
699 settings.setValue("font", font.toString());
700 TWApp::instance()->setDefaultCodec(QTextCodec::codecForName(dlg.encoding->currentText().toLatin1()));
701 if (dlg.language->currentIndex() >= 0) {
702 QVariant data = dlg.language->itemData(dlg.language->currentIndex());
703 if (data.isValid())
704 settings.setValue("language", data);
705 else
706 settings.setValue("language", "None");
707 }
708 else
709 settings.setValue("language", "None");
710 bool highlightLine = dlg.highlightCurrentLine->isChecked();
711 settings.setValue("highlightCurrentLine", highlightLine);
712 CompletingEdit::setHighlightCurrentLine(highlightLine);
713
714 bool autocompleteEnabled = dlg.autocompleteEnabled->isChecked();
715 settings.setValue("autocompleteEnabled", autocompleteEnabled);
716 CompletingEdit::setAutocompleteEnabled(autocompleteEnabled);
717
718 // Since the tab width can't be set by any other means, forcibly update
719 // all windows now
720 foreach (QWidget* widget, TWApp::instance()->allWidgets()) {
721 QTextEdit* editor = qobject_cast<QTextEdit*>(widget);
722 if (editor)
723 editor->setTabStopWidth(dlg.tabWidth->value());
724 }
725
726 // Preview
727 int scaleOption = 1;
728 if (dlg.fitWidth->isChecked())
729 scaleOption = 2;
730 else if (dlg.fitWindow->isChecked())
731 scaleOption = 3;
732 else if (dlg.fixedScale->isChecked())
733 scaleOption = 4;
734 int scale = dlg.scale->value();
735 settings.setValue("scaleOption", scaleOption);
736 settings.setValue("previewScale", scale);
737 switch (dlg.pdfPageMode->currentIndex()) {
738 case 0:
739 settings.setValue("pdfPageMode", QtPDF::PDFDocumentView::PageMode_SinglePage);
740 break;
741 case 1:
742 settings.setValue("pdfPageMode", QtPDF::PDFDocumentView::PageMode_OneColumnContinuous);
743 break;
744 case 2:
745 settings.setValue("pdfPageMode", QtPDF::PDFDocumentView::PageMode_TwoColumnContinuous);
746 break;
747 }
748
749 double resolution = dlg.resolution->dpi();
750 if (resolution != oldResolution) {
751 settings.setValue("previewResolution", resolution);
752 foreach (QWidget *widget, qApp->topLevelWidgets()) {
753 PDFDocument *thePdfDoc = qobject_cast<PDFDocument*>(widget);
754 if (thePdfDoc != NULL)
755 thePdfDoc->setResolution(resolution);
756 }
757 }
758
759 int magSize = 2;
760 if (dlg.smallMag->isChecked())
761 magSize = 1;
762 else if (dlg.largeMag->isChecked())
763 magSize = 3;
764 settings.setValue("magnifierSize", magSize);
765 bool circular = dlg.circularMag->isChecked();
766 settings.setValue("circularMagnifier", circular);
767 if (oldMagSize != magSize || oldCircular != circular) {
768 foreach (QWidget *widget, qApp->topLevelWidgets()) {
769 PDFDocument *thePdfDoc = qobject_cast<PDFDocument*>(widget);
770 if (thePdfDoc != NULL)
771 thePdfDoc->resetMagnifier();
772 }
773 }
774
775 // Typesetting
776 if (dlg.pathsChanged) {
777 QStringList paths;
778 for (int i = 0; i < dlg.binPathList->count(); ++i)
779 paths << dlg.binPathList->item(i)->text();
780 TWApp::instance()->setBinaryPaths(paths);
781 }
782 if (dlg.toolsChanged)
783 TWApp::instance()->setEngineList(dlg.engineList);
784 TWApp::instance()->setDefaultEngine(dlg.defaultTool->currentText());
785 settings.setValue("autoHideConsole", dlg.autoHideOutput->currentIndex());
786
787 // Scripts
788 settings.setValue("allowScriptFileReading", dlg.allowScriptFileReading->isChecked());
789 settings.setValue("allowScriptFileWriting", dlg.allowScriptFileWriting->isChecked());
790 settings.setValue("allowSystemCommands", dlg.allowSystemCommands->isChecked());
791 settings.setValue("enableScriptingPlugins", dlg.enableScriptingPlugins->isChecked());
792 settings.setValue("scriptDebugger", dlg.scriptDebugger->isChecked());
793 // with changed settings, the availability of scripts may have changed
794 // (e.g., because of enabling/disabling the use of scripting plugins)
795 TWApp::instance()->updateScriptsList();
796 }
797
798 return result;
799 }
800
801 int PrefsDialog::sCurrentTab = -1;
802
ToolConfig(QWidget * parent)803 ToolConfig::ToolConfig(QWidget *parent)
804 : QDialog(parent)
805 {
806 init();
807 }
808
init()809 void ToolConfig::init()
810 {
811 setupUi(this);
812
813 connect(arguments, SIGNAL(itemSelectionChanged()), this, SLOT(updateArgButtons()));
814 connect(argUp, SIGNAL(clicked()), this, SLOT(moveArgUp()));
815 connect(argDown, SIGNAL(clicked()), this, SLOT(moveArgDown()));
816 connect(argAdd, SIGNAL(clicked()), this, SLOT(addArg()));
817 connect(argRemove, SIGNAL(clicked()), this, SLOT(removeArg()));
818 connect(btnBrowseForProgram, SIGNAL(clicked()), this, SLOT(browseForProgram()));
819 }
820
browseForProgram()821 void ToolConfig::browseForProgram()
822 {
823 QFileInfo info(program->text());
824 QString str = QFileDialog::getOpenFileName(this, tr("Select program file"),
825 info.exists() ? info.canonicalFilePath() : QString());
826 if (!str.isNull()) {
827 info.setFile(str);
828 if (!info.isExecutable()) {
829 QMessageBox::warning(this, tr("Invalid program"),
830 tr("The file '%1' is not executable!").arg(info.fileName()));
831 return;
832 }
833 program->setText(info.canonicalFilePath());
834 }
835 }
836
updateArgButtons()837 void ToolConfig::updateArgButtons()
838 {
839 int selRow = -1;
840 if (arguments->selectedItems().count() > 0)
841 selRow = arguments->currentRow();
842 argRemove->setEnabled(selRow != -1);
843 argUp->setEnabled(selRow > 0);
844 argDown->setEnabled(selRow != -1 && selRow < arguments->count() - 1);
845 }
846
moveArgUp()847 void ToolConfig::moveArgUp()
848 {
849 int selRow = -1;
850 if (arguments->selectedItems().count() > 0)
851 selRow = arguments->currentRow();
852 if (selRow > 0) {
853 QListWidgetItem *item = arguments->takeItem(selRow);
854 arguments->insertItem(selRow - 1, item);
855 arguments->setCurrentItem(arguments->item(selRow - 1));
856 }
857 }
858
moveArgDown()859 void ToolConfig::moveArgDown()
860 {
861 int selRow = -1;
862 if (arguments->selectedItems().count() > 0)
863 selRow = arguments->currentRow();
864 if (selRow != -1 && selRow < arguments->count() - 1) {
865 QListWidgetItem *item = arguments->takeItem(selRow);
866 arguments->insertItem(selRow + 1, item);
867 arguments->setCurrentItem(arguments->item(selRow + 1));
868 }
869 }
870
addArg()871 void ToolConfig::addArg()
872 {
873 arguments->addItem(tr("NewArgument"));
874 QListWidgetItem* item = arguments->item(arguments->count() - 1);
875 item->setFlags(item->flags() | Qt::ItemIsEditable);
876 arguments->setCurrentItem(item);
877 arguments->editItem(item);
878 }
879
removeArg()880 void ToolConfig::removeArg()
881 {
882 if (arguments->currentRow() > -1)
883 if (arguments->currentItem()->isSelected())
884 arguments->takeItem(arguments->currentRow());
885 }
886
doToolConfig(QWidget * parent,Engine & engine)887 QDialog::DialogCode ToolConfig::doToolConfig(QWidget *parent, Engine &engine)
888 {
889 ToolConfig dlg(parent);
890
891 dlg.toolName->setText(engine.name());
892 dlg.program->setText(engine.program());
893 dlg.arguments->addItems(engine.arguments());
894 for (int i = 0; i < dlg.arguments->count(); ++i) {
895 QListWidgetItem *item = dlg.arguments->item(i);
896 item->setFlags(item->flags() | Qt::ItemIsEditable);
897 }
898 dlg.viewPdf->setChecked(engine.showPdf());
899
900 dlg.show();
901
902 DialogCode result = (DialogCode)dlg.exec();
903 if (result == Accepted) {
904 dlg.arguments->setCurrentItem(NULL); // ensure editing is terminated
905 engine.setName(dlg.toolName->text());
906 engine.setProgram(dlg.program->text());
907 QStringList args;
908 for (int i = 0; i < dlg.arguments->count(); ++i)
909 args << dlg.arguments->item(i)->text();
910 engine.setArguments(args);
911 engine.setShowPdf(dlg.viewPdf->isChecked());
912 }
913
914 return result;
915 }
916