ff4c78a50b3138514ba3c177a63eb4c100cbb9d3
[kitchenalert] / src / kitchenalertmainwindow.cpp
1 /**************************************************************************
2
3         KitchenAlert
4
5         Copyright (C) 2010  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 <QFileDialog>
46 #include <QFile>
47
48
49
50 KitchenAlertMainWindow::KitchenAlertMainWindow(QWidget *parent) :
51     QMainWindow(parent),
52     ui(new Ui::KitchenAlertMainWindow)
53     {
54     ui->setupUi(this);
55
56
57   //alerts' tableview setup
58
59
60   ui->ComingAlertsTableView->setModel(&model_);
61   ui->ComingAlertsTableView->setSelectionMode(QAbstractItemView::SingleSelection);
62   ui->ComingAlertsTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
63   ui->ComingAlertsTableView->horizontalHeader()->setResizeMode(QHeaderView::Fixed);
64   ui->ComingAlertsTableView->horizontalHeader()->resizeSection(0,460);
65   ui->ComingAlertsTableView->horizontalHeader()->resizeSection(1,140);
66   ui->ComingAlertsTableView->horizontalHeader()->resizeSection(2,100);
67
68   ui->ComingAlertsTableView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
69 //  ui->ComingAlertsTableView->verticalHeader()->setDefaultSectionSize(40); //Needed with fixed cell heght only
70
71
72
73
74   ui->ComingAlertsTableView->horizontalHeader()->hide();
75   ui->ComingAlertsTableView->setWordWrap(true);
76
77
78   //Buttons used when a timer is selected are disabled by default and enabled upon selection
79
80   disableSelectionDependentButtons();
81
82   connect(ui->ComingAlertsTableView->selectionModel(),SIGNAL(selectionChanged(QItemSelection,QItemSelection)),this,SLOT(timerSelected(QItemSelection,QItemSelection)));
83
84   //connect buttons to respective functions
85   connect(ui->CreateNewScheduleButton, SIGNAL (pressed()), 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->loadButton,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         //get user input from the dialog
133
134
135        QList<Timer *>  alltimers = createdialog.getTimers();
136
137        // take first timer (currently the only one!)
138
139
140        Timer* timer1 = alltimers.at(0);
141
142
143        //connect alert
144
145
146        connect(timer1,SIGNAL(alert(QModelIndex)),this,SLOT(alert(QModelIndex)));
147
148
149        //Disable buttons, as selection is cleared when view is refreshed to show the new timer
150
151        disableSelectionDependentButtons();
152
153
154        // give timers to the model
155
156        model_.addTimers(alltimers);
157
158
159        //start the timer when it's safely in the model (consider moving this to the model's addTimers function)
160
161
162        timer1->start();
163
164
165     }
166     // if cancelled, do nothing
167
168
169
170 }
171
172
173
174
175
176 void KitchenAlertMainWindow::alert(QModelIndex indexOfAlerter)
177 {
178
179     // The program is brought to front and activated when alerted
180
181     raise();
182     activateWindow();
183
184     // The alerting timer is selected
185     ui->ComingAlertsTableView->selectionModel()->select(QItemSelection(indexOfAlerter,indexOfAlerter),QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows );
186 //    qDebug() << "Should be selected now";
187
188
189     //Snooze button is enabled
190
191
192     ui->SnoozeButton->setEnabled(true);
193
194     //The alert sound is played (consider moving this operation inside timer, as now stopping one alert will silence all alerting alerts)
195
196     alertSound_.play();
197
198 }
199
200
201 void KitchenAlertMainWindow::timerSelected(QItemSelection selected,QItemSelection deselected)
202 {
203     ui->DoneButton->setEnabled(true);
204     ui->RestartButton->setEnabled(true);
205     ui->RemoveButton->setEnabled(true);
206     ui->SaveButton->setEnabled(true);
207
208
209     //enabled only when alerting
210     QModelIndexList indexes = selected.indexes();
211
212     //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
213     QModelIndex index = indexes.value(0);
214     if (index.isValid())
215     {
216         if (model_.isThisTimerAlerting(index) == true)
217         {
218              ui->SnoozeButton->setEnabled(true);
219         }
220         else ui->SnoozeButton->setDisabled(true);
221     }
222
223 }
224
225 void KitchenAlertMainWindow::snooze()
226 {
227     QModelIndex row = selectedRow();
228     if (row.isValid()) //If there was no row selected invalid row was returned
229     {
230         model_.snoozeTimer(row);
231     }
232     ui->SnoozeButton->setDisabled(true);
233     alertSound_.stop();
234
235 }
236
237 void KitchenAlertMainWindow::restart()
238 {
239     QModelIndex row = selectedRow(); //If there was no row selected invalid row was returned
240     if (row.isValid())
241     {
242
243         model_.startTimer(row);
244     }
245     ui->SnoozeButton->setDisabled(true);
246     alertSound_.stop();
247
248 }
249
250 void KitchenAlertMainWindow::stop()
251 {
252     QModelIndex row = selectedRow();
253     if (row.isValid()) //If there was no row selected invalid row was returned
254     {
255         model_.stopTimer(row);
256     }
257     ui->SnoozeButton->setDisabled(true);
258     alertSound_.stop();
259     qDebug() << "Stopped.";
260 }
261
262 QModelIndex KitchenAlertMainWindow::selectedRow()
263 {
264     QModelIndexList chosenRows = ui->ComingAlertsTableView->selectionModel()->selectedRows();
265
266     //The selection mode used allows only one row to be selected at time, so we just take the first
267     //There are indexes for all columns in the row in the list, but as we only use the row, it does not matter which one we take
268
269     return chosenRows.value(0); //gives an invalid QModelIndex if the list is empty
270 }
271
272 void KitchenAlertMainWindow::openSelectSoundDialog()
273 {
274     SelectSoundDialog dialog;
275    if ( dialog.exec() == QDialog::Accepted) //if user pressed OK
276     {
277        if (dialog.isDefaultSoundChecked() == true)
278            alertSound_.setDefaultSound();
279        else
280         alertSound_.setSound(dialog.getSoundFileName());
281
282    //opening a dialog clears the selection so the selection dependen buttons must be disabled
283     }
284     disableSelectionDependentButtons();
285 }
286
287 void KitchenAlertMainWindow::openAbout()
288 {
289     QMessageBox::about(this,tr("About KitchenAlert"),tr("<p>Version 0.1.1"
290                                                         "<p>Copyright &copy; Heli Hyv&auml;ttinen 2010"
291                                                          "<p>License: General Public License v3"
292                                                          "<p>Bugtracker and project page: https://garage.maemo.org/projects/kitchenalert/"));
293 }
294
295 bool KitchenAlertMainWindow::event(QEvent *event)
296 {
297     QMainWindow::event(event);
298
299     switch (event->type())
300     {
301         case QEvent::WindowActivate:
302
303             model_.setUpdateViewOnChanges(true);
304               break;
305
306        case QEvent::WindowDeactivate:
307             model_.setUpdateViewOnChanges(false);
308             break;
309
310        default:
311             break;
312     }
313 }
314
315 void KitchenAlertMainWindow::disableSelectionDependentButtons()
316 {
317     ui->DoneButton->setDisabled(true);
318     ui->SnoozeButton->setDisabled(true);
319     ui->RestartButton->setDisabled(true);
320     ui->RemoveButton->setDisabled(true);
321     ui->SaveButton->setDisabled(true);
322 }
323
324 void KitchenAlertMainWindow::remove()
325 {
326    QModelIndex row = selectedRow();
327    if (row.isValid())
328    {
329     model_.removeTimer(row);
330     alertSound_.stop();
331     ui->ComingAlertsTableView->clearSelection();
332     disableSelectionDependentButtons();
333    }
334 }
335
336 void KitchenAlertMainWindow::saveTimer()
337 {
338
339     QModelIndex row = selectedRow();
340
341     if (row.isValid() == false) //If there was no row selected invalid row was returned
342         return;
343
344
345     //file name is asked. As the filename will be appended, there's no point in confirming owerwrite here
346     QString filename = QFileDialog::getSaveFileName(this, "", "", "*.kitchenalert",NULL,QFileDialog::DontConfirmOverwrite);
347
348     disableSelectionDependentButtons();
349
350     qDebug() << filename;
351
352     if (filename.isEmpty()) //user cancelled the dialog (or gave an empty name)
353     {
354         return;
355     }
356
357     if (!filename.endsWith(".kitchenalert"))
358     {
359         filename.append(".kitchenalert");
360
361     }
362
363     qDebug() << "filename appended to " << filename;
364
365
366     //MANUAL CONFIRMATION OF OWERWRITE
367
368     if ( QFile::exists(filename))
369     {
370          //ASK FOR CONFIRMATION
371
372         QString overwriteQuestion ("File ");
373         overwriteQuestion.append(filename);
374         overwriteQuestion.append(" already exists. Do you want to overwrite it?");
375         if (QMessageBox::question(this,"Confirm overwrite?", overwriteQuestion,QMessageBox::Yes | QMessageBox::No,QMessageBox::No) != QMessageBox::Yes)
376         {
377             return;
378         }
379     }
380
381
382
383
384
385     QString errorMessage(tr("Cannot write to file "));
386     errorMessage.append(filename);
387
388     if (!model_.saveTimer(row,filename)) //Save the file, if not successful give an error message
389     {
390         QMessageBox::critical(this,tr("Save timer failed!"), errorMessage);
391     }
392
393
394 }
395
396 void KitchenAlertMainWindow::loadTimer()
397 {
398     QString filename = QFileDialog::getOpenFileName(this,"","",tr("KitchenAlert timer files (*.kitchenalert)"));
399     if (!filename.isEmpty())
400     {
401
402 //        if (!filename.endsWith(".kitchenalert"))      //not needed, the dialog won't let the user to select files not ending with ".kitchenalert"
403 //        {
404 //            filename.append(".kitchenalert");
405 //        }
406
407         QString errorTitle(tr("Failed to load file "));
408         errorTitle.append(filename);
409
410         Timer * p_timer = new Timer();
411         if (!p_timer->load(filename))
412         {
413             QMessageBox::critical(this,errorTitle,tr("Unable to open file or not a valid KitchenAlert timer file."));
414             delete p_timer;
415             return;
416         }
417
418         initializeTimer(p_timer);
419     }
420 }
421
422
423 void KitchenAlertMainWindow::initializeTimer(Timer *p_timer)
424 {
425
426 //connect alert
427
428
429 connect(p_timer,SIGNAL(alert(QModelIndex)),this,SLOT(alert(QModelIndex)));
430
431
432 //Disable buttons, as selection is cleared when view is refreshed to show the new timer
433
434 disableSelectionDependentButtons();
435
436
437 // give timers to the model (model wants list of timers now..)
438
439 QList<Timer *> timerList;
440
441 timerList.append(p_timer);
442 model_.addTimers(timerList);
443
444
445 //start the timer when it's safely in the model (consider moving this to the model's addTimers function)
446
447
448 p_timer->start();
449 }