2 * CarMainWindow main class
4 * @author Toni Jussila <toni.jussila@fudeco.com>
5 * @author Janne Änäkkälä <janne.anakkala@fudeco.com>
6 * @author Tiina Kivilinna-Korhola <tiina.kivilinna-korhola@fudeco.com>
7 * @author Olavi Pulkkinen <olavi.pulkkinen@fudeco.com>
8 * @author Rikhard Kuutti <rikhard.kuutti@fudeco.com>
9 * @author Kai Rasilainen <kai.rasilainen@fudeco.com>
10 * @copyright (c) 2010 Speed Freak team
11 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
14 #include "carmainwindow.h"
17 #define kAccelerometerSampleRate 50
18 #define kFilteringFactor 0.2
19 #define kSecondsInHour 3600
22 *Constructor of this class.
23 *@param QWidget pointer to parent object. By default the value is NULL.
25 CarMainWindow::CarMainWindow(QWidget *parent):QMainWindow(parent), ui(new Ui::CarMainWindow)
28 ui->tabWidget->setCurrentWidget(this->ui->StartTab);
29 result = new ResultDialog();
30 //measure = new MeasureDialog();
31 welcomeDialog = new WelcomeDialog();
32 welcomeDialog->show();
34 initComboBoxStartTabUnits();
35 initListViewStartTabAccelerationCategories();
37 myLogin = new LoginWindow(this);
38 myCategorylist = new CategoryList();
39 myHttpClient = new HttpClient(this);
40 myRegistration = new Registration(this);
41 connect(myRegistration,SIGNAL(sendregistration()),this,SLOT(regUserToServer()));
42 connect(myLogin,SIGNAL(userNameChanged()),this,SLOT(userLogin()));
43 connect(myHttpClient->myXmlreader, SIGNAL(receivedCategoryList()), this, SLOT(setCategoryCompoBox()));
44 connect(myHttpClient->myXmlreader, SIGNAL(receivedTop10List()), this, SLOT(showTop10()));
45 myRoute = new RouteDialog( this);
48 location = new Maemo5Location(this);
49 gpsData = new GPSData(location);
50 connect(location,SIGNAL(agnss()),this,SLOT(gpsStatus()));
51 gpsTime = new QDateTime();
55 counterForSaveResults = 0;
59 accelerometer = new Accelerometer();
61 reverseAccelerationFlag = false;
62 vehicleStartedMoving = false;
66 accelerationStartThreshold = 0.02;
68 accelerometerTimer = new QTimer(this);
69 //tkk connect(accelerometerTimer, SIGNAL(timeout()), this, SLOT(readAccelerometerData()));
70 //accelerometerTimer->start(kAccelerometerSampleRate);
73 calculate = new Calculate();
74 connect(calculate, SIGNAL(checkPointReached()), this, SLOT(handleCheckPoint()));
76 resetAccelerometerMeasurements();
78 measures = new Measures();
79 this->initializeMeasures();
81 this->timer->setInterval(300);
83 connect(this->timer, SIGNAL(timeout()), this, SLOT(after_timeout()));
84 connect(myLogin, SIGNAL( userNameChanged()), this, SLOT(updateUserName()));
86 ui->labelMeasureTabResult->hide();
87 ui->pushButtonShowResultDialog->setEnabled(false);
89 this->setWindowTitle("Speed Freak");
94 *Destructor of this class. Deletes all dynamic objects and sets them to NULL.
96 CarMainWindow::~CarMainWindow()
102 delete myCategorylist;
103 myCategorylist = NULL;
104 delete welcomeDialog;
105 welcomeDialog = NULL;
115 *This function is used to .
118 void CarMainWindow::changeEvent(QEvent *e)
120 QMainWindow::changeEvent(e);
122 case QEvent::LanguageChange:
123 ui->retranslateUi(this);
131 *This slot function is called when ever list view is update. Start-tab view.
133 void CarMainWindow::on_listViewStartTabAccelerationCategories_clicked(QModelIndex index)
135 QString str = index.data().toString();
136 QStringList list = str.split("-");
137 QStringList list2 = list[1].split(" ");
139 ui->lineEditStartTabMin->setText(list[0]);
140 ui->lineEditStartTabMax->setText(list2[0]);
141 updateComboBoxStartTabUnits(list2[1]);
145 *This slot function is called when ever auto start button clicked. Start-tab view.
146 *@todo Check setDiagramGapStem(100) <- (choiceInt == 2)
148 void CarMainWindow::on_autoStartButton_clicked()
150 initializeMeasures();
151 resetAccelerometerMeasurements();
152 ui->pushButtonSendResult->setEnabled(false);
153 ui->pushButtonShowResultDialog->setEnabled(false);
154 choice = ui->listViewStartTabAccelerationCategories->currentIndex();
155 choiceInt = choice.row();
156 qDebug() << "choiceInt" << choiceInt << " " << catList.at(choiceInt);
159 ui->labelMeasureTabHeader->setText("Accelerate to 40 km/h");
160 result->setDiagramGapStem(75);
162 else if (choiceInt == 1)
164 ui->labelMeasureTabHeader->setText("Accelerate to 100 km/h");
165 result->setDiagramGapStem(30);
167 else if (choiceInt == 2)
169 ui->labelMeasureTabHeader->setText("Accelerate to 10 km/h");
170 result->setDiagramGapStem(100);
174 ui->labelMeasureTabHeader->setText("Accelerate to 80 km/h");
175 result->setDiagramGapStem(37.5);
177 ui->labelMeasureTabResult->setText("");
179 this->accelerometerTimer->start(kAccelerometerSampleRate);
180 this->timer->start();
183 ui->tabWidget->setCurrentWidget(this->ui->tabMeasureResult);
187 *This slot function is called when ever list view is update. Start-tab view.
188 *@param QString unit.
190 void CarMainWindow::updateComboBoxStartTabUnits(QString unit)
192 ui->comboBoxStartTabUnits->setCurrentIndex(ui->comboBoxStartTabUnits->findText(unit, Qt::MatchExactly));
196 *This function is used to init unit combobox. Start-tab view.
198 void CarMainWindow::initComboBoxStartTabUnits()
200 units << "km/h" << "km" << "h" << "m" << "min" << "Mile" << "Mph" << "in" << "ft" << "yrd";
201 ui->comboBoxStartTabUnits->addItems(units);
205 *This function is used to set items to unit combobox. Start-tab view.
206 *@param QStringlist units
208 void CarMainWindow::setComboBoxStartTabUnits(QStringList units)
210 ui->comboBoxStartTabUnits->addItems(units);
214 *This function is used to init listViewStartTabAccelerationCategories. Start-tab view.
215 *@todo During development categories index values that are used for measuring are hardcoded
216 *@todo and accelerationCategoriesStartTab and catList are used instead of using
217 *@todo CategoryList::categoryList and CategoryList::cats.
219 void CarMainWindow::initListViewStartTabAccelerationCategories()
221 //Connect the user`s choice fron GUI to a correct variable name
222 catList.insert(0,"acceleration-0-40");
223 catList.insert(1,"acceleration-0-100");
224 catList.insert(2,"acceleration-0-10");
226 accelerationCategoriesStartTab << "0-40 km/h" << "0-100 km/h" << "0-10 km/h"; //<< "0-1/4 Mile" << "0-1/8 Mile" << "50-100 Mile" << "0-60 Mph" << "0-100 m" << "0-50 ft" << "0-50 yrd" << "0-500 in";
227 QAbstractItemModel *model = new StringListModel(accelerationCategoriesStartTab);
228 ui->listViewStartTabAccelerationCategories->setModel(model);
232 *This function is used to set items to listViewStartTabAccelerationCategories. Start-tab view.
233 *@param QStringlist accelerationCategoriesStartTab
235 void CarMainWindow::setListViewStartTabAccelerationCategories(QStringList accelerationCategoriesStartTab)
237 QAbstractItemModel *model = new StringListModel(accelerationCategoriesStartTab);
238 ui->listViewStartTabAccelerationCategories->setModel(model);
242 *This function is used to set items to category combobox. Top-tab view.
245 void CarMainWindow::setCategoryCompoBox()
247 qDebug() << "_setCategoryCompoBox";
248 ui->comboBoxTopCategory->addItems(myHttpClient->myXmlreader->myCategoryList->getCategoryList());
252 *This function prcesses UI updating after a new top10List has been received.
253 *@todo Check where limitNr is taken, fixed or user input, see on_comboBoxTopCategory_currentIndexChanged.
255 void CarMainWindow::showTop10()
258 setListViewTopList(recentCategory, limitNr);
262 *This function is used to set items to labelTopList. Top-tab view.
264 *@param Size, number of results.
266 void CarMainWindow::setListViewTopList(QString category, int size)
268 qDebug() << "_setListViewTopList";
270 topList.append(myHttpClient->myXmlreader->myCategoryList->getTopList(category, size));
271 ui->labelTopList->setText(topList);
275 *This slot function is called when speed is achieved in measure dialog. Opens result dialog.
277 void CarMainWindow::openResultView()
283 *This slot function is called when registrate button is clicked.
285 void CarMainWindow::on_registratePushButton_clicked()
287 myRegistration->show();
291 *This slot function is called when ever refresh button clicked. Top-tab view.
293 void CarMainWindow::on_buttonTopRefresh_clicked()
295 myHttpClient->requestCategories();
299 *This slot function is called when ever category combobox current index changed. Top-tab view.
300 *@param QString category.
301 *@todo Check where limitNr is taken, fixed or user input, see showTop10.
303 void CarMainWindow::on_comboBoxTopCategory_currentIndexChanged(QString category)
305 qDebug() << "_on_comboBoxTopCategory_currentIndexChanged: " << category;
306 recentCategory = category; //for showTop10()
308 QString limit = QString::number(limitNr);
309 myHttpClient->requestTopList(category, limit);
313 *This slot function is called when set/change user button is clicked.
315 void CarMainWindow::on_setUserPushButton_clicked()
321 *@brief Just for development, for the real button is not shown until
322 *measurin started and there are results.
323 *@todo Implement with real code and yet leave sendXml in the bottom in use.
325 void CarMainWindow::on_manualStartButton_clicked()
331 * This slot function is called when timer gives timeout signal. Checks current speed
332 * and stores times in measure class.
334 void CarMainWindow::after_timeout()
336 QString timeString, speedString;
339 timeString.setNum(time);
340 speedString.setNum(speed);
341 ui->labelMeasureTabTime->setText(timeString);
342 ui->labelMeasureTabSpeed->setText(speedString);
344 //handleCheckPoint(time, speed);
348 * Initializes measures class's member variables.
350 void CarMainWindow::initializeMeasures()
352 measures->setTime10kmh(0);
353 measures->setTime20kmh(0);
354 measures->setTime30kmh(0);
355 measures->setTime40kmh(0);
356 measures->setTime50kmh(0);
357 measures->setTime60kmh(0);
358 measures->setTime70kmh(0);
359 measures->setTime80kmh(0);
360 measures->setTime90kmh(0);
361 measures->setTime100kmh(0);
365 * This slot function is called when Abort button is clicked.
367 void CarMainWindow::on_pushButtonMeasureTabAbort_clicked()
369 ui->pushButtonSendResult->setEnabled(false);
370 ui->pushButtonShowResultDialog->setEnabled(false);
371 ui->labelMeasureTabResult->hide();
372 ui->labelMeasureTabTime->setText("");
373 ui->labelMeasureTabSpeed->setText("");
374 measures->setTime10kmh(0);
375 measures->setTime20kmh(0);
376 measures->setTime30kmh(0);
377 measures->setTime40kmh(0);
378 measures->setTime50kmh(0);
379 measures->setTime60kmh(0);
380 measures->setTime70kmh(0);
381 measures->setTime80kmh(0);
382 measures->setTime90kmh(0);
383 measures->setTime100kmh(0);
384 this->accelerometerTimer->stop();
388 ui->tabWidget->setCurrentWidget(this->ui->StartTab);
393 *This slot function is called when pushButtonSendResult is clicked.
394 *@todo Use real category value.
396 void CarMainWindow::on_pushButtonSendResult_clicked()
398 //Pick up relevant category name and pass it to the server
399 myHttpClient->sendResultXml(catList.at(choiceInt));
400 ui->pushButtonSendResult->setEnabled(false);
403 void CarMainWindow::updateUserName()
407 newUserName = myLogin->getUserName();
408 ui->userNameLabel->setText( "User: " + newUserName);
410 if (newUserName.length())
412 ui->setUserPushButton->setText( "Change User");
413 this->setWindowTitle("Speed Freak - " + newUserName);
417 ui->setUserPushButton->setText( "Set User");
418 this->setWindowTitle("Speed Freak");
422 void CarMainWindow::regUserToServer()
424 myHttpClient->requestRegistration();
428 void CarMainWindow::on_drawRoutePushButton_clicked()
434 * Opens result dialog when show result button is clicked.
435 * Sends measures as parameter to the resultdialogs saveMeasuresToArray-function.
437 void CarMainWindow::on_pushButtonShowResultDialog_clicked()
439 result->saveMeasuresToArray(measures);
440 this->result->show();
443 void CarMainWindow::userLogin()
445 myHttpClient->checkLogin();
449 * Resets Accelerometer measurement variables
451 void CarMainWindow::resetAccelerometerMeasurements()
453 currentAcceleration = 0;
454 currentAccelerationString = "";
457 distanceTraveled = "";
458 firstAcceleration = 0;
461 //lastScreenUpdateInSeconds = 0;
463 reverseAccelerationFlag = false;
464 stopWatch.setHMS(0, 0, 0, 0);
465 //accelerometer->stop();
467 vehicleStartedMoving = false;
472 * This function is called to handle checkpoints
473 *@param totalTime total time elapsed since starting measurements
474 *@param currentSpeed current speed of the device
476 void CarMainWindow::handleCheckPoint(double totalTime, double currentSpeed)
478 switch (counterForSaveResults)
481 measures->setTime10kmh(totalTime);
485 measures->setTime20kmh(totalTime);
489 measures->setTime30kmh(totalTime);
493 measures->setTime40kmh(totalTime);
497 measures->setTime50kmh(totalTime);
501 measures->setTime60kmh(totalTime);
505 measures->setTime70kmh(totalTime);
509 measures->setTime80kmh(totalTime);
513 measures->setTime90kmh(totalTime);
517 measures->setTime100kmh(totalTime);
523 counterForSaveResults++;
525 if (choiceInt == 0 && measures->getTime40kmh() != 0)
527 setTimeAxisGapAndShowResult(measures->getTime40kmh());
529 this->accelerometerTimer->stop();
532 counterForSaveResults = 0;
534 else if (choiceInt == 1 && measures->getTime100kmh() != 0)
536 setTimeAxisGapAndShowResult(measures->getTime100kmh());
538 this->accelerometerTimer->stop();
541 counterForSaveResults = 0;
543 else if (choiceInt == 2 && measures->getTime10kmh() != 0)
545 setTimeAxisGapAndShowResult(measures->getTime10kmh());
547 this->accelerometerTimer->stop();
550 counterForSaveResults = 0;
552 else if (choiceInt != 1 && choiceInt != 0 && measures->getTime80kmh() != 0)
554 setTimeAxisGapAndShowResult(measures->getTime80kmh());
556 this->accelerometerTimer->stop();
559 counterForSaveResults = 0;
563 qDebug() << "something wrong in handleCheckPoint()";
568 *This function is called to read (and process) data from the accelerometer
570 void CarMainWindow::readAccelerometerData()
573 double changeInAcceleration = 0;
576 accelerometer->getAcceleration(x, y, z);
577 accelerometer->smoothData(x, y, z);
580 x -= accelerometer->getCalibrationX();
581 y -= accelerometer->getCalibrationY();
582 z -= accelerometer->getCalibrationZ();
584 QString str = QString("acc x: " + QString::number(x) + "\n" +
585 "acc y: " + QString::number(y) + "\n" +
586 "acc z: " + QString::number(z) + "\n");
588 if (!vehicleStartedMoving)
592 firstAcceleration = sqrt(x*x + y*y + z*z);
593 //firstAcceleration = y; // first read
598 currentAcceleration = sqrt(x*x + y*y + z*z);
599 changeInAcceleration = (currentAcceleration - firstAcceleration); // firstAcceleration only gets set once
601 if (((fabs(changeInAcceleration) <= accelerationStartThreshold)
602 && !vehicleStartedMoving))
607 if (reverseAccelerationFlag)
609 // will be false until after 1st calculation
610 if ((changeInAcceleration <= 0))
612 // actually increasing here...
613 changeInAcceleration = fabs(changeInAcceleration);
617 // actually decreasing here...
618 changeInAcceleration = (changeInAcceleration * -1);
621 if (!vehicleStartedMoving)
623 if ((changeInAcceleration < 0))
625 // we started to move backwards first time through
626 reverseAccelerationFlag = true;
627 changeInAcceleration = fabs(changeInAcceleration);
629 vehicleStartedMoving = true;
631 stopWatch.setHMS(0, 0, 0, 0);
634 // keep the following line as close to the SetKinematicsProperties method as possible
635 currentTime = stopWatch.elapsed();
636 calculate->calculateParameters(changeInAcceleration, (currentTime - previousTime)/1000);
637 previousTime = currentTime;
639 s.sprintf("%.2f", changeInAcceleration);
640 currentAccelerationString = s;
643 speed = calculate->getCurrentSpeed();
644 speed = ((speed*1000)/kSecondsInHour);
645 s.sprintf("%.2f", speed);
648 s.sprintf("%.2f", calculate->getDistanceTraveled());
649 distanceTraveled = s;
655 time = calculate->getTotalTime();
657 s.sprintf("%.2f", time);
660 str.append("ca: " + currentAccelerationString + " G\n" );
661 str.append("cspeed: " + currentSpeed + " km/h \n" );
662 str.append("dist: " + distanceTraveled + " m \n" );
663 str.append("time: " + totalTime + " s \n" );
665 if ((stopTime > 0) && (previousTime >= stopTime))
667 // we want to end at a stopping point that the user chose
669 resetAccelerometerMeasurements();
674 *This function is used to calibrate accelerometer
676 void CarMainWindow::calibrateAccelerometer()
678 resetAccelerometerMeasurements();
679 accelerometer->calibrate();
683 *This slot function is called when GPS on checkbox state changed. Route-tab view.
686 void CarMainWindow::on_gpsOnCheckBox_stateChanged(int GPSState)
690 ui->labelRouteTabGPSStatus->setText("GPS off");//testing
691 location->stopPollingGPS();
695 ui->labelRouteTabGPSStatus->setText("GPS on");//testing
696 location->startPollingGPS();
701 *This slot function is called when GPS status changed. Route-tab view.
703 void CarMainWindow::gpsStatus()
705 if (ui->gpsOnCheckBox->isChecked())
707 if (location->getSatellitesInUse() >= 4)
710 //ui->labelRouteTabGPSStatus->setText("GPS ready");
711 ui->labelRouteTabGPSStatus->setText(QString::number(gpsData->roundCounter));
714 gpsTime->setTime_t(location->getTime());
715 ui->labelRouteTabGPSTime->setText(gpsTime->toString());
717 //Set latitude & longitude
718 ui->labelRouteTabLatitude->setText("Lat: " + QString::number(location->getLatitude()));
719 ui->labelRouteTabLongitude->setText("Lon: " + QString::number(location->getLongitude()));
724 ui->labelRouteTabGPSStatus->setText("Waiting for GPS");
727 ui->labelRouteTabSpeed->setText(QString::number(location->getSpeed()));
730 void CarMainWindow::on_startRecPushButton_clicked()
732 ui->labelRouteTabRecStatus->setText("Recording started");
733 gpsData->startRouteRecording(ui->labelRouteTabGPSTime->text());
736 void CarMainWindow::on_stopRecPushButton_clicked()
738 ui->labelRouteTabRecStatus->setText("Recording stopped");
739 gpsData->stopRouteRecording(ui->labelRouteTabGPSTime->text());
743 *Sets time axis right way in result dialog and shows target speed result.
744 *@param double pTime is the target speed result time which is shown to the user.
746 void CarMainWindow::setTimeAxisGapAndShowResult(double pTime)
748 ui->pushButtonShowResultDialog->setEnabled(true);
749 ui->pushButtonSendResult->setEnabled(true);
751 timeInteger.setNum(pTime);
752 ui->labelMeasureTabResult->show();
753 ui->labelMeasureTabResult->setText(timeInteger);
755 if (floor(pTime) <= 5)
757 result->setDiagramGapHorizontal(80);
760 else if (floor(pTime) <= 10)
762 result->setDiagramGapHorizontal(40);
767 result->setDiagramGapHorizontal(20);