• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Plasma

calculatorrunner.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright (C) 2007 Barış Metin <baris@pardus.org.tr>
00003  *   Copyright (C) 2006 David Faure <faure@kde.org>
00004  *   Copyright (C) 2007 Richard Moore <rich@kde.org>
00005  *
00006  *   This program is free software; you can redistribute it and/or modify
00007  *   it under the terms of the GNU Library General Public License version 2 as
00008  *   published by the Free Software Foundation
00009  *
00010  *   This program is distributed in the hope that it will be useful,
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *   GNU General Public License for more details
00014  *
00015  *   You should have received a copy of the GNU Library General Public
00016  *   License along with this program; if not, write to the
00017  *   Free Software Foundation, Inc.,
00018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  */
00020 
00021 #include "calculatorrunner.h"
00022 
00023 #include <QHBoxLayout>
00024 #include <QLabel>
00025 #include <QWidget>
00026 #include <QScriptEngine>
00027 
00028 #include <KIcon>
00029 
00030 CalculatorRunner::CalculatorRunner( QObject* parent, const QVariantList &args )
00031     : Plasma::AbstractRunner(parent, args)
00032 {
00033     Q_UNUSED(args)
00034 
00035     setObjectName("Calculator");
00036     setIgnoredTypes(Plasma::RunnerContext::Directory | Plasma::RunnerContext::File | 
00037                          Plasma::RunnerContext::NetworkLocation | Plasma::RunnerContext::Executable |
00038                          Plasma::RunnerContext::ShellCommand);
00039 }
00040 
00041 CalculatorRunner::~CalculatorRunner()
00042 {
00043 }
00044 
00045 void CalculatorRunner::powSubstitutions(QString& cmd)
00046 {
00047      if (cmd.contains("e+", Qt::CaseInsensitive)) {
00048          cmd=cmd.replace("e+", "^", Qt::CaseInsensitive);
00049      }
00050 
00051      if (cmd.contains("e-", Qt::CaseInsensitive)) {
00052          cmd=cmd.replace("e-", "^-", Qt::CaseInsensitive);
00053      }
00054 
00055     // the below code is scary mainly because we have to honor priority
00056    // honor decimal numbers and parenthesis. 
00057     if (cmd.contains('^')){
00058         int where = cmd.indexOf('^');
00059         cmd = cmd.replace('^', ',');
00060         int preIndex = where - 1;
00061         int postIndex = where + 1;
00062         int count = 0;
00063 
00064         QChar decimalSymbol = KGlobal::locale()->decimalSymbol().at(0);
00065         //avoid out of range on weird commands 
00066         preIndex = qMax(0, preIndex);
00067         postIndex = qMin(postIndex, cmd.length()-1);
00068 
00069         //go backwards looking for the beginning of the number or expression
00070         while (preIndex != 0) {
00071             QChar current = cmd.at(preIndex);
00072             QChar next = cmd.at(preIndex-1);
00073             //kDebug() << "index " << preIndex << " char " << current;
00074             if (current == ')') {
00075                 count++;
00076             } else if (current == '(') {
00077                 count--;
00078             } else {
00079                 if (((next <= '9' ) && (next >= '0')) || next == decimalSymbol) {
00080                     preIndex--;
00081                     continue;
00082                 }
00083             }
00084             if (count == 0) {
00085                 break;
00086             }
00087             preIndex--;
00088         }
00089 
00090        //go forwards looking for the end of the number or expression
00091         count = 0;
00092         while (postIndex != cmd.size() - 1) { 
00093             QChar current=cmd.at(postIndex);
00094             QChar next=cmd.at(postIndex + 1);
00095             if (current == '(') {
00096                 count++;
00097             } else if (current == ')') {
00098                 count--;
00099             } else {
00100                 if (((next <= '9' ) && (next >= '0')) || next == decimalSymbol) {
00101                     postIndex++;
00102                     continue;
00103                  }
00104             }
00105             if (count == 0) {
00106                 break;
00107             }
00108             postIndex++;
00109         }
00110 
00111         preIndex = qMax(0, preIndex);
00112         postIndex = qMin(postIndex, cmd.length()); 
00113 
00114         cmd.insert(preIndex,"pow(");
00115         // +1 +4 == next position to the last number after we add 4 new characters pow(
00116         cmd.insert(postIndex + 1 + 4, ')'); 
00117         //kDebug() << "from" << preIndex << " to " << postIndex << " got: " << cmd;
00118     }
00119 }
00120 
00121 void CalculatorRunner::hexSubstitutions(QString& cmd)
00122 {
00123     if (cmd.contains("0x")) {
00124         bool ok;
00125         int pos = 0;
00126         QString hex;
00127 
00128         for (int i = 0; i < cmd.size(); i++) {
00129             hex.clear();
00130             pos = cmd.indexOf("0x", pos);
00131 
00132             for (int q = 0; q < cmd.size(); q++) {//find end of hex number
00133                 QChar current = cmd[pos+q+2];
00134                 if (((current <= '9' ) && (current >= '0')) || ((current <= 'F' ) && (current >= 'A'))) { //Check if valid hex sign
00135                     hex[q] = current;
00136                 } else {
00137                     break;
00138                 }
00139             }
00140             cmd = cmd.replace("0x" + hex,QString::number(hex.toInt(&ok,16))); //replace hex with decimal
00141         }
00142     } 
00143 
00144 }
00145 
00146 void CalculatorRunner::userFriendlySubstitutions(QString& cmd)
00147 {
00148     if (cmd.contains(KGlobal::locale()->decimalSymbol(), Qt::CaseInsensitive)) {
00149          cmd=cmd.replace(KGlobal::locale()->decimalSymbol(), ".", Qt::CaseInsensitive);
00150     }
00151 
00152     hexSubstitutions(cmd);
00153     powSubstitutions(cmd);
00154 
00155     if (cmd.contains(QRegExp("\\d+and\\d+"))) {
00156          cmd = cmd.replace(QRegExp("(\\d+)and(\\d+)"), "\\1&\\2");
00157     }
00158     if (cmd.contains(QRegExp("\\d+or\\d+"))) {
00159          cmd = cmd.replace(QRegExp("(\\d+)or(\\d+)"), "\\1|\\2");
00160     }
00161     if (cmd.contains(QRegExp("\\d+xor\\d+"))) {
00162          cmd = cmd.replace(QRegExp("(\\d+)xor(\\d+)"), "\\1^\\2");
00163     }
00164 }
00165 
00166 
00167 void CalculatorRunner::match(Plasma::RunnerContext &context)
00168 {
00169     const QString term = context.query();
00170     QString cmd = term;
00171 
00172     //no meanless space between friendly guys: helps simplify code
00173     cmd = cmd.trimmed().replace(" ", "");
00174 
00175     if (cmd.length() < 4) {
00176         return;
00177     }
00178 
00179     bool toHex = cmd.startsWith("hex=");
00180     bool startsWithEquals = !toHex && cmd[0] == '=';
00181 
00182     if (toHex || startsWithEquals) {
00183         cmd.remove(0, cmd.indexOf('=') + 1);
00184     } else if (cmd.endsWith('=')) {
00185         cmd.chop(1);
00186     } else {
00187         // we don't have an actionable equation here
00188         return;
00189     }
00190 
00191     if (cmd.isEmpty()) {
00192         return;
00193     }
00194 
00195     userFriendlySubstitutions(cmd);
00196     cmd.replace(QRegExp("([a-zA-Z]+)"), "Math.\\1"); //needed for accessing math funktions like sin(),....
00197 
00198     QString result = calculate(cmd);
00199 
00200     if (!result.isEmpty() && result != cmd) {
00201         if (toHex) {
00202             result = "0x" + QString::number(result.toInt(), 16).toUpper();
00203         }
00204 
00205         Plasma::QueryMatch match(this);
00206         match.setType(Plasma::QueryMatch::InformationalMatch);
00207         match.setIcon(KIcon("accessories-calculator"));
00208         match.setText(result);
00209         match.setData("= " + result);
00210         match.setId(QString());
00211         context.addMatch(term, match);
00212     }
00213 }
00214 
00215 QString CalculatorRunner::calculate(const QString& term)
00216 {
00217     //kDebug() << "calculating" << term;
00218     QScriptEngine eng;
00219     QScriptValue result = eng.evaluate(term);
00220 
00221     if (result.isError()) {
00222         return QString();
00223     }
00224 
00225     return result.toString();
00226 }
00227 
00228 #include "calculatorrunner.moc"

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal