4 #include <QGraphicsScene> 5 #include <QGraphicsView> 6 #include <QGraphicsPixmapItem> 9 #include <QDomDocument> 10 #include <QDomElement> 11 #include <QFileDialog> 12 #include <QMessageBox> 14 #include <QDesktopServices> 17 #include "../model/arena.h" 18 #include "../model/arenaelement.h" 19 #include "../model/arenaelementtype.h" 20 #include "../model/arenaelementtyperegistry.h" 27 #include "../global.h" 31 , m_ui(new
Ui::MainWindow)
32 , m_loadingSuccessful(false)
38 qDebug() <<
"[Rescue Arena Designer] Successfully parsed hector_arena_gui and hector_arena_elements package dirs from command line arguments.";
42 qDebug() <<
"[Rescue Arena Designer] Using rospack to find hector_arena_gui and hector_arena_elements packages.";
75 m_arenaView->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
78 m_ui->infoRot->setTextFormat(Qt::RichText);
86 connect(
m_ui->actionRotateClockwise, SIGNAL(triggered()),
89 connect(
m_ui->actionRotateCounterClockwise, SIGNAL(triggered()),
92 connect(
m_ui->actionRemove, SIGNAL(triggered()),
95 connect(
m_ui->infoItemMountPoint, SIGNAL(currentIndexChanged(
int)),
99 connect(
m_ui->actionNew, SIGNAL(triggered()),
102 connect(
m_ui->actionOpen, SIGNAL(triggered()),
105 connect(
m_ui->actionSave, SIGNAL(triggered()),
108 connect(
m_ui->actionSaveAs, SIGNAL(triggered()),
111 connect(
m_ui->actionExport, SIGNAL(triggered()),
114 connect(
m_ui->actionExportSdf, SIGNAL(triggered()),
117 connect(
m_ui->actionShowDocumentation, SIGNAL(triggered()),
120 connect(
m_arena, SIGNAL(modified()),
126 connect(
m_ui->actionZoomIn, SIGNAL(triggered()),
129 connect(
m_ui->actionZoomOut, SIGNAL(triggered()),
136 connect(
m_arena, SIGNAL(modified()),
139 setUnifiedTitleAndToolBarOnMac(
true);
145 setWindowModified(
false);
153 rosFind.start(
"rospack", QStringList() <<
"find" << name);
154 if (!rosFind.waitForFinished())
156 if (rosFind.error() == QProcess::FailedToStart)
157 QMessageBox::critical(
this,
"Can't find rospack",
158 "The program 'rospack' is missing or not in your PATH. Check your ROS installation.");
160 QMessageBox::critical(
this,
"Can't find " + name +
" ROS package",
161 "The program 'rospack' used to locate ROS packages didn't terminate correctly. Check your ROS installation.");
165 QByteArray rosFindOutput = rosFind.readAll();
166 QList<QByteArray> rosFindOutputLines = rosFindOutput.split(
'\n');
167 foreach (QByteArray line, rosFindOutputLines)
173 if (line.startsWith(
"["))
178 if (result.isEmpty())
180 QMessageBox::critical(
this,
"Can't find " + name +
" ROS package",
181 "The program 'rospack' could not locate the package " + name +
". Check your installation.");
191 if (qApp->arguments().size() < 2)
194 QString gui_dir, elements_dir;
195 QStringList args = qApp->arguments();
198 foreach (QString arg, args)
200 QStringList splitted = arg.split(
'=');
201 if (splitted.size() != 2)
203 if (splitted.at(0) ==
"-hector_arena_gui_dir")
204 gui_dir = splitted.at(1);
205 else if (splitted.at(0) ==
"-hector_arena_elements_dir")
206 elements_dir = splitted.at(1);
209 if (!gui_dir.isEmpty() && !elements_dir.isEmpty())
211 if (!QDir(gui_dir).exists())
213 QMessageBox::critical(
this,
"Invalid path name",
214 "The path " + gui_dir +
" doesn't exist. Check your -hector_arena_gui command line argument. Falling back to 'rospack find'...");
217 if (!QDir(elements_dir).exists())
219 QMessageBox::critical(
this,
"Invalid path name",
220 "The path " + elements_dir +
" doesn't exist. Check your -hector_arena_elements command line argument. Falling back to 'rospack find'...");
229 qDebug() <<
"[Rescue Arena Designer] Invalid command line arguments:";
230 qDebug() <<
"[Rescue Arena Designer]" << args;
237 QFile in(configFile);
238 in.open(QFile::ReadOnly);
240 bool configValid = doc.setContent(&in);
245 QDomElement rootElement = doc.firstChildElement();
246 Q_ASSERT(rootElement.tagName() ==
"config");
248 QDomNodeList childNodes = rootElement.childNodes();
249 for (
int i = 0; i < childNodes.count(); i++)
251 QDomElement childElement = childNodes.at(i).toElement();
252 if (childElement.tagName() ==
"arena-elements")
261 QMessageBox::warning(
this,
"Failed to load config.xml",
"Your config.xml seems to be an invalid XML file. Make sure it is valid and try again.");
306 bool hasSingleSelection = _selectedElements.count() == 1;
307 m_ui->infoWidget->setVisible(hasSingleSelection);
308 m_ui->infoHintLabel->setVisible(!hasSingleSelection);
309 if (!hasSingleSelection)
314 m_ui->infoWidget->show();
315 m_ui->infoHintLabel->hide();
321 QTextStream(&name) <<
"(" << element->
pos().x() <<
", " << element->
pos().y() <<
")";
322 m_ui->infoPos->setText(name);
325 QTextStream(&rot) << element->
rotation() <<
"°";
326 m_ui->infoRot->setText(rot);
330 m_ui->infoOffsetLabel->setVisible(
true);
331 m_ui->infoOffset->setVisible(
true);
333 QTextStream stream(&offsetText);
334 stream.setRealNumberNotation(QTextStream::FixedNotation);
335 stream.setRealNumberPrecision(3);
337 m_ui->infoOffset->setText(offsetText);
341 m_ui->infoOffsetLabel->setVisible(
false);
342 m_ui->infoOffset->setVisible(
false);
347 m_ui->infoItemMountPointLabel->setVisible(
true);
348 m_ui->infoItemMountPoint->setVisible(
true);
349 m_ui->infoItemMountPoint->clear();
351 m_ui->infoItemMountPoint->setEnabled(contextElement);
358 m_ui->infoItemMountPoint->blockSignals(
true);
361 m_ui->infoItemMountPoint->addItem(hole.first);
364 m_ui->infoItemMountPoint->blockSignals(
false);
369 m_ui->infoItemMountPointLabel->setVisible(
false);
370 m_ui->infoItemMountPoint->setVisible(
false);
381 bool hasSingleSelection = _selectedElements.count() == 1;
382 if (!hasSingleSelection)
393 if (isWindowModified())
395 QString text =
"Do you want to save changes to the current arena?";
396 if (QMessageBox::question(
this,
"Save Arena?", text, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes)
403 setWindowModified(
true);
412 setWindowModified(
false);
418 QString target = QFileDialog::getOpenFileName(
this,
"Select arena file to open",
m_openSaveDir,
".raf File (*.raf)");
419 if (!target.isEmpty())
424 setWindowModified(
false);
435 setWindowModified(
false);
440 QString target = QFileDialog::getSaveFileName(
this,
"Select file to save arena to",
m_openSaveDir,
".raf File (*.raf)");
441 if (!target.isEmpty())
445 setWindowModified(
false);
451 QString target = QFileDialog::getSaveFileName(
this,
"Select file to export arena to",
m_exportDir,
"Gazebo .world File (*.world)");
452 if (!target.isEmpty())
461 QString target = QFileDialog::getSaveFileName(
this,
"Select file to export arena to",
m_exportDir,
"Gazebo .world File (*.world)");
462 if (!target.isEmpty())
472 QDesktopServices::openUrl(indexHtml);
493 QMainWindow::closeEvent(event);
QString findRosPackage(const QString &name)
ArenaElementType const * type() const
void loadConfig(const QDomElement &arenaElements)
void removeElement(ArenaElement *element)
QList< ItemMountPoint > itemMountPoints() const
void slotElementTypeHovered(ArenaElement *element)
void setCurrentArenaFile(QString fileName)
void setItemMountPoint(int mountPoint)
See itemMountPoint(). Use -1 to set index to "unspecified".
void clear()
Removes all elements from this arena.
QList< ArenaSceneElement * > selectedElements()
int itemMountPoint() const
QString m_hector_arena_gui_package_dir
void saveWorld(const QString &filename)
Writes .world format-compliant XML.
void load(const QString &filename)
Deserializes this arena from XML.
ArenaScene * m_arenaScene
void askToSaveChangesIfModified()
bool isItem() const
Convenience method returning true iff. this is an item element (freely movable)
void slotRotateClockwise()
void slotSelectionChanged()
QVector< QStringPair > metaInfos() const
void slotRotateCounterClockwise()
ArenaElementTypeScene * m_typeScene
Editor(QWidget *parent=0)
ArenaElement * element() const
ArenaElement * contextElement(ArenaElement *element) const
QString m_currentArenaFile
QPair< QString, QPointF > ItemMountPoint
QPointF itemOffset() const
Returns the item's offset from the grid point with 0 <= x,y <= 1 ( (0,0) is bottom left) ...
void loadConfig(const QString &configFile)
int rotation() const
Returns the rotation in degrees.
bool parseRosPackageDirsFromCommandLineArguments()
void setRotation(int rotation)
Sets the rotation in degrees.
QPoint pos() const
Returns the position in arena coordinates.
void slotItemMountPointChanged(int index)
QString m_windowTitlePrefix
QString m_hector_arena_worlds_package_dir
void setArena(Arena *arena)
ArenaElementTypeRegistry * m_typeRegistry
void closeEvent(QCloseEvent *event)
void saveWorldSdf(const QString &filename)
void slotShowDocumentation()
ArenaController * m_controller
bool isMountableItem() const
Convenience method returning true iff. this is a mountable-item element.
QString humanReadableName() const
Returns the "Name" meta info field if it exists, otherwise name()
QString m_hector_arena_elements_package_dir
void save(const QString &filename)
Serializes this arena in XML.