Logo Search packages:      
Sourcecode: qalculate-kde version File versions  Download package

qalculateresultdisplay.cpp

/***************************************************************************
 *   Copyright (C) 2005 by Niklas Knutsson   *
 *   nq@altern.org   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "qalculateresultdisplay.h"

#include "qalculate_kde_utils.h"
#include "kqalculate.h"
#include <kpopupmenu.h>
#include <kxmlguifactory.h>
#include <kxmlguiclient.h>
#include <kaction.h>
#include <kmessagebox.h>
#include <qwhatsthis.h>
#include <qtooltip.h>
#include <klocale.h>
#include <kapplication.h>
#include <qsimplerichtext.h>

extern vector<mode_struct> modes;

extern QString parsed_text;
extern KQalculate *mainWin;
extern MathStructure *mstruct;
extern PrintOptions printops;
extern EvaluationOptions evalops;

QString linkInfo(const MathStructure *m, QWidget *w, bool full_length = false) {
      QString str;
      if(m) {
            if(m->isSymbolic()) {
                  str = "\"";
                  str += m->symbol().c_str();
                  str += "\"";
            } else if(m->isVector()) {
                  if(m->isMatrix()) {
                        str = i18n("a matrix");
                  } else {
                        str = i18n("a vector");
                  }
                  str += "\n";
                  str += i18n("double-click to view/edit");
            } else if(m->isVariable()) {
                  if(m->variable()->subtype() == SUBTYPE_UNKNOWN_VARIABLE) {
                        str = i18n("Unknown variable");
                  } else {
                        str = i18n("Variable");
                  }
                  str += ": ";
                  str += m->variable()->title(true).c_str();
            } else if(m->isUnit()) {
                  str = i18n("Unit");
                  str += ": ";
                  str += m->unit()->title(true).c_str();
                  if(m->prefix() && m->prefix() != CALCULATOR->decimal_null_prefix && m->prefix() != CALCULATOR->binary_null_prefix) {
                        str += "\n";
                        str += i18n("Prefix");
                        str += ": ";
                        QString pstr;
                        switch(m->prefix()->type()) {
                              case PREFIX_DECIMAL: {
                                    QTextOStream(&pstr) << m->prefix()->name(false, printops.use_unicode_signs, &can_display_unicode_string_function, (void*) w).c_str() << " (10e" << ((DecimalPrefix*) m->prefix())->exponent() << ")";
                                    break;
                              }
                              case PREFIX_BINARY: {
                                    QTextOStream(&pstr) << m->prefix()->name(false, printops.use_unicode_signs, &can_display_unicode_string_function, (void*) w).c_str() << " (2e" << ((BinaryPrefix*) m->prefix())->exponent() << ")";
                                    break;
                              }
                              case PREFIX_NUMBER: {
                                    QTextOStream(&pstr) << m->prefix()->name(false, printops.use_unicode_signs, &can_display_unicode_string_function, (void*) w).c_str();
                                    break;
                              }                 
                        }
                        str += pstr;
                  }
            } else if(m->isFunction()) {
                  str = i18n("Function");
                  str += ": ";
                  str += m->function()->title(true).c_str();
                  Argument default_arg;
                  MathFunction *f = m->function();
                  str += "<br>";
                  const ExpressionName *ename = &f->preferredName(false, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) w);
                  str += "<i><b>";
                  str += ename->name.c_str();
                  str += "</b>";
                  int iargs = f->maxargs();
                  if(iargs < 0) {
                        iargs = f->minargs() + 1;
                  }
                  str += "(";
                  if(iargs != 0) {
                        for(int i2 = 1; i2 <= iargs; i2++) {
                              if(i2 > f->minargs()) {
                                    str += "[";
                              }
                              if(i2 > 1) {
                                    str += CALCULATOR->getComma().c_str();
                                    str += " ";
                              }
                              Argument *arg = f->getArgumentDefinition(i2);
                              if(arg && !arg->name().empty()) {
                                    str += arg->name().c_str();
                              } else {
                                    str += i18n("argument");
                                    str += " ";
                                    str += QString::number(i2);
                              }
                              if(i2 > f->minargs()) {
                                    str += "]";
                              }
                        }
                        if(f->maxargs() < 0) {
                              str += CALCULATOR->getComma().c_str();
                              str += " ...";
                        }
                  }
                  str += ")";
                  str += "</i>";
                  if(full_length) {
                        str += "<i>";
                        for(size_t i2 = 1; i2 <= f->countNames(); i2++) {
                              if(&f->getName(i2) != ename) {
                                    str += "<br>";
                                    str += f->getName(i2).name.c_str();
                              }
                        }
                        str += "</i>";
                        if(f->subtype() == SUBTYPE_DATA_SET) {
                              str += "<br>";
                              str += "<br>";
                              QString str2;
                              str2.sprintf(i18n("Retrieves data from the %s data set for a given object and property. If \"info\" is typed as property, a dialog window will pop up with all properties of the object."), f->title().c_str());
                              str2.replace("<", "&lt;");
                              str2.replace(">", "&gt;");
                              str += str2;
                        }
                        if(!f->description().empty()) {
                              str += "<br>";
                              str += "<br>";
                              QString str2 = f->description().c_str();
                              str2.replace("<", "&lt;");
                              str2.replace(">", "&gt;");
                              str += str2;
                        }
                  }
            }
      }
      return str;
}


QString linkInfo(const QString &link, QWidget *w, bool full_length = false) {
      if(!link.isEmpty() && link[0] == '+') {
            QString str = link;
            str.remove(0, 1);
            return str;
      } else {
            return linkInfo(mainWin->getResultPart(link.toInt()), w, full_length);
      }
}

class QalculateExpressionToolTip : public QToolTip {

public:

      QalculateResultDisplay *qrd;

      QalculateExpressionToolTip(QalculateResultDisplay *parent, QToolTipGroup *group = 0) : QToolTip(parent->viewport(), group) {  
            qrd = parent;
      }
      virtual ~QalculateExpressionToolTip() {}

protected:

      void maybeTip(const QPoint &p) {
            int cx = qrd->contentsX();
            int cy = qrd->contentsY();
            QString str = qrd->anchorAt(qrd->viewportToContents(p), Qt::AnchorName);
            if(str.isEmpty()) return;
            int w = 5;
            while(p.x() + w < qrd->visibleWidth() && qrd->anchorAt(QPoint(p.x() + cx + w, p.y() + cy), Qt::AnchorName) == str) {
                  w += 5;
            }
            int x = p.x() - 5;
            w += 5;
            while(x > 0 && qrd->anchorAt(QPoint(x + cx, p.y() + cy), Qt::AnchorName) == str) {
                  x -= 5;
                  w += 5;
            }
            if(x < 0) x = 0;
            if(w + x > qrd->visibleWidth()) w = qrd->visibleWidth() - x;
            int h = 5;
            while(p.y() + h < qrd->visibleHeight() && qrd->anchorAt(QPoint(p.x() + cx, p.y() + cy + h), Qt::AnchorName) == str) {
                  h += 5;
            }
            int y = p.y() - 5;
            h += 5;
            while(y > 0 && qrd->anchorAt(QPoint(p.x() + cx, y + cy), Qt::AnchorName) == str) {
                  y -= 5;
                  h += 5;
            }
            if(y < 0) y = 0;
            if(h + y > qrd->visibleHeight()) h = qrd->visibleHeight() - y;
            tip(QRect(x, y, w, h), linkInfo(str, qrd, true));
      }
      
};

QalculateResultDisplay::QalculateResultDisplay(QWidget *parent, const char *name): QTextBrowser(parent, name) {

      setResizePolicy(AutoOneFit);
      setVScrollBarMode(Auto);
      setHScrollBarMode(Auto);
      setTextFormat(Qt::RichText);
      setFrameStyle(QFrame::NoFrame);
      //setFocusPolicy(QWidget::TabFocus);
      paletteChanged();
      m_under_pointer = NULL;

      QToolTipGroup *tgroup = new QToolTipGroup(viewport());
      tooltip = new QalculateExpressionToolTip(this, tgroup);
      
      //connect(this, SIGNAL(anchorClicked(const QString&, const QString&)), this, SLOT(onAnchorClicked(const QString&, const QString&)));
      connect(this, SIGNAL(doubleClicked(int, int)), this, SLOT(onDoubleClicked(int, int)));
      if(kapp) {
            connect(kapp, SIGNAL(kdisplayPaletteChanged()), this, SLOT(paletteChanged()));
      }

}

QalculateResultDisplay::~QalculateResultDisplay() {}

void QalculateResultDisplay::setRightMargin(int i_margin) {
      setMargins(0, 0, i_margin, 0);
}

void QalculateResultDisplay::onAnchorClicked(const QString&, const QString&) {
      /*if(name.isEmpty()) return;
      QWhatsThis::display(linkInfo(name, this, true));*/
}

