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()
430 QString routeFile = QString("route.txt");
431 if (myRoute->readRouteFromFile( routeFile) == true)
438 * Opens result dialog when show result button is clicked.
439 * Sends measures as parameter to the resultdialogs saveMeasuresToArray-function.
441 void CarMainWindow::on_pushButtonShowResultDialog_clicked()
443 result->saveMeasuresToArray(measures);
444 this->result->show();
447 void CarMainWindow::userLogin()
449 myHttpClient->checkLogin();
453 * Resets Accelerometer measurement variables
455 void CarMainWindow::resetAccelerometerMeasurements()
457 currentAcceleration = 0;
458 currentAccelerationString = "";
461 distanceTraveled = "";
462 firstAcceleration = 0;
465 //lastScreenUpdateInSeconds = 0;
467 reverseAccelerationFlag = false;
468 stopWatch.setHMS(0, 0, 0, 0);
469 //accelerometer->stop();
471 vehicleStartedMoving = false;
476 * This function is called to handle checkpoints
477 *@param totalTime total time elapsed since starting measurements
478 *@param currentSpeed current speed of the device
480 void CarMainWindow::handleCheckPoint(double totalTime, double currentSpeed)
482 switch (counterForSaveResults)
485 measures->setTime10kmh(totalTime);
489 measures->setTime20kmh(totalTime);
493 measures->setTime30kmh(totalTime);
497 measures->setTime40kmh(totalTime);
501 measures->setTime50kmh(totalTime);
505 measures->setTime60kmh(totalTime);
509 measures->setTime70kmh(totalTime);
513 measures->setTime80kmh(totalTime);
517 measures->setTime90kmh(totalTime);
521 measures->setTime100kmh(totalTime);
527 counterForSaveResults++;
529 if (choiceInt == 0 && measures->getTime40kmh() != 0)
531 setTimeAxisGapAndShowResult(measures->getTime40kmh());
533 this->accelerometerTimer->stop();
536 counterForSaveResults = 0;
538 else if (choiceInt == 1 && measures->getTime100kmh() != 0)
540 setTimeAxisGapAndShowResult(measures->getTime100kmh());
542 this->accelerometerTimer->stop();
545 counterForSaveResults = 0;
547 else if (choiceInt == 2 && measures->getTime10kmh() != 0)
549 setTimeAxisGapAndShowResult(measures->getTime10kmh());
551 this->accelerometerTimer->stop();
554 counterForSaveResults = 0;
556 else if (choiceInt != 1 && choiceInt != 0 && measures->getTime80kmh() != 0)
558 setTimeAxisGapAndShowResult(measures->getTime80kmh());
560 this->accelerometerTimer->stop();
563 counterForSaveResults = 0;
567 qDebug() << "something wrong in handleCheckPoint()";
572 *This function is called to read (and process) data from the accelerometer
574 void CarMainWindow::readAccelerometerData()
577 double changeInAcceleration = 0;
580 accelerometer->getAcceleration(x, y, z);
581 accelerometer->smoothData(x, y, z);
584 x -= accelerometer->getCalibrationX();
585 y -= accelerometer->getCalibrationY();
586 z -= accelerometer->getCalibrationZ();
588 QString str = QString("acc x: " + QString::number(x) + "\n" +
589 "acc y: " + QString::number(y) + "\n" +
590 "acc z: " + QString::number(z) + "\n");
592 if (!vehicleStartedMoving)
596 firstAcceleration = sqrt(x*x + y*y + z*z);
597 //firstAcceleration = y; // first read
602 currentAcceleration = sqrt(x*x + y*y + z*z);
603 changeInAcceleration = (currentAcceleration - firstAcceleration); // firstAcceleration only gets set once
605 if (((fabs(changeInAcceleration) <= accelerationStartThreshold)
606 && !vehicleStartedMoving))
611 if (reverseAccelerationFlag)
613 // will be false until after 1st calculation
614 if ((changeInAcceleration <= 0))
616 // actually increasing here...
617 changeInAcceleration = fabs(changeInAcceleration);
621 // actually decreasing here...
622 changeInAcceleration = (changeInAcceleration * -1);
625 if (!vehicleStartedMoving)
627 if ((changeInAcceleration < 0))
629 // we started to move backwards first time through
630 reverseAccelerationFlag = true;
631 changeInAcceleration = fabs(changeInAcceleration);
633 vehicleStartedMoving = true;
635 stopWatch.setHMS(0, 0, 0, 0);
638 // keep the following line as close to the SetKinematicsProperties method as possible
639 currentTime = stopWatch.elapsed();
640 calculate->calculateParameters(changeInAcceleration, (currentTime - previousTime)/1000);
641 previousTime = currentTime;
643 s.sprintf("%.2f", changeInAcceleration);
644 currentAccelerationString = s;
647 speed = calculate->getCurrentSpeed();
648 speed = ((speed*1000)/kSecondsInHour);
649 s.sprintf("%.2f", speed);
652 s.sprintf("%.2f", calculate->getDistanceTraveled());
653 distanceTraveled = s;
659 time = calculate->getTotalTime();
661 s.sprintf("%.2f", time);
664 str.append("ca: " + currentAccelerationString + " G\n" );
665 str.append("cspeed: " + currentSpeed + " km/h \n" );
666 str.append("dist: " + distanceTraveled + " m \n" );
667 str.append("time: " + totalTime + " s \n" );
669 if ((stopTime > 0) && (previousTime >= stopTime))
671 // we want to end at a stopping point that the user chose
673 resetAccelerometerMeasurements();
678 *This function is used to calibrate accelerometer
680 void CarMainWindow::calibrateAccelerometer()
682 resetAccelerometerMeasurements();
683 accelerometer->calibrate();
687 *This slot function is called when GPS on checkbox state changed. Route-tab view.
690 void CarMainWindow::on_gpsOnCheckBox_stateChanged(int GPSState)
694 ui->labelRouteTabGPSStatus->setText("GPS off");//testing
695 location->stopPollingGPS();
699 ui->labelRouteTabGPSStatus->setText("GPS on");//testing
700 location->startPollingGPS();
705 *This slot function is called when GPS status changed. Route-tab view.
707 void CarMainWindow::gpsStatus()
709 if (ui->gpsOnCheckBox->isChecked())
711 if (location->getSatellitesInUse() >= 4)
714 //ui->labelRouteTabGPSStatus->setText("GPS ready");
715 ui->labelRouteTabGPSStatus->setText(QString::number(gpsData->roundCounter));
718 gpsTime->setTime_t(location->getTime());
719 ui->labelRouteTabGPSTime->setText(gpsTime->toString());
721 //Set latitude & longitude
722 ui->labelRouteTabLatitude->setText("Lat: " + QString::number(location->getLatitude()));
723 ui->labelRouteTabLongitude->setText("Lon: " + QString::number(location->getLongitude()));
728 ui->labelRouteTabGPSStatus->setText("Waiting for GPS");
731 ui->labelRouteTabSpeed->setText(QString::number(location->getSpeed()));
734 void CarMainWindow::on_startRecPushButton_clicked()
736 ui->labelRouteTabRecStatus->setText("Recording started");
737 gpsData->startRouteRecording(ui->labelRouteTabGPSTime->text());
740 void CarMainWindow::on_stopRecPushButton_clicked()
742 ui->labelRouteTabRecStatus->setText("Recording stopped");
743 gpsData->stopRouteRecording(ui->labelRouteTabGPSTime->text());
747 *Sets time axis right way in result dialog and shows target speed result.
748 *@param double pTime is the target speed result time which is shown to the user.
750 void CarMainWindow::setTimeAxisGapAndShowResult(double pTime)
752 ui->pushButtonShowResultDialog->setEnabled(true);
753 ui->pushButtonSendResult->setEnabled(true);
755 timeInteger.setNum(pTime);
756 ui->labelMeasureTabResult->show();
757 ui->labelMeasureTabResult->setText(timeInteger);
759 if (floor(pTime) <= 5)
761 result->setDiagramGapHorizontal(80);
764 else if (floor(pTime) <= 10)
766 result->setDiagramGapHorizontal(40);
771 result->setDiagramGapHorizontal(20);