Go to the documentation of this file.00001 #include <QDir>
00002 #include <QFileInfo>
00003 #include <QTextStream>
00004 #include <ros/console.h>
00005 #include "utilities/ros_package.h"
00006 #include "utilities/exception.h"
00007 #include "utilities/xml_settings.h"
00008
00009 namespace utilities
00010 {
00011 RosPackage::RosPackage(QObject* parent)
00012 : AbstractConfig(parent), export_(new Export(this))
00013 {
00014 reset();
00015 updateRp();
00016 connect(export_, SIGNAL(changed()), this, SIGNAL(changed()));
00017 }
00018
00019 RosPackage::~RosPackage() {}
00020
00021 QString RosPackage::getWorkspaceUrl() const { return workspace_url_; }
00022
00023 QString RosPackage::getName() const { return name_; }
00024
00025 QString RosPackage::getUrl() const { return url_; }
00026
00027 QString RosPackage::getVersion() const { return version_; }
00028
00029 QString RosPackage::getDescription() const { return description_; }
00030
00031 QString RosPackage::getAuthor() const { return author_; }
00032
00033 QString RosPackage::getAuthorEmail() const { return author_email_; }
00034
00035 QString RosPackage::getMaintainer() const { return maintainer_; }
00036
00037 QString RosPackage::getMaintainerEmail() const { return maintainer_email_; }
00038
00039 QString RosPackage::getLicense() const { return license_; }
00040
00041 QString RosPackage::getBuildtoolDepend() const { return buildtool_depend_; }
00042
00043 QStringList RosPackage::getBuildDepends() const { return build_depends_; }
00044
00045 QStringList RosPackage::getRunDepends() const { return run_depends_; }
00046
00047 Export* RosPackage::getExport() const { return export_; }
00048
00049 void RosPackage::setWorkspaceUrl(const QString& url)
00050 {
00051 if (url != workspace_url_)
00052 {
00053 workspace_url_ = url;
00054 emit workspaceUrlChanged(url);
00055 emit changed();
00056 setUrl();
00057 }
00058 }
00059
00060 void RosPackage::setName(const QString& name)
00061 {
00062 if (name != name_)
00063 {
00064 name_ = name;
00065 emit nameChanged(name);
00066 emit changed();
00067 setUrl();
00068 }
00069 }
00070
00071 void RosPackage::setUrl()
00072 {
00073 std::string url;
00074 rp_.find(name_.toStdString(), url);
00075 if (url.empty() && !workspace_url_.isEmpty() && !name_.isEmpty())
00076 {
00077 setUrl(workspace_url_ + "/src/" + name_);
00078 }
00079 else
00080 {
00081 setUrl(QString::fromStdString(url));
00082 }
00083 }
00084
00085 void RosPackage::setUrl(const QString& url)
00086 {
00087 if (url != url_)
00088 {
00089 url_ = url;
00090 emit urlChanged(url);
00091 emit changed();
00092 }
00093 }
00094
00095 void RosPackage::setVersion(const QString& version)
00096 {
00097 if (version != version_)
00098 {
00099 version_ = version;
00100 emit versionChanged(version);
00101 emit changed();
00102 }
00103 }
00104
00105 void RosPackage::setDescription(const QString& description)
00106 {
00107 if (description != description_)
00108 {
00109 description_ = description;
00110 emit descriptionChanged(description);
00111 emit changed();
00112 }
00113 }
00114
00115 void RosPackage::setAuthor(const QString& name)
00116 {
00117 if (name != author_)
00118 {
00119 author_ = name;
00120 emit authorChanged(name);
00121 emit changed();
00122 }
00123 }
00124
00125 void RosPackage::setAuthorEmail(const QString& email)
00126 {
00127 if (email != author_email_)
00128 {
00129 author_email_ = email;
00130 emit authorEmailChanged(email);
00131 emit changed();
00132 }
00133 }
00134
00135 void RosPackage::setMaintainer(const QString& name)
00136 {
00137 if (name != maintainer_)
00138 {
00139 maintainer_ = name;
00140 emit maintainerChanged(name);
00141 emit changed();
00142 }
00143 }
00144
00145 void RosPackage::setMaintainerEmail(const QString& email)
00146 {
00147 if (email != maintainer_email_)
00148 {
00149 maintainer_email_ = email;
00150 emit maintainerEmailChanged(email);
00151 emit changed();
00152 }
00153 }
00154
00155 void RosPackage::setLicense(const QString& license)
00156 {
00157 if (license != license_)
00158 {
00159 license_ = license;
00160 emit licenseChanged(license);
00161 emit changed();
00162 }
00163 }
00164
00165 void RosPackage::setBuildtoolDepend(const QString& depend)
00166 {
00167 if (depend != buildtool_depend_)
00168 {
00169 buildtool_depend_ = depend;
00170 emit buildtoolDependChanged(depend);
00171 emit changed();
00172 }
00173 }
00174
00175 void RosPackage::setBuildDepends(const QString& depends)
00176 {
00177 int count(depends.count());
00178 QStringRef depends_ref(&depends, depends[0] == '[' ? 1 : 0,
00179 count - (depends[count - 1] == ']' ? 2 : 0));
00180 setBuildDepends(depends_ref.toString().split(','));
00181 }
00182
00183 void RosPackage::setBuildDepends(const QStringList& depends)
00184 {
00185 if (depends != build_depends_)
00186 {
00187 build_depends_ = depends;
00188 emit buildDependsChanged(depends);
00189 emit changed();
00190 }
00191 }
00192
00193 void RosPackage::setRunDepends(const QString& depends)
00194 {
00195 int count(depends.count());
00196 QStringRef depends_ref(&depends, depends[0] == '[' ? 1 : 0,
00197 count - (depends[count - 1] == ']' ? 2 : 0));
00198 setBuildDepends(depends_ref.toString().split(','));
00199 }
00200
00201 void RosPackage::setRunDepends(const QStringList& depends)
00202 {
00203 if (depends != run_depends_)
00204 {
00205 run_depends_ = depends;
00206 emit runDependsChanged(depends);
00207 emit changed();
00208 }
00209 }
00210
00211 size_t RosPackage::countBuildDepends() const { return build_depends_.count(); }
00212
00213 size_t RosPackage::countRunDepends() const { return run_depends_.count(); }
00214
00215 QString RosPackage::getBuildDepend(size_t index) const
00216 {
00217 return build_depends_[index];
00218 }
00219
00220 QString RosPackage::getRunDepend(size_t index) const
00221 {
00222 return run_depends_[index];
00223 }
00224
00225 void RosPackage::addBuildDepend(const QString& depend)
00226 {
00227 std::string package_path;
00228 rp_.find(depend.toStdString(), package_path);
00229 if (!build_depends_.contains(depend) && !package_path.empty())
00230 ;
00231 {
00232 build_depends_.append(depend);
00233 emit buildDependAdded(depend);
00234 emit changed();
00235 }
00236 }
00237
00238 void RosPackage::addRunDepend(const QString& depend)
00239 {
00240 std::string package_path;
00241 rp_.find(depend.toStdString(), package_path);
00242 if (!run_depends_.contains(depend) && !package_path.empty())
00243 {
00244 run_depends_.append(depend);
00245 emit runDependAdded(depend);
00246 emit changed();
00247 }
00248 }
00249
00250 void RosPackage::removeBuildDepend(const QString& depend)
00251 {
00252 if (build_depends_.contains(depend))
00253 {
00254 build_depends_.removeAll(depend);
00255 emit buildDependRemoved(depend);
00256 emit changed();
00257 }
00258 }
00259
00260 void RosPackage::removeRunDepend(const QString& depend)
00261 {
00262 if (run_depends_.contains(depend))
00263 {
00264 run_depends_.removeAll(depend);
00265 emit runDependRemoved(depend);
00266 emit changed();
00267 }
00268 }
00269
00270 void RosPackage::clearBuildDepends()
00271 {
00272 if (!build_depends_.isEmpty())
00273 {
00274 build_depends_.clear();
00275 emit buildDependsCleared();
00276 emit changed();
00277 }
00278 }
00279
00280 void RosPackage::clearRunDepends()
00281 {
00282 if (!run_depends_.isEmpty())
00283 {
00284 run_depends_.clear();
00285 emit runDependsCleared();
00286 emit changed();
00287 }
00288 }
00289
00290 QString RosPackage::validate() const
00291 {
00292 if (name_.isEmpty())
00293 {
00294 return "The package name must not be empty.";
00295 }
00296 if (name_.contains(' '))
00297 {
00298 return "The package name must not contain space characters.";
00299 }
00300 if (version_.isEmpty())
00301 {
00302 return "The package version must be defined.";
00303 }
00304 if (description_.isEmpty())
00305 {
00306 return "The package description must be given.";
00307 }
00308 if (maintainer_.isEmpty())
00309 {
00310 return "The package maintainer must be given.";
00311 }
00312 if (maintainer_email_.isEmpty() || !maintainer_email_.contains('@'))
00313 {
00314 return "The e-mail of the package maintainer must be given.";
00315 }
00316 if (license_.isEmpty())
00317 {
00318 return "The package license must be defined.";
00319 }
00320 return "";
00321 }
00322
00323 bool RosPackage::isValidPackageName() const
00324 {
00325 return !name_.isEmpty() && !name_.contains(' ');
00326 }
00327
00328 bool RosPackage::createPackage()
00329 {
00330 QDir dir(url_);
00331 if (dir.exists())
00332 {
00333 ROS_WARN_STREAM("The given package [" << name_.toStdString()
00334 << "] already exists.");
00335 return false;
00336 }
00337 if (workspaceExists() || catkinInitWorkspace())
00338 {
00339 QDir package_dir(workspace_url_ + "/src");
00340 package_dir.mkdir(name_);
00341 if (createManifest() && createCMakeLists() && catkinMake())
00342 {
00343 updateRp();
00344 setUrl(workspace_url_ + "/src/" + name_);
00345 }
00346 }
00347 return url_ == workspace_url_ + "/src/" + name_;
00348 }
00349
00350 bool RosPackage::createManifest()
00351 {
00352 QString error_message(validate());
00353 if (!error_message.isEmpty())
00354 {
00355 ROS_ERROR("%s", error_message.toStdString().c_str());
00356 return false;
00357 }
00358 if (!workspaceExists())
00359 {
00360 ROS_ERROR_STREAM("The given url [" << workspace_url_.toStdString()
00361 << "] is not a ROS workspace.");
00362 return false;
00363 }
00364 QString package_url(workspace_url_ + "/src/" + name_);
00365 QDir package_dir(package_url);
00366 if (!package_dir.exists())
00367 {
00368 ROS_ERROR_STREAM("The given package location [" << package_url.toStdString()
00369 << "] does not exist.");
00370 return false;
00371 }
00372 QFileInfo file_info(getManifestUrl());
00373 if (file_info.exists())
00374 {
00375 ROS_ERROR_STREAM("The given package ["
00376 << name_.toStdString()
00377 << "] already has its package.xml file.");
00378 return false;
00379 }
00380 QSettings settings(package_url + "/package.xml",
00381 utilities::XmlSettings::format);
00382 if (settings.isWritable())
00383 {
00384 settings.clear();
00385 save(settings);
00386 settings.sync();
00387 if (settings.status() == QSettings::NoError)
00388 {
00389 ROS_INFO_STREAM("Created the " << name_.toStdString()
00390 << " manifest file.");
00391 return true;
00392 }
00393 }
00394 ROS_ERROR_STREAM("Unable to create the " << name_.toStdString()
00395 << " manifest file.");
00396 return false;
00397 }
00398
00399 bool RosPackage::createCMakeLists()
00400 {
00401 if (!isValidPackageName())
00402 {
00403 ROS_ERROR_STREAM("The given package name [" << name_.toStdString()
00404 << "] is not valid.");
00405 return false;
00406 }
00407 if (!workspaceExists())
00408 {
00409 ROS_ERROR_STREAM("The given url [" << workspace_url_.toStdString()
00410 << "] is not a ROS workspace.");
00411 return false;
00412 }
00413 QString package_url(workspace_url_ + "/src/" + name_);
00414 QDir package_dir(package_url);
00415 if (!package_dir.exists())
00416 {
00417 ROS_ERROR_STREAM("The given package location [" << package_url.toStdString()
00418 << "] does not exist.");
00419 return false;
00420 }
00421 QFile file(package_url + "/CMakeLists.txt");
00422 if (file.exists())
00423 {
00424 ROS_ERROR_STREAM("The given package ["
00425 << name_.toStdString()
00426 << "] already has its CMakeLists.txt file.");
00427 return false;
00428 }
00429 QString cmake_lists_text;
00430 cmake_lists_text += "cmake_minimum_required(VERSION 2.8.3)\n";
00431 cmake_lists_text += "project(" + name_ + ")\n";
00432 cmake_lists_text += "find_package(catkin REQUIRED)\n";
00433 cmake_lists_text += "catkin_package()";
00434 if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
00435 {
00436 ROS_ERROR_STREAM("Unable to open the " << package_url.toStdString()
00437 << "/CMakeLists.txt file.");
00438 return false;
00439 }
00440 file.write(cmake_lists_text.toStdString().c_str());
00441 file.close();
00442 ROS_INFO_STREAM("Created the " << name_.toStdString()
00443 << " CMakeLists.txt file.");
00444 return true;
00445 }
00446
00447 bool RosPackage::updateManifest()
00448 {
00449 ROS_FATAL("The RosPackage::updateManifest() has not been implemented yet.");
00450 return false;
00451 }
00452
00453 QString RosPackage::getManifestUrl() const
00454 {
00455 return !getUrl().isEmpty() ? getUrl() + "/package.xml" : "";
00456 }
00457
00458 QString RosPackage::getCMakeListsUrl() const
00459 {
00460 return !getUrl().isEmpty() ? getUrl() + "/CMakeLists.txt" : "";
00461 }
00462
00463 bool RosPackage::catkinMake() const
00464 {
00465 if (workspace_url_.isEmpty())
00466 {
00467 ROS_ERROR("The workspace url is not defined yet.");
00468 return false;
00469 }
00470 QDir workspace_dir(workspace_url_);
00471 if (!workspace_dir.exists())
00472 {
00473 ROS_ERROR_STREAM("The given workspace url [" << workspace_url_.toStdString()
00474 << "] does not exist.");
00475 return false;
00476 }
00477 QFileInfo file_info(workspace_url_ + "/src/CMakeLists.txt");
00478 if (!file_info.exists())
00479 {
00480 ROS_ERROR_STREAM("The given url [" << workspace_url_.toStdString()
00481 << "] is not a ROS workspace.");
00482 return false;
00483 }
00484 ROS_INFO_STREAM("Running the catkin_make command at the given workspace url ["
00485 << workspace_url_.toStdString() << "]");
00486 QString cmd("cd " + workspace_url_ + " && catkin_make");
00487 system(cmd.toStdString().c_str());
00488 return true;
00489 }
00490
00491 bool RosPackage::workspaceExists() const
00492 {
00493 if (workspace_url_.isEmpty())
00494 {
00495 return false;
00496 }
00497 QFileInfo file_info(workspace_url_ + "/src/CMakeLists.txt");
00498 return file_info.exists();
00499 }
00500
00501 bool RosPackage::catkinInitWorkspace() const
00502 {
00503 if (workspaceExists())
00504 {
00505 ROS_ERROR_STREAM("The given url [" << workspace_url_.toStdString()
00506 << "] is already a ROS workspace.");
00507 return false;
00508 }
00509 QDir workspace_dir(workspace_url_);
00510 if (!workspace_dir.exists())
00511 {
00512 ROS_ERROR_STREAM("The given url ["
00513 << workspace_url_.toStdString()
00514 << "] ror the ROS workspace does not exist.");
00515 return false;
00516 }
00517 QString workspace_src_url(workspace_url_ + "/src");
00518 QDir workspace_src_dir(workspace_src_url);
00519 if (!workspace_src_dir.exists())
00520 {
00521 workspace_dir.mkdir("src");
00522 if (!workspace_src_dir.exists())
00523 {
00524 ROS_ERROR_STREAM(
00525 "Unable to make directory: " << workspace_src_url.toStdString());
00526 return false;
00527 }
00528 ROS_INFO_STREAM("Made directory: " << workspace_src_url.toStdString());
00529 }
00530 QString cmd("cd " + workspace_src_url + " && catkin_init_workspace");
00531 system(cmd.toStdString().c_str());
00532 if (!workspaceExists())
00533 {
00534 ROS_ERROR_STREAM(
00535 "Unable to create ROS workspace at: " << workspace_url_.toStdString());
00536 return false;
00537 }
00538 ROS_INFO_STREAM(
00539 "Created ROS workspace at: " << workspace_src_url.toStdString());
00540 catkinMake();
00541 QString bashrc_url(QDir::homePath() + "/.bashrc");
00542 QFileInfo bashrc_file_info(bashrc_url);
00543 if (!bashrc_file_info.exists())
00544 {
00545 ROS_ERROR_STREAM("Unable to configure ROS workspace at the ~/bashrc file.");
00546 return false;
00547 }
00548 QFile bashrc_file(bashrc_url);
00549 if (!bashrc_file.open(QIODevice::ReadWrite | QIODevice::Append))
00550 {
00551 ROS_ERROR_STREAM("Unable to open the ~/bashrc file.");
00552 return false;
00553 }
00554 cmd = "\nsource " + workspace_url_ + "/devel/setup.bash";
00555 QTextStream stream(&bashrc_file);
00556 QString line(stream.readLine());
00557 while (!line.isNull())
00558 ;
00559 {
00560 if (line.contains(cmd))
00561 {
00562 bashrc_file.close();
00563 return true;
00564 }
00565 line = stream.readLine();
00566 }
00567 ROS_INFO_STREAM("Appending the 'source "
00568 << workspace_url_.toStdString()
00569 << "/devel/setup.bash' command to ~/.bashrc ");
00570 bashrc_file.write(cmd.toStdString().c_str());
00571 bashrc_file.close();
00572 return true;
00573 }
00574
00575 void RosPackage::save() const
00576 {
00577 QString url(getManifestUrl());
00578 if (url.isEmpty())
00579 {
00580 throw Exception(
00581 "The package url must be setted before saving its manifest file.");
00582 }
00583 QSettings settings(url, utilities::XmlSettings::format);
00584 if (!settings.isWritable())
00585 {
00586 throw Exception("The package manifest url must be writable.");
00587 }
00588 settings.clear();
00589 save(settings);
00590 settings.sync();
00591 if (settings.status() == QSettings::NoError)
00592 {
00593 ROS_INFO_STREAM("Saved application configuration file ["
00594 << url.toStdString() << "].");
00595 }
00596 }
00597
00598 void RosPackage::save(QSettings& settings) const
00599 {
00600 QString validation(validate());
00601 if (!validation.isEmpty())
00602 {
00603 throw Exception("All mandatory parameters of the package manifest must be "
00604 "given before saving it: " +
00605 validation.toStdString());
00606 }
00607 settings.beginGroup("package");
00608 settings.setValue("name", name_);
00609 settings.setValue("version", version_);
00610 settings.setValue("description", description_);
00611 settings.setValue("author", author_);
00612 settings.setValue("author/@email", author_email_);
00613 settings.setValue("maintainer", maintainer_);
00614 settings.setValue("maintainer/@email", maintainer_email_);
00615 settings.setValue("license", license_);
00616 settings.setValue("buildtool_depend", buildtool_depend_);
00617 if (!build_depends_.isEmpty())
00618 {
00619 QString depends(build_depends_[0]);
00620 for (size_t i(1); i < build_depends_.count(); i++)
00621 {
00622 depends += "," + build_depends_[i];
00623 }
00624 settings.setValue("build_depend", "[" + depends + "]");
00625 }
00626 if (!run_depends_.isEmpty())
00627 {
00628 QString depends(run_depends_[0]);
00629 for (size_t i(1); i < run_depends_.count(); i++)
00630 {
00631 depends += "," + run_depends_[i];
00632 }
00633 settings.setValue("run_depend", "[" + depends + "]");
00634 }
00635 export_->save(settings);
00636 settings.endGroup();
00637 }
00638
00639 void RosPackage::load(const QString& url)
00640 {
00641 QFileInfo file_info(url);
00642 ROS_ERROR_STREAM("[RosPackage::load] url: " << url.toStdString());
00643 if (!file_info.isReadable())
00644 {
00645 throw Exception("The given package manifest url must be readeable.");
00646 }
00647 QSettings settings(url, utilities::XmlSettings::format);
00648 if (settings.status() == QSettings::NoError)
00649 {
00650 load(settings);
00651 ROS_INFO_STREAM("Loaded application configuration file ["
00652 << url.toStdString() << "].");
00653 }
00654 }
00655
00656 void RosPackage::load(QSettings& settings)
00657 {
00658 if (settings.value("package@format").toString() == "2")
00659 {
00660 throw Exception("The given manifest format (2) is not treated yet.");
00661 }
00662 settings.beginGroup("package");
00663 setName(settings.value("name").toString());
00664 std::string url;
00665 rp_.find(name_.toStdString(), url);
00666 workspace_url_ = QString::fromStdString(url);
00667 setWorkspaceUrl(workspace_url_.left(workspace_url_.lastIndexOf("/src/")));
00668 setVersion(settings.value("version").toString());
00669 setDescription(settings.value("description").toString());
00670 setAuthor(settings.value("author").toString());
00671 setAuthorEmail(settings.value("author/@email").toString());
00672 setMaintainer(settings.value("maintainer").toString());
00673 setMaintainerEmail(settings.value("maintainer/@email").toString());
00674 setLicense(settings.value("license").toString());
00675 setBuildtoolDepend(settings.value("buildtool_depend").toString());
00676 setBuildDepends(settings.value("build_depend").toString());
00677 setRunDepends(settings.value("run_depend").toString());
00678 export_->load(settings);
00679 settings.endGroup();
00680 }
00681
00682 void RosPackage::updateRp()
00683 {
00684 rp_ = rospack::Rospack();
00685 rp_.setQuiet(true);
00686 std::vector<std::string> search_path;
00687 rp_.getSearchPathFromEnv(search_path);
00688 rp_.crawl(search_path, true);
00689 }
00690
00691 void RosPackage::reset()
00692 {
00693 setWorkspaceUrl("");
00694 setName("");
00695 setVersion("1.0.0");
00696 setDescription("");
00697 setAuthor("Adriano Henrique Rossette Leite");
00698 setAuthorEmail("adrianohrl@gmail.com");
00699 setMaintainer("");
00700 setMaintainerEmail("");
00701 setLicense("BSD");
00702 setBuildtoolDepend("catkin");
00703 clearBuildDepends();
00704 clearRunDepends();
00705 export_->reset();
00706 }
00707
00708 void RosPackage::write(QDataStream& stream) const
00709 {
00710 stream << workspace_url_;
00711 stream << name_;
00712 stream << version_;
00713 stream << description_;
00714 stream << author_;
00715 stream << author_email_;
00716 stream << maintainer_;
00717 stream << maintainer_email_;
00718 stream << license_;
00719 stream << buildtool_depend_;
00720 stream << build_depends_.count();
00721 for (size_t i(0); i < build_depends_.count(); i++)
00722 {
00723 stream << build_depends_[i];
00724 }
00725 stream << run_depends_.count();
00726 for (size_t i(0); i < run_depends_.count(); i++)
00727 {
00728 stream << run_depends_[i];
00729 }
00730 export_->write(stream);
00731 }
00732
00733 void RosPackage::read(QDataStream& stream)
00734 {
00735 QString workspace_url;
00736 QString name;
00737 QString version;
00738 QString description;
00739 QString author;
00740 QString author_email;
00741 QString maintainer;
00742 QString maintainer_email;
00743 QString license;
00744 QString buildtool_depend;
00745 quint64 count;
00746 QString depend;
00747 QStringList build_depends;
00748 QStringList run_depends;
00749 stream >> workspace_url;
00750 setWorkspaceUrl(workspace_url);
00751 stream >> name;
00752 setName(name);
00753 stream >> version;
00754 setVersion(version);
00755 stream >> description;
00756 setDescription(description);
00757 stream >> author;
00758 setAuthor(author);
00759 stream >> author_email;
00760 setAuthorEmail(author_email);
00761 stream >> maintainer;
00762 setMaintainer(maintainer);
00763 stream >> maintainer_email;
00764 setMaintainerEmail(maintainer_email);
00765 stream >> license;
00766 setLicense(license);
00767 stream >> buildtool_depend;
00768 setBuildtoolDepend(buildtool_depend);
00769 stream >> count;
00770 for (size_t i(0); i < count; i++)
00771 {
00772 stream >> depend;
00773 build_depends.append(depend);
00774 }
00775 setBuildDepends(build_depends);
00776 stream >> count;
00777 for (size_t i(0); i < count; i++)
00778 {
00779 stream >> depend;
00780 run_depends.append(depend);
00781 }
00782 setBuildDepends(run_depends);
00783 export_->read(stream);
00784 }
00785
00786 RosPackage& RosPackage::operator=(const RosPackage& config)
00787 {
00788 setWorkspaceUrl(config.workspace_url_);
00789 setName(config.name_);
00790 setVersion(config.version_);
00791 setDescription(config.description_);
00792 setAuthor(config.author_);
00793 setAuthorEmail(config.author_email_);
00794 setMaintainer(config.maintainer_);
00795 setMaintainerEmail(config.maintainer_email_);
00796 setLicense(config.license_);
00797 setBuildtoolDepend(config.buildtool_depend_);
00798 setBuildDepends(config.build_depends_);
00799 setRunDepends(config.run_depends_);
00800 *export_ = *config.export_;
00801 return *this;
00802 }
00803
00804 RosMetapackage::RosMetapackage(QObject* parent) : RosPackage(parent) {}
00805
00806 RosMetapackage::~RosMetapackage() {}
00807
00808 void RosMetapackage::reset()
00809 {
00810 RosPackage::reset();
00811 export_->add("metapackage", "");
00812 }
00813
00814 bool RosMetapackage::createCMakeLists()
00815 {
00816 if (!isValidPackageName())
00817 {
00818 ROS_ERROR_STREAM("The given package name [" << name_.toStdString()
00819 << "] is not valid.");
00820 return false;
00821 }
00822 if (!workspaceExists())
00823 {
00824 ROS_ERROR_STREAM("The given url [" << workspace_url_.toStdString()
00825 << "] is not a ROS workspace.");
00826 return false;
00827 }
00828 QString package_url(workspace_url_ + "/src/" + name_);
00829 QDir package_dir(package_url);
00830 if (!package_dir.exists())
00831 {
00832 ROS_ERROR_STREAM("The given package location [" << package_url.toStdString()
00833 << "] does not exist.");
00834 return false;
00835 }
00836 QFile file(package_url + "/CMakeLists.txt");
00837 if (file.exists())
00838 {
00839 ROS_ERROR_STREAM("The given package ["
00840 << name_.toStdString()
00841 << "] already has its CMakeLists.txt file.");
00842 return false;
00843 }
00844 QString cmake_lists_text;
00845 cmake_lists_text += "cmake_minimum_required(VERSION 2.8.3)\n";
00846 cmake_lists_text += "project(" + name_ + ")\n";
00847 cmake_lists_text += "find_package(catkin REQUIRED)\n";
00848 cmake_lists_text += "catkin_metapackage()";
00849 if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
00850 {
00851 ROS_ERROR_STREAM("Unable to open the " << package_url.toStdString()
00852 << "/CMakeLists.txt file.");
00853 return false;
00854 }
00855 file.write(cmake_lists_text.toStdString().c_str());
00856 file.close();
00857 ROS_INFO_STREAM("Created the " << name_.toStdString()
00858 << " CMakeLists.txt file.");
00859 return true;
00860 }
00861
00862 Export::Export(RosPackage* parent) : AbstractConfig(parent) {}
00863
00864 Export::~Export() {}
00865
00866 QString Export::getName(size_t index) const { return all_names_[index]; }
00867
00868 QString Export::getValue(const QString& name) const
00869 {
00870 return all_values_[all_names_.indexOf(name)];
00871 }
00872
00873 QStringList Export::getAllNames() const { return all_names_; }
00874
00875 QStringList Export::getAllValues() const { return all_values_; }
00876
00877 void Export::setAll(const QStringList& all_names, const QStringList& all_values)
00878 {
00879 if (all_names != all_names_ && all_values != all_values_)
00880 {
00881 all_names_ = all_names;
00882 all_values_ = all_values;
00883 emit allChanged(all_names, all_values);
00884 emit changed();
00885 }
00886 }
00887
00888 size_t Export::count() const { return all_names_.count(); }
00889
00890 void Export::add(const QString& name, const QString& value)
00891 {
00892 int index(all_names_.indexOf(name));
00893 if (index == -1)
00894 {
00895 all_names_.append(name);
00896 all_values_.append(value);
00897 emit added(name, value);
00898 emit changed();
00899 }
00900 }
00901
00902 void Export::remove(const QString& name)
00903 {
00904 int index(all_names_.indexOf(name));
00905 if (index != -1)
00906 {
00907 all_names_.removeAt(index);
00908 QString value(all_values_[index]);
00909 all_values_.removeAt(index);
00910 emit removed(name, value);
00911 emit changed();
00912 }
00913 }
00914
00915 void Export::clear()
00916 {
00917 all_names_.clear();
00918 all_values_.clear();
00919 }
00920
00921 void Export::save(QSettings& settings) const
00922 {
00923 settings.beginGroup("export");
00924 for (size_t i(0); i < count(); i++)
00925 {
00926 settings.setValue(all_names_[i], all_values_[i]);
00927 }
00928 settings.endGroup();
00929 }
00930
00931 void Export::load(QSettings& settings)
00932 {
00933 settings.beginGroup("export");
00934 QStringList all_names(settings.allKeys());
00935 QStringList all_values;
00936 for (size_t i(0); i < all_names.count(); i++)
00937 {
00938 all_values.append(settings.value(all_names[i]).toString());
00939 }
00940 setAll(all_names, all_values);
00941 settings.endGroup();
00942 }
00943
00944 void Export::reset()
00945 {
00946 all_names_.clear();
00947 all_values_.clear();
00948 }
00949
00950 void Export::write(QDataStream& stream) const
00951 {
00952 stream << (quint64)count();
00953 for (size_t i(0); i < count(); i++)
00954 {
00955 stream << all_names_[i];
00956 stream << all_values_[i];
00957 }
00958 }
00959
00960 void Export::read(QDataStream& stream)
00961 {
00962 quint64 count;
00963 QString name;
00964 QString value;
00965 stream >> count;
00966 QStringList all_names;
00967 QStringList all_values;
00968 for (size_t i(0); i < count; i++)
00969 {
00970 stream >> name;
00971 stream >> value;
00972 all_names.append(name);
00973 all_values.append(value);
00974 }
00975 setAll(all_names, all_values);
00976 }
00977
00978 Export& Export::operator=(const Export& config)
00979 {
00980 setAll(config.all_names_, config.all_values_);
00981 return *this;
00982 }
00983 }