소스 검색

ENH: PluginGenerator: First working version for generating CTK plugins

The generator can be extended by plugins and further customization
possibilities will be added in the future.
Sascha Zelzer 14 년 전
부모
커밋
f228840719
41개의 변경된 파일2364개의 추가작업 그리고 111개의 파일을 삭제
  1. 1 1
      Applications/ctkPluginBrowser/ctkPluginBrowser.cpp
  2. 5 2
      Applications/ctkPluginGenerator/CMakeLists.txt
  3. 1 9
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCmdArg.cpp
  4. 290 12
      Applications/ctkPluginGenerator/ctkPluginGenerator.cpp
  5. 5 0
      Applications/ctkPluginGenerator/ctkPluginGenerator.qrc
  6. 58 2
      Applications/ctkPluginGenerator/ctkPluginGeneratorMain.cpp
  7. 120 22
      Applications/ctkPluginGenerator/ctkPluginGeneratorMainWindow.ui
  8. 53 0
      Applications/ctkPluginGenerator/ctkPluginGeneratorOptionsDialog.cpp
  9. 74 0
      Applications/ctkPluginGenerator/ctkPluginGeneratorOptionsDialog.ui
  10. 19 5
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCmdArg.h
  11. 25 5
      Applications/ctkPluginGenerator/ctkPluginGenerator.h
  12. 8 0
      Plugins/org.commontk.plugingenerator.core/CMakeLists.txt
  13. 51 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorAbstractExtension.cpp
  14. 8 3
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorAbstractExtension.h
  15. 74 8
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorAbstractTemplate.cpp
  16. 18 3
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorAbstractTemplate.h
  17. 31 9
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCMakeLists.cpp
  18. 3 2
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCMakeLists.h
  19. 131 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCodeModel.cpp
  20. 24 5
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCodeModel.h
  21. 41 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorConstants.cpp
  22. 47 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorConstants.h
  23. 63 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCorePlugin.cpp
  24. 56 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCorePlugin_p.h
  25. 174 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCppPluginActivator.cpp
  26. 45 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCppPluginActivator.h
  27. 140 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCppTemplate.cpp
  28. 51 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCppTemplate.h
  29. 227 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorHeaderTemplate.cpp
  30. 49 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorHeaderTemplate.h
  31. 64 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorTargetLibraries.cpp
  32. 43 0
      Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorTargetLibraries.h
  33. 2 0
      Plugins/org.commontk.plugingenerator.ui/CMakeLists.txt
  34. 8 3
      Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorAbstractUiExtension.cpp
  35. 2 3
      Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorAbstractUiExtension.h
  36. 159 8
      Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorMainExtension.cpp
  37. 8 2
      Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorMainExtension.h
  38. 79 7
      Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorMainExtension.ui
  39. 51 0
      Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorUiPlugin.cpp
  40. 46 0
      Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorUiPlugin_p.h
  41. 10 0
      Plugins/org.commontk.plugingenerator.ui/target_libraries.cmake

+ 1 - 1
Applications/ctkPluginBrowser/ctkPluginBrowser.cpp

@@ -118,7 +118,7 @@ void ctkPluginBrowser::pluginDoubleClicked(const QModelIndex& index)
   {
     ctkServiceReference* ref = it.next();
     qDebug() << "Service from" << ref->getPlugin()->getSymbolicName() << ":" << ref->getPropertyKeys();
-    qDebug() << "Object Classes:" << ref->getProperty(PluginConstants::OBJECTCLASS).toStringList();
+    qDebug() << "Object Classes:" << ref->getProperty(ctkPluginConstants::OBJECTCLASS).toStringList();
   }
 
   ctkServiceReference* cliRef = plugin->getPluginContext()->getServiceReference("ctkICLIManager");

+ 5 - 2
Applications/ctkPluginGenerator/CMakeLists.txt

@@ -7,21 +7,24 @@ PROJECT(ctkPluginGenerator)
 SET(KIT_SRCS
   ctkPluginGenerator.cpp
   ctkPluginGeneratorMain.cpp
+  ctkPluginGeneratorOptionsDialog.cpp
 )
 
 # Headers that should run through moc
 SET(KIT_MOC_SRCS
-  ctkPluginGenerator.h
+  ctkPluginGenerator_p.h
+  ctkPluginGeneratorOptionsDialog_p.h
 )
 
 # UI files
 SET(KIT_UI_FORMS
   ctkPluginGeneratorMainWindow.ui
+  ctkPluginGeneratorOptionsDialog.ui
 )
 
 # Resources
 SET(KIT_resources
-  
+  ctkPluginGenerator.qrc
 )
 
 # Target libraries - See CMake/ctkMacroGetTargetLibraries.cmake

+ 1 - 9
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCmdArg.cpp

@@ -2,8 +2,7 @@
 
   Library: CTK
 
-  Copyright (c) 2010 German Cancer Research Center,
-    Division of Medical and Biological Informatics
+  Copyright (c) 2010 %1
 
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
@@ -18,10 +17,3 @@
   limitations under the License.
 
 =============================================================================*/
-
-
-#include "ctkPluginGeneratorCmdArg.h"
-
-ctkPluginGeneratorCmdArg::ctkPluginGeneratorCmdArg()
-{
-}

+ 290 - 12
Applications/ctkPluginGenerator/ctkPluginGenerator.cpp

@@ -19,49 +19,327 @@
 
 =============================================================================*/
 
-#include "ctkPluginGenerator.h"
+#include "ctkPluginGenerator_p.h"
 #include "ui_ctkPluginGeneratorMainWindow.h"
 
 #include <ctkPluginFramework.h>
+#include <ctkPluginContext.h>
+#include <ctkServiceReference.h>
+#include <ctkPluginConstants.h>
+#include <ctkPluginGeneratorCodeModel.h>
+#include <ctkPluginGeneratorConstants.h>
+#include <ctkPluginGeneratorOptionsDialog_p.h>
 
+#include <QDebug>
+#include <QListWidgetItem>
+#include <QDir>
+#include <QFileSystemModel>
+#include <QTime>
+#include <QMessageBox>
+#include <QSettings>
+
+#include <stdexcept>
+
+
+class ctkTemporaryDir
+{
+public:
+
+  static QString create(const QString& path = QString())
+  {
+    QString tmpPath = path;
+    if (tmpPath.isEmpty())
+    {
+      tmpPath = "ctkplugingenerator";
+    }
+    tmpPath +=  "." + QTime::currentTime().toString("hhmmsszzz");
+
+    QDir tmp = QDir::temp();
+    if (!tmp.mkdir(tmpPath))
+    {
+      QString msg = QString("Creating temporary directory ") + tmpPath + " in "
+                    + QDir::temp().canonicalPath() + " failed.";
+      throw std::runtime_error(msg.toStdString());
+    }
+
+    tmp.cd(tmpPath);
+
+    return tmp.canonicalPath();
+  }
+
+  static bool removeDir(const QString& dirName)
+  {
+    bool result = true;
+    QDir dir(dirName);
+
+    if (dir.exists(dirName))
+    {
+      foreach (QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden  | QDir::AllDirs | QDir::Files, QDir::DirsFirst))
+      {
+        if (info.isDir()) {
+          result = removeDir(info.absoluteFilePath());
+        }
+        else {
+          result = QFile::remove(info.absoluteFilePath());
+        }
+
+        if (!result) {
+          return result;
+        }
+      }
+      result = dir.rmdir(dirName);
+    }
+
+    return result;
+  }
+};
 
 ctkPluginGenerator::ctkPluginGenerator(ctkPluginFramework* framework, QWidget *parent) :
     QMainWindow(parent),
     framework(framework), ui(new Ui::ctkPluginGeneratorMainWindow),
-    mode(EDIT)
+    mode(EDIT), previewModel(0)
 {
-    ui->setupUi(this);
+  ui->setupUi(this);
+
+  previewModel = new QFileSystemModel(this);
+  ui->previewTreeView->setModel(previewModel);
+  ui->previewTreeView->hideColumn(1);
+  ui->previewTreeView->hideColumn(2);
+  ui->previewTreeView->hideColumn(3);
+
+  this->setStatusBar(0);
+
+  connect(ui->actionOptions, SIGNAL(triggered(bool)), this, SLOT(menuOptionsTriggered()));
+  connect(ui->generateButton, SIGNAL(clicked()), this, SLOT(generateClicked()));
+  connect(ui->previewButton, SIGNAL(clicked()), this, SLOT(previewClicked()));
+  connect(ui->cancelButton, SIGNAL(clicked()), qApp, SLOT(quit()));
+  connect(ui->uiExtensionList, SIGNAL(itemClicked(QListWidgetItem*)),
+          this, SLOT(extensionItemClicked(QListWidgetItem*)));
+  connect(ui->previewTreeView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), this, SLOT(previewIndexChanged(QModelIndex)));
+
+  QList<ctkServiceReference*> serviceRefs = framework->getPluginContext()->
+                                            getServiceReferences("ctkPluginGeneratorAbstractUiExtension");
+  QListIterator<ctkServiceReference*> it(serviceRefs);
+  while (it.hasNext())
+  {
+    ctkServiceReference* serviceRef = it.next();
+    ctkPluginGeneratorAbstractUiExtension* extension =
+        qobject_cast<ctkPluginGeneratorAbstractUiExtension*>(framework->getPluginContext()->getService(serviceRef));
+    qDebug() << "Service reference found";
+    if (extension)
+    {
+      qDebug() << "inserted";
+      int ranking = serviceRef->getProperty(ctkPluginConstants::SERVICE_RANKING).toInt();
+      if (ranking > 0)
+      {
+        uiExtensionMap.insert(ranking, extension);
+      }
+      else
+      {
+        uiExtensionMap.insert(-1, extension);
+      }
+    }
+  }
 
-    this->setStatusBar(0);
+  int id = 0;
+  foreach (ctkPluginGeneratorAbstractUiExtension* extension, uiExtensionMap)
+  {
+    idToExtensionMap.insert(id, extension);
+    ui->extensionStack->addWidget(extension->getWidget());
 
-    connect(ui->previewButton, SIGNAL(clicked()), this, SLOT(previewClicked()));
-    connect(ui->cancelButton, SIGNAL(clicked()), qApp, SLOT(quit()));
+    connect(extension, SIGNAL(errorMessageChanged(QString)), this, SLOT(errorMessageChanged(QString)));
 
+    extension->validate();
+
+    (new QListWidgetItem(extension->getTitle(), ui->uiExtensionList))->setData(Qt::UserRole, id);
+    ++id;
+  }
 
+  ui->uiExtensionList->setCurrentRow(0);
+  extensionClicked(idToExtensionMap[0]);
 }
 
 ctkPluginGenerator::~ctkPluginGenerator()
 {
-    delete ui;
+  delete ui;
+  if (!previewDir.isEmpty())
+  {
+    ctkTemporaryDir::removeDir(previewDir);
+  }
 }
 
-void ctkPluginGenerator::sectionErrorMessage(const QString& errorMsg)
+void ctkPluginGenerator::menuOptionsTriggered()
 {
-  ui->sectionMessageLabel->setText(errorMsg);
+  ctkPluginGeneratorOptionsDialog optionsDialog;
+  int result = optionsDialog.exec();
+  if (result == QDialog::Accepted && mode == PREVIEW)
+  {
+    QString selPath;
+    QString oldPreviewDir = previewDir;
+    if (!ui->previewTreeView->selectionModel()->selection().isEmpty())
+    {
+      QModelIndex index = ui->previewTreeView->selectionModel()->selectedIndexes().front();
+      selPath = previewModel->data(index, QFileSystemModel::FilePathRole).toString();
+    }
+    if (createPreview())
+    {
+      ui->modeStack->setCurrentWidget(ui->previewPage);
+      ui->previewButton->setText(tr("<< Back"));
+      ui->previewTreeView->expandAll();
+      if (!selPath.isEmpty())
+      {
+        selPath.replace(oldPreviewDir, previewDir);
+        QModelIndex index = previewModel->index(selPath);
+        ui->previewTreeView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
+        previewIndexChanged(index);
+      }
+    }
+  }
 }
 
 void ctkPluginGenerator::previewClicked()
 {
   if (mode == EDIT)
   {
-    ui->modeStack->setCurrentWidget(ui->previewPage);
-    ui->previewButton->setText(tr("<< Back"));
-    mode = PREVIEW;
+    if (createPreview())
+    {
+      ui->modeStack->setCurrentWidget(ui->previewPage);
+      ui->previewButton->setText(tr("<< Back"));
+      ui->previewTreeView->expandAll();
+      if (!ui->previewTreeView->selectionModel()->selection().isEmpty())
+      {
+        previewIndexChanged(ui->previewTreeView->selectionModel()->selectedIndexes().front());
+      }
+      mode = PREVIEW;
+    }
   }
   else
   {
     ui->modeStack->setCurrentWidget(ui->editPage);
     ui->previewButton->setText(tr("Preview >>"));
     mode = EDIT;
+
+    ctkTemporaryDir::removeDir(previewDir);
+    previewDir.clear();
   }
 }