QPopupMenu *QalculateResultDisplay::createPopupMenu(const QPoint &pos) {

      m_under_pointer = NULL;

      QPopupMenu *menu = QTextBrowser::createPopupMenu(pos);
      menu->insertSeparator();
      mainWin->ActionStoreResult->plug(menu);
      mainWin->ActionSaveAsImage->plug(menu);
      menu->insertSeparator();
      if(mstruct && mstruct->containsType(STRUCT_ADDITION)) {
            if(evalops.structuring != STRUCTURING_FACTORIZE) {
                  mainWin->ActionFactorize->plug(menu);
            }
            if(evalops.structuring != STRUCTURING_SIMPLIFY) {
                  mainWin->ActionSimplify->plug(menu);
            }
      }
      if(mstruct && mstruct->containsUnknowns()) {
            mainWin->ActionSetUnknowns->plug(menu);
      }
      if(mstruct && (mstruct->containsType(STRUCT_ADDITION) || mstruct->containsUnknowns())) {
            menu->insertSeparator();
      }
      if(mstruct && mstruct->containsDivision()) {
            mainWin->ActionNonZeroDenominators->plug(menu);
            menu->insertSeparator();
      }
      mainWin->ActionNumericalDisplayNormal->plug(menu);
      mainWin->ActionNumericalDisplayScientific->plug(menu);
      if(!mstruct || !mstruct->containsType(STRUCT_UNIT)) {
            menu->insertSeparator();
            mainWin->ActionNumberBaseBinary->plug(menu);
            mainWin->ActionNumberBaseOctal->plug(menu);
            mainWin->ActionNumberBaseDecimal->plug(menu);
            mainWin->ActionNumberBaseHexadecimal->plug(menu);
            menu->insertSeparator();
            mainWin->ActionFractionalDisplayDecimal->plug(menu);
            mainWin->ActionFractionalDisplayDecimalTryExact->plug(menu);
            mainWin->ActionFractionalDisplayFraction->plug(menu);
            mainWin->ActionFractionalDisplayCombined->plug(menu);
      }
      menu->insertSeparator();
      mainWin->ActionAbbreviateNames->plug(menu);
      if(mstruct && mstruct->containsType(STRUCT_UNIT)) {
            menu->insertSeparator();
            mainWin->ActionConvertToUnitExpression->plug(menu);
            mainWin->ActionConvertToBaseUnits->plug(menu);
            mainWin->ActionConvertToBestUnit->plug(menu);
            menu->insertSeparator();
            mainWin->ActionEnablePrefixes->plug(menu);
            mainWin->ActionEnableUseOfAllPrefixes->plug(menu);
            mainWin->ActionEnableDenominatorPrefixes->plug(menu);
      }
      menu->insertSeparator();
      QPopupMenu *modes_menu = new QPopupMenu(menu);
      QObject::connect(modes_menu, SIGNAL(activated(int)), mainWin, SLOT(loadMode(int)));
      for(size_t i = 0; i < modes.size(); i++) {
            modes_menu->insertItem(modes[i].name, i, i);
      }
      modes_menu->insertSeparator();
      mainWin->ActionSaveModeAs->plug(modes_menu);
      mainWin->ActionDeleteMode->plug(modes_menu);
      menu->insertItem(i18n("Meta Modes"), modes_menu);
      if(parsed_text.isEmpty()) return menu;
      menu->insertSeparator();
      menu->insertItem(i18n("Show Parsed Expression"), this, SLOT(showParsedExpression()));
      QString str = anchorAt(viewportToContents(pos), Qt::AnchorName);
      if(!str.isEmpty()) {
            if(str[0] == '+') {
                  name_under_pointer = str;
                  name_under_pointer.remove(0, 1);
                  menu->insertItem(i18n("Show Object Info"), this, SLOT(showInfo()));
            } else {
                  m_under_pointer = mainWin->getResultPart(str.toInt());
                  if(m_under_pointer) {
                        if(m_under_pointer->isVector()) {
                              if(m_under_pointer->isMatrix()) {
                                    menu->insertItem(i18n("View/Edit Matrix"), this, SLOT(editMatrix()));
                              } else {
                                    menu->insertItem(i18n("View/Edit Vector"), this, SLOT(editVector()));
                              }
                        } else {
                              menu->insertItem(i18n("Show Object Info"), this, SLOT(showInfo()));
                        }
                  }
            }
      }
      curpos = viewport()->mapToGlobal(pos);
      return menu;

}

