692b64c951a78b2ddba620361641418836348aec
[pierogi] / mainwindow.cpp
1 #include "mainwindow.h"
2 #include "ui_mainwindow.h"
3
4 #include <QtCore/QCoreApplication>
5 #include <QMutex>
6 #include <QtGui/QMessageBox>
7 //#include <QtGui>
8 #include <QSettings>
9
10 #include "pirkeysetwidgetitem.h"
11 #include "pirselectkeysetform.h"
12 #include "pirselectdeviceform.h"
13 #include "pirpanelselectionform.h"
14 #include "pirdocumentationform.h"
15 #include "piraboutform.h"
16 #include "pirkeysetmanager.h"
17 #include "pirpanelmanager.h"
18
19 //#define DEBUGGING
20
21 // Some ugly globals used for thread communications:
22
23 // A global to show that a command is being processed:
24 bool commandInFlight = false;
25 QMutex commandIFMutex;
26
27 // The stopRepeatingFlag boolean is the method used to tell running commands
28 // in the worker thread to stop:
29 bool stopRepeatingFlag = false;
30 QMutex stopRepeatingMutex;
31
32
33 extern PIRMakeMgr makeManager;
34
35
36 MainWindow::MainWindow(QWidget *parent)
37   : QMainWindow(parent),
38     ui(new Ui::MainWindow),
39     selectKeysetForm(0),
40     selectDeviceForm(0),
41     panelSelectionForm(0),
42     documentationForm(0),
43     aboutForm(0),
44     currentKeyset(0)
45 {
46   ui->setupUi(this);
47
48   // Make this a Maemo 5 stacked widget:
49   setAttribute(Qt::WA_Maemo5StackedWindow);
50
51   // Create the managers:
52   myKeysets = new PIRKeysetManager();
53   myPanels = new PIRPanelManager(this);
54
55   // Set up the keyset selection window:
56   selectKeysetForm = new PIRSelectKeysetForm(this);
57
58   // Set up the device selection window:
59   selectDeviceForm = new PIRSelectDeviceForm(this);
60
61   // Set up the panel selection window:
62   panelSelectionForm = new PIRPanelSelectionForm(this);
63
64   myKeysets->populateSelectionWidgets(selectKeysetForm, selectDeviceForm);
65 //  myPanels->setupPanels(panelSelectionForm);
66
67   // Remember any favorites the user has already set:
68   populateFavorites();
69
70   // Retrieve the user's most recent keyset (if any):
71   QSettings settings("pietrzak.org", "Pierogi");
72   if (settings.contains("currentKeysetName"))
73   {
74     myKeysets->findKeysetID(
75       settings.value("currentKeysetMake").toString(),
76       settings.value("currentKeysetName").toString(),
77       currentKeyset);
78 //    currentKeyset = settings.value("currentKeyset").toInt();
79   }
80
81   enableButtons();
82
83   QListWidget *fkw = myPanels->getFavoritesListWidget();
84
85   connect(
86     fkw,
87     SIGNAL(itemActivated(QListWidgetItem *)),
88     this,
89     SLOT(keysetSelectionChanged(QListWidgetItem *)),
90     Qt::QueuedConnection);
91
92   // Make sure the three selection lists don't show different selections:
93   QListWidget *klw = selectKeysetForm->getKeysetListWidget();
94   QListWidget *dlw = selectDeviceForm->getDeviceListWidget();
95
96   // favorites -> keyset name
97   connect(
98     fkw,
99     SIGNAL(itemActivated(QListWidgetItem *)),
100     klw,
101     SLOT(clearSelection()),
102     Qt::QueuedConnection);
103
104   // favorites -> device name
105   connect(
106     fkw,
107     SIGNAL(itemActivated(QListWidgetItem *)),
108     dlw,
109     SLOT(clearSelection()),
110     Qt::QueuedConnection);
111
112   // keyset name -> favorites
113   connect(
114     klw,
115     SIGNAL(itemActivated(QListWidgetItem *)),
116     fkw,
117     SLOT(clearSelection()),
118     Qt::QueuedConnection);
119
120   // device name -> favorites
121   connect(
122     dlw,
123     SIGNAL(itemActivated(QListWidgetItem *)),
124     fkw,
125     SLOT(clearSelection()),
126     Qt::QueuedConnection);
127
128   // keyset name -> device name
129   connect(
130     klw,
131     SIGNAL(itemActivated(QListWidgetItem *)),
132     dlw,
133     SLOT(clearSelection()),
134     Qt::QueuedConnection);
135
136   // device name -> keyset name
137   connect(
138     dlw,
139     SIGNAL(itemActivated(QListWidgetItem *)),
140     klw,
141     SLOT(clearSelection()),
142     Qt::QueuedConnection);
143
144 #ifndef DEBUGGING
145   // The PIRModprobe object should take care of setting up and shutting down
146   // the lirc_rx51 kernel module, if necessary:
147  
148   if (modprobeObj.loadRX51Module() != 0)
149   {
150     // Couldn't load module, quit:
151     QMessageBox errBox;
152     errBox.setText("Couldn't load lirc_rx51 kernel module!");
153     errBox.setIcon(QMessageBox::Warning);
154     errBox.exec();
155 //    throw; // Need a clean way to exit here!!!
156   }
157 #endif
158 }
159
160
161 MainWindow::~MainWindow()
162 {
163   delete myKeysets;
164   if (selectKeysetForm) delete selectKeysetForm;
165   if (selectDeviceForm) delete selectDeviceForm;
166   if (panelSelectionForm) delete panelSelectionForm;
167   if (documentationForm) delete documentationForm;
168   if (aboutForm) delete aboutForm;
169   delete ui;
170 }
171
172
173 void MainWindow::setOrientation(ScreenOrientation orientation)
174 {
175 #if defined(Q_OS_SYMBIAN)
176     // If the version of Qt on the device is < 4.7.2, that attribute won't work
177     if (orientation != ScreenOrientationAuto) {
178         const QStringList v = QString::fromAscii(qVersion()).split(QLatin1Char('.'));
179         if (v.count() == 3 && (v.at(0).toInt() << 16 | v.at(1).toInt() << 8 | v.at(2).toInt()) < 0x040702) {
180             qWarning("Screen orientation locking only supported with Qt 4.7.2 and above");
181             return;
182         }
183     }
184 #endif // Q_OS_SYMBIAN
185
186     Qt::WidgetAttribute attribute;
187     switch (orientation) {
188 #if QT_VERSION < 0x040702
189     // Qt < 4.7.2 does not yet have the Qt::WA_*Orientation attributes
190     case ScreenOrientationLockPortrait:
191         attribute = static_cast<Qt::WidgetAttribute>(128);
192         break;
193     case ScreenOrientationLockLandscape:
194         attribute = static_cast<Qt::WidgetAttribute>(129);
195         break;
196     default:
197     case ScreenOrientationAuto:
198         attribute = static_cast<Qt::WidgetAttribute>(130);
199         break;
200 #else // QT_VERSION < 0x040702
201     case ScreenOrientationLockPortrait:
202         attribute = Qt::WA_LockPortraitOrientation;
203         break;
204     case ScreenOrientationLockLandscape:
205         attribute = Qt::WA_LockLandscapeOrientation;
206         break;
207     default:
208     case ScreenOrientationAuto:
209         attribute = Qt::WA_AutoOrientation;
210         break;
211 #endif // QT_VERSION < 0x040702
212     };
213     setAttribute(attribute, true);
214 }
215
216 void MainWindow::showExpanded()
217 {
218 #if defined(Q_OS_SYMBIAN) || defined(Q_WS_SIMULATOR)
219     showFullScreen();
220 #elif defined(Q_WS_MAEMO_5)
221     showMaximized();
222 #else
223     show();
224 #endif
225 }
226
227
228 void MainWindow::enableButtons()
229 {
230   // Just to be sure, check to see if the keyset has been populated:
231   myKeysets->populateKeyset(this, currentKeyset);
232
233   myPanels->enableButtons(myKeysets, currentKeyset);
234 }
235
236
237 void MainWindow::receivedExternalWarning(
238   const char *warning)
239 {
240   QMessageBox errBox;
241   errBox.setText(warning);
242   errBox.setIcon(QMessageBox::Warning);
243   errBox.exec();
244 }
245
246
247 // Menu actions:
248
249 void MainWindow::on_actionSelectKeyset_triggered()
250 {
251   selectKeysetForm->show();
252 }
253
254 void MainWindow::on_actionSelect_Device_By_Name_triggered()
255 {
256   selectDeviceForm->show();
257 }
258
259 void MainWindow::on_actionArrange_Button_Panels_triggered()
260 {
261   panelSelectionForm->show();
262 }
263
264 void MainWindow::on_actionAbout_triggered()
265 {
266   if (!aboutForm)
267   {
268     aboutForm = new PIRAboutForm(this);
269   }
270
271   aboutForm->show();
272 }
273
274 void MainWindow::on_actionDocumentation_triggered()
275 {
276   if (!documentationForm)
277   {
278     documentationForm = new PIRDocumentationForm(this);
279   }
280
281   documentationForm->show();
282 }
283
284
285 // Other actions:
286
287 void MainWindow::keysetSelectionChanged(
288   QListWidgetItem *item)
289 {
290   if (!item) return;  // Should probably display error message here!
291
292   PIRKeysetWidgetItem *kwi = dynamic_cast<PIRKeysetWidgetItem *>(item);
293
294   if (!kwi) return; // Also need to say something here
295
296   if (currentKeyset == kwi->getID())
297   {
298     // We're already on that keyset, so nothing to do:
299     return;
300   }
301   
302   currentKeyset = kwi->getID();
303
304   QSettings settings("pietrzak.org", "Pierogi");
305 //  settings.setValue("currentKeyset", currentKeyset);
306
307   settings.setValue(
308     "currentKeysetMake",
309     makeManager.getMakeString(kwi->getMake()));
310
311   settings.setValue(
312     "currentKeysetName",
313     myKeysets->getDisplayName(currentKeyset));
314
315   enableButtons();
316 }
317
318
319 void MainWindow::finalCleanup()
320 {
321   // Perform any necessary cleanup work here.
322
323   // Make certain that the thread stops repeating:
324   stopRepeating();
325 }
326
327
328 void MainWindow::addCurrentKeyset(
329   QListWidget *qlw)
330 {
331   // Is the current keyset already a favorite?
332   int count = qlw->count();
333   int index = 0;
334   PIRKeysetWidgetItem *kwi = NULL;
335   while (index < count)
336   {
337     kwi = dynamic_cast<PIRKeysetWidgetItem *>(
338       qlw->item(index));
339
340     if (kwi && (kwi->getID() == currentKeyset))
341     {
342       // Current keyset already in list!  No need to continue.
343       return;
344     }
345     ++index;
346   }
347
348   // Ok, add the current keyset to the favorites:
349   PIRMakeName make = myKeysets->getMake(currentKeyset);
350
351   QString name = makeManager.getMakeString(make);
352   name.append(" ");
353   name.append(myKeysets->getDisplayName(currentKeyset));
354
355   qlw->addItem(new PIRKeysetWidgetItem(name, currentKeyset, make));
356
357   // And, add the keyset id to the persistent list:
358   QSettings settings("pietrzak.org", "Pierogi");
359
360   int favSettingsSize = settings.beginReadArray("favorites");
361   settings.endArray();
362
363   settings.beginWriteArray("favorites");
364   settings.setArrayIndex(favSettingsSize);
365 //  settings.setValue("keysetID", currentKeyset);
366
367   settings.setValue(
368     "keysetMake",
369     makeManager.getMakeString(myKeysets->getMake(currentKeyset)));
370
371   settings.setValue("keysetName", myKeysets->getDisplayName(currentKeyset));
372
373   settings.endArray();
374 }
375
376
377 void MainWindow::removeFavoriteKeyset(
378   QListWidget *qlw)
379 {
380   // Deleting an item removes it from the list, so just grab the currently
381   // selected item and delete it:
382   QListWidgetItem *item = qlw->currentItem();
383
384   if (item) delete item;
385
386   // Remove this item from the persistent list.  Well, actually, it seems a
387   // little more convenient to just blow away the existing list of favorites
388   // and rewrite it, as modifying an existing QSettings array in the middle
389   // seems a bit hard...
390   QSettings settings("pietrzak.org", "Pierogi");
391
392   settings.remove("favorites");
393
394   int count = qlw->count();
395
396   // If the count is empty, we can stop right here:
397   if (count == 0) return;
398
399   int index = 0;
400   unsigned int id;
401   PIRKeysetWidgetItem *kwi = NULL;
402   settings.beginWriteArray("favorites");
403   while (index < count)
404   {
405     kwi = dynamic_cast<PIRKeysetWidgetItem *>(qlw->item(index));
406
407     settings.setArrayIndex(index);
408 //    settings.setValue("keysetID", kwi->getID());
409     id = kwi->getID();
410
411     settings.setValue(
412       "keysetMake",
413       makeManager.getMakeString(myKeysets->getMake(id)));
414
415     settings.setValue("keysetName", myKeysets->getDisplayName(id));
416
417     ++index;
418   }
419   settings.endArray();
420 }
421
422
423 void MainWindow::populateFavorites()
424 {
425   QSettings settings("pietrzak.org", "Pierogi");
426
427   int size = settings.beginReadArray("favorites");
428   int index = 0;
429   QString make;
430   QString name;
431   PIRKeysetWidgetItem *kwi;
432
433   while (index < size)
434   {
435     settings.setArrayIndex(index);
436     make = settings.value("keysetMake").toString();
437     name = settings.value("keysetName").toString();
438
439     kwi = myKeysets->makeKeysetItem(make, name);
440
441     // Did the item creation work?
442     if (kwi)
443     {
444       // Keyset does exist, so continue:
445       myPanels->addFavoritesItem(kwi);
446     }
447
448     ++index;
449   }
450
451   settings.endArray();
452 }
453
454
455 void MainWindow::startRepeating(
456   PIRKeyName name)
457 {
458   QMutexLocker locker(&commandIFMutex);
459   if (!commandInFlight)
460   {
461     commandInFlight = true;
462     emit buttonPressed(currentKeyset, name);
463   }
464 }
465
466
467 void MainWindow::stopRepeating()
468 {
469   QMutexLocker locker(&stopRepeatingMutex);
470   stopRepeatingFlag = true;
471 }
472
473
474 void MainWindow::selectPrevFavKeyset()
475 {
476   myPanels->selectPrevFavKeyset();
477 }
478
479
480 void MainWindow::selectNextFavKeyset()
481 {
482   myPanels->selectNextFavKeyset();
483 }
484
485
486 void MainWindow::managePanel(
487   PIRPanelName name,
488   int state)
489 {
490   myPanels->managePanel(name, state);
491 }
492
493
494 void MainWindow::insertPanel(
495   int index,
496   QWidget *panel,
497   const QString &displayName)
498 {
499   ui->stackedButtonsWidget->insertWidget(index, panel);
500   ui->selectPanelComboBox->insertItem(index, displayName);
501 }
502
503
504 void MainWindow::removePanel(
505   int index,
506   QWidget *panel)
507 {
508   ui->stackedButtonsWidget->removeWidget(panel);
509   ui->selectPanelComboBox->removeItem(index);
510 }
511
512
513 void MainWindow::on_prevPanelButton_clicked()
514 {
515   int count = ui->selectPanelComboBox->count();
516
517   // No need to do anything if there are less than two panels available:
518   if (count < 2) return;
519
520   int index = ui->selectPanelComboBox->currentIndex();
521   if (index == 0)
522   {
523     index = count - 1;
524   }
525   else
526   {
527     --index;
528   }
529
530   ui->selectPanelComboBox->setCurrentIndex(index);
531 }
532
533
534 void MainWindow::on_nextPanelButton_clicked()
535 {
536   int count = ui->selectPanelComboBox->count();
537
538   // No need to do anything if there are less than two panels available:
539   if (count < 2) return;
540
541   int index = ui->selectPanelComboBox->currentIndex();
542   if (index == count - 1)
543   {
544     index = 0;
545   }
546   else
547   {
548     ++index;
549   }
550
551   ui->selectPanelComboBox->setCurrentIndex(index);
552 }
553
554
555 void MainWindow::on_selectPanelComboBox_currentIndexChanged(int index)
556 {
557   ui->stackedButtonsWidget->setCurrentIndex(index);
558 }