diff --git a/include/f1x/openauto/autoapp/App.hpp b/include/f1x/openauto/autoapp/App.hpp index f31e2d5..5bbdbe2 100644 --- a/include/f1x/openauto/autoapp/App.hpp +++ b/include/f1x/openauto/autoapp/App.hpp @@ -20,6 +20,9 @@ #include #include +#include +#include +#include #include #include @@ -35,10 +38,11 @@ class App: public projection::IAndroidAutoEntityEventHandler, public std::enable public: typedef std::shared_ptr Pointer; - App(boost::asio::io_service& ioService, projection::IAndroidAutoEntityFactory& androidAutoEntityFactory, + App(boost::asio::io_service& ioService, aasdk::usb::USBWrapper& usbWrapper, aasdk::tcp::ITCPWrapper& tcpWrapper, projection::IAndroidAutoEntityFactory& androidAutoEntityFactory, aasdk::usb::IUSBHub::Pointer usbHub, aasdk::usb::IConnectedAccessoriesEnumerator::Pointer connectedAccessoriesEnumerator); - void start(); + void waitForUSBDevice(); + void start(aasdk::tcp::ITCPEndpoint::SocketPointer socket); void stop(); void onAndroidAutoQuit() override; @@ -51,6 +55,8 @@ private: void onUSBHubError(const aasdk::error::Error& error); boost::asio::io_service& ioService_; + aasdk::usb::USBWrapper& usbWrapper_; + aasdk::tcp::ITCPWrapper& tcpWrapper_; boost::asio::io_service::strand strand_; projection::IAndroidAutoEntityFactory& androidAutoEntityFactory_; aasdk::usb::IUSBHub::Pointer usbHub_; diff --git a/include/f1x/openauto/autoapp/Configuration/IRecentAddressesList.hpp b/include/f1x/openauto/autoapp/Configuration/IRecentAddressesList.hpp new file mode 100644 index 0000000..88213de --- /dev/null +++ b/include/f1x/openauto/autoapp/Configuration/IRecentAddressesList.hpp @@ -0,0 +1,46 @@ +/* +* This file is part of openauto project. +* Copyright (C) 2018 f1x.studio (Michal Szwaj) +* +* openauto is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 3 of the License, or +* (at your option) any later version. + +* openauto is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with openauto. If not, see . +*/ + +#pragma once + +#include +#include + +namespace f1x +{ +namespace openauto +{ +namespace autoapp +{ +namespace configuration +{ + +class IRecentAddressesList +{ +public: + typedef std::deque RecentAddresses; + + virtual void read() = 0; + virtual void insertAddress(const std::string& address) = 0; + virtual RecentAddresses getList() const = 0; +}; + +} +} +} +} diff --git a/include/f1x/openauto/autoapp/Configuration/RecentAddressesList.hpp b/include/f1x/openauto/autoapp/Configuration/RecentAddressesList.hpp new file mode 100644 index 0000000..3c12591 --- /dev/null +++ b/include/f1x/openauto/autoapp/Configuration/RecentAddressesList.hpp @@ -0,0 +1,57 @@ +/* +* This file is part of openauto project. +* Copyright (C) 2018 f1x.studio (Michal Szwaj) +* +* openauto is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 3 of the License, or +* (at your option) any later version. + +* openauto is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with openauto. If not, see . +*/ + +#pragma once + +#include +#include + +namespace f1x +{ +namespace openauto +{ +namespace autoapp +{ +namespace configuration +{ + +class RecentAddressesList: public IRecentAddressesList +{ +public: + RecentAddressesList(size_t maxListSize); + + void read() override; + void insertAddress(const std::string& address) override; + RecentAddresses getList() const override; + +private: + void load(); + void save(); + + size_t maxListSize_; + RecentAddresses list_; + + static const std::string cConfigFileName; + static const std::string cRecentEntiresCount; + static const std::string cRecentEntryPrefix; +}; + +} +} +} +} diff --git a/include/f1x/openauto/autoapp/Main.hpp b/include/f1x/openauto/autoapp/Main.hpp deleted file mode 100644 index 4cb6746..0000000 --- a/include/f1x/openauto/autoapp/Main.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -* This file is part of openauto project. -* Copyright (C) 2018 f1x.studio (Michal Szwaj) -* -* openauto is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 3 of the License, or -* (at your option) any later version. - -* openauto is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with openauto. If not, see . -*/ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace f1x -{ -namespace openauto -{ -namespace autoapp -{ - -class Main -{ -public: - Main(aasdk::usb::IUSBWrapper& usbWrapper, boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration); - - void start(); - void stop(); - -private: - aasdk::usb::IUSBWrapper& usbWrapper_; - boost::asio::io_service& ioService_; - aasdk::usb::AccessoryModeQueryFactory queryFactory_; - aasdk::usb::AccessoryModeQueryChainFactory queryChainFactory_; - projection::ServiceFactory serviceFactory_; - projection::AndroidAutoEntityFactory androidAutoEntityFactory_; - autoapp::App::Pointer app_; -}; - -} -} -} diff --git a/include/f1x/openauto/autoapp/Projection/AndroidAutoEntityFactory.hpp b/include/f1x/openauto/autoapp/Projection/AndroidAutoEntityFactory.hpp index 1df64dc..73b8696 100644 --- a/include/f1x/openauto/autoapp/Projection/AndroidAutoEntityFactory.hpp +++ b/include/f1x/openauto/autoapp/Projection/AndroidAutoEntityFactory.hpp @@ -36,18 +36,16 @@ namespace projection class AndroidAutoEntityFactory: public IAndroidAutoEntityFactory { public: - AndroidAutoEntityFactory(aasdk::usb::IUSBWrapper& usbWrapper, - boost::asio::io_service& ioService, + AndroidAutoEntityFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration, IServiceFactory& serviceFactory); - IAndroidAutoEntity::Pointer create(aasdk::usb::DeviceHandle deviceHandle) override; + IAndroidAutoEntity::Pointer create(aasdk::usb::IAOAPDevice::Pointer aoapDevice) override; IAndroidAutoEntity::Pointer create(aasdk::tcp::ITCPEndpoint::Pointer tcpEndpoint) override; private: IAndroidAutoEntity::Pointer create(aasdk::transport::ITransport::Pointer transport); - aasdk::usb::IUSBWrapper& usbWrapper_; boost::asio::io_service& ioService_; configuration::IConfiguration::Pointer configuration_; IServiceFactory& serviceFactory_; diff --git a/include/f1x/openauto/autoapp/Projection/IAndroidAutoEntityFactory.hpp b/include/f1x/openauto/autoapp/Projection/IAndroidAutoEntityFactory.hpp index 945c247..f9f37c3 100644 --- a/include/f1x/openauto/autoapp/Projection/IAndroidAutoEntityFactory.hpp +++ b/include/f1x/openauto/autoapp/Projection/IAndroidAutoEntityFactory.hpp @@ -19,7 +19,7 @@ #pragma once #include -#include +#include #include namespace f1x @@ -36,7 +36,7 @@ class IAndroidAutoEntityFactory public: virtual ~IAndroidAutoEntityFactory() = default; - virtual IAndroidAutoEntity::Pointer create(aasdk::usb::DeviceHandle deviceHandle) = 0; + virtual IAndroidAutoEntity::Pointer create(aasdk::usb::IAOAPDevice::Pointer aoapDevice) = 0; virtual IAndroidAutoEntity::Pointer create(aasdk::tcp::ITCPEndpoint::Pointer tcpEndpoint) = 0; }; diff --git a/include/f1x/openauto/autoapp/UI/ConnectDialog.hpp b/include/f1x/openauto/autoapp/UI/ConnectDialog.hpp new file mode 100644 index 0000000..9e944aa --- /dev/null +++ b/include/f1x/openauto/autoapp/UI/ConnectDialog.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace Ui { +class ConnectDialog; +} + +namespace f1x +{ +namespace openauto +{ +namespace autoapp +{ +namespace ui +{ + +class ConnectDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ConnectDialog(boost::asio::io_service& ioService, aasdk::tcp::ITCPWrapper& tcpWrapper, openauto::autoapp::configuration::IRecentAddressesList& recentAddressesList, QWidget *parent = nullptr); + ~ConnectDialog() override; + +signals: + void connectToDevice(const QString& ipAddress); + void connectionSucceed(aasdk::tcp::ITCPEndpoint::SocketPointer socket, const std::string& ipAddress); + void connectionFailed(const QString& message); + +private slots: + void onConnectButtonClicked(); + void onConnectionFailed(const QString& message); + void onConnectionSucceed(aasdk::tcp::ITCPEndpoint::SocketPointer socket, const std::string& ipAddress); + void onRecentAddressClicked(const QModelIndex& index); + +private: + void insertIpAddress(const std::string& ipAddress); + void loadRecentList(); + void setControlsEnabledStatus(bool status); + void connectHandler(const boost::system::error_code& ec, const std::string& ipAddress, aasdk::tcp::ITCPEndpoint::SocketPointer socket); + + boost::asio::io_service& ioService_; + aasdk::tcp::ITCPWrapper& tcpWrapper_; + openauto::autoapp::configuration::IRecentAddressesList& recentAddressesList_; + Ui::ConnectDialog *ui_; + QStringListModel recentAddressesModel_; +}; + +} +} +} +} diff --git a/include/f1x/openauto/autoapp/UI/MainWindow.hpp b/include/f1x/openauto/autoapp/UI/MainWindow.hpp index 2c82330..b7e2354 100644 --- a/include/f1x/openauto/autoapp/UI/MainWindow.hpp +++ b/include/f1x/openauto/autoapp/UI/MainWindow.hpp @@ -46,6 +46,7 @@ signals: void exit(); void openSettings(); void toggleCursor(); + void openConnectDialog(); private: Ui::MainWindow* ui_; diff --git a/src/autoapp/App.cpp b/src/autoapp/App.cpp index 73a7b3d..b3f92a0 100644 --- a/src/autoapp/App.cpp +++ b/src/autoapp/App.cpp @@ -17,6 +17,8 @@ */ #include +#include +#include #include #include @@ -27,9 +29,11 @@ namespace openauto namespace autoapp { -App::App(boost::asio::io_service& ioService, projection::IAndroidAutoEntityFactory& androidAutoEntityFactory, +App::App(boost::asio::io_service& ioService, aasdk::usb::USBWrapper& usbWrapper, aasdk::tcp::ITCPWrapper& tcpWrapper, projection::IAndroidAutoEntityFactory& androidAutoEntityFactory, aasdk::usb::IUSBHub::Pointer usbHub, aasdk::usb::IConnectedAccessoriesEnumerator::Pointer connectedAccessoriesEnumerator) : ioService_(ioService) + , usbWrapper_(usbWrapper) + , tcpWrapper_(tcpWrapper) , strand_(ioService_) , androidAutoEntityFactory_(androidAutoEntityFactory) , usbHub_(std::move(usbHub)) @@ -39,7 +43,7 @@ App::App(boost::asio::io_service& ioService, projection::IAndroidAutoEntityFacto } -void App::start() +void App::waitForUSBDevice() { strand_.dispatch([this, self = this->shared_from_this()]() { this->waitForDevice(); @@ -47,6 +51,36 @@ void App::start() }); } +void App::start(aasdk::tcp::ITCPEndpoint::SocketPointer socket) +{ + strand_.dispatch([this, self = this->shared_from_this(), socket = std::move(socket)]() mutable { + if(androidAutoEntity_ == nullptr) + { + try + { + usbHub_->cancel(); + connectedAccessoriesEnumerator_->cancel(); + + auto tcpEndpoint(std::make_shared(tcpWrapper_, std::move(socket))); + androidAutoEntity_ = androidAutoEntityFactory_.create(std::move(tcpEndpoint)); + androidAutoEntity_->start(*this); + } + catch(const aasdk::error::Error& error) + { + OPENAUTO_LOG(error) << "[App] TCP AndroidAutoEntity create error: " << error.what(); + + androidAutoEntity_.reset(); + this->waitForDevice(); + } + } + else + { + tcpWrapper_.close(*socket); + OPENAUTO_LOG(warning) << "[App] android auto entity is still running."; + } + }); +} + void App::stop() { strand_.dispatch([this, self = this->shared_from_this()]() { @@ -69,12 +103,15 @@ void App::aoapDeviceHandler(aasdk::usb::DeviceHandle deviceHandle) { try { - androidAutoEntity_ = androidAutoEntityFactory_.create(std::move(deviceHandle)); + connectedAccessoriesEnumerator_->cancel(); + + auto aoapDevice(aasdk::usb::AOAPDevice::create(usbWrapper_, ioService_, deviceHandle)); + androidAutoEntity_ = androidAutoEntityFactory_.create(std::move(aoapDevice)); androidAutoEntity_->start(*this); } catch(const aasdk::error::Error& error) { - OPENAUTO_LOG(error) << "[App] AndroidAutoEntity create error: " << error.what(); + OPENAUTO_LOG(error) << "[App] USB AndroidAutoEntity create error: " << error.what(); androidAutoEntity_.reset(); this->waitForDevice(); @@ -128,8 +165,8 @@ void App::onUSBHubError(const aasdk::error::Error& error) { OPENAUTO_LOG(error) << "[App] usb hub error: " << error.what(); - if(error.getCode() == aasdk::error::ErrorCode::OPERATION_ABORTED || - error.getCode() == aasdk::error::ErrorCode::OPERATION_IN_PROGRESS) + if(error.getCode() != aasdk::error::ErrorCode::OPERATION_ABORTED && + error.getCode() != aasdk::error::ErrorCode::OPERATION_IN_PROGRESS) { this->waitForDevice(); } diff --git a/src/autoapp/Configuration/RecentAddressesList.cpp b/src/autoapp/Configuration/RecentAddressesList.cpp new file mode 100644 index 0000000..c29fdcf --- /dev/null +++ b/src/autoapp/Configuration/RecentAddressesList.cpp @@ -0,0 +1,116 @@ +/* +* This file is part of openauto project. +* Copyright (C) 2018 f1x.studio (Michal Szwaj) +* +* openauto is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 3 of the License, or +* (at your option) any later version. + +* openauto is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with openauto. If not, see . +*/ + +#include +#include +#include + +namespace f1x +{ +namespace openauto +{ +namespace autoapp +{ +namespace configuration +{ + +const std::string RecentAddressesList::cConfigFileName = "openauto_wifi_recent.ini"; +const std::string RecentAddressesList::cRecentEntiresCount = "Recent.EntiresCount"; +const std::string RecentAddressesList::cRecentEntryPrefix = "Recent.Entry_"; + +RecentAddressesList::RecentAddressesList(size_t maxListSize) + : maxListSize_(maxListSize) +{ + +} + +void RecentAddressesList::read() +{ + this->load(); +} + +void RecentAddressesList::insertAddress(const std::string& address) +{ + if(std::find(list_.begin(), list_.end(), address) != list_.end()) + { + return; + } + + if(list_.size() >= maxListSize_) + { + list_.pop_back(); + } + + list_.push_front(address); + this->save(); +} + +RecentAddressesList::RecentAddresses RecentAddressesList::getList() const +{ + return list_; +} + +void RecentAddressesList::load() +{ + boost::property_tree::ptree iniConfig; + + try + { + boost::property_tree::ini_parser::read_ini(cConfigFileName, iniConfig); + + const auto listSize = std::min(maxListSize_, iniConfig.get(cRecentEntiresCount, 0)); + + for(size_t i = 0; i < listSize; ++i) + { + const auto key = cRecentEntryPrefix + std::to_string(i); + const auto address = iniConfig.get(key, RecentAddresses::value_type()); + + if(!address.empty()) + { + list_.push_back(address); + } + } + } + catch(const boost::property_tree::ini_parser_error& e) + { + OPENAUTO_LOG(warning) << "[RecentAddressesList] failed to read configuration file: " << cConfigFileName + << ", error: " << e.what() + << ". Empty list will be used."; + } +} + +void RecentAddressesList::save() +{ + boost::property_tree::ptree iniConfig; + + const auto entiresCount = std::min(maxListSize_, list_.size()); + iniConfig.put(cRecentEntiresCount, entiresCount); + + for(size_t i = 0; i < entiresCount; ++i) + { + const auto key = cRecentEntryPrefix + std::to_string(i); + iniConfig.put(key, list_.at(i)); + } + + boost::property_tree::ini_parser::write_ini(cConfigFileName, iniConfig); +} + +} +} +} +} diff --git a/src/autoapp/Main.cpp b/src/autoapp/Main.cpp deleted file mode 100644 index 84ea91e..0000000 --- a/src/autoapp/Main.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* -* This file is part of openauto project. -* Copyright (C) 2018 f1x.studio (Michal Szwaj) -* -* openauto is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 3 of the License, or -* (at your option) any later version. - -* openauto is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with openauto. If not, see . -*/ - -#include -#include -#include -#include - -namespace f1x -{ -namespace openauto -{ -namespace autoapp -{ - -Main::Main(aasdk::usb::IUSBWrapper& usbWrapper, boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration) - : usbWrapper_(usbWrapper) - , ioService_(ioService) - , queryFactory_(usbWrapper_, ioService_) - , queryChainFactory_(usbWrapper_, ioService_, queryFactory_) - , serviceFactory_(ioService_, configuration) - , androidAutoEntityFactory_(usbWrapper_, ioService_, configuration, serviceFactory_) -{ - auto usbHub(std::make_shared(usbWrapper_, ioService_, queryChainFactory_)); - auto ConnectedAccessoriesEnumerator(std::make_shared(usbWrapper_, ioService_, queryChainFactory_)); - - app_ = std::make_shared(ioService_, androidAutoEntityFactory_, - std::move(usbHub), std::move(ConnectedAccessoriesEnumerator)); -} - -void Main::start() -{ - app_->start(); -} - -void Main::stop() -{ - app_->stop(); -} - -} -} -} diff --git a/src/autoapp/Projection/AndroidAutoEntityFactory.cpp b/src/autoapp/Projection/AndroidAutoEntityFactory.cpp index cc31fae..0eb6942 100644 --- a/src/autoapp/Projection/AndroidAutoEntityFactory.cpp +++ b/src/autoapp/Projection/AndroidAutoEntityFactory.cpp @@ -33,23 +33,19 @@ namespace autoapp namespace projection { -AndroidAutoEntityFactory::AndroidAutoEntityFactory(aasdk::usb::IUSBWrapper& usbWrapper, - boost::asio::io_service& ioService, +AndroidAutoEntityFactory::AndroidAutoEntityFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration, IServiceFactory& serviceFactory) - : usbWrapper_(usbWrapper) - , ioService_(ioService) + : ioService_(ioService) , configuration_(std::move(configuration)) , serviceFactory_(serviceFactory) { } -IAndroidAutoEntity::Pointer AndroidAutoEntityFactory::create(aasdk::usb::DeviceHandle deviceHandle) +IAndroidAutoEntity::Pointer AndroidAutoEntityFactory::create(aasdk::usb::IAOAPDevice::Pointer aoapDevice) { - auto aoapDevice(aasdk::usb::AOAPDevice::create(usbWrapper_, ioService_, deviceHandle)); - auto transport(std::make_shared(ioService_, aoapDevice)); - + auto transport(std::make_shared(ioService_, std::move(aoapDevice))); return create(std::move(transport)); } diff --git a/src/autoapp/UI/ConnectDialog.cpp b/src/autoapp/UI/ConnectDialog.cpp new file mode 100644 index 0000000..127e216 --- /dev/null +++ b/src/autoapp/UI/ConnectDialog.cpp @@ -0,0 +1,125 @@ +#include +#include +#include "ui_connectdialog.h" + +namespace f1x +{ +namespace openauto +{ +namespace autoapp +{ +namespace ui +{ + +ConnectDialog::ConnectDialog(boost::asio::io_service& ioService, aasdk::tcp::ITCPWrapper& tcpWrapper, openauto::autoapp::configuration::IRecentAddressesList& recentAddressesList, QWidget *parent) + : QDialog(parent) + , ioService_(ioService) + , tcpWrapper_(tcpWrapper) + , recentAddressesList_(recentAddressesList) + , ui_(new Ui::ConnectDialog) +{ + qRegisterMetaType("aasdk::tcp::ITCPEndpoint::SocketPointer"); + qRegisterMetaType("std::string"); + + ui_->setupUi(this); + connect(ui_->pushButtonCancel, &QPushButton::clicked, this, &ConnectDialog::close); + connect(ui_->pushButtonConnect, &QPushButton::clicked, this, &ConnectDialog::onConnectButtonClicked); + connect(ui_->listViewRecent, &QListView::clicked, this, &ConnectDialog::onRecentAddressClicked); + connect(this, &ConnectDialog::connectionSucceed, this, &ConnectDialog::onConnectionSucceed); + connect(this, &ConnectDialog::connectionFailed, this, &ConnectDialog::onConnectionFailed); + + ui_->listViewRecent->setModel(&recentAddressesModel_); + this->loadRecentList(); +} + +ConnectDialog::~ConnectDialog() +{ + delete ui_; +} + +void ConnectDialog::onConnectButtonClicked() +{ + this->setControlsEnabledStatus(false); + + const auto& ipAddress = ui_->lineEditIPAddress->text().toStdString(); + auto socket = std::make_shared(ioService_); + + try + { + tcpWrapper_.asyncConnect(*socket, ipAddress, 5277, std::bind(&ConnectDialog::connectHandler, this, std::placeholders::_1, ipAddress, socket)); + } + catch(const boost::system::system_error& se) + { + emit connectionFailed(QString(se.what())); + } +} + +void ConnectDialog::connectHandler(const boost::system::error_code& ec, const std::string& ipAddress, aasdk::tcp::ITCPEndpoint::SocketPointer socket) +{ + if(!ec) + { + emit connectionSucceed(std::move(socket), ipAddress); + this->close(); + } + else + { + emit connectionFailed(QString::fromStdString(ec.message())); + } +} + +void ConnectDialog::onConnectionSucceed(aasdk::tcp::ITCPEndpoint::SocketPointer, const std::string& ipAddress) +{ + this->insertIpAddress(ipAddress); + this->setControlsEnabledStatus(true); +} + +void ConnectDialog::onConnectionFailed(const QString& message) +{ + this->setControlsEnabledStatus(true); + + QMessageBox errorMessage(QMessageBox::Critical, "Connect error", message, QMessageBox::Ok); + errorMessage.setWindowFlags(Qt::WindowStaysOnTopHint); + errorMessage.exec(); +} + +void ConnectDialog::onRecentAddressClicked(const QModelIndex& index) +{ + const auto& recentAddressesList = recentAddressesList_.getList(); + + if(static_cast(index.row()) <= recentAddressesList.size()) + { + ui_->lineEditIPAddress->setText(QString::fromStdString(recentAddressesList.at(index.row()))); + } +} + +void ConnectDialog::setControlsEnabledStatus(bool status) +{ + ui_->pushButtonConnect->setVisible(status); + ui_->pushButtonCancel->setEnabled(status); + ui_->lineEditIPAddress->setEnabled(status); + ui_->listViewRecent->setEnabled(status); +} + +void ConnectDialog::loadRecentList() +{ + QStringList stringList; + const auto& configList = recentAddressesList_.getList(); + + for(const auto& element : configList) + { + stringList.append(QString::fromStdString(element)); + } + + recentAddressesModel_.setStringList(stringList); +} + +void ConnectDialog::insertIpAddress(const std::string& ipAddress) +{ + recentAddressesList_.insertAddress(ipAddress); + this->loadRecentList(); +} + +} +} +} +} diff --git a/src/autoapp/UI/MainWindow.cpp b/src/autoapp/UI/MainWindow.cpp index 8569c06..49954f8 100644 --- a/src/autoapp/UI/MainWindow.cpp +++ b/src/autoapp/UI/MainWindow.cpp @@ -37,6 +37,7 @@ MainWindow::MainWindow(QWidget *parent) connect(ui_->pushButtonSettings, &QPushButton::clicked, this, &MainWindow::openSettings); connect(ui_->pushButtonExit, &QPushButton::clicked, this, &MainWindow::exit); connect(ui_->pushButtonToggleCursor, &QPushButton::clicked, this, &MainWindow::toggleCursor); + connect(ui_->pushButtonWirelessConnection, &QPushButton::clicked, this, &MainWindow::openConnectDialog); } MainWindow::~MainWindow() diff --git a/src/autoapp/UI/connectdialog.ui b/src/autoapp/UI/connectdialog.ui new file mode 100644 index 0000000..445e962 --- /dev/null +++ b/src/autoapp/UI/connectdialog.ui @@ -0,0 +1,160 @@ + + + ConnectDialog + + + + 0 + 0 + 301 + 389 + + + + Connect to device + + + + + 10 + 10 + 281 + 61 + + + + IP Address + + + + + 10 + 30 + 261 + 25 + + + + + + + + 10 + 80 + 281 + 181 + + + + Recent + + + + + 10 + 30 + 261 + 141 + + + + QAbstractItemView::NoEditTriggers + + + + + + + 60 + 260 + 221 + 81 + + + + <html><head/><body><p><span style=" font-style:italic;">In order to use wireless mode you must enable head unit server in developer settings.</span></p></body></html> + + + true + + + + + + 20 + 290 + 21 + 21 + + + + <html><head/><body><p><img src=":/ico_info.png"/></p></body></html> + + + + + + 40 + 340 + 121 + 41 + + + + Cancel + + + + + + 170 + 340 + 121 + 41 + + + + Connect + + + + + + 170 + 340 + 121 + 41 + + + + 0 + + + 0 + + + + + + 188 + 350 + 91 + 20 + + + + Connecting... + + + groupBoxIPAddress + groupBoxRecent + labelHeadUnitServerInfo + labelCopyrightsInfoIcon + pushButtonCancel + progressBarConnect + labelConnecting + pushButtonConnect + + + + diff --git a/src/autoapp/UI/mainwindow.ui b/src/autoapp/UI/mainwindow.ui index 8bf5291..6da956e 100644 --- a/src/autoapp/UI/mainwindow.ui +++ b/src/autoapp/UI/mainwindow.ui @@ -48,7 +48,7 @@ color: rgb(238, 238, 236); 630 - 340 + 370 161 41 @@ -67,7 +67,7 @@ color: rgb(238, 238, 236); 630 - 390 + 420 161 41 @@ -79,7 +79,7 @@ color: rgb(238, 238, 236); false - + 340 @@ -92,11 +92,11 @@ color: rgb(238, 238, 236); <html><head/><body><p><span style=" font-style:italic; color:#eeeeec;">Plug in your device to start AndroidAuto (tm).</span></p></body></html> - + 10 - 410 + 440 271 21 @@ -167,20 +167,20 @@ color: rgb(238, 238, 236); 220 - 376 + 400 21 - 21 + 31 <html><head/><body><p><img src=":/ico_info.png"/></p></body></html> - + 250 - 370 + 400 361 31 @@ -193,7 +193,7 @@ color: rgb(238, 238, 236); 630 - 290 + 270 161 41 @@ -208,21 +208,30 @@ color: rgb(238, 238, 236); false + + + + 630 + 320 + 161 + 41 + + + + Wireless connection + + + false + + + false + + - - - - 0 - 0 - 800 - 22 - - - - pushButtonToggleCursor + pushButtonWirelessConnection pushButtonSettings pushButtonExit diff --git a/src/autoapp/UI/settingswindow.ui b/src/autoapp/UI/settingswindow.ui index 63ad7a2..b066a78 100644 --- a/src/autoapp/UI/settingswindow.ui +++ b/src/autoapp/UI/settingswindow.ui @@ -23,7 +23,7 @@ - Form + Settings background-color: rgb(46, 52, 54); diff --git a/src/autoapp/autoapp.cpp b/src/autoapp/autoapp.cpp index 4b4b4b5..8c2565c 100644 --- a/src/autoapp/autoapp.cpp +++ b/src/autoapp/autoapp.cpp @@ -18,10 +18,21 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include -#include +#include #include namespace aasdk = f1x::aasdk; @@ -66,35 +77,54 @@ int main(int argc, char* argv[]) return 1; } - QApplication qApplication(argc, argv); boost::asio::io_service ioService; boost::asio::io_service::work work(ioService); + std::vector threadPool; + startUSBWorkers(ioService, usbContext, threadPool); + startIOServiceWorkers(ioService, threadPool); + QApplication qApplication(argc, argv); autoapp::ui::MainWindow mainWindow; mainWindow.setWindowFlags(Qt::WindowStaysOnTopHint); - mainWindow.showFullScreen(); auto configuration = std::make_shared(); autoapp::ui::SettingsWindow settingsWindow(configuration); settingsWindow.setWindowFlags(Qt::WindowStaysOnTopHint); - qApplication.setOverrideCursor(Qt::BlankCursor); - bool cursorVisible = false; - QObject::connect(&mainWindow, &autoapp::ui::MainWindow::toggleCursor, [&cursorVisible, &qApplication]() { - cursorVisible = !cursorVisible; - qApplication.setOverrideCursor(cursorVisible ? Qt::ArrowCursor : Qt::BlankCursor); - }); + autoapp::configuration::RecentAddressesList recentAddressesList(7); + recentAddressesList.read(); - aasdk::usb::USBWrapper usbWrapper(usbContext); - autoapp::Main main(usbWrapper, ioService, configuration); + aasdk::tcp::TCPWrapper tcpWrapper; + autoapp::ui::ConnectDialog connectDialog(ioService, tcpWrapper, recentAddressesList); + connectDialog.setWindowFlags(Qt::WindowStaysOnTopHint); QObject::connect(&mainWindow, &autoapp::ui::MainWindow::exit, []() { std::exit(0); }); QObject::connect(&mainWindow, &autoapp::ui::MainWindow::openSettings, &settingsWindow, &autoapp::ui::SettingsWindow::showFullScreen); + QObject::connect(&mainWindow, &autoapp::ui::MainWindow::openConnectDialog, &connectDialog, &autoapp::ui::ConnectDialog::exec); - std::vector threadPool; - startUSBWorkers(ioService, usbContext, threadPool); - startIOServiceWorkers(ioService, threadPool); - main.start(); + qApplication.setOverrideCursor(Qt::BlankCursor); + QObject::connect(&mainWindow, &autoapp::ui::MainWindow::toggleCursor, [&qApplication]() { + const auto cursor = qApplication.overrideCursor()->shape() == Qt::BlankCursor ? Qt::ArrowCursor : Qt::BlankCursor; + qApplication.setOverrideCursor(cursor); + }); + + mainWindow.showFullScreen(); + + aasdk::usb::USBWrapper usbWrapper(usbContext); + aasdk::usb::AccessoryModeQueryFactory queryFactory(usbWrapper, ioService); + aasdk::usb::AccessoryModeQueryChainFactory queryChainFactory(usbWrapper, ioService, queryFactory); + autoapp::projection::ServiceFactory serviceFactory(ioService, configuration); + autoapp::projection::AndroidAutoEntityFactory androidAutoEntityFactory(ioService, configuration, serviceFactory); + + auto usbHub(std::make_shared(usbWrapper, ioService, queryChainFactory)); + auto connectedAccessoriesEnumerator(std::make_shared(usbWrapper, ioService, queryChainFactory)); + auto app = std::make_shared(ioService, usbWrapper, tcpWrapper, androidAutoEntityFactory, std::move(usbHub), std::move(connectedAccessoriesEnumerator)); + + QObject::connect(&connectDialog, &autoapp::ui::ConnectDialog::connectionSucceed, [&app](auto socket) { + app->start(std::move(socket)); + }); + + app->waitForUSBDevice(); auto result = qApplication.exec(); std::for_each(threadPool.begin(), threadPool.end(), std::bind(&std::thread::join, std::placeholders::_1));