#include "filetemplatesplugin.h" #include "templateclassassistant.h" #include "templatepreviewtoolview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define debug() kDebug(debugArea()) using namespace KDevelop; int debugArea() { static int area = KDebug::registerArea("kdevfiletemplates"); return area; } K_PLUGIN_FACTORY(FileTemplatesFactory, registerPlugin();) K_EXPORT_PLUGIN(FileTemplatesFactory(KAboutData("kdevfiletemplates", "kdevfiletemplates", ki18n("File Templates Configuration"), "0.1", ki18n("Manages templates for source files"), KAboutData::License_GPL))) class TemplatePreviewFactory : public KDevelop::IToolViewFactory { public: TemplatePreviewFactory(FileTemplatesPlugin* plugin) : KDevelop::IToolViewFactory() , m_plugin(plugin) { } virtual QWidget* create(QWidget* parent = 0) { return new TemplatePreviewToolView(m_plugin, parent); } virtual QString id() const { return "org.kdevelop.TemplateFilePreview"; } virtual Qt::DockWidgetArea defaultPosition() { return Qt::RightDockWidgetArea; } private: FileTemplatesPlugin* m_plugin; }; FileTemplatesPlugin::FileTemplatesPlugin(QObject* parent, const QVariantList& args) : IPlugin(FileTemplatesFactory::componentData(), parent) , m_model(0) { Q_UNUSED(args); KDEV_USE_EXTENSION_INTERFACE(ITemplateProvider) setXMLFile("kdevfiletemplates.rc"); KAction* action = actionCollection()->addAction("new_from_template"); action->setText( i18n( "New From Template" ) ); action->setIcon( KIcon( "code-class" ) ); action->setWhatsThis( i18n( "Allows you to create new source code files, such as classes or unit tests, using templates." ) ); action->setStatusTip( i18n( "Create new files from a template" ) ); connect (action, SIGNAL(triggered(bool)), SLOT(createFromTemplate())); m_toolView = new TemplatePreviewFactory(this); core()->uiController()->addToolView(i18n("Template Preview"), m_toolView); } FileTemplatesPlugin::~FileTemplatesPlugin() { } void FileTemplatesPlugin::unload() { core()->uiController()->removeToolView(m_toolView); } ContextMenuExtension FileTemplatesPlugin::contextMenuExtension (Context* context) { ContextMenuExtension ext; KUrl fileUrl; if (context->type() == Context::ProjectItemContext) { ProjectItemContext* projectContext = dynamic_cast(context); QList items = projectContext->items(); if (items.size() != 1) { return ext; } KUrl url; ProjectBaseItem* item = items.first(); if (item->folder()) { url = item->path().toUrl(); } else if (item->target()) { url = item->parent()->path().toUrl(); } if (url.isValid()) { KAction* action = new KAction(i18n("Create From Template"), this); action->setIcon(KIcon("code-class")); action->setData(url); connect(action, SIGNAL(triggered(bool)), SLOT(createFromTemplate())); ext.addAction(ContextMenuExtension::FileGroup, action); } if (item->file()) { fileUrl = item->path().toUrl(); } } else if (context->type() == Context::EditorContext) { KDevelop::EditorContext* editorContext = dynamic_cast(context); fileUrl = editorContext->url(); } if (fileUrl.isValid() && determineTemplateType(fileUrl) != NoTemplate) { KAction* action = new KAction(i18n("Show Template Preview"), this); action->setIcon(KIcon("document-preview")); action->setData(fileUrl); connect(action, SIGNAL(triggered(bool)), SLOT(previewTemplate())); ext.addAction(ContextMenuExtension::ExtensionGroup, action); } return ext; } QString FileTemplatesPlugin::name() const { return i18n("File Templates"); } QIcon FileTemplatesPlugin::icon() const { return KIcon("code-class"); } QAbstractItemModel* FileTemplatesPlugin::templatesModel() { if(!m_model) { m_model = new TemplatesModel("kdevfiletemplates", this); } return m_model; } QString FileTemplatesPlugin::knsConfigurationFile() const { return "kdevfiletemplates.knsrc"; } QStringList FileTemplatesPlugin::supportedMimeTypes() const { QStringList types; types << "application/x-desktop"; types << "application/x-bzip-compressed-tar"; types << "application/zip"; return types; } void FileTemplatesPlugin::reload() { templatesModel(); m_model->refresh(); } void FileTemplatesPlugin::loadTemplate(const QString& fileName) { templatesModel(); m_model->loadTemplateFile(fileName); } void FileTemplatesPlugin::createFromTemplate() { KUrl baseUrl; if (QAction* action = qobject_cast(sender())) { baseUrl = action->data().value(); } if (!baseUrl.isValid()) { // fall-back to currently active document's parent directory IDocument* doc = ICore::self()->documentController()->activeDocument(); if (doc && doc->url().isValid()) { baseUrl = doc->url().upUrl(); } } TemplateClassAssistant* assistant = new TemplateClassAssistant(QApplication::activeWindow(), baseUrl); assistant->setAttribute(Qt::WA_DeleteOnClose); assistant->show(); } FileTemplatesPlugin::TemplateType FileTemplatesPlugin::determineTemplateType(const KUrl& url) { QDir dir(url.toLocalFile()); /* * Search for a description file in the url's directory. * If it is not found there, try cascading up a maximum of 5 directories. */ int level = 0; while (dir.cdUp() && level < 5) { QStringList filters; filters << "*.kdevtemplate" << "*.desktop"; foreach (const QString& entry, dir.entryList(filters)) { kDebug() << "Trying entry" << entry; /* * This logic is not perfect, but it works for most cases. * * Project template description files usually have the suffix * ".kdevtemplate", so those are easy to find. For project templates, * all the files in the directory are template files. * * On the other hand, file templates use the generic suffix ".desktop". * Fortunately, those explicitly list input and output files, so we * only match the explicitly listed files */ if (entry.endsWith(".kdevtemplate")) { return ProjectTemplate; } KConfig* config = new KConfig(dir.absoluteFilePath(entry), KConfig::SimpleConfig); KConfigGroup group = config->group("General"); kDebug() << "General group keys:" << group.keyList(); if (!group.hasKey("Name") || !group.hasKey("Category")) { continue; } if (group.hasKey("Files")) { kDebug() << "Group has files " << group.readEntry("Files", QStringList()); foreach (const QString& outputFile, group.readEntry("Files", QStringList())) { if (dir.absoluteFilePath(config->group(outputFile).readEntry("File")) == url.toLocalFile()) { return FileTemplate; } } } if (group.hasKey("ShowFilesAfterGeneration")) { return ProjectTemplate; } } ++level; } return NoTemplate; } void FileTemplatesPlugin::previewTemplate() { QAction* action = qobject_cast(sender()); if (!action || !action->data().value().isValid()) { return; } TemplatePreviewToolView* preview = qobject_cast(core()->uiController()->findToolView(i18n("Template Preview"), m_toolView)); if (!preview) { return; } core()->documentController()->activateDocument(core()->documentController()->openDocument(action->data().value())); }