void QalculateResultDisplay::showParsedExpression() {
      QString str = i18n("Parsed expression:");
      str += "\n";
      str += parsed_text;
      QWhatsThis::display(str, curpos);
}
void QalculateResultDisplay::showInfo() {
      if(m_under_pointer) {
            QWhatsThis::display(linkInfo(m_under_pointer, this, true), curpos);
      } else {
            QWhatsThis::display(linkInfo(name_under_pointer, this, true), curpos);
      }
}
void QalculateResultDisplay::editVector() {
      mainWin->insertMatrixVector(m_under_pointer, true, false, true);
}
void QalculateResultDisplay::editMatrix() {
      mainWin->insertMatrixVector(m_under_pointer, false, false, true);
}

void QalculateResultDisplay::paletteChanged() {
      QPalette p = kapp ? kapp->palette() : palette();
      p.setBrush(QColorGroup::Base, p.brush(QPalette::Normal, QColorGroup::Background));
      p.setColor(QColorGroup::Text, p.color(QPalette::Normal, QColorGroup::Foreground));
      setPalette(p);
}

void QalculateResultDisplay::virtual_hook(int, void*) {
}

void QalculateResultDisplay::focusInEvent(QFocusEvent* fe) {
      QTextBrowser::focusInEvent(fe);
      if(fe->reason() == QFocusEvent::Tab || fe->reason() == QFocusEvent::Backtab)
            selectAll(true);
}

