2 ******************************************************************************
4 * @file uavsettingsimportexportfactory.cpp
5 * @author (C) 2011 The OpenPilot Team, http://www.openpilot.org
6 * @addtogroup GCSPlugins GCS Plugins
8 * @addtogroup UAVSettingsImportExport UAVSettings Import/Export Plugin
10 * @brief UAVSettings Import/Export Plugin
11 *****************************************************************************/
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "uavsettingsimportexportfactory.h"
30 #include <QStringList>
33 #include "importsummary.h"
34 #include "version_info/version_info.h"
37 #include <coreplugin/coreconstants.h>
38 #include <coreplugin/actionmanager/actionmanager.h>
39 #include <coreplugin/icore.h>
40 #include <QKeySequence>
43 #include "uavdataobject.h"
44 #include "uavobjectmanager.h"
45 #include "extensionsystem/pluginmanager.h"
48 #include <QDomDocument>
50 // for file dialog and error messages
51 #include <QFileDialog>
52 #include <QMessageBox>
54 UAVSettingsImportExportFactory::~UAVSettingsImportExportFactory()
59 UAVSettingsImportExportFactory::UAVSettingsImportExportFactory(QObject
*parent
) : QObject(parent
)
62 Core::ActionManager
*am
= Core::ICore::instance()->actionManager();
63 Core::ActionContainer
*ac
= am
->actionContainer(Core::Constants::M_FILE
);
64 Core::Command
*cmd
= am
->registerAction(new QAction(this),
65 "UAVSettingsImportExportPlugin.UAVSettingsExport",
67 Core::Constants::C_GLOBAL_ID
);
69 cmd
->setDefaultKeySequence(QKeySequence("Ctrl+E"));
70 cmd
->action()->setText(tr("Export UAV Settings..."));
71 ac
->addAction(cmd
, Core::Constants::G_FILE_SAVE
);
72 connect(cmd
->action(), SIGNAL(triggered(bool)), this, SLOT(exportUAVSettings()));
74 cmd
= am
->registerAction(new QAction(this),
75 "UAVSettingsImportExportPlugin.UAVSettingsImport",
77 Core::Constants::C_GLOBAL_ID
);
78 cmd
->setDefaultKeySequence(QKeySequence("Ctrl+I"));
79 cmd
->action()->setText(tr("Import UAV Settings..."));
80 ac
->addAction(cmd
, Core::Constants::G_FILE_SAVE
);
81 connect(cmd
->action(), SIGNAL(triggered(bool)), this, SLOT(importUAVSettings()));
83 ac
= am
->actionContainer(Core::Constants::M_HELP
);
84 cmd
= am
->registerAction(new QAction(this),
85 "UAVSettingsImportExportPlugin.UAVDataExport",
87 Core::Constants::C_GLOBAL_ID
);
88 cmd
->action()->setText(tr("Export UAV Data..."));
89 ac
->addAction(cmd
, Core::Constants::G_HELP_HELP
);
90 connect(cmd
->action(), SIGNAL(triggered(bool)), this, SLOT(exportUAVData()));
93 // Slot called by the menu manager on user action
94 void UAVSettingsImportExportFactory::importUAVSettings()
98 QString filters
= tr("UAVObjects XML files (*.uav);; XML files (*.xml)");
100 fileName
= QFileDialog::getOpenFileName(0, tr("Import UAV Settings"), "", filters
);
101 if (fileName
.isEmpty()) {
106 QFile
file(fileName
);
107 QDomDocument
doc("UAVObjects");
108 file
.open(QFile::ReadOnly
| QFile::Text
);
109 if (!doc
.setContent(file
.readAll())) {
111 msgBox
.setText(tr("File Parsing Failed."));
112 msgBox
.setInformativeText(tr("This file is not a correct XML file"));
113 msgBox
.setStandardButtons(QMessageBox::Ok
);
119 // find the root of settings subtree
120 emit
importAboutToBegin();
121 qDebug() << "Import about to begin";
123 QDomElement root
= doc
.documentElement();
124 if (root
.tagName() == "uavobjects") {
125 root
= root
.firstChildElement("settings");
127 if (root
.isNull() || (root
.tagName() != "settings")) {
129 msgBox
.setText(tr("Wrong file contents"));
130 msgBox
.setInformativeText(tr("This file does not contain correct UAVSettings"));
131 msgBox
.setStandardButtons(QMessageBox::Ok
);
136 // We are now ok: setup the import summary dialog & update it as we
138 ImportSummaryDialog
swui((QWidget
*)Core::ICore::instance()->mainWindow());
140 ExtensionSystem::PluginManager
*pm
= ExtensionSystem::PluginManager::instance();
141 UAVObjectManager
*objManager
= pm
->getObject
<UAVObjectManager
>();
144 QDomNode node
= root
.firstChild();
145 while (!node
.isNull()) {
146 QDomElement e
= node
.toElement();
147 if (e
.tagName() == "object") {
148 // - Read each object
149 QString uavObjectName
= e
.attribute("name");
150 uint uavObjectID
= e
.attribute("id").toUInt(NULL
, 16);
153 UAVObject
*obj
= objManager
->getObject(uavObjectName
);
155 // This object is unknown!
156 qDebug() << "Object unknown:" << uavObjectName
<< uavObjectID
;
157 swui
.addLine(uavObjectName
, "Error (Object unknown)", false);
159 // - Update each field
160 // - Issue and "updated" command
162 bool setError
= false;
163 QDomNode field
= node
.firstChild();
164 while (!field
.isNull()) {
165 QDomElement f
= field
.toElement();
166 if (f
.tagName() == "field") {
167 UAVObjectField
*uavfield
= obj
->getField(f
.attribute("name"));
169 QStringList list
= f
.attribute("values").split(",");
170 if (list
.length() == 1) {
171 if (false == uavfield
->checkValue(f
.attribute("values"))) {
172 qDebug() << "checkValue returned false on: " << uavObjectName
<< f
.attribute("values");
175 uavfield
->setValue(f
.attribute("values"));
180 QStringList list
= f
.attribute("values").split(",");
181 foreach(QString element
, list
) {
182 if (false == uavfield
->checkValue(element
, i
)) {
183 qDebug() << "checkValue(list) returned false on: " << uavObjectName
<< list
;
186 uavfield
->setValue(element
, i
);
195 field
= field
.nextSibling();
200 swui
.addLine(uavObjectName
, "Warning (Object field unknown)", true);
201 } else if (uavObjectID
!= obj
->getObjID()) {
202 qDebug() << "Mismatch for Object " << uavObjectName
<< uavObjectID
<< " - " << obj
->getObjID();
203 swui
.addLine(uavObjectName
, "Warning (ObjectID mismatch)", true);
204 } else if (setError
) {
205 swui
.addLine(uavObjectName
, "Warning (Objects field value(s) invalid)", false);
207 swui
.addLine(uavObjectName
, "OK", true);
211 node
= node
.nextSibling();
213 qDebug() << "End import";
217 // Create an XML document from UAVObject database
218 QString
UAVSettingsImportExportFactory::createXMLDocument(const enum storedData what
, const bool fullExport
)
220 // generate an XML first (used for all export formats as a formatted data source)
221 ExtensionSystem::PluginManager
*pm
= ExtensionSystem::PluginManager::instance();
222 UAVObjectManager
*objManager
= pm
->getObject
<UAVObjectManager
>();
224 // create an XML root
225 QDomDocument
doc("UAVObjects");
226 QDomElement root
= doc
.createElement("uavobjects");
228 doc
.appendChild(root
);
230 // add hardware, firmware and GCS version info
231 QDomElement versionInfo
= doc
.createElement("version");
232 root
.appendChild(versionInfo
);
234 UAVObjectUtilManager
*utilMngr
= pm
->getObject
<UAVObjectUtilManager
>();
235 deviceDescriptorStruct board
= utilMngr
->getBoardDescriptionStruct();
237 QDomElement hw
= doc
.createElement("hardware");
238 hw
.setAttribute("type", QString().setNum(board
.boardType
, 16));
239 hw
.setAttribute("revision", QString().setNum(board
.boardRevision
, 16));
240 hw
.setAttribute("serial", QString(utilMngr
->getBoardCPUSerial().toHex()));
241 versionInfo
.appendChild(hw
);
243 QDomElement fw
= doc
.createElement("firmware");
244 QString uavo
= board
.uavoHash
.toHex();
245 fw
.setAttribute("tag", board
.gitTag
);
246 fw
.setAttribute("date", board
.gitDate
);
247 fw
.setAttribute("hash", board
.gitHash
);
248 fw
.setAttribute("uavo", uavo
.left(8));
249 versionInfo
.appendChild(fw
);
251 QDomElement gcs
= doc
.createElement("gcs");
252 gcs
.setAttribute("tag", VersionInfo::tagOrBranch() + VersionInfo::dirty());
253 gcs
.setAttribute("date", VersionInfo::dateTime());
254 gcs
.setAttribute("hash", VersionInfo::hash().left(8));
255 gcs
.setAttribute("uavo", VersionInfo::uavoHash().left(8));
256 versionInfo
.appendChild(gcs
);
258 // create settings and/or data elements
259 QDomElement settings
= doc
.createElement("settings");
260 QDomElement data
= doc
.createElement("data");
264 root
.appendChild(settings
);
267 root
.appendChild(data
);
270 root
.appendChild(data
);
271 root
.appendChild(settings
);
275 // iterate over settings objects
276 QList
< QList
<UAVDataObject
*> > objList
= objManager
->getDataObjects();
277 foreach(QList
<UAVDataObject
*> list
, objList
) {
278 foreach(UAVDataObject
* obj
, list
) {
279 if (((what
== Settings
) && obj
->isSettingsObject()) ||
280 ((what
== Data
) && !obj
->isSettingsObject()) ||
282 // add each object to the XML
283 QDomElement o
= doc
.createElement("object");
284 o
.setAttribute("name", obj
->getName());
285 o
.setAttribute("id", QString("0x") + QString().setNum(obj
->getObjID(), 16).toUpper());
287 QDomElement d
= doc
.createElement("description");
288 QDomText t
= doc
.createTextNode(obj
->getDescription().remove("@Ref ", Qt::CaseInsensitive
));
293 // iterate over fields
294 QList
<UAVObjectField
*> fieldList
= obj
->getFields();
296 foreach(UAVObjectField
* field
, fieldList
) {
297 QDomElement f
= doc
.createElement("field");
299 // iterate over values
301 quint32 nelem
= field
->getNumElements();
303 for (unsigned int n
= 0; n
< nelem
; ++n
) {
304 vals
.append(QString("%1,").arg(field
->getValue(n
).toString()));
308 f
.setAttribute("name", field
->getName());
309 f
.setAttribute("values", vals
);
311 f
.setAttribute("type", field
->getTypeAsString());
312 f
.setAttribute("units", field
->getUnits());
313 f
.setAttribute("elements", nelem
);
314 if (field
->getType() == UAVObjectField::ENUM
) {
315 f
.setAttribute("options", field
->getOptions().join(","));
321 // append to the settings or data element
322 if (obj
->isSettingsObject()) {
323 settings
.appendChild(o
);
331 return doc
.toString(4);
334 // Slot called by the menu manager on user action
335 void UAVSettingsImportExportFactory::exportUAVSettings()
339 QString filters
= tr("UAVObjects XML files (*.uav)");
341 fileName
= QFileDialog::getSaveFileName(0, tr("Save UAVSettings File As"), "", filters
);
342 if (fileName
.isEmpty()) {
346 // If the filename ends with .xml, we will do a full export, otherwise, a simple export
347 bool fullExport
= false;
348 if (fileName
.endsWith(".xml")) {
350 } else if (!fileName
.endsWith(".uav")) {
351 fileName
.append(".uav");
354 // generate an XML first (used for all export formats as a formatted data source)
355 QString xml
= createXMLDocument(Settings
, fullExport
);
358 QFile
file(fileName
);
359 if (file
.open(QIODevice::WriteOnly
) &&
360 (file
.write(xml
.toLatin1()) != -1)) {
363 QMessageBox::critical(0,
364 tr("UAV Settings Export"),
365 tr("Unable to save settings: ") + fileName
,
371 msgBox
.setText(tr("Settings saved."));
372 msgBox
.setStandardButtons(QMessageBox::Ok
);
376 // Slot called by the menu manager on user action
377 void UAVSettingsImportExportFactory::exportUAVData()
379 if (QMessageBox::question(0, tr("Are you sure?"),
380 tr("This option is only useful for passing your current "
381 "system data to the technical support staff. "
382 "Do you really want to export?"),
383 QMessageBox::Ok
| QMessageBox::Cancel
,
384 QMessageBox::Ok
) != QMessageBox::Ok
) {
390 QString filters
= tr("UAVObjects XML files (*.uav)");
392 fileName
= QFileDialog::getSaveFileName(0, tr("Save UAVData File As"), "", filters
);
393 if (fileName
.isEmpty()) {
397 // If the filename ends with .xml, we will do a full export, otherwise, a simple export
398 bool fullExport
= false;
399 if (fileName
.endsWith(".xml")) {
401 } else if (!fileName
.endsWith(".uav")) {
402 fileName
.append(".uav");
405 // generate an XML first (used for all export formats as a formatted data source)
406 QString xml
= createXMLDocument(Both
, fullExport
);
409 QFile
file(fileName
);
410 if (file
.open(QIODevice::WriteOnly
) &&
411 (file
.write(xml
.toLatin1()) != -1)) {
414 QMessageBox::critical(0,
415 tr("UAV Data Export"),
416 tr("Unable to save data: ") + fileName
,
422 msgBox
.setText(tr("Data saved."));
423 msgBox
.setStandardButtons(QMessageBox::Ok
);