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();
52 gpsTimer = new QTimer();
53 connect(gpsTimer, SIGNAL(timeout()),this, SLOT(gpsTimerTimeout()));
55 gpsSpeedPrevious = 0.0;
56 gpsAcceleration = 0.0;
57 timeFromGps = 0.0; //Measure-tab view.
62 counterForSaveResults = 0;
66 accelerometer = new Accelerometer();
68 reverseAccelerationFlag = false;
69 vehicleStartedMoving = false;
73 accelerationStartThreshold = 0.02;
75 accelerometerTimer = new QTimer(this);
76 connect(accelerometerTimer, SIGNAL(timeout()), this, SLOT(readAccelerometerData()));
77 //accelerometerTimer->start(kAccelerometerSampleRate);
80 calculate = new Calculate();
81 connect(calculate, SIGNAL(checkPointReached()), this, SLOT(handleCheckPoint()));
83 resetAccelerometerMeasurements();
85 measures = new Measures();
86 this->initializeMeasures();
88 this->timer->setInterval(100);
90 connect(this->timer, SIGNAL(timeout()), this, SLOT(after_timeout()));
91 connect(myLogin, SIGNAL( userNameChanged()), this, SLOT(updateUserName()));
93 ui->labelMeasureTabResult->hide();
94 ui->pushButtonShowResultDialog->setEnabled(false);
95 ui->pushButtonShowResultDialog->setEnabled(false);
97 this->setWindowTitle("Speed Freak");
101 *Destructor of this class. Deletes all dynamic objects and sets them to NULL.
103 CarMainWindow::~CarMainWindow()
109 delete myCategorylist;
110 myCategorylist = NULL;
111 delete welcomeDialog;
112 welcomeDialog = NULL;
122 gpsSpeedPrevious = 0.0;
123 gpsAcceleration = 0.0;
130 *This function is used to .
133 void CarMainWindow::changeEvent(QEvent *e)
135 QMainWindow::changeEvent(e);
137 case QEvent::LanguageChange:
138 ui->retranslateUi(this);
146 *This slot function is called when ever list view is update. Start-tab view.
148 void CarMainWindow::on_listViewStartTabAccelerationCategories_clicked(QModelIndex index)
150 QString str = index.data().toString();
151 QStringList list = str.split("-");
152 QStringList list2 = list[1].split(" ");
154 ui->lineEditStartTabMin->setText(list[0]);
155 ui->lineEditStartTabMax->setText(list2[0]);
156 updateComboBoxStartTabUnits(list2[1]);
160 *This slot function is called when ever auto start button clicked. Start-tab view.
161 *@todo Check setDiagramGapStem(100) <- (choiceInt == 2)
163 void CarMainWindow::on_autoStartButton_clicked()
165 initializeMeasures();
166 resetAccelerometerMeasurements();
167 ui->pushButtonSendResult->setEnabled(false);
168 ui->pushButtonShowResultDialog->setEnabled(false);
169 choice = ui->listViewStartTabAccelerationCategories->currentIndex();
170 choiceInt = choice.row();
171 //qDebug() << "choiceInt" << choiceInt << " " << catList.at(choiceInt);
174 ui->labelMeasureTabHeader->setText("Accelerate to 40 km/h");
175 result->setDiagramGapStem(75);
177 else if (choiceInt == 1)
179 ui->labelMeasureTabHeader->setText("Accelerate to 100 km/h");
180 result->setDiagramGapStem(30);
182 else if (choiceInt == 2)
184 ui->labelMeasureTabHeader->setText("Accelerate to 10 km/h");
185 result->setDiagramGapStem(100);
189 ui->labelMeasureTabHeader->setText("Accelerate to 80 km/h");
190 result->setDiagramGapStem(37.5);
192 ui->labelMeasureTabResult->setText("");
194 this->accelerometerTimer->start(kAccelerometerSampleRate);
195 this->timer->start();
198 ui->tabWidget->setCurrentWidget(this->ui->tabMeasureResult);
202 *This slot function is called when ever list view is update. Start-tab view.
203 *@param QString unit.
205 void CarMainWindow::updateComboBoxStartTabUnits(QString unit)
207 ui->comboBoxStartTabUnits->setCurrentIndex(ui->comboBoxStartTabUnits->findText(unit, Qt::MatchExactly));
211 *This function is used to init unit combobox. Start-tab view.
213 void CarMainWindow::initComboBoxStartTabUnits()
215 units << "km/h" << "km" << "h" << "m" << "min" << "Mile" << "Mph" << "in" << "ft" << "yrd";
216 ui->comboBoxStartTabUnits->addItems(units);
220 *This function is used to set items to unit combobox. Start-tab view.
221 *@param QStringlist units
223 void CarMainWindow::setComboBoxStartTabUnits(QStringList units)
225 ui->comboBoxStartTabUnits->addItems(units);
229 *This function is used to init listViewStartTabAccelerationCategories. Start-tab view.
230 *@todo During development categories index values that are used for measuring are hardcoded
231 *@todo and accelerationCategoriesStartTab and catList are used instead of using
232 *@todo CategoryList::categoryList and CategoryList::cats.
234 void CarMainWindow::initListViewStartTabAccelerationCategories()
236 //Connect the user`s choice fron GUI to a correct variable name
237 catList.insert(0,"acceleration-0-40");
238 catList.insert(1,"acceleration-0-100");
239 catList.insert(2,"acceleration-0-10");
241 accelerationCategoriesStartTab << "0-40 km/h" << "0-100 km/h" << "0-10 km/h";
242 //<< "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";
243 QAbstractItemModel *model = new StringListModel(accelerationCategoriesStartTab);
244 ui->listViewStartTabAccelerationCategories->setModel(model);
248 *This function is used to set items to listViewStartTabAccelerationCategories. Start-tab view.
249 *@param QStringlist accelerationCategoriesStartTab
251 void CarMainWindow::setListViewStartTabAccelerationCategories(QStringList accelerationCategoriesStartTab)
253 QAbstractItemModel *model = new StringListModel(accelerationCategoriesStartTab);
254 ui->listViewStartTabAccelerationCategories->setModel(model);
257 void CarMainWindow::setLabelInfoToUser(QString infoText)
259 ui->labelInfoToUser->setText(infoText);
263 *This function is used to set items to category combobox. Top-tab view.
266 void CarMainWindow::setCategoryCompoBox()
268 qDebug() << "_setCategoryCompoBox";
269 ui->comboBoxTopCategory->addItems(myHttpClient->myXmlreader->myCategoryList->getCategoryList());
273 *This function prcesses UI updating after a new top10List has been received.
274 *@todo Check where limitNr is taken, fixed or user input, see on_comboBoxTopCategory_currentIndexChanged.
276 void CarMainWindow::showTop10()
279 setListViewTopList(recentCategory, limitNr);
283 *This function is used to set items to labelTopList. Top-tab view.
285 *@param Size, number of results.
287 void CarMainWindow::setListViewTopList(QString category, int size)
289 qDebug() << "_setListViewTopList";
291 topList.append(myHttpClient->myXmlreader->myCategoryList->getTopList(category, size));
292 ui->labelTopList->setText(topList);
296 *This slot function is called when speed is achieved in measure dialog. Opens result dialog.
298 void CarMainWindow::openResultView()
304 *This slot function is called when registrate button is clicked.
306 void CarMainWindow::on_registratePushButton_clicked()
308 myRegistration->show();
312 *This slot function is called when ever refresh button clicked. Top-tab view.
314 void CarMainWindow::on_buttonTopRefresh_clicked()
316 myHttpClient->requestCategories();
320 *This slot function is called when ever category combobox current index changed. Top-tab view.
321 *@param QString category.
322 *@todo Check where limitNr is taken, fixed or user input, see showTop10.
324 void CarMainWindow::on_comboBoxTopCategory_currentIndexChanged(QString category)
326 qDebug() << "_on_comboBoxTopCategory_currentIndexChanged: " << category;
327 recentCategory = category; //for showTop10()
329 QString limit = QString::number(limitNr);
330 myHttpClient->requestTopList(category, limit);
334 *This slot function is called when set/change user button is clicked.
336 void CarMainWindow::on_setUserPushButton_clicked()
342 *@brief Just for development, for the real button is not shown until
343 *measurin started and there are results.
344 *@todo Implement with real code and yet leave sendXml in the bottom in use.
346 void CarMainWindow::on_manualStartButton_clicked()
352 * This slot function is called when timer gives timeout signal. Checks current speed
353 * and stores times in measure class.
355 void CarMainWindow::after_timeout()
357 if ( gpsSpeed > 1.0 )
364 * Initializes measures class's member variables.
366 void CarMainWindow::initializeMeasures()
368 measures->setTime10kmh(0);
369 measures->setTime20kmh(0);
370 measures->setTime30kmh(0);
371 measures->setTime40kmh(0);
372 measures->setTime50kmh(0);
373 measures->setTime60kmh(0);
374 measures->setTime70kmh(0);
375 measures->setTime80kmh(0);
376 measures->setTime90kmh(0);
377 measures->setTime100kmh(0);
381 * This slot function is called when Abort button is clicked.
383 void CarMainWindow::on_pushButtonMeasureTabAbort_clicked()
385 ui->pushButtonSendResult->setEnabled(false);
386 ui->pushButtonShowResultDialog->setEnabled(false);
387 ui->labelMeasureTabResult->hide();
388 ui->labelMeasureTabTime->setText("");
389 ui->labelMeasureTabSpeed->setText("");
390 measures->setTime10kmh(0);
391 measures->setTime20kmh(0);
392 measures->setTime30kmh(0);
393 measures->setTime40kmh(0);
394 measures->setTime50kmh(0);
395 measures->setTime60kmh(0);
396 measures->setTime70kmh(0);
397 measures->setTime80kmh(0);
398 measures->setTime90kmh(0);
399 measures->setTime100kmh(0);
400 this->accelerometerTimer->stop();
404 ui->tabWidget->setCurrentWidget(this->ui->StartTab);
413 *This slot function is called when pushButtonSendResult is clicked.
414 *@todo Use real category value.
416 void CarMainWindow::on_pushButtonSendResult_clicked()
418 //Pick up relevant category name and pass it to the server
419 myHttpClient->sendResultXml(catList.at(choiceInt));
420 ui->pushButtonSendResult->setEnabled(false);
423 void CarMainWindow::updateUserName()
427 newUserName = myLogin->getUserName();
428 ui->userNameLabel->setText( "User: " + newUserName);
430 if (newUserName.length())
432 ui->setUserPushButton->setText( "Change User");
433 this->setWindowTitle("Speed Freak - " + newUserName);
437 ui->setUserPushButton->setText( "Set User");
438 this->setWindowTitle("Speed Freak");
442 void CarMainWindow::regUserToServer()
444 myHttpClient->requestRegistration();
448 void CarMainWindow::on_drawRoutePushButton_clicked()
450 QString routeFile = QString("route.txt");
451 if (myRoute->readRouteFromFile( routeFile) == true)
458 * Opens result dialog when show result button is clicked.
459 * Sends measures as parameter to the resultdialogs saveMeasuresToArray-function.
461 void CarMainWindow::on_pushButtonShowResultDialog_clicked()
463 result->saveMeasuresToArray(measures);
464 this->result->show();
467 void CarMainWindow::userLogin()
469 myHttpClient->checkLogin();
473 * Resets Accelerometer measurement variables
475 void CarMainWindow::resetAccelerometerMeasurements()
477 currentAcceleration = 0;
478 currentAccelerationString = "";
481 distanceTraveled = "";
482 firstAcceleration = 0;
485 //lastScreenUpdateInSeconds = 0;
487 reverseAccelerationFlag = false;
488 stopWatch.setHMS(0, 0, 0, 0);
489 //accelerometer->stop();
491 vehicleStartedMoving = false;
496 * This function is called to handle checkpoints
497 *@param totalTime total time elapsed since starting measurements
498 *@param currentSpeed current speed of the device
500 void CarMainWindow::handleCheckPoint(double totalTime, double currentSpeed)
502 switch (counterForSaveResults)
505 measures->setTime10kmh(totalTime);
509 measures->setTime20kmh(totalTime);
513 measures->setTime30kmh(totalTime);
517 measures->setTime40kmh(totalTime);
521 measures->setTime50kmh(totalTime);
525 measures->setTime60kmh(totalTime);
529 measures->setTime70kmh(totalTime);
533 measures->setTime80kmh(totalTime);
537 measures->setTime90kmh(totalTime);
541 measures->setTime100kmh(totalTime);
547 counterForSaveResults++;
549 if (choiceInt == 0 && measures->getTime40kmh() != 0)
551 setTimeAxisGapAndShowResult(measures->getTime40kmh());
553 this->accelerometerTimer->stop();
556 counterForSaveResults = 0;
558 else if (choiceInt == 1 && measures->getTime100kmh() != 0)
560 setTimeAxisGapAndShowResult(measures->getTime100kmh());
562 this->accelerometerTimer->stop();
565 counterForSaveResults = 0;
567 else if (choiceInt == 2 && measures->getTime10kmh() != 0)
569 setTimeAxisGapAndShowResult(measures->getTime10kmh());
571 this->accelerometerTimer->stop();
574 counterForSaveResults = 0;
576 else if (choiceInt != 1 && choiceInt != 0 && measures->getTime80kmh() != 0)
578 setTimeAxisGapAndShowResult(measures->getTime80kmh());
580 this->accelerometerTimer->stop();
583 counterForSaveResults = 0;
587 qDebug() << "something wrong in handleCheckPoint()";
592 *This function is called to read (and process) data from the accelerometer
594 void CarMainWindow::readAccelerometerData()
597 double changeInAcceleration = 0;
600 accelerometer->getAcceleration(x, y, z);
601 accelerometer->smoothData(x, y, z);
604 x -= accelerometer->getCalibrationX();
605 y -= accelerometer->getCalibrationY();
606 z -= accelerometer->getCalibrationZ();
608 QString str = QString("acc x: " + QString::number(x) + "\n" +
609 "acc y: " + QString::number(y) + "\n" +
610 "acc z: " + QString::number(z) + "\n");
612 if (!vehicleStartedMoving)
616 firstAcceleration = sqrt(x*x + y*y + z*z);
617 //firstAcceleration = y; // first read
622 currentAcceleration = sqrt(x*x + y*y + z*z);
623 changeInAcceleration = (currentAcceleration - firstAcceleration); // firstAcceleration only gets set once
625 if (((fabs(changeInAcceleration) <= accelerationStartThreshold)
626 && !vehicleStartedMoving))
631 if (reverseAccelerationFlag)
633 // will be false until after 1st calculation
634 if ((changeInAcceleration <= 0))
636 // actually increasing here...
637 changeInAcceleration = fabs(changeInAcceleration);
641 // actually decreasing here...
642 changeInAcceleration = (changeInAcceleration * -1);
645 if (!vehicleStartedMoving)
647 if ((changeInAcceleration < 0))
649 // we started to move backwards first time through
650 reverseAccelerationFlag = true;
651 changeInAcceleration = fabs(changeInAcceleration);
653 vehicleStartedMoving = true;
655 stopWatch.setHMS(0, 0, 0, 0);
658 // keep the following line as close to the SetKinematicsProperties method as possible
659 currentTime = stopWatch.elapsed();
660 calculate->calculateParameters(changeInAcceleration, (currentTime - previousTime)/1000);
661 previousTime = currentTime;
663 s.sprintf("%.2f", changeInAcceleration);
664 currentAccelerationString = s;
667 speed = calculate->getCurrentSpeed();
668 speed = ((speed*1000)/kSecondsInHour);
669 s.sprintf("%.2f", speed);
672 s.sprintf("%.2f", calculate->getDistanceTraveled());
673 distanceTraveled = s;
679 time = calculate->getTotalTime();
681 s.sprintf("%.2f", time);
684 str.append("ca: " + currentAccelerationString + " G\n" );
685 str.append("cspeed: " + currentSpeed + " km/h \n" );
686 str.append("dist: " + distanceTraveled + " m \n" );
687 str.append("time: " + totalTime + " s \n" );
689 if ((stopTime > 0) && (previousTime >= stopTime))
691 // we want to end at a stopping point that the user chose
693 resetAccelerometerMeasurements();
698 *This function is used to calibrate accelerometer
700 void CarMainWindow::calibrateAccelerometer()
702 resetAccelerometerMeasurements();
703 accelerometer->calibrate();
707 *This slot function is called when GPS on checkbox state changed. Route-tab view.
710 void CarMainWindow::on_gpsOnCheckBox_stateChanged(int GPSState)
712 //Stop polling GPS. Route-tab view.
715 ui->labelRouteTabGPSStatus->setText("GPS status: GPS off");
716 location->stopPollingGPS();
720 //Start polling GPS. Route-tab view.
723 ui->labelRouteTabGPSStatus->setText("GPS status: GPS on");
724 location->startPollingGPS();
729 *This slot function is called when GPS status changed. Route- and measure-tab view.
731 void CarMainWindow::gpsStatus()
733 //IF GPS checkbox is ON
734 if (ui->gpsOnCheckBox->isChecked())
736 //If GPS find 4 satellite.
737 if (location->getSatellitesInUse() >= 4)
739 //Set gps status. Route-tab view.
740 ui->labelRouteTabGPSStatus->setText("GPS ready");
742 //Set time. Route-tab view.
743 gpsTime->setTime_t(location->getTime());
744 QString gpsDateNow = gpsTime->toString("dd.MM.yyyy hh:mm:ss");
745 ui->labelRouteTabGPSTime->setText("GPS time: " + gpsDateNow);
747 //Set latitude & longitude. Route-tab view.
748 ui->labelRouteTabLatitude->setText("Latitude: " + QString::number(location->getLatitude()));
749 ui->labelRouteTabLongitude->setText("Longitude: " + QString::number(location->getLongitude()));
751 //Set rec status. Route-tab view.
752 if (ui->startRecPushButton->text() == "Stop recording")
754 ui->labelRouteTabRecStatus->setText("Recorded " + QString::number(gpsData->roundCounter) + " point");
757 //Get speed. Route- and Measure-tab view.
758 gpsSpeed = location->getSpeed();
760 //Set speed. Route-tab view.
761 ui->labelRouteTabSpeed->setText("Speed:" + QString::number(gpsSpeed) + "km/h +/-" + QString::number(location->getEps()) + "km/h");
766 ui->labelMeasureTabSpeed->setText(QString::number(gpsSpeed)); //Set speed. //Measure-tab view.
767 ui->labelMeasureTabTime->setText(QString::number(timeFromGps)); //Set time. //Measure-tab view.
772 timer->stop(); //Measure timer
773 ui->labelMeasureTabResult->setText(QString::number(timeFromGps));
774 ui->labelMeasureTabResult->show();
775 ui->pushButtonShowResultDialog->setEnabled(true);
776 ui->pushButtonShowResultDialog->setEnabled(true);
780 //If GPS find less than 4 satellite.
783 ui->labelRouteTabGPSStatus->setText("GPS status: Waiting for GPS");
793 *This slot function is called when gps timer timeout(10ms).
795 void CarMainWindow::gpsTimerTimeout()
800 //IF time is 1 second
801 if (time1000ms == 1000)
803 //Calculate acceleration 1/s
804 gpsSpeedPrevious = gpsSpeedNow; //Previous speed
805 gpsSpeedNow = (location->getSpeed())/3.6; //Speed now (m/s)
806 gpsAcceleration = (gpsSpeedNow - gpsSpeedPrevious)/1; //Calculate acceleration: speed now - previous speed / 1s.
807 //Set acceleration. Route-tab view.
808 ui->labelRouteTabAcceleration->setText("Acceleration: " + QString::number( gpsAcceleration ) + " m/s2");
812 //Set GPS update time. Route-tab view.
813 ui->labelRouteTabGPSUpdateTime->setText("GPS update time: " + QString::number(gpsUpdateTime) + " ms");
817 *This slot function is called when start rec push button clicked. Route-tab view.
819 void CarMainWindow::on_startRecPushButton_clicked()
821 //Start route recording.
822 if (ui->startRecPushButton->text() == "Start recording")
824 ui->startRecPushButton->setText("Stop recording");
825 ui->labelRouteTabRecStatus->setText("Recording started");
826 gpsData->startRouteRecording(ui->labelRouteTabGPSTime->text());
829 //Stop route recording.
830 else if (ui->startRecPushButton->text() == "Stop recording")
832 ui->startRecPushButton->setText("Start recording");
833 ui->labelRouteTabRecStatus->setText("Recording stopped");
834 gpsData->stopRouteRecording(ui->labelRouteTabGPSTime->text());
839 *Sets time axis right way in result dialog and shows target speed result.
840 *@param double pTime is the target speed result time which is shown to the user.
842 void CarMainWindow::setTimeAxisGapAndShowResult(double pTime)
844 ui->pushButtonShowResultDialog->setEnabled(true);
845 ui->pushButtonSendResult->setEnabled(true);
847 timeInteger.setNum(pTime);
848 ui->labelMeasureTabResult->show();
849 ui->labelMeasureTabResult->setText(timeInteger);
851 if (floor(pTime) <= 5)
853 result->setDiagramGapHorizontal(80);
856 else if (floor(pTime) <= 10)
858 result->setDiagramGapHorizontal(40);
863 result->setDiagramGapHorizontal(20);