Initial replace for nokia USSD implementation
[ussd-widget] / qussd / main.cpp
1 #include <QtGui>
2 #include <iostream>
3 #include <string.h>
4 #include <QtDBus/QtDBus>
5
6 #define PROCESSING "Processing..."
7
8 class QUssd : public QMainWindow {
9         Q_OBJECT
10
11         public:
12                 QUssd(QString message, bool lock = false) {
13                         number = "";
14
15                         QActionGroup *filterGroup = new QActionGroup(this);
16                         filterGroup->setExclusive(true);
17
18                         actPortrait = new QAction(tr("Portrait"), filterGroup);
19                         actPortrait->setCheckable(true);
20
21                         actLandscape = new QAction(tr("Landscape"), filterGroup);
22                         actLandscape->setCheckable(true);
23
24                         actAuto = new QAction(tr("Auto"), filterGroup);
25                         actAuto->setCheckable(true);
26                         actAuto->setChecked(true);
27                 
28                         menuBar()->addActions(filterGroup->actions());
29
30                         connect(actPortrait, SIGNAL(changed()), this, SLOT(setOrientation()));
31                         connect(actLandscape, SIGNAL(changed()), this, SLOT(setOrientation()));
32                         connect(actAuto, SIGNAL(changed()), this, SLOT(setOrientation()));
33
34                         replyLabel = new QLabel(message);
35                         replyLabel->setMinimumWidth(400);
36                         replyLabel->setMaximumHeight(100);
37                         replyLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
38
39                         numberLabel = new QLabel("");
40                         replyLabel->setMinimumWidth(400);
41                         replyLabel->setMinimumHeight(150);
42                         replyLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
43
44                         indicationLayout = new QVBoxLayout;
45                         indicationLayout->addWidget(numberLabel);
46                         indicationLayout->addWidget(replyLabel);
47
48                         padDel = new QPushButton("C");
49                         connect(padDel, SIGNAL(clicked()), this, SLOT(del()));
50                         padDel->setMaximumWidth(150);
51                         padDel->setMaximumHeight(72);
52                         padDel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
53                         padSend = new QPushButton("SEND");
54                         connect(padSend, SIGNAL(clicked()), this, SLOT(send()));
55                         padSend->setMaximumWidth(300);
56                         padSend->setMaximumHeight(72);
57                         padSend->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
58
59                         btnLayout = new QHBoxLayout;
60                         btnLayout->addWidget(padSend);
61                         btnLayout->addWidget(padDel);
62
63                         numberPad = new QGridLayout();
64                         numberPad->setSpacing(2);
65
66                         padBtn1 = new QPushButton("1");
67                         connect(padBtn1, SIGNAL(clicked()), this, SLOT(add1()));
68                         padBtn1->setMaximumWidth(150);
69                         padBtn1->setMaximumHeight(72);
70                         padBtn1->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
71                         numberPad->addWidget(padBtn1, 0, 0);
72                         padBtn2 = new QPushButton("2");
73                         connect(padBtn2, SIGNAL(clicked()), this, SLOT(add2()));
74                         padBtn2->setMaximumWidth(150);
75                         padBtn2->setMaximumHeight(72);
76                         padBtn2->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
77                         numberPad->addWidget(padBtn2, 0, 1);
78                         padBtn3 = new QPushButton("3");
79                         connect(padBtn3, SIGNAL(clicked()), this, SLOT(add3()));
80                         padBtn3->setMaximumWidth(150);
81                         padBtn3->setMaximumHeight(72);
82                         padBtn3->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
83                         numberPad->addWidget(padBtn3, 0, 2);
84                         padBtn4 = new QPushButton("4");
85                         connect(padBtn4, SIGNAL(clicked()), this, SLOT(add4()));
86                         padBtn4->setMaximumWidth(150);
87                         padBtn4->setMaximumHeight(72);
88                         padBtn4->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
89                         numberPad->addWidget(padBtn4, 1, 0);
90                         padBtn5 = new QPushButton("5");
91                         connect(padBtn5, SIGNAL(clicked()), this, SLOT(add5()));
92                         padBtn5->setMaximumWidth(150);
93                         padBtn5->setMaximumHeight(72);
94                         padBtn5->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
95                         numberPad->addWidget(padBtn5, 1, 1);
96                         padBtn6 = new QPushButton("6");
97                         connect(padBtn6, SIGNAL(clicked()), this, SLOT(add6()));
98                         padBtn6->setMaximumWidth(150);
99                         padBtn6->setMaximumHeight(72);
100                         padBtn6->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
101                         numberPad->addWidget(padBtn6, 1, 2);
102                         padBtn7 = new QPushButton("7");
103                         connect(padBtn7, SIGNAL(clicked()), this, SLOT(add7()));
104                         padBtn7->setMaximumWidth(150);
105                         padBtn7->setMaximumHeight(72);
106                         padBtn7->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
107                         numberPad->addWidget(padBtn7, 2, 0);
108                         padBtn8 = new QPushButton("8");
109                         connect(padBtn8, SIGNAL(clicked()), this, SLOT(add8()));
110                         padBtn8->setMaximumWidth(150);
111                         padBtn8->setMaximumHeight(72);
112                         padBtn8->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
113                         numberPad->addWidget(padBtn8, 2, 1);
114                         padBtn9 = new QPushButton("9");
115                         connect(padBtn9, SIGNAL(clicked()), this, SLOT(add9()));
116                         padBtn9->setMaximumWidth(150);
117                         padBtn9->setMaximumHeight(72);
118                         padBtn9->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
119                         numberPad->addWidget(padBtn9, 2, 2);
120                         padBtnStar = new QPushButton("*+");
121                         connect(padBtnStar, SIGNAL(clicked()), this, SLOT(addStar()));
122                         padBtnStar->setMaximumWidth(150);
123                         padBtnStar->setMaximumHeight(72);
124                         padBtnStar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
125                         numberPad->addWidget(padBtnStar, 3, 0);
126                         padBtn0 = new QPushButton("0");
127                         connect(padBtn0, SIGNAL(clicked()), this, SLOT(add0()));
128                         padBtn0->setMaximumWidth(150);
129                         padBtn0->setMaximumHeight(72);
130                         padBtn0->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
131                         numberPad->addWidget(padBtn0, 3, 1);
132                         padBtnGrid = new QPushButton("#");
133                         connect(padBtnGrid, SIGNAL(clicked()), this, SLOT(addGrid()));
134                         padBtnGrid->setMaximumWidth(150);
135                         padBtnGrid->setMaximumHeight(72);
136                         padBtnGrid->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
137                         numberPad->addWidget(padBtnGrid, 3, 2);
138
139                         centralWidget = new QWidget;
140                         setCentralWidget(centralWidget);
141                         mainLayout = new QGridLayout(centralWidget);
142
143                         connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(orientationChanged()));
144                         setOrientation();
145                         orientationChanged();
146
147                         startUSSD (lock);
148                 }
149
150                 ~QUssd () {
151                         USSDquery->write("exit\n");
152                         USSDquery->closeWriteChannel();
153                         USSDquery->waitForFinished();
154
155                         delete USSDquery;
156                 }
157
158         public slots:
159                 void restartUSSD( int, QProcess::ExitStatus) {
160                         replyLabel->setText(QString("Error: ")+QString::fromUtf8(reply));
161                         reply = "";
162                         number = "";
163                         setNumber();
164
165                         delete USSDquery;
166                         startUSSD ();
167                 }
168
169
170                 void send() {
171                         QDBusInterface iface("su.kibergus.ussdd", "/su/kibergus/ussdd", "su.kibergus.ussdd", QDBusConnection::systemBus());
172                         if (iface.isValid())
173                                 iface.call("skip_next");
174                         USSDquery->write(number.toUtf8().data());
175                         USSDquery->write("\n");
176                         number = tr(PROCESSING);
177                         setNumber();
178                 }
179
180                 void readData() {
181                         QByteArray line;
182                         for (line = USSDquery->readLine(); !line.isEmpty(); line = USSDquery->readLine()) {
183                                 reply += line;
184                                 if (reply.endsWith("\n==MESSAGE END ==\n")) {
185                                         reply.chop(strlen("\n==MESSAGE END ==\n"));
186                                         if (!reply.isEmpty())
187                                                 replyLabel->setText(QString::fromUtf8(reply));
188                                         reply = "";
189                                         number = "";
190                                         setNumber();
191                                         break;
192                                 }
193                         }
194                 }
195
196                 void setOrientation() {
197                         if (actLandscape->isChecked())
198                                 setAttribute(Qt::WA_Maemo5LandscapeOrientation, true);
199                         else if (actPortrait->isChecked())
200                                 setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
201                         else
202                                 setAttribute(Qt::WA_Maemo5AutoOrientation, true);
203                 }
204
205                 void orientationChanged() {
206                         QRect screenGeometry = QApplication::desktop()->screenGeometry();
207                         mainLayout->removeItem(indicationLayout);
208                         mainLayout->removeItem(numberPad);
209                         mainLayout->removeItem(btnLayout);
210                         
211                         if (screenGeometry.width() > screenGeometry.height()) {
212                                 mainLayout->addLayout(indicationLayout, 0, 0);
213                                 mainLayout->addLayout(btnLayout, 1, 0);
214                                 mainLayout->addLayout(numberPad, 0, 1, -1, 1);
215                         } else {
216                                 mainLayout->addLayout(indicationLayout, 0, 0);
217                                 mainLayout->addLayout(numberPad, 1, 0);
218                                 mainLayout->addLayout(btnLayout, 2, 0);
219                         }
220                 }
221         
222                 void add1 () {
223                         if (number != tr(PROCESSING)) {
224                                 number += "1";
225                                 setNumber();
226                         }
227                 }
228
229                 void add2 () {
230                         if (number != tr(PROCESSING)) {
231                                 number += "2";
232                                 setNumber();
233                         }
234                 }
235
236                 void add3 () {
237                         if (number != tr(PROCESSING)) {
238                                 number += "3";
239                                 setNumber();
240                         }
241                 }
242
243                 void add4 () {
244                         if (number != tr(PROCESSING)) {
245                                 number += "4";
246                                 setNumber();
247                         }
248                 }
249
250                 void add5 () {
251                         if (number != tr(PROCESSING)) {
252                                 number += "5";
253                                 setNumber();
254                         }
255                 }
256
257                 void add6 () {
258                         if (number != tr(PROCESSING)) {
259                                 number += "6";
260                                 setNumber();
261                         }
262                 }
263         
264                 void add7 () {
265                         if (number != tr(PROCESSING)) {
266                                 number += "7";
267                                 setNumber();
268                         }
269                 }
270
271                 void add8 () {
272                         if (number != tr(PROCESSING)) {
273                                 number += "8";
274                                 setNumber();
275                         }
276                 }
277
278                 void add9 () {
279                         if (number != tr(PROCESSING)) {
280                                 number += "9";
281                                 setNumber();
282                         }
283                 }
284
285                 void add0 () {
286                         if (number != tr(PROCESSING)) {
287                                 number += "0";
288                                 setNumber();
289                         }
290                 }
291
292                 void addGrid () {
293                         if (number != tr(PROCESSING)) {
294                                 number += "#";
295                                 setNumber();
296                         }
297                 }
298
299                 void addStar () {
300                         if (number != tr(PROCESSING)) {
301                                 if (number[number.length()-1] == '*') {
302                                         number[number.length()-1] = '+';
303                                 } else
304                                         number += "*";
305                                 setNumber();
306                         }
307                 }
308
309                 void del () {
310                         if (number != tr(PROCESSING)) {
311                                 number.chop(1);
312                                 setNumber();
313                         }
314                 }
315
316         private:
317                 void startUSSD (bool lock = false) {
318                         QString program = "ussdquery.py";
319                         QStringList arguments;
320                         arguments << "interactive" << "-d" << "\n==MESSAGE END ==\n";
321                         if (lock)
322                                 arguments << "-m";
323
324                         USSDquery = new QProcess();
325                         USSDquery->setProcessChannelMode(QProcess::MergedChannels);
326                         connect(USSDquery, SIGNAL(readyReadStandardOutput()), this, SLOT(readData()));
327                         connect(USSDquery, SIGNAL(readyReadStandardError()), this, SLOT(readData()));
328                         connect(USSDquery, SIGNAL(finished( int, QProcess::ExitStatus )), this, SLOT(restartUSSD( int, QProcess::ExitStatus )));
329
330                         USSDquery->start(program, arguments);
331                 }
332
333                 void setNumber () {
334                         numberLabel->setText(QString("<p style=\"font-size: 30pt;\" align=\"center\">")+number+"</p>");
335                 }
336
337                 QLabel *replyLabel;
338                 QLabel *numberLabel;
339                 QAction *actPortrait;
340                 QAction *actLandscape;
341                 QAction *actAuto;
342
343                 QVBoxLayout *indicationLayout;
344                 QHBoxLayout *btnLayout;
345                 QGridLayout *numberPad;
346                 QGridLayout *mainLayout;
347                 QWidget* centralWidget;
348
349                 QPushButton *padBtn1;
350                 QPushButton *padBtn2;
351                 QPushButton *padBtn3;
352                 QPushButton *padBtn4;
353                 QPushButton *padBtn5;
354                 QPushButton *padBtn6;
355                 QPushButton *padBtn7;
356                 QPushButton *padBtn8;
357                 QPushButton *padBtn9;
358                 QPushButton *padBtn0;
359                 QPushButton *padBtnStar;
360                 QPushButton *padBtnGrid;
361
362                 QPushButton *padDel;
363                 QPushButton *padSend;
364
365                 QProcess *USSDquery;
366
367                 QString number;
368                 QByteArray reply;
369 };
370
371 int main(int argc, char *argv[]) {
372         QApplication app(argc, argv);
373
374         bool lock = false;
375         QString message;
376         if (argc >= 2)
377                 message = message.fromUtf8(argv[1]);
378         if (argc >=3 && !strcmp(argv[2], "lock"))
379                 lock = true;
380
381         QUssd w(message, lock);
382         w.show();
383         
384         return app.exec();
385 }
386
387 #include "main.moc"