summaryrefslogtreecommitdiffstats
path: root/src/qalculateresultdisplay.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qalculateresultdisplay.cpp')
-rw-r--r--src/qalculateresultdisplay.cpp495
1 files changed, 495 insertions, 0 deletions
diff --git a/src/qalculateresultdisplay.cpp b/src/qalculateresultdisplay.cpp
new file mode 100644
index 0000000..91f5667
--- /dev/null
+++ b/src/qalculateresultdisplay.cpp
@@ -0,0 +1,495 @@
+/***************************************************************************
+ * 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);
+ }
+ } else if(mstruct && mstruct->isNumber() && mstruct->number().isInteger() && !mstruct->number().isZero()) {
+ mainWin->ActionFactorize->plug(menu);
+ menu->insertSeparator();
+ }
+ 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();
+ }
+ int id = menu->insertItem(i18n("Normal"));
+ if(printops.min_exp == EXP_PRECISION) menu->setItemChecked(id, true);
+ else menu->connectItem(id, this, SLOT(displayNormal()));
+ id = menu->insertItem(i18n("Engineering"));
+ if(printops.min_exp == EXP_BASE_3) menu->setItemChecked(id, true);
+ else menu->connectItem(id, this, SLOT(displayEngineering()));
+ id = menu->insertItem(i18n("Scientific"));
+ if(printops.min_exp == EXP_SCIENTIFIC) menu->setItemChecked(id, true);
+ else menu->connectItem(id, this, SLOT(displayScientific()));
+ /*mainWin->ActionNumericalDisplayNormal->plug(menu);
+ mainWin->ActionNumericalDisplayEngineering->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(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::displayNormal() {
+ printops.negative_exponents = false;
+ printops.sort_options.minus_last = true;
+ mainWin->ActionNumericalDisplayNormal->activate();
+ mainWin->ActionNegativeExponents->setChecked(false);
+ mainWin->ActionSortMinusLast->setChecked(true);
+}
+void QalculateResultDisplay::displayEngineering() {
+ mainWin->ActionNumericalDisplayEngineering->activate();
+}
+void QalculateResultDisplay::displayScientific() {
+ printops.negative_exponents = true;
+ printops.sort_options.minus_last = false;
+ mainWin->ActionNumericalDisplayScientific->activate();
+ mainWin->ActionNegativeExponents->setChecked(true);
+ mainWin->ActionSortMinusLast->setChecked(false);
+}
+
+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"