diff --git a/ground/openpilotgcs/src/plugins/setupwizard/vehicletemplateselectorwidget.cpp b/ground/openpilotgcs/src/plugins/setupwizard/vehicletemplateselectorwidget.cpp index ceb17e2c4..5c4d916dc 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/vehicletemplateselectorwidget.cpp +++ b/ground/openpilotgcs/src/plugins/setupwizard/vehicletemplateselectorwidget.cpp @@ -27,20 +27,183 @@ #include "vehicletemplateselectorwidget.h" #include "ui_vehicletemplateselectorwidget.h" +#include +#include +#include +#include +#include "vehicletemplateexportdialog.h" +#include "utils/pathutils.h" VehicleTemplateSelectorWidget::VehicleTemplateSelectorWidget(QWidget *parent) : QWidget(parent), ui(new Ui::VehicleTemplateSelectorWidget) { ui->setupUi(this); + ui->templateImage->setScene(new QGraphicsScene()); + connect(ui->templateList, SIGNAL(itemSelectionChanged()), this, SLOT(templateSelectionChanged())); } VehicleTemplateSelectorWidget::~VehicleTemplateSelectorWidget() { + ui->templateList->clear(); + foreach(QJsonObject * templ, m_templates.values()) { + delete templ; + } + m_templates.clear(); + delete ui; } void VehicleTemplateSelectorWidget::updateTemplates() { - + loadValidFiles(); + setupTemplateList(); +} + +void VehicleTemplateSelectorWidget::updatePhoto(QJsonObject *templ) +{ + QPixmap photo; + + if (m_photoItem != NULL) { + ui->templateImage->scene()->removeItem(m_photoItem); + } + if (templ != NULL && !templ->value("photo").isUndefined()) { + QByteArray imageData = QByteArray::fromBase64(templ->value("photo").toString().toLatin1()); + photo.loadFromData(imageData, "PNG"); + } else { + photo.load(":/core/images/openpilot_logo_500.png"); + } + m_photoItem = ui->templateImage->scene()->addPixmap(photo); + ui->templateImage->setSceneRect(ui->templateImage->scene()->itemsBoundingRect()); + ui->templateImage->fitInView(ui->templateImage->scene()->itemsBoundingRect(), Qt::KeepAspectRatio); +} + +void VehicleTemplateSelectorWidget::updateDescription(QJsonObject *templ) +{ + if (templ != NULL) { + QString description; + description.append("").append(tr("Name of Vehicle: ")).append("").append(templ->value("name").toString()).append("
"); + description.append("").append(tr("Name of Owner: ")).append("").append(templ->value("owner").toString()); + if (templ->value("nick") != QStringLiteral("")) { + description.append(" (").append(templ->value("nick").toString()).append(")"); + } + description.append("
"); + description.append("").append(tr("Size: ")).append("").append(templ->value("size").toString()).append("
"); + description.append("").append(tr("Weight: ")).append("").append(templ->value("weight").toString()).append("
"); + description.append("").append(tr("Motor(s): ")).append("").append(templ->value("motor").toString()).append("
"); + description.append("").append(tr("ESC(s): ")).append("").append(templ->value("esc").toString()).append("
"); + description.append("").append(tr("Servo(s): ")).append("").append(templ->value("servo").toString()).append("
"); + description.append("").append(tr("Battery: ")).append("").append(templ->value("battery").toString()).append("
"); + description.append("").append(tr("Propellers(s): ")).append("").append(templ->value("propeller").toString()).append("
"); + description.append("").append(tr("Controller: ")).append("").append(templ->value("controller").toString()).append("
"); + description.append("").append(tr("Comments: ")).append("").append(templ->value("comment").toString()); + ui->templateDescription->setText(description); + } else { + ui->templateDescription->setText(tr("This option will use the current tuning settings saved on the controller, if your controller " + "is currently unconfigured, then the OpenPilot firmware defaults will be used.\n\n" + "It is suggested that if this is a first time configuration of your controller, rather than " + "use this option, instead select a tuning set that matches your own airframe as close as " + "possible from the list above or if you are not able to fine one, then select the generic item " + "from the list.")); + } +} + +void VehicleTemplateSelectorWidget::templateSelectionChanged() +{ + if (ui->templateList->currentRow() >= 0) { + QJsonObject *templ = ui->templateList->item(ui->templateList->currentRow())->data(Qt::UserRole + 1).value(); + updatePhoto(templ); + updateDescription(templ); + } +} + +bool VehicleTemplateSelectorWidget::airframeIsCompatible(int vehicleType, int vehicleSubType) +{ + if (vehicleType != m_vehicleType) { + return false; + } + + return vehicleSubType == m_vehicleSubType; +} + +void VehicleTemplateSelectorWidget::loadFilesInDir(QString templateBasePath) +{ + QDir templateDir(templateBasePath); + + qDebug() << "Loading templates from base path:" << templateBasePath; + QStringList names; + names << "*.optmpl"; + templateDir.setNameFilters(names); + templateDir.setSorting(QDir::Name); + QStringList files = templateDir.entryList(); + foreach(QString fileName, files) { + QFile file(QString("%1/%2").arg(templateDir.absolutePath()).arg(fileName)); + + if (file.open(QFile::ReadOnly)) { + QByteArray jsonData = file.readAll(); + QJsonParseError error; + QJsonDocument templateDoc = QJsonDocument::fromJson(jsonData, &error); + if (error.error == QJsonParseError::NoError) { + QJsonObject json = templateDoc.object(); + if (airframeIsCompatible(json["type"].toInt(), json["subtype"].toInt())) { + QString uuid = json["uuid"].toString(); + if (!m_templates.contains(uuid)) { + m_templates[json["uuid"].toString()] = new QJsonObject(json); + } + } + } else { + qDebug() << "Error parsing json file: " + << fileName << ". Error was:" << error.errorString(); + } + } + file.close(); + } +} + +void VehicleTemplateSelectorWidget::loadValidFiles() +{ + ui->templateList->clear(); + foreach(QJsonObject * templ, m_templates.values()) { + delete templ; + } + m_templates.clear(); + + loadFilesInDir(QString("%1/%2/").arg(Utils::PathUtils().InsertDataPath("%%DATAPATH%%cloudconfig")).arg(m_templateFolder)); + loadFilesInDir(QString("%1/%2/").arg(Utils::PathUtils().InsertStoragePath("%%STOREPATH%%cloudconfig")).arg(m_templateFolder)); +} + +void VehicleTemplateSelectorWidget::setupTemplateList() +{ + QListWidgetItem *item; + + foreach(QString templ, m_templates.keys()) { + QJsonObject *json = m_templates[templ]; + + item = new QListWidgetItem(json->value("name").toString(), ui->templateList); + item->setData(Qt::UserRole + 1, QVariant::fromValue(json)); + } + ui->templateList->sortItems(Qt::AscendingOrder); + + item = new QListWidgetItem(tr("Current Tuning")); + item->setData(Qt::UserRole + 1, QVariant::fromValue((QJsonObject *)NULL)); + ui->templateList->insertItem(0, item); + ui->templateList->setCurrentRow(0); + // TODO Add generics to top under item Current tuning +} + +QString VehicleTemplateSelectorWidget::getTemplateKey(QJsonObject *templ) +{ + return QString(templ->value("name").toString()); +} + +void VehicleTemplateSelectorWidget::resizeEvent(QResizeEvent *) +{ + ui->templateImage->setSceneRect(ui->templateImage->scene()->itemsBoundingRect()); + ui->templateImage->fitInView(ui->templateImage->scene()->itemsBoundingRect(), Qt::KeepAspectRatio); +} + +void VehicleTemplateSelectorWidget::showEvent(QShowEvent *) +{ + ui->templateImage->setSceneRect(ui->templateImage->scene()->itemsBoundingRect()); + ui->templateImage->fitInView(ui->templateImage->scene()->itemsBoundingRect(), Qt::KeepAspectRatio); } diff --git a/ground/openpilotgcs/src/plugins/setupwizard/vehicletemplateselectorwidget.h b/ground/openpilotgcs/src/plugins/setupwizard/vehicletemplateselectorwidget.h index e64749645..99e828142 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/vehicletemplateselectorwidget.h +++ b/ground/openpilotgcs/src/plugins/setupwizard/vehicletemplateselectorwidget.h @@ -28,6 +28,8 @@ #ifndef VEHICLETEMPLATESELECTORWIDGET_H #define VEHICLETEMPLATESELECTORWIDGET_H +#include +#include #include namespace Ui { @@ -48,14 +50,34 @@ public: updateTemplates(); } +public slots: + void templateSelectionChanged(); + +protected: + void resizeEvent(QResizeEvent *); + void showEvent(QShowEvent *); + private: Ui::VehicleTemplateSelectorWidget *ui; QString m_templateFolder; int m_vehicleType; int m_vehicleSubType; + QMap m_templates; + QGraphicsPixmapItem *m_photoItem; + + void loadValidFiles(); + void loadFilesInDir(QString templateBasePath); + void setupTemplateList(); + QString getTemplateKey(QJsonObject *templ); + void updatePhoto(QJsonObject *templ); + void updateDescription(QJsonObject *templ); + bool airframeIsCompatible(int vehicleType, int vehicleSubType); + private slots: void updateTemplates(); }; +Q_DECLARE_METATYPE(QJsonObject *) + #endif // VEHICLETEMPLATESELECTORWIDGET_H