• Skip to content
  • Skip to link menu
KDE 4.1 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     KGlobal::locale()->insertCatalog("krunner_calculatorrunner");
00034     Q_UNUSED(args)
00035 
00036     setObjectName(i18n("Calculator"));
00037     setIgnoredTypes(Plasma::RunnerContext::Directory | Plasma::RunnerContext::File | 
00038                          Plasma::RunnerContext::NetworkLocation | Plasma::RunnerContext::Executable |
00039                          Plasma::RunnerContext::ShellCommand);
00040 }
00041 
00042 CalculatorRunner::~CalculatorRunner()
00043 {
00044 }
00045 
00046 void CalculatorRunner::powSubstitutions(QString& cmd)
00047 {
00048      if (cmd.contains("e+", Qt::CaseInsensitive)) {
00049          cmd=cmd.replace("e+", "^", Qt::CaseInsensitive);
00050      }
00051 
00052      if (cmd.contains("e-", Qt::CaseInsensitive)) {
00053          cmd=cmd.replace("e-", "^-", Qt::CaseInsensitive);
00054      }
00055 
00056     // the below code is scary mainly because we have to honor priority
00057    // honor decimal numbers and parenthesis. 
00058     if (cmd.contains('^')){
00059         int where = cmd.indexOf('^');
00060         cmd = cmd.replace('^', ',');
00061         int preIndex = where - 1;
00062         int postIndex = where + 1;
00063         int count = 0;
00064 
00065         QChar decimalSymbol = KGlobal::locale()->decimalSymbol().at(0);     
00066         //avoid out of range on weird commands 
00067         preIndex = qMax(0, preIndex);
00068         postIndex = qMin(postIndex, cmd.length()-1); 
00069 
00070         //go backwards looking for the beginning of the number or expression
00071         while (preIndex != 0) {
00072             QChar current = cmd.at(preIndex);
00073             QChar next = cmd.at(preIndex-1);
00074             //kDebug() << "index " << preIndex << " char " << current;
00075             if (current == ')') {
00076                 count++;
00077             } else if (current == '(') {
00078                 count--;
00079             } else {
00080                 if (((next < '9' ) && (next > '0')) || next == decimalSymbol) {
00081                     preIndex--;
00082                     continue;
00083                 }
00084             }
00085             if (count == 0) {
00086                 break;
00087             }
00088             preIndex--;
00089         }
00090 
00091        //go forwards looking for the end of the number or expression
00092         count = 0;
00093         while (postIndex != cmd.size() - 1) { 
00094             QChar current=cmd.at(postIndex);
00095             QChar next=cmd.at(postIndex + 1);
00096             if (current == '(') {
00097                 count++;
00098             } else if (current == ')') {
00099                 count--;
00100             } else {
00101                 if (((next < '9' ) && (next > '0')) || next == decimalSymbol) {
00102                     postIndex++;
00103                     continue;
00104                  }
00105             }
00106             if (count == 0) {
00107                 break;
00108             }
00109             postIndex++;
00110         }   
00111        
00112         preIndex = qMax(0, preIndex);
00113         postIndex = qMin(postIndex, cmd.length()); 
00114 
00115         cmd.insert(preIndex,"pow(");
00116         // +1 +4 == next position to the last number after we add 4 new characters pow(
00117         cmd.insert(postIndex + 1 + 4, ')'); 
00118         //kDebug() << "from" << preIndex << " to " << postIndex << " got: " << cmd;
00119     }
00120 }
00121 
00122 void CalculatorRunner::hexSubstitutions(QString& cmd)
00123 {
00124     if (cmd.contains("0x")) {
00125         bool ok;
00126         int pos = 0;
00127         QString hex;
00128 
00129         for (int i = 0; i < cmd.size(); i++) {
00130             hex.clear();
00131             pos = cmd.indexOf("0x", pos);
00132 
00133             for (int q = 0; q < cmd.size(); q++) {//find end of hex number
00134                 QChar current = cmd[pos+q+2];
00135                 if (((current <= '9' ) && (current >= '0')) || ((current <= 'F' ) && (current >= 'A'))) { //Check if valid hex sign
00136                     hex[q] = current;
00137                 } else {
00138                     break;
00139                 }
00140             }
00141             cmd = cmd.replace("0x" + hex,QString::number(hex.toInt(&ok,16))); //replace hex with decimal
00142         }
00143     } 
00144 
00145 }
00146 
00147 void CalculatorRunner::userFriendlySubstitutions(QString& cmd)
00148 {
00149     if (cmd.contains(KGlobal::locale()->decimalSymbol(), Qt::CaseInsensitive)) {
00150          cmd=cmd.replace(KGlobal::locale()->decimalSymbol(), ".", Qt::CaseInsensitive);
00151     }
00152 
00153     hexSubstitutions(cmd);
00154 
00155     powSubstitutions(cmd);
00156 
00157     if (cmd.contains(QRegExp("\\d+and\\d+"))) {
00158          cmd = cmd.replace(QRegExp("(\\d+)and(\\d+)"), "\\1&\\2");
00159     }
00160     if (cmd.contains(QRegExp("\\d+or\\d+"))) {
00161          cmd = cmd.replace(QRegExp("(\\d+)or(\\d+)"), "\\1|\\2");
00162     }
00163     if (cmd.contains(QRegExp("\\d+xor\\d+"))) {
00164          cmd = cmd.replace(QRegExp("(\\d+)xor(\\d+)"), "\\1^\\2");
00165     }
00166    
00167 }
00168 
00169 
00170 void CalculatorRunner::match(Plasma::RunnerContext &context)
00171 {
00172     const QString term = context.query();
00173     QString cmd = term;
00174 
00175     //no meanless space between friendly guys: helps simplify code
00176     cmd = cmd.trimmed().replace(" ", "");
00177 
00178     if (cmd.length() < 4) {
00179         return;
00180     }
00181     bool toHex = cmd.startsWith("hex=");
00182 
00183     if (!toHex && (cmd[0] != '=')) {
00184         return;
00185     }
00186 
00187     cmd = cmd.remove(0, cmd.indexOf('=')+1);
00188 
00189     if (cmd.isEmpty()) {
00190         return;
00191     }
00192 
00193     userFriendlySubstitutions(cmd);
00194     cmd.replace(QRegExp("([a-zA-Z]+)"), "Math.\\1"); //needed for accessing math funktions like sin(),....
00195 
00196     QString result = calculate(cmd);
00197 
00198     if (!result.isEmpty() && result != cmd) {
00199         if (toHex) {
00200             result = "0x" + QString::number(result.toInt(), 16).toUpper();
00201         }
00202 
00203         Plasma::QueryMatch match(this);
00204         match.setType(Plasma::QueryMatch::InformationalMatch);
00205         match.setIcon(KIcon("accessories-calculator"));
00206         match.setText(result);
00207         match.setData("= " + result);
00208         match.setId(QString());
00209         context.addMatch(term, match);
00210     }
00211 }
00212 
00213 QString CalculatorRunner::calculate( const QString& term )
00214 {
00215     //kDebug() << "calculating" << term;
00216     QScriptEngine eng;
00217     QScriptValue result = eng.evaluate(term);
00218 
00219     if (result.isError()) {
00220         return QString();
00221     }
00222 
00223     return result.toString();
00224 }
00225 
00226 #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
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
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