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