Sfoglia il codice sorgente

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 anni fa
parent
commit
f228840719
41 ha cambiato i file con 2364 aggiunte e 111 eliminazioni
  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
+  )