Qalculate! – TDE frontend for the ultimate desktop calculator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
qalculate-tde/src/qalculateresultdisplay.cpp

496 lines
16 KiB

/***************************************************************************
* 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 <vector>
#include <tdepopupmenu.h>
#include <kxmlguifactory.h>
#include <kxmlguiclient.h>
#include <tdeaction.h>
#include <tdemessagebox.h>
#include <tqwhatsthis.h>
#include <tqtooltip.h>
#include <tdelocale.h>
#include <tdeapplication.h>
#include <tqsimplerichtext.h>
extern std::vector<mode_struct> 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 += "<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 += TQString::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>";
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("<", "&lt;");
str2.replace(">", "&gt;");
str += str2;
}
if(!f->description().empty()) {
str += "<br>";
str += "<br>";
TQString str2 = f->description().c_str();
str2.replace("<", "&lt;");
str2.replace(">", "&gt;");
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("<font size=6>X</font>", font());
rt.setWidth(100);
TQSimpleRichText 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 TQSize(w, h);
}
TQSize QalculateResultDisplay::sizeHint() const {
return minimumSizeHint();
}
#include "qalculateresultdisplay.moc"