00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stdio.h>
00025
00026 #include <QtCore>
00027 #include <QtGui>
00028
00029 #include <klfbackend.h>
00030
00031 #include <ui_klfprogerr.h>
00032 #include <ui_klfmainwin.h>
00033
00034 #include <klflibview.h>
00035 #include <klfguiutil.h>
00036
00037 #include "klflatexedit.h"
00038 #include "klflibbrowser.h"
00039 #include "klflatexsymbols.h"
00040 #include "klfsettings.h"
00041 #include "klfmain.h"
00042 #include "klfstylemanager.h"
00043 #include "klfmime.h"
00044
00045 #include "klfmainwin.h"
00046 #include "klfmainwin_p.h"
00047
00048
00049 #define DEBUG_GEOM_ARGS(g) (g).topLeft().x(), (g).topLeft().y(), (g).size().width(), (g).size().height()
00050
00051 static QRect klf_get_window_geometry(QWidget *w)
00052 {
00053 #if defined(Q_WS_X11)
00054 QRect g = w->frameGeometry();
00055 #else
00056 QRect g = w->geometry();
00057 #endif
00058 return g;
00059 }
00060
00061 static void klf_set_window_geometry(QWidget *w, QRect g)
00062 {
00063 if ( ! g.isValid() )
00064 return;
00065
00066 w->setGeometry(g);
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 KLFProgErr::KLFProgErr(QWidget *parent, QString errtext) : QDialog(parent)
00078 {
00079 u = new Ui::KLFProgErr;
00080 u->setupUi(this);
00081 setObjectName("KLFProgErr");
00082
00083 u->txtError->setText(errtext);
00084 }
00085
00086 KLFProgErr::~KLFProgErr()
00087 {
00088 delete u;
00089 }
00090
00091 void KLFProgErr::showError(QWidget *parent, QString errtext)
00092 {
00093 KLFProgErr dlg(parent, errtext);
00094 dlg.exec();
00095 }
00096
00097
00098
00099
00100
00101 KLFPreviewBuilderThread::KLFPreviewBuilderThread(QObject *parent, KLFBackend::klfInput input,
00102 KLFBackend::klfSettings settings, int labelwidth,
00103 int labelheight)
00104 : QThread(parent), _input(input), _settings(settings), _lwidth(labelwidth), _lheight(labelheight),
00105 _hasnewinfo(false), _abort(false)
00106 {
00107 }
00108 KLFPreviewBuilderThread::~KLFPreviewBuilderThread()
00109 {
00110 _mutex.lock();
00111 _abort = true;
00112 _condnewinfoavail.wakeOne();
00113 _mutex.unlock();
00114 wait();
00115 }
00116
00117 void KLFPreviewBuilderThread::run()
00118 {
00119 KLFBackend::klfInput input;
00120 KLFBackend::klfSettings settings;
00121 KLFBackend::klfOutput output;
00122 QImage img;
00123 int lwid, lhgt;
00124
00125 for (;;) {
00126 _mutex.lock();
00127 bool abrt = _abort;
00128 _mutex.unlock();
00129 if (abrt)
00130 return;
00131
00132
00133 _mutex.lock();
00134 input = _input;
00135 settings = _settings;
00136 settings.epstopdfexec = "";
00137 lwid = _lwidth;
00138 lhgt = _lheight;
00139 _hasnewinfo = false;
00140 _mutex.unlock();
00141
00142
00143
00144
00145
00146 if ( input.latex.trimmed().isEmpty() ) {
00147 emit previewAvailable(QImage(), 0);
00148 } else {
00149
00150 output = KLFBackend::getLatexFormula(input, settings);
00151 img = output.result;
00152 if (output.status == 0) {
00153 if (img.width() > lwid || img.height() > lhgt)
00154 img = img.scaled(QSize(lwid, lhgt), Qt::KeepAspectRatio, Qt::SmoothTransformation);
00155 } else {
00156 img = QImage();
00157 }
00158 }
00159
00160 _mutex.lock();
00161 bool abort = _abort;
00162 bool hasnewinfo = _hasnewinfo;
00163 _mutex.unlock();
00164
00165 if (abort)
00166 return;
00167 if (hasnewinfo)
00168 continue;
00169
00170 emit previewAvailable(img, output.status != 0);
00171
00172 _mutex.lock();
00173 _condnewinfoavail.wait(&_mutex);
00174 _mutex.unlock();
00175 }
00176 }
00177 bool KLFPreviewBuilderThread::inputChanged(const KLFBackend::klfInput& input)
00178 {
00179 QMutexLocker mutexlocker(&_mutex);
00180 if (_input == input) {
00181 return false;
00182 }
00183 _input = input;
00184 _hasnewinfo = true;
00185 _condnewinfoavail.wakeOne();
00186 return true;
00187 }
00188 void KLFPreviewBuilderThread::settingsChanged(const KLFBackend::klfSettings& settings,
00189 int lwidth, int lheight)
00190 {
00191 _mutex.lock();
00192 _settings = settings;
00193 if (lwidth > 0) _lwidth = lwidth;
00194 if (lheight > 0) _lheight = lheight;
00195 _hasnewinfo = true;
00196 _condnewinfoavail.wakeOne();
00197 _mutex.unlock();
00198 }
00199
00200
00201
00202
00203
00204 KLFMainWin::KLFMainWin()
00205 : QWidget(0, Qt::Window)
00206 {
00207 u = new Ui::KLFMainWin;
00208 u->setupUi(this);
00209 setObjectName("KLFMainWin");
00210 setAttribute(Qt::WA_StyledBackground);
00211
00212 #ifdef Q_WS_MAC
00213
00214 QApplication::instance()->installEventFilter(this);
00215 #endif
00216
00217 mPopup = NULL;
00218
00219 loadSettings();
00220
00221 _firstshow = true;
00222
00223 _output.status = 0;
00224 _output.errorstr = QString();
00225
00226
00227
00228 loadStyles();
00229
00230 mLatexSymbols = new KLFLatexSymbols(this, _settings);
00231
00232 u->txtLatex->setFont(klfconfig.UI.latexEditFont);
00233 u->txtPreamble->setFont(klfconfig.UI.preambleEditFont);
00234
00235 u->frmOutput->setEnabled(false);
00236
00237 QMenu *DPIPresets = new QMenu(this);
00238
00239 connect(u->aDPI1200, SIGNAL(triggered()), this, SLOT(slotPresetDPISender()));
00240 u->aDPI1200->setData(1200);
00241 DPIPresets->addAction(u->aDPI1200);
00242
00243 connect(u->aDPI600, SIGNAL(triggered()), this, SLOT(slotPresetDPISender()));
00244 u->aDPI600->setData(600);
00245 DPIPresets->addAction(u->aDPI600);
00246
00247 connect(u->aDPI300, SIGNAL(triggered()), this, SLOT(slotPresetDPISender()));
00248 u->aDPI300->setData(300);
00249 DPIPresets->addAction(u->aDPI300);
00250
00251 connect(u->aDPI150, SIGNAL(triggered()), this, SLOT(slotPresetDPISender()));
00252 u->aDPI150->setData(150);
00253 DPIPresets->addAction(u->aDPI150);
00254
00255 u->btnDPIPresets->setMenu(DPIPresets);
00256
00257
00258 connect(u->txtLatex->syntaxHighlighter(), SIGNAL(newSymbolTyped(const QString&)),
00259 this, SLOT(slotNewSymbolTyped(const QString&)));
00260
00261 u->lblOutput->setLabelFixedSize(klfconfig.UI.labelOutputFixedSize);
00262 u->lblOutput->setEnableToolTipPreview(klfconfig.UI.enableToolTipPreview);
00263 u->lblOutput->setGlowEffect(klfconfig.UI.glowEffect);
00264 u->lblOutput->setGlowEffectColor(klfconfig.UI.glowEffectColor);
00265 u->lblOutput->setGlowEffectRadius(klfconfig.UI.glowEffectRadius);
00266
00267 connect(u->lblOutput, SIGNAL(labelDrag()), this, SLOT(slotDrag()));
00268
00269 connect(u->btnShowBigPreview, SIGNAL(clicked()),
00270 this, SLOT(slotShowBigPreview()));
00271
00272 int h;
00273 h = u->btnDrag->sizeHint().height(); u->btnDrag->setFixedHeight(h - 5);
00274 h = u->btnCopy->sizeHint().height(); u->btnCopy->setFixedHeight(h - 5);
00275 h = u->btnSave->sizeHint().height(); u->btnSave->setFixedHeight(h - 5);
00276
00277 QGridLayout *lyt = new QGridLayout(u->lblOutput);
00278 lyt->setSpacing(0);
00279 lyt->setMargin(0);
00280 mExportMsgLabel = new QLabel(u->lblOutput);
00281
00282 mExportMsgLabel->setObjectName("mExportMsgLabel");
00283 QFont smallfont = mExportMsgLabel->font();
00284 smallfont.setPointSize(QFontInfo(smallfont).pointSize() - 1);
00285 mExportMsgLabel->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
00286 mExportMsgLabel->setFont(smallfont);
00287 mExportMsgLabel->setMargin(1);
00288 mExportMsgLabel->setAlignment(Qt::AlignRight|Qt::AlignBottom);
00289 QPalette pal = mExportMsgLabel->palette();
00290 pal.setColor(QPalette::Window, QColor(180,180,180,200));
00291 pal.setColor(QPalette::WindowText, QColor(0,0,0,255));
00292 mExportMsgLabel->setPalette(pal);
00293 mExportMsgLabel->setAutoFillBackground(true);
00294 mExportMsgLabel->setProperty("defaultPalette", QVariant::fromValue<QPalette>(pal));
00295
00296 lyt->addItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding), 0, 1, 2, 1);
00297
00298 lyt->addWidget(mExportMsgLabel, 1, 0, 1, 2);
00299
00300 pExportMsgLabelTimerId = -1;
00301
00302 mExportMsgLabel->hide();
00303
00304 refreshWindowSizes();
00305
00306 u->frmDetails->hide();
00307
00308 u->txtLatex->installEventFilter(this);
00309 u->txtLatex->setMainWinDataOpener(this);
00310
00311 setFixedSize(_shrinkedsize);
00312
00313 u->btnEvaluate->installEventFilter(this);
00314
00315
00316 u->btnDrag->installEventFilter(this);
00317 u->btnCopy->installEventFilter(this);
00318
00319
00320 new QShortcut(QKeySequence(tr("Ctrl+Q")), this, SLOT(quit()), SLOT(quit()),
00321 Qt::ApplicationShortcut);
00322
00323
00324
00325 new QShortcut(QKeySequence(Qt::Key_F4), this, SLOT(slotActivateEditor()),
00326 SLOT(slotActivateEditor()), Qt::ApplicationShortcut);
00327
00328 new QShortcut(QKeySequence(Qt::Key_F4 | Qt::ShiftModifier), this, SLOT(slotActivateEditorSelectAll()),
00329 SLOT(slotActivateEditorSelectAll()), Qt::ApplicationShortcut);
00330
00331 new QShortcut(QKeySequence(Qt::Key_F2), this, SLOT(slotShowBigPreview()),
00332 SLOT(slotShowBigPreview()), Qt::WindowShortcut);
00333
00334
00335 mStyleManager = new KLFStyleManager(&_styles, this);
00336 connect(mStyleManager, SIGNAL(refreshStyles()), this, SLOT(refreshStylePopupMenus()));
00337 connect(this, SIGNAL(stylesChanged()), mStyleManager, SLOT(slotRefresh()));
00338
00339 connect(this, SIGNAL(stylesChanged()), this, SLOT(saveStyles()));
00340 connect(mStyleManager, SIGNAL(refreshStyles()), this, SLOT(saveStyles()));
00341
00342 loadDefaultStyle();
00343
00344
00345
00346 QTimer *synthighlighttimer = new QTimer(this);
00347 connect(synthighlighttimer, SIGNAL(timeout()), u->txtLatex->syntaxHighlighter(), SLOT(refreshAll()));
00348 connect(synthighlighttimer, SIGNAL(timeout()), u->txtPreamble->syntaxHighlighter(), SLOT(refreshAll()));
00349 synthighlighttimer->start(250);
00350
00351
00352 u->cbxMarginsUnit->setCurrentUnitAbbrev("pt");
00353
00354
00355 u->cbxMathMode->addItems(klfconfig.UI.customMathModes);
00356
00357
00358 mLibBrowser = new KLFLibBrowser(this);
00359
00360 refreshShowCorrectClearButton();
00361
00362
00363
00364
00365 connect(u->aClearLatex, SIGNAL(triggered()), this, SLOT(slotClearLatex()));
00366 connect(u->aClearAll, SIGNAL(triggered()), this, SLOT(slotClearAll()));
00367 connect(u->btnEvaluate, SIGNAL(clicked()), this, SLOT(slotEvaluate()));
00368 connect(u->btnSymbols, SIGNAL(toggled(bool)), this, SLOT(slotSymbols(bool)));
00369 connect(u->btnLibrary, SIGNAL(toggled(bool)), this, SLOT(slotLibrary(bool)));
00370 connect(u->btnExpand, SIGNAL(clicked()), this, SLOT(slotExpandOrShrink()));
00371 connect(u->btnCopy, SIGNAL(clicked()), this, SLOT(slotCopy()));
00372 connect(u->btnDrag, SIGNAL(released()), this, SLOT(slotDrag()));
00373 connect(u->btnSave, SIGNAL(clicked()), this, SLOT(slotSave()));
00374 connect(u->btnSettings, SIGNAL(clicked()), this, SLOT(slotSettings()));
00375 connect(u->btnSaveStyle, SIGNAL(clicked()), this, SLOT(slotSaveStyle()));
00376
00377 connect(u->btnQuit, SIGNAL(clicked()), this, SLOT(quit()));
00378
00379 connect(mLibBrowser, SIGNAL(requestRestore(const KLFLibEntry&, uint)),
00380 this, SLOT(restoreFromLibrary(const KLFLibEntry&, uint)));
00381 connect(mLibBrowser, SIGNAL(requestRestoreStyle(const KLFStyle&)),
00382 this, SLOT(slotLoadStyle(const KLFStyle&)));
00383 connect(mLatexSymbols, SIGNAL(insertSymbol(const KLFLatexSymbol&)),
00384 this, SLOT(insertSymbol(const KLFLatexSymbol&)));
00385
00386
00387
00388 connect(u->btnHelp, SIGNAL(clicked()), this, SLOT(showAbout()));
00389
00390
00391
00392 mPreviewBuilderThread = new KLFPreviewBuilderThread(this, collectInput(false), _settings,
00393 klfconfig.UI.labelOutputFixedSize.width(),
00394 klfconfig.UI.labelOutputFixedSize.height());
00395
00396 connect(u->txtLatex, SIGNAL(textChanged()), this,
00397 SLOT(updatePreviewBuilderThreadInput()), Qt::QueuedConnection);
00398 connect(u->txtLatex, SIGNAL(insertContextMenuActions(const QPoint&, QList<QAction*> *)),
00399 this, SLOT(slotEditorContextMenuInsertActions(const QPoint&, QList<QAction*> *)));
00400 connect(u->cbxMathMode, SIGNAL(editTextChanged(const QString&)),
00401 this, SLOT(updatePreviewBuilderThreadInput()),
00402 Qt::QueuedConnection);
00403 connect(u->chkMathMode, SIGNAL(stateChanged(int)), this, SLOT(updatePreviewBuilderThreadInput()),
00404 Qt::QueuedConnection);
00405 connect(u->colFg, SIGNAL(colorChanged(const QColor&)), this, SLOT(updatePreviewBuilderThreadInput()),
00406 Qt::QueuedConnection);
00407 connect(u->chkBgTransparent, SIGNAL(stateChanged(int)), this, SLOT(updatePreviewBuilderThreadInput()),
00408 Qt::QueuedConnection);
00409 connect(u->colBg, SIGNAL(colorChanged(const QColor&)), this, SLOT(updatePreviewBuilderThreadInput()),
00410 Qt::QueuedConnection);
00411
00412 connect(mPreviewBuilderThread, SIGNAL(previewAvailable(const QImage&, bool)),
00413 this, SLOT(showRealTimePreview(const QImage&, bool)), Qt::QueuedConnection);
00414
00415 if (klfconfig.UI.enableRealTimePreview) {
00416 mPreviewBuilderThread->start();
00417 }
00418
00419
00420
00421 mSettingsDialog = new KLFSettings(this);
00422
00423
00424
00425
00426 mLibBrowser->installEventFilter(this);
00427 mLatexSymbols->installEventFilter(this);
00428 mStyleManager->installEventFilter(this);
00429 mSettingsDialog->installEventFilter(this);
00430
00431
00432
00433
00434 _evaloutput_uptodate = true;
00435
00436 retranslateUi(false);
00437
00438 connect(this, SIGNAL(applicationLocaleChanged(const QString&)), this, SLOT(retranslateUi()));
00439 connect(this, SIGNAL(applicationLocaleChanged(const QString&)), mLibBrowser, SLOT(retranslateUi()));
00440 connect(this, SIGNAL(applicationLocaleChanged(const QString&)), mSettingsDialog, SLOT(retranslateUi()));
00441 connect(this, SIGNAL(applicationLocaleChanged(const QString&)), mStyleManager, SLOT(retranslateUi()));
00442
00443
00444 mAboutDialog = new KLFAboutDialog(this);
00445 mWhatsNewDialog = new KLFWhatsNewDialog(this);
00446
00447 connect(mAboutDialog, SIGNAL(linkActivated(const QUrl&)), this, SLOT(helpLinkAction(const QUrl&)));
00448 connect(mWhatsNewDialog, SIGNAL(linkActivated(const QUrl&)), this, SLOT(helpLinkAction(const QUrl&)));
00449
00450 mHelpLinkActions << HelpLinkAction("/whats_new", this, "showWhatsNew", false);
00451 mHelpLinkActions << HelpLinkAction("/about", this, "showAbout", false);
00452 mHelpLinkActions << HelpLinkAction("/popup_close", this, "slotPopupClose", false);
00453 mHelpLinkActions << HelpLinkAction("/popup", this, "slotPopupAction", true);
00454 mHelpLinkActions << HelpLinkAction("/settings", this, "showSettingsHelpLinkAction", true);
00455
00456 if ( klfconfig.Core.thisVersionMajMinFirstRun && ! klfconfig.checkExePaths() ) {
00457 addWhatsNewText("<p><b><span style=\"color: #a00000\">"+
00458 tr("Your executable paths (latex, dvips, gs) seem not to be detected properly. "
00459 "Please adjust the settings in the <a href=\"klfaction:/settings?control="
00460 "ExecutablePaths\">settings dialog</a>.",
00461 "[[additional text in what's-new-dialog in case of bad detected settings. this "
00462 "is HTML formatted text.]]")
00463 +"</span></b></p>");
00464 }
00465
00466 klfDbg("Font is "<<font()<<", family is "<<fontInfo().family()) ;
00467 if (QFontInfo(klfconfig.UI.applicationFont).family().contains("CMU")) {
00468 addWhatsNewText("<p>"+tr("LaTeX' Computer Modern Sans Serif font is used as the <b>default application font</b>."
00469 " Don't like it? <a href=\"%1\">Choose your preferred application font</a>.")
00470 .arg("klfaction:/settings?control=AppFonts") + "</p>");
00471 }
00472
00473
00474
00475 _loadedlibrary = true;
00476 loadLibrary();
00477
00478 registerDataOpener(new KLFBasicDataOpener(this));
00479 registerDataOpener(new KLFAddOnDataOpener(this));
00480 }
00481
00482 void KLFMainWin::retranslateUi(bool alsoBaseUi)
00483 {
00484 if (alsoBaseUi)
00485 u->retranslateUi(this);
00486
00487
00488 u->lblPromptMain->setToolTip(tr("KLatexFormula %1").arg(QString::fromUtf8(KLF_VERSION_STRING)));
00489
00490 refreshStylePopupMenus();
00491 }
00492
00493
00494 KLFMainWin::~KLFMainWin()
00495 {
00496 klfDbg( "()" ) ;
00497
00498 saveLibraryState();
00499 saveSettings();
00500 saveStyles();
00501
00502 if (mStyleMenu)
00503 delete mStyleMenu;
00504 if (mLatexSymbols)
00505 delete mLatexSymbols;
00506 if (mLibBrowser)
00507 delete mLibBrowser;
00508 if (mSettingsDialog)
00509 delete mSettingsDialog;
00510
00511 if (mPreviewBuilderThread)
00512 delete mPreviewBuilderThread;
00513
00514 delete u;
00515 }
00516
00517 void KLFMainWin::startupFinished()
00518 {
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 pExportProfileQuickMenuActionList.clear();
00530 int k;
00531 QList<KLFMimeExportProfile> eplist = KLFMimeExportProfile::exportProfileList();
00532 QMenu *menu = new QMenu(u->btnSetExportProfile);
00533 QActionGroup *actionGroup = new QActionGroup(menu);
00534 actionGroup->setExclusive(true);
00535 QSignalMapper *smapper = new QSignalMapper(menu);
00536 for (k = 0; k < eplist.size(); ++k) {
00537 QAction *action = new QAction(actionGroup);
00538 action->setText(eplist[k].description());
00539 action->setData(eplist[k].profileName());
00540 action->setCheckable(true);
00541 action->setChecked( (klfconfig.UI.dragExportProfile==klfconfig.UI.copyExportProfile) &&
00542 (klfconfig.UI.dragExportProfile==eplist[k].profileName()) );
00543 menu->addAction(action);
00544 smapper->setMapping(action, eplist[k].profileName());
00545 connect(action, SIGNAL(triggered()), smapper, SLOT(map()));
00546 pExportProfileQuickMenuActionList.append(action);
00547 }
00548 connect(smapper, SIGNAL(mapped(const QString&)), this, SLOT(slotSetExportProfile(const QString&)));
00549
00550 u->btnSetExportProfile->setMenu(menu);
00551 }
00552
00553
00554
00555 void KLFMainWin::refreshWindowSizes()
00556 {
00557 bool curstate_shown = u->frmDetails->isVisible();
00558 u->frmDetails->show();
00559 _shrinkedsize = u->frmMain->sizeHint() + QSize(3, 3);
00560 _expandedsize.setWidth(u->frmMain->sizeHint().width() + u->frmDetails->sizeHint().width() + 3);
00561 _expandedsize.setHeight(u->frmMain->sizeHint().height() + 3);
00562 if (curstate_shown) {
00563 setFixedSize(_expandedsize);
00564 u->frmDetails->show();
00565 } else {
00566 setFixedSize(_shrinkedsize);
00567 u->frmDetails->hide();
00568 }
00569 updateGeometry();
00570 }
00571
00572 void KLFMainWin::refreshShowCorrectClearButton()
00573 {
00574 bool lo = klfconfig.UI.clearLatexOnly;
00575 u->btnClearAll->setVisible(!lo);
00576 u->btnClearLatex->setVisible(lo);
00577 }
00578
00579
00580 bool KLFMainWin::loadDefaultStyle()
00581 {
00582
00583 bool r;
00584 r = loadNamedStyle(tr("Default", "[[style name]]"));
00585 r = r || loadNamedStyle("Default");
00586 r = r || loadNamedStyle("default");
00587 return r;
00588 }
00589
00590 bool KLFMainWin::loadNamedStyle(const QString& sty)
00591 {
00592
00593 for (int kl = 0; kl < _styles.size(); ++kl) {
00594 if (_styles[kl].name == sty) {
00595 slotLoadStyle(kl);
00596 return true;
00597 }
00598 }
00599 return false;
00600 }
00601
00602 void KLFMainWin::loadSettings()
00603 {
00604 _settings.tempdir = klfconfig.BackendSettings.tempDir;
00605 _settings.latexexec = klfconfig.BackendSettings.execLatex;
00606 _settings.dvipsexec = klfconfig.BackendSettings.execDvips;
00607 _settings.gsexec = klfconfig.BackendSettings.execGs;
00608 _settings.epstopdfexec = klfconfig.BackendSettings.execEpstopdf;
00609 _settings.execenv = klfconfig.BackendSettings.execenv;
00610
00611 _settings.lborderoffset = klfconfig.BackendSettings.lborderoffset;
00612 _settings.tborderoffset = klfconfig.BackendSettings.tborderoffset;
00613 _settings.rborderoffset = klfconfig.BackendSettings.rborderoffset;
00614 _settings.bborderoffset = klfconfig.BackendSettings.bborderoffset;
00615
00616 _settings.outlineFonts = klfconfig.BackendSettings.outlineFonts;
00617
00618 _settings_altered = false;
00619 }
00620
00621 void KLFMainWin::saveSettings()
00622 {
00623 if ( ! _settings_altered ) {
00624 klfconfig.BackendSettings.tempDir = _settings.tempdir;
00625 klfconfig.BackendSettings.execLatex = _settings.latexexec;
00626 klfconfig.BackendSettings.execDvips = _settings.dvipsexec;
00627 klfconfig.BackendSettings.execGs = _settings.gsexec;
00628 klfconfig.BackendSettings.execEpstopdf = _settings.epstopdfexec;
00629 klfconfig.BackendSettings.execenv = _settings.execenv;
00630 klfconfig.BackendSettings.lborderoffset = _settings.lborderoffset;
00631 klfconfig.BackendSettings.tborderoffset = _settings.tborderoffset;
00632 klfconfig.BackendSettings.rborderoffset = _settings.rborderoffset;
00633 klfconfig.BackendSettings.bborderoffset = _settings.bborderoffset;
00634 klfconfig.BackendSettings.outlineFonts = _settings.outlineFonts;
00635 }
00636
00637 klfconfig.UI.userColorList = KLFColorChooser::colorList();
00638 klfconfig.UI.colorChooseWidgetRecent = KLFColorChooseWidget::recentColors();
00639 klfconfig.UI.colorChooseWidgetCustom = KLFColorChooseWidget::customColors();
00640
00641 klfconfig.writeToConfig();
00642
00643 mPreviewBuilderThread->settingsChanged(_settings, klfconfig.UI.labelOutputFixedSize.width(),
00644 klfconfig.UI.labelOutputFixedSize.height());
00645
00646 u->lblOutput->setLabelFixedSize(klfconfig.UI.labelOutputFixedSize);
00647 u->lblOutput->setEnableToolTipPreview(klfconfig.UI.enableToolTipPreview);
00648
00649 u->lblOutput->setGlowEffect(klfconfig.UI.glowEffect);
00650 u->lblOutput->setGlowEffectColor(klfconfig.UI.glowEffectColor);
00651 u->lblOutput->setGlowEffectRadius(klfconfig.UI.glowEffectRadius);
00652
00653 int k;
00654 if (klfconfig.UI.dragExportProfile == klfconfig.UI.copyExportProfile) {
00655 klfDbg("checking quick menu action item export profile="<<klfconfig.UI.copyExportProfile) ;
00656
00657 for (k = 0; k < pExportProfileQuickMenuActionList.size(); ++k) {
00658 if (pExportProfileQuickMenuActionList[k]->data().toString() == klfconfig.UI.copyExportProfile) {
00659 klfDbg("checking item #"<<k<<": "<<pExportProfileQuickMenuActionList[k]->data()) ;
00660
00661 pExportProfileQuickMenuActionList[k]->setChecked(true);
00662 break;
00663 }
00664 }
00665 } else {
00666
00667 for (k = 0; k < pExportProfileQuickMenuActionList.size(); ++k)
00668 pExportProfileQuickMenuActionList[k]->setChecked(false);
00669 }
00670
00671 u->btnSetExportProfile->setEnabled(klfconfig.UI.menuExportProfileAffectsDrag ||
00672 klfconfig.UI.menuExportProfileAffectsCopy);
00673
00674 if (klfconfig.UI.enableRealTimePreview) {
00675 if ( ! mPreviewBuilderThread->isRunning() ) {
00676 delete mPreviewBuilderThread;
00677 mPreviewBuilderThread =
00678 new KLFPreviewBuilderThread(this, collectInput(false), _settings,
00679 klfconfig.UI.labelOutputFixedSize.width(),
00680 klfconfig.UI.labelOutputFixedSize.height());
00681 mPreviewBuilderThread->start();
00682 }
00683 } else {
00684 if ( mPreviewBuilderThread->isRunning() ) {
00685 delete mPreviewBuilderThread;
00686
00687 mPreviewBuilderThread =
00688 new KLFPreviewBuilderThread(this, collectInput(false), _settings,
00689 klfconfig.UI.labelOutputFixedSize.width(),
00690 klfconfig.UI.labelOutputFixedSize.height());
00691 }
00692 }
00693 }
00694
00695 void KLFMainWin::showExportMsgLabel(const QString& msg, int timeout)
00696 {
00697 mExportMsgLabel->show();
00698 mExportMsgLabel->setPalette(mExportMsgLabel->property("defaultPalette").value<QPalette>());
00699
00700 mExportMsgLabel->setProperty("timeTotal", timeout);
00701 mExportMsgLabel->setProperty("timeRemaining", timeout);
00702 mExportMsgLabel->setProperty("timeInterval", 200);
00703
00704 mExportMsgLabel->setText(msg);
00705
00706 if (pExportMsgLabelTimerId == -1) {
00707 pExportMsgLabelTimerId = startTimer(mExportMsgLabel->property("timeInterval").toInt());
00708 }
00709 }
00710
00711 void KLFMainWin::refreshStylePopupMenus()
00712 {
00713 if (mStyleMenu == NULL)
00714 mStyleMenu = new QMenu(this);
00715 mStyleMenu->clear();
00716
00717 QAction *a;
00718 for (int i = 0; i < _styles.size(); ++i) {
00719 a = mStyleMenu->addAction(_styles[i].name);
00720 a->setData(i);
00721 connect(a, SIGNAL(triggered()), this, SLOT(slotLoadStyleAct()));
00722 }
00723
00724 mStyleMenu->addSeparator();
00725 mStyleMenu->addAction(QIcon(":/pics/managestyles.png"), tr("Manage Styles"),
00726 this, SLOT(slotStyleManager()), 0 );
00727
00728 }
00729
00730
00731
00732 static QString kdelocate(const char *fname)
00733 {
00734 QString candidate;
00735
00736 QStringList env = QProcess::systemEnvironment();
00737 QStringList kdehome = env.filter(QRegExp("^KDEHOME="));
00738 if (kdehome.size() == 0) {
00739 candidate = QDir::homePath() + QString("/.kde/share/apps/klatexformula/") + QString::fromLocal8Bit(fname);
00740 } else {
00741 QString kdehomeval = kdehome[0];
00742 kdehomeval.replace(QRegExp("^KDEHOME="), "");
00743 candidate = kdehomeval + "/share/apps/klatexformula/" + QString::fromLocal8Bit(fname);
00744 }
00745 if (QFile::exists(candidate)) {
00746 return candidate;
00747 }
00748 return QString::null;
00749 }
00750
00751 bool KLFMainWin::try_load_style_list(const QString& styfname)
00752 {
00753 if ( ! QFile::exists(styfname) )
00754 return false;
00755
00756 QFile fsty(styfname);
00757 if ( ! fsty.open(QIODevice::ReadOnly) )
00758 return false;
00759
00760 QDataStream str(&fsty);
00761
00762 QString readHeader;
00763 QString readCompatKLFVersion;
00764 bool r = klfDataStreamReadHeader(str, QStringList()<<QLatin1String("KLATEXFORMULA_STYLE_LIST"),
00765 &readHeader, &readCompatKLFVersion);
00766 if (!r) {
00767 if (readHeader.isEmpty() || readCompatKLFVersion.isEmpty()) {
00768 QMessageBox::critical(this, tr("Error"), tr("Error: Style file is incorrect or corrupt!\n"));
00769 return false;
00770 }
00771
00772 QMessageBox::warning(this, tr("Load Styles"),
00773 tr("The style file found was created by a more recent version "
00774 "of KLatexFormula.\n"
00775 "The process of style loading may fail.")
00776 );
00777 }
00778
00779 str >> _styles;
00780 return true;
00781 }
00782
00783 void KLFMainWin::loadStyles()
00784 {
00785 _styles = KLFStyleList();
00786
00787 QStringList styfnamecandidates;
00788 styfnamecandidates << klfconfig.homeConfigDir + QString("/styles-klf%1").arg(KLF_DATA_STREAM_APP_VERSION)
00789 << klfconfig.homeConfigDir + QLatin1String("/styles")
00790 << QLatin1String("kde-locate");
00791
00792 int k;
00793 bool result = false;
00794 for (k = 0; k < styfnamecandidates.size(); ++k) {
00795 QString fn = styfnamecandidates[k];
00796 if (fn == QLatin1String("kde-locate"))
00797 fn = kdelocate("styles");
00798
00799 if ( (result = try_load_style_list(fn)) == true )
00800 break;
00801 }
00802
00803
00804
00805
00806
00807 if (_styles.isEmpty()) {
00808
00809 KLFStyle s1(tr("Default"), qRgb(0, 0, 0), qRgba(255, 255, 255, 0), "\\[ ... \\]", "", 600);
00810
00811
00812 _styles.append(s1);
00813
00814 }
00815
00816 mStyleMenu = 0;
00817 refreshStylePopupMenus();
00818
00819 u->btnLoadStyle->setMenu(mStyleMenu);
00820 }
00821
00822 void KLFMainWin::saveStyles()
00823 {
00824 klfconfig.ensureHomeConfigDir();
00825 QString s = klfconfig.homeConfigDir + QString("/styles-klf%1").arg(KLF_DATA_STREAM_APP_VERSION);
00826 QFile f(s);
00827 if ( ! f.open(QIODevice::WriteOnly) ) {
00828 QMessageBox::critical(this, tr("Error"), tr("Error: Unable to write to styles file!\n%1").arg(s));
00829 return;
00830 }
00831 QDataStream stream(&f);
00832
00833 klfDataStreamWriteHeader(stream, "KLATEXFORMULA_STYLE_LIST");
00834
00835 stream << _styles;
00836 }
00837
00838 void KLFMainWin::loadLibrary()
00839 {
00840 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00841
00842
00843
00844
00845 loadLibrarySavedState();
00846
00847
00848
00849
00850
00851
00852
00853 QString localfname = klfconfig.Core.libraryFileName;
00854 if (QFileInfo(localfname).isRelative())
00855 localfname.prepend(klfconfig.homeConfigDir + "/");
00856
00857 QString importfname;
00858 if ( ! QFile::exists(localfname) ) {
00859
00860 importfname = klfconfig.homeConfigDir + "/library";
00861 if ( ! QFile::exists(importfname) )
00862 importfname = kdelocate("library");
00863 if ( ! QFile::exists(importfname) )
00864 importfname = kdelocate("history");
00865 if ( ! QFile::exists(importfname) ) {
00866
00867 importfname = ":/data/defaultlibrary.klf";
00868 }
00869 }
00870
00871
00872
00873 QUrl localliburl = QUrl::fromLocalFile(localfname);
00874 localliburl.setScheme(klfconfig.Core.libraryLibScheme);
00875 localliburl.addQueryItem("klfDefaultSubResource", "History");
00876
00877
00878
00879 mHistoryLibResource = mLibBrowser->getOpenResource(localliburl);
00880
00881 if (!QFile::exists(localfname)) {
00882
00883 KLFLibEngineFactory *localLibFactory = KLFLibEngineFactory::findFactoryFor(localliburl.scheme());
00884 if (localLibFactory == NULL) {
00885 qWarning()<<KLF_FUNC_NAME<<": Can't find library resource engine factory for scheme "<<localliburl.scheme()<<"!";
00886 qFatal("%s: Can't find library resource engine factory for scheme '%s'!",
00887 KLF_FUNC_NAME, qPrintable(localliburl.scheme()));
00888 return;
00889 }
00890 KLFLibEngineFactory::Parameters param;
00891 param["Filename"] = localliburl.path();
00892 param["klfDefaultSubResource"] = QLatin1String("History");
00893 param["klfDefaultSubResourceTitle"] = tr("History", "[[default sub-resource title for history]]");
00894 mHistoryLibResource = localLibFactory->createResource(localliburl.scheme(), param, this);
00895 if (mHistoryLibResource == NULL) {
00896 qWarning()<<KLF_FUNC_NAME<<": Can't create resource engine for library, of scheme "<<localliburl.scheme()<<"! "
00897 <<"Create parameters are "<<param;
00898 qFatal("%s: Can't create resource engine for library!", KLF_FUNC_NAME);
00899 return;
00900 }
00901 mHistoryLibResource->setTitle(tr("Local Library"));
00902 mHistoryLibResource
00903 -> createSubResource(QLatin1String("Archive"),
00904 tr("Archive", "[[default sub-resource title for archive sub-resource]]"));
00905 if (mHistoryLibResource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResourceProps) {
00906 mHistoryLibResource->setSubResourceProperty(QLatin1String("History"),
00907 KLFLibResourceEngine::SubResPropViewType,
00908 QLatin1String("default+list"));
00909 mHistoryLibResource->setSubResourceProperty(QLatin1String("Archive"),
00910 KLFLibResourceEngine::SubResPropViewType,
00911 QLatin1String("default"));
00912 } else {
00913 mHistoryLibResource->setViewType(QLatin1String("default+list"));
00914 }
00915 }
00916
00917 if (mHistoryLibResource == NULL) {
00918 mHistoryLibResource = KLFLibEngineFactory::openURL(localliburl, this);
00919 }
00920 if (mHistoryLibResource == NULL) {
00921 qWarning()<<"KLFMainWin::loadLibrary(): Can't open local history resource!\n\tURL="<<localliburl
00922 <<"\n\tNot good! Expect crash!";
00923 return;
00924 }
00925
00926 klfDbg("opened history: resource-ptr="<<mHistoryLibResource<<"\n\tImportFile="<<importfname);
00927
00928 if (!importfname.isEmpty()) {
00929
00930 klfDbg("Importing library from "<<importfname) ;
00931
00932
00933 KLFProgressDialog pdlg(QString(), this);
00934 connect(mHistoryLibResource, SIGNAL(operationStartReportingProgress(KLFProgressReporter *,
00935 const QString&)),
00936 &pdlg, SLOT(startReportingProgress(KLFProgressReporter *)));
00937 pdlg.setAutoClose(false);
00938 pdlg.setAutoReset(false);
00939
00940
00941 QUrl importliburl = QUrl::fromLocalFile(importfname);
00942 QString scheme = KLFLibBasicWidgetFactory::guessLocalFileScheme(importfname);
00943 if (scheme.isEmpty()) {
00944
00945 scheme = "klf+legacy";
00946 }
00947 importliburl.setScheme(scheme);
00948 importliburl.addQueryItem("klfReadOnly", "true");
00949
00950 KLFLibEngineFactory *factory = KLFLibEngineFactory::findFactoryFor(importliburl.scheme());
00951 if (factory == NULL) {
00952 qWarning()<<"KLFMainWin::loadLibrary(): Can't find factory for URL="<<importliburl<<"!";
00953 } else {
00954 KLFLibResourceEngine *importres = factory->openResource(importliburl, this);
00955
00956 QStringList subResList = importres->subResourceList();
00957 klfDbg( "\tImporting sub-resources: "<<subResList ) ;
00958 int j;
00959 for (j = 0; j < subResList.size(); ++j) {
00960 QString subres = subResList[j];
00961 pdlg.setDescriptiveText(tr("Importing Library from previous version of KLatexFormula ... "
00962 "%3 (%1/%2)")
00963 .arg(j+1).arg(subResList.size()).arg(subResList[j]));
00964 QList<KLFLibResourceEngine::KLFLibEntryWithId> allentries
00965 = importres->allEntries(subres);
00966 klfDbg("Got "<<allentries.size()<<" entries from sub-resource "<<subres);
00967 int k;
00968 KLFLibEntryList insertentries;
00969 for (k = 0; k < allentries.size(); ++k) {
00970 insertentries << allentries[k].entry;
00971 }
00972 if ( ! mHistoryLibResource->hasSubResource(subres) ) {
00973 mHistoryLibResource->createSubResource(subres);
00974 }
00975 mHistoryLibResource->insertEntries(subres, insertentries);
00976 }
00977 }
00978 }
00979
00980
00981 bool r;
00982 r = mLibBrowser->openResource(mHistoryLibResource,
00983 KLFLibBrowser::NoCloseRoleFlag|KLFLibBrowser::OpenNoRaise,
00984 QLatin1String("default+list"));
00985 if ( ! r ) {
00986 qWarning()<<"KLFMainWin::loadLibrary(): Can't open local history resource!\n\tURL="<<localliburl
00987 <<"\n\tExpect Crash!";
00988 return;
00989 }
00990
00991
00992 QStringList subresources = mHistoryLibResource->subResourceList();
00993 int k;
00994 for (k = 0; k < subresources.size(); ++k) {
00995
00996
00997
00998 QUrl url = localliburl;
00999 url.removeAllQueryItems("klfDefaultSubResource");
01000 url.addQueryItem("klfDefaultSubResource", subresources[k]);
01001
01002 uint flags = KLFLibBrowser::NoCloseRoleFlag|KLFLibBrowser::OpenNoRaise;
01003 QString sr = subresources[k].toLower();
01004 if (sr == "history" || sr == tr("History").toLower())
01005 flags |= KLFLibBrowser::HistoryRoleFlag;
01006 if (sr == "archive" || sr == tr("Archive").toLower())
01007 flags |= KLFLibBrowser::ArchiveRoleFlag;
01008
01009 mLibBrowser->openResource(url, flags);
01010 }
01011 }
01012
01013 void KLFMainWin::loadLibrarySavedState()
01014 {
01015 QString fname = klfconfig.homeConfigDir + "/libbrowserstate.xml";
01016 if ( ! QFile::exists(fname) ) {
01017 klfDbg("No saved library browser state found ("<<fname<<")");
01018 return;
01019 }
01020
01021 QFile f(fname);
01022 if ( ! f.open(QIODevice::ReadOnly) ) {
01023 qWarning()<<"Can't open file "<<fname<<" for loading library browser state";
01024 return;
01025 }
01026 QDomDocument doc("klflibbrowserstate");
01027 doc.setContent(&f);
01028 f.close();
01029
01030 QDomNode rootNode = doc.documentElement();
01031 if (rootNode.nodeName() != "klflibbrowserstate") {
01032 qWarning()<<"Invalid root node in file "<<fname<<" !";
01033 return;
01034 }
01035 QDomNode n;
01036 QVariantMap vstatemap;
01037 for (n = rootNode.firstChild(); ! n.isNull(); n = n.nextSibling()) {
01038 QDomElement e = n.toElement();
01039 if ( e.isNull() || n.nodeType() != QDomNode::ElementNode )
01040 continue;
01041 if ( e.nodeName() == "statemap" ) {
01042 vstatemap = klfLoadVariantMapFromXML(e);
01043 continue;
01044 }
01045
01046 qWarning("%s: Ignoring unrecognized node `%s' in file %s.", KLF_FUNC_NAME,
01047 qPrintable(e.nodeName()), qPrintable(fname));
01048 }
01049
01050 mLibBrowser->loadGuiState(vstatemap, klfconfig.LibraryBrowser.restoreURLs);
01051 }
01052
01053 void KLFMainWin::saveLibraryState()
01054 {
01055 QString fname = klfconfig.homeConfigDir + "/libbrowserstate.xml";
01056
01057 QVariantMap statemap = mLibBrowser->saveGuiState();
01058
01059 QFile f(fname);
01060 if ( ! f.open(QIODevice::WriteOnly) ) {
01061 qWarning()<<"Can't open file "<<fname<<" for saving library browser state";
01062 return;
01063 }
01064
01065 QDomDocument doc("klflibbrowserstate");
01066 QDomElement rootNode = doc.createElement("klflibbrowserstate");
01067 QDomElement statemapNode = doc.createElement("statemap");
01068
01069 klfSaveVariantMapToXML(statemap, statemapNode);
01070
01071 rootNode.appendChild(statemapNode);
01072 doc.appendChild(rootNode);
01073
01074 f.write(doc.toByteArray(2));
01075 }
01076
01077
01078 void KLFMainWin::slotOpenHistoryLibraryResource()
01079 {
01080 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
01081
01082 bool r;
01083 r = mLibBrowser->openResource(mHistoryLibResource, KLFLibBrowser::NoCloseRoleFlag,
01084 QLatin1String("default+list"));
01085 if ( ! r )
01086 qWarning()<<KLF_FUNC_NAME<<": Can't open local history resource!";
01087
01088 }
01089
01090
01091
01092 void KLFMainWin::restoreFromLibrary(const KLFLibEntry& entry, uint restoreFlags)
01093 {
01094 if (restoreFlags & KLFLib::RestoreStyle) {
01095 KLFStyle style = entry.style();
01096 slotLoadStyle(style);
01097 }
01098
01099
01100 if (restoreFlags & KLFLib::RestoreLatex) {
01101
01102 slotSetLatex(entry.latexWithCategoryTagsComments());
01103 }
01104
01105 u->lblOutput->display(entry.preview(), entry.preview(), false);
01106 u->frmOutput->setEnabled(false);
01107 activateWindow();
01108 raise();
01109 u->txtLatex->setFocus();
01110 }
01111
01112 void KLFMainWin::slotLibraryButtonRefreshState(bool on)
01113 {
01114 u->btnLibrary->setChecked(on);
01115 }
01116
01117
01118 void KLFMainWin::insertSymbol(const KLFLatexSymbol& s)
01119 {
01120
01121 QStringList cmds = s.preamble;
01122 int k;
01123 QString preambletext = u->txtPreamble->toPlainText();
01124 QString addtext;
01125 for (k = 0; k < cmds.size(); ++k) {
01126 slotEnsurePreambleCmd(cmds[k]);
01127 }
01128
01129
01130
01131 QTextCursor c1(u->txtLatex->document());
01132 c1.beginEditBlock();
01133 c1.setPosition(u->txtLatex->textCursor().position());
01134 c1.insertText(s.symbol+"\n");
01135 c1.deletePreviousChar();
01136 c1.endEditBlock();
01137
01138 activateWindow();
01139 raise();
01140 u->txtLatex->setFocus();
01141 }
01142
01143 void KLFMainWin::insertDelimiter(const QString& delim, int charsBack)
01144 {
01145 u->txtLatex->insertDelimiter(delim, charsBack);
01146 }
01147
01148
01149 void KLFMainWin::getMissingCmdsFor(const QString& symbol, QStringList * missingCmds,
01150 QString *guiText, bool wantHtmlText)
01151 {
01152 if (missingCmds == NULL) {
01153 qWarning()<<KLF_FUNC_NAME<<": missingCmds is NULL!";
01154 return;
01155 }
01156 if (guiText == NULL) {
01157 qWarning()<<KLF_FUNC_NAME<<": guiText is NULL!";
01158 return;
01159 }
01160
01161 missingCmds->clear();
01162 *guiText = QString();
01163
01164 if (symbol.isEmpty())
01165 return;
01166
01167 KLFLatexSymbol sym = KLFLatexSymbolsCache::theCache()->findSymbol(symbol);
01168 if (!sym.valid())
01169 return;
01170
01171 QStringList cmds = sym.preamble;
01172 klfDbg("Got symbol for "<<symbol<<"; cmds is "<<cmds);
01173 if (cmds.isEmpty()) {
01174 return;
01175 }
01176
01177 QString curpreambletext = u->txtPreamble->toPlainText();
01178 QStringList packages;
01179 bool moreDefinitions = false;
01180 int k;
01181 for (k = 0; k < cmds.size(); ++k) {
01182 if (curpreambletext.indexOf(cmds[k]) >= 0)
01183 continue;
01184
01185 missingCmds->append(cmds[k]);
01186
01187 QRegExp rx("\\\\usepackage.*\\{(\\w+)\\}");
01188 klfDbg(" regexp="<<rx.pattern()<<"; cmd for symbol: "<<cmds[k].trimmed());
01189 if (rx.exactMatch(cmds[k].trimmed())) {
01190 packages << rx.cap(1);
01191 } else {
01192
01193 moreDefinitions = true;
01194 }
01195 }
01196 if (wantHtmlText)
01197 packages.replaceInStrings(QRegExp("^(.*)$"), QString("<b>\\1</b>"));
01198
01199 QString requiredtext;
01200 if (packages.size()) {
01201 if (packages.size() == 1)
01202 requiredtext += tr("package %1",
01203 "[[part of popup text, if one package only]]").arg(packages[0]);
01204 else
01205 requiredtext += tr("packages %1",
01206 "[[part of popup text, if multiple packages]]").arg(packages.join(", "));
01207 }
01208 if (moreDefinitions)
01209 requiredtext += packages.size()
01210 ? tr(" and <i>some more definitions</i>",
01211 "[[part of hint popup text, when packages also need to be included]]")
01212 : tr("<i>some definitions</i>",
01213 "[[part of hint popup text, when no packages need to be included]]");
01214 if (!wantHtmlText)
01215 requiredtext.replace(QRegExp("<[^>]*>"), "");
01216
01217 *guiText = requiredtext;
01218 }
01219
01220 void KLFMainWin::slotNewSymbolTyped(const QString& symbol)
01221 {
01222 if (mPopup == NULL)
01223 mPopup = new KLFMainWinPopup(this);
01224
01225 if (!klfconfig.UI.showHintPopups)
01226 return;
01227
01228 QStringList cmds;
01229 QString requiredtext;
01230
01231 getMissingCmdsFor(symbol, &cmds, &requiredtext);
01232
01233 if (cmds.isEmpty())
01234 return;
01235
01236 QByteArray cmdsData = klfSaveVariantToText(QVariant(cmds));
01237 QString msgkey = "preambleCmdStringList:"+QString::fromLatin1(cmdsData);
01238 QUrl urlaction;
01239 urlaction.setScheme("klfaction");
01240 urlaction.setPath("/popup");
01241 QUrl urlactionClose = urlaction;
01242 urlaction.addQueryItem("preambleCmdStringList", QString::fromLatin1(cmdsData));
01243 urlactionClose.addQueryItem("removeMessageKey", msgkey);
01244 mPopup->addMessage(msgkey,
01245
01246
01247 tr("Symbol <tt>%3</tt> may require <a href=\"%1\">%2</a>.")
01248 .arg(urlaction.toEncoded(), requiredtext, symbol) );
01249 mPopup->show();
01250 mPopup->raise();
01251 }
01252 void KLFMainWin::slotPopupClose()
01253 {
01254 if (mPopup != NULL) {
01255 delete mPopup;
01256 mPopup = NULL;
01257 }
01258 }
01259 void KLFMainWin::slotPopupAction(const QUrl& url)
01260 {
01261 klfDbg("url="<<url.toEncoded());
01262 if (url.hasQueryItem("preambleCmdStringList")) {
01263
01264 QByteArray data = url.queryItemValue("preambleCmdStringList").toLatin1();
01265 klfDbg("data="<<data);
01266 QStringList cmds = klfLoadVariantFromText(data, "QStringList").toStringList();
01267 klfDbg("ensuring CMDS="<<cmds);
01268 int k;
01269 for (k = 0; k < cmds.size(); ++k) {
01270 slotEnsurePreambleCmd(cmds[k]);
01271 }
01272 mPopup->removeMessage("preambleCmdStringList:"+QString::fromLatin1(data));
01273 if (!mPopup->hasMessages())
01274 slotPopupClose();
01275 return;
01276 }
01277 if (url.hasQueryItem("acceptAll")) {
01278 slotPopupAcceptAll();
01279 return;
01280 }
01281 if (url.hasQueryItem("removeMessageKey")) {
01282 QString key = url.queryItemValue("removeMessageKey");
01283 mPopup->removeMessage(key);
01284 if (!mPopup->hasMessages())
01285 slotPopupClose();
01286 return;
01287 }
01288 if (url.hasQueryItem("configDontShow")) {
01289
01290 slotPopupClose();
01291 klfconfig.UI.showHintPopups = false;
01292 saveSettings();
01293 return;
01294 }
01295 }
01296 void KLFMainWin::slotPopupAcceptAll()
01297 {
01298 if (mPopup == NULL)
01299 return;
01300
01301
01302 QStringList keys = mPopup->messageKeys();
01303 int k;
01304 for (k = 0; k < keys.size(); ++k) {
01305 QString s = keys[k];
01306 if (s.startsWith("preambleCmdStringList:")) {
01307 QByteArray data = s.mid(strlen("preambleCmdStringList:")).toLatin1();
01308 QStringList cmds = klfLoadVariantFromText(data, "QStringList").toStringList();
01309 int k;
01310 for (k = 0; k < cmds.size(); ++k) {
01311 slotEnsurePreambleCmd(cmds[k]);
01312 }
01313 continue;
01314 }
01315 qWarning()<<KLF_FUNC_NAME<<": Unknown message key: "<<s;
01316 }
01317 slotPopupClose();
01318 }
01319
01320 void KLFMainWin::slotEditorContextMenuInsertActions(const QPoint& pos, QList<QAction*> *actionList)
01321 {
01322 KLFLatexEdit *latexEdit = qobject_cast<KLFLatexEdit*>(sender());
01323 KLF_ASSERT_NOT_NULL( latexEdit, "KLFLatexEdit sender is NULL!", return ) ;
01324
01325
01326
01327 QTextCursor cur = latexEdit->cursorForPosition(pos);
01328 QString text = latexEdit->toPlainText();
01329 int curpos = cur.position();
01330
01331 QRegExp rxSym("\\\\(\\w+|.)");
01332 int i = text.lastIndexOf(rxSym, curpos);
01333 if (i >= 0) {
01334
01335 int len = rxSym.matchedLength();
01336 QString symbol = text.mid(i, len);
01337 QStringList cmds;
01338 QString guitext;
01339 getMissingCmdsFor(symbol, &cmds, &guitext, false);
01340 if (cmds.size()) {
01341 QAction * aInsCmds = new QAction(latexEdit);
01342 aInsCmds->setText(tr("Include missing definitions for %1").arg(symbol));
01343 aInsCmds->setData(QVariant(cmds));
01344 connect(aInsCmds, SIGNAL(triggered()), this, SLOT(slotInsertMissingPackagesFromActionSender()));
01345 *actionList << aInsCmds;
01346 }
01347 }
01348
01349 QAction *insertSymbolAction = new QAction(QIcon(":/pics/symbols.png"),
01350 tr("Insert Symbol ...", "[[context menu entry]]"), latexEdit);
01351 connect(insertSymbolAction, SIGNAL(triggered()), this, SLOT(slotSymbols()));
01352 *actionList << insertSymbolAction;
01353 }
01354
01355
01356 void KLFMainWin::slotInsertMissingPackagesFromActionSender()
01357 {
01358 QAction * a = qobject_cast<QAction*>(sender());
01359 if (a == NULL) {
01360 qWarning()<<KLF_FUNC_NAME<<": NULL QAction sender!";
01361 return;
01362 }
01363 QVariant data = a->data();
01364 QStringList cmds = data.toStringList();
01365 int k;
01366 for (k = 0; k < cmds.size(); ++k) {
01367 slotEnsurePreambleCmd(cmds[k]);
01368 }
01369 }
01370
01371
01372
01373 void KLFMainWin::slotSymbolsButtonRefreshState(bool on)
01374 {
01375 u->btnSymbols->setChecked(on);
01376 }
01377
01378 void KLFMainWin::showAbout()
01379 {
01380 mAboutDialog->show();
01381 }
01382
01383 void KLFMainWin::showWhatsNew()
01384 {
01385
01386 QSize desktopSize = QApplication::desktop()->screenGeometry(this).size();
01387 QSize wS = mWhatsNewDialog->sizeHint();
01388 mWhatsNewDialog->move(desktopSize.width()/2 - wS.width()/2,
01389 desktopSize.height()/2 - wS.height()/2);
01390 mWhatsNewDialog->show();
01391 }
01392
01393 void KLFMainWin::showSettingsHelpLinkAction(const QUrl& link)
01394 {
01395 klfDbg( ": link="<<link ) ;
01396 mSettingsDialog->show();
01397 mSettingsDialog->showControl(link.queryItemValue("control"));
01398 }
01399
01400 void KLFMainWin::helpLinkAction(const QUrl& link)
01401 {
01402 klfDbg( ": Link is "<<link<<"; scheme="<<link.scheme()<<"; path="<<link.path()
01403 <<"; queryItems="<<link.queryItems() ) ;
01404
01405 if (link.scheme() == "http") {
01406
01407 QDesktopServices::openUrl(link);
01408 return;
01409 }
01410 if (link.scheme() == "klfaction") {
01411
01412 bool calledOne = false;
01413 int k;
01414 for (k = 0; k < mHelpLinkActions.size(); ++k) {
01415 if (mHelpLinkActions[k].path == link.path()) {
01416
01417 if (mHelpLinkActions[k].wantParam)
01418 QMetaObject::invokeMethod(mHelpLinkActions[k].reciever,
01419 mHelpLinkActions[k].memberFunc.constData(),
01420 Qt::QueuedConnection, Q_ARG(QUrl, link));
01421 else
01422 QMetaObject::invokeMethod(mHelpLinkActions[k].reciever,
01423 mHelpLinkActions[k].memberFunc.constData(),
01424 Qt::QueuedConnection);
01425
01426 calledOne = true;
01427 }
01428 }
01429 if (!calledOne) {
01430 qWarning()<<KLF_FUNC_NAME<<": no action found for link="<<link;
01431 }
01432 return;
01433 }
01434 qWarning()<<KLF_FUNC_NAME<<"("<<link<<"): Unrecognized link scheme!";
01435 }
01436
01437 void KLFMainWin::addWhatsNewText(const QString& htmlSnipplet)
01438 {
01439 mWhatsNewDialog->addExtraText(htmlSnipplet);
01440 }
01441
01442
01443 void KLFMainWin::registerHelpLinkAction(const QString& path, QObject *object, const char * member,
01444 bool wantUrlParam)
01445 {
01446 mHelpLinkActions << HelpLinkAction(path, object, member, wantUrlParam);
01447 }
01448
01449
01450 void KLFMainWin::registerOutputSaver(KLFAbstractOutputSaver *outputsaver)
01451 {
01452 KLF_ASSERT_NOT_NULL( outputsaver, "Refusing to register NULL Output Saver object!", return ) ;
01453
01454 pOutputSavers.append(outputsaver);
01455 }
01456
01457 void KLFMainWin::unregisterOutputSaver(KLFAbstractOutputSaver *outputsaver)
01458 {
01459 pOutputSavers.removeAll(outputsaver);
01460 }
01461
01462 void KLFMainWin::registerDataOpener(KLFAbstractDataOpener *dataopener)
01463 {
01464 KLF_ASSERT_NOT_NULL( dataopener, "Refusing to register NULL Data Opener object!", return ) ;
01465
01466 pDataOpeners.append(dataopener);
01467 }
01468 void KLFMainWin::unregisterDataOpener(KLFAbstractDataOpener *dataopener)
01469 {
01470 pDataOpeners.removeAll(dataopener);
01471 }
01472
01473
01474 void KLFMainWin::setWidgetStyle(const QString& qtstyle)
01475 {
01476
01477 if (_widgetstyle == qtstyle) {
01478
01479 return;
01480 }
01481 if (qtstyle.isNull()) {
01482
01483 _widgetstyle = QString::null;
01484 return;
01485 }
01486 QStringList stylelist = QStyleFactory::keys();
01487 if (stylelist.indexOf(qtstyle) == -1) {
01488 qWarning("Bad Style: %s. List of possible styles are:", qPrintable(qtstyle));
01489 int k;
01490 for (k = 0; k < stylelist.size(); ++k)
01491 qWarning("\t%s", qPrintable(stylelist[k]));
01492 return;
01493 }
01494
01495 QStyle *s = QStyleFactory::create(qtstyle);
01496
01497 if ( ! s ) {
01498 qWarning("Can't instantiate style %s!", qPrintable(qtstyle));
01499 return;
01500 }
01501 _widgetstyle = qtstyle;
01502 qApp->setStyle( s );
01503 }
01504
01505 void KLFMainWin::setQuitOnClose(bool quitOnClose)
01506 {
01507 _ignore_close_event = ! quitOnClose;
01508 }
01509
01510
01511 void KLFMainWin::quit()
01512 {
01513 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
01514
01515 hide();
01516
01517 if (mLibBrowser)
01518 mLibBrowser->hide();
01519 if (mLatexSymbols)
01520 mLatexSymbols->hide();
01521 if (mStyleManager)
01522 mStyleManager->hide();
01523 if (mSettingsDialog)
01524 mSettingsDialog->hide();
01525 qApp->quit();
01526 }
01527
01528 bool KLFMainWin::event(QEvent *e)
01529 {
01530 klfDbg("e->type() == "<<e->type());
01531
01532 if (e->type() == QEvent::ApplicationFontChange) {
01533 klfDbg("Application font change.") ;
01534 if (klfconfig.UI.useSystemAppFont)
01535 klfconfig.UI.applicationFont = QApplication::font();
01536 }
01537
01538 return QWidget::event(e);
01539 }
01540
01541 void KLFMainWin::childEvent(QChildEvent *e)
01542 {
01543 QObject *child = e->child();
01544 if (e->type() == QEvent::ChildAdded && child->isWidgetType()) {
01545 QWidget *w = qobject_cast<QWidget*>(child);
01546 if (w->windowFlags() & Qt::Window) {
01547
01548
01549 pWindowList.append(w);
01550 klfDbg( ": Added child "<<w<<" ("<<w->objectName()<<")" ) ;
01551 }
01552 } else if (e->type() == QEvent::ChildRemoved && child->isWidgetType()) {
01553 QWidget *w = qobject_cast<QWidget*>(child);
01554 int k;
01555 if ((k = pWindowList.indexOf(w)) >= 0) {
01556 klfDbg( ": Removing child "<<w<<" ("<<w->objectName()<<")"
01557 <<" at position k="<<k ) ;
01558 pWindowList.removeAt(k);
01559 }
01560 }
01561
01562 QWidget::childEvent(e);
01563 }
01564
01565 bool KLFMainWin::eventFilter(QObject *obj, QEvent *e)
01566 {
01567
01568
01569 if (obj == u->txtLatex) {
01570 if (e->type() == QEvent::KeyPress) {
01571 QKeyEvent *ke = (QKeyEvent*) e;
01572 if (ke->key() == Qt::Key_Return &&
01573 (QApplication::keyboardModifiers() == Qt::ShiftModifier ||
01574 QApplication::keyboardModifiers() == Qt::ControlModifier)) {
01575 slotEvaluate();
01576 return true;
01577 }
01578 if (mPopup != NULL && ke->key() == Qt::Key_Return &&
01579 QApplication::keyboardModifiers() == Qt::AltModifier) {
01580 slotPopupAcceptAll();
01581 return true;
01582 }
01583 if (mPopup != NULL && ke->key() == Qt::Key_Escape) {
01584 slotPopupClose();
01585 return true;
01586 }
01587 if (ke->key() == Qt::Key_F9) {
01588 slotExpand(true);
01589 u->tabsOptions->setCurrentWidget(u->tabLatexImage);
01590 u->txtPreamble->setFocus();
01591 return true;
01592 }
01593 }
01594 }
01595 if (obj == u->txtLatex || obj == u->btnEvaluate) {
01596 if (e->type() == QEvent::KeyPress) {
01597 QKeyEvent *ke = (QKeyEvent*) e;
01598 QKeySequence seq = QKeySequence(ke->key() | ke->modifiers());
01599 if (seq.matches(QKeySequence::Copy)) {
01600
01601
01602
01603 if ( u->txtLatex->textCursor().hasSelection()) {
01604 u->txtLatex->copy();
01605 return true;
01606 } else {
01607 slotCopy();
01608 return true;
01609 }
01610 }
01611 }
01612 }
01613
01614
01615 if ( obj->isWidgetType() && (e->type() == QEvent::Hide || e->type() == QEvent::Show) ) {
01616
01617 int k = pWindowList.indexOf(qobject_cast<QWidget*>(obj));
01618 if (k >= 0) {
01619 QWidget *w = qobject_cast<QWidget*>(obj);
01620
01621 if (e->type() == QEvent::Hide && !((QHideEvent*)e)->spontaneous()) {
01622 if (pLastWindowShownStatus[w])
01623 pLastWindowGeometries[w] = klf_get_window_geometry(w);
01624 pLastWindowShownStatus[w] = false;
01625 } else if (e->type() == QEvent::Show && !((QShowEvent*)e)->spontaneous()) {
01626 pLastWindowShownStatus[w] = true;
01627 klf_set_window_geometry(w, pLastWindowGeometries[w]);
01628 }
01629 }
01630 }
01631
01632 if ( obj == mLibBrowser && (e->type() == QEvent::Hide || e->type() == QEvent::Show) ) {
01633 slotLibraryButtonRefreshState(mLibBrowser->isVisible());
01634 }
01635 if ( obj == mLatexSymbols && (e->type() == QEvent::Hide || e->type() == QEvent::Show) ) {
01636 slotSymbolsButtonRefreshState(mLatexSymbols->isVisible());
01637 }
01638
01639
01640 if ( obj == QApplication::instance() && e->type() == QEvent::FileOpen ) {
01641
01642 openFile(((QFileOpenEvent*)e)->file());
01643 return true;
01644 }
01645
01646
01647 if ( (obj == u->btnCopy || obj == u->btnDrag) && e->type() == QEvent::ToolTip ) {
01648 QString tooltipText;
01649 if (obj == u->btnCopy) {
01650 tooltipText = tr("Copy the formula to the clipboard. Current export profile: %1")
01651 .arg(KLFMimeExportProfile::findExportProfile(klfconfig.UI.copyExportProfile).description());
01652 } else if (obj == u->btnDrag) {
01653 tooltipText = tr("Click and keep mouse button pressed to drag your formula to an other application. "
01654 "Current export profile: %1")
01655 .arg(KLFMimeExportProfile::findExportProfile(klfconfig.UI.dragExportProfile).description());
01656 }
01657 QToolTip::showText(((QHelpEvent*)e)->globalPos(), tooltipText, qobject_cast<QWidget*>(obj));
01658 return true;
01659 }
01660
01661 return QWidget::eventFilter(obj, e);
01662 }
01663
01664
01665 void KLFMainWin::refreshAllWindowStyleSheets()
01666 {
01667 int k;
01668 for (k = 0; k < pWindowList.size(); ++k)
01669 pWindowList[k]->setStyleSheet(pWindowList[k]->styleSheet());
01670
01671 setStyleSheet(styleSheet());
01672 }
01673
01674
01675 QHash<QWidget*,bool> KLFMainWin::currentWindowShownStatus(bool mainWindowToo)
01676 {
01677 QHash<QWidget*,bool> status;
01678 if (mainWindowToo)
01679 status[this] = isVisible();
01680 int k;
01681 for (k = 0; k < pWindowList.size(); ++k)
01682 status[pWindowList[k]] = pWindowList[k]->isVisible();
01683 return status;
01684 }
01685 QHash<QWidget*,bool> KLFMainWin::prepareAllWindowShownStatus(bool visibleStatus, bool mainWindowToo)
01686 {
01687 QHash<QWidget*,bool> status;
01688 if (mainWindowToo)
01689 status[this] = visibleStatus;
01690 int k;
01691 for (k = 0; k < pWindowList.size(); ++k)
01692 status[pWindowList[k]] = visibleStatus;
01693 return status;
01694 }
01695
01696 void KLFMainWin::setWindowShownStatus(const QHash<QWidget*,bool>& shownStatus)
01697 {
01698 for (QHash<QWidget*,bool>::const_iterator it = shownStatus.begin(); it != shownStatus.end(); ++it)
01699 QMetaObject::invokeMethod(it.key(), "setVisible", Qt::QueuedConnection, Q_ARG(bool, it.value()));
01700 }
01701
01702
01703 void KLFMainWin::hideEvent(QHideEvent *e)
01704 {
01705 if ( ! e->spontaneous() ) {
01706 pSavedWindowShownStatus = currentWindowShownStatus(false);
01707 pLastWindowGeometries[this] = klf_get_window_geometry(this);
01708 setWindowShownStatus(prepareAllWindowShownStatus(false, false));
01709 }
01710
01711 QWidget::hideEvent(e);
01712 }
01713
01714 void KLFMainWin::showEvent(QShowEvent *e)
01715 {
01716 if ( _firstshow ) {
01717 _firstshow = false;
01718
01719
01720 if ( klfconfig.Core.thisVersionMajMinFirstRun ) {
01721 QMetaObject::invokeMethod(this, "showWhatsNew", Qt::QueuedConnection);
01722 }
01723 }
01724
01725 if ( ! e->spontaneous() ) {
01726
01727 if (pLastWindowGeometries.contains(this))
01728 klf_set_window_geometry(this, pLastWindowGeometries[this]);
01729 setWindowShownStatus(pSavedWindowShownStatus);
01730 }
01731
01732 QWidget::showEvent(e);
01733 }
01734
01735
01736 void KLFMainWin::timerEvent(QTimerEvent *e)
01737 {
01738 if (e->timerId() == pExportMsgLabelTimerId) {
01739 int total = mExportMsgLabel->property("timeTotal").toInt();
01740 int remaining = mExportMsgLabel->property("timeRemaining").toInt();
01741 int interval = mExportMsgLabel->property("timeInterval").toInt();
01742
01743 int fadepercent = (100 * remaining / total) * 3;
01744 if (fadepercent < 100 && fadepercent >= 0) {
01745 QPalette pal = mExportMsgLabel->property("defaultPalette").value<QPalette>();
01746 QColor c = pal.color(QPalette::Window);
01747 c.setAlpha(c.alpha() * fadepercent / 100);
01748 pal.setColor(QPalette::Window, c);
01749 QColor c2 = pal.color(QPalette::WindowText);
01750 c2.setAlpha(c2.alpha() * fadepercent / 100);
01751 pal.setColor(QPalette::WindowText, c2);
01752 mExportMsgLabel->setPalette(pal);
01753 }
01754
01755 remaining -= interval;
01756 if (remaining < 0) {
01757 mExportMsgLabel->hide();
01758 killTimer(pExportMsgLabelTimerId);
01759 pExportMsgLabelTimerId = -1;
01760 } else {
01761 mExportMsgLabel->setProperty("timeRemaining", QVariant(remaining));
01762 }
01763 }
01764 }
01765
01766
01767
01768 void KLFMainWin::alterSetting(altersetting_which which, int ivalue)
01769 {
01770 _settings_altered = true;
01771 switch (which) {
01772 case altersetting_LBorderOffset:
01773 _settings.lborderoffset = ivalue; break;
01774 case altersetting_TBorderOffset:
01775 _settings.tborderoffset = ivalue; break;
01776 case altersetting_RBorderOffset:
01777 _settings.rborderoffset = ivalue; break;
01778 case altersetting_BBorderOffset:
01779 _settings.bborderoffset = ivalue; break;
01780 case altersetting_OutlineFonts:
01781 _settings.outlineFonts = (bool)ivalue; break;
01782 default:
01783 break;
01784 }
01785 }
01786 void KLFMainWin::alterSetting(altersetting_which which, QString svalue)
01787 {
01788 _settings_altered = true;
01789 switch (which) {
01790 case altersetting_TempDir:
01791 _settings.tempdir = svalue; break;
01792 case altersetting_Latex:
01793 _settings.latexexec = svalue; break;
01794 case altersetting_Dvips:
01795 _settings.dvipsexec = svalue; break;
01796 case altersetting_Gs:
01797 _settings.gsexec = svalue; break;
01798 case altersetting_Epstopdf:
01799 _settings.epstopdfexec = svalue; break;
01800 default:
01801 break;
01802 }
01803 }
01804
01805
01806 KLFLatexEdit *KLFMainWin::latexEdit()
01807 {
01808 return u->txtLatex;
01809 }
01810 KLFLatexSyntaxHighlighter * KLFMainWin::syntaxHighlighter()
01811 {
01812 return u->txtLatex->syntaxHighlighter();
01813 }
01814 KLFLatexSyntaxHighlighter * KLFMainWin::preambleSyntaxHighlighter()
01815 {
01816 return u->txtPreamble->syntaxHighlighter();
01817 }
01818
01819
01820
01821
01822
01823 void KLFMainWin::applySettings(const KLFBackend::klfSettings& s)
01824 {
01825 _settings = s;
01826 _settings_altered = false;
01827 }
01828
01829 void KLFMainWin::displayError(const QString& error)
01830 {
01831 QMessageBox::critical(this, tr("Error"), error);
01832 }
01833
01834
01835 void KLFMainWin::updatePreviewBuilderThreadInput()
01836 {
01837 bool reallyinputchanged = mPreviewBuilderThread->inputChanged(collectInput(false));
01838 if (reallyinputchanged) {
01839 _evaloutput_uptodate = false;
01840 }
01841 }
01842
01843 void KLFMainWin::setTxtLatexFont(const QFont& f)
01844 {
01845 u->txtLatex->setFont(f);
01846 }
01847 void KLFMainWin::setTxtPreambleFont(const QFont& f)
01848 {
01849 u->txtPreamble->setFont(f);
01850 }
01851
01852 void KLFMainWin::showRealTimePreview(const QImage& preview, bool latexerror)
01853 {
01854 klfDbg("preview.size=" << preview.size()<< " latexerror=" << latexerror);
01855 if (_evaloutput_uptodate)
01856 return;
01857
01858 if (latexerror)
01859 u->lblOutput->displayError(false);
01860 else
01861 u->lblOutput->display(preview, preview, false);
01862
01863 }
01864
01865 KLFBackend::klfInput KLFMainWin::collectInput(bool final)
01866 {
01867
01868 KLFBackend::klfInput input;
01869
01870 input.latex = u->txtLatex->toPlainText();
01871 if (u->chkMathMode->isChecked()) {
01872 input.mathmode = u->cbxMathMode->currentText();
01873 if (final && u->cbxMathMode->findText(input.mathmode) == -1) {
01874 u->cbxMathMode->addItem(input.mathmode);
01875 klfconfig.UI.customMathModes.append(input.mathmode);
01876 }
01877 } else {
01878 input.mathmode = "...";
01879 }
01880 input.preamble = u->txtPreamble->toPlainText();
01881 input.fg_color = u->colFg->color().rgb();
01882 if (u->chkBgTransparent->isChecked() == false)
01883 input.bg_color = u->colBg->color().rgb();
01884 else
01885 input.bg_color = qRgba(255, 255, 255, 0);
01886
01887 input.dpi = u->spnDPI->value();
01888
01889 return input;
01890 }
01891
01892 void KLFMainWin::slotEvaluate()
01893 {
01894
01895 KLFBackend::klfInput input;
01896
01897 u->btnEvaluate->setEnabled(false);
01898
01899
01900 input = collectInput(true);
01901
01902 KLFBackend::klfSettings settings = _settings;
01903
01904 if (u->gbxOverrideMargins->isChecked()) {
01905 settings.tborderoffset = u->spnMarginTop->valueInRefUnit();
01906 settings.rborderoffset = u->spnMarginRight->valueInRefUnit();
01907 settings.bborderoffset = u->spnMarginBottom->valueInRefUnit();
01908 settings.lborderoffset = u->spnMarginLeft->valueInRefUnit();
01909 }
01910
01911
01912 _output = KLFBackend::getLatexFormula(input, settings);
01913
01914 if (_output.status < 0) {
01915 QString comment = "";
01916 bool showSettingsPaths = false;
01917 if (_output.status == KLFERR_NOLATEXPROG ||
01918 _output.status == KLFERR_NODVIPSPROG ||
01919 _output.status == KLFERR_NOGSPROG ||
01920 _output.status == KLFERR_NOEPSTOPDFPROG) {
01921 comment = "\n"+tr("Are you sure you configured your system paths correctly in the settings dialog ?");
01922 showSettingsPaths = true;
01923 }
01924 QMessageBox::critical(this, tr("Error"), _output.errorstr+comment);
01925 u->lblOutput->displayClear();
01926 u->frmOutput->setEnabled(false);
01927 if (showSettingsPaths) {
01928 mSettingsDialog->show();
01929 mSettingsDialog->showControl(KLFSettings::ExecutablePaths);
01930 }
01931 }
01932 if (_output.status > 0) {
01933 KLFProgErr::showError(this, _output.errorstr);
01934 u->frmOutput->setEnabled(false);
01935 }
01936 if (_output.status == 0) {
01937
01938 _evaloutput_uptodate = true;
01939
01940 QPixmap sc;
01941
01942 QSize fsize = klfconfig.UI.labelOutputFixedSize;
01943 if (_output.result.width() > fsize.width() || _output.result.height() > fsize.height())
01944 sc = QPixmap::fromImage(_output.result.scaled(fsize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
01945 else
01946 sc = QPixmap::fromImage(_output.result);
01947
01948 QSize goodsize = _output.result.size();
01949 QImage tooltipimg = _output.result;
01950 if ( klfconfig.UI.previewTooltipMaxSize != QSize(0, 0) &&
01951 ( tooltipimg.width() > klfconfig.UI.previewTooltipMaxSize.width() ||
01952 tooltipimg.height() > klfconfig.UI.previewTooltipMaxSize.height() ) ) {
01953 tooltipimg =
01954 _output.result.scaled(klfconfig.UI.previewTooltipMaxSize, Qt::KeepAspectRatio,
01955 Qt::SmoothTransformation);
01956 }
01957 emit evaluateFinished(_output);
01958 u->lblOutput->display(sc.toImage(), tooltipimg, true);
01959 u->frmOutput->setEnabled(true);
01960
01961 KLFLibEntry newentry = KLFLibEntry(input.latex, QDateTime::currentDateTime(), sc.toImage(),
01962 currentStyle());
01963
01964 bool needInsertThisEntry = true;
01965 KLFLibResourceEngine::Query query;
01966 query.matchCondition = KLFLib::EntryMatchCondition::mkMatchAll();
01967 query.skip = 0;
01968 query.limit = 1;
01969 query.orderPropId = KLFLibEntry::DateTime;
01970 query.orderDirection = Qt::DescendingOrder;
01971 query.wantedEntryProperties =
01972 QList<int>() << KLFLibEntry::Latex << KLFLibEntry::Style << KLFLibEntry::Category << KLFLibEntry::Tags;
01973 KLFLibResourceEngine::QueryResult queryResult(KLFLibResourceEngine::QueryResult::FillRawEntryList);
01974 int num = mHistoryLibResource->query(mHistoryLibResource->defaultSubResource(), query, &queryResult);
01975 if (num >= 1) {
01976 KLFLibEntry e = queryResult.rawEntryList[0];
01977 if (e.latex() == newentry.latex() &&
01978 e.category() == newentry.category() &&
01979 e.tags() == newentry.tags() &&
01980 e.style() == newentry.style())
01981 needInsertThisEntry = false;
01982 }
01983
01984 if (needInsertThisEntry) {
01985 int eid = mHistoryLibResource->insertEntry(newentry);
01986 bool result = (eid >= 0);
01987 if ( ! result && mHistoryLibResource->locked() ) {
01988 int r = QMessageBox::warning(this, tr("Warning"),
01989 tr("Can't add the item to history library because the history "
01990 "resource is locked. Do you want to unlock it?"),
01991 QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes);
01992 if (r == QMessageBox::Yes) {
01993 mHistoryLibResource->setLocked(false);
01994 result = mHistoryLibResource->insertEntry(newentry);
01995 }
01996 }
01997 uint fl = mHistoryLibResource->supportedFeatureFlags();
01998 if ( ! result && (fl & KLFLibResourceEngine::FeatureSubResources) &&
01999 (fl & KLFLibResourceEngine::FeatureSubResourceProps) &&
02000 mHistoryLibResource->subResourceProperty(mHistoryLibResource->defaultSubResource(),
02001 KLFLibResourceEngine::SubResPropLocked).toBool() ) {
02002 int r = QMessageBox::warning(this, tr("Warning"),
02003 tr("Can't add the item to history library because the history "
02004 "sub-resource is locked. Do you want to unlock it?"),
02005 QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes);
02006 if (r == QMessageBox::Yes) {
02007 mHistoryLibResource->setSubResourceProperty(mHistoryLibResource->defaultSubResource(),
02008 KLFLibResourceEngine::SubResPropLocked, false);
02009 result = mHistoryLibResource->insertEntry(newentry);
02010 }
02011 }
02012 if ( ! result && mHistoryLibResource->isReadOnly() ) {
02013 qWarning("KLFMainWin::slotEvaluate: History resource is READ-ONLY !! Should NOT!");
02014 QMessageBox::critical(this, tr("Error"),
02015 tr("Can't add the item to history library because the history "
02016 "resource is opened in read-only mode. This should not happen! "
02017 "You will need to manually copy and paste your Latex code somewhere "
02018 "else to save it."),
02019 QMessageBox::Ok, QMessageBox::Ok);
02020 }
02021 if ( ! result ) {
02022 qWarning("KLFMainWin::slotEvaluate: History resource couldn't be written!");
02023 QMessageBox::critical(this, tr("Error"),
02024 tr("An error occurred when trying to write the new entry into the "
02025 "history resource!"
02026 "You will need to manually copy and paste your Latex code somewhere "
02027 "else to save it."),
02028 QMessageBox::Ok, QMessageBox::Ok);
02029 }
02030 }
02031 }
02032
02033 u->btnEvaluate->setEnabled(true);
02034 u->btnEvaluate->setFocus();
02035 }
02036
02037 void KLFMainWin::slotClearLatex()
02038 {
02039 u->txtLatex->clearLatex();
02040 }
02041 void KLFMainWin::slotClearAll()
02042 {
02043 slotClearLatex();
02044 loadDefaultStyle();
02045 }
02046
02047
02048 void KLFMainWin::slotLibrary(bool showlib)
02049 {
02050 klfDbg("showlib="<<showlib) ;
02051 mLibBrowser->setShown(showlib);
02052 if (showlib) {
02053
02054 mLibBrowser->activateWindow();
02055 mLibBrowser->raise();
02056 }
02057 }
02058
02059 void KLFMainWin::slotSymbols(bool showsymbs)
02060 {
02061 mLatexSymbols->setShown(showsymbs);
02062 slotSymbolsButtonRefreshState(showsymbs);
02063 mLatexSymbols->activateWindow();
02064 mLatexSymbols->raise();
02065 }
02066
02067 void KLFMainWin::slotExpandOrShrink()
02068 {
02069 if (u->frmDetails->isVisible()) {
02070 u->frmDetails->hide();
02071 setFixedSize(_shrinkedsize);
02072
02073 u->btnExpand->setIcon(QIcon(":/pics/switchexpanded.png"));
02074 } else {
02075 setFixedSize(_expandedsize);
02076 u->frmDetails->show();
02077
02078 u->btnExpand->setIcon(QIcon(":/pics/switchshrinked.png"));
02079 }
02080 }
02081 void KLFMainWin::slotExpand(bool expanded)
02082 {
02083 if (u->frmDetails->isVisible() == expanded)
02084 return;
02085
02086 slotExpandOrShrink();
02087 }
02088
02089
02090 void KLFMainWin::slotSetLatex(const QString& latex)
02091 {
02092 u->txtLatex->setLatex(latex);
02093 }
02094
02095 void KLFMainWin::slotSetMathMode(const QString& mathmode)
02096 {
02097 u->chkMathMode->setChecked(mathmode.simplified() != "...");
02098 if (mathmode.simplified() != "...")
02099 u->cbxMathMode->setEditText(mathmode);
02100 }
02101
02102 void KLFMainWin::slotSetPreamble(const QString& preamble)
02103 {
02104 u->txtPreamble->setLatex(preamble);
02105 }
02106
02107 void KLFMainWin::slotEnsurePreambleCmd(const QString& line)
02108 {
02109 QTextCursor c = u->txtPreamble->textCursor();
02110
02111 c.beginEditBlock();
02112 c.movePosition(QTextCursor::End);
02113
02114 QString preambletext = u->txtPreamble->toPlainText();
02115 if (preambletext.indexOf(line) == -1) {
02116 QString addtext = "";
02117 if (preambletext.length() > 0 &&
02118 preambletext[preambletext.length()-1] != '\n')
02119 addtext = "\n";
02120 addtext += line;
02121 c.insertText(addtext);
02122 preambletext += addtext;
02123 }
02124
02125 c.endEditBlock();
02126 }
02127
02128 void KLFMainWin::slotSetDPI(int DPI)
02129 {
02130 u->spnDPI->setValue(DPI);
02131 }
02132
02133 void KLFMainWin::slotSetFgColor(const QColor& fg)
02134 {
02135 u->colFg->setColor(fg);
02136 }
02137 void KLFMainWin::slotSetFgColor(const QString& s)
02138 {
02139 QColor fgcolor;
02140 fgcolor.setNamedColor(s);
02141 slotSetFgColor(fgcolor);
02142 }
02143 void KLFMainWin::slotSetBgColor(const QColor& bg)
02144 {
02145 u->colBg->setColor(bg);
02146 }
02147 void KLFMainWin::slotSetBgColor(const QString& s)
02148 {
02149 QColor bgcolor;
02150 if (s == "-")
02151 bgcolor.setRgb(255, 255, 255, 0);
02152 else
02153 bgcolor.setNamedColor(s);
02154 slotSetBgColor(bgcolor);
02155 }
02156
02157 void KLFMainWin::slotEvaluateAndSave(const QString& output, const QString& format)
02158 {
02159 if ( u->txtLatex->toPlainText().isEmpty() )
02160 return;
02161
02162 slotEvaluate();
02163
02164 if ( ! output.isEmpty() ) {
02165 if ( _output.result.isNull() ) {
02166 QMessageBox::critical(this, tr("Error"), tr("There is no image to save."));
02167 } else {
02168 KLFBackend::saveOutputToFile(_output, output, format.trimmed().toUpper());
02169 }
02170 }
02171
02172 }
02173
02174
02175
02176
02177 static QString find_list_agreement(const QStringList& a, const QStringList& b)
02178 {
02179
02180
02181 int i, j;
02182 for (i = 0; i < a.size(); ++i)
02183 for (j = 0; j < b.size(); ++j)
02184 if (a[i] == b[j])
02185 return a[i];
02186 return QString();
02187 }
02188
02189 bool KLFMainWin::canOpenFile(const QString& fileName)
02190 {
02191 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
02192 klfDbg("file name="<<fileName) ;
02193 int k;
02194 for (k = 0; k < pDataOpeners.size(); ++k)
02195 if (pDataOpeners[k]->canOpenFile(fileName))
02196 return true;
02197 klfDbg("cannot open file.") ;
02198 return false;
02199 }
02200 bool KLFMainWin::canOpenData(const QByteArray& data)
02201 {
02202 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
02203 klfDbg("data. length="<<data.size()) ;
02204 int k;
02205 for (k = 0; k < pDataOpeners.size(); ++k)
02206 if (pDataOpeners[k]->canOpenData(data))
02207 return true;
02208 klfDbg("cannot open data.") ;
02209 return false;
02210 }
02211 bool KLFMainWin::canOpenData(const QMimeData *mimeData)
02212 {
02213 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
02214 QStringList formats = mimeData->formats();
02215 klfDbg("mime data. formats="<<formats) ;
02216
02217 QString mimetype;
02218 int k;
02219 for (k = 0; k < pDataOpeners.size(); ++k) {
02220 mimetype = find_list_agreement(formats, pDataOpeners[k]->supportedMimeTypes());
02221 if (!mimetype.isEmpty())
02222 return true;
02223 }
02224 klfDbg("cannot open data: no appropriate opener found.") ;
02225 return false;
02226 }
02227
02228
02229 bool KLFMainWin::openFile(const QString& file)
02230 {
02231 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02232 klfDbg("file="<<file) ;
02233 int k;
02234 for (k = 0; k < pDataOpeners.size(); ++k)
02235 if (pDataOpeners[k]->openFile(file))
02236 return true;
02237
02238 QMessageBox::critical(this, tr("Error"), tr("Failed to load file %1.").arg(file));
02239
02240 return false;
02241 }
02242
02243 bool KLFMainWin::openFiles(const QStringList& fileList)
02244 {
02245 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02246 klfDbg("file list="<<fileList) ;
02247 int k;
02248 bool result = true;
02249 for (k = 0; k < fileList.size(); ++k) {
02250 result = result && openFile(fileList[k]);
02251 klfDbg("Opened file "<<fileList[k]<<": result="<<result) ;
02252 }
02253 return result;
02254 }
02255
02256 bool KLFMainWin::openData(const QMimeData *mimeData, bool *openerFound)
02257 {
02258 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02259 klfDbg("mime data, formats="<<mimeData->formats()) ;
02260 int k;
02261 QString mimetype;
02262 QStringList fmts = mimeData->formats();
02263 if (openerFound != NULL)
02264 *openerFound = false;
02265 for (k = 0; k < pDataOpeners.size(); ++k) {
02266 mimetype = find_list_agreement(fmts, pDataOpeners[k]->supportedMimeTypes());
02267 if (!mimetype.isEmpty()) {
02268 if (openerFound != NULL)
02269 *openerFound = true;
02270
02271 klfDbg("Opening mimetype "<<mimetype) ;
02272 QByteArray data = mimeData->data(mimetype);
02273 if (pDataOpeners[k]->openData(data, mimetype))
02274 return true;
02275 }
02276 }
02277
02278 return false;
02279 }
02280 bool KLFMainWin::openData(const QByteArray& data)
02281 {
02282 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02283 klfDbg("data, len="<<data.length()) ;
02284 int k;
02285 for (k = 0; k < pDataOpeners.size(); ++k)
02286 if (pDataOpeners[k]->openData(data, QString()))
02287 return true;
02288
02289 return false;
02290 }
02291
02292
02293 bool KLFMainWin::openLibFiles(const QStringList& files, bool showLibrary)
02294 {
02295 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02296 int k;
02297 bool imported = false;
02298 for (k = 0; k < files.size(); ++k) {
02299 bool ok = openLibFile(files[k], false);
02300 imported = imported || ok;
02301 klfDbg("imported file "<<files[k]<<": imported status is now "<<imported) ;
02302 }
02303 if (showLibrary && imported)
02304 slotLibrary(true);
02305 return imported;
02306 }
02307
02308 bool KLFMainWin::openLibFile(const QString& fname, bool showLibrary)
02309 {
02310 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02311 klfDbg("fname="<<fname<<"; showLibrary="<<showLibrary) ;
02312 QUrl url = QUrl::fromLocalFile(fname);
02313 QString scheme = KLFLibBasicWidgetFactory::guessLocalFileScheme(fname);
02314 if (scheme.isEmpty()) {
02315 klfDbg("Can't guess scheme for file "<<fname) ;
02316 return false;
02317 }
02318 url.setScheme(scheme);
02319 klfDbg("url to open is "<<url) ;
02320 QStringList subreslist = KLFLibEngineFactory::listSubResources(url);
02321 if ( subreslist.isEmpty() ) {
02322 klfDbg("no sub-resources...") ;
02323
02324 return mLibBrowser->openResource(url);
02325 }
02326 klfDbg("subreslist is "<<subreslist);
02327 bool loaded = false;
02328 int k;
02329 for (k = 0; k < subreslist.size(); ++k) {
02330 QUrl url2 = url;
02331 url2.addQueryItem("klfDefaultSubResource", subreslist[k]);
02332 bool thisloaded = mLibBrowser->openResource(url2);
02333 loaded = loaded || thisloaded;
02334 }
02335 if (showLibrary && loaded)
02336 slotLibrary(true);
02337 return loaded;
02338 }
02339
02340
02341 void KLFMainWin::setApplicationLocale(const QString& locale)
02342 {
02343 klf_reload_translations(qApp, locale);
02344
02345 emit applicationLocaleChanged(locale);
02346 }
02347
02348 void KLFMainWin::slotSetExportProfile(const QString& exportProfile)
02349 {
02350 if (klfconfig.UI.menuExportProfileAffectsCopy)
02351 klfconfig.UI.copyExportProfile = exportProfile;
02352 if (klfconfig.UI.menuExportProfileAffectsDrag)
02353 klfconfig.UI.dragExportProfile = exportProfile;
02354 saveSettings();
02355 }
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388 void KLFMainWin::slotDrag()
02389 {
02390 if ( _output.result.isNull() )
02391 return;
02392
02393 QDrag *drag = new QDrag(this);
02394 KLFMimeData *mime = new KLFMimeData(klfconfig.UI.dragExportProfile, _output);
02395
02396
02397
02398
02399
02400
02401 drag->setMimeData(mime);
02402
02403 QSize sz = QSize(200, 100);
02404 QImage img = _output.result;
02405 if (img.width() > sz.width() || img.height() > sz.height())
02406 img = img.scaled(sz, Qt::KeepAspectRatio, Qt::SmoothTransformation);
02407
02408 QString exportProfileText = KLFMimeExportProfile::findExportProfile(klfconfig.UI.dragExportProfile).description();
02409 { QPainter painter(&img);
02410 QFont smallfont = QFont("Helvetica", 8);
02411 smallfont.setPixelSize(12);
02412 painter.setFont(smallfont);
02413 painter.setRenderHint(QPainter::TextAntialiasing, false);
02414 QRect rall = QRect(QPoint(0,0), img.size());
02415 QRect bb = painter.boundingRect(rall, Qt::AlignBottom|Qt::AlignRight, exportProfileText);
02416 klfDbg("BB is "<<bb) ;
02417 painter.setPen(QPen(QColor(255,255,255,0), 0, Qt::NoPen));
02418 painter.fillRect(bb, QColor(150,150,150,128));
02419 painter.setPen(QPen(QColor(0,0,0), 1, Qt::SolidLine));
02420 painter.drawText(rall, Qt::AlignBottom|Qt::AlignRight, exportProfileText);
02421
02422
02423
02424
02425
02426
02427
02428 }
02429 QPixmap p = QPixmap::fromImage(img);
02430 drag->setPixmap(p);
02431 drag->setDragCursor(p, Qt::MoveAction);
02432 drag->setHotSpot(QPoint(p.width()/2, p.height()));
02433 drag->exec(Qt::CopyAction);
02434 }
02435
02436 void KLFMainWin::slotCopy()
02437 {
02438 #ifdef Q_WS_WIN
02439 extern void klfWinClipboardCopy(HWND h, const QStringList& wintypes,
02440 const QList<QByteArray>& datalist);
02441
02442 QString profilename = klfconfig.UI.copyExportProfile;
02443 KLFMimeExportProfile p = KLFMimeExportProfile::findExportProfile(profilename);
02444
02445 QStringList mimetypes = p.mimeTypes();
02446 QStringList wintypes;
02447 QList<QByteArray> datalist;
02448
02449 int k;
02450 for (k = 0; k < mimetypes.size(); ++k) {
02451 QString mimetype = mimetypes[k];
02452 QString wintype = p.respectiveWinType(k);
02453 if (wintype.isEmpty())
02454 wintype = mimetype;
02455 KLFMimeExporter *exporter = KLFMimeExporter::mimeExporterLookup(mimetype);
02456 if (exporter == NULL) {
02457 qWarning()<<KLF_FUNC_NAME<<": Can't find exporter for type "<<mimetype
02458 <<", winformat="<<wintype<<".";
02459 continue;
02460 }
02461 QByteArray data = exporter->data(mimetype, _output);
02462 wintypes << wintype;
02463 datalist << data;
02464 }
02465
02466 klfWinClipboardCopy(winId(), wintypes, datalist);
02467
02468 #else
02469 KLFMimeData *mimedata = new KLFMimeData(klfconfig.UI.copyExportProfile, _output);
02470 QApplication::clipboard()->setMimeData(mimedata, QClipboard::Clipboard);
02471 #endif
02472
02473 KLFMimeExportProfile profile = KLFMimeExportProfile::findExportProfile(klfconfig.UI.copyExportProfile);
02474 showExportMsgLabel(tr("Copied as <b>%1</b>").arg(profile.description()));
02475 }
02476
02477 void KLFMainWin::slotSave(const QString& suggestfname)
02478 {
02479
02480 static QString selectedfilter;
02481
02482 QStringList formatlist, filterformatlist;
02483 QMap<QString,QString> formatsByFilterName;
02484 QList<QByteArray> formats = QImageWriter::supportedImageFormats();
02485
02486 for (QList<QByteArray>::iterator it = formats.begin(); it != formats.end(); ++it) {
02487 QString f = (*it).toLower();
02488 if (f == "jpg" || f == "jpeg" || f == "png" || f == "pdf" || f == "eps")
02489 continue;
02490 QString s = tr("%1 Image (*.%2)").arg(f).arg(f);
02491 filterformatlist << s;
02492 formatlist.push_back(f);
02493 formatsByFilterName[s] = f;
02494 }
02495
02496 QMap<QString,QString> externFormatsByFilterName;
02497 QMap<QString,KLFAbstractOutputSaver*> externSaverByKey;
02498 int k, j;
02499 for (k = 0; k < pOutputSavers.size(); ++k) {
02500 QStringList xoformats = pOutputSavers[k]->supportedMimeFormats();
02501 for (j = 0; j < xoformats.size(); ++j) {
02502 QString f = QString("%1 (%2)").arg(pOutputSavers[k]->formatTitle(xoformats[j]),
02503 pOutputSavers[k]->formatFilePatterns(xoformats[j]).join(" "));
02504 filterformatlist << f;
02505 externFormatsByFilterName[f] = xoformats[j];
02506 externSaverByKey[xoformats[j]] = pOutputSavers[k];
02507 }
02508 }
02509
02510 QString s;
02511 s = tr("EPS PostScript (*.eps)");
02512 filterformatlist.push_front(s);
02513 formatlist.push_front("eps");
02514 formatsByFilterName[s] = "eps";
02515 s = tr("PDF Portable Document Format (*.pdf)");
02516 filterformatlist.push_front(s);
02517 formatlist.push_front("pdf");
02518 formatsByFilterName[s] = "pdf";
02519 s = tr("Standard JPEG Image (*.jpg *.jpeg)");
02520 filterformatlist.push_front(s);
02521 formatlist.push_front("jpeg");
02522 formatlist.push_front("jpg");
02523 formatsByFilterName[s] = "jpeg";
02524 selectedfilter = s = tr("Standard PNG Image (*.png)");
02525 filterformatlist.push_front(s);
02526 formatlist.push_front("png");
02527 formatsByFilterName[s] = "png";
02528
02529 QString filterformat = filterformatlist.join(";;");
02530 QString fname, format;
02531
02532 QString suggestion = suggestfname;
02533 if (suggestion.isEmpty())
02534 suggestion = klfconfig.UI.lastSaveDir;
02535 if (suggestion.isEmpty())
02536 suggestion = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
02537
02538 fname = QFileDialog::getSaveFileName(this, tr("Save Image Formula"), suggestion, filterformat,
02539 &selectedfilter);
02540
02541 if (fname.isEmpty())
02542 return;
02543
02544
02545 if ( externFormatsByFilterName.contains(selectedfilter) ) {
02546
02547 QString key = externFormatsByFilterName[selectedfilter];
02548 if ( ! externSaverByKey.contains(key) ) {
02549 qWarning()<<KLF_FUNC_NAME<<": Internal error: externSaverByKey() does not contain key="<<key
02550 <<": "<<externSaverByKey;
02551 return;
02552 }
02553 KLFAbstractOutputSaver *saver = externSaverByKey[key];
02554 if (saver == NULL) {
02555 qWarning()<<KLF_FUNC_NAME<<": Internal error: saver is NULL!";
02556 return;
02557 }
02558 bool result = saver->saveToFile(key, fname, _output);
02559 if (!result)
02560 qWarning()<<KLF_FUNC_NAME<<": saver failed to save format "<<key<<".";
02561 return;
02562 }
02563
02564 QFileInfo fi(fname);
02565 klfconfig.UI.lastSaveDir = fi.absolutePath();
02566 if ( fi.suffix().length() == 0 ) {
02567
02568 if ( ! formatsByFilterName.contains(selectedfilter) && ! externFormatsByFilterName.contains(selectedfilter) ) {
02569 qWarning("%s: ERROR: Unknown format filter selected: `%s'! Assuming PNG!\n", KLF_FUNC_NAME,
02570 qPrintable(selectedfilter));
02571 format = "png";
02572 } else {
02573 format = formatsByFilterName[selectedfilter];
02574 }
02575 fname += "."+format;
02576
02577 if (QFile::exists(fname)) {
02578 int r = QMessageBox::warning(this, tr("File Exists"),
02579 tr("The file <b>%1</b> already exists.\nOverwrite?").arg(fname),
02580 QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel, QMessageBox::No);
02581 if (r == QMessageBox::Yes) {
02582
02583 } else if (r == QMessageBox::No) {
02584
02585 slotSave(fname);
02586 return;
02587 } else {
02588
02589 return;
02590 }
02591 }
02592 }
02593 fi.setFile(fname);
02594 int index = formatlist.indexOf(fi.suffix().toLower());
02595 if ( index < 0 ) {
02596
02597 QMessageBox msgbox(this);
02598 msgbox.setIcon(QMessageBox::Warning);
02599 msgbox.setWindowTitle(tr("Extension not recognized"));
02600 msgbox.setText(tr("Extension <b>%1</b> not recognized.").arg(fi.suffix().toUpper()));
02601 msgbox.setInformativeText(tr("Press \"Change\" to change the file name, or \"Use PNG\" to save as PNG."));
02602 QPushButton *png = new QPushButton(tr("Use PNG"), &msgbox);
02603 msgbox.addButton(png, QMessageBox::AcceptRole);
02604 QPushButton *chg = new QPushButton(tr("Change ..."), &msgbox);
02605 msgbox.addButton(chg, QMessageBox::ActionRole);
02606 QPushButton *cancel = new QPushButton(tr("Cancel"), &msgbox);
02607 msgbox.addButton(cancel, QMessageBox::RejectRole);
02608 msgbox.setDefaultButton(chg);
02609 msgbox.setEscapeButton(cancel);
02610 msgbox.exec();
02611 if (msgbox.clickedButton() == png) {
02612 format = "png";
02613 } else if (msgbox.clickedButton() == cancel) {
02614 return;
02615 } else {
02616
02617 slotSave(fname);
02618 return;
02619 }
02620 } else {
02621 format = formatlist[index];
02622 }
02623
02624
02625
02626 QString error;
02627 bool res = KLFBackend::saveOutputToFile(_output, fname, format, &error);
02628 if ( ! res ) {
02629 QMessageBox::critical(this, tr("Error"), error);
02630 }
02631 }
02632
02633
02634 void KLFMainWin::slotActivateEditor()
02635 {
02636 raise();
02637 activateWindow();
02638 u->txtLatex->setFocus();
02639 }
02640
02641 void KLFMainWin::slotActivateEditorSelectAll()
02642 {
02643 slotActivateEditor();
02644 u->txtLatex->selectAll();
02645 }
02646
02647 void KLFMainWin::slotShowBigPreview()
02648 {
02649 if ( ! u->btnShowBigPreview->isEnabled() )
02650 return;
02651
02652 QString text =
02653 tr("<p>%1</p><p align=\"right\" style=\"font-size: %2pt; font-style: italic;\">"
02654 "This preview can be opened with the <strong>F2</strong> key. Hit "
02655 "<strong>Esc</strong> to close.</p>")
02656 .arg(u->lblOutput->bigPreviewText())
02657 .arg(QFontInfo(qApp->font()).pointSize()-1);
02658 QWhatsThis::showText(u->btnEvaluate->pos(), text, u->lblOutput);
02659 }
02660
02661
02662
02663 void KLFMainWin::slotPresetDPISender()
02664 {
02665 QAction *a = qobject_cast<QAction*>(sender());
02666 if (a) {
02667 slotSetDPI(a->data().toInt());
02668 }
02669 }
02670
02671
02672 KLFStyle KLFMainWin::currentStyle() const
02673 {
02674 KLFStyle sty;
02675
02676 sty.name = QString::null;
02677 sty.fg_color = u->colFg->color().rgb();
02678 QColor bgc = u->colBg->color();
02679 sty.bg_color = qRgba(bgc.red(), bgc.green(), bgc.blue(), u->chkBgTransparent->isChecked() ? 0 : 255 );
02680 sty.mathmode = (u->chkMathMode->isChecked() ? u->cbxMathMode->currentText() : "...");
02681 sty.preamble = u->txtPreamble->toPlainText();
02682 sty.dpi = u->spnDPI->value();
02683
02684 if (u->gbxOverrideMargins->isChecked()) {
02685 sty.overrideBBoxExpand.top = u->spnMarginTop->valueInRefUnit();
02686 sty.overrideBBoxExpand.right = u->spnMarginRight->valueInRefUnit();
02687 sty.overrideBBoxExpand.bottom = u->spnMarginBottom->valueInRefUnit();
02688 sty.overrideBBoxExpand.left = u->spnMarginLeft->valueInRefUnit();
02689 }
02690
02691 return sty;
02692 }
02693
02694 QFont KLFMainWin::txtLatexFont() const
02695 {
02696 return u->txtLatex->font();
02697 }
02698 QFont KLFMainWin::txtPreambleFont() const
02699 {
02700 return u->txtPreamble->font();
02701 }
02702
02703 void KLFMainWin::slotLoadStyleAct()
02704 {
02705 QAction *a = qobject_cast<QAction*>(sender());
02706 if (a) {
02707 slotLoadStyle(a->data().toInt());
02708 }
02709 }
02710
02711 void KLFMainWin::slotLoadStyle(const KLFStyle& style)
02712 {
02713 QColor cfg, cbg;
02714 cfg.setRgb(style.fg_color);
02715 cbg.setRgb(style.bg_color);
02716 u->colFg->setColor(cfg);
02717 u->colBg->setColor(cbg);
02718 u->chkBgTransparent->setChecked(qAlpha(style.bg_color) == 0);
02719 u->chkMathMode->setChecked(style.mathmode.simplified() != "...");
02720 if (style.mathmode.simplified() != "...")
02721 u->cbxMathMode->setEditText(style.mathmode);
02722 slotSetPreamble(style.preamble);
02723 u->spnDPI->setValue(style.dpi);
02724
02725 if (style.overrideBBoxExpand.valid()) {
02726 u->gbxOverrideMargins->setChecked(true);
02727 u->spnMarginTop->setValueInRefUnit(style.overrideBBoxExpand.top);
02728 u->spnMarginRight->setValueInRefUnit(style.overrideBBoxExpand.right);
02729 u->spnMarginBottom->setValueInRefUnit(style.overrideBBoxExpand.bottom);
02730 u->spnMarginLeft->setValueInRefUnit(style.overrideBBoxExpand.left);
02731 } else {
02732 u->gbxOverrideMargins->setChecked(false);
02733 }
02734 }
02735
02736 void KLFMainWin::slotLoadStyle(int n)
02737 {
02738 if (n < 0 || n >= (int)_styles.size())
02739 return;
02740
02741 slotLoadStyle(_styles[n]);
02742 }
02743 void KLFMainWin::slotSaveStyle()
02744 {
02745 KLFStyle sty;
02746
02747 QString name = QInputDialog::getText(this, tr("Enter Style Name"),
02748 tr("Enter new style name:"));
02749 if (name.isEmpty()) {
02750 return;
02751 }
02752
02753
02754 int found_i = -1;
02755 for (int kl = 0; found_i == -1 && kl < _styles.size(); ++kl) {
02756 if (_styles[kl].name.trimmed() == name.trimmed()) {
02757 found_i = kl;
02758
02759 int r = QMessageBox::question(this, tr("Overwrite Style"),
02760 tr("Style name already exists. Do you want to overwrite?"),
02761 QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel, QMessageBox::No);
02762 switch (r) {
02763 case QMessageBox::No:
02764 slotSaveStyle();
02765 return;
02766 case QMessageBox::Yes:
02767 break;
02768 default:
02769 return;
02770 }
02771 }
02772 }
02773
02774 sty = currentStyle();
02775 sty.name = name;
02776
02777 if (found_i == -1)
02778 _styles.append(sty);
02779 else
02780 _styles[found_i] = sty;
02781
02782 refreshStylePopupMenus();
02783
02784
02785 saveStyles();
02786
02787 emit stylesChanged();
02788 }
02789
02790 void KLFMainWin::slotStyleManager()
02791 {
02792 mStyleManager->show();
02793 }
02794
02795
02796 void KLFMainWin::slotSettings()
02797 {
02798 mSettingsDialog->show();
02799 }
02800
02801
02802 void KLFMainWin::closeEvent(QCloseEvent *event)
02803 {
02804 if (_ignore_close_event) {
02805
02806 hide();
02807
02808 event->ignore();
02809 return;
02810 }
02811
02812 event->accept();
02813 quit();
02814 }
02815
02816
02817
02818