+
+void ctkPluginGenerator::generateClicked()
+{
+  try
+  {
+    createPlugin(ui->outputDirButton->directory());
+
+    QMessageBox msgBox;
+    msgBox.setText(tr("Successfully create plugin"));
+    msgBox.setStandardButtons(QMessageBox::Ok);
+    msgBox.setIcon(QMessageBox::Information);
+    msgBox.exec();
+  }
+  catch (const std::runtime_error& error)
+  {
+    QMessageBox msgBox;
+    msgBox.setText(tr("Creating the plugin failed."));
+    msgBox.setInformativeText(QString::fromLatin1(error.what()));
+    msgBox.setStandardButtons(QMessageBox::Ok);
+    msgBox.setIcon(QMessageBox::Critical);
+    msgBox.exec();
+  }
+}
+
+QString ctkPluginGenerator::createPlugin(const QString& path)
+{
+  ctkServiceReference* codeModelRef = framework->getPluginContext()->
+                                      getServiceReference("ctkPluginGeneratorCodeModel");
+  if (!codeModelRef)
+  {
+    QString msg(tr("Retrieving service \"%1\" failed.").arg("ctkPluginGeneratorCodeModel"));
+    throw std::runtime_error(msg.toStdString());
+  }
+
+  ctkPluginGeneratorCodeModel* codeModel =
+      qobject_cast<ctkPluginGeneratorCodeModel*>(framework->getPluginContext()->getService(codeModelRef));
+  codeModel->reset();
+
+  // set global code model info from QSettings object
+  QSettings settings;
+  codeModel->setLicense(settings.value(ctkPluginGeneratorConstants::PLUGIN_LICENSE_MARKER).toString());
+
+  foreach(ctkPluginGeneratorAbstractUiExtension* extension, idToExtensionMap)
+  {
+    extension->updateCodeModel();
+  }
+
+  QString pluginDir = path + "/" + codeModel->getSymbolicName(true);
+  if (!QDir(path).mkdir(codeModel->getSymbolicName(true)))
+  {
+    QString msg(tr("Creating directory \"%1\" failed.").arg(pluginDir));
+    throw std::runtime_error(msg.toStdString());
+  }
+
+  codeModel->create(pluginDir);
+  return pluginDir;
+}
+
+void ctkPluginGenerator::previewIndexChanged(const QModelIndex& index)
+{
+  QString filePath = previewModel->data(index, QFileSystemModel::FilePathRole).toString();
+  ui->previewTextLabel->setText(QDir(QString(filePath).replace(previewDir, ui->outputDirButton->directory())).absolutePath());
+
+  QFile file(filePath);
+  file.open(QFile::ReadOnly);
+  QTextStream textStream(&file);
+  ui->previewTextEdit->setText(textStream.readAll());
+}
+
+bool ctkPluginGenerator::createPreview()
+{
+  try
+  {
+    previewDir = ctkTemporaryDir::create();
+
+    QString tmpPluginDir = createPlugin(previewDir);
+
+    previewModel->setRootPath(tmpPluginDir);
+    ui->previewTreeView->setRootIndex(previewModel->index(previewDir));
+  }
+  catch (const std::runtime_error& error)
+  {
+    QMessageBox msgBox;
+    msgBox.setText(tr("Creating the preview failed."));
+    msgBox.setInformativeText(QString::fromLatin1(error.what()));
+    msgBox.setStandardButtons(QMessageBox::Ok);
+    msgBox.setIcon(QMessageBox::Critical);
+    msgBox.exec();
+    return false;
+  }
+
+  return true;
+}
+
+void ctkPluginGenerator::extensionItemClicked(QListWidgetItem* item)
+{
+  ctkPluginGeneratorAbstractUiExtension* extension = idToExtensionMap[item->data(Qt::UserRole).toInt()];
+  extensionClicked(extension);
+}
+
+void ctkPluginGenerator::extensionClicked(ctkPluginGeneratorAbstractUiExtension* extension)
+{
+  ui->extensionStack->setCurrentWidget(extension->getWidget());
+  ui->extensionMsgLabel->setText(extension->getTitle());
+  this->errorMessageChanged(extension->getErrorMessage());
+}
+
+void ctkPluginGenerator::errorMessageChanged(const QString& errMsg)
+{
+  ui->extensionErrMsgLabel->setText(errMsg);
+
+  bool enableButtons = false;
+  if (errMsg.isEmpty())
+  {
+    enableButtons = true;
+  }
+
+  ui->previewButton->setEnabled(enableButtons);
+  ui->generateButton->setEnabled(enableButtons);
+}

+ 5 - 0
Applications/ctkPluginGenerator/ctkPluginGenerator.qrc

@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/generatordefaults">
+        <file alias="license.txt">DefaultLicense.txt</file>
+    </qresource>
+</RCC>

+ 58 - 2
Applications/ctkPluginGenerator/ctkPluginGeneratorMain.cpp

@@ -22,16 +22,42 @@
 #include <ctkPluginFrameworkFactory.h>
 #include <ctkPluginFramework.h>
 #include <ctkPluginException.h>
+#include <ctkPluginGeneratorConstants.h>
 
-#include "ctkPluginGenerator.h"
+#include "ctkPluginGenerator_p.h"
 
 #include <QApplication>
-
+#include <QSettings>
+#include <QDirIterator>
+#include <QInputDialog>
 
 int main(int argv, char** argc)
 {
   QApplication app(argv, argc);
 
+  qApp->setOrganizationName("CTK");
+  qApp->setOrganizationDomain("commontk.org");
+  qApp->setApplicationName("ctkPluginGenerator");
+
+  // init global template defaults
+  QSettings settings;
+  if (!settings.contains(ctkPluginGeneratorConstants::PLUGIN_LICENSE_MARKER))
+  {
+    QFile license(":/generatordefaults/license.txt");
+    license.open(QIODevice::ReadOnly);
+    QString licenseText = license.readAll();
+    bool ok;
+    QString organization = QInputDialog::getText(0, qApp->translate("OrganizationInputDialog", "CTK Plugin Generator"),
+                                                 qApp->translate("OrganizationInputDialog", "Enter the name of your organization:"),
+                                                 QLineEdit::Normal, qApp->translate("OrganizationInputDialog", "<your-organization>"), &ok);
+    if (!ok)
+    {
+      exit(0);
+    }
+    organization.replace("\\n", "\n");
+    settings.setValue(ctkPluginGeneratorConstants::PLUGIN_LICENSE_MARKER, licenseText.arg(organization));
+  }
+
   ctkPluginFrameworkFactory fwFactory;
   ctkPluginFramework* framework = fwFactory.getFramework();
 
@@ -44,6 +70,36 @@ int main(int argv, char** argc)
     exit(1);
   }
 
+#ifdef CMAKE_INTDIR
+  QString pluginPath = qApp->applicationDirPath() + "/../plugins/" CMAKE_INTDIR "/";
+#else
+  QString pluginPath = qApp->applicationDirPath() + "/plugins/";
+#endif
+
+  qApp->addLibraryPath(pluginPath);
+
+  QStringList libFilter;
+  libFilter << "*.dll" << "*.so" << "*.dylib";
+  QDirIterator dirIter(pluginPath, libFilter, QDir::Files);
+  while(dirIter.hasNext())
+  {
+    try
+    {
+      QString fileLocation = dirIter.next();
+      if (fileLocation.contains("org_commontk_plugingenerator"))
+      {
+        ctkPlugin* plugin = framework->getPluginContext()->installPlugin(QUrl::fromLocalFile(fileLocation));
+        plugin->start(ctkPlugin::START_TRANSIENT);
+      }
+    }
+    catch (const ctkPluginException& e)
+    {
+      qCritical() << e.what();
+    }
+  }
+
+  framework->start();
+
   ctkPluginGenerator generator(framework);
   generator.show();
 

+ 120 - 22
Applications/ctkPluginGenerator/ctkPluginGeneratorMainWindow.ui

@@ -26,6 +26,9 @@
         <verstretch>1</verstretch>
        </sizepolicy>
       </property>
+      <property name="currentIndex">
+       <number>0</number>
+      </property>
       <widget class="QWidget" name="editPage">
        <layout class="QVBoxLayout" name="verticalLayout_4">
         <property name="margin">
@@ -84,6 +87,12 @@ p, li { white-space: pre-wrap; }
            </layout>
           </widget>
           <widget class="QWidget" name="widget_4" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+             <horstretch>1</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
            <layout class="QVBoxLayout" name="verticalLayout_2">
             <property name="leftMargin">
              <number>6</number>
@@ -98,23 +107,88 @@ p, li { white-space: pre-wrap; }
              <number>0</number>
             </property>
             <item>
-             <widget class="QLabel" name="sectionMessageLabel">
-              <property name="minimumSize">
-               <size>
-                <width>0</width>
-                <height>40</height>
-               </size>
-              </property>
-              <property name="text">
-               <string/>
-              </property>
-              <property name="alignment">
-               <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
-              </property>
+             <widget class="QWidget" name="widget_7" native="true">
+              <layout class="QVBoxLayout" name="verticalLayout_8">
+               <property name="spacing">
+                <number>0</number>
+               </property>
+               <property name="margin">
+                <number>0</number>
+               </property>
+               <item>
+                <widget class="QLabel" name="extensionMsgLabel">
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="font">
+                  <font>
+                   <weight>75</weight>
+                   <bold>true</bold>
+                  </font>
+                 </property>
+                 <property name="text">
+                  <string>TextLabel</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QLabel" name="extensionErrMsgLabel">
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="palette">
+                  <palette>
+                   <active>
+                    <colorrole role="WindowText">
+                     <brush brushstyle="SolidPattern">
+                      <color alpha="255">
+                       <red>255</red>
+                       <green>0</green>
+                       <blue>0</blue>
+                      </color>
+                     </brush>
+                    </colorrole>
+                   </active>
+                   <inactive>
+                    <colorrole role="WindowText">
+                     <brush brushstyle="SolidPattern">
+                      <color alpha="255">
+                       <red>255</red>
+                       <green>0</green>
+                       <blue>0</blue>
+                      </color>
+                     </brush>
+                    </colorrole>
+                   </inactive>
+                   <disabled>
+                    <colorrole role="WindowText">
+                     <brush brushstyle="SolidPattern">
+                      <color alpha="255">
+                       <red>150</red>
+                       <green>147</green>
+                       <blue>140</blue>
+                      </color>
+                     </brush>
+                    </colorrole>
+                   </disabled>
+                  </palette>
+                 </property>
+                 <property name="text">
+                  <string>TextLabel</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
              </widget>
             </item>
             <item>
-             <widget class="QStackedWidget" name="sectionsStack">
+             <widget class="QStackedWidget" name="extensionStack">
               <property name="sizePolicy">
                <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
                 <horstretch>1</horstretch>
@@ -193,12 +267,19 @@ p, li { white-space: pre-wrap; }
                <string/>
               </property>
               <property name="alignment">
-               <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+               <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+              </property>
+              <property name="wordWrap">
+               <bool>true</bool>
               </property>
              </widget>
             </item>
             <item>
-             <widget class="QTextEdit" name="previewTextEdit"/>
+             <widget class="QTextEdit" name="previewTextEdit">
+              <property name="readOnly">
+               <bool>true</bool>
+              </property>
+             </widget>
             </item>
            </layout>
           </widget>
@@ -223,20 +304,23 @@ p, li { white-space: pre-wrap; }
           </sizepolicy>
          </property>
          <property name="text">
-          <string>Output Directory</string>
+          <string>Output directory</string>
          </property>
         </widget>
        </item>
        <item>
-        <widget class="QPushButton" name="outputDirButton">
+        <widget class="ctkDirectoryButton" name="outputDirButton">
          <property name="sizePolicy">
-          <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+          <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
            <horstretch>1</horstretch>
            <verstretch>0</verstretch>
           </sizepolicy>
          </property>
-         <property name="text">
-          <string>PushButton</string>
+         <property name="caption">
+          <string>Choose output directory</string>
+         </property>
+         <property name="options">
+          <set>ctkDirectoryButton::HideNameFilterDetails|ctkDirectoryButton::ShowDirsOnly</set>
          </property>
         </widget>
        </item>
@@ -299,7 +383,7 @@ p, li { white-space: pre-wrap; }
        <item>
         <widget class="QPushButton" name="cancelButton">
          <property name="text">
-          <string>Cancel</string>
+          <string>Exit</string>
          </property>
         </widget>
        </item>
@@ -321,6 +405,8 @@ p, li { white-space: pre-wrap; }
     <property name="title">
      <string>File</string>
     </property>
+    <addaction name="actionOptions"/>
+    <addaction name="separator"/>
     <addaction name="actionExit"/>
    </widget>
    <addaction name="menuFile"/>
@@ -334,7 +420,19 @@ p, li { white-space: pre-wrap; }
     <string>Ctrl+Q</string>
    </property>
   </action>
