Newer
Older
lm
committed
#include "QGCToolWidget.h"
#include "ui_QGCToolWidget.h"
#include <QMenu>
#include <QList>
#include <QInputDialog>
#include <QDockWidget>
#include <QContextMenuEvent>
#include <QFileDialog>
#include <QDesktopServices>
lm
committed
#include "QGCParamSlider.h"
Michael Carpenter
committed
#include "QGCComboBox.h"
Michael Carpenter
committed
#include "QGCTextLabel.h"
lm
committed
#include "UASManager.h"
QGCToolWidget::QGCToolWidget(const QString& title, QWidget *parent, QSettings* settings) :
QWidget(parent),
mav(NULL),
mainMenuAction(NULL),
widgetTitle(title),
lm
committed
{
Michael Carpenter
committed
isFromMetaData = false;
ui->setupUi(this);
if (settings) loadSettings(*settings);
if (title == "Unnamed Tool")
{
widgetTitle = QString("%1 %2").arg(title).arg(QGCToolWidget::instances()->count());
}
lm
committed
createActions();
lm
committed
toolLayout->setAlignment(Qt::AlignTop);
lm
committed
toolLayout->setSpacing(8);
lm
committed
QDockWidget* dock = dynamic_cast<QDockWidget*>(this->parentWidget());
dock->setWindowTitle(widgetTitle);
dock->setObjectName(widgetTitle+"DOCK");
// Try with parent
dock = dynamic_cast<QDockWidget*>(parent);
dock->setWindowTitle(widgetTitle);
dock->setObjectName(widgetTitle+"DOCK");
}
lm
committed
QList<UASInterface*> systems = UASManager::instance()->getUASList();
foreach (UASInterface* uas, systems)
{
lm
committed
UAS* newMav = dynamic_cast<UAS*>(uas);
lm
committed
addUAS(uas);
}
}
connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), this, SLOT(addUAS(UASInterface*)));
if (!instances()->contains(widgetTitle)) instances()->insert(widgetTitle, this);
// Enforce storage if this not loaded from settings
// is MUST NOT BE SAVED if it was loaded from settings!
Michael Carpenter
committed
//if (!settings) storeWidgetsToSettings();
lm
committed
}
QGCToolWidget::~QGCToolWidget()
{
if (mainMenuAction) mainMenuAction->deleteLater();
if (QGCToolWidget::instances()) QGCToolWidget::instances()->remove(widgetTitle);
lm
committed
delete ui;
}
void QGCToolWidget::setParent(QWidget *parent)
{
QWidget::setParent(parent);
// Try with parent
QDockWidget* dock = dynamic_cast<QDockWidget*>(parent);
if (dock)
{
dock->setWindowTitle(getTitle());
dock->setObjectName(getTitle()+"DOCK");
}
}
/**
* @param parent Object later holding these widgets, usually the main window
* @return List of all widgets
*/
QList<QGCToolWidget*> QGCToolWidget::createWidgetsFromSettings(QWidget* parent, QString settingsFile)
// Load widgets from application settings
QSettings* settings;
// Or load them from a settings file
if (!settingsFile.isEmpty())
{
settings = new QSettings(settingsFile, QSettings::IniFormat);
//qDebug() << "LOADING SETTINGS FROM" << settingsFile;
}
else
{
settings = new QSettings();
//qDebug() << "LOADING SETTINGS FROM DEFAULT" << settings->fileName();
Michael Carpenter
committed
settings->beginGroup("Custom_Tool_Widgets");
int size = settings->beginReadArray("QGC_TOOL_WIDGET_NAMES");
for (int i = 0; i < size; i++)
{
QString name = settings->value("TITLE", "").toString();
Michael Carpenter
committed
QString objname = settings->value("OBJECT_NAME", "").toString();
if (!instances()->contains(name) && name.length() != 0)
QGCToolWidget* tool = new QGCToolWidget(name, parent, settings);
Michael Carpenter
committed
tool->setObjectName(objname);
else if (name.length() == 0)
{
// Silently catch empty widget name - sanity check
// to survive broken settings (e.g. from user manipulation)
}
//qDebug() << "WIDGET" << name << "DID ALREADY EXIST, REJECTING";
//qDebug() << "NEW WIDGETS: " << newWidgets.size();
for (int i = 0; i < newWidgets.size(); i++)
{
Michael Carpenter
committed
settings->endGroup();
settings->sync();
Michael Carpenter
committed
void QGCToolWidget::showLabel(QString name,int num)
{
for (int i=0;i<toolItemList.size();i++)
{
if (toolItemList[i]->objectName() == name)
{
QGCTextLabel *label = qobject_cast<QGCTextLabel*>(toolItemList[i]);
if (label)
{
label->enableText(num);
}
}
}
}
/**
* @param singleinstance If this is set to true, the widget settings will only be loaded if not another widget with the same title exists
*/
bool QGCToolWidget::loadSettings(const QString& settings, bool singleinstance)
QSettings set(settings, QSettings::IniFormat);
QStringList groups = set.childGroups();
if (groups.length() > 0)
{
QString widgetName = groups.first();
this->setObjectName(widgetName);
if (singleinstance && QGCToolWidget::instances()->keys().contains(widgetName)) return false;
// Do not use setTitle() here,
// interferes with loading settings
widgetTitle = widgetName;
//qDebug() << "WIDGET TITLE LOADED: " << widgetName;
loadSettings(set);
return true;
}
else
{
return false;
}
Michael Carpenter
committed
void QGCToolWidget::setSettings(QVariantMap& settings)
{
Michael Carpenter
committed
isFromMetaData = true;
Michael Carpenter
committed
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
settingsMap = settings;
QString widgetName = getTitle();
int size = settingsMap["count"].toInt();
for (int j = 0; j < size; j++)
{
QString type = settings.value(widgetName + "\\" + QString::number(j) + "\\" + "TYPE", "UNKNOWN").toString();
if (type == "SLIDER")
{
QString checkparam = settingsMap.value(widgetName + "\\" + QString::number(j) + "\\" + "QGC_PARAM_SLIDER_PARAMID").toString();
paramList.append(checkparam);
}
else if (type == "COMBO")
{
QString checkparam = settingsMap.value(widgetName + "\\" + QString::number(j) + "\\" + "QGC_PARAM_COMBOBOX_PARAMID").toString();
paramList.append(checkparam);
}
}
}
QList<QString> QGCToolWidget::getParamList()
{
return paramList;
}
void QGCToolWidget::setParameterValue(int uas, int component, QString parameterName, const QVariant value)
{
QString widgetName = getTitle();
int size = settingsMap["count"].toInt();
Michael Carpenter
committed
if (paramToItemMap.contains(parameterName))
{
//If we already have an item for this parameter, updates are handled internally.
Michael Carpenter
committed
return;
}
Michael Carpenter
committed
for (int j = 0; j < size; j++)
{
QString type = settingsMap.value(widgetName + "\\" + QString::number(j) + "\\" + "TYPE", "UNKNOWN").toString();
QGCToolWidgetItem* item = NULL;
if (type == "COMMANDBUTTON")
{
//This shouldn't happen, but I'm not sure... so lets test for it.
continue;
Michael Carpenter
committed
}
else if (type == "SLIDER")
{
QString checkparam = settingsMap.value(widgetName + "\\" + QString::number(j) + "\\" + "QGC_PARAM_SLIDER_PARAMID").toString();
if (checkparam == parameterName)
{
item = new QGCParamSlider(this);
Michael Carpenter
committed
paramToItemMap[parameterName] = item;
Michael Carpenter
committed
addToolWidget(item);
item->readSettings(widgetName + "\\" + QString::number(j) + "\\",settingsMap);
return;
}
}
else if (type == "COMBO")
{
QString checkparam = settingsMap.value(widgetName + "\\" + QString::number(j) + "\\" + "QGC_PARAM_COMBOBOX_PARAMID").toString();
if (checkparam == parameterName)
{
item = new QGCComboBox(this);
addToolWidget(item);
item->readSettings(widgetName + "\\" + QString::number(j) + "\\",settingsMap);
Michael Carpenter
committed
paramToItemMap[parameterName] = item;
Michael Carpenter
committed
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
return;
}
}
}
}
void QGCToolWidget::loadSettings(QVariantMap& settings)
{
QString widgetName = getTitle();
//settings.beginGroup(widgetName);
qDebug() << "LOADING FOR" << widgetName;
//int size = settings.beginReadArray("QGC_TOOL_WIDGET_ITEMS");
int size = settings["count"].toInt();
qDebug() << "CHILDREN SIZE:" << size;
for (int j = 0; j < size; j++)
{
QApplication::processEvents();
//settings.setArrayIndex(j);
QString type = settings.value(widgetName + "\\" + QString::number(j) + "\\" + "TYPE", "UNKNOWN").toString();
if (type != "UNKNOWN")
{
QGCToolWidgetItem* item = NULL;
if (type == "COMMANDBUTTON")
{
item = new QGCCommandButton(this);
//qDebug() << "CREATED COMMANDBUTTON";
}
Michael Carpenter
committed
else if (type == "TEXT")
{
item = new QGCTextLabel(this);
item->setActiveUAS(mav);
}
Michael Carpenter
committed
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
else if (type == "SLIDER")
{
item = new QGCParamSlider(this);
//qDebug() << "CREATED PARAM SLIDER";
}
else if (type == "COMBO")
{
item = new QGCComboBox(this);
//qDebug() << "CREATED PARAM COMBOBOX";
}
if (item)
{
// Configure and add to layout
addToolWidget(item);
item->readSettings(widgetName + "\\" + QString::number(j) + "\\",settings);
//qDebug() << "Created tool widget";
}
}
else
{
qDebug() << "UNKNOWN TOOL WIDGET TYPE" << type;
}
}
//settings.endArray();
//settings.endGroup();
}
void QGCToolWidget::loadSettings(QSettings& settings)
{
QString widgetName = getTitle();
settings.beginGroup(widgetName);
int size = settings.beginReadArray("QGC_TOOL_WIDGET_ITEMS");
for (int j = 0; j < size; j++)
{
settings.setArrayIndex(j);
QString type = settings.value("TYPE", "UNKNOWN").toString();
if (type == "COMMANDBUTTON")
{
Michael Carpenter
committed
QGCCommandButton *button = new QGCCommandButton(this);
connect(button,SIGNAL(showLabel(QString,int)),this,SLOT(showLabel(QString,int)));
item = button;
item->setActiveUAS(mav);
}
else if (type == "SLIDER")
{
Michael Carpenter
committed
item->setActiveUAS(mav);
Michael Carpenter
committed
else if (type == "COMBO")
{
item = new QGCComboBox(this);
Michael Carpenter
committed
item->setActiveUAS(mav);
Michael Carpenter
committed
qDebug() << "CREATED PARAM COMBOBOX";
}
Michael Carpenter
committed
else if (type == "TEXT")
{
item = new QGCTextLabel(this);
item->setObjectName(settings.value("QGC_TEXT_ID").toString());
item->setActiveUAS(mav);
}
// Configure and add to layout
addToolWidget(item);
item->readSettings(settings);
}
}
settings.endArray();
settings.endGroup();
}
void QGCToolWidget::storeWidgetsToSettings(QString settingsFile)
QSettings* settings;
if (!settingsFile.isEmpty())
{
settings = new QSettings(settingsFile, QSettings::IniFormat);
//qDebug() << "STORING SETTINGS TO" << settings->fileName();
}
else
{
settings = new QSettings();
//qDebug() << "STORING SETTINGS TO DEFAULT" << settings->fileName();
Michael Carpenter
committed
settings->beginGroup("Custom_Tool_Widgets");
int preArraySize = settings->beginReadArray("QGC_TOOL_WIDGET_NAMES");
settings->endArray();
settings->beginWriteArray("QGC_TOOL_WIDGET_NAMES");
Michael Carpenter
committed
int num = 0;
for (int i = 0; i < qMax(preArraySize, instances()->size()); ++i)
if (i < instances()->size())
{
// Updating value
Michael Carpenter
committed
if (!instances()->values().at(i)->fromMetaData())
{
settings->setArrayIndex(num++);
settings->setValue("TITLE", instances()->values().at(i)->getTitle());
Michael Carpenter
committed
settings->setValue("OBJECT_NAME", instances()->values().at(i)->objectName());
Michael Carpenter
committed
//qDebug() << "WRITING TITLE" << instances()->values().at(i)->getTitle();
}
}
else
{
// Deleting old value
settings->remove("TITLE");
}
for (int i = 0; i < instances()->size(); ++i)
{
instances()->values().at(i)->storeSettings(*settings);
}
Michael Carpenter
committed
settings->endGroup();
settings->sync();
void QGCToolWidget::storeSettings()
{
QSettings settings;
storeSettings(settings);
}
void QGCToolWidget::storeSettings(const QString& settingsFile)
{
QSettings settings(settingsFile, QSettings::IniFormat);
storeSettings(settings);
}
void QGCToolWidget::storeSettings(QSettings& settings)
{
Michael Carpenter
committed
if (isFromMetaData)
{
//Refuse to store if this is loaded from metadata or dynamically generated.
return;
}
//qDebug() << "WRITING WIDGET" << widgetTitle << "TO SETTINGS";
settings.beginWriteArray("QGC_TOOL_WIDGET_ITEMS");
int k = 0; // QGCToolItem counter
for (int j = 0; j < children().size(); ++j)
{
// Store only QGCToolWidgetItems
QGCToolWidgetItem* item = dynamic_cast<QGCToolWidgetItem*>(children().at(j));
// Only count actual tool widget item children
settings.setArrayIndex(k++);
// Store the ToolWidgetItem
item->writeSettings(settings);
//qDebug() << "WROTE" << k << "SUB-WIDGETS TO SETTINGS";
settings.endArray();
settings.endGroup();
lm
committed
void QGCToolWidget::addUAS(UASInterface* uas)
{
UAS* newMav = dynamic_cast<UAS*>(uas);
lm
committed
// FIXME Convert to list
if (mav == NULL) mav = newMav;
}
}
void QGCToolWidget::contextMenuEvent (QContextMenuEvent* event)
{
QMenu menu(this);
menu.addAction(addParamAction);
menu.addSeparator();
lm
committed
menu.addAction(setTitleAction);
lm
committed
menu.exec(event->globalPos());
}
void QGCToolWidget::hideEvent(QHideEvent* event)
{
// Store settings
QWidget::hideEvent(event);
}
/**
* The widgets current view and the applied dock widget area.
* Both values are only stored internally and allow an external
* widget to configure it accordingly
*/
void QGCToolWidget::setViewVisibilityAndDockWidgetArea(int view, bool visible, Qt::DockWidgetArea area)
{
viewVisible.insert(view, visible);
dockWidgetArea.insert(view, area);
}
lm
committed
void QGCToolWidget::createActions()
{
addParamAction = new QAction(tr("New &Parameter Slider"), this);
addParamAction->setStatusTip(tr("Add a parameter setting slider widget to the tool"));
connect(addParamAction, SIGNAL(triggered()), this, SLOT(addParam()));
addCommandAction = new QAction(tr("New MAV &Command Button"), this);
addCommandAction->setStatusTip(tr("Add a new action button to the tool"));
connect(addCommandAction, SIGNAL(triggered()), this, SLOT(addCommand()));
lm
committed
setTitleAction = new QAction(tr("Set Widget Title"), this);
setTitleAction->setStatusTip(tr("Set the title caption of this tool widget"));
connect(setTitleAction, SIGNAL(triggered()), this, SLOT(setTitle()));
deleteAction = new QAction(tr("Delete this widget"), this);
deleteAction->setStatusTip(tr("Delete this widget permanently"));
connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteWidget()));
exportAction = new QAction(tr("Export this widget"), this);
exportAction->setStatusTip(tr("Export this widget to be reused by others"));
connect(exportAction, SIGNAL(triggered()), this, SLOT(exportWidget()));
importAction = new QAction(tr("Import widget"), this);
importAction->setStatusTip(tr("Import this widget from a file (current content will be removed)"));
connect(importAction, SIGNAL(triggered()), this, SLOT(importWidget()));
}
QMap<QString, QGCToolWidget*>* QGCToolWidget::instances()
{
static QMap<QString, QGCToolWidget*>* instances;
if (!instances) instances = new QMap<QString, QGCToolWidget*>();
return instances;
}
QList<QGCToolWidgetItem*>* QGCToolWidget::itemList()
{
static QList<QGCToolWidgetItem*>* instances;
if (!instances) instances = new QList<QGCToolWidgetItem*>();
return instances;
lm
committed
}
Michael Carpenter
committed
void QGCToolWidget::addParam(int uas,int component,QString paramname,QVariant value)
{
Michael Carpenter
committed
isFromMetaData = true;
Michael Carpenter
committed
QGCParamSlider* slider = new QGCParamSlider(this);
connect(slider, SIGNAL(destroyed()), this, SLOT(storeSettings()));
if (ui->hintLabel)
{
ui->hintLabel->deleteLater();
ui->hintLabel = NULL;
}
toolLayout->addWidget(slider);
slider->setActiveUAS(mav);
slider->setParameterValue(uas,component,0,-1,paramname,value);
}
lm
committed
void QGCToolWidget::addParam()
{
QGCParamSlider* slider = new QGCParamSlider(this);
connect(slider, SIGNAL(destroyed()), this, SLOT(storeSettings()));
ui->hintLabel = NULL;
lm
committed
toolLayout->addWidget(slider);
slider->startEditMode();
}
void QGCToolWidget::addCommand()
{
QGCCommandButton* button = new QGCCommandButton(this);
connect(button, SIGNAL(destroyed()), this, SLOT(storeSettings()));
ui->hintLabel->deleteLater();
ui->hintLabel = NULL;
}
toolLayout->addWidget(button);
button->startEditMode();
}
void QGCToolWidget::addToolWidget(QGCToolWidgetItem* widget)
{
ui->hintLabel = NULL;
connect(widget, SIGNAL(destroyed()), this, SLOT(storeSettings()));
Michael Carpenter
committed
toolItemList.append(widget);
void QGCToolWidget::exportWidget()
{
const QString widgetFileExtension(".qgw");
QString fileName = QFileDialog::getSaveFileName(this, tr("Specify File Name"), QDesktopServices::storageLocation(QDesktopServices::DesktopLocation), tr("QGroundControl Widget (*%1);;").arg(widgetFileExtension));
if (!fileName.endsWith(widgetFileExtension))
{
fileName = fileName.append(widgetFileExtension);
}
storeSettings(fileName);
const QString widgetFileExtension(".qgw");
QString fileName = QFileDialog::getOpenFileName(this, tr("Specify File Name"), QDesktopServices::storageLocation(QDesktopServices::DesktopLocation), tr("QGroundControl Widget (*%1);;").arg(widgetFileExtension));
loadSettings(fileName);
return widgetTitle;
lm
committed
void QGCToolWidget::setTitle()
{
QDockWidget* parent = dynamic_cast<QDockWidget*>(this->parentWidget());
QString text = QInputDialog::getText(this, tr("Enter Widget Title"),
lm
committed
tr("Widget title:"), QLineEdit::Normal,
parent->windowTitle(), &ok);
if (ok && !text.isEmpty())
{
setTitle(text);
lm
committed
}
}
void QGCToolWidget::setWindowTitle(const QString& title)
{
// Sets title and calls setWindowTitle on QWidget
widgetTitle = title;
QWidget::setWindowTitle(title);
void QGCToolWidget::setTitle(QString title)
{
// Remove references to old title
Michael Carpenter
committed
/*QSettings settings;
settings.beginGroup(widgetTitle);
settings.remove("");
settings.endGroup();
Michael Carpenter
committed
settings.sync();*/
if (instances()->contains(widgetTitle)) instances()->remove(widgetTitle);
// Switch to new title
widgetTitle = title;
if (!instances()->contains(title)) instances()->insert(title, this);
QWidget::setWindowTitle(title);
QDockWidget* parent = dynamic_cast<QDockWidget*>(this->parentWidget());
if (parent) parent->setWindowTitle(title);
Michael Carpenter
committed
//storeWidgetsToSettings();
emit titleChanged(title);
if (mainMenuAction) mainMenuAction->setText(title);
}
void QGCToolWidget::setMainMenuAction(QAction* action)
{
this->mainMenuAction = action;
}
void QGCToolWidget::deleteWidget()
{
// Remove from settings
// Hide
this->hide();
instances()->remove(getTitle());
Michael Carpenter
committed
/*QSettings settings;
settings.beginGroup(getTitle());
settings.remove("");
settings.endGroup();
Michael Carpenter
committed
storeWidgetsToSettings();*/