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