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