32 setWhatsThis(
"Module Wizard enables management of all RTXI modules. You can download and install new modules directly from the GitHub site..etc");
35 subWindow =
new QMdiSubWindow;
36 subWindow->setWindowIcon(QIcon(
"/usr/local/share/rtxi/RTXI-widget-icon.png"));
37 subWindow->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint |
38 Qt::WindowMinimizeButtonHint);
39 subWindow->setAttribute(Qt::WA_DeleteOnClose);
42 QGridLayout *customLayout =
new QGridLayout;
44 QGroupBox *buttonBox =
new QGroupBox;
45 QHBoxLayout *buttonLayout =
new QHBoxLayout();
46 buttonBox->setLayout(buttonLayout);
47 syncButton =
new QPushButton(
"Sync",
this);
48 cloneButton =
new QPushButton(
"Install",
this);
49 cloneButton->setEnabled(
false);
50 buttonLayout->addWidget(syncButton);
51 buttonLayout->addWidget(cloneButton);
53 QGroupBox *installedBox =
new QGroupBox(
"Installed");
54 QVBoxLayout *installedLayout =
new QVBoxLayout;
55 installedBox->setLayout(installedLayout);
56 installedListWidget =
new QListWidget(installedBox);
57 installedListWidget->setFixedWidth(175);
58 installedListWidget->setSortingEnabled(
true);
59 installedLayout->addWidget(installedListWidget);
61 QGroupBox *moduleBox =
new QGroupBox(
"Available");
62 QVBoxLayout *moduleLayout =
new QVBoxLayout;
63 moduleBox->setLayout(moduleLayout);
64 availableListWidget =
new QListWidget(
this);
65 availableListWidget->setFixedWidth(175);
66 availableListWidget->setSortingEnabled(
true);
67 moduleLayout->addWidget(availableListWidget);
69 readmeWindow =
new QTextEdit;
70 readmeWindow->setReadOnly(
true);
73 customLayout->addWidget(buttonBox, 0, 0);
74 customLayout->addWidget(moduleBox, 1, 0);
75 customLayout->addWidget(installedBox, 2, 0);
76 customLayout->addWidget(readmeWindow, 0, 1, 3, 1);
77 customLayout->setColumnStretch(0, 0);
78 customLayout->setColumnStretch(1, 1);
80 QObject::connect(syncButton, SIGNAL(clicked()),
this, SLOT(getRepos()));
81 QObject::connect(cloneButton, SIGNAL(clicked()),
this, SLOT(cloneModule()));
82 QObject::connect(availableListWidget, SIGNAL(itemClicked(QListWidgetItem*)),
this, SLOT(getReadme(
void)));
83 QObject::connect(availableListWidget, SIGNAL(itemClicked(QListWidgetItem*)),
this, SLOT(updateButton(
void)));
84 QObject::connect(installedListWidget, SIGNAL(itemClicked(QListWidgetItem*)),
this, SLOT(getReadme(
void)));
85 QObject::connect(installedListWidget, SIGNAL(itemClicked(QListWidgetItem*)),
this, SLOT(updateButton(
void)));
87 setLayout(customLayout);
88 setWindowTitle(
"Module Wizard");
89 subWindow->setWidget(
this);
90 subWindow->resize(700, subWindow->sizeHint().height());
102 void RTXIWizard::Panel::initParameters(
void)
108 exclude_list = std::vector<QString> ({
110 QString(
"rtxi.github.io"),
111 QString(
"genicam-camera"),
112 QString(
"rtxi-crawler"),
113 QString(
"matlab-tools"),
114 QString(
"tutorials"),
116 QString(
"camera-control"),
118 QString(
"dynamo-examples"),
120 QString(
"python-plugin"),
122 QString(
"user-manual"),
124 QString(
"live-image"),
125 QString(
"conference-2015")
127 button_mode = DOWNLOAD;
133 void RTXIWizard::Panel::updateButton(
void)
135 QListWidget *parent = qobject_cast<QListWidget*>(sender());
137 if ( parent == availableListWidget )
139 cloneButton->setText(
"Install");
140 button_mode = DOWNLOAD;
142 else if ( parent == installedListWidget )
144 cloneButton->setText(
"Update");
145 button_mode = UPDATE;
151 void RTXIWizard::Panel::cloneModule(
void)
153 cloneButton->setEnabled(
false);
154 availableListWidget->setDisabled(
true);
155 installedListWidget->setDisabled(
true);
158 QProgressDialog *progress =
new QProgressDialog(
"Installing plugin",
"Cancel", 0, 4,
this);
159 progress->setWindowModality(Qt::WindowModal);
161 progress->setLabelText(
"Configuring...");
162 QApplication::processEvents();
168 name = availableListWidget->currentItem()->text();
172 name = installedListWidget->currentItem()->text();
176 std::cout<<
"ERROR: default in switch block in cloneModule()"<<std::endl;
186 QByteArray temp = modules[name].clone_url.toString().toLatin1();
187 const char *url = temp.data();
188 QByteArray temp2 = modules[name].location.toString().toLatin1();
189 const char *path = temp2.data();
193 progress->setLabelText(
"Downloading extension...");
194 progress->setValue(1);
195 QApplication::processEvents();
197 if ( (QDir(modules[name].location.toString())).exists() )
199 git_repository *repo = NULL;
200 git_remote *remote = NULL;
202 git_repository_open(&repo, path);
203 printGitError(git_remote_lookup(&remote, repo,
"origin"));
205 printGitError(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL));
207 printGitError(git_remote_download(remote, NULL, NULL));
209 git_remote_disconnect(remote);
210 git_remote_free(remote);
211 git_repository_free(repo);
215 git_repository *repo = NULL;
216 printGitError(git_clone(&repo, url, path, NULL));
217 git_repository_free(repo);
222 std::cout<<
"git ERROR"<<std::endl;
226 progress->setLabelText(
"Building...");
227 progress->setValue(2);
228 QApplication::processEvents();
232 QString make_cmd =
"/usr/bin/make -j2 -C " + modules[name].location.toString();
233 QString make_install_cmd;
237 if (getuid()) make_install_cmd =
"gksudo \"/usr/bin/make install -C" + modules[name].location.toString() +
"\"";
238 else make_install_cmd =
"/usr/bin/make install -C" + modules[name].location.toString();
241 QProcess *make =
new QProcess();
242 QProcess *make_install =
new QProcess();
243 make->start(make_cmd);
245 if (!make->waitForFinished())
247 QMessageBox *errmessage;
248 errmessage->critical(0,
"Error",
"Could not compile plugin. Email help@rtxi.org for assistance");
249 std::cout<<
"make -C "<<path<<
" failed"<<std::endl;
253 progress->setLabelText(
"Installing binaries...");
254 progress->setValue(3);
255 QApplication::processEvents();
256 make_install->start(make_install_cmd);
257 if (!make_install->waitForFinished())
259 std::cout<<
"make install -C"<<path<<
" failed..."<<std::endl;
260 std::cout<<
"...despite make -C succeeding."<<std::endl;
263 modules[name].installed =
true;
268 progress->setValue(4);
269 QApplication::processEvents();
271 make_install->close();
276 cloneButton->setEnabled(
true);
277 rebuildListWidgets();
278 availableListWidget->setDisabled(
false);
279 installedListWidget->setDisabled(
false);
283 void RTXIWizard::Panel::getRepos()
285 availableListWidget->setDisabled(
true);
286 installedListWidget->setDisabled(
true);
288 if (!availableListWidget->count())
290 QUrl url(
"https://api.github.com/orgs/rtxi/repos?per_page=100");
291 reply = qnam.get(QNetworkRequest(url));
292 QObject::connect(reply, SIGNAL(finished()),
this, SLOT(parseRepos(
void)));
299 availableListWidget->setDisabled(
false);
300 installedListWidget->setDisabled(
false);
312 void RTXIWizard::Panel::getReadme(
void)
314 availableListWidget->setDisabled(
true);
315 installedListWidget->setDisabled(
true);
316 QListWidget *parent = qobject_cast<QListWidget*>(sender());
317 QString name = parent->currentItem()->text();
320 if (modules[parent->currentItem()->text()].readme ==
"")
322 reply = qnam.get(QNetworkRequest(modules[name].readme_url));
323 QObject::connect(reply, SIGNAL(finished()),
this, SLOT(parseReadme()));
329 readmeWindow->setHtml(modules[parent->currentItem()->text()].readme);
330 cloneButton->setEnabled(
true);
331 availableListWidget->setDisabled(
false);
332 installedListWidget->setDisabled(
false);
338 void RTXIWizard::Panel::parseReadme(
void)
340 const char* raw_data = (reply->readAll()).constData();
341 MMIOT *m = mkd_string(raw_data, strlen(raw_data), 0);
345 int len = mkd_document(m, &text);
346 std::string html(text, text+len);
349 QString fileText = QString::fromStdString(html);
357 modules[availableListWidget->currentItem()->text()].readme = fileText;
361 modules[installedListWidget->currentItem()->text()].readme = fileText;
365 std::cout<<
"ERROR: default in swtich block in cloneModule()"<<std::endl;
369 readmeWindow->setHtml(fileText);
370 readmeWindow->show();
373 cloneButton->setEnabled(
true);
374 availableListWidget->setDisabled(
false);
375 installedListWidget->setDisabled(
false);
379 void RTXIWizard::Panel::parseRepos(
void)
381 QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll().data());
382 QJsonArray jsonArr = jsonDoc.array();
384 QString readmeUrlPrefix =
"https://raw.githubusercontent.com/RTXI/";
385 QString readmeUrlSuffix =
"/master/README.md";
388 QString locationPrefix;
391 locationPrefix = QString(getenv(
"HOME")) +
"/.config/RTXI/";
395 locationPrefix =
"/usr/local/lib/rtxi_modules/";
398 for (
int idx = 0; idx < jsonArr.size(); idx++)
400 QJsonObject newObj = (jsonArr.at(idx)).toObject();
401 newObj.find(
"name").key();
404 if (std::find(exclude_list.begin(), exclude_list.end(), newObj.value(
"name").toString()) == exclude_list.end())
408 QString name = newObj.value(
"name").toString();
409 module.readme_url = QUrl(readmeUrlPrefix + newObj.value(
"name").toString() + readmeUrlSuffix);
410 module.clone_url = QUrl(newObj.value(
"clone_url").toString());
411 module.location = QString(locationPrefix + name);
414 if ( (QDir(module.location.toString())).exists() )
416 module.installed =
true;
420 module.installed =
false;
422 modules[name] = module;
427 reply->deleteLater();
430 rebuildListWidgets();
431 availableListWidget->setDisabled(
false);
432 installedListWidget->setDisabled(
false);
437 availableListWidget->clear();
438 installedListWidget->clear();
440 for (std::map<QString,module_t>::iterator i = modules.begin(); i != modules.end(); ++i) {
441 if (i->second.installed) installedListWidget->addItem(i->first);
442 else availableListWidget->addItem(i->first);
445 installedListWidget->sortItems(Qt::AscendingOrder);
446 availableListWidget->sortItems(Qt::AscendingOrder);
456 QProcess *make =
new QProcess();
457 QProcess *make_install =
new QProcess();
460 QProgressDialog *progress =
new QProgressDialog(
"Installing plugin",
"Cancel", 0, 5,
this);
461 progress->setWindowModality(Qt::WindowModal);
462 progress->setLabelText(
"Configuring...");
463 std::string cloneUrl =
"https://github.com/rtxi/" + module_name;
465 std::string locationUrl;
468 locationUrl = std::string(getenv(
"HOME")) +
"/.config/RTXI/" + module_name;
472 locationUrl =
"/usr/local/lib/rtxi_modules/" + module_name;
475 const char *url = cloneUrl.c_str();
476 const char *path = locationUrl.c_str();
478 progress->setLabelText(
"Downloading Plugin...");
479 progress->setValue(1);
481 if ( (QDir(QString::fromStdString(locationUrl))).exists() )
483 git_repository *repo = NULL;
484 git_remote *remote = NULL;
486 git_repository_open(&repo, path);
487 printGitError(git_remote_lookup(&remote, repo,
"origin"));
489 printGitError(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL));
491 printGitError(git_remote_download(remote, NULL, NULL));
493 git_remote_disconnect(remote);
494 git_remote_free(remote);
495 git_repository_free(repo);
500 git_repository *repo = NULL;
501 printGitError(git_clone(&repo, url, path, NULL));
502 git_repository_free(repo);
507 std::cout<<
"git ERROR"<<std::endl;
511 QString make_cmd =
"/usr/bin/make -j2 -C " + QString::fromStdString(locationUrl);
512 QString make_install_cmd;
513 if (getuid()) make_install_cmd =
"gksudo \"/usr/bin/make install -C" + QString::fromStdString(locationUrl) +
"\"";
514 else make_install_cmd =
"/usr/bin/make install -C" + QString::fromStdString(locationUrl);
516 progress->setLabelText(
"Building...");
517 progress->setValue(2);
518 make->start(make_cmd);
520 progress->setLabelText(
"Installing extension...");
521 progress->setValue(3);
522 if (!make->waitForFinished())
524 std::cout<<
"make -C "<<path<<
" failed"<<std::endl;
528 make_install->start(make_install_cmd);
529 if (!make_install->waitForFinished())
531 std::cout<<
"make install -C"<<path<<
" failed..."<<std::endl;
532 std::cout<<
"...despite make -C succeeding."<<std::endl;
537 make_install->close();
538 progress->setValue(5);
541 int RTXIWizard::Panel::printGitError(
int error) {
543 const git_error *e = giterr_last();
544 printf(
"Error %d/%d: %s\n", error, e->klass, e->message);
554 RTXIWizard::Plugin::Plugin(
void) : panel(0)
559 RTXIWizard::Plugin::~Plugin(
void)