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