[KLF Application][KLF Tools][KLF Backend][KLF Home]
KLatexFormula Project
klfmainwin_p.h
Go to the documentation of this file.
1 /***************************************************************************
2  * file klfmainwin_p.h
3  * This file is part of the KLatexFormula Project.
4  * Copyright (C) 2011 by Philippe Faist
5  * philippe.faist at bluewin.ch
6  * *
7  * This program is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program; if not, write to the *
19  * Free Software Foundation, Inc., *
20  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21  ***************************************************************************/
22 /* $Id: klfmainwin_p.h 631 2011-04-14 10:14:00Z phfaist $ */
23 
24 #ifndef KLFMAINWIN_P_H
25 #define KLFMAINWIN_P_H
26 
27 
33 #include <QDialog>
34 #include <QFile>
35 #include <QString>
36 #include <QByteArray>
37 #include <QLabel>
38 #include <QImageReader>
39 #include <QBuffer>
40 #include <QFileInfo>
41 #include <QMessageBox>
42 
43 #include <klfutil.h>
44 #include "klflibview.h"
45 #include "klfmain.h"
46 #include "klfsettings.h"
47 
48 #include "klfmainwin.h"
49 
50 #include <ui_klfaboutdialog.h>
51 #include <ui_klfwhatsnewdialog.h>
52 
55 {
56 public:
57  KLFHelpDialogCommon(const QString& baseFName) : pBaseFName(baseFName) { }
58  virtual ~KLFHelpDialogCommon() { }
59 
60  virtual void addExtraText(const QString& htmlSnipplet)
61  {
62  pHtmlExtraSnipplets << htmlSnipplet;
63  }
64 
65  virtual QString getFullHtml()
66  {
67  QString html;
68  QString fn = klfFindTranslatedDataFile(":/data/"+pBaseFName, ".html");
69 
70  QFile f(fn);
71  f.open(QIODevice::ReadOnly);
72  html = QString::fromUtf8(f.readAll());
73 
74  klfDbg( "read from file="<<fn<<" the HTML code=\n"<<html ) ;
75 
76  const QString marker = QLatin1String("<!--KLF_MARKER_INSERT_SPOT-->");
77  int k;
78  for (k = 0; k < pHtmlExtraSnipplets.size(); ++k)
79  html.replace(marker, pHtmlExtraSnipplets[k]+"\n"+marker);
80 
81  klfDbg( "new HTML is:\n"<<html ) ;
82 
83  // replace some general recognized "macros"
84  html.replace("<!--KLF_VERSION-->", KLF_VERSION_STRING);
85 
86  return html;
87  }
88 
89 protected:
92 };
93 
94 
97 {
98  Q_OBJECT
99 signals:
100  void linkActivated(const QUrl&);
101 public:
102  KLFAboutDialog(QWidget *parent) : QDialog(parent), KLFHelpDialogCommon("about")
103  {
104  u = new Ui::KLFAboutDialog;
105  u->setupUi(this);
106 
107  connect(u->txtDisplay, SIGNAL(anchorClicked(const QUrl&)),
108  this, SIGNAL(linkActivated(const QUrl&)));
109  }
110  virtual ~KLFAboutDialog() { }
111 
112  virtual void show()
113  {
114  u->txtDisplay->setHtml(getFullHtml());
115  QDialog::show();
116  // refresh our style sheet
117  setStyleSheet(styleSheet());
118  }
119 
120 private:
121  Ui::KLFAboutDialog *u;
122 };
123 
124 
127 {
128  Q_OBJECT
129 signals:
130  void linkActivated(const QUrl&);
131 public:
133  : QDialog(parent),
134  KLFHelpDialogCommon(QString("whats-new-%1.%2").arg(klfVersionMaj()).arg(klfVersionMin()))
135  {
136  u = new Ui::KLFWhatsNewDialog;
137  u->setupUi(this);
138 
139  connect(u->txtDisplay, SIGNAL(anchorClicked(const QUrl&)),
140  this, SIGNAL(linkActivated(const QUrl&)));
141  }
142  virtual ~KLFWhatsNewDialog() { }
143 
144  virtual void show()
145  {
146  u->txtDisplay->setHtml(getFullHtml());
147  QDialog::show();
148  // refresh our style sheet
149  setStyleSheet(styleSheet());
150  }
151 
152 private:
153  Ui::KLFWhatsNewDialog *u;
154 };
155 
156 
157 
159 class KLFMainWinPopup : public QLabel
160 {
161  Q_OBJECT
162 public:
164  : QLabel(mainwin, Qt::Window|Qt::FramelessWindowHint|Qt::CustomizeWindowHint|
165  Qt::WindowStaysOnTopHint|Qt::X11BypassWindowManagerHint)
166  {
167  setObjectName("KLFMainWinPopup");
168  setFocusPolicy(Qt::NoFocus);
169  QWidget *frmMain = mainwin->findChild<QWidget*>("frmMain");
170  if (frmMain)
171  setGeometry(QRect(mainwin->geometry().topLeft()+QPoint(25,mainwin->height()*2/3),
172  QSize(frmMain->width()+15, 0)));
173  setAttribute(Qt::WA_ShowWithoutActivating, true);
174  setProperty("klfTopLevelWidget", QVariant(true));
175  setAttribute(Qt::WA_StyledBackground, true);
176  setStyleSheet(mainwin->window()->styleSheet());
177  setMargin(0);
178  QFont f = font();
179  f.setPointSize(QFontInfo(f).pointSize() - 1);
180  setFont(f);
181  setWordWrap(true);
182 
183  connect(this, SIGNAL(linkActivated(const QString&)),
184  this, SLOT(internalLinkActivated(const QString&)));
185  connect(this, SIGNAL(linkActivated(const QUrl&)),
186  mainwin, SLOT(helpLinkAction(const QUrl&)));
187  }
188 
189  virtual ~KLFMainWinPopup() { }
190 
191  bool hasMessages() { return (bool)msgKeys.size(); }
192 
193  QStringList messageKeys() { return msgKeys; }
194 
195 signals:
196  void linkActivated(const QUrl& url);
197 
198 public slots:
199 
203  void addMessage(const QString& msgKey, const QString& msgText)
204  {
205  klfDbg("adding message "<<msgKey<<" -> "<<msgText);
206  msgKeys << msgKey;
207  messages << ("<p>"+msgText+"</p>");
208  updateText();
209  }
210 
211  void removeMessage(const QString& msgKey)
212  {
213  int i = msgKeys.indexOf(msgKey);
214  if (i < 0)
215  return;
216  msgKeys.removeAt(i);
217  messages.removeAt(i);
218  updateText();
219  }
220 
221  void show()
222  {
223  QLabel::show();
224  setStyleSheet(styleSheet());
225  }
226 
227 private slots:
228  void internalLinkActivated(const QString& url)
229  {
230  emit linkActivated(QUrl::fromEncoded(url.toLatin1()));
231  }
232 
233  void updateText()
234  {
235  setText("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\""
236  " \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
237  "<html><head><meta name=\"qrichtext\" content=\"1\" />"
238  "<style type=\"text/css\">\n"
239  "body { margin: 2px 10px; }\n"
240  "p { white-space: pre-wrap; padding: 0px; margin: 0px 0px 2px 0px; }\n"
241  "a, a:link { text-decoration: underline; color: #0000af }\n"
242  "a:hover { color: #0000ff }\n"
243  "a:active { color: #ff0000 }\n"
244  "}\n"
245  "</style>"
246  "</head>"
247  "<body>\n"
248  + messages.join("\n") +
249  "<p style=\"margin-top: 5px\">"
250  "<a href=\"klfaction:/popup?acceptAll\">"+tr("Accept [<b>Alt-Enter</b>]")+"</a> | "+
251  " <a href=\"klfaction:/popup_close\">"+tr("Close [<b>Esc</b>]")+"</a> | " +
252  " <a href=\"klfaction:/popup?configDontShow\">"+tr("Don't Show Again")+"</a></p>"+
253  "</body></html>" );
254  resize(width(), sizeHint().height());
255  }
256 
257 private:
258  QStringList msgKeys;
259  QStringList messages;
260 };
261 
262 
263 
264 
265 
266 // -------------------------------------------------
267 
268 
270 {
271  Q_OBJECT
272 public:
273  KLFBasicDataOpener(KLFMainWin *mainwin) : QObject(mainwin), KLFAbstractDataOpener(mainwin) { }
274  virtual ~KLFBasicDataOpener() { }
275 
277  {
278  QStringList types;
279  types << "image/png"
280  << "image/jpeg"
281  << "text/uri-list"
282  << "application/x-klf-libentries"
283  << "application/x-klatexformula"
284  << "application/x-klatexformula-db" ;
285  int k;
287  for (k = 0; k < fmts.size(); ++k) {
288  types << "image/"+fmts[k].toLower();
289  types << "image/x-"+fmts[k].toLower();
290  }
291  klfDbg("mime types: "<<types) ;
292  return types;
293  }
294 
295  virtual bool canOpenFile(const QString& file)
296  {
298  klfDbg("file="<<file) ;
299 
300  QFile f(file);
301  bool r = f.open(QIODevice::ReadOnly);
302  if (!r) {
303  klfDbg(" ... file cannot be accessed.") ;
304  return false;
305  }
306  bool isimage = false;
307  if (isKlfImage(&f, &isimage)) {
308  klfDbg(" ... is KLF-saved image.") ;
309  return true;
310  }
311  if (isimage) { // no try going further, we can't otherwise read image ...
312  klfDbg(" ... is a non-KLF image.") ;
313  return false;
314  }
315 
317  if (!libscheme.isEmpty()) {
318  klfDbg(" ... libscheme="<<libscheme) ;
319  return true; // it is a library file
320  }
321  // by default, fail
322  klfDbg(" ... not recognized.") ;
323  return false;
324  }
325 
326  virtual bool canOpenData(const QByteArray& data)
327  {
328  QBuffer buf;
329  buf.setData(data);
330  buf.open(QIODevice::ReadOnly);
331  bool isimg = false;
332  if (isKlfImage(&buf, &isimg))
333  return true;
334  if (isimg) // no try going further, we can't otherwise read image ...
335  return false;
336 
337  // try to read beginning with a QDataStream to look for a known x-klf-libentries header
338  QDataStream stream(&buf);
339  stream.setVersion(QDataStream::Qt_4_4);
340  QString headerstr;
341  stream >> headerstr;
342  if (headerstr == QLatin1String("KLF_LIBENTRIES"))
343  return true;
344  // *** see note in openData() for library formats. ***
345  // don't try to open .klf or .klf.db formats.
346 
347  // otherwise, we can't recognize data, fail
348  return false;
349  }
350 
351  virtual bool openFile(const QString& file)
352  {
354  klfDbg("file="<<file);
355  QFileInfo fi(file);
356  if (!fi.exists() || !fi.isReadable()) {
357  klfDbg(" ... file is not readable") ;
358  return false;
359  }
360  QString ext = fi.suffix().trimmed().toLower();
361 
362  { // try to open image
363  QFile f(file);
364  bool r = f.open(QIODevice::ReadOnly);
365  if (!r) {
366  klfDbg(" ... file cannot be opened") ;
367  return false;
368  }
369  bool isimage = false;
370  if (tryOpenImageData(&f, &isimage)) {
371  klfDbg(" ... loaded image data!") ;
372  return true;
373  }
374  if (isimage) { // no try going further, we can't otherwise read image ...
375  klfDbg(" ... is non-KLF image...") ;
376  return false;
377  }
378  }
379 
380  // open image failed, try the other formats...
381 
382  // try to load library file
383  bool result = mainWin()->openLibFile(file);
384 
385  klfDbg("mainWin()->openLibFile("<<file<<") returned "<<result) ;
386  if (result)
387  return true;
388 
389  // and otherwise, fail
390  return false;
391  }
392 
393  virtual bool openData(const QByteArray& data, const QString& mimetype)
394  {
396  klfDbg("mimetype is "<<mimetype) ;
397 
398  QBuffer buf;
399  buf.setData(data);
400  buf.open(QIODevice::ReadOnly);
401 
402  if (mimetype == "text/uri-list") {
403  klfDbg("Opening uri-list") ;
404  QByteArray line;
405  QStringList flist;
406  char sbuf[1024];
407  qint64 len;
408  while ((len = buf.readLine(sbuf, sizeof(sbuf))) > 0) {
409  line = QByteArray(sbuf, len);
410  line = line.trimmed(); // gnome uses \r\n, and URLs don't have whitespace.
411  QUrl url = QUrl::fromEncoded(line);
412  if (url.scheme() != "file") {
413  qWarning()<<KLF_FUNC_NAME<<": can't open URL "<<url.scheme()<<" (can only open local files)";
414  continue;
415  }
416  flist << klfUrlLocalFilePath(url);
417  klfDbg("... added file "<<flist.last()) ;
418  }
419  if (flist.isEmpty()) {
420  klfDbg("file list is empty.") ;
421  return true;
422  }
423  return mainWin()->openFiles(flist);
424  }
425 
426  bool isimage = false;
427  if (tryOpenImageData(&buf, &isimage))
428  return true;
429  if (isimage) // no try going further, we can't otherwise read image ...
430  return false;
431 
432  // drop application/x-klf-libentries
433  if (tryOpenKlfLibEntries(&buf))
434  return true;
435 
436  // otherwise if we paste/drop library entries, the case is more delicate, as it can't be
437  // just opened in the library browser, as they are not in a file. So for now, fail to open the data
438  // Possibly, todo: suggest user to create a resource/sub-resource to drop the data into
439  return false;
440  }
441 
442 private:
443  bool prepareImageReader(QImageReader *imagereader, QImage *img, bool *isImage)
444  {
445  *isImage = false;
446  if (!imagereader->canRead()) {
447  klfDbg("format "<<imagereader->format()<<": canRead() returned FALSE!") ;
448  return false;
449  }
450  *img = imagereader->read();
451  if (img->isNull()) {
452  klfDbg("read() returned a null qimage!") ;
453  return false;
454  }
455  *isImage = true;
456  klfDbg("format: '"<<imagereader->format().constData()<<"': text keys set: "<<img->textKeys()
457  <<"; error="<<imagereader->error()
458  <<"; quality="<<imagereader->quality()
459  <<"; supportsOption(description)="<<imagereader->supportsOption(QImageIOHandler::Description)
460  <<"; text('AppVersion')="<<img->text("AppVersion")
461  ) ;
462  if (!img->text("AppVersion").startsWith("KLatexFormula ") && !img->text("AppVersion").startsWith("KLF ")) {
463  klfDbg("AppVersion is not set to 'KL[atex]F[ormula] [...]' in image metadata.") ;
464  return false;
465  }
466  // it is a klf-saved image
467  return true;
468  }
469  bool isKlfImage(QIODevice *device, bool *isImage)
470  {
472  int k;
473  QImage img;
474  QImageReader imagereader;
475  for (k = 0; k < formatlist.size(); ++k) {
476  device->seek(0);
477  imagereader.setFormat(formatlist[k]);
478  imagereader.setDevice(device);
479  if (prepareImageReader(&imagereader, &img, isImage))
480  return true;
481  }
482  return false;
483  }
484  bool tryOpenImageData(QIODevice *device, bool *isimage)
485  {
487  int k;
488  QImageReader imagereader;
489  QImage img;
490  for (k = 0; k < formatlist.size(); ++k) {
491  device->seek(0);
492  imagereader.setFormat(formatlist[k]);
493  imagereader.setDevice(device);
494  if (!prepareImageReader(&imagereader, &img, isimage))
495  continue;
496 
497  // read meta-information
498  QString latex = img.text("InputLatex");
499  KLFStyle style;
500  style.fg_color = read_color(img.text("InputFgColor"));
501  style.bg_color = read_color(img.text("InputBgColor"));
502  style.mathmode = img.text("InputMathMode");
503  style.preamble = img.text("InputPreamble");
504  style.dpi = img.text("InputDPI").toInt();
505 
506  mainWin()->slotLoadStyle(style);
507  mainWin()->slotSetLatex(latex);
508  return true;
509  }
510  return false;
511  }
512  unsigned long read_color(const QString& text)
513  {
514  // 1 2 3 4 5
515  QRegExp rx1("\\s*rgba?\\s*\\(\\s*(\\d+),\\s*(\\d+),\\s*(\\d+)(\\s*,\\s*(\\d+))?\\s*\\)\\s*");
516  if (rx1.exactMatch(text)) {
517  if (rx1.cap(4).isEmpty())
518  return qRgb(rx1.cap(1).toInt(), rx1.cap(2).toInt(), rx1.cap(3).toInt());
519  else
520  return qRgba(rx1.cap(1).toInt(), rx1.cap(2).toInt(), rx1.cap(3).toInt(), rx1.cap(5).toInt());
521  }
522  // try named color format
523  QColor c(text);
524  return c.rgba();
525  }
526 
527  bool tryOpenKlfLibEntries(QIODevice *dev)
528  {
529  // if ONE entry -> load that latex and style
530  // if more entries -> warn user, and fail
531  QDataStream stream(dev);
532  stream.setVersion(QDataStream::Qt_4_4);
533  QString headerstr;
534  stream >> headerstr;
535  if (headerstr != QLatin1String("KLF_LIBENTRIES"))
536  return false;
537  QVariantMap properties;
538  KLFLibEntryList entries;
539  stream >> properties >> entries;
540  if (entries.size() > 1) {
541  QMessageBox::critical(mainWin(), tr("Error"),
542  tr("The data you have request to open contains multiple formulas.\n"
543  "You may only open one formula into the LaTeX code editor."));
544  return false;
545  }
546  if (entries.size() == 0) {
547  QMessageBox::critical(mainWin(), tr("Error"),
548  tr("The data you have request to open contains no formulas."));
549  return false;
550  }
551  mainWin()->restoreFromLibrary(entries[0], KLFLib::RestoreAll);
552  return true;
553  }
554 };
555 
556 
557 
558 
559 
560 
562 {
563  Q_OBJECT
564 public:
565  KLFAddOnDataOpener(KLFMainWin *mainwin) : QObject(mainwin), KLFAbstractDataOpener(mainwin) { }
566  virtual ~KLFAddOnDataOpener() { }
567 
569  {
570  return QStringList();
571  }
572 
573  virtual bool canOpenFile(const QString& file)
574  {
575  if (QFileInfo(file).suffix() == "rcc")
576  return true;
577  QFile f(file);
578  bool r = f.open(QIODevice::ReadOnly);
579  if (!r) { // can't open file
580  return false;
581  }
582  // check if file is RCC file (begins with 'qres')
583  if (f.read(4) == "qres")
584  return true;
585  // not a Qt RCC file
586  return false;
587  }
588 
589  virtual bool canOpenData(const QByteArray& /*data*/)
590  {
591  // Dropped files are opened by the basic data opener, which handles "text/uri-list"
592  // by calling the main window's openFiles()
593  return false;
594  }
595 
596  virtual bool openFile(const QString& file)
597  {
599  klfDbg("file="<<file);
600 
601  if (!canOpenFile(file)) {
602  klfDbg("file is not openable by us: "<<file);
603  return false;
604  }
605 
606  mainWin()->settingsDialog()->show();
607  mainWin()->settingsDialog()->showControl(KLFSettings::ManageAddOns);
608  mainWin()->settingsDialog()->importAddOn(file, true);
609 
610  return true;
611  }
612 
613  virtual bool openData(const QByteArray& /*data*/, const QString& /*mimetype*/)
614  {
615  return false;
616  }
617 };
618 
619 
620 
621 
622 #endif
void removeMessage(const QString &msgKey)
Definition: klfmainwin_p.h:211
virtual ~KLFHelpDialogCommon()
Definition: klfmainwin_p.h:58
setPointSize(int pointSize)
cap(int nth=0)
virtual ~KLFAboutDialog()
Definition: klfmainwin_p.h:110
virtual bool openData(const QByteArray &data, const QString &mimetype)
Definition: klfmainwin_p.h:393
seek(qint64 pos)
virtual ~KLFBasicDataOpener()
Definition: klfmainwin_p.h:274
virtual bool canOpenFile(const QString &file)
Definition: klfmainwin_p.h:295
KLF_EXPORT int klfVersionMin()
const char * style
virtual QStringList supportedMimeTypes()
Definition: klfmainwin_p.h:568
KLF_EXPORT int klfVersionMaj()
setData(const QByteArray &data)
virtual void addExtraText(const QString &htmlSnipplet)
Definition: klfmainwin_p.h:60
#define klfDbg(streamableItems)
#define KLF_DEBUG_BLOCK(msg)
virtual bool canOpenData(const QByteArray &data)
Definition: klfmainwin_p.h:326
text(const QString &key=QString()
QString mathmode
replace(int position, int n, const QString &after)
virtual void show()
Definition: klfmainwin_p.h:112
virtual ~KLFAddOnDataOpener()
Definition: klfmainwin_p.h:566
fromUtf8(const char *str, int size=-1)
KLFHelpDialogCommon(const QString &baseFName)
Definition: klfmainwin_p.h:57
KLF_EXPORT QString klfUrlLocalFilePath(const QUrl &url)
virtual QString getFullHtml()
Definition: klfmainwin_p.h:65
virtual ~KLFMainWinPopup()
Definition: klfmainwin_p.h:189
open(OpenMode mode)
scheme()
setVersion(int v)
void addMessage(const QString &msgKey, const QString &msgText)
Definition: klfmainwin_p.h:203
virtual bool openData(const QByteArray &, const QString &)
Definition: klfmainwin_p.h:613
#define KLF_FUNC_NAME
static QString guessLocalFileScheme(const QString &fileName)
QString preamble
virtual QStringList supportedMimeTypes()
Definition: klfmainwin_p.h:276
virtual bool canOpenFile(const QString &file)
Definition: klfmainwin_p.h:573
KLFMainWinPopup(KLFMainWin *mainwin)
Definition: klfmainwin_p.h:163
KLFBasicDataOpener(KLFMainWin *mainwin)
Definition: klfmainwin_p.h:273
virtual ~KLFWhatsNewDialog()
Definition: klfmainwin_p.h:142
KLF_EXPORT QString klfFindTranslatedDataFile(const QString &baseFileName, const QString &extension)
Definition: klfmain.cpp:504
virtual bool openFile(const QString &file)
Definition: klfmainwin_p.h:351
KLFWhatsNewDialog(QWidget *parent)
Definition: klfmainwin_p.h:132
critical(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons=Ok, StandardButton defaultButton=NoButton)
supportsOption(QImageIOHandler::ImageOption option)
KLFAboutDialog(QWidget *parent)
Definition: klfmainwin_p.h:102
setFormat(const QByteArray &format)
setDevice(QIODevice *device)
virtual bool canOpenData(const QByteArray &)
Definition: klfmainwin_p.h:589
virtual void show()
Definition: klfmainwin_p.h:144
KLFAddOnDataOpener(KLFMainWin *mainwin)
Definition: klfmainwin_p.h:565
QStringList pHtmlExtraSnipplets
Definition: klfmainwin_p.h:91
exactMatch(const QString &str)
unsigned long bg_color
fromEncoded(const QByteArray &input)
virtual bool openFile(const QString &file)
Definition: klfmainwin_p.h:596
QStringList messageKeys()
Definition: klfmainwin_p.h:193
unsigned long fg_color

Generated by doxygen 1.8.11