[KLF Backend][KLF Tools][KLF Home]
KLatexFormula Project
src/klftools/klfguiutil.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  *   file klfguiutil.cpp
00003  *   This file is part of the KLatexFormula Project.
00004  *   Copyright (C) 2011 by Philippe Faist
00005  *   philippe.faist at bluewin.ch
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 /* $Id$ */
00023 
00024 #include <cmath>
00025 
00026 #include <QApplication>
00027 #include <QDesktopWidget>
00028 #include <QIcon>
00029 #include <QPushButton>
00030 #include <QDebug>
00031 
00032 #include "klfutil.h"
00033 #include "klfrelativefont.h"
00034 #include "klfguiutil.h"
00035 
00036 
00037 // ----------------------------------------------
00038 
00039 
00040 KLFProgressReporter::KLFProgressReporter(int min, int max, QObject *parent)
00041   : QObject(parent)
00042 {
00043   pMin = min;
00044   pMax = max;
00045   pFinished = false;
00046 }
00047 KLFProgressReporter::~KLFProgressReporter()
00048 {
00049   if (!pFinished) {  // make sure finished() is emitted.
00050     emit progress(pMax); // some connected clients just wait for maximum value progress
00051     emit finished();
00052   }
00053 }
00054 
00055 void KLFProgressReporter::doReportProgress(int value)
00056 {
00057   if (pFinished) {
00058     qWarning()<<KLF_FUNC_NAME<<": Operation is already finished!";
00059     return;
00060   }
00061   emit progress(value);
00062   if (value >= pMax) {
00063     emit finished();
00064     pFinished = true;
00065   }
00066 }
00067 
00068 
00069 
00070 // ---------------------------------------------------------
00071 
00072 
00073 
00074 KLFProgressDialog::KLFProgressDialog(QString labelText, QWidget *parent)
00075   : QProgressDialog(parent)
00076 {
00077   setup(false);
00078   init(labelText);
00079 }
00080 KLFProgressDialog::KLFProgressDialog(bool canCancel, QString labelText, QWidget *parent)
00081   : QProgressDialog(parent)
00082 {
00083   setup(canCancel);
00084   init(labelText);
00085 }
00086 KLFProgressDialog::~KLFProgressDialog()
00087 {
00088 }
00089 
00090 void KLFProgressDialog::setup(bool canCancel)
00091 {
00092   pProgressReporter = NULL;
00093   setAutoClose(true);
00094   setAutoReset(true);
00095   setModal(true);
00096   //  setWindowModality(Qt::ApplicationModal);
00097   setWindowIcon(QIcon(":/pics/klatexformula-16.png"));
00098   setWindowTitle(tr("Progress"));
00099   QPushButton *cbtn = new QPushButton(tr("Cancel"), this);
00100   setCancelButton(cbtn);
00101   cbtn->setEnabled(canCancel);
00102 }
00103 void KLFProgressDialog::init(const QString& labelText)
00104 {
00105   setDescriptiveText(labelText);
00106 }
00107 
00108 void KLFProgressDialog::setDescriptiveText(const QString& labelText)
00109 {
00110   setLabelText(labelText);
00111   setFixedSize((int)(sizeHint().width()*1.3), (int)(sizeHint().height()*1.1));
00112 }
00113 void KLFProgressDialog::startReportingProgress(KLFProgressReporter *progressReporter,
00114                                                const QString& descriptiveText)
00115 {
00116   reset();
00117   setDescriptiveText(descriptiveText);
00118   setRange(progressReporter->min(), progressReporter->max());
00119   setValue(0);
00120 
00121   // disconnect any previous progress reporter object
00122   if (pProgressReporter != NULL)
00123     disconnect(pProgressReporter, 0, this, SLOT(setValue(int)));
00124   // and connect to this new one
00125   connect(progressReporter, SIGNAL(progress(int)), this, SLOT(setValue(int)));
00126 }
00127 
00128 void KLFProgressDialog::startReportingProgress(KLFProgressReporter *progressReporter)
00129 {
00130   reset();
00131   setRange(progressReporter->min(), progressReporter->max());
00132   setValue(0);
00133   // disconnect any previous progress reporter object
00134   if (pProgressReporter != NULL)
00135     disconnect(pProgressReporter, 0, this, SLOT(setValue(int)));
00136   // and connect to this new one
00137   connect(progressReporter, SIGNAL(progress(int)), this, SLOT(setValue(int)));
00138 }
00139 
00140 void KLFProgressDialog::setValue(int value)
00141 {
00142   //  KLF_DEBUG_BLOCK(KLF_FUNC_NAME);
00143   klfDbg("value="<<value);
00144   QProgressDialog::setValue(value);
00145 }
00146 
00147 void KLFProgressDialog::paintEvent(QPaintEvent *event)
00148 {
00149   KLF_DEBUG_BLOCK(KLF_FUNC_NAME);
00150   QProgressDialog::paintEvent(event);
00151 }
00152 
00153 
00154 // --------------------------
00155 
00156 
00157 static Qt::WindowFlags klfpleasewait_flagsForSettings(bool alwaysAbove)
00158 {
00159   Qt::WindowFlags f =  Qt::Window|Qt::SplashScreen|Qt::FramelessWindowHint;
00160   if (alwaysAbove)
00161     f |= Qt::WindowStaysOnTopHint|Qt::X11BypassWindowManagerHint;
00162   return f;
00163 }
00164 
00165 KLFPleaseWaitPopup::KLFPleaseWaitPopup(const QString& text, QWidget *parent, bool alwaysAbove)
00166   : QLabel(text, ((parent!=NULL)?parent->window():NULL), klfpleasewait_flagsForSettings(alwaysAbove)),
00167     pParentWidget(parent), pDisableUi(false), pGotPaintEvent(false), pDiscarded(false)
00168 {
00169   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00170   KLFRelativeFont *relfont = new KLFRelativeFont(this);
00171   relfont->setRelPointSize(+2);
00172 
00173   setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
00174   setWindowModality(Qt::ApplicationModal);
00175   // let this window be styled by skins
00176   setAttribute(Qt::WA_StyledBackground, true);
00177   setProperty("klfTopLevelWidget", QVariant(true));
00178 
00179   setFrameStyle(QFrame::Panel|QFrame::Sunken);
00180 
00181   QWidget *pw = parentWidget(); // the one set in QLabel constructor, this is the top-level window
00182   if (pw != NULL)
00183     setStyleSheet(pw->window()->styleSheet());
00184 
00185   int w = qMax( (int)(sizeHint().width() *1.3) , 500 );
00186   int h = qMax( (int)(sizeHint().height()*1.1) , 100 );
00187   setFixedSize(w, h);
00188   setWindowOpacity(0.94);
00189 }
00190 KLFPleaseWaitPopup::~KLFPleaseWaitPopup()
00191 {
00192   if (pDisableUi && pParentWidget != NULL)
00193     pParentWidget->setEnabled(true);
00194 }
00195 
00196 void KLFPleaseWaitPopup::setDisableUi(bool disableUi)
00197 {
00198   pDisableUi = disableUi;
00199 }
00200 
00201 void KLFPleaseWaitPopup::showPleaseWait()
00202 {
00203   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00204 
00205   QSize desktopSize;
00206   QDesktopWidget *dw = QApplication::desktop();
00207   if (dw != NULL) {
00208     desktopSize = dw->screenGeometry(this).size();
00209   } else {
00210     desktopSize = QSize(1024, 768); // assume some default, worst case widget is more left and higher
00211   }
00212   move(desktopSize.width()/2 - width()/2, desktopSize.height()/2 - height()/2);
00213   show();
00214   setStyleSheet(styleSheet());
00215 
00216   if (pDisableUi && pParentWidget != NULL)
00217     pParentWidget->setEnabled(false);
00218 
00219   while (!pGotPaintEvent)
00220     qApp->processEvents();
00221 }
00222 
00223 void KLFPleaseWaitPopup::mousePressEvent(QMouseEvent */*event*/)
00224 {
00225   hide();
00226   pDiscarded = true;
00227 }
00228 
00229 void KLFPleaseWaitPopup::paintEvent(QPaintEvent *event)
00230 {
00231   pGotPaintEvent = true;
00232   QLabel::paintEvent(event);
00233 }
00234 
00235 
00236 
00237 // --------------------------
00238 
00239 
00240 KLFDelayedPleaseWaitPopup::KLFDelayedPleaseWaitPopup(const QString& text, QWidget *callingWidget)
00241   : KLFPleaseWaitPopup(text, callingWidget), pDelay(1000)
00242 {
00243   timer.start();
00244 }
00245 KLFDelayedPleaseWaitPopup::~KLFDelayedPleaseWaitPopup()
00246 {
00247 }
00248 void KLFDelayedPleaseWaitPopup::setDelay(int ms)
00249 {
00250   pDelay = ms;
00251 }
00252 void KLFDelayedPleaseWaitPopup::process()
00253 {
00254   if (!pleaseWaitShown() && timer.elapsed() > pDelay)
00255     showPleaseWait();
00256   qApp->processEvents();
00257 }
00258 
00259 
00260 
00261 // ------------------------------------------------
00262 
00263 
00264 KLFEnumComboBox::KLFEnumComboBox(QWidget *parent)
00265   : QComboBox(parent)
00266 {
00267   setEnumValues(QList<int>(), QStringList());
00268   connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(internalCurrentIndexChanged(int)));
00269 }
00270 
00271 KLFEnumComboBox::KLFEnumComboBox(const QList<int>& enumValues, const QStringList& enumTitles,
00272                                  QWidget *parent)
00273   : QComboBox(parent)
00274 {
00275   setEnumValues(enumValues, enumTitles);
00276   connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(internalCurrentIndexChanged(int)));
00277 }
00278 
00279 KLFEnumComboBox::~KLFEnumComboBox()
00280 {
00281 }
00282 
00283 void KLFEnumComboBox::setEnumValues(const QList<int>& enumValues, const QStringList& enumTitles)
00284 {
00285   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00286   klfDbg("enumValues="<<enumValues<<"; enumTitles="<<enumTitles);
00287   blockSignals(true);
00288   int savedCurrentIndex = currentIndex();
00289   if (enumValues.size() != enumTitles.size()) {
00290     qWarning()<<KLF_FUNC_NAME<<": enum value list and enum title list do not match!";
00291     return;
00292   }
00293   pEnumValueList = enumValues;
00294   clear();
00295   int k;
00296   for (k = 0; k < enumValues.size(); ++k) {
00297     pEnumValues[enumValues[k]] = enumTitles[k];
00298     insertItem(k, enumTitles[k], QVariant(enumValues[k]));
00299     pEnumCbxIndexes[enumValues[k]] = k;
00300   }
00301   if (savedCurrentIndex >= 0 && savedCurrentIndex < count())
00302     setCurrentIndex(savedCurrentIndex);
00303   blockSignals(false);
00304 }
00305 
00306 int KLFEnumComboBox::selectedValue() const
00307 {
00308   return itemData(currentIndex()).toInt();
00309 }
00310 
00311 QString KLFEnumComboBox::enumText(int enumValue) const
00312 {
00313   if (!pEnumValueList.contains(enumValue)) {
00314     qWarning()<<KLF_FUNC_NAME<<": "<<enumValue<<" is not a registered valid enum value!";
00315     return QString();
00316   }
00317   return pEnumValues[enumValue];
00318 }
00319 
00320 void KLFEnumComboBox::setSelectedValue(int val)
00321 {
00322   if (!pEnumCbxIndexes.contains(val)) {
00323     qWarning()<<KLF_FUNC_NAME<<": "<<val<<" is not a registered valid enum value!";
00324     return;
00325   }
00326   setCurrentIndex(pEnumCbxIndexes[val]);
00327 }
00328 
00329 void KLFEnumComboBox::internalCurrentIndexChanged(int index)
00330 {
00331   emit selectedValueChanged(itemData(index).toInt());
00332 }
00333 
00334 
00335 // ------------------------
00336 
00337 
00338 KLFWaitAnimationOverlay::KLFWaitAnimationOverlay(QWidget *parent)
00339   : QLabel(parent)
00340 {
00341   pAnimMovie = NULL;
00342   /*
00343     pAnimMovie = new QMovie(":/pics/wait_anim.mng", "MNG", this);
00344     pAnimMovie->setCacheMode(QMovie::CacheAll);
00345   */
00346 
00347   setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
00348 
00349   hide();
00350 
00351   pAnimTimerId = -1;
00352   pIsWaiting = false;
00353 
00354   // default values
00355   pWidthPercent = 30;
00356   pHeightPercent = 70;
00357   pPositionXPercent = 50;
00358   pPositionYPercent = 50;
00359 
00360   setBackgroundColor(QColor(255,255,255,128));
00361 }
00362 
00363 KLFWaitAnimationOverlay::~KLFWaitAnimationOverlay()
00364 {
00365 }
00366 
00367 QColor KLFWaitAnimationOverlay::backgroundColor() const
00368 {
00369   return palette().color(QPalette::Window);
00370 }
00371 
00372 void KLFWaitAnimationOverlay::setWaitMovie(QMovie *movie)
00373 {
00374   if (pAnimMovie != NULL) {
00375     delete pAnimMovie;
00376   }
00377   pAnimMovie = movie;
00378   pAnimMovie->setParent(this);
00379 }
00380 
00381 void KLFWaitAnimationOverlay::setWaitMovie(const QString& filename)
00382 {
00383   QMovie *m = new QMovie(filename);
00384   m->setCacheMode(QMovie::CacheAll);
00385   setWaitMovie(m);
00386 }
00387 
00388 
00389 void KLFWaitAnimationOverlay::setBackgroundColor(const QColor& c)
00390 {
00391   setStyleSheet(QString("background-color: rgba(%1,%2,%3,%4)")
00392                 .arg(c.red()).arg(c.green()).arg(c.blue()).arg(c.alpha()));
00393 }
00394 
00395 
00396 void KLFWaitAnimationOverlay::startWait()
00397 {
00398   if (pIsWaiting)
00399     return;
00400 
00401   pIsWaiting = true;
00402   if (pAnimMovie == NULL)
00403     return;
00404 
00405   pAnimMovie->jumpToFrame(0);
00406   setPixmap(pAnimMovie->currentPixmap());
00407   setGeometry(calcAnimationLabelGeometry());
00408   show();
00409   update();
00410 
00411   qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
00412 
00413   pAnimTimerId = startTimer(pAnimMovie->nextFrameDelay());
00414 }
00415 
00416 void KLFWaitAnimationOverlay::stopWait()
00417 {
00418   if (!pIsWaiting)
00419     return;
00420 
00421   hide();
00422 
00423   if (pAnimTimerId >= 0)
00424     killTimer(pAnimTimerId);
00425   pAnimTimerId = -1;
00426   pIsWaiting = false;
00427 }
00428 
00429 void KLFWaitAnimationOverlay::timerEvent(QTimerEvent *event)
00430 {
00431   if (event->timerId() == pAnimTimerId) {
00432     pAnimMovie->jumpToNextFrame();
00433     setPixmap(pAnimMovie->currentPixmap());
00434     repaint();
00435     return;
00436   }
00437 }
00438 
00439 QRect KLFWaitAnimationOverlay::calcAnimationLabelGeometry()
00440 {
00441   QWidget * w = parentWidget();
00442   if (w == NULL) {
00443     qWarning()<<KLF_FUNC_NAME<<": this animation label MUST be used with a parent!";
00444     return QRect();
00445   }
00446   QRect g = w->geometry();
00447   QSize sz = QSize(w->width()*pWidthPercent/100,w->height()*pHeightPercent/100);
00448 
00449   klfDbg("parent geometry: "<<g<<"; our size="<<sz) ;
00450 
00451   return KLF_DEBUG_TEE( QRect(QPoint( (g.width()-sz.width())*pPositionXPercent/100,
00452                                       (g.height()-sz.height())*pPositionYPercent/100),
00453                               sz) );
00454 }
00455 
00456 
00457 
00458 // -----------------------
00459 
00460 
00461 KLF_EXPORT void klfDrawGlowedImage(QPainter *p, const QImage& foreground, const QColor& glowcol,
00462                                    int r, bool also_draw_image)
00463 {
00464   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00465 
00466   QImage fg = foreground;
00467   if (fg.format() != QImage::Format_ARGB32_Premultiplied &&
00468       fg.format() != QImage::Format_ARGB32)
00469     fg = fg.convertToFormat(QImage::Format_ARGB32);
00470 
00471   QRgb glow_color = glowcol.rgba();
00472 
00473   qreal dpr = p->device()->devicePixelRatioF();
00474   QSize userspace_size = fg.size() / dpr;
00475 
00476   int r2 = r*dpr;
00477 
00478   QImage glow(fg.size(), QImage::Format_ARGB32_Premultiplied);
00479   int x, y;
00480   qreal ga = qAlpha(glow_color) / qreal(255);
00481   ga /= r*r; // heuristic scaling of alpha
00482   for (x = 0; x < fg.width(); ++x) {
00483     for (y = 0; y < fg.height(); ++y) {
00484       qreal ai = qAlpha(fg.pixel(x,y)) * ga;
00485       qreal a = ai / 255;
00486       // glow format is argb32_premultiplied
00487       glow.setPixel(x,y, qRgba(qRed(glow_color)*a, qGreen(glow_color)*a, qBlue(glow_color)*a, ai));
00488     }
00489   }
00490   // now draw that glowed image a few times moving around the interest point to do a glow effect
00491   //  p->save();
00492   //  p->setOpacity(std::log(-numoverlaps));
00493   //  p->setCompositionMode(QPainter::CompositionMode_Plus);
00494   int dx, dy;
00495   for (dx = -r2; dx <= r2; dx += dpr) {
00496     for (dy = -r2; dy <= r2; dy += dpr) {
00497       if (dx*dx+dy*dy > r2*r2) // don't go beyond r2 device pixels from (0,0)
00498         continue;
00499       p->drawImage(QRectF(QPointF(dx/dpr,dy/dpr), userspace_size), glow);
00500     }
00501   }
00502   //  p->restore();
00503   if (also_draw_image) {
00504     p->drawImage(QRect(QPoint(0,0), userspace_size), fg);
00505   }
00506 }
00507 
00508 
00509 
00510 // --------------------------
00511 
00512 QImage klfImageScaled(const QImage& source, const QSize& newSize)
00513 {
00514   QImage img = source.scaled(newSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
00515   // set text attributes
00516   QStringList keys = source.textKeys();
00517   int k;
00518   for (k = 0; k < keys.size(); ++k) {
00519     img.setText(keys[k], source.text(keys[k]));
00520   }
00521   return img;
00522 }
00523 
00524 
00525 // --------------------
00526 
00527 KLF_EXPORT QRect klf_get_window_geometry(QWidget *w)
00528 {
00529 #if defined(KLF_WS_X11)
00530   QRect g = w->frameGeometry();
00531 #else
00532   QRect g = w->geometry();
00533 #endif
00534   return g;
00535 }
00536 
00537 KLF_EXPORT void klf_set_window_geometry(QWidget *w, QRect g)
00538 {
00539   if ( ! g.isValid() )
00540     return;
00541 
00542   w->setGeometry(g);
00543 }
00544 
00545 
00546 KLFWindowGeometryRestorer::KLFWindowGeometryRestorer(QWidget *window)
00547   : QObject(window), pWindow(window)
00548 {
00549   window->installEventFilter(this);
00550 }
00551 
00552 KLFWindowGeometryRestorer::~KLFWindowGeometryRestorer()
00553 {
00554 }
00555 
00556 bool KLFWindowGeometryRestorer::eventFilter(QObject *obj, QEvent *event)
00557 {
00558   if (obj == pWindow) {
00559     if (event->type() == QEvent::Hide) {
00560       // save geometry
00561       pWindow->setProperty("klf_saved_geometry", klf_get_window_geometry(pWindow));
00562     } else if (event->type() == QEvent::Show) {
00563       QVariant val;
00564       if ((val = pWindow->property("klf_saved_geometry")).isValid())
00565         klf_set_window_geometry(pWindow, val.value<QRect>());
00566     }
00567   }
00568 
00569   return false;
00570 }
00571 
00572 
00573 
00578 static QHash<QWidget*,bool> windowShownStates;
00579 
00580 /*
00581 inline bool has_ancestor_of_type(QObject *testobj, const char * type)
00582 {
00583   klfDbg("testing if "<<testobj<<" is (grand-)child of object inheriting "<<type) ;
00584   if (testobj == NULL)
00585     return false;
00586   do {
00587     if (testobj->inherits(type)) {
00588       klfDbg("inherits "<<type<<"!") ;
00589       return true;
00590     }
00591   } while ((testobj = testobj->parent()) != NULL) ;
00592   klfDbg("no.") ;
00593   return false;
00594 }
00595 */
00596 
00597 KLF_EXPORT void klfHideWindows()
00598 {
00599   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00600   //  / ** \todo don't _FORCE_ this setting, remember and restore it.... * /
00601   //  qApp->setQuitOnLastWindowClosed(false);
00602 
00603   // save the window states, while checking that not all the windows are already hidden
00604   QHash<QWidget*,bool> states;
00605   bool allalreadyhidden = true;
00606   QWidgetList wlist = QApplication::topLevelWidgets();
00607   foreach (QWidget *w, wlist) {
00608     //    if (w->inherits("QMenu"))
00609     //      continue;
00610     uint wflags = w->windowFlags();
00611     klfDbg("next widget in line: "<<w<<", wflags="<<wflags) ;
00612     if ((wflags & Qt::Window) == 0) {
00613       continue;
00614     }
00615     if (wflags & Qt::X11BypassWindowManagerHint) {
00619       continue;
00620     }
00621     klfDbg("dealing with widget "<<w) ;
00622     bool shown = w->isVisible();
00623     states[w] = shown;
00624     if (shown) {
00625       klfDbg("hiding window "<<w<<", wflags="<<w->windowFlags()) ;
00626       w->hide();
00627       allalreadyhidden = false;
00628     }
00629   }
00630   if (!allalreadyhidden) {
00631     // don't overwrite the saved status list with an all-hidden state list
00632     windowShownStates = states;
00633   }
00634 }
00635 
00636 KLF_EXPORT void klfRestoreWindows()
00637 {
00638   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00639   QWidgetList wlist = QApplication::topLevelWidgets();
00640   foreach (QWidget *w, wlist) {
00641     if (!windowShownStates.contains(w))
00642       continue;
00643     // restore this window
00644     if (!w->isVisible()) {
00645       klfDbg("Restoring window "<<w) ;
00646       w->setVisible(windowShownStates[w]);
00647     }
00648   }
00649 }

Generated by doxygen 1.7.6.1. The KLatexFormula website is hosted on sourceforge.net