diff --git a/Applications/PluginGenerator/CMakeLists.txt b/Applications/PluginGenerator/CMakeLists.txt index 0106f4fdcb..9dcb1ba2a4 100644 --- a/Applications/PluginGenerator/CMakeLists.txt +++ b/Applications/PluginGenerator/CMakeLists.txt @@ -1,70 +1,76 @@ cmake_minimum_required(VERSION 2.8.4) project(MITKPluginGenerator) set(VERSION_MAJOR 1) -set(VERSION_MINOR 0) -set(VERSION_PATCH 0) +set(VERSION_MINOR 1) +set(VERSION_PATCH 1) + +set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(standalone_build 1) else() set(standalone_build 0) endif() #----------------------------------------------------------------------------- # Prerequesites #----------------------------------------------------------------------------- set(QT_DONT_USE_QTGUI 1) find_package(Qt 4.6.2 REQUIRED) include(${QT_USE_FILE}) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/PluginGeneratorConfig.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/PluginGeneratorConfig.h" @ONLY) +include_directories("${CMAKE_CURRENT_BINARY_DIR}") + #----------------------------------------------------------------------------- # Executable #----------------------------------------------------------------------------- set(src_files PluginGenerator.cpp ctkCommandLineParser.cpp ) qt4_wrap_cpp(src_files ctkCommandLineParser.h) qt4_add_resources(src_files plugin_template.qrc project_template.qrc) set(exec_target ${PROJECT_NAME}) add_executable(${exec_target} ${src_files}) target_link_libraries(${exec_target} ${QT_LIBRARIES}) if(NOT standalone_build) # subproject support add_dependencies(MITK-CoreUI ${exec_target}) endif() #----------------------------------------------------------------------------- # Win32 Convenience #----------------------------------------------------------------------------- if(WIN32 AND NOT standalone_build) file(TO_NATIVE_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}" native_runtime_dir) add_custom_target(NewPlugin start "MITK PluginGenerator" /D "${native_runtime_dir}" cmd /K ${exec_target}.exe -h DEPENDS ${exec_target}) endif() #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(NOT standalone_build) # Test the plugin generator include(mitkTestPluginGenerator) endif() #----------------------------------------------------------------------------- # Packaging support #----------------------------------------------------------------------------- if(standalone_build) include(SetupPackaging.cmake) endif() diff --git a/Applications/PluginGenerator/PluginGenerator.cpp b/Applications/PluginGenerator/PluginGenerator.cpp index 7663f9b7d1..326f548ecb 100644 --- a/Applications/PluginGenerator/PluginGenerator.cpp +++ b/Applications/PluginGenerator/PluginGenerator.cpp @@ -1,402 +1,407 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/ for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "ctkCommandLineParser.h" +#include #include #include #include #include #include #include #include #include #include bool readAnswer(char defaultAnswer) { std::string line; std::cin >> std::noskipws >> line; // consume the new line character std::cin.clear(); std::cin.ignore(std::numeric_limits::max(), '\n'); char answer = defaultAnswer; if (!line.empty() && line[0] != '\n') { answer = std::tolower(line[0]); } if (answer == 'y') return true; if (answer == 'n') return false; if (defaultAnswer == 'y') return true; return false; } void createFilePathMapping(const QString& templateName, const QString& baseInDir, const QString& baseOutDir, QHash& fileNameMapping) { QFileInfo info(templateName); if (info.isDir()) { QStringList subEntries = QDir(templateName).entryList(); foreach(QString subEntry, subEntries) { createFilePathMapping(templateName + "/" + subEntry, baseInDir, baseOutDir, fileNameMapping); } return; } fileNameMapping[templateName] = QString(templateName).replace(baseInDir, baseOutDir); } QHash createTemplateFileMapping(const QString& qrcBase, const QString& baseOutDir, const QHash& fileNameMapping) { QHash filePathMapping; createFilePathMapping(qrcBase, qrcBase, baseOutDir, filePathMapping); QMutableHashIterator i(filePathMapping); while(i.hasNext()) { i.next(); QHashIterator j(fileNameMapping); while(j.hasNext()) { j.next(); i.setValue(i.value().replace(j.key(), j.value())); } } return filePathMapping; } bool generateFiles(const QHash& parameters, const QHash& filePathMapping) { QHashIterator paths(filePathMapping); while(paths.hasNext()) { paths.next(); QFile templ(paths.key()); templ.open(QIODevice::ReadOnly); QByteArray templContent = templ.readAll(); QHashIterator i(parameters); while (i.hasNext()) { i.next(); templContent.replace(i.key(), QByteArray(i.value().toLatin1())); } QFile outTempl(paths.value()); QDir dir(QFileInfo(outTempl).dir()); if (!dir.exists()) { if (!dir.mkpath(dir.absolutePath())) { qCritical() << "Could not create directory" << dir.absolutePath(); return EXIT_FAILURE; } } if (!outTempl.open(QIODevice::WriteOnly)) { qCritical() << outTempl.errorString(); return false; } outTempl.write(templContent); } return true; } int main(int argc, char** argv) { + QString appName("MITKPluginGenerator"); + QCoreApplication app(argc, argv); - app.setApplicationName("PluginGenerator"); + app.setApplicationName(appName); app.setOrganizationName("DKFZ"); ctkCommandLineParser parser; // Use Unix-style argument names parser.setArgumentPrefix("--", "-"); parser.setStrictModeEnabled(true); // Add command line argument names parser.addArgument("help", "h", QVariant::Bool, "Show this help text"); parser.addArgument("out-dir", "o", QVariant::String, "Output directory", QDir::tempPath()); parser.addArgument("license", "l", QVariant::String, "Path to a file containing license information", ":/MITKLicense.txt"); parser.addArgument("vendor", "v", QVariant::String, "The vendor of the generated code", "DKFZ, Medical and Biological Informatics"); parser.addArgument("quiet", "q", QVariant::Bool, "Do not print additional information"); parser.addArgument("confirm-all", "y", QVariant::Bool, "Answer all questions with 'yes'"); parser.beginGroup("Plug-in options"); parser.addArgument("plugin-symbolic-name", "ps", QVariant::String, "The plugin's symbolic name"); parser.setExactMatchRegularExpression("-ps", "^[a-zA-Z]+\\.[a-zA-Z0-9._]+[^\\.]$", "Symbolic name invalid"); parser.addArgument("plugin-name", "pn", QVariant::String, "The plug-in's human readable name"); parser.beginGroup("Plug-in View options"); parser.addArgument("view-class", "vc", QVariant::String, "The View's' class name"); parser.addArgument("view-name", "vn", QVariant::String, "The View's human readable name"); parser.beginGroup("Project options"); parser.addArgument("project-copyright", "", QVariant::String, "Path to a file containing copyright information", ":/MITKCopyright.txt"); parser.addArgument("project-name", "", QVariant::String, "The project name"); parser.setExactMatchRegularExpression("--project-name", "^[a-zA-Z_\\-]+$", "Project name invalid"); parser.addArgument("project-app-name", "", QVariant::String, "The application name"); parser.setExactMatchRegularExpression("--project-app-name", "^[a-zA-Z_\\-]+$", "Project application name invalid"); parser.endGroup(); // Parse the command line arguments bool ok = false; QHash parsedArgs = parser.parseArguments(QCoreApplication::arguments(), &ok); if (!ok) { QTextStream(stderr, QIODevice::WriteOnly) << "Error parsing arguments: " - << parser.errorString() << "\n"; + << parser.errorString() << "\nType '" << appName << " -h' for help\n"; return EXIT_FAILURE; } QTextStream out(stdout, QIODevice::WriteOnly); // Show a help message if (parsedArgs.contains("help")) { - out << "A CTK plug-in generator for MITK\n\n" + out << "A CTK plug-in generator for MITK (version " PLUGIN_GENERATOR_VERSION ")\n\n" << parser.helpText(); return EXIT_SUCCESS; } // Check arguments // Project options QString projectName = parsedArgs["project-name"].toString(); QString projectAppName = parsedArgs["project-app-name"].toString(); QString copyrightPath = QDir::fromNativeSeparators(parsedArgs["project-copyright"].toString()); bool createProject = !projectName.isEmpty(); if (createProject && projectAppName.isEmpty()) { projectAppName = projectName; } QString pluginSymbolicName = parsedArgs["plugin-symbolic-name"].toString(); if (pluginSymbolicName.isEmpty()) { qCritical() << "Required argument 'plugin-symbolic-name' missing."; + qCritical("%s%s%s", "Type '", qPrintable(appName), " -h' for help"); return EXIT_FAILURE; } QString pluginTarget(pluginSymbolicName); pluginTarget.replace('.', '_'); QString outDir = QDir::fromNativeSeparators(parsedArgs["out-dir"].toString()); QString licensePath = QDir::fromNativeSeparators(parsedArgs["license"].toString()); QString pluginExportDirective = pluginSymbolicName.split('.').last().toUpper() + "_EXPORT"; QString pluginName = parsedArgs["plugin-name"].toString(); if (pluginName.isEmpty()) { QStringList toks = pluginSymbolicName.split('.'); pluginName = toks.last(); pluginName[0] = pluginName[0].toUpper(); } QString vendor = parsedArgs["vendor"].toString(); QString viewName = parsedArgs["view-name"].toString(); if (viewName.isEmpty()) { qCritical() << "Required argument 'view-name' missing."; + qCritical("%s%s%s", "Type '", qPrintable(appName), " -h' for help"); return EXIT_FAILURE; } QStringList toks = viewName.split(QRegExp("\\s"), QString::SkipEmptyParts); QString viewClass = parsedArgs["view-class"].toString(); if (viewClass.isEmpty()) { foreach(QString tok, toks) { QString tmp = tok; tmp[0] = tmp[0].toUpper(); viewClass += tmp; } } QString viewId; if (viewId.isEmpty()) { viewId = "org.mitk.views."; foreach(QString tok, toks) { viewId += tok.toLower(); } } bool quiet = parsedArgs.contains("quiet"); bool autoConfirm = parsedArgs.contains("confirm-all"); if (!outDir.endsWith('/')) outDir += '/'; if (createProject) outDir += projectName; else outDir += pluginSymbolicName; // Print the collected information if(!quiet) { if (createProject) { out << "Using the following information to create a project:\n\n" << " Project Name: " << projectName << '\n' << " Application Name: " << projectAppName << '\n' << " Copyright File: " << QDir::toNativeSeparators(copyrightPath) << '\n'; } else { out << "Using the following information to create a plug-in:\n\n"; } out << " License File: " << QDir::toNativeSeparators(licensePath) << '\n' << " Plugin-SymbolicName: " << pluginSymbolicName << '\n' << " Plugin-Name: " << pluginName << '\n' << " Plugin-Vendor: " << vendor << '\n' << " View Name: " << viewName << '\n' << " View Id: " << viewId << '\n' << " View Class: " << viewClass << '\n' << '\n' << "Create in: " << outDir << '\n' << '\n'; if (!autoConfirm) out << "Continue [Y/n]? "; out.flush(); if(!autoConfirm && !readAnswer('y')) { out << "Aborting.\n"; return EXIT_SUCCESS; } } // Check the output directory if (!QDir(outDir).exists()) { if (!autoConfirm) { out << "Directory '" << outDir << "' does not exist. Create it [Y/n]? "; out.flush(); } if (autoConfirm || readAnswer('y')) { if (!QDir().mkpath(outDir)) { qCritical() << "Could not create directory:" << outDir; return EXIT_FAILURE; } } else { out << "Aborting.\n"; return EXIT_SUCCESS; } } if (!QDir(outDir).entryList(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty()) { if (!autoConfirm) { out << "Directory '" << outDir << "' is not empty. Continue [y/N]? "; out.flush(); } if (!autoConfirm && !readAnswer('n')) { out << "Aborting.\n"; return EXIT_SUCCESS; } } // Extract the license text QFile licenseFile(licensePath); if (!licenseFile.open(QIODevice::ReadOnly)) { qCritical() << "Cannot open file" << licenseFile.fileName(); return EXIT_FAILURE; } QString licenseText = licenseFile.readAll(); licenseFile.close(); QHash parameters; if (createProject) { // Extract the copyright QFile copyrightFile(copyrightPath); if (!copyrightFile.open(QIODevice::ReadOnly)) { qCritical() << "Cannot open file" << copyrightFile.fileName(); return EXIT_FAILURE; } QString copyrighText = copyrightFile.readAll(); copyrightFile.close(); parameters["$(copyright)"] = copyrighText; parameters["$(project-name)"] = projectName; parameters["$(project-app-name)"] = projectAppName; parameters["$(project-plugins)"] = QString("Plugins/") + pluginSymbolicName + ":ON"; QStringList toks = pluginTarget.split("_"); QString projectPluginBase = toks[0] + "_" + toks[1]; parameters["$(project-plugin-base)"] = projectPluginBase; } parameters["$(license)"] = licenseText; parameters["$(plugin-name)"] = pluginName; parameters["$(plugin-symbolic-name)"] = pluginSymbolicName; parameters["$(vendor)"] = vendor; parameters["$(plugin-target)"] = pluginTarget; parameters["$(plugin-export-directive)"] = pluginExportDirective; parameters["$(view-id)"] = viewId; parameters["$(view-name)"] = viewName; parameters["$(view-file-name)"] = viewClass; parameters["$(view-class-name)"] = viewClass; if (createProject) { QHash projectFileNameMapping; projectFileNameMapping["TemplateApp"] = projectAppName; QHash filePathMapping = createTemplateFileMapping(":/ProjectTemplate", outDir, projectFileNameMapping); generateFiles(parameters, filePathMapping); } QHash pluginFileNameMapping; pluginFileNameMapping["QmitkTemplateView"] = viewClass; if (createProject) { if (!outDir.endsWith('/')) outDir += '/'; outDir += "Plugins/" + pluginSymbolicName; } QHash filePathMapping = createTemplateFileMapping(":/PluginTemplate", outDir, pluginFileNameMapping); generateFiles(parameters, filePathMapping); return EXIT_SUCCESS; } diff --git a/Applications/PluginGenerator/PluginGeneratorConfig.h.in b/Applications/PluginGenerator/PluginGeneratorConfig.h.in new file mode 100644 index 0000000000..2a1c287859 --- /dev/null +++ b/Applications/PluginGenerator/PluginGeneratorConfig.h.in @@ -0,0 +1,23 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/ for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef PLUGINGENERATORCONFIG_H +#define PLUGINGENERATORCONFIG_H + +#define PLUGIN_GENERATOR_VERSION "@VERSION_STRING@" + +#endif