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.
162 void CarMainWindow::on_autoStartButton_clicked()
164 initializeMeasures();
165 resetAccelerometerMeasurements();
166 ui->pushButtonSendResult->setEnabled(false);
167 ui->pushButtonShowResultDialog->setEnabled(false);
168 choice = ui->listViewStartTabAccelerationCategories->currentIndex();
169 choiceInt = choice.row();
170 qDebug() << choiceInt;
173 ui->labelMeasureTabHeader->setText("Accelerate to 40 km/h");
174 result->setDiagramGapStem(75);
177 else if (choiceInt == 1)
179 ui->labelMeasureTabHeader->setText("Accelerate to 100 km/h");
180 result->setDiagramGapStem(30);
185 ui->labelMeasureTabHeader->setText("Accelerate to 80 km/h");
186 result->setDiagramGapStem(37.5);
188 ui->labelMeasureTabResult->setText("");
190 this->accelerometerTimer->start(kAccelerometerSampleRate);
191 this->timer->start();
194 ui->tabWidget->setCurrentWidget(this->ui->tabMeasureResult);
198 *This slot function is called when ever list view is update. Start-tab view.
199 *@param QString unit.
201 void CarMainWindow::updateComboBoxStartTabUnits(QString unit)
203 ui->comboBoxStartTabUnits->setCurrentIndex(ui->comboBoxStartTabUnits->findText(unit, Qt::MatchExactly));
207 *This function is used to init unit combobox. Start-tab view.
209 void CarMainWindow::initComboBoxStartTabUnits()
211 units << "km/h" << "km" << "h" << "m" << "min" << "Mile" << "Mph" << "in" << "ft" << "yrd";
212 ui->comboBoxStartTabUnits->addItems(units);
216 *This function is used to set items to unit combobox. Start-tab view.
217 *@param QStringlist units
219 void CarMainWindow::setComboBoxStartTabUnits(QStringList units)
221 ui->comboBoxStartTabUnits->addItems(units);
225 *This function is used to init listViewStartTabAccelerationCategories. Start-tab view.
227 void CarMainWindow::initListViewStartTabAccelerationCategories()
229 accelerationCategoriesStartTab << "0-40 km/h" << "0-100 km/h"; //<< "0-1/4 Mile" << "0-1/8 Mile" << "0-50 km" << "50-100 Mile" << "0-60 Mph" << "0-100 m" << "0-50 ft" << "0-50 yrd" << "0-500 in";
230 QAbstractItemModel *model = new StringListModel(accelerationCategoriesStartTab);
231 ui->listViewStartTabAccelerationCategories->setModel(model);
235 *This function is used to set items to listViewStartTabAccelerationCategories. Start-tab view.
236 *@param QStringlist accelerationCategoriesStartTab
238 void CarMainWindow::setListViewStartTabAccelerationCategories(QStringList accelerationCategoriesStartTab)
240 QAbstractItemModel *model = new StringListModel(accelerationCategoriesStartTab);
241 ui->listViewStartTabAccelerationCategories->setModel(model);
245 *This function is used to set items to category combobox. Top-tab view.
248 void CarMainWindow::setCategoryCompoBox()
250 qDebug() << "_setCategoryCompoBox";
251 ui->comboBoxTopCategory->addItems(myHttpClient->myXmlreader->myCategoryList->getCategoryList());
255 *This function prcesses UI updating after a new top10List has been received.
256 *@todo Check where limitNr is taken, fixed or user input, see on_comboBoxTopCategory_currentIndexChanged.
258 void CarMainWindow::showTop10()
261 setListViewTopList(recentCategory, limitNr);
265 *This function is used to set items to labelTopList. Top-tab view.
267 *@param Size, number of results.
269 void CarMainWindow::setListViewTopList(QString category, int size)
271 qDebug() << "_setListViewTopList";
273 topList.append(myHttpClient->myXmlreader->myCategoryList->getTopList(category, size));
274 ui->labelTopList->setText(topList);
278 *This slot function is called when speed is achieved in measure dialog. Opens result dialog.
280 void CarMainWindow::openResultView()
286 *This slot function is called when registrate button is clicked.
288 void CarMainWindow::on_registratePushButton_clicked()
290 myRegistration->show();
294 *This slot function is called when ever refresh button clicked. Top-tab view.
296 void CarMainWindow::on_buttonTopRefresh_clicked()
298 myHttpClient->requestCategories();
302 *This slot function is called when ever category combobox current index changed. Top-tab view.
303 *@param QString category.
304 *@todo Check where limitNr is taken, fixed or user input, see showTop10.
306 void CarMainWindow::on_comboBoxTopCategory_currentIndexChanged(QString category)
308 qDebug() << "_on_comboBoxTopCategory_currentIndexChanged: " << category;
309 recentCategory = category; //for showTop10()
311 QString limit = QString::number(limitNr);
312 myHttpClient->requestTopList(category, limit);
316 *This slot function is called when set/change user button is clicked.
318 void CarMainWindow::on_setUserPushButton_clicked()
324 *@brief Just for development, for the real button is not shown until
325 *measurin started and there are results.
326 *@todo Implement with real code and yet leave sendXml in the bottom in use.
328 void CarMainWindow::on_manualStartButton_clicked()
334 * This slot function is called when timer gives timeout signal. Checks current speed
335 * and stores times in measure class.
337 void CarMainWindow::after_timeout()
339 if ( gpsSpeed > 1.0 )
346 * Initializes measures class's member variables.
348 void CarMainWindow::initializeMeasures()
350 measures->setTime10kmh(0);
351 measures->setTime20kmh(0);
352 measures->setTime30kmh(0);
353 measures->setTime40kmh(0);
354 measures->setTime50kmh(0);
355 measures->setTime60kmh(0);
356 measures->setTime70kmh(0);
357 measures->setTime80kmh(0);
358 measures->setTime90kmh(0);
359 measures->setTime100kmh(0);
363 * This slot function is called when Abort button is clicked.
365 void CarMainWindow::on_pushButtonMeasureTabAbort_clicked()
367 ui->pushButtonSendResult->setEnabled(false);
368 ui->pushButtonShowResultDialog->setEnabled(false);
369 ui->labelMeasureTabResult->hide();
370 ui->labelMeasureTabTime->setText("");
371 ui->labelMeasureTabSpeed->setText("");
372 measures->setTime10kmh(0);
373 measures->setTime20kmh(0);
374 measures->setTime30kmh(0);
375 measures->setTime40kmh(0);
376 measures->setTime50kmh(0);
377 measures->setTime60kmh(0);
378 measures->setTime70kmh(0);
379 measures->setTime80kmh(0);
380 measures->setTime90kmh(0);
381 measures->setTime100kmh(0);
382 this->accelerometerTimer->stop();
386 ui->tabWidget->setCurrentWidget(this->ui->StartTab);
395 *This slot function is called when pushButtonSendResult is clicked.
396 *@todo Use real category value.
398 void CarMainWindow::on_pushButtonSendResult_clicked()
400 myHttpClient->sendResultXml("acceleration-0-100");
401 ui->pushButtonSendResult->setEnabled(false);
404 void CarMainWindow::updateUserName()
408 newUserName = myLogin->getUserName();
409 ui->userNameLabel->setText( "User: " + newUserName);
411 if (newUserName.length())
413 ui->setUserPushButton->setText( "Change User");
414 this->setWindowTitle("Speed Freak - " + newUserName);
418 ui->setUserPushButton->setText( "Set User");
419 this->setWindowTitle("Speed Freak");
423 void CarMainWindow::regUserToServer()
425 myHttpClient->requestRegistration();
429 void CarMainWindow::on_drawRoutePushButton_clicked()
435 * Opens result dialog when show result button is clicked.
436 * Sends measures as parameter to the resultdialogs saveMeasuresToArray-function.
438 void CarMainWindow::on_pushButtonShowResultDialog_clicked()
440 result->saveMeasuresToArray(measures);
441 this->result->show();
444 void CarMainWindow::userLogin()
446 myHttpClient->checkLogin();
450 * Resets Accelerometer measurement variables
452 void CarMainWindow::resetAccelerometerMeasurements()
454 currentAcceleration = 0;
455 currentAccelerationString = "";
458 distanceTraveled = "";
459 firstAcceleration = 0;
462 //lastScreenUpdateInSeconds = 0;
464 reverseAccelerationFlag = false;
465 stopWatch.setHMS(0, 0, 0, 0);
466 //accelerometer->stop();
468 vehicleStartedMoving = false;
473 * This function is called to handle checkpoints
474 *@param totalTime total time elapsed since starting measurements
475 *@param currentSpeed current speed of the device
477 void CarMainWindow::handleCheckPoint(double totalTime, double currentSpeed)
479 switch (counterForSaveResults)
482 measures->setTime10kmh(totalTime);
486 measures->setTime20kmh(totalTime);
490 measures->setTime30kmh(totalTime);
494 measures->setTime40kmh(totalTime);
498 measures->setTime50kmh(totalTime);
502 measures->setTime60kmh(totalTime);
506 measures->setTime70kmh(totalTime);
510 measures->setTime80kmh(totalTime);
514 measures->setTime90kmh(totalTime);
518 measures->setTime100kmh(totalTime);
524 counterForSaveResults++;
526 if (choiceInt == 0 && measures->getTime40kmh() != 0)
528 setTimeAxisGapAndShowResult(measures->getTime40kmh());
530 this->accelerometerTimer->stop();
533 counterForSaveResults = 0;
536 else if (choiceInt == 1 && measures->getTime100kmh() != 0)
538 setTimeAxisGapAndShowResult(measures->getTime100kmh());
540 this->accelerometerTimer->stop();
543 counterForSaveResults = 0;
547 else if (choiceInt != 1 && choiceInt != 0 && measures->getTime80kmh() != 0)
549 setTimeAxisGapAndShowResult(measures->getTime80kmh());
551 this->accelerometerTimer->stop();
554 counterForSaveResults = 0;
564 *This function is called to read (and process) data from the accelerometer
566 void CarMainWindow::readAccelerometerData()
569 double changeInAcceleration = 0;
572 accelerometer->getAcceleration(x, y, z);
573 accelerometer->smoothData(x, y, z);
576 x -= accelerometer->getCalibrationX();
577 y -= accelerometer->getCalibrationY();
578 z -= accelerometer->getCalibrationZ();
580 QString str = QString("acc x: " + QString::number(x) + "\n" +
581 "acc y: " + QString::number(y) + "\n" +
582 "acc z: " + QString::number(z) + "\n");
584 if (!vehicleStartedMoving)
588 firstAcceleration = sqrt(x*x + y*y + z*z);
589 //firstAcceleration = y; // first read
594 currentAcceleration = sqrt(x*x + y*y + z*z);
595 changeInAcceleration = (currentAcceleration - firstAcceleration); // firstAcceleration only gets set once
597 if (((fabs(changeInAcceleration) <= accelerationStartThreshold)
598 && !vehicleStartedMoving))
603 if (reverseAccelerationFlag)
605 // will be false until after 1st calculation
606 if ((changeInAcceleration <= 0))
608 // actually increasing here...
609 changeInAcceleration = fabs(changeInAcceleration);
613 // actually decreasing here...
614 changeInAcceleration = (changeInAcceleration * -1);
617 if (!vehicleStartedMoving)
619 if ((changeInAcceleration < 0))
621 // we started to move backwards first time through
622 reverseAccelerationFlag = true;
623 changeInAcceleration = fabs(changeInAcceleration);
625 vehicleStartedMoving = true;
627 stopWatch.setHMS(0, 0, 0, 0);
630 // keep the following line as close to the SetKinematicsProperties method as possible
631 currentTime = stopWatch.elapsed();
632 calculate->calculateParameters(changeInAcceleration, (currentTime - previousTime)/1000);
633 previousTime = currentTime;
635 s.sprintf("%.2f", changeInAcceleration);
636 currentAccelerationString = s;
639 speed = calculate->getCurrentSpeed();
640 speed = ((speed*1000)/kSecondsInHour);
641 s.sprintf("%.2f", speed);
644 s.sprintf("%.2f", calculate->getDistanceTraveled());
645 distanceTraveled = s;
651 time = calculate->getTotalTime();
653 s.sprintf("%.2f", time);
656 str.append("ca: " + currentAccelerationString + " G\n" );
657 str.append("cspeed: " + currentSpeed + " km/h \n" );
658 str.append("dist: " + distanceTraveled + " m \n" );
659 str.append("time: " + totalTime + " s \n" );
661 if ((stopTime > 0) && (previousTime >= stopTime))
663 // we want to end at a stopping point that the user chose
665 resetAccelerometerMeasurements();
670 *This function is used to calibrate accelerometer
672 void CarMainWindow::calibrateAccelerometer()
674 resetAccelerometerMeasurements();
675 accelerometer->calibrate();
679 *This slot function is called when GPS on checkbox state changed. Route-tab view.
682 void CarMainWindow::on_gpsOnCheckBox_stateChanged(int GPSState)
684 //Stop polling GPS. Route-tab view.
687 ui->labelRouteTabGPSStatus->setText("GPS status: GPS off");
688 location->stopPollingGPS();
692 //Start polling GPS. Route-tab view.
695 ui->labelRouteTabGPSStatus->setText("GPS status: GPS on");
696 location->startPollingGPS();
701 *This slot function is called when GPS status changed. Route- and measure-tab view.
703 void CarMainWindow::gpsStatus()
705 //IF GPS checkbox is ON
706 if (ui->gpsOnCheckBox->isChecked())
708 //If GPS find 4 satellite.
709 if (location->getSatellitesInUse() >= 4)
711 //Set gps status. Route-tab view.
712 ui->labelRouteTabGPSStatus->setText("GPS ready");
714 //Set time. Route-tab view.
715 gpsTime->setTime_t(location->getTime());
716 QString gpsDateNow = gpsTime->toString("dd.MM.yyyy hh:mm:ss");
717 ui->labelRouteTabGPSTime->setText("GPS time: " + gpsDateNow);
719 //Set latitude & longitude. Route-tab view.
720 ui->labelRouteTabLatitude->setText("Latitude: " + QString::number(location->getLatitude()));
721 ui->labelRouteTabLongitude->setText("Longitude: " + QString::number(location->getLongitude()));
723 //Set rec status. Route-tab view.
724 if (ui->startRecPushButton->text() == "Stop recording")
726 ui->labelRouteTabRecStatus->setText("Recorded " + QString::number(gpsData->roundCounter) + " point");
729 //Get speed. Route- and Measure-tab view.
730 gpsSpeed = location->getSpeed();
732 //Set speed. Route-tab view.
733 ui->labelRouteTabSpeed->setText("Speed:" + QString::number(gpsSpeed) + "km/h +/-" + QString::number(location->getEps()) + "km/h");
738 ui->labelMeasureTabSpeed->setText(QString::number(gpsSpeed)); //Set speed. //Measure-tab view.
739 ui->labelMeasureTabTime->setText(QString::number(timeFromGps)); //Set time. //Measure-tab view.
744 timer->stop(); //Measure timer
745 ui->labelMeasureTabResult->setText(QString::number(timeFromGps));
746 ui->labelMeasureTabResult->show();
747 ui->pushButtonShowResultDialog->setEnabled(true);
748 ui->pushButtonShowResultDialog->setEnabled(true);
752 //If GPS find less than 4 satellite.
755 ui->labelRouteTabGPSStatus->setText("GPS status: Waiting for GPS");
765 *This slot function is called when gps timer timeout(10ms).
767 void CarMainWindow::gpsTimerTimeout()
772 //IF time is 1 second
773 if (time1000ms == 1000)
775 //Calculate acceleration 1/s
776 gpsSpeedPrevious = gpsSpeedNow; //Previous speed
777 gpsSpeedNow = (location->getSpeed())/3.6; //Speed now (m/s)
778 gpsAcceleration = (gpsSpeedNow - gpsSpeedPrevious)/1; //Calculate acceleration: speed now - previous speed / 1s.
779 //Set acceleration. Route-tab view.
780 ui->labelRouteTabAcceleration->setText("Acceleration: " + QString::number( gpsAcceleration ) + " m/s2");
784 //Set GPS update time. Route-tab view.
785 ui->labelRouteTabGPSUpdateTime->setText("GPS update time: " + QString::number(gpsUpdateTime) + " ms");
789 *This slot function is called when start rec push button clicked. Route-tab view.
791 void CarMainWindow::on_startRecPushButton_clicked()
793 //Start route recording.
794 if (ui->startRecPushButton->text() == "Start recording")
796 ui->startRecPushButton->setText("Stop recording");
797 ui->labelRouteTabRecStatus->setText("Recording started");
798 gpsData->startRouteRecording(ui->labelRouteTabGPSTime->text());
801 //Stop route recording.
802 else if (ui->startRecPushButton->text() == "Stop recording")
804 ui->startRecPushButton->setText("Start recording");
805 ui->labelRouteTabRecStatus->setText("Recording stopped");
806 gpsData->stopRouteRecording(ui->labelRouteTabGPSTime->text());
811 *Sets time axis right way in result dialog and shows target speed result.
812 *@param double pTime is the target speed result time which is shown to the user.
814 void CarMainWindow::setTimeAxisGapAndShowResult(double pTime)
816 ui->pushButtonShowResultDialog->setEnabled(true);
817 ui->pushButtonSendResult->setEnabled(true);
819 timeInteger.setNum(pTime);
820 ui->labelMeasureTabResult->show();
821 ui->labelMeasureTabResult->setText(timeInteger);
823 if (floor(pTime) <= 5)
825 result->setDiagramGapHorizontal(80);
828 else if (floor(pTime) <= 10)
830 result->setDiagramGapHorizontal(40);
835 result->setDiagramGapHorizontal(20);