+  <action name="actionOptions">
+   <property name="text">
+    <string>Options...</string>
+   </property>
+  </action>
  </widget>
+ <customwidgets>
+  <customwidget>
+   <class>ctkDirectoryButton</class>
+   <extends>QWidget</extends>
+   <header>ctkDirectoryButton.h</header>
+  </customwidget>
+ </customwidgets>
  <resources/>
  <connections>
   <connection>

+ 53 - 0
Applications/ctkPluginGenerator/ctkPluginGeneratorOptionsDialog.cpp

@@ -0,0 +1,53 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#include "ctkPluginGeneratorOptionsDialog_p.h"
+#include "ui_ctkPluginGeneratorOptionsDialog.h"
+
+#include <ctkPluginGeneratorConstants.h>
+
+#include <QSettings>
+
+ctkPluginGeneratorOptionsDialog::ctkPluginGeneratorOptionsDialog(QWidget *parent) :
+    QDialog(parent),
+    ui(new Ui::ctkPluginGeneratorOptionsDialog)
+{
+    ui->setupUi(this);
+
+    QSettings settings;
+    ui->licenseEdit->setPlainText(settings.value(
+        ctkPluginGeneratorConstants::PLUGIN_LICENSE_MARKER).toString());
+}
+
+ctkPluginGeneratorOptionsDialog::~ctkPluginGeneratorOptionsDialog()
+{
+    delete ui;
+}
+
+void ctkPluginGeneratorOptionsDialog::accept()
+{
+  QSettings settings;
+  settings.setValue(ctkPluginGeneratorConstants::PLUGIN_LICENSE_MARKER,
+                    ui->licenseEdit->toPlainText());
+
+  QDialog::accept();
+}

+ 74 - 0
Applications/ctkPluginGenerator/ctkPluginGeneratorOptionsDialog.ui

@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ctkPluginGeneratorOptionsDialog</class>
+ <widget class="QDialog" name="ctkPluginGeneratorOptionsDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>License template</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QPlainTextEdit" name="licenseEdit"/>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>ctkPluginGeneratorOptionsDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>ctkPluginGeneratorOptionsDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>

+ 19 - 5
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCmdArg.h

@@ -20,13 +20,27 @@
 =============================================================================*/
 
 
-#ifndef CTKPLUGINGENERATORCMDARG_H
-#define CTKPLUGINGENERATORCMDARG_H
+#ifndef CTKPLUGINGENERATOROPTIONSDIALOG_H
+#define CTKPLUGINGENERATOROPTIONSDIALOG_H
 
-class ctkPluginGeneratorCmdArg
+#include <QDialog>
+
+namespace Ui {
+    class ctkPluginGeneratorOptionsDialog;
+}
+
+class ctkPluginGeneratorOptionsDialog : public QDialog
 {
+    Q_OBJECT
+
 public:
-    ctkPluginGeneratorCmdArg();
+    explicit ctkPluginGeneratorOptionsDialog(QWidget *parent = 0);
+    ~ctkPluginGeneratorOptionsDialog();
+
+    void accept();
+
+private:
+    Ui::ctkPluginGeneratorOptionsDialog *ui;
 };
 
-#endif // CTKPLUGINGENERATORCMDARG_H
+#endif // CTKPLUGINGENERATOROPTIONSDIALOG_H

+ 25 - 5
Applications/ctkPluginGenerator/ctkPluginGenerator.h

@@ -23,11 +23,17 @@
 #define CTKPLUGINGENERATOR_H
 
 #include <QMainWindow>
+#include <QMultiMap>
 
 #include <ctkPluginGeneratorAbstractUiExtension.h>
 
 class ctkPluginFramework;
 
+class QListWidgetItem;
+class QFileSystemModel;
+
+#include <QModelIndex>
+
 namespace Ui {
     class ctkPluginGeneratorMainWindow;
 }
@@ -42,24 +48,38 @@ public:
 
 protected slots:
 
-    void sectionErrorMessage(const QString& errorMsg);
-
     void previewClicked();
+    void generateClicked();
+    void previewIndexChanged(const QModelIndex& index);
+    void extensionItemClicked(QListWidgetItem* item);
+    void errorMessageChanged(const QString& errMsg);
+
+    void menuOptionsTriggered();
 
 private:
 
+    void extensionClicked(ctkPluginGeneratorAbstractUiExtension* extension);
+
+    QString createPlugin(const QString& path);
+
+    bool createPreview();
+
     enum GeneratorMode {
       EDIT,
       PREVIEW
     };
 
     ctkPluginFramework *const framework;
+    Ui::ctkPluginGeneratorMainWindow *ui;
+    GeneratorMode mode;
 
-    QList<ctkPluginGeneratorAbstractUiExtension*> uiExtensionList;
+    QFileSystemModel* previewModel;
 
-    Ui::ctkPluginGeneratorMainWindow *ui;
+    QString previewDir;
+
+    QMultiMap<int, ctkPluginGeneratorAbstractUiExtension*> uiExtensionMap;
+    QHash<int, ctkPluginGeneratorAbstractUiExtension*> idToExtensionMap;
 
-    GeneratorMode mode;
 };
 
 #endif // CTKPLUGINGENERATOR_H

+ 8 - 0
Plugins/org.commontk.plugingenerator.core/CMakeLists.txt

