Plasma
calculatorrunner.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00057
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
00067 preIndex = qMax(0, preIndex);
00068 postIndex = qMin(postIndex, cmd.length()-1);
00069
00070
00071 while (preIndex != 0) {
00072 QChar current = cmd.at(preIndex);
00073 QChar next = cmd.at(preIndex-1);
00074
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
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
00117 cmd.insert(postIndex + 1 + 4, ')');
00118
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++) {
00134 QChar current = cmd[pos+q+2];
00135 if (((current <= '9' ) && (current >= '0')) || ((current <= 'F' ) && (current >= 'A'))) {
00136 hex[q] = current;
00137 } else {
00138 break;
00139 }
00140 }
00141 cmd = cmd.replace("0x" + hex,QString::number(hex.toInt(&ok,16)));
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
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");
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
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"