/*************************************************************************** * 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_tde_utils.h" #include "kqalculate.h" #include #include #include #include #include #include #include #include #include #include #include extern std::vector modes; extern TQString parsed_text; extern KQalculate *mainWin; extern MathStructure *mstruct; extern PrintOptions printops; extern EvaluationOptions evalops; TQString linkInfo(const MathStructure *m, TQWidget *w, bool full_length = false) { TQString 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 += ": "; TQString pstr; switch(m->prefix()->type()) { case PREFIX_DECIMAL: { TQTextOStream(&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: { TQTextOStream(&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: { TQTextOStream(&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 += "
"; const ExpressionName *ename = &f->preferredName(false, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) w); str += ""; str += ename->name.c_str(); str += ""; 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 += TQString::number(i2); } if(i2 > f->minargs()) { str += "]"; } } if(f->maxargs() < 0) { str += CALCULATOR->getComma().c_str(); str += " ..."; } } str += ")"; str += ""; if(full_length) { str += ""; for(size_t i2 = 1; i2 <= f->countNames(); i2++) { if(&f->getName(i2) != ename) { str += "
"; str += f->getName(i2).name.c_str(); } } str += "
"; if(f->subtype() == SUBTYPE_DATA_SET) { str += "
"; str += "
"; TQString 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("<", "<"); str2.replace(">", ">"); str += str2; } if(!f->description().empty()) { str += "
"; str += "
"; TQString str2 = f->description().c_str(); str2.replace("<", "<"); str2.replace(">", ">"); str += str2; } } } } return str; } TQString linkInfo(const TQString &link, TQWidget *w, bool full_length = false) { if(!link.isEmpty() && link[0] == '+') { TQString str = link; str.remove(0, 1); return str; } else { return linkInfo(mainWin->getResultPart(link.toInt()), w, full_length); } } class QalculateExpressionToolTip : public TQToolTip { public: QalculateResultDisplay *qrd; QalculateExpressionToolTip(QalculateResultDisplay *parent, TQToolTipGroup *group = 0) : TQToolTip(parent->viewport(), group) { qrd = parent; } virtual ~QalculateExpressionToolTip() {} protected: void maybeTip(const TQPoint &p) { int cx = qrd->contentsX(); int cy = qrd->contentsY(); TQString str = qrd->anchorAt(qrd->viewportToContents(p), TQt::AnchorName); if(str.isEmpty()) return; int w = 5; while(p.x() + w < qrd->visibleWidth() && qrd->anchorAt(TQPoint(p.x() + cx + w, p.y() + cy), TQt::AnchorName) == str) { w += 5; } int x = p.x() - 5; w += 5; while(x > 0 && qrd->anchorAt(TQPoint(x + cx, p.y() + cy), TQt::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(TQPoint(p.x() + cx, p.y() + cy + h), TQt::AnchorName) == str) { h += 5; } int y = p.y() - 5; h += 5; while(y > 0 && qrd->anchorAt(TQPoint(p.x() + cx, y + cy), TQt::AnchorName) == str) { y -= 5; h += 5; } if(y < 0) y = 0; if(h + y > qrd->visibleHeight()) h = qrd->visibleHeight() - y; tip(TQRect(x, y, w, h), linkInfo(str, qrd, true)); } }; QalculateResultDisplay::QalculateResultDisplay(TQWidget *parent, const char *name): TQTextBrowser(parent, name) { setResizePolicy(AutoOneFit); setVScrollBarMode(Auto); setHScrollBarMode(Auto); setTextFormat(TQt::RichText); setFrameStyle(TQFrame::NoFrame); //setFocusPolicy(TQWidget::TabFocus); paletteChanged(); m_under_pointer = NULL; TQToolTipGroup *tgroup = new TQToolTipGroup(viewport()); tooltip = new QalculateExpressionToolTip(this, tgroup); //connect(this, SIGNAL(anchorClicked(const TQString&, const TQString&)), this, SLOT(onAnchorClicked(const TQString&, const TQString&))); connect(this, SIGNAL(doubleClicked(int, int)), this, SLOT(onDoubleClicked(int, int))); if(kapp) { connect(kapp, SIGNAL(tdedisplayPaletteChanged()), this, SLOT(paletteChanged())); } } QalculateResultDisplay::~QalculateResultDisplay() {} void QalculateResultDisplay::setRightMargin(int i_margin) { setMargins(0, 0, i_margin, 0); } void QalculateResultDisplay::onAnchorClicked(const TQString&, const TQString&) { /*if(name.isEmpty()) return; TQWhatsThis::display(linkInfo(name, this, true));*/ } TQPopupMenu *QalculateResultDisplay::createPopupMenu(const TQPoint &pos) { m_under_pointer = NULL; TQPopupMenu *menu = TQTextBrowser::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(); TQPopupMenu *modes_menu = new TQPopupMenu(menu); TQObject::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())); TQString str = anchorAt(pos, TQt::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() { TQString str = i18n("Parsed expression:"); str += "\n"; str += parsed_text; TQWhatsThis::display(str, curpos); } void QalculateResultDisplay::showInfo() { if(m_under_pointer) { TQWhatsThis::display(linkInfo(m_under_pointer, this, true), curpos); } else { TQWhatsThis::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() { TQPalette p = kapp ? kapp->palette() : palette(); p.setBrush(TQColorGroup::Base, p.brush(TQPalette::Normal, TQColorGroup::Background)); p.setColor(TQColorGroup::Text, p.color(TQPalette::Normal, TQColorGroup::Foreground)); setPalette(p); } void QalculateResultDisplay::virtual_hook(int, void*) { } void QalculateResultDisplay::focusInEvent(TQFocusEvent* fe) { TQTextBrowser::focusInEvent(fe); if(fe->reason() == TQFocusEvent::Tab || fe->reason() == TQFocusEvent::Backtab) selectAll(true); } void QalculateResultDisplay::focusOutEvent(TQFocusEvent* fe) { TQTextBrowser::focusOutEvent(fe); if(fe->reason() == TQFocusEvent::Tab || fe->reason() == TQFocusEvent::Backtab) selectAll(false); } void QalculateResultDisplay::onDoubleClicked(int, int) { curpos = TQCursor::pos(); TQString str = anchorAt(viewportToContents(viewport()->mapFromGlobal(curpos)), TQt::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(TQKeyEvent *e) { switch (e->key()) { case Key_Down: case Key_Up: case Key_Left: case Key_Right: // jump over TQTextEdit's key navigation breakage. // we're not interested in keyboard navigation within the text TQWidget::keyPressEvent(e); break; default: TQTextBrowser::keyPressEvent(e); } } TQSize QalculateResultDisplay::minimumSizeHint() const { TQSize ms = minimumSize(); if((ms.width() > 0) && (ms.height() > 0)) return ms; int w = 100; if(ms.width() > 0) w = ms.width(); TQSimpleRichText rt("X", font()); rt.setWidth(100); TQSimpleRichText rt2("X", 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 TQSize(w, h); } TQSize QalculateResultDisplay::sizeHint() const { return minimumSizeHint(); } #include "qalculateresultdisplay.moc"