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 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";
227 //<< "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";
228 QAbstractItemModel *model = new StringListModel(accelerationCategoriesStartTab);
229 ui->listViewStartTabAccelerationCategories->setModel(model);
233 *This function is used to set items to listViewStartTabAccelerationCategories. Start-tab view.
234 *@param QStringlist accelerationCategoriesStartTab
236 void CarMainWindow::setListViewStartTabAccelerationCategories(QStringList accelerationCategoriesStartTab)
238 QAbstractItemModel *model = new StringListModel(accelerationCategoriesStartTab);
239 ui->listViewStartTabAccelerationCategories->setModel(model);
242 void CarMainWindow::setLabelInfoToUser(QString infoText)
244 ui->labelInfoToUser->setText(infoText);
248 *This function is used to set items to category combobox. Top-tab view.
251 void CarMainWindow::setCategoryCompoBox()
253 qDebug() << "_setCategoryCompoBox";
254 ui->comboBoxTopCategory->addItems(myHttpClient->myXmlreader->myCategoryList->getCategoryList());
258 *This function prcesses UI updating after a new top10List has been received.
259 *@todo Check where limitNr is taken, fixed or user input, see on_comboBoxTopCategory_currentIndexChanged.
261 void CarMainWindow::showTop10()
264 setListViewTopList(recentCategory, limitNr);
268 *This function is used to set items to labelTopList. Top-tab view.
270 *@param Size, number of results.
272 void CarMainWindow::setListViewTopList(QString category, int size)
274 qDebug() << "_setListViewTopList";
276 topList.append(myHttpClient->myXmlreader->myCategoryList->getTopList(category, size));
277 ui->labelTopList->setText(topList);
281 *This slot function is called when speed is achieved in measure dialog. Opens result dialog.
283 void CarMainWindow::openResultView()
289 *This slot function is called when registrate button is clicked.
291 void CarMainWindow::on_registratePushButton_clicked()
293 myRegistration->show();
297 *This slot function is called when ever refresh button clicked. Top-tab view.
299 void CarMainWindow::on_buttonTopRefresh_clicked()
301 myHttpClient->requestCategories();
305 *This slot function is called when ever category combobox current index changed. Top-tab view.
306 *@param QString category.
307 *@todo Check where limitNr is taken, fixed or user input, see showTop10.
309 void CarMainWindow::on_comboBoxTopCategory_currentIndexChanged(QString category)
311 qDebug() << "_on_comboBoxTopCategory_currentIndexChanged: " << category;
312 recentCategory = category; //for showTop10()
314 QString limit = QString::number(limitNr);
315 myHttpClient->requestTopList(category, limit);
319 *This slot function is called when set/change user button is clicked.
321 void CarMainWindow::on_setUserPushButton_clicked()
327 *@brief Just for development, for the real button is not shown until
328 *measurin started and there are results.
329 *@todo Implement with real code and yet leave sendXml in the bottom in use.
331 void CarMainWindow::on_manualStartButton_clicked()
337 * This slot function is called when timer gives timeout signal. Checks current speed
338 * and stores times in measure class.
340 void CarMainWindow::after_timeout()
342 QString timeString, speedString;
345 timeString.setNum(time);
346 speedString.setNum(speed);
347 ui->labelMeasureTabTime->setText(timeString);
348 ui->labelMeasureTabSpeed->setText(speedString);
350 //handleCheckPoint(time, speed);
354 * Initializes measures class's member variables.
356 void CarMainWindow::initializeMeasures()
358 measures->setTime10kmh(0);
359 measures->setTime20kmh(0);
360 measures->setTime30kmh(0);
361 measures->setTime40kmh(0);
362 measures->setTime50kmh(0);
363 measures->setTime60kmh(0);
364 measures->setTime70kmh(0);
365 measures->setTime80kmh(0);
366 measures->setTime90kmh(0);
367 measures->setTime100kmh(0);
371 * This slot function is called when Abort button is clicked.
373 void CarMainWindow::on_pushButtonMeasureTabAbort_clicked()
375 ui->pushButtonSendResult->setEnabled(false);
376 ui->pushButtonShowResultDialog->setEnabled(false);
377 ui->labelMeasureTabResult->hide();
378 ui->labelMeasureTabTime->setText("");
379 ui->labelMeasureTabSpeed->setText("");
380 measures->setTime10kmh(0);
381 measures->setTime20kmh(0);
382 measures->setTime30kmh(0);
383 measures->setTime40kmh(0);
384 measures->setTime50kmh(0);
385 measures->setTime60kmh(0);
386 measures->setTime70kmh(0);
387 measures->setTime80kmh(0);
388 measures->setTime90kmh(0);
389 measures->setTime100kmh(0);
390 this->accelerometerTimer->stop();
394 ui->tabWidget->setCurrentWidget(this->ui->StartTab);
399 *This slot function is called when pushButtonSendResult is clicked.
400 *@todo Use real category value.
402 void CarMainWindow::on_pushButtonSendResult_clicked()
404 //Pick up relevant category name and pass it to the server
405 myHttpClient->sendResultXml(catList.at(choiceInt));
406 ui->pushButtonSendResult->setEnabled(false);
409 void CarMainWindow::updateUserName()
413 newUserName = myLogin->getUserName();
414 ui->userNameLabel->setText( "User: " + newUserName);
416 if (newUserName.length())
418 ui->setUserPushButton->setText( "Change User");
419 this->setWindowTitle("Speed Freak - " + newUserName);
423 ui->setUserPushButton->setText( "Set User");
424 this->setWindowTitle("Speed Freak");
428 void CarMainWindow::regUserToServer()
430 myHttpClient->requestRegistration();
434 void CarMainWindow::on_drawRoutePushButton_clicked()
440 * Opens result dialog when show result button is clicked.
441 * Sends measures as parameter to the resultdialogs saveMeasuresToArray-function.
443 void CarMainWindow::on_pushButtonShowResultDialog_clicked()
445 result->saveMeasuresToArray(measures);
446 this->result->show();
449 void CarMainWindow::userLogin()
451 myHttpClient->checkLogin();
455 * Resets Accelerometer measurement variables
457 void CarMainWindow::resetAccelerometerMeasurements()
459 currentAcceleration = 0;
460 currentAccelerationString = "";
463 distanceTraveled = "";
464 firstAcceleration = 0;
467 //lastScreenUpdateInSeconds = 0;
469 reverseAccelerationFlag = false;
470 stopWatch.setHMS(0, 0, 0, 0);
471 //accelerometer->stop();
473 vehicleStartedMoving = false;
478 * This function is called to handle checkpoints
479 *@param totalTime total time elapsed since starting measurements
480 *@param currentSpeed current speed of the device
482 void CarMainWindow::handleCheckPoint(double totalTime, double currentSpeed)
484 switch (counterForSaveResults)
487 measures->setTime10kmh(totalTime);
491 measures->setTime20kmh(totalTime);
495 measures->setTime30kmh(totalTime);
499 measures->setTime40kmh(totalTime);
503 measures->setTime50kmh(totalTime);
507 measures->setTime60kmh(totalTime);
511 measures->setTime70kmh(totalTime);
515 measures->setTime80kmh(totalTime);
519 measures->setTime90kmh(totalTime);
523 measures->setTime100kmh(totalTime);
529 counterForSaveResults++;
531 if (choiceInt == 0 && measures->getTime40kmh() != 0)
533 setTimeAxisGapAndShowResult(measures->getTime40kmh());
535 this->accelerometerTimer->stop();
538 counterForSaveResults = 0;
540 else if (choiceInt == 1 && measures->getTime100kmh() != 0)
542 setTimeAxisGapAndShowResult(measures->getTime100kmh());
544 this->accelerometerTimer->stop();
547 counterForSaveResults = 0;
549 else if (choiceInt == 2 && measures->getTime10kmh() != 0)
551 setTimeAxisGapAndShowResult(measures->getTime10kmh());
553 this->accelerometerTimer->stop();
556 counterForSaveResults = 0;
558 else if (choiceInt != 1 && choiceInt != 0 && measures->getTime80kmh() != 0)
560 setTimeAxisGapAndShowResult(measures->getTime80kmh());
562 this->accelerometerTimer->stop();
565 counterForSaveResults = 0;
569 qDebug() << "something wrong in handleCheckPoint()";
574 *This function is called to read (and process) data from the accelerometer
576 void CarMainWindow::readAccelerometerData()
579 double changeInAcceleration = 0;
582 accelerometer->getAcceleration(x, y, z);
583 accelerometer->smoothData(x, y, z);
586 x -= accelerometer->getCalibrationX();
587 y -= accelerometer->getCalibrationY();
588 z -= accelerometer->getCalibrationZ();
590 QString str = QString("acc x: " + QString::number(x) + "\n" +
591 "acc y: " + QString::number(y) + "\n" +
592 "acc z: " + QString::number(z) + "\n");
594 if (!vehicleStartedMoving)
598 firstAcceleration = sqrt(x*x + y*y + z*z);
599 //firstAcceleration = y; // first read
604 currentAcceleration = sqrt(x*x + y*y + z*z);
605 changeInAcceleration = (currentAcceleration - firstAcceleration); // firstAcceleration only gets set once
607 if (((fabs(changeInAcceleration) <= accelerationStartThreshold)
608 && !vehicleStartedMoving))
613 if (reverseAccelerationFlag)
615 // will be false until after 1st calculation
616 if ((changeInAcceleration <= 0))
618 // actually increasing here...
619 changeInAcceleration = fabs(changeInAcceleration);
623 // actually decreasing here...
624 changeInAcceleration = (changeInAcceleration * -1);
627 if (!vehicleStartedMoving)
629 if ((changeInAcceleration < 0))
631 // we started to move backwards first time through
632 reverseAccelerationFlag = true;
633 changeInAcceleration = fabs(changeInAcceleration);
635 vehicleStartedMoving = true;
637 stopWatch.setHMS(0, 0, 0, 0);
640 // keep the following line as close to the SetKinematicsProperties method as possible
641 currentTime = stopWatch.elapsed();
642 calculate->calculateParameters(changeInAcceleration, (currentTime - previousTime)/1000);
643 previousTime = currentTime;
645 s.sprintf("%.2f", changeInAcceleration);
646 currentAccelerationString = s;
649 speed = calculate->getCurrentSpeed();
650 speed = ((speed*1000)/kSecondsInHour);
651 s.sprintf("%.2f", speed);
654 s.sprintf("%.2f", calculate->getDistanceTraveled());
655 distanceTraveled = s;
661 time = calculate->getTotalTime();
663 s.sprintf("%.2f", time);
666 str.append("ca: " + currentAccelerationString + " G\n" );
667 str.append("cspeed: " + currentSpeed + " km/h \n" );
668 str.append("dist: " + distanceTraveled + " m \n" );
669 str.append("time: " + totalTime + " s \n" );
671 if ((stopTime > 0) && (previousTime >= stopTime))
673 // we want to end at a stopping point that the user chose
675 resetAccelerometerMeasurements();
680 *This function is used to calibrate accelerometer
682 void CarMainWindow::calibrateAccelerometer()
684 resetAccelerometerMeasurements();
685 accelerometer->calibrate();
689 *This slot function is called when GPS on checkbox state changed. Route-tab view.
692 void CarMainWindow::on_gpsOnCheckBox_stateChanged(int GPSState)
696 ui->labelRouteTabGPSStatus->setText("GPS off");//testing
697 location->stopPollingGPS();
701 ui->labelRouteTabGPSStatus->setText("GPS on");//testing
702 location->startPollingGPS();
707 *This slot function is called when GPS status changed. Route-tab view.
709 void CarMainWindow::gpsStatus()
711 if (ui->gpsOnCheckBox->isChecked())
713 if (location->getSatellitesInUse() >= 4)
716 //ui->labelRouteTabGPSStatus->setText("GPS ready");
717 ui->labelRouteTabGPSStatus->setText(QString::number(gpsData->roundCounter));
720 gpsTime->setTime_t(location->getTime());
721 ui->labelRouteTabGPSTime->setText(gpsTime->toString());
723 //Set latitude & longitude
724 ui->labelRouteTabLatitude->setText("Lat: " + QString::number(location->getLatitude()));
725 ui->labelRouteTabLongitude->setText("Lon: " + QString::number(location->getLongitude()));
730 ui->labelRouteTabGPSStatus->setText("Waiting for GPS");
733 ui->labelRouteTabSpeed->setText(QString::number(location->getSpeed()));
736 void CarMainWindow::on_startRecPushButton_clicked()
738 ui->labelRouteTabRecStatus->setText("Recording started");
739 gpsData->startRouteRecording(ui->labelRouteTabGPSTime->text());
742 void CarMainWindow::on_stopRecPushButton_clicked()
744 ui->labelRouteTabRecStatus->setText("Recording stopped");
745 gpsData->stopRouteRecording(ui->labelRouteTabGPSTime->text());
749 *Sets time axis right way in result dialog and shows target speed result.
750 *@param double pTime is the target speed result time which is shown to the user.
752 void CarMainWindow::setTimeAxisGapAndShowResult(double pTime)
754 ui->pushButtonShowResultDialog->setEnabled(true);
755 ui->pushButtonSendResult->setEnabled(true);
757 timeInteger.setNum(pTime);
758 ui->labelMeasureTabResult->show();
759 ui->labelMeasureTabResult->setText(timeInteger);
761 if (floor(pTime) <= 5)
763 result->setDiagramGapHorizontal(80);
766 else if (floor(pTime) <= 10)
768 result->setDiagramGapHorizontal(40);
773 result->setDiagramGapHorizontal(20);