Back to index

texmacs  1.0.7.15
qt_utilities.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : qt_utilities.cpp
00004 * DESCRIPTION: Utilities for QT
00005 * COPYRIGHT  : (C) 2007  Massimiliano Gubinelli
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "qt_utilities.hpp"
00013 
00014 #include <QImage>
00015 #include <QPrinter>
00016 #include <QPainter>
00017 #include <QCoreApplication>
00018 #include <QLocale>
00019 #include <QDateTime>
00020 #include <QTextCodec>
00021 #include <QHash>
00022 #include <QStringList>
00023 
00024 #include <QPrinter>
00025 #include <QPrintDialog>
00026 
00027 #include "rgb_colors.hpp"
00028 #include "dictionary.hpp"
00029 #include "converter.hpp"
00030 #include "language.hpp"
00031 
00032 #include "qt_gui.hpp"    // gui_maximal_extents()
00033 
00034 #ifdef USE_GS
00035 #include "Ghostscript/gs_utilities.hpp"
00036 #endif
00037 
00039 tm_ostream&
00040 operator << (tm_ostream& out, QRect rect) {
00041   return out << "(" << rect.x() << "," << rect.y() << ","
00042   << rect.width() << "," << rect.height() << ")";
00043 }
00044 
00045 QRect
00046 to_qrect (const coord4 & p) {
00047   float c= 1.0/PIXEL;
00048   return QRect (p.x1*c, -p.x4*c, (p.x3-p.x1+PIXEL-1)*c, (p.x4-p.x2+PIXEL-1)*c);
00049 }
00050 
00051 QPoint
00052 to_qpoint (const coord2 & p) {
00053   float c= 1.0/PIXEL;
00054   return QPoint (p.x1*c, -p.x2*c);
00055 }
00056 
00057 QSize
00058 to_qsize (const coord2 & p) {
00059   float c= 1.0/PIXEL;
00060   return QSize (p.x1*c, p.x2*c);
00061 }
00062 
00063 
00064 QString
00065 parse_tm_style(int style) {
00066   QString sheet;
00067   if (style & WIDGET_STYLE_MINI)  // use smaller text font inside widget
00068     sheet += "font-size: 10pt;";
00069   if (style & WIDGET_STYLE_MONOSPACED)  // use monospaced font inside widget
00070     sheet += "font-family: \"monospace\";";
00071   if (style & WIDGET_STYLE_GREY)  // use grey text font
00072     sheet += "font-color: #eeeeee";
00073   if (style & WIDGET_STYLE_PRESSED)   // indicate that a button is currently pressed
00074     sheet += "";
00075   if (style & WIDGET_STYLE_INERT)  // only render but don't associate any action to widget
00076     sheet += "";
00077   if (style & WIDGET_STYLE_BUTTON)  // indicate that a button should explicitly rendered as a button
00078     sheet += "";
00079   if (style & WIDGET_STYLE_CENTERED)  // use centered text
00080     sheet += "text-align: center;";
00081   if (style & WIDGET_STYLE_BOLD)
00082     sheet += "font-weight: bold;";
00083   return sheet;
00084 }
00085 
00087 QString
00088 to_qstylesheet(int style) {
00089   return "* {" + parse_tm_style(style) + "}";
00090 }
00091 
00092 QString
00093 to_qstylesheet(int style, color c) {
00094   int r,g,b,a;
00095   get_rgb_color(c, r, g, b, a);
00096   a = a*100/255;
00097   return "* {" + parse_tm_style(style)
00098     + QString("color: rgba(%1, %2, %3, %4%);").arg(r).arg(g).arg(b).arg(a)
00099     + "}";
00100 }
00101 
00102 
00109 QSize
00110 qt_decode_length (string width, QWidget* qwid) {
00111   QSize size;
00112   if (qwid)
00113     size= qwid->minimumSizeHint();
00114   else 
00115     gui_maximal_extents (size.rwidth(), size.rheight());
00116   
00117   if (ends (width, "w") && is_double (width (0, N(width) - 1))) {
00118     double x= as_double (width (0, N(width) - 1));
00119     size.rwidth() *= x;
00120   }
00121   else if (ends (width, "h") && is_double (width (0, N(width) - 1))) {
00122     double y= as_double (width (0, N(width) - 1));
00123     size.rheight() *= y;
00124   }
00125   else if (ends (width, "em") && is_double (width (0, N(width) - 2))) {
00126     double x= as_double (width (0, N(width) - 2));
00127     if (qwid) {
00128       size.setWidth(x * qwid->fontInfo().pointSize()); 
00129     } else {
00130       size.setWidth(x * QApplication::font().pointSize());
00131     }
00132   }
00133   else if (ends (width, "px") && is_double (width (0, N(width) - 2))) {
00134     double x= as_double (width (0, N(width) - 2));
00135     size.setWidth(x);
00136   }
00137   return size;
00138 }
00139 
00140 coord4
00141 from_qrect (const QRect & rect) {
00142   SI c1, c2, c3, c4;
00143   c1= rect.x() * PIXEL;
00144   c2= -(rect.y() + rect.height()) * PIXEL;       
00145   c3= (rect.x() + rect.width()) * PIXEL;
00146   c4= -rect.y() * PIXEL;
00147   return coord4 (c1, c2, c3, c4);
00148 }
00149 
00150 coord2
00151 from_qpoint (const QPoint & pt) {
00152   SI c1, c2;
00153   c1= pt.x() * PIXEL;
00154   c2= -pt.y() * PIXEL;
00155   return coord2 (c1, c2);
00156 }
00157 
00158 coord2
00159 from_qsize (const QSize & s) {
00160   SI c1, c2;
00161   c1= s.width() * PIXEL;
00162   c2= s.height() * PIXEL;
00163   return coord2 (c1, c2);
00164 }
00165 
00166 QStringList
00167 to_qstringlist(array<string> l) {
00168   QStringList ql;
00169   for(int i=0; i<N(l); ++i)
00170     ql << to_qstring(l[i]);
00171   return ql;
00172 }
00173 
00174 array<string>
00175 from_qstringlist(const QStringList& l) {
00176   array<string> tl (l.size());
00177   for(QStringList::const_iterator it = l.begin(); it != l.end(); ++it)
00178     tl << from_qstring(*it);
00179   return tl;
00180 }
00181 
00182 QString
00183 to_qstring (string s) {
00184   string out_lan= get_output_language ();
00185   if ((out_lan == "bulgarian") || 
00186       (out_lan == "russian") ||
00187       (out_lan == "ukrainian"))
00188     s = t2a_to_utf8 (s);
00189   else
00190     s = cork_to_utf8 (s);
00191       
00192   char* p= as_charp (s);
00193   QString nss= QString::fromUtf8 (p, N(s));
00194   tm_delete_array (p);
00195   return nss;
00196 }
00197 
00198 QString
00199 utf8_to_qstring (string s) {
00200   char* p= as_charp (s);
00201   QString nss= QString::fromUtf8 (p, N(s));
00202   tm_delete_array (p);
00203   return nss;
00204 }
00205 
00206 string
00207 from_qstring_utf8 (const QString &s) {
00208   QByteArray arr= s.toUtf8 ();
00209   const char* cstr= arr.constData ();
00210   return string ((char*) cstr);
00211 }
00212 
00213 string
00214 from_qstring (const QString &s) {
00215   return utf8_to_cork (from_qstring_utf8(s));
00216 }
00217 
00218 // Although slow to build, this should provide better lookup times than
00219 // linearly traversing the array of colors.
00220 static QHash<QString, QColor> _NamedColors;
00221 
00226 void initNamedColors(void) {
00227   for(int i = 0; i < RGBColorsSize; ++i)
00228     _NamedColors.insert(QString(RGBColors[i].name), 
00229                         QColor(RGBColors[i].r, RGBColors[i].g, RGBColors[i].b));
00230 }
00231 
00236 QColor
00237 to_qcolor (const string& col) {
00238   QString _col = to_qstring(col);
00239   if(_col.startsWith("#"))
00240     return QColor(_col);
00241   if(_NamedColors.isEmpty())
00242     initNamedColors();
00243   if(_NamedColors.contains(_col))
00244     return _NamedColors[_col];
00245   if(DEBUG_QT)
00246     cout << "to_qcolor(" << col << "): name is not defined in RGBColors.\n";
00247   return QColor(100,100,100);  // FIXME? 
00248 }
00249 
00251 string
00252 from_qcolor (const QColor& col) {
00253   return from_qstring(col.name());
00254 }
00255 
00256 // FIXME: Unnecessary? QColor::setRgba() does this.
00257 QColor
00258 to_qcolor(color c) {
00259   int r, g, b, a;
00260   get_rgb_color (c, r, g, b, a);
00261   return QColor (r, g, b, a);
00262 }
00263 
00264 
00265 string
00266 qt_translate (string s) {
00267   string in_lan= get_input_language ();
00268   string out_lan= get_output_language ();
00269 //  return tm_var_encode (translate (s, "english", out_lan));
00270   return tm_var_encode (translate (s, in_lan, out_lan));
00271 }
00272 
00273 //FIXME!?!?
00274 bool
00275 qt_supports (url u) {
00276   string s= suffix (u);
00277   if (s == "ps" || s == "eps" || s == "pdf") return false;
00278   return true;
00279 }
00280 
00281 void
00282 qt_image_size (url image, int& w, int& h) {
00283   //cout <<  concretize (image) << LF;
00284   QImage im= QImage (utf8_to_qstring (concretize (image)));
00285   if (im.isNull ()) {
00286     cerr << "TeXmacs] cannot read image file '" << image << "'" 
00287         << " in qt_image_size" << LF;
00288     w= 35; h= 35;
00289   }
00290   else {
00291     w= im.width ();
00292     h= im.height ();
00293   }
00294 }
00295 
00296 void
00297 qt_convert_image (url image, url dest, int w, int h) {
00298   QImage im (utf8_to_qstring (concretize (image)));
00299   if (im.isNull ())
00300     cerr << "TeXmacs] cannot read image file '" << image << "'" 
00301          << " in qt_convert_image" << LF;
00302   else {
00303     if (w > 0 && h > 0) 
00304       im= im.scaled (w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
00305     im.scaled (w, h).save (utf8_to_qstring (concretize (dest)));
00306   }
00307 }
00308 
00309 void
00310 qt_image_to_eps (url image, url eps, int w_pt, int h_pt, int dpi) {
00311   static const char* d= "0123456789ABCDEF";
00312   QImage im (utf8_to_qstring (concretize (image)));
00313   if (im.isNull ())
00314     cerr << "TeXmacs Cannot read image file '" << image << "'"
00315         << " in qt_image_to_eps" << LF;
00316   else {
00317     if (dpi > 0 && w_pt > 0 && h_pt > 0) {
00318       int ww= w_pt * dpi / 72;
00319       int hh= h_pt * dpi / 72;
00320       if (ww < im.width () || hh < im.height ()) {
00321         im= im.scaled (ww, hh, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
00322       }
00323     }
00324     string res;
00325     string sw= as_string (im.width ());
00326     string sh= as_string (im.height ());
00327     res << "%!PS-Adobe-3.0 EPSF-3.0\n%%Creator: TeXmacs\n%%BoundingBox: ";
00328     res << "0 0 " << sw << " " << sh << "\n";
00329     res << "%%LanguageLevel: 2\n%%Pages: 1\n%%DocumentData: Clean7Bit\n";
00330     res <<  sw << " " << sh << " scale\n";
00331     res <<  sw << " " << sh << " 8 [" << sw << " 0 0 -" << sh << " 0 " << sh << "]\n";
00332     res << "{currentfile 3 " << sw << " mul string readhexstring pop} bind\nfalse 3 colorimage\n";
00333     int v, i= 0, j= 0, l= 0;
00334     for (j= 0; j < im.height (); j++) {
00335       for (i=0; i < im.width (); i++) {
00336         l++;
00337         QRgb p= im.pixel (i, j);
00338         v= qRed (p);
00339         res << d [(v >> 4)] << d [v % 16];
00340         v= qGreen (p);
00341         res << d [(v >> 4)] << d [v % 16];
00342         v= qBlue (p);
00343         res << d [(v >> 4)] << d [v % 16];
00344         if (l > 10) {
00345           res << "\n";
00346           l= 0;
00347         }
00348       }
00349     }
00350     res << "\n%%EOF";
00351     save_string (eps, res);
00352 #ifdef USE_GS
00353     url temp= url_temp (".eps");
00354     gs_to_eps (eps, temp);
00355     copy (temp, eps);
00356     remove (temp);
00357 #endif
00358   }
00359 }
00360 
00361 string 
00362 qt_application_directory () {
00363   return  string (QCoreApplication::applicationDirPath () .toAscii() .constData());
00364   // return from_qstring (QCoreApplication::applicationDirPath ());
00365 }
00366 
00367 string
00368 qt_get_date (string lan, string fm) {
00369   QDateTime localtime = QDateTime::currentDateTime();
00370   if (fm == "") {
00371     if ((lan == "british") || (lan == "english") || (lan == "american"))
00372       fm = "MMMM d, yyyy";
00373     else if (lan == "german")
00374       fm = "d. MMMM yyyy";
00375     else if (lan == "chinese" || lan == "japanese" ||
00376              lan == "korean" || lan == "taiwanese")
00377     {
00378       string y = as_string(localtime.date().year());
00379       string m = as_string(localtime.date().month());
00380       string d = as_string(localtime.date().day());
00381       if (lan == "japanese")
00382         return y * "<#5e74>" * m * "<#6708>" * d * "<#65e5>";
00383       if (lan == "korean")
00384         return y * "<#b144> " * m * "<#c6d4> " * d * "<#c77c>";
00385       return y * "," * m * "," * d;
00386     }
00387     else fm = "d MMMM yyyy";
00388   }
00389   QLocale loc = QLocale(to_qstring(language_to_locale(lan)));
00390 #if (QT_VERSION >= 0x040400)
00391   QString date = loc.toString(localtime, to_qstring(fm));
00392 #else
00393   QString date = localtime.toString(to_qstring(fm));
00394 #endif
00395   return from_qstring(date);
00396 }
00397 
00398 #ifndef _MBD_EXPERIMENTAL_PRINTER_WIDGET  // this is in qt_printer_widget
00399 
00400 #define PAPER(fmt)  case QPrinter::fmt : return "fmt"
00401 static string 
00402 qt_papersize_to_string( QPrinter::PaperSize sz ) {
00403   switch (sz) {
00404       PAPER (A0) ;
00405       PAPER (A1) ;
00406       PAPER (A2) ;
00407       PAPER (A3) ;
00408       PAPER (A4) ;
00409       PAPER (A5) ;
00410       PAPER (A6) ;
00411       PAPER (A7) ;
00412       PAPER (A8) ;
00413       PAPER (A9) ;
00414       PAPER (B0) ;
00415       PAPER (B1) ;
00416       PAPER (B2) ;
00417       PAPER (B3) ;
00418       PAPER (B4) ;
00419       PAPER (B5) ;
00420       PAPER (B6) ;
00421       PAPER (B7) ;
00422       PAPER (B8) ;
00423       PAPER (B9) ;
00424       PAPER (B10) ;      
00425       PAPER (Letter) ;
00426       
00427     default:
00428       return "A4";
00429   }
00430 }
00431 #undef PAPER
00432 
00433 
00434 bool 
00435 qt_print (bool& to_file, bool& landscape, string& pname, url& filename, 
00436           string& first, string& last, string& paper_type) {
00437   static QPrinter *qprinter = NULL;
00438   if (!qprinter) {
00439     qprinter = new QPrinter;
00440   }
00441   QPrintDialog pdialog(qprinter);
00442   if (pdialog.exec() == QDialog::Accepted) {
00443     to_file = !(qprinter->outputFileName().isNull());
00444     pname = from_qstring( qprinter->printerName() );
00445     filename = from_qstring( qprinter->outputFileName() );
00446     landscape = (qprinter->orientation() == QPrinter::Landscape);
00447     paper_type = qt_papersize_to_string(qprinter->paperSize());
00448     if (qprinter->printRange() == QPrinter::PageRange) {
00449       first = qprinter->fromPage(); 
00450       last = qprinter->toPage(); 
00451     }
00452     //cout << "Printer :" << pname << LF;
00453     //cout << "File :" << filename << LF;
00454     return true;
00455   }
00456   return false;
00457 }
00458 
00459 #endif //_MBD_EXPERIMENTAL_PRINTER_WIDGET