b1bd95c9d2831661896e1fa21c118abb8a1b726f
[kitchenalert] / src / kitchenalertmainwindow.cpp
1 /**************************************************************************
2
3         KitchenAlert
4
5         Copyright (C) 2010-2011  Heli Hyvättinen
6
7         This file is part of KitchenAlert.
8
9         Kitchen Alert is free software: you can redistribute it and/or modify
10         it under the terms of the GNU General Public License as published by
11         the Free Software Foundation, either version 3 of the License, or
12         (at your option) any later version.
13
14         This program is distributed in the hope that it will be useful,
15         but WITHOUT ANY WARRANTY; without even the implied warranty of
16         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17         GNU General Public License for more details.
18
19         You should have received a copy of the GNU General Public License
20         along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22 **************************************************************************/
23
24
25
26
27
28 #include "kitchenalertmainwindow.h"
29 #include "ui_kitchenalertmainwindow.h"
30
31 #include <QString>
32 #include <QList>
33
34
35 #include "createtimersequencedialog.h"
36 #include "selectsounddialog.h"
37
38
39
40 #include <QDebug>
41
42 #include <QAction>
43 #include <QMenuBar>
44 #include <QMessageBox>
45 #include <QSettings>
46 #include <QFileDialog>
47
48
49
50 KitchenAlertMainWindow::KitchenAlertMainWindow(QWidget *parent) :
51     QMainWindow(parent),
52     ui(new Ui::KitchenAlertMainWindow)
53     {
54     ui->setupUi(this);
55
56     setWindowIcon(QIcon(":/kitchenalert.png"));
57
58
59
60
61   connect(ui->CreateNewScheduleButton, SIGNAL (pressed()), this, SLOT (newTimerSequence()));
62
63
64   //alerts' tableview setup
65
66
67   ui->ComingAlertsTableView->setModel(&model_);
68   ui->ComingAlertsTableView->setSelectionMode(QAbstractItemView::SingleSelection);
69   ui->ComingAlertsTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
70
71   ui->ComingAlertsTableView->horizontalHeader()->hide();
72 //  ui->ComingAlertsTableView->verticalHeader()->setVisible(true);
73
74   ui->ComingAlertsTableView->horizontalHeader()->setResizeMode(QHeaderView::Fixed);
75   ui->ComingAlertsTableView->horizontalHeader()->resizeSection(0,535);
76   ui->ComingAlertsTableView->horizontalHeader()->resizeSection(1,140);
77   ui->ComingAlertsTableView->horizontalHeader()->resizeSection(2,100);
78
79   ui->ComingAlertsTableView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
80
81
82   //Buttons used to reacting an alarm are hidden by default
83
84   disableSelectionDependentButtons();
85
86
87   connect(ui->ComingAlertsTableView->selectionModel(),SIGNAL(selectionChanged(QItemSelection,QItemSelection)),this,SLOT(timerSelected(QItemSelection,QItemSelection)));
88
89   connect(ui->DoneButton,SIGNAL(clicked()),this,SLOT(stop()));
90   connect(ui->RestartButton,SIGNAL(clicked()),this,SLOT(restart()));
91   connect(ui->SnoozeButton,SIGNAL(clicked()),this, SLOT(snooze()));
92   connect(ui->RemoveButton,SIGNAL(clicked()),this,SLOT(remove()));
93   connect(ui->SaveButton,SIGNAL(clicked()),this,SLOT(saveTimer()));
94   connect(ui->OpenButton,SIGNAL(clicked()),this,SLOT(loadTimer()));
95   // menu setup
96
97   QAction * p_SelectSoundAction = new QAction(tr("Select alert sound"),this);
98   connect(p_SelectSoundAction, SIGNAL(triggered()), this, SLOT(openSelectSoundDialog()));
99   menuBar()->addAction(p_SelectSoundAction);
100
101   QAction * p_AboutAction = new QAction(tr("About"),this);
102   connect(p_AboutAction,SIGNAL(triggered()),this,SLOT(openAbout()));
103   menuBar()->addAction(p_AboutAction);
104     }
105
106 KitchenAlertMainWindow::~KitchenAlertMainWindow()
107 {
108     delete ui;
109 }
110
111 void KitchenAlertMainWindow::changeEvent(QEvent *e)
112 {
113     QMainWindow::changeEvent(e);
114     switch (e->type()) {
115     case QEvent::LanguageChange:
116         ui->retranslateUi(this);
117         break;
118     default:
119         break;
120
121     }
122
123 }
124
125
126 void KitchenAlertMainWindow::newTimerSequence()
127 {
128     CreateTimerSequenceDialog createdialog;
129
130
131     if (createdialog.exec() == QDialog::Accepted) //if user pressed OK
132     {
133
134
135        QList<Timer *>  alltimers = createdialog.getTimers();  //get user input from the dialog
136
137        Timer* timer1 = alltimers.at(0); // take first timer (currently the only one!)
138
139
140
141        connect(timer1,SIGNAL(alert(QModelIndex)),this,SLOT(alert(QModelIndex)));
142
143
144
145        connect(this,SIGNAL(defaultSoundEnabled()),timer1,SLOT(enableDefaultSound()));
146        connect(this,SIGNAL(soundChanged(QString)),timer1,SLOT(changeAlertSound(QString)));
147
148
149
150         model_.addTimers(alltimers); // give timers to the model, they are started automatically by default
151
152  //       ui->ComingAlertsTableView->resizeColumnsToContents();
153
154
155         //Disable buttons, as selection is cleared when view is refreshed to show the new timer
156         //But only if the timer has not already alerted and thus been selected
157
158         if (!selectedRow().isValid())
159             disableSelectionDependentButtons();
160
161
162
163     }
164     // if cancelled, do nothing
165
166
167
168 }
169
170
171
172
173
174 void KitchenAlertMainWindow::alert(QModelIndex indexOfAlerter)
175 {
176
177     // The program is brought to front and activated when alerted
178
179
180     activateWindow();
181
182 // removing everything below does not solve the bug #6752!
183
184     raise();  //this may be unnecessary
185
186     // The alerting timer is selected
187     ui->ComingAlertsTableView->selectionModel()->select(QItemSelection(indexOfAlerter,indexOfAlerter),QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows );
188
189     //Scrolls the view so that the alerting timer is visible
190     ui->ComingAlertsTableView->scrollTo(indexOfAlerter);
191
192    // qDebug() << "Should be selected now";
193
194
195     //Snooze button is enabled
196
197
198     ui->SnoozeButton->setEnabled(true);
199 //qDebug ("Snooze on when alerting");
200
201 }
202
203
204 void KitchenAlertMainWindow::timerSelected(QItemSelection selected,QItemSelection)
205 {
206     ui->DoneButton->setEnabled(true);
207     ui->RestartButton->setEnabled(true);
208     ui->RemoveButton->setEnabled(true);
209
210
211     //snooze button enabled only when alerting
212     QModelIndexList indexes = selected.indexes();
213
214     //the selection model only allows selecting one row at the time & we only need to know the row, so we can just take the first one
215     QModelIndex index = indexes.value(0);
216     if (index.isValid())
217     {
218         if (model_.isThisTimerAlerting(index) == true)
219         {
220              ui->SnoozeButton->setEnabled(true);
221 //qDebug() << "Snooze on";
222         }
223         else
224         {
225             ui->SnoozeButton->setDisabled(true);
226 //qDebug() << "Snooze off";
227         }
228     }
229
230 }
231
232 void KitchenAlertMainWindow::snooze()
233 {
234     QModelIndex row = selectedRow();
235     if (row.isValid()) //If there was no row selected invalid row was returned
236     {
237         model_.snoozeTimer(row);
238     }
239     ui->SnoozeButton->setDisabled(true);
240
241
242 }
243
244 void KitchenAlertMainWindow::restart()
245 {
246     QModelIndex row = selectedRow(); //If there was no row selected invalid row was returned
247     if (row.isValid())
248     {
249
250         model_.startTimer(row);
251     }
252
253
254    if (model_.isThisTimerAlerting(row) == false) //This has to be checked, because 00:00:00 alerts alert *before* the program execution reaches here
255     {
256         ui->SnoozeButton->setDisabled(true);
257     }
258  //   qDebug () << "disabled snooze because of restart";
259
260
261 }
262
263 void KitchenAlertMainWindow::stop()
264 {
265     QModelIndex row = selectedRow();
266     if (row.isValid()) //If there was no row selected invalid row was returned
267     {
268         model_.stopTimer(row);
269     }
270     ui->SnoozeButton->setDisabled(true);
271
272 }
273
274 QModelIndex KitchenAlertMainWindow::selectedRow()
275 {
276     //Returns the cells in row 0 that have the whole row selected (the selection mode used allows only selecting whole rows
277
278     QModelIndexList chosenRows = ui->ComingAlertsTableView->selectionModel()->selectedRows();
279
280     //The selection mode used allows only one row to be selected at time, so we just take the first
281
282
283     return chosenRows.value(0); //gives an invalid QModelIndex if the list is empty
284 }
285
286 void KitchenAlertMainWindow::openSelectSoundDialog()
287 {
288
289     SelectSoundDialog dialog;
290    if ( dialog.exec() == QDialog::Accepted) //if user pressed OK
291     {
292        QSettings settings ("KitchenAlert","KitchenAlert");
293       
294        if (dialog.isDefaultSoundChecked() == true)
295        { 
296          
297            settings.setValue("UseDefaultSound",true); 
298            emit defaultSoundEnabled();
299        }   
300       else
301        {
302            QString filename = dialog.getSoundFileName();
303            settings.setValue("UseDefaultSound",false);
304            settings.setValue("soundfile",filename);
305            emit soundChanged(filename);
306        }
307
308     }
309
310 }
311
312 void KitchenAlertMainWindow::openAbout()
313 {
314     QMessageBox::about(this,tr("About KitchenAlert"),tr("<p>Version %1"
315                                                         "<p>Copyright &copy; Heli Hyv&auml;ttinen 2010-2011"
316                                                          "<p>License: General Public License v3"
317                                                          "<p>Web page: http://kitchenalert.garage.maemo.org/"
318                                                          "<p>Bugtracker: https://garage.maemo.org/projects/kitchenalert/").arg(QApplication::applicationVersion()));
319 }
320
321 bool KitchenAlertMainWindow::event(QEvent *event)
322 {
323
324
325     switch (event->type())
326     {
327         case QEvent::WindowActivate:
328
329             model_.setUpdateViewOnChanges(true);
330 //            ui->debugLabel->setText("Returned to the application!");
331             break;
332
333        case QEvent::WindowDeactivate:
334             model_.setUpdateViewOnChanges(false);
335 //            ui->debugLabel->setText("");
336             break;
337
338        default:
339             break;
340
341     }
342
343     return QMainWindow::event(event); // Send the event to the base class implementation (also when handling the event in this function): necessary for the program to work!
344 }
345
346 void KitchenAlertMainWindow::disableSelectionDependentButtons()
347 {
348     ui->DoneButton->setDisabled(true);
349     ui->SnoozeButton->setDisabled(true);
350     ui->RestartButton->setDisabled(true);
351     ui->RemoveButton->setDisabled(true);
352
353 }
354
355 void KitchenAlertMainWindow::initializeAlertSound()
356 {
357     QSettings settings;
358
359     bool useDefaultSound = settings.value("UseDefaultSound",true).toBool();
360     QString filename = settings.value("soundfile","").toString();
361
362     if (useDefaultSound == true)
363     {
364         openSelectSoundDialog();
365     }
366     else if (filename.isEmpty())
367     {
368         openSelectSoundDialog();
369     }
370
371    QString currentFilename = settings.value("soundfile","").toString();
372
373    if (currentFilename.isEmpty())
374    {
375         ui->debugLabel->setText("<FONT color=red>No alert sound file set. Alert sound will not be played!</FONT>");
376
377    }
378
379 }
380
381 void KitchenAlertMainWindow::remove()
382 {
383     QModelIndex row = selectedRow();
384     if (row.isValid()) //If there was no row selected invalid row was returned
385     {
386         QString text = tr("Are you sure you want to remove this timer from the list:\n");
387         text.append((row.data().toString()));
388         if (QMessageBox::question(this,tr("Confirm timer removal"),text,QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
389         {
390             model_.removeTimer(row);
391         }
392     }
393     ui->SnoozeButton->setDisabled(true);
394 }
395
396 void KitchenAlertMainWindow::saveTimer()
397 {
398
399     QModelIndex row = selectedRow();
400
401     if (row.isValid() == false) //If there was no row selected invalid row was returned
402         return;
403
404
405     //file name is asked. As the filename will be appended, there's no point in confirming owerwrite here
406     QString filename = QFileDialog::getSaveFileName(this, "", "", "*.kitchenalert",NULL,QFileDialog::DontConfirmOverwrite);
407
408     disableSelectionDependentButtons();
409
410     qDebug() << filename;
411
412     if (filename.isEmpty()) //user cancelled the dialog (or gave an empty name)
413     {
414         return;
415     }
416
417     if (!filename.endsWith(".kitchenalert"))
418     {
419         filename.append(".kitchenalert");
420
421     }
422
423     qDebug() << "filename appended to " << filename;
424
425
426     //MANUAL CONFIRMATION OF OWERWRITE
427
428     if ( QFile::exists(filename))
429     {
430          //ASK FOR CONFIRMATION
431
432         QString overwriteQuestion ("File ");
433         overwriteQuestion.append(filename);
434         overwriteQuestion.append(" already exists. Do you want to overwrite it?");
435         if (QMessageBox::question(this,"Confirm overwrite?", overwriteQuestion,QMessageBox::Yes | QMessageBox::No,QMessageBox::No) != QMessageBox::Yes)
436         {
437             return;
438         }
439     }
440
441
442
443
444     QString errorMessage(tr("Cannot write to file "));
445     errorMessage.append(filename);
446
447     if (!model_.saveTimer(row,filename)) //Save the file, if not successful give an error message
448     {
449         QMessageBox::critical(this,tr("Save timer failed!"), errorMessage);
450     }
451
452
453 }
454
455 void KitchenAlertMainWindow::loadTimer()
456 {
457     QString filename = QFileDialog::getOpenFileName(this,"","",tr("KitchenAlert timer files (*.kitchenalert)"));
458     if (!filename.isEmpty())
459     {
460
461 //        if (!filename.endsWith(".kitchenalert"))      //not needed, the dialog won't let the user to select files not ending with ".kitchenalert"
462 //        {
463 //            filename.append(".kitchenalert");
464 //        }
465
466         QString errorTitle(tr("Failed to load file "));
467         errorTitle.append(filename);
468
469         Timer * p_timer = new Timer();
470         if (!p_timer->load(filename))
471         {
472             QMessageBox::critical(this,errorTitle,tr("Unable to open file or not a valid KitchenAlert timer file."));
473             delete p_timer;
474             return;
475         }
476
477         initializeTimer(p_timer);
478     }
479 }
480
481 void KitchenAlertMainWindow::initializeTimer(Timer *p_timer)
482 {
483
484 //connect alert
485
486
487 connect(p_timer,SIGNAL(alert(QModelIndex)),this,SLOT(alert(QModelIndex)));
488
489
490 //connect change sound functions
491
492 connect(this,SIGNAL(defaultSoundEnabled()),p_timer,SLOT(enableDefaultSound()));
493 connect(this,SIGNAL(soundChanged(QString)),p_timer,SLOT(changeAlertSound(QString)));
494
495
496 //Disable buttons, as selection is cleared when view is refreshed to show the new timer
497
498 disableSelectionDependentButtons();
499
500
501 // give timers to the model (model wants list of timers now..)
502
503 QList<Timer *> timerList;
504
505 timerList.append(p_timer);
506 model_.addTimers(timerList,true); //timer gets started in the model
507
508 }
509
510
511