@@ -5,13 +5,21 @@ SET(PLUGIN_export_directive "org_commontk_plugingenerator_core_EXPORT")
 SET(PLUGIN_SRCS
   ctkPluginGeneratorAbstractExtension.cpp
   ctkPluginGeneratorAbstractTemplate.cpp
+  ctkPluginGeneratorConstants.cpp
+  ctkPluginGeneratorCorePlugin.cpp
   ctkPluginGeneratorCMakeLists.cpp
   ctkPluginGeneratorCodeModel.cpp
+  ctkPluginGeneratorCppPluginActivator
+  ctkPluginGeneratorCppTemplate.cpp
+  ctkPluginGeneratorHeaderTemplate.cpp
+  ctkPluginGeneratorTargetLibraries.cpp
 )
 
 SET(PLUGIN_MOC_SRCS
   ctkPluginGeneratorAbstractExtension.h
   ctkPluginGeneratorAbstractTemplate.h
+  ctkPluginGeneratorCodeModel.h
+  ctkPluginGeneratorCorePlugin_p.h
 )
 
 SET(PLUGIN_UI_FORMS

+ 51 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorAbstractExtension.cpp

@@ -22,11 +22,21 @@
 
 #include "ctkPluginGeneratorAbstractExtension.h"
 
+#include "ctkPluginGeneratorCorePlugin_p.h"
+
+#include <QVariant>
+
 class ctkPluginGeneratorAbstractExtensionPrivate
 {
 public:
 
+  ctkPluginGeneratorAbstractExtensionPrivate()
+    : valid(true)
+  {}
+
+  bool valid;
   QString errorMessage;
+  QHash<QString, QVariant> parameters;
 };
 
 ctkPluginGeneratorAbstractExtension::ctkPluginGeneratorAbstractExtension()
@@ -38,12 +48,53 @@ ctkPluginGeneratorAbstractExtension::~ctkPluginGeneratorAbstractExtension()
 {
 }
 
+void ctkPluginGeneratorAbstractExtension::setParameter(const QHash<QString, QVariant>& params)
+{
+  Q_D(ctkPluginGeneratorAbstractExtension);
+  d->parameters = params;
+}
+
+void ctkPluginGeneratorAbstractExtension::setParameter(const QString& name, const QVariant& value)
+{
+  Q_D(ctkPluginGeneratorAbstractExtension);
+  d->parameters[name] = value;
+}
+
+QHash<QString, QVariant> ctkPluginGeneratorAbstractExtension::getParameter() const
+{
+  Q_D(const ctkPluginGeneratorAbstractExtension);
+  return d->parameters;
+}
+
+bool ctkPluginGeneratorAbstractExtension::isValid() const
+{
+  Q_D(const ctkPluginGeneratorAbstractExtension);
+  return d->valid;
+}
+
+void ctkPluginGeneratorAbstractExtension::validate()
+{
+  Q_D(ctkPluginGeneratorAbstractExtension);
+  d->valid = verifyParameters(d->parameters);
+}
+
+void ctkPluginGeneratorAbstractExtension::updateCodeModel()
+{
+  Q_D(ctkPluginGeneratorAbstractExtension);
+  this->updateCodeModel(d->parameters);
+}
+
 QString ctkPluginGeneratorAbstractExtension::getErrorMessage() const
 {
   Q_D(const ctkPluginGeneratorAbstractExtension);
   return d->errorMessage;
 }
 
+ctkPluginGeneratorCodeModel* ctkPluginGeneratorAbstractExtension::getCodeModel() const
+{
+  return ctkPluginGeneratorCorePlugin::getInstance()->getCodeModel();
+}
+
 void ctkPluginGeneratorAbstractExtension::setErrorMessage(const QString& errorMsg)
 {
   Q_D(ctkPluginGeneratorAbstractExtension);

+ 8 - 3
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorAbstractExtension.h

@@ -29,6 +29,7 @@
 #include <org_commontk_plugingenerator_core_Export.h>
 
 class ctkPluginGeneratorAbstractExtensionPrivate;
+class ctkPluginGeneratorCodeModel;
 
 class org_commontk_plugingenerator_core_EXPORT ctkPluginGeneratorAbstractExtension : public QObject
 {
@@ -38,16 +39,19 @@ public:
     ctkPluginGeneratorAbstractExtension();
     virtual ~ctkPluginGeneratorAbstractExtension();
 
-    virtual void getCommandLineArgs() const = 0;
+    //virtual void getCommandLineArgs() const = 0;
 
     void setParameter(const QHash<QString, QVariant>& params);
+    void setParameter(const QString& name, const QVariant& value);
     QHash<QString, QVariant> getParameter() const;
 
     bool isValid() const;
+    void validate();
+    void updateCodeModel();
 
     QString getErrorMessage() const;
 
-    void generate();
+    ctkPluginGeneratorCodeModel* getCodeModel() const;
 
 signals:
 
@@ -57,7 +61,8 @@ protected:
 
     void setErrorMessage(const QString& errMsg);
 
-    virtual void verifyParameter(const QHash<QString, QVariant>& params) = 0;
+    virtual bool verifyParameters(const QHash<QString, QVariant>& params) = 0;
+    virtual void updateCodeModel(const QHash<QString, QVariant>& params) = 0;
 
 private:
 

+ 74 - 8
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorAbstractTemplate.cpp

@@ -22,6 +22,9 @@
 
 #include "ctkPluginGeneratorAbstractTemplate.h"
 
+#include "ctkPluginGeneratorCodeModel.h"
+#include "ctkPluginGeneratorConstants.h"
+
 #include <QHash>
 #include <QFile>
 
@@ -29,6 +32,13 @@ class ctkPluginGeneratorAbstractTemplatePrivate
 {
 public:
 
+  ctkPluginGeneratorAbstractTemplatePrivate()
+    : codeModel(0)
+  {}
+
+  ctkPluginGeneratorCodeModel* codeModel;
+
+  QString filename;
   QHash<QString, QStringList> contentMap;
 };
 
@@ -44,16 +54,59 @@ ctkPluginGeneratorAbstractTemplate::~ctkPluginGeneratorAbstractTemplate()
 
 }
 
-void ctkPluginGeneratorAbstractTemplate::addContent(const QString &marker, const QString &content, Position pos)
+void ctkPluginGeneratorAbstractTemplate::setCodeModel(ctkPluginGeneratorCodeModel *codeModel)
+{
+  Q_D(ctkPluginGeneratorAbstractTemplate);
+  d->codeModel = codeModel;
+}
+
+void ctkPluginGeneratorAbstractTemplate::setFilename(const QString& filename)
 {
   Q_D(ctkPluginGeneratorAbstractTemplate);
-  if (pos == START)
+  d->filename = filename;
+}
+
+QString ctkPluginGeneratorAbstractTemplate::getFilename() const
+{
+  Q_D(const ctkPluginGeneratorAbstractTemplate);
+
+  QString filename = this->objectName();
+  if(!d->filename.isEmpty())
   {
-    d->contentMap[marker].prepend(content);
+    filename = d->filename;
   }
-  else if (pos == END)
+
+  return filename;
+}
+
+void ctkPluginGeneratorAbstractTemplate::reset()
+{
+  Q_D(ctkPluginGeneratorAbstractTemplate);
+  d->contentMap.clear();
+}
+
+void ctkPluginGeneratorAbstractTemplate::addContent(const QString &marker, const QString &content, Position pos)
+{
+  Q_D(ctkPluginGeneratorAbstractTemplate);
+  switch (pos)
   {
-    d->contentMap[marker].append(content);
+  case PREPEND:
+    {
+      d->contentMap[marker].prepend(content);
+      break;
+    }
+  case APPEND:
+    {
+      d->contentMap[marker].append(content);
+      break;
+    }
+  case REPLACE:
+    {
+      QStringList& v = d->contentMap[marker];
+      v.clear();
+      v.append(content);
+      break;
+    }
   }
 }
 
@@ -65,13 +118,21 @@ QStringList ctkPluginGeneratorAbstractTemplate::getContent(const QString &marker
     return d->contentMap[marker];
   }
 
+  QString globalDefault = d->codeModel->getContent(marker);
+  if (!globalDefault.isEmpty())
+  {
+    return QStringList(globalDefault);
+  }
+
   return QStringList();
 }
 
 void ctkPluginGeneratorAbstractTemplate::create(const QString& location)
 {
-  const QString filename = location + "/" + this->objectName();
-  QFile file(filename);
+  QString filename = getFilename();
+
+  const QString path = location + "/" + filename;
+  QFile file(path);
   file.open(QIODevice::WriteOnly | QIODevice::Text);
   file.write(this->generateContent().toAscii());
   file.close();
@@ -79,6 +140,11 @@ void ctkPluginGeneratorAbstractTemplate::create(const QString& location)
 
 QStringList ctkPluginGeneratorAbstractTemplate::getMarkers() const
 {
-  return QStringList();
+  return ctkPluginGeneratorConstants::getGlobalMarkers();
 }
 
+QString ctkPluginGeneratorAbstractTemplate::getSymbolicName(bool withPeriods) const
+{
+  Q_D(const ctkPluginGeneratorAbstractTemplate);
+  return d->codeModel->getSymbolicName(withPeriods);
+}

+ 18 - 3
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorAbstractTemplate.h

@@ -29,6 +29,7 @@
 
 #include <org_commontk_plugingenerator_core_Export.h>
 
+class ctkPluginGeneratorCodeModel;
 class ctkPluginGeneratorAbstractTemplatePrivate;
 
 class org_commontk_plugingenerator_core_EXPORT ctkPluginGeneratorAbstractTemplate : public QObject
@@ -38,28 +39,42 @@ class org_commontk_plugingenerator_core_EXPORT ctkPluginGeneratorAbstractTemplat
 public:
 
   enum Position {
-    START,
-    END
+    PREPEND,
+    APPEND,
+    REPLACE
   };
 
   ctkPluginGeneratorAbstractTemplate(const QString& name, ctkPluginGeneratorAbstractTemplate* parent = 0);
 
   virtual ~ctkPluginGeneratorAbstractTemplate();
 
-  void addContent(const QString& marker, const QString& content, Position pos = END);
+  void setFilename(const QString& filename);
+  QString getFilename() const;
+
+  void addContent(const QString& marker, const QString& content, Position pos = APPEND);
 
   QStringList getContent(const QString& marker) const;
 
   virtual void create(const QString& location);
 
+  void reset();
+
   virtual QStringList getMarkers() const;
 
   virtual QString generateContent() = 0;
 
+protected:
+
+  QString getSymbolicName(bool withPeriods = false) const;
+
 private:
 
+  friend class ctkPluginGeneratorCodeModel;
+
   Q_DECLARE_PRIVATE(ctkPluginGeneratorAbstractTemplate)
 
+  void setCodeModel(ctkPluginGeneratorCodeModel* codeModel);
+
   const QScopedPointer<ctkPluginGeneratorAbstractTemplatePrivate> d_ptr;
 };
 

+ 31 - 9
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCMakeLists.cpp

@@ -22,13 +22,15 @@
 
 #include "ctkPluginGeneratorCMakeLists.h"
 
+#include "ctkPluginGeneratorConstants.h"
+
 #include <QTextStream>
 
 const QString ctkPluginGeneratorCMakeLists::PLUGIN_PROJECT_NAME_MARKER = "plugin_project_name";
-const QString ctkPluginGeneratorCMakeLists::PLUGIN_EXPORT_DIRECTIVE_MARKER = "plugin_export_directive";
 const QString ctkPluginGeneratorCMakeLists::PLUGIN_SRCS_MARKER = "plugin_srcs";
 const QString ctkPluginGeneratorCMakeLists::PLUGIN_MOC_SRCS_MARKER = "plugin_moc_srcs";
 const QString ctkPluginGeneratorCMakeLists::PLUGIN_RESOURCES_MARKER = "plugin_resources";
+const QString ctkPluginGeneratorCMakeLists::PLUGIN_UI_FORMS_MARKER = "plugin_ui_forms";
 
 ctkPluginGeneratorCMakeLists::ctkPluginGeneratorCMakeLists(ctkPluginGeneratorAbstractTemplate *parent) :
     ctkPluginGeneratorAbstractTemplate("CMakeLists.txt", parent)
@@ -42,20 +44,36 @@ QString ctkPluginGeneratorCMakeLists::generateContent()
 
   stream
     << "PROJECT(" << this->getContent(PLUGIN_PROJECT_NAME_MARKER).front() << ")\n\n"
-    << "SET(PLUGIN_export_directive \"" << this->getContent(PLUGIN_EXPORT_DIRECTIVE_MARKER).front() << "\")\n\n"
+    << "SET(PLUGIN_export_directive \"" << this->getContent(ctkPluginGeneratorConstants::PLUGIN_EXPORTMACRO_MARKER).front() << "\")\n\n"
     << "SET(PLUGIN_SRCS\n";
 
-  for (QStringListIterator it(this->getContent(PLUGIN_SRCS_MARKER)); it.hasNext();)
+  QStringList markerContent = this->getContent(PLUGIN_SRCS_MARKER);
+  markerContent.sort();
+  for (QStringListIterator it(markerContent); it.hasNext();)
   {
     stream << "  " << it.next() << "\n";
   }
 
   stream
     << ")\n\n"
-    << "# Files which should be processed my Qts moc\n"
+    << "# Files which should be processed by Qts moc\n"
     << "SET(PLUGIN_MOC_SRCS\n";
 
-  for (QStringListIterator it(this->getContent(PLUGIN_MOC_SRCS_MARKER)); it.hasNext();)
+  markerContent = this->getContent(PLUGIN_MOC_SRCS_MARKER);
+  markerContent.sort();
+  for (QStringListIterator it(markerContent); it.hasNext();)
+  {
+    stream << "  " << it.next() << "\n";
+  }
+
+  stream
+    << ")\n\n"
+    << "# Qt Designer files which should be processed by Qts uic\n"
+    << "SET(PLUGIN_UI_FORMS\n";
+
+  markerContent = this->getContent(PLUGIN_UI_FORMS_MARKER);
+  markerContent.sort();
+  for (QStringListIterator it(markerContent); it.hasNext();)
   {
     stream << "  " << it.next() << "\n";
   }
@@ -65,20 +83,23 @@ QString ctkPluginGeneratorCMakeLists::generateContent()
     << "# QRC Files which should be compiled into the plugin\n"
     << "SET(PLUGIN_resources\n";
 
-  for (QStringListIterator it(this->getContent(PLUGIN_RESOURCES_MARKER)); it.hasNext();)
+  markerContent = this->getContent(PLUGIN_RESOURCES_MARKER);
+  markerContent.sort();
+  for (QStringListIterator it(markerContent); it.hasNext();)
   {
     stream << "  " << it.next() << "\n";
   }
 
   stream
     << ")\n\n"
-    << "#Compute the library dependencies\n"
+    << "#Compute the plugin dependencies\n"
     << "ctkMacroGetTargetLibraries(PLUGIN_target_libraries)\n\n"
     << "ctkMacroBuildPlugin(\n"
     << "  NAME ${PROJECT_NAME}\n"
     << "  EXPORT_DIRECTIVE ${PLUGIN_export_directive}\n"
     << "  SRCS ${PLUGIN_SRCS}\n"
     << "  MOC_SRCS ${PLUGIN_MOC_SRCS}\n"
+    << "  UI_FORMS ${PLUGIN_UI_FORMS}\n"
     << "  RESOURCES ${PLUGIN_resources}\n"
     << "  TARGET_LIBRARIES ${PLUGIN_target_libraries}\n"
     << ")\n";
@@ -88,11 +109,12 @@ QString ctkPluginGeneratorCMakeLists::generateContent()
 
 QStringList ctkPluginGeneratorCMakeLists::getMarkers() const
 {
-  QStringList markers;
+  QStringList markers = ctkPluginGeneratorAbstractTemplate::getMarkers();
+
   markers << PLUGIN_PROJECT_NAME_MARKER
-      << PLUGIN_EXPORT_DIRECTIVE_MARKER
       << PLUGIN_SRCS_MARKER
       << PLUGIN_MOC_SRCS_MARKER
       << PLUGIN_RESOURCES_MARKER;
+
   return markers;
 }

+ 3 - 2
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCMakeLists.h

@@ -25,16 +25,17 @@
 
 #include "ctkPluginGeneratorAbstractTemplate.h"
 
-class ctkPluginGeneratorCMakeLists : public ctkPluginGeneratorAbstractTemplate
+class org_commontk_plugingenerator_core_EXPORT ctkPluginGeneratorCMakeLists
+  : public ctkPluginGeneratorAbstractTemplate
 {
 
 public:
 
   static const QString PLUGIN_PROJECT_NAME_MARKER;
-  static const QString PLUGIN_EXPORT_DIRECTIVE_MARKER;
   static const QString PLUGIN_SRCS_MARKER;
   static const QString PLUGIN_MOC_SRCS_MARKER;
   static const QString PLUGIN_RESOURCES_MARKER;
+  static const QString PLUGIN_UI_FORMS_MARKER;
 
   ctkPluginGeneratorCMakeLists(ctkPluginGeneratorAbstractTemplate *parent = 0);
 

+ 131 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCodeModel.cpp

@@ -27,12 +27,19 @@
 
 #include <stdexcept>
 
+
 class ctkPluginGeneratorCodeModelPrivate
 {
 public:
 
   QHash<QString, ctkPluginGeneratorAbstractTemplate*> rootTemplates;
+  QHash<QString, QString> contentMap;
 
+  QString symbolicNameWithPeriods;
+  QString symbolicNameWithUnderscores;
+  QString exportMacro;
+  QString exportMacroInclude;
+  QString license;
 };
 
 class ctkPluginGeneratorFolderTemplate : public ctkPluginGeneratorAbstractTemplate
@@ -76,13 +83,86 @@ ctkPluginGeneratorCodeModel::~ctkPluginGeneratorCodeModel()
 {
 }
 
+void ctkPluginGeneratorCodeModel::addContent(const QString& marker, const QString& content)
+{
+  Q_D(ctkPluginGeneratorCodeModel);
+  d->contentMap[marker] = content;
+}
+
+QString ctkPluginGeneratorCodeModel::getContent(const QString& marker) const
+{
+  Q_D(const ctkPluginGeneratorCodeModel);
+  if (d->contentMap.contains(marker))
+  {
+    return d->contentMap[marker];
+  }
+  return QString();
+}
+
+void ctkPluginGeneratorCodeModel::setExportMacro(const QString& exportMacro)
+{
+  Q_D(ctkPluginGeneratorCodeModel);
+  d->exportMacro = exportMacro;
+}
+
+QString ctkPluginGeneratorCodeModel::getExportMacro() const
+{
+  Q_D(const ctkPluginGeneratorCodeModel);
+  return d->exportMacro;
+}
+
+void ctkPluginGeneratorCodeModel::setExportMacroInclude(const QString& exportMacroInclude)
+{
+  Q_D(ctkPluginGeneratorCodeModel);
+  d->exportMacroInclude = exportMacroInclude;
+}
+
+QString ctkPluginGeneratorCodeModel::getExportMacroInclude() const
+{
+  Q_D(const ctkPluginGeneratorCodeModel);
+  return d->exportMacroInclude;
+}
+
+void ctkPluginGeneratorCodeModel::setSymbolicName(const QString& symbolicName)
+{
+  Q_D(ctkPluginGeneratorCodeModel);
+  d->symbolicNameWithPeriods = QString(symbolicName).replace("_", ".");
+  d->symbolicNameWithUnderscores = QString(symbolicName).replace(".", "_");
+}
+
+QString ctkPluginGeneratorCodeModel::getSymbolicName(bool withPeriods) const
+{
+  Q_D(const ctkPluginGeneratorCodeModel);
+  if (withPeriods)
+  {
+    return d->symbolicNameWithPeriods;
+  }
+ return d->symbolicNameWithUnderscores;
+}
+
+void ctkPluginGeneratorCodeModel::setLicense(const QString& license)
+{
+  Q_D(ctkPluginGeneratorCodeModel);
+  d->license = license;
+}
+
+QString ctkPluginGeneratorCodeModel::getLicense() const
+{
+  Q_D(const ctkPluginGeneratorCodeModel);
+  return d->license;
+}
+
 void ctkPluginGeneratorCodeModel::addTemplate(ctkPluginGeneratorAbstractTemplate *templ,
                                               const QString& path)
 {
   Q_D(ctkPluginGeneratorCodeModel);
+
+  templ->setCodeModel(this);
+
   if (path.isEmpty())
   {
     d->rootTemplates.insert(templ->objectName(), templ);
+    templ->setParent(this);
   }
   else
   {
@@ -137,6 +217,50 @@ void ctkPluginGeneratorCodeModel::addTemplate(ctkPluginGeneratorAbstractTemplate
   }
 }
 
+ctkPluginGeneratorAbstractTemplate* ctkPluginGeneratorCodeModel::getTemplate(const QString& path) const
+{
+  Q_D(const ctkPluginGeneratorCodeModel);
+
+  if (!path.contains("/"))
+  {
+    foreach(ctkPluginGeneratorAbstractTemplate* t, d->rootTemplates)
+    {
+      if (t->objectName() == path) return t;
+      ctkPluginGeneratorAbstractTemplate* child =
+          t->findChild<ctkPluginGeneratorAbstractTemplate*>(path);
+      if (child) return child;
+    }
+    return 0;
+  }
+
+  QStringList paths = path.split("/", QString::SkipEmptyParts);
+  if (paths.empty()) return 0;
+
+  QObject* currChild = d->rootTemplates[paths.front()];
+  paths.pop_front();
+
+  int depth = 0;
+  foreach (QString curr, paths)
+  {
+    foreach (QObject* child, currChild->children())
+    {
+      if (child->objectName() == curr)
+      {
+        currChild = child;
+        ++depth;
+        break;
+      }
+    }
+  }
+
+  if (paths.size() == depth)
+  {
+    return qobject_cast<ctkPluginGeneratorAbstractTemplate*>(currChild);
+  }
+
+  return 0;
+}
+
 void ctkPluginGeneratorCodeModel::create(const QString& location)
 {
   Q_D(ctkPluginGeneratorCodeModel);
@@ -148,3 +272,10 @@ void ctkPluginGeneratorCodeModel::create(const QString& location)
     templ->create(location);
   }
 }
+
+void ctkPluginGeneratorCodeModel::reset()
+{
+  Q_D(ctkPluginGeneratorCodeModel);
+  qDeleteAll(d->rootTemplates.values());
+  d->rootTemplates.clear();
+}

+ 24 - 5
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCodeModel.h

@@ -32,17 +32,36 @@ class ctkPluginGeneratorCodeModelPrivate;
 
 class org_commontk_plugingenerator_core_EXPORT ctkPluginGeneratorCodeModel : public QObject
 {
+  Q_OBJECT
 
 public:
-    ctkPluginGeneratorCodeModel();
 
-    virtual ~ctkPluginGeneratorCodeModel();
+  ctkPluginGeneratorCodeModel();
 
-    void addTemplate(ctkPluginGeneratorAbstractTemplate* templ, const QString& path = "");
+  virtual ~ctkPluginGeneratorCodeModel();
 
-    ctkPluginGeneratorAbstractTemplate* getTemplate(const QString& path) const;
+  void addTemplate(ctkPluginGeneratorAbstractTemplate* templ, const QString& path = "");
 
-    void create(const QString& location);
+  ctkPluginGeneratorAbstractTemplate* getTemplate(const QString& path) const;
+
+  void addContent(const QString& marker, const QString& content);
+  QString getContent(const QString& marker) const;
+
+  void setExportMacro(const QString& exportMacro);
+  QString getExportMacro() const;
+
+  void setExportMacroInclude(const QString& exportMacroInclude);
+  QString getExportMacroInclude() const;
+
+  void setSymbolicName(const QString& symbolicName);
+  QString getSymbolicName(bool withPeriods = false) const;
+
+  void setLicense(const QString& license);
+  QString getLicense() const;
+
+  void create(const QString& location);
+
+  void reset();
 
 private:
 

+ 41 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorConstants.cpp

@@ -0,0 +1,41 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#include "ctkPluginGeneratorConstants.h"
+
+#include <QStringList>
+
+const QString ctkPluginGeneratorConstants::PLUGIN_LICENSE_MARKER = "plugin_license";
+const QString ctkPluginGeneratorConstants::PLUGIN_EXPORTMACRO_MARKER = "plugin_exportmacro";
+const QString ctkPluginGeneratorConstants::PLUGIN_NAMESPACE_MARKER = "plugin_namespace";
+
+QStringList ctkPluginGeneratorConstants::getGlobalMarkers()
+{
+  return QStringList()
+      << PLUGIN_LICENSE_MARKER
+      << PLUGIN_EXPORTMACRO_MARKER
+      << PLUGIN_NAMESPACE_MARKER;
+}
+
+const QString ctkPluginGeneratorConstants::TEMPLATE_CMAKELISTS_TXT = "CMakeLists.txt";
+const QString ctkPluginGeneratorConstants::TEMPLATE_PLUGINACTIVATOR_H = "PluginActivator.h";
+const QString ctkPluginGeneratorConstants::TEMPLATE_PLUGINACTIVATOR_CPP = "PluginActivator.cpp";

+ 47 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorConstants.h

@@ -0,0 +1,47 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#ifndef CTKPLUGINGENERATORCONSTANTS_H
+#define CTKPLUGINGENERATORCONSTANTS_H
+
+#include <QString>
+
+#include <org_commontk_plugingenerator_core_Export.h>
+
+struct org_commontk_plugingenerator_core_EXPORT ctkPluginGeneratorConstants
+{
+
+  // project wide template markers
+  static const QString PLUGIN_LICENSE_MARKER;
+  static const QString PLUGIN_EXPORTMACRO_MARKER;
+  static const QString PLUGIN_NAMESPACE_MARKER;
+
+  static QStringList getGlobalMarkers();
+
+  // template names
+  static const QString TEMPLATE_CMAKELISTS_TXT;
+  static const QString TEMPLATE_PLUGINACTIVATOR_H;
+  static const QString TEMPLATE_PLUGINACTIVATOR_CPP;
+
+};
+
+#endif // CTKPLUGINGENERATORCONSTANTS_H

+ 63 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCorePlugin.cpp

@@ -0,0 +1,63 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#include "ctkPluginGeneratorCorePlugin_p.h"
+
+#include "ctkPluginGeneratorCodeModel.h"
+
+#include <QtPlugin>
+
+ctkPluginGeneratorCorePlugin* ctkPluginGeneratorCorePlugin::instance = 0;
+
+void ctkPluginGeneratorCorePlugin::start(ctkPluginContext* context)
+{
+  pluginContext = context;
+  instance = this;
+
+  codeModel = new ctkPluginGeneratorCodeModel();
+  context->registerService(QStringList("ctkPluginGeneratorCodeModel"), codeModel);
+}
+
+void ctkPluginGeneratorCorePlugin::stop(ctkPluginContext* context)
+{
+  Q_UNUSED(context);
+
+  delete codeModel;
+  instance = 0;
+}
+
+ctkPluginContext* ctkPluginGeneratorCorePlugin::getContext() const
+{
+  return pluginContext;
+}
+
+ctkPluginGeneratorCodeModel* ctkPluginGeneratorCorePlugin::getCodeModel() const
+{
+  return codeModel;
+}
+
+ctkPluginGeneratorCorePlugin* ctkPluginGeneratorCorePlugin::getInstance()
+{
+  return instance;
+}
+
+Q_EXPORT_PLUGIN2(org_commontk_plugingenerator_core, ctkPluginGeneratorCorePlugin)

+ 56 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCorePlugin_p.h

@@ -0,0 +1,56 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#ifndef CTKPLUGINGENERATORCOREPLUGIN_H
+#define CTKPLUGINGENERATORCOREPLUGIN_H
+
+#include <ctkPluginActivator.h>
+
+class ctkPluginGeneratorCodeModel;
+
+class ctkPluginGeneratorCorePlugin : public QObject,
+                                     public ctkPluginActivator
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkPluginActivator)
+
+public:
+
+  void start(ctkPluginContext* context);
+  void stop(ctkPluginContext* context);
+
+  ctkPluginContext* getContext() const;
+
+  ctkPluginGeneratorCodeModel* getCodeModel() const;
+
+  static ctkPluginGeneratorCorePlugin* getInstance();
+
+private:
+
+  static ctkPluginGeneratorCorePlugin* instance;
+
+  ctkPluginContext* pluginContext;
+
+  ctkPluginGeneratorCodeModel* codeModel;
+};
+
+#endif // CTKPLUGINGENERATORCOREPLUGIN_H

+ 174 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCppPluginActivator.cpp

@@ -0,0 +1,174 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#include "ctkPluginGeneratorCppPluginActivator.h"
+#include "ctkPluginGeneratorConstants.h"
+
+#include <QTextStream>
+
+const QString ctkPluginGeneratorCppPluginActivator::PLUGINACTIVATOR_START_MARKER = "pluginactivator_start";
+const QString ctkPluginGeneratorCppPluginActivator::PLUGINACTIVATOR_STOP_MARKER = "pluginactivator_stop";
+
+ctkPluginGeneratorCppPluginActivator::ctkPluginGeneratorCppPluginActivator(ctkPluginGeneratorAbstractTemplate* parent)
+  : ctkPluginGeneratorCppTemplate(ctkPluginGeneratorConstants::TEMPLATE_PLUGINACTIVATOR_CPP, parent)
+{
+
+}
+
+QString ctkPluginGeneratorCppPluginActivator::generateContent()
+{
+  addContent(CPP_INCLUDES_MARKER, "#include <QtPlugin>");
+
+  QString constructorContent;
+  QTextStream constructor(&constructorContent);
+
+  QStringList constructorInit = getContent(CPP_CONSTRUCTOR_INITLIST_MARKER);
+  QStringList constructorBody = getContent(CPP_CONSTRUCTOR_BODY_MARKER);
+  if (!constructorInit.isEmpty() || !constructorBody.isEmpty())
+  {
+    constructor << this->getClassNameToken() << "::" << this->getClassNameToken() << "()\n";
+
+    if (!constructorInit.isEmpty())
+    {
+      constructor << "  : ";
+      int i = 1;
+      foreach(QString initToken, constructorInit)
+      {
+        constructor << initToken;
+        if (i < constructorInit.size()) constructor << ", ";
+        ++i;
+      }
+      constructor << "\n";
+    }
+    constructor << "{\n";
+
+    if (!constructorBody.isEmpty())
+    {
+      int i = 1;
+      foreach(QString bodyToken, constructorBody)
+      {
+        constructor << "  " << bodyToken.replace("\n", "\n  ") << "\n";
+        if (i < constructorBody.size()) constructor << "\n";
+        ++i;
+      }
+    }
+    constructor << "}";
+  }
+
+  QString destructorContent;
+  QTextStream destructor(&destructorContent);
+
+  QStringList destructorBody = getContent(CPP_DESTRUCTOR_BODY_MARKER);
+  if (!destructorBody.isEmpty())
+  {
+    destructor << this->getClassNameToken() << "::~" << this->getClassNameToken() << "()\n"
+        << "{\n";
+    int i = 1;
+    foreach(QString bodyToken, destructorBody)
+    {
+      if (!bodyToken.isEmpty())
+      {
+        destructor << "\n";
+      }
+      else
+      {
+        destructor << "  " << bodyToken.replace("\n", "\n  ") << "\n";
+        if (i < destructorBody.size()) destructor << "\n";
+      }
+      ++i;
+    }
+    destructor << "}";
+  }
+
+  QString startMethodContent;
+  QTextStream startMethod(&startMethodContent);
+
+  startMethod << "void " << this->getClassNameToken() << "::start(ctkPluginContext* context)\n"
+      << "{\n";
+
+  QStringList startContent = getContent(PLUGINACTIVATOR_START_MARKER);
+  if (!startContent.isEmpty())
+  {
+    int i = 1;
+    foreach(QString block, startContent)
+    {
+      startMethod << "  " << block.replace("\n", "\n  ") << "\n";
+      if (i < startContent.size()) startMethod << "\n";
+      ++i;
+    }
+  }
+  else
+  {
+    startMethod << "  Q_UNUSED(context)\n";
+  }
+
+  startMethod << "}";
+
+
+  QString stopMethodContent;
+  QTextStream stopMethod(&stopMethodContent);
+
+  stopMethod << "void " << this->getClassNameToken() << "::stop(ctkPluginContext* context)\n"
+      << "{\n";
+
+  QStringList stopContent = getContent(PLUGINACTIVATOR_STOP_MARKER);
+  if (!stopContent.isEmpty())
+  {
+    int i = 1;
+    foreach(QString block, stopContent)
+    {
+      stopMethod << "  " << block.replace("\n", "\n  ") << "\n";
+      if (i < stopContent.size()) stopMethod << "\n";
+    }
+    ++i;
+  }
+  else
+  {
+    stopMethod << "  Q_UNUSED(context)\n";
+  }
+
+  stopMethod << "}";
+
+  addContent(CPP_METHODS_MARKER, stopMethodContent, PREPEND);
+  addContent(CPP_METHODS_MARKER, startMethodContent, PREPEND);
+  if (!destructorContent.isEmpty())
+  {
+    addContent(CPP_METHODS_MARKER, destructorContent, PREPEND);
+  }
+  if (!constructorContent.isEmpty())
+  {
+    addContent(CPP_METHODS_MARKER, constructorContent, PREPEND);
+  }
+
+  QString exportPlugin = "Q_EXPORT_PLUGIN2(" + getSymbolicName() + ", " + getClassNameToken() + ")\n";
+  addContent(CPP_METHODS_MARKER, exportPlugin);
+
+  return ctkPluginGeneratorCppTemplate::generateContent();
+}
+
+QStringList ctkPluginGeneratorCppPluginActivator::getMarkers() const
+{
+  QStringList markers;
+  markers << PLUGINACTIVATOR_START_MARKER
+      << PLUGINACTIVATOR_STOP_MARKER;
+  return markers;
+}

+ 45 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCppPluginActivator.h

@@ -0,0 +1,45 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#ifndef CTKPLUGINGENERATORCPPPLUGINACTIVATOR_H
+#define CTKPLUGINGENERATORCPPPLUGINACTIVATOR_H
+
+#include "ctkPluginGeneratorCppTemplate.h"
+
+class org_commontk_plugingenerator_core_EXPORT ctkPluginGeneratorCppPluginActivator
+  : public ctkPluginGeneratorCppTemplate
+{
+
+public:
+
+  static const QString PLUGINACTIVATOR_START_MARKER;
+  static const QString PLUGINACTIVATOR_STOP_MARKER;
+
+  ctkPluginGeneratorCppPluginActivator(ctkPluginGeneratorAbstractTemplate* parent = 0);
+
+  QString generateContent();
+
+  QStringList getMarkers() const;
+
+};
+
+#endif // CTKPLUGINGENERATORCPPPLUGINACTIVATOR_H

+ 140 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCppTemplate.cpp

@@ -0,0 +1,140 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#include "ctkPluginGeneratorCppTemplate.h"
+
+#include "ctkPluginGeneratorConstants.h"
+
+#include <QTextStream>
+
+const QString ctkPluginGeneratorCppTemplate::CPP_CLASSNAME_MARKER = "cpp_classname";
+const QString ctkPluginGeneratorCppTemplate::CPP_INCLUDES_MARKER = "cpp_includes";
+const QString ctkPluginGeneratorCppTemplate::CPP_GLOBAL_MARKER = "cpp_globals";
+const QString ctkPluginGeneratorCppTemplate::CPP_METHODS_MARKER = "cpp_methods";
+const QString ctkPluginGeneratorCppTemplate::CPP_CONSTRUCTOR_INITLIST_MARKER = "cpp_constructor_initlist";
+const QString ctkPluginGeneratorCppTemplate::CPP_CONSTRUCTOR_BODY_MARKER = "cpp_constructor_body";
+const QString ctkPluginGeneratorCppTemplate::CPP_DESTRUCTOR_BODY_MARKER = "cpp_destructor_body";
+
+ctkPluginGeneratorCppTemplate::ctkPluginGeneratorCppTemplate(
+    const QString& name, ctkPluginGeneratorAbstractTemplate* parent)
+  : ctkPluginGeneratorAbstractTemplate(name, parent)
+{
+
+}
+
+QStringList ctkPluginGeneratorCppTemplate::getMarkers() const
+{
+  QStringList markers = ctkPluginGeneratorAbstractTemplate::getMarkers();
+
+  markers << CPP_CLASSNAME_MARKER
+      << CPP_INCLUDES_MARKER
+      << CPP_GLOBAL_MARKER
+      << CPP_METHODS_MARKER
+      << CPP_CONSTRUCTOR_INITLIST_MARKER
+      << CPP_CONSTRUCTOR_BODY_MARKER;
+
+  return markers;
+}
+
+QString ctkPluginGeneratorCppTemplate::generateContent()
+{
+  QString content;
+  QTextStream stream(&content);
+
+  // get the namespace
+  QString namespaceToken;
+  QStringList namespc = this->getContent(ctkPluginGeneratorConstants::PLUGIN_NAMESPACE_MARKER);
+  if (!namespc.isEmpty() && !namespc.back().isEmpty())
+  {
+    namespaceToken = namespc.back();
+  }
+
+  // License header
+  QStringList licenseText = this->getContent(ctkPluginGeneratorConstants::PLUGIN_LICENSE_MARKER);
+  if (!licenseText.isEmpty() && !licenseText.back().isEmpty())
+  {
+    stream << licenseText.back() << "\n\n";
+  }
+
+  // include statements
+  QStringList includes = this->getContent(CPP_INCLUDES_MARKER);
+  if (!includes.isEmpty())
+  {
+    foreach(QString includeStatement, includes)
+    {
+      stream << includeStatement << "\n";
+    }
+    stream << "\n";
+  }
+
+  // namespace
+  if (!namespaceToken.isEmpty())
+  {
+    stream << "namespace " << namespaceToken << " {\n\n";
+  }
+
+  // global definitions
+  QStringList globals = this->getContent(CPP_GLOBAL_MARKER);
+  if (!globals.isEmpty())
+  {
+    foreach (QString global, globals)
+    {
+      stream << global << "\n";
+    }
+    stream << "\n";
+  }
+
+  // method definitions
+  QStringList methods = this->getContent(CPP_METHODS_MARKER);
+  if (!methods.isEmpty())
+  {
+    foreach (QString method, methods)
+    {
+      stream << method << "\n\n";
+    }
+  }
+
+  // end namespace
+  if (!namespaceToken.isEmpty())
+  {
+    stream << "} // end namespace " << namespaceToken << "\n";
+  }
+
+  return content;
+}
+
+QString ctkPluginGeneratorCppTemplate::getClassNameToken() const
+{
+  QString classNameToken;
+  QStringList classname = this->getContent(CPP_CLASSNAME_MARKER);
+  if (!classname.isEmpty() && !classname.back().isEmpty())
+  {
+    classNameToken = classname.back();
+  }
+  else
+  {
+    // use the filename without ending
+    classNameToken = getFilename().left(getFilename().lastIndexOf("."));
+  }
+
+  return classNameToken;
+}

+ 51 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorCppTemplate.h

@@ -0,0 +1,51 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#ifndef CTKPLUGINGENERATORCPPTEMPLATE_H
+#define CTKPLUGINGENERATORCPPTEMPLATE_H
+
+#include "ctkPluginGeneratorAbstractTemplate.h"
+
+class org_commontk_plugingenerator_core_EXPORT ctkPluginGeneratorCppTemplate : public ctkPluginGeneratorAbstractTemplate
+{
+public:
+
+  static const QString CPP_CLASSNAME_MARKER;
+  static const QString CPP_INCLUDES_MARKER;
+  static const QString CPP_GLOBAL_MARKER;
+  static const QString CPP_METHODS_MARKER;
+  static const QString CPP_CONSTRUCTOR_INITLIST_MARKER;
+  static const QString CPP_CONSTRUCTOR_BODY_MARKER;
+  static const QString CPP_DESTRUCTOR_BODY_MARKER;
+
+  ctkPluginGeneratorCppTemplate(const QString& name, ctkPluginGeneratorAbstractTemplate* parent = 0);
+
+  QStringList getMarkers() const;
+
+  QString generateContent();
+
+protected:
+
+  QString getClassNameToken() const;
+};
+
+#endif // CTKPLUGINGENERATORCPPTEMPLATE_H

+ 227 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorHeaderTemplate.cpp

@@ -0,0 +1,227 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#include "ctkPluginGeneratorHeaderTemplate.h"
+
+#include "ctkPluginGeneratorConstants.h"
+
+#include <QTextStream>
+
+const QString ctkPluginGeneratorHeaderTemplate::H_CLASSNAME_MARKER = "h_classname";
+const QString ctkPluginGeneratorHeaderTemplate::H_INCLUDES_MARKER = "h_includes";
+const QString ctkPluginGeneratorHeaderTemplate::H_FORWARD_DECL_MARKER = "h_forward_decl";
+const QString ctkPluginGeneratorHeaderTemplate::H_FORWARD_DECL_NAMESPACE_MARKER = "h_forward_decl_namespace";
+const QString ctkPluginGeneratorHeaderTemplate::H_SUPERCLASSES_MARKER = "h_superclasses";
+const QString ctkPluginGeneratorHeaderTemplate::H_DEFAULT_ACCESS_MARKER = "h_default_access";
+const QString ctkPluginGeneratorHeaderTemplate::H_PUBLIC_MARKER = "h_public";
+const QString ctkPluginGeneratorHeaderTemplate::H_PROTECTED_MARKER = "h_protected";
+const QString ctkPluginGeneratorHeaderTemplate::H_PRIVATE_MARKER = "h_private";
+
+ctkPluginGeneratorHeaderTemplate::ctkPluginGeneratorHeaderTemplate(const QString& name, ctkPluginGeneratorAbstractTemplate* parent)
+  : ctkPluginGeneratorAbstractTemplate(name, parent)
+{
+
+}
+
+QStringList ctkPluginGeneratorHeaderTemplate::getMarkers() const
+{
+  QStringList markers = ctkPluginGeneratorAbstractTemplate::getMarkers();
+
+  markers << H_CLASSNAME_MARKER
+      << H_INCLUDES_MARKER
+      << H_FORWARD_DECL_MARKER
+      << H_FORWARD_DECL_NAMESPACE_MARKER
+      << H_SUPERCLASSES_MARKER
+      << H_DEFAULT_ACCESS_MARKER
+      << H_PUBLIC_MARKER
+      << H_PROTECTED_MARKER
+      << H_PRIVATE_MARKER;
+
+  return markers;
+}
+
+QString ctkPluginGeneratorHeaderTemplate::generateContent()
+{
+  QString content;
+  QTextStream stream(&content);
+
+  // get the namespace
+  QString namespaceToken;
+  QStringList namespc = this->getContent(ctkPluginGeneratorConstants::PLUGIN_NAMESPACE_MARKER);
+  if (!namespc.isEmpty() && !namespc.back().isEmpty())
+  {
+    namespaceToken = namespc.back();
+  }
+
+  // get the classname
+  QString classNameToken;
+  QStringList classname = this->getContent(H_CLASSNAME_MARKER);
+  if (!classname.isEmpty() && !classname.back().isEmpty())
+  {
+    classNameToken = classname.back();
+  }
+  else
+  {
+    // use the filename without ending
+    classNameToken = getFilename().left(getFilename().lastIndexOf("."));
+  }
+
+  // License header
+  QStringList licenseText = this->getContent(ctkPluginGeneratorConstants::PLUGIN_LICENSE_MARKER);
+  if (!licenseText.isEmpty() && !licenseText.back().isEmpty())
+  {
+    stream << licenseText.back() << "\n\n";
+  }
+
+  // include guard
+  QString includeGuardToken;
+  if (!namespaceToken.isEmpty())
+  {
+    includeGuardToken += namespaceToken.toUpper() + "_";
+  }
+  includeGuardToken += getFilename().toUpper().replace(".", "_");
+  stream << "#ifndef " << includeGuardToken << "\n";
+  stream << "#define " << includeGuardToken << "\n\n";
+
+  // include statements
+  QStringList includes = this->getContent(H_INCLUDES_MARKER);
+  if (!includes.isEmpty())
+  {
+    foreach(QString includeStatement, includes)
+    {
+      stream << includeStatement << "\n";
+    }
+    stream << "\n";
+  }
+
+  // forward declarations
+  QStringList forwards = this->getContent(H_FORWARD_DECL_MARKER);
+  if (!forwards.isEmpty())
+  {
+    foreach(QString forward, forwards)
+    {
+      stream << forward << "\n";
+    }
+    stream << "\n";
+  }
+
+  // namespace
+  if (!namespaceToken.isEmpty())
+  {
+    stream << "namespace " << namespaceToken << " {\n\n";
+  }
+
+  // forward declarations inside namespace
+  QStringList forwardsN = this->getContent(H_FORWARD_DECL_NAMESPACE_MARKER);
+  if (!forwardsN.isEmpty())
+  {
+    foreach(QString forward, forwardsN)
+    {
+      stream << forward << "\n";
+    }
+    stream << "\n";
+  }
+
+  // class declaration
+  stream << "class ";
+  QStringList exportMacro = this->getContent(ctkPluginGeneratorConstants::PLUGIN_EXPORTMACRO_MARKER);
+  if (!exportMacro.isEmpty() && !exportMacro.back().isEmpty())
+  {
+    stream << exportMacro.back() << " ";
+  }
+  stream << classNameToken;
+  QStringList superclasses = this->getContent(H_SUPERCLASSES_MARKER);
+  if (!superclasses.isEmpty())
+  {
+    stream << " :\n";
+    int i = 1;
+    foreach(QString superclass, superclasses)
+    {
+      stream << "  " << superclass;
+      if (i < superclasses.size()) stream << ",";
+    }
+  }
+  stream << "\n{\n";
+
+  // method and member declarations
+
+  // default access
+  QStringList defaultAccess = this->getContent(H_DEFAULT_ACCESS_MARKER);
+  if (!defaultAccess.isEmpty())
+  {
+    foreach(QString entry, defaultAccess)
+    {
+      stream << "  " << entry.replace("\n", "\n  ") << "\n";
+    }
+    stream << "\n";
+  }
+
+  // public access
+  QStringList publicAccess = this->getContent(H_PUBLIC_MARKER);
+  if (!publicAccess.isEmpty())
+  {
+    stream << "public:\n\n";
+    foreach(QString entry, publicAccess)
+    {
+      stream << "  " << entry.replace("\n", "\n  ") << "\n\n";
+    }
+    stream << "\n";
+  }
+
+  // protected access
+  QStringList protectedAccess = this->getContent(H_PROTECTED_MARKER);
+  if (!protectedAccess.isEmpty())
+  {
+    stream << "protected:\n\n";
+    foreach(QString entry, protectedAccess)
+    {
+      stream << "  " << entry.replace("\n", "\n  ") << "\n\n";
+    }
+    stream << "\n";
+  }
+
+  // private access
+  QStringList privateAccess = this->getContent(H_PRIVATE_MARKER);
+  if (!privateAccess.isEmpty())
+  {
+    stream << "private:\n\n";
+    foreach(QString entry, privateAccess)
+    {
+      stream << "  " << entry.replace("\n", "\n  ") << "\n\n";
+    }
+    stream << "\n";
+  }
+
+  // end class declaration
+  stream << "}; // " << classNameToken << "\n\n";
+
+  // end namespace
+  if (!namespaceToken.isEmpty())
+  {
+    stream << "} // end namespace " << namespaceToken << "\n";
+  }
+
+  // end include guard
+  stream << "#endif // " << includeGuardToken << "\n";
+
+  return content;
+}

+ 49 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorHeaderTemplate.h

@@ -0,0 +1,49 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#ifndef CTKPLUGINGENERATORHEADERTEMPLATE_H
+#define CTKPLUGINGENERATORHEADERTEMPLATE_H
+
+#include "ctkPluginGeneratorAbstractTemplate.h"
+
+class org_commontk_plugingenerator_core_EXPORT ctkPluginGeneratorHeaderTemplate : public ctkPluginGeneratorAbstractTemplate
+{
+public:
+
+  static const QString H_CLASSNAME_MARKER;
+  static const QString H_INCLUDES_MARKER;
+  static const QString H_FORWARD_DECL_MARKER;
+  static const QString H_FORWARD_DECL_NAMESPACE_MARKER;
+  static const QString H_SUPERCLASSES_MARKER;
+  static const QString H_DEFAULT_ACCESS_MARKER;
+  static const QString H_PUBLIC_MARKER;
+  static const QString H_PROTECTED_MARKER;
+  static const QString H_PRIVATE_MARKER;
+
+  ctkPluginGeneratorHeaderTemplate(const QString& name, ctkPluginGeneratorAbstractTemplate* parent = 0);
+
+  QStringList getMarkers() const;
+
+  QString generateContent();
+};
+
+#endif // CTKPLUGINGENERATORHEADERTEMPLATE_H

+ 64 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorTargetLibraries.cpp

@@ -0,0 +1,64 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#include "ctkPluginGeneratorTargetLibraries.h"
+
+#include <QTextStream>
+
+const QString ctkPluginGeneratorTargetLibraries::TARGETLIBRARIES_MARKER = "targetlibraries";
+
+ctkPluginGeneratorTargetLibraries::ctkPluginGeneratorTargetLibraries(ctkPluginGeneratorAbstractTemplate* parent)
+  : ctkPluginGeneratorAbstractTemplate("target_libraries.cmake", parent)
+{
+
+}
+
+QString ctkPluginGeneratorTargetLibraries::generateContent()
+{
+  QString content;
+  QTextStream stream(&content);
+
+  stream << "# See CMake/ctkMacroGetTargetLibraries.cmake\n"
+      << "#\n"
+      << "# This file should list the libraries required to build the current CTK plugin.\n"
+      << "# For specifying required plugins, see the manifest_headers.cmake file.\n"
+      << "#\n\n"
+      << "SET(target_libraries\n";
+
+  QStringList libs = getContent(TARGETLIBRARIES_MARKER);
+  foreach(QString lib, libs)
+  {
+    stream << "  " << lib << "\n";
+  }
+
+  stream << ")\n";
+
+  return content;
+}
+
+QStringList ctkPluginGeneratorTargetLibraries::getMarkers() const
+{
+  QStringList markers = ctkPluginGeneratorAbstractTemplate::getMarkers();
+
+  markers << TARGETLIBRARIES_MARKER;
+  return markers;
+}

+ 43 - 0
Plugins/org.commontk.plugingenerator.core/ctkPluginGeneratorTargetLibraries.h

@@ -0,0 +1,43 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#ifndef CTKPLUGINGENERATORTARGETLIBRARIES_H
+#define CTKPLUGINGENERATORTARGETLIBRARIES_H
+
+#include "ctkPluginGeneratorAbstractTemplate.h"
+
+class org_commontk_plugingenerator_core_EXPORT ctkPluginGeneratorTargetLibraries
+  : public ctkPluginGeneratorAbstractTemplate
+{
+
+public:
+
+  static const QString TARGETLIBRARIES_MARKER;
+
+  ctkPluginGeneratorTargetLibraries(ctkPluginGeneratorAbstractTemplate* parent = 0);
+
+  QString generateContent();
+
+  QStringList getMarkers() const;
+};
+
+#endif // CTKPLUGINGENERATORTARGETLIBRARIES_H

+ 2 - 0
Plugins/org.commontk.plugingenerator.ui/CMakeLists.txt

@@ -5,11 +5,13 @@ SET(PLUGIN_export_directive "org_commontk_plugingenerator_ui_EXPORT")
 SET(PLUGIN_SRCS
   ctkPluginGeneratorAbstractUiExtension.cpp
   ctkPluginGeneratorMainExtension.cpp
+  ctkPluginGeneratorUiPlugin.cpp
 )
 
 SET(PLUGIN_MOC_SRCS
   ctkPluginGeneratorAbstractUiExtension.h
   ctkPluginGeneratorMainExtension.h
+  ctkPluginGeneratorUiPlugin_p.h
 )
 
 SET(PLUGIN_UI_FORMS

+ 8 - 3
Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorAbstractUiExtension.cpp

@@ -26,12 +26,12 @@ class ctkPluginGeneratorAbstractUiExtensionPrivate
 public:
 
   ctkPluginGeneratorAbstractUiExtensionPrivate()
-    : sectionWidget(0)
+    : extensionWidget(0)
   {
 
   }
 
-  QWidget* sectionWidget;
+  QWidget* extensionWidget;
 
   QString description;
   QString title;
@@ -53,7 +53,12 @@ ctkPluginGeneratorAbstractUiExtension::~ctkPluginGeneratorAbstractUiExtension()
 QWidget* ctkPluginGeneratorAbstractUiExtension::getWidget()
 {
   Q_D(ctkPluginGeneratorAbstractUiExtension);
-  return d->sectionWidget;
+  if (d->extensionWidget == 0)
+  {
+    d->extensionWidget = this->createWidget();
+  }
+
+  return d->extensionWidget;
 }
 
 QString ctkPluginGeneratorAbstractUiExtension::getDescription() const

+ 2 - 3
Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorAbstractUiExtension.h

@@ -44,12 +44,9 @@ public:
 
   QWidget* getWidget();
 
-  virtual QWidget* createWidget(QWidget* parent) = 0;
-
   QString getDescription() const;
   QString getTitle() const;
 
-  QString getErrorMessage() const;
   QString getMessage() const;
 
   QIcon getIcon() const;
@@ -63,6 +60,8 @@ signals:
 
 protected:
 
+  virtual QWidget* createWidget() = 0;
+
   void setDescription(const QString& description);
   void setTitle(const QString& title);
 

+ 159 - 8
Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorMainExtension.cpp

@@ -22,16 +22,24 @@
 
 #include "ctkPluginGeneratorMainExtension.h"
 
+#include <ctkPluginGeneratorCodeModel.h>
+#include <ctkPluginGeneratorConstants.h>
+#include <ctkPluginGeneratorCMakeLists.h>
+#include <ctkPluginGeneratorHeaderTemplate.h>
+#include <ctkPluginGeneratorCppPluginActivator.h>
+#include <ctkPluginGeneratorTargetLibraries.h>
+
 ctkPluginGeneratorMainExtension::ctkPluginGeneratorMainExtension()
   : ui(0)
 {
-
+  this->setTitle(tr("Main"));
+  this->setDescription("The main parameters for a new plugin");
 }
 
-QWidget* ctkPluginGeneratorMainExtension::createWidget(QWidget* parent)
+QWidget* ctkPluginGeneratorMainExtension::createWidget()
 {
   ui = new Ui::ctkPluginGeneratorMainExtension();
-  QWidget* container = new QWidget(parent);
+  QWidget* container = new QWidget();
   ui->setupUi(container);
 
   connectSignals();
@@ -43,18 +51,161 @@ QWidget* ctkPluginGeneratorMainExtension::createWidget(QWidget* parent)
 
 void ctkPluginGeneratorMainExtension::connectSignals()
 {
-  connect(ui->symbolicNameEdit, SIGNAL(textChanged(QString)), this, SLOT(verifySection()));
+  connect(ui->symbolicNameEdit, SIGNAL(textChanged(QString)), this, SLOT(symbolicNameChanged()));
+  connect(ui->activatorClassEdit, SIGNAL(textChanged(QString)), this, SLOT(activatorClassChanged()));
+  connect(ui->symbolicNameEdit, SIGNAL(textChanged(QString)), this, SLOT(updateParameters()));
+  connect(ui->exportDirectiveEdit, SIGNAL(textChanged(QString)), this, SLOT(updateParameters()));
+  connect(ui->activatorClassEdit, SIGNAL(textChanged(QString)), this, SLOT(updateParameters()));
+  connect(ui->activatorHeaderEdit, SIGNAL(textChanged(QString)), this, SLOT(updateParameters()));
+  connect(ui->activatorSourceEdit, SIGNAL(textChanged(QString)), this, SLOT(updateParameters()));
+}
+
+void ctkPluginGeneratorMainExtension::symbolicNameChanged()
+{
+  QString symbolicName = ui->symbolicNameEdit->text().replace(".", "_");
+  ui->exportDirectiveEdit->setText(symbolicName + "_EXPORT");
+
+  QString activatorClassName;
+  QStringList tokens = symbolicName.split('_');
+
+  if (tokens.size() > 1)
+  {
+    tokens.pop_front();
+    activatorClassName += tokens.takeFirst();
+    foreach(QString token, tokens)
+    {
+      activatorClassName += token.left(1).toUpper() + token.mid(1);
+    }
+  }
+
+  activatorClassName += "Plugin";
+
+  ui->activatorClassEdit->setText(activatorClassName);
+  ui->activatorHeaderEdit->setText(activatorClassName + "_p.h");
+  ui->activatorSourceEdit->setText(activatorClassName + ".cpp");
+}
+
+void ctkPluginGeneratorMainExtension::activatorClassChanged()
+{
+  QString activatorClassName = ui->activatorClassEdit->text();
+  ui->activatorHeaderEdit->setText(activatorClassName + "_p.h");
+  ui->activatorSourceEdit->setText(activatorClassName + ".cpp");
+
+  ui->advancedButton->setText(tr("Advanced (activator class: %1)").arg(activatorClassName));
 }
 
-void ctkPluginGeneratorMainExtension::verifySection()
+bool ctkPluginGeneratorMainExtension::verifyParameters(
+        const QHash<QString, QVariant>& params)
 {
-  if (ui->symbolicNameEdit->text().isEmpty())
+  if (params["symbolic-name"].toString().isEmpty())
   {
     this->setErrorMessage(tr("The symbolic name cannot be empty"));
+    return false;
+  }
+
+  if (params["export-directive"].toString().isEmpty())
+  {
+    this->setErrorMessage(tr("The export directive cannot be empty"));
+    return false;
+  }
+
+  if (params["activator-classname"].toString().isEmpty())
+  {
+    this->setErrorMessage(tr("The activator class name cannot be empty"));
+    return false;
+  }
+
+  if (params["activator-headerfile"].toString().isEmpty())
+  {
+    this->setErrorMessage(tr("The activator header filename cannot be empty"));
+    return false;
   }
-  else
+
+  if (params["activator-sourcefile"].toString().isEmpty())
   {
-    this->setErrorMessage("");
+    this->setErrorMessage(tr("The activator source filename cannot be empty"));
+    return false;
   }
+
+  this->setErrorMessage("");
+  return true;
+}
+
+void ctkPluginGeneratorMainExtension::updateCodeModel(const QHash<QString, QVariant>& params)
+{
+  ctkPluginGeneratorCodeModel* codeModel = this->getCodeModel();
+
+  codeModel->setSymbolicName(params["symbolic-name"].toString());
+  codeModel->setExportMacroInclude(QString("#include <") + codeModel->getSymbolicName() + "_Export.h>");
+  codeModel->setExportMacro(params["export-directive"].toString());
+
+  // Add CMakeLists.txt template
+  codeModel->addTemplate(new ctkPluginGeneratorCMakeLists());
+
+  ctkPluginGeneratorAbstractTemplate* cmakelistsTemplate = codeModel->getTemplate(ctkPluginGeneratorConstants::TEMPLATE_CMAKELISTS_TXT);
+
+  cmakelistsTemplate->addContent(ctkPluginGeneratorCMakeLists::PLUGIN_PROJECT_NAME_MARKER,
+                                 codeModel->getSymbolicName(),
+                                 ctkPluginGeneratorAbstractTemplate::REPLACE);
+  cmakelistsTemplate->addContent(ctkPluginGeneratorConstants::PLUGIN_EXPORTMACRO_MARKER,
+                                 codeModel->getExportMacro(),
+                                 ctkPluginGeneratorAbstractTemplate::REPLACE);
+
+  // Add <plugin-activator>.h template
+  QString activatorClassName = params["activator-classname"].toString();
+  ctkPluginGeneratorAbstractTemplate* activatorHeaderTemplate =
+      new ctkPluginGeneratorHeaderTemplate(ctkPluginGeneratorConstants::TEMPLATE_PLUGINACTIVATOR_H);
+  activatorHeaderTemplate->addContent(ctkPluginGeneratorConstants::PLUGIN_LICENSE_MARKER, codeModel->getLicense());
+  activatorHeaderTemplate->addContent(ctkPluginGeneratorHeaderTemplate::H_INCLUDES_MARKER, "#include <ctkPluginActivator.h>");
+  activatorHeaderTemplate->addContent(ctkPluginGeneratorHeaderTemplate::H_CLASSNAME_MARKER, activatorClassName);
+  activatorHeaderTemplate->addContent(ctkPluginGeneratorHeaderTemplate::H_SUPERCLASSES_MARKER, "public QObject, public ctkPluginActivator");
+  activatorHeaderTemplate->addContent(ctkPluginGeneratorHeaderTemplate::H_DEFAULT_ACCESS_MARKER, "Q_OBJECT\nQ_INTERFACES(ctkPluginActivator)");
+  activatorHeaderTemplate->addContent(ctkPluginGeneratorHeaderTemplate::H_PUBLIC_MARKER, activatorClassName + "();\n~" + activatorClassName + "();");
+  activatorHeaderTemplate->addContent(ctkPluginGeneratorHeaderTemplate::H_PUBLIC_MARKER, "void start(ctkPluginContext* context);\nvoid stop(ctkPluginContext* context);");
+  activatorHeaderTemplate->addContent(ctkPluginGeneratorHeaderTemplate::H_PUBLIC_MARKER, QString("static ") + activatorClassName + "* getInstance();");
+  activatorHeaderTemplate->addContent(ctkPluginGeneratorHeaderTemplate::H_PUBLIC_MARKER, "ctkPluginContext* getPluginContext() const;");
+  activatorHeaderTemplate->addContent(ctkPluginGeneratorHeaderTemplate::H_PRIVATE_MARKER, QString("static ") + activatorClassName + "* instance;\nctkPluginContext* context;");
+  activatorHeaderTemplate->setFilename(params["activator-headerfile"].toString());
+
+  codeModel->addTemplate(activatorHeaderTemplate);
+
+  // Add <plugin-activator>.cpp template
+  ctkPluginGeneratorAbstractTemplate* activatorCppTemplate =
+      new ctkPluginGeneratorCppPluginActivator();
+  activatorCppTemplate->addContent(ctkPluginGeneratorConstants::PLUGIN_LICENSE_MARKER, codeModel->getLicense());
+  activatorCppTemplate->addContent(ctkPluginGeneratorCppTemplate::CPP_CLASSNAME_MARKER, activatorClassName);
+  activatorCppTemplate->addContent(ctkPluginGeneratorCppTemplate::CPP_INCLUDES_MARKER, QString("#include \"") + activatorHeaderTemplate->getFilename() + "\"");
+  activatorCppTemplate->addContent(ctkPluginGeneratorCppTemplate::CPP_GLOBAL_MARKER, activatorClassName + "* " + activatorClassName + "::instance = 0;");
+  activatorCppTemplate->addContent(ctkPluginGeneratorCppTemplate::CPP_CONSTRUCTOR_INITLIST_MARKER, "context(0)");
+  activatorCppTemplate->addContent(ctkPluginGeneratorCppTemplate::CPP_DESTRUCTOR_BODY_MARKER, "");
+  activatorCppTemplate->addContent(ctkPluginGeneratorCppPluginActivator::PLUGINACTIVATOR_START_MARKER, "instance = this;\nthis->context = context;");
+  activatorCppTemplate->addContent(ctkPluginGeneratorCppTemplate::CPP_METHODS_MARKER, activatorClassName + "* " + activatorClassName + "::getInstance()\n{\n  return instance;\n}");
+  activatorCppTemplate->addContent(ctkPluginGeneratorCppTemplate::CPP_METHODS_MARKER, QString("ctkPluginContext* ") + activatorClassName + "::getPluginContext() const\n{\n  return context;\n}");
+  activatorCppTemplate->setFilename(params["activator-sourcefile"].toString());
+  codeModel->addTemplate(activatorCppTemplate);
+
+  // Add target_libraries.cmake template
+  // TODO only add the CTKPluginFramework library if there are no plugin dependencies
+  ctkPluginGeneratorAbstractTemplate* targetLibrariesTemplate =
+      new ctkPluginGeneratorTargetLibraries();
+  targetLibrariesTemplate->addContent(ctkPluginGeneratorTargetLibraries::TARGETLIBRARIES_MARKER, "CTKPluginFramework");
+  codeModel->addTemplate(targetLibrariesTemplate);
+
+  // add project files to CMakeLists.txt
+  cmakelistsTemplate->addContent(ctkPluginGeneratorCMakeLists::PLUGIN_SRCS_MARKER, activatorCppTemplate->getFilename());
+  cmakelistsTemplate->addContent(ctkPluginGeneratorCMakeLists::PLUGIN_MOC_SRCS_MARKER, activatorHeaderTemplate->getFilename());
+}
+
+void ctkPluginGeneratorMainExtension::updateParameters()
+{
+  this->setParameter("symbolic-name", ui->symbolicNameEdit->text());
+  this->setParameter("plugin-name", ui->nameEdit->text());
+  this->setParameter("plugin-version", ui->versionEdit->text());
+  this->setParameter("export-directive", ui->exportDirectiveEdit->text());
+  this->setParameter("activator-classname", ui->activatorClassEdit->text());
+  this->setParameter("activator-headerfile", ui->activatorHeaderEdit->text());
+  this->setParameter("activator-sourcefile", ui->activatorSourceEdit->text());
+
+  this->validate();
 }
 

+ 8 - 2
Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorMainExtension.h

@@ -36,15 +36,21 @@ public:
 
 protected slots:
 
-    void verifySection();
+    void updateParameters();
+    void symbolicNameChanged();
+    void activatorClassChanged();
 
 protected:
 
-    QWidget* createWidget(QWidget* parent);
+    bool verifyParameters(const QHash<QString, QVariant>& params);
+    void updateCodeModel(const QHash<QString, QVariant>& params);
+
+    QWidget* createWidget();
 
     void connectSignals();
 
     Ui::ctkPluginGeneratorMainExtension* ui;
+
 };
 
 #endif // CTKPLUGINGENERATORMAINEXTENSION_H

+ 79 - 7
Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorMainExtension.ui

@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>400</width>
-    <height>300</height>
+    <width>470</width>
+    <height>476</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -24,7 +24,7 @@
     <widget class="QLineEdit" name="nameEdit"/>
    </item>
    <item row="2" column="2">
-    <widget class="QLineEdit" name="lineEdit_3"/>
+    <widget class="QLineEdit" name="versionEdit"/>
    </item>
    <item row="1" column="1">
     <widget class="QLabel" name="label_2">
@@ -36,7 +36,7 @@
    <item row="0" column="1">
     <widget class="QLabel" name="label">
      <property name="text">
-      <string>Symbolic Name</string>
+      <string>Symbolic name</string>
      </property>
     </widget>
    </item>
@@ -47,7 +47,7 @@
      </property>
     </widget>
    </item>
-   <item row="4" column="2">
+   <item row="5" column="2">
     <spacer name="verticalSpacer">
      <property name="orientation">
       <enum>Qt::Vertical</enum>
@@ -63,12 +63,12 @@
    <item row="3" column="1">
     <widget class="QLabel" name="label_7">
      <property name="text">
-      <string>Activation Policy</string>
+      <string>Activation policy</string>
      </property>
     </widget>
    </item>
    <item row="3" column="2">
-    <widget class="QComboBox" name="comboBox">
+    <widget class="QComboBox" name="activationPolicyCombo">
      <item>
       <property name="text">
        <string>Lazy</string>
@@ -81,8 +81,80 @@
      </item>
     </widget>
    </item>
+   <item row="4" column="1" colspan="2">
+    <widget class="ctkCollapsibleButton" name="advancedButton">
+     <property name="text">
+      <string>Advanced</string>
+     </property>
+     <property name="collapsed">
+      <bool>true</bool>
+     </property>
+     <property name="collapsedHeight">
+      <number>0</number>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="QWidget" name="widget" native="true">
+        <layout class="QGridLayout" name="gridLayout_2">
+         <property name="margin">
+          <number>0</number>
+         </property>
+         <item row="0" column="0">
+          <widget class="QLabel" name="label_4">
+           <property name="text">
+            <string>Export directive</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="1">
+          <widget class="QLineEdit" name="exportDirectiveEdit"/>
+         </item>
+         <item row="1" column="0">
+          <widget class="QLabel" name="label_5">
+           <property name="text">
+            <string>Activator class name</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="1">
+          <widget class="QLineEdit" name="activatorClassEdit"/>
+         </item>
+         <item row="2" column="0">
+          <widget class="QLabel" name="label_6">
+           <property name="text">
+            <string>Activator header file</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="1">
+          <widget class="QLineEdit" name="activatorHeaderEdit"/>
+         </item>
+         <item row="3" column="0">
+          <widget class="QLabel" name="label_8">
+           <property name="text">
+            <string>Activator source file</string>
+           </property>
+          </widget>
+         </item>
+         <item row="3" column="1">
+          <widget class="QLineEdit" name="activatorSourceEdit"/>
+         </item>
+        </layout>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
   </layout>
  </widget>
+ <customwidgets>
+  <customwidget>
+   <class>ctkCollapsibleButton</class>
+   <extends>QWidget</extends>
+   <header>ctkCollapsibleButton.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
  <resources/>
  <connections/>
 </ui>

+ 51 - 0
Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorUiPlugin.cpp

@@ -0,0 +1,51 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#include "ctkPluginGeneratorUiPlugin_p.h"
+
+#include "ctkPluginGeneratorMainExtension.h"
+
+#include <ctkPluginConstants.h>
+
+#include <QtPlugin>
+#include <QDebug>
+
+void ctkPluginGeneratorUiPlugin::start(ctkPluginContext* context)
+{
+  mainExtension = new ctkPluginGeneratorMainExtension();
+
+  ServiceProperties props;
+  props.insert(ctkPluginConstants::SERVICE_RANKING, 0);
+  context->registerService(QStringList("ctkPluginGeneratorAbstractUiExtension"),
+                           mainExtension, props);
+
+  qDebug() << "Registered Main Extension";
+}
+
+void ctkPluginGeneratorUiPlugin::stop(ctkPluginContext* context)
+{
+  Q_UNUSED(context)
+
+  delete mainExtension;
+}
+
+Q_EXPORT_PLUGIN2(org_commontk_plugingenerator_ui, ctkPluginGeneratorUiPlugin)

+ 46 - 0
Plugins/org.commontk.plugingenerator.ui/ctkPluginGeneratorUiPlugin_p.h

@@ -0,0 +1,46 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#ifndef CTKPLUGINGENERATORUIPLUGIN_H
+#define CTKPLUGINGENERATORUIPLUGIN_H
+
+#include <ctkPluginActivator.h>
+
+class ctkPluginGeneratorAbstractUiExtension;
+
+class ctkPluginGeneratorUiPlugin : public QObject,
+                                   public ctkPluginActivator
+{
+  Q_OBJECT
+  Q_INTERFACES(ctkPluginActivator)
+
+public:
+
+  void start(ctkPluginContext* context);
+  void stop(ctkPluginContext* context);
+
+private:
+
+  ctkPluginGeneratorAbstractUiExtension* mainExtension;
+};
+
+#endif // CTKPLUGINGENERATORUIPLUGIN_H

+ 10 - 0
Plugins/org.commontk.plugingenerator.ui/target_libraries.cmake

@@ -0,0 +1,10 @@
+#
+# See CMake/ctkMacroGetTargetLibraries.cmake
+# 
+# This file should list the libraries required to build the current CTK plugin.
+# To specify required plugins, see the file manifest_headers.cmake.
+# 
+
+SET(target_libraries
+  CTKWidgets
+  )