ctkPluginGenerator.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /*=============================================================================
  2. Library: CTK
  3. Copyright (c) German Cancer Research Center,
  4. Division of Medical and Biological Informatics
  5. Licensed under the Apache License, Version 2.0 (the "License");
  6. you may not use this file except in compliance with the License.
  7. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. =============================================================================*/
  15. #include "ctkPluginGenerator_p.h"
  16. #include "ui_ctkPluginGeneratorMainWindow.h"
  17. #include <ctkPluginFramework.h>
  18. #include <ctkPluginContext.h>
  19. #include <ctkServiceReference.h>
  20. #include <ctkPluginConstants.h>
  21. #include <ctkPluginGeneratorCodeModel.h>
  22. #include <ctkPluginGeneratorConstants.h>
  23. #include <ctkPluginGeneratorOptionsDialog_p.h>
  24. #include <ctkUtils.h>
  25. #include <QDebug>
  26. #include <QListWidgetItem>
  27. #include <QDir>
  28. #include <QFileSystemModel>
  29. #include <QTime>
  30. #include <QMessageBox>
  31. #include <QSettings>
  32. #include <stdexcept>
  33. class ctkTemporaryDir
  34. {
  35. public:
  36. static QString create(const QString& path = QString())
  37. {
  38. QString tmpPath = path;
  39. if (tmpPath.isEmpty())
  40. {
  41. tmpPath = "ctkplugingenerator";
  42. }
  43. tmpPath += "." + QTime::currentTime().toString("hhmmsszzz");
  44. QDir tmp = QDir::temp();
  45. if (!tmp.mkdir(tmpPath))
  46. {
  47. QString msg = QString("Creating temporary directory ") + tmpPath + " in "
  48. + QDir::temp().canonicalPath() + " failed.";
  49. throw std::runtime_error(msg.toStdString());
  50. }
  51. tmp.cd(tmpPath);
  52. return tmp.canonicalPath();
  53. }
  54. };
  55. ctkPluginGenerator::ctkPluginGenerator(ctkPluginFramework* framework, QWidget *parent) :
  56. QMainWindow(parent),
  57. framework(framework), ui(new Ui::ctkPluginGeneratorMainWindow),
  58. mode(EDIT), previewModel(0)
  59. {
  60. ui->setupUi(this);
  61. previewModel = new QFileSystemModel(this);
  62. ui->previewTreeView->setModel(previewModel);
  63. ui->previewTreeView->hideColumn(1);
  64. ui->previewTreeView->hideColumn(2);
  65. ui->previewTreeView->hideColumn(3);
  66. this->setStatusBar(0);
  67. connect(ui->actionOptions, SIGNAL(triggered(bool)), this, SLOT(menuOptionsTriggered()));
  68. connect(ui->generateButton, SIGNAL(clicked()), this, SLOT(generateClicked()));
  69. connect(ui->previewButton, SIGNAL(clicked()), this, SLOT(previewClicked()));
  70. connect(ui->cancelButton, SIGNAL(clicked()), qApp, SLOT(quit()));
  71. connect(ui->uiExtensionList, SIGNAL(itemClicked(QListWidgetItem*)),
  72. this, SLOT(extensionItemClicked(QListWidgetItem*)));
  73. connect(ui->previewTreeView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), this, SLOT(previewIndexChanged(QModelIndex)));
  74. QList<ctkServiceReference> serviceRefs = framework->getPluginContext()->
  75. getServiceReferences("ctkPluginGeneratorAbstractUiExtension");
  76. QListIterator<ctkServiceReference> it(serviceRefs);
  77. while (it.hasNext())
  78. {
  79. ctkServiceReference serviceRef = it.next();
  80. ctkPluginGeneratorAbstractUiExtension* extension =
  81. qobject_cast<ctkPluginGeneratorAbstractUiExtension*>(framework->getPluginContext()->getService(serviceRef));
  82. qDebug() << "Service reference found";
  83. if (extension)
  84. {
  85. qDebug() << "inserted";
  86. int ranking = serviceRef.getProperty(ctkPluginConstants::SERVICE_RANKING).toInt();
  87. if (ranking > 0)
  88. {
  89. uiExtensionMap.insert(ranking, extension);
  90. }
  91. else
  92. {
  93. uiExtensionMap.insert(-1, extension);
  94. }
  95. }
  96. }
  97. int id = 0;
  98. foreach (ctkPluginGeneratorAbstractUiExtension* extension, uiExtensionMap)
  99. {
  100. idToExtensionMap.insert(id, extension);
  101. ui->extensionStack->addWidget(extension->getWidget());
  102. connect(extension, SIGNAL(errorMessageChanged(QString)), this, SLOT(errorMessageChanged(QString)));
  103. extension->validate();
  104. (new QListWidgetItem(extension->getTitle(), ui->uiExtensionList))->setData(Qt::UserRole, id);
  105. ++id;
  106. }
  107. ui->uiExtensionList->setCurrentRow(0);
  108. extensionClicked(idToExtensionMap[0]);
  109. }
  110. ctkPluginGenerator::~ctkPluginGenerator()
  111. {
  112. delete ui;
  113. if (!previewDir.isEmpty())
  114. {
  115. ctk::removeDirRecursively(previewDir);
  116. }
  117. }
  118. void ctkPluginGenerator::menuOptionsTriggered()
  119. {
  120. ctkPluginGeneratorOptionsDialog optionsDialog;
  121. int result = optionsDialog.exec();
  122. if (result == QDialog::Accepted && mode == PREVIEW)
  123. {
  124. QString selPath;
  125. QString oldPreviewDir = previewDir;
  126. if (!ui->previewTreeView->selectionModel()->selection().isEmpty())
  127. {
  128. QModelIndex index = ui->previewTreeView->selectionModel()->selectedIndexes().front();
  129. selPath = previewModel->data(index, QFileSystemModel::FilePathRole).toString();
  130. }
  131. if (createPreview())
  132. {
  133. ui->modeStack->setCurrentWidget(ui->previewPage);
  134. ui->previewButton->setText(tr("<< Back"));
  135. ui->previewTreeView->expandAll();
  136. if (!selPath.isEmpty())
  137. {
  138. selPath.replace(oldPreviewDir, previewDir);
  139. QModelIndex index = previewModel->index(selPath);
  140. ui->previewTreeView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
  141. previewIndexChanged(index);
  142. }
  143. }
  144. }
  145. }
  146. void ctkPluginGenerator::previewClicked()
  147. {
  148. if (mode == EDIT)
  149. {
  150. if (createPreview())
  151. {
  152. ui->modeStack->setCurrentWidget(ui->previewPage);
  153. ui->previewButton->setText(tr("<< Back"));
  154. ui->previewTreeView->expandAll();
  155. if (!ui->previewTreeView->selectionModel()->selection().isEmpty())
  156. {
  157. previewIndexChanged(ui->previewTreeView->selectionModel()->selectedIndexes().front());
  158. }
  159. mode = PREVIEW;
  160. }
  161. }
  162. else
  163. {
  164. ui->modeStack->setCurrentWidget(ui->editPage);
  165. ui->previewButton->setText(tr("Preview >>"));
  166. mode = EDIT;
  167. ctk::removeDirRecursively(previewDir);
  168. previewDir.clear();
  169. }
  170. }
  171. void ctkPluginGenerator::generateClicked()
  172. {
  173. try
  174. {
  175. createPlugin(ui->outputDirButton->directory());
  176. QMessageBox msgBox;
  177. msgBox.setText(tr("Successfully create plugin"));
  178. msgBox.setStandardButtons(QMessageBox::Ok);
  179. msgBox.setIcon(QMessageBox::Information);
  180. msgBox.exec();
  181. }
  182. catch (const std::runtime_error& error)
  183. {
  184. QMessageBox msgBox;
  185. msgBox.setText(tr("Creating the plugin failed."));
  186. msgBox.setInformativeText(QString::fromLatin1(error.what()));
  187. msgBox.setStandardButtons(QMessageBox::Ok);
  188. msgBox.setIcon(QMessageBox::Critical);
  189. msgBox.exec();
  190. }
  191. }
  192. QString ctkPluginGenerator::createPlugin(const QString& path)
  193. {
  194. ctkServiceReference codeModelRef = framework->getPluginContext()->
  195. getServiceReference("ctkPluginGeneratorCodeModel");
  196. ctkPluginGeneratorCodeModel* codeModel =
  197. qobject_cast<ctkPluginGeneratorCodeModel*>(framework->getPluginContext()->getService(codeModelRef));
  198. codeModel->reset();
  199. // set global code model info from QSettings object
  200. QSettings settings;
  201. codeModel->setLicense(settings.value(ctkPluginGeneratorConstants::PLUGIN_LICENSE_MARKER).toString());
  202. foreach(ctkPluginGeneratorAbstractUiExtension* extension, idToExtensionMap)
  203. {
  204. extension->updateCodeModel();
  205. }
  206. QString pluginDir = path + "/" + codeModel->getSymbolicName(true);
  207. if (!QDir(path).mkdir(codeModel->getSymbolicName(true)))
  208. {
  209. QString msg(tr("Creating directory \"%1\" failed.").arg(pluginDir));
  210. throw std::runtime_error(msg.toStdString());
  211. }
  212. codeModel->create(pluginDir);
  213. return pluginDir;
  214. }
  215. void ctkPluginGenerator::previewIndexChanged(const QModelIndex& index)
  216. {
  217. QString filePath = previewModel->data(index, QFileSystemModel::FilePathRole).toString();
  218. ui->previewTextLabel->setText(QDir(QString(filePath).replace(previewDir, ui->outputDirButton->directory())).absolutePath());
  219. QFile file(filePath);
  220. file.open(QFile::ReadOnly);
  221. QTextStream textStream(&file);
  222. ui->previewTextEdit->setText(textStream.readAll());
  223. }
  224. bool ctkPluginGenerator::createPreview()
  225. {
  226. try
  227. {
  228. previewDir = ctkTemporaryDir::create();
  229. QString tmpPluginDir = createPlugin(previewDir);
  230. previewModel->setRootPath(tmpPluginDir);
  231. ui->previewTreeView->setRootIndex(previewModel->index(previewDir));
  232. }
  233. catch (const std::runtime_error& error)
  234. {
  235. QMessageBox msgBox;
  236. msgBox.setText(tr("Creating the preview failed."));
  237. msgBox.setInformativeText(QString::fromLatin1(error.what()));
  238. msgBox.setStandardButtons(QMessageBox::Ok);
  239. msgBox.setIcon(QMessageBox::Critical);
  240. msgBox.exec();
  241. return false;
  242. }
  243. return true;
  244. }
  245. void ctkPluginGenerator::extensionItemClicked(QListWidgetItem* item)
  246. {
  247. ctkPluginGeneratorAbstractUiExtension* extension = idToExtensionMap[item->data(Qt::UserRole).toInt()];
  248. extensionClicked(extension);
  249. }
  250. void ctkPluginGenerator::extensionClicked(ctkPluginGeneratorAbstractUiExtension* extension)
  251. {
  252. ui->extensionStack->setCurrentWidget(extension->getWidget());
  253. ui->extensionMsgLabel->setText(extension->getTitle());
  254. this->errorMessageChanged(extension->getErrorMessage());
  255. }
  256. void ctkPluginGenerator::errorMessageChanged(const QString& errMsg)
  257. {
  258. ui->extensionErrMsgLabel->setText(errMsg);
  259. bool enableButtons = false;
  260. if (errMsg.isEmpty())
  261. {
  262. enableButtons = true;
  263. }
  264. ui->previewButton->setEnabled(enableButtons);
  265. ui->generateButton->setEnabled(enableButtons);
  266. }