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 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
00056
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
00066 preIndex = qMax(0, preIndex);
00067 postIndex = qMin(postIndex, cmd.length()-1);
00068
00069
00070 while (preIndex != 0) {
00071 QChar current = cmd.at(preIndex);
00072 QChar next = cmd.at(preIndex-1);
00073
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
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
00116 cmd.insert(postIndex + 1 + 4, ')');
00117
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++) {
00133 QChar current = cmd[pos+q+2];
00134 if (((current <= '9' ) && (current >= '0')) || ((current <= 'F' ) && (current >= 'A'))) {
00135 hex[q] = current;
00136 } else {
00137 break;
00138 }
00139 }
00140 cmd = cmd.replace("0x" + hex,QString::number(hex.toInt(&ok,16)));
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
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
00188 return;
00189 }
00190
00191 if (cmd.isEmpty()) {
00192 return;
00193 }
00194
00195 userFriendlySubstitutions(cmd);
00196 cmd.replace(QRegExp("([a-zA-Z]+)"), "Math.\\1");
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
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"