void QalculateResultDisplay::focusOutEvent(QFocusEvent* fe) {
      QTextBrowser::focusOutEvent(fe);
      if(fe->reason() == QFocusEvent::Tab || fe->reason() == QFocusEvent::Backtab)
            selectAll(false);
}

void QalculateResultDisplay::onDoubleClicked(int, int) {
      curpos = QCursor::pos();
      QString str = anchorAt(viewportToContents(viewport()->mapFromGlobal(curpos)), Qt::AnchorName);
      if(!str.isEmpty()) {
            if(str[0] == '+') {
                  selectAll(false);
                  name_under_pointer = str;
                  name_under_pointer.remove(0, 1);
                  showInfo();
            } else {
                  m_under_pointer = mainWin->getResultPart(str.toInt());
                  if(m_under_pointer) {
                        selectAll(false);
                        if(m_under_pointer->isVector()) {
                              if(m_under_pointer->isMatrix()) {
                                    editMatrix();
                              } else {
                                    editVector();
                              }
                        } else {
                              showInfo();
                        }
                  }
            }
      }
}

void QalculateResultDisplay::keyPressEvent(QKeyEvent *e) {

      switch (e->key()) {
            case Key_Down:
            case Key_Up:
            case Key_Left:
            case Key_Right:
                  // jump over QTextEdit's key navigation breakage.
                  // we're not interested in keyboard navigation within the text
                  QWidget::keyPressEvent(e);
                  break;
            default:
                  QTextBrowser::keyPressEvent(e);
      }
      
}

QSize QalculateResultDisplay::minimumSizeHint() const {

      QSize ms = minimumSize();
      if((ms.width() > 0) && (ms.height() > 0))
            return ms;

      int w = 100;
      if(ms.width() > 0)
            w = ms.width();

      QSimpleRichText rt("<font size=6>X</font>", font());
      rt.setWidth(100);
      QSimpleRichText rt2("<font size=2>X</font>", font());
      rt2.setWidth(100);
      int h2 = (int) (rt2.height() / 1.5);
      h2 += h2 % 2;
      int h = rt.height() * 2 + h2 + 2 * frameWidth();
      if(h < ms.height())
            h = ms.height();

      return QSize(w, h);
}

QSize QalculateResultDisplay::sizeHint() const {
      return minimumSizeHint();
}


#include "qalculateresultdisplay.moc"

Generated by  Doxygen 1.6.0   Back to index