forked from qt-creator/qt-creator
Polish the Qt plugin wizard
- Add overrides for pure virtual base class functions - Modernize C++ in the generated code - Do not build into the Qt installation directory by default - Rename misleading "Qt4Plugin" enum - Remove Qt 4 compatibility code - Remove some excess newlines Fixes: QTCREATORBUG-21207 Change-Id: I50641eddf9084ef3eb8199684aec639c5e5d71fc Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
#include "librarywizarddialog.h"
|
||||
|
||||
#include <utils/codegeneration.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QTextStream>
|
||||
#include <QStringList>
|
||||
@@ -35,7 +36,6 @@ namespace QmakeProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
void LibraryParameters::generateCode(QtProjectParameters:: Type t,
|
||||
const QString &projectTarget,
|
||||
const QString &headerName,
|
||||
const QString &sharedHeader,
|
||||
const QString &exportMacro,
|
||||
@@ -75,7 +75,9 @@ void LibraryParameters::generateCode(QtProjectParameters:: Type t,
|
||||
const QString namespaceIndent = Utils::writeOpeningNameSpaces(namespaceList, indent, headerStr);
|
||||
|
||||
// Class declaraction
|
||||
headerStr << '\n' << namespaceIndent << "class ";
|
||||
if (!namespaceIndent.isEmpty())
|
||||
headerStr << '\n';
|
||||
headerStr << namespaceIndent << "class ";
|
||||
if (t == QtProjectParameters::SharedLibrary && !exportMacro.isEmpty())
|
||||
headerStr << exportMacro << ' ';
|
||||
|
||||
@@ -85,30 +87,37 @@ void LibraryParameters::generateCode(QtProjectParameters:: Type t,
|
||||
headerStr << "\n{\n";
|
||||
|
||||
// Is this a QObject (plugin)
|
||||
const bool inheritsQObject = t == QtProjectParameters::Qt4Plugin;
|
||||
const bool inheritsQObject = t == QtProjectParameters::QtPlugin;
|
||||
if (inheritsQObject)
|
||||
headerStr << namespaceIndent << indent << "Q_OBJECT\n";
|
||||
if (t == QtProjectParameters::Qt4Plugin) { // Write Qt 5 plugin meta data.
|
||||
if (t == QtProjectParameters::QtPlugin) { // Write Qt plugin meta data.
|
||||
const QString qt5InterfaceName = LibraryWizardDialog::pluginInterface(baseClassName);
|
||||
if (!qt5InterfaceName.isEmpty()) {
|
||||
headerStr << "#if QT_VERSION >= 0x050000\n"
|
||||
<< namespaceIndent << indent << "Q_PLUGIN_METADATA(IID \""
|
||||
QTC_CHECK(!qt5InterfaceName.isEmpty());
|
||||
headerStr << namespaceIndent << indent << "Q_PLUGIN_METADATA(IID \""
|
||||
<< qt5InterfaceName << '"';
|
||||
if (!pluginJsonFileName.isEmpty())
|
||||
QTC_CHECK(!pluginJsonFileName.isEmpty());
|
||||
headerStr << " FILE \"" << pluginJsonFileName << '"';
|
||||
headerStr << ")\n#endif // QT_VERSION >= 0x050000\n";
|
||||
}
|
||||
headerStr << ")\n";
|
||||
}
|
||||
|
||||
headerStr << namespaceIndent << "\npublic:\n";
|
||||
if (inheritsQObject)
|
||||
headerStr << namespaceIndent << indent << unqualifiedClassName << "(QObject *parent = 0);\n";
|
||||
else
|
||||
if (inheritsQObject) {
|
||||
headerStr << namespaceIndent << indent << "explicit " << unqualifiedClassName
|
||||
<< "(QObject *parent = nullptr);\n";
|
||||
} else {
|
||||
headerStr << namespaceIndent << indent << unqualifiedClassName << "();\n";
|
||||
headerStr << namespaceIndent << "};\n\n";
|
||||
}
|
||||
if (!pureVirtualSignatures.empty()) {
|
||||
headerStr << "\nprivate:\n";
|
||||
for (const QString &signature : pureVirtualSignatures)
|
||||
headerStr << namespaceIndent << indent << signature << " override;\n";
|
||||
}
|
||||
headerStr << namespaceIndent << "};\n";
|
||||
if (!namespaceIndent.isEmpty())
|
||||
headerStr << '\n';
|
||||
Utils::writeClosingNameSpaces(namespaceList, indent, headerStr);
|
||||
if (!usePragmaOnce)
|
||||
headerStr << "#endif // " << guard << '\n';
|
||||
headerStr << "\n#endif // " << guard << '\n';
|
||||
|
||||
/// 2) Source
|
||||
QTextStream sourceStr(source);
|
||||
@@ -117,8 +126,11 @@ void LibraryParameters::generateCode(QtProjectParameters:: Type t,
|
||||
sourceStr << '\n';
|
||||
|
||||
Utils::writeOpeningNameSpaces(namespaceList, indent, sourceStr);
|
||||
if (!namespaceIndent.isEmpty())
|
||||
sourceStr << '\n';
|
||||
|
||||
// Constructor
|
||||
sourceStr << '\n' << namespaceIndent << unqualifiedClassName << "::" << unqualifiedClassName;
|
||||
sourceStr << namespaceIndent << unqualifiedClassName << "::" << unqualifiedClassName;
|
||||
if (inheritsQObject) {
|
||||
sourceStr << "(QObject *parent) :\n"
|
||||
<< namespaceIndent << indent << baseClassName << "(parent)\n";
|
||||
@@ -126,14 +138,26 @@ void LibraryParameters::generateCode(QtProjectParameters:: Type t,
|
||||
sourceStr << "()\n";
|
||||
}
|
||||
sourceStr << namespaceIndent << "{\n" << namespaceIndent << "}\n";
|
||||
for (const QString &signature : pureVirtualSignatures) {
|
||||
const int parenIndex = signature.indexOf('(');
|
||||
QTC_ASSERT(parenIndex != -1, continue);
|
||||
int nameIndex = -1;
|
||||
for (int i = parenIndex - 1; i > 0; --i) {
|
||||
if (!signature.at(i).isLetterOrNumber()) {
|
||||
nameIndex = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
QTC_ASSERT(nameIndex != -1, continue);
|
||||
sourceStr << '\n' << namespaceIndent << signature.left(nameIndex);
|
||||
if (signature.at(nameIndex - 1) != ' ')
|
||||
sourceStr << ' ';
|
||||
sourceStr << unqualifiedClassName << "::" << signature.mid(nameIndex) << '\n';
|
||||
sourceStr << namespaceIndent << "{\n" << indent
|
||||
<< "static_assert(false, \"You need to implement this function\");\n}\n";
|
||||
}
|
||||
|
||||
Utils::writeClosingNameSpaces(namespaceList, indent, sourceStr);
|
||||
|
||||
if (t == QtProjectParameters::Qt4Plugin) { // Qt 4 plugin export
|
||||
sourceStr << "\n#if QT_VERSION < 0x050000\n"
|
||||
<< "Q_EXPORT_PLUGIN2(" << projectTarget << ", " << className << ")\n"
|
||||
<< "#endif // QT_VERSION < 0x050000\n";
|
||||
}
|
||||
}
|
||||
|
||||
QString LibraryParameters::generateSharedHeader(const QString &globalHeaderFileName,
|
||||
|
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "qtprojectparameters.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
namespace QmakeProjectManager {
|
||||
namespace Internal {
|
||||
@@ -38,7 +38,6 @@ struct LibraryParameters {
|
||||
|
||||
// generate class
|
||||
void generateCode(QtProjectParameters:: Type t,
|
||||
const QString &projectTarget,
|
||||
const QString &headerName,
|
||||
const QString &sharedHeader,
|
||||
const QString &exportMacro,
|
||||
@@ -58,6 +57,7 @@ struct LibraryParameters {
|
||||
QString baseClassName;
|
||||
QString sourceFileName;
|
||||
QString headerFileName;
|
||||
QStringList pureVirtualSignatures;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -63,12 +63,15 @@ Core::BaseFileWizard *LibraryWizard::create(QWidget *parent, const Core::WizardD
|
||||
return dialog;
|
||||
}
|
||||
|
||||
static void writeLinuxProFile(QTextStream &str)
|
||||
static void writeLinuxProFile(QTextStream &str, const QtProjectParameters ¶ms)
|
||||
{
|
||||
str << "\n"
|
||||
"unix {\n"
|
||||
" target.path = /usr/lib\n"
|
||||
" INSTALLS += target\n"
|
||||
"unix {\n";
|
||||
if (!params.targetDirectory.isEmpty())
|
||||
str << " target.path = " << params.targetDirectory << '\n';
|
||||
else
|
||||
str << " target.path = /usr/lib\n";
|
||||
str << " INSTALLS += target\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
@@ -94,7 +97,7 @@ Core::GeneratedFiles LibraryWizard::generateFiles(const QWizard *w,
|
||||
const QString headerFileName = Utils::FileName::fromString(headerFileFullName).fileName();
|
||||
QString pluginJsonFileFullName;
|
||||
QString pluginJsonFileName;
|
||||
if (projectParams.type == QtProjectParameters::Qt4Plugin) {
|
||||
if (projectParams.type == QtProjectParameters::QtPlugin) {
|
||||
pluginJsonFileFullName = buildFileName(projectPath, projectParams.fileName, QLatin1String("json"));
|
||||
pluginJsonFileName = Utils::FileName::fromString(pluginJsonFileFullName).fileName();
|
||||
}
|
||||
@@ -114,7 +117,7 @@ Core::GeneratedFiles LibraryWizard::generateFiles(const QWizard *w,
|
||||
|
||||
// Generate code
|
||||
QString headerContents, sourceContents;
|
||||
params.generateCode(projectParams.type, projectParams.fileName, headerFileName,
|
||||
params.generateCode(projectParams.type, headerFileName,
|
||||
globalHeaderFileName, sharedLibExportMacro, pluginJsonFileName,
|
||||
/* indentation*/ 4, usePragmaOnce, &headerContents, &sourceContents);
|
||||
|
||||
@@ -141,7 +144,7 @@ Core::GeneratedFiles LibraryWizard::generateFiles(const QWizard *w,
|
||||
proStr << " \\\n " << globalHeaderFileName << " \n";
|
||||
if (!pluginJsonFileName.isEmpty())
|
||||
proStr << "\nDISTFILES += " << pluginJsonFileName << " \n";
|
||||
writeLinuxProFile(proStr);
|
||||
writeLinuxProFile(proStr, projectParams);
|
||||
}
|
||||
profile.setContents(profileContents);
|
||||
rc.push_back(profile);
|
||||
|
@@ -44,27 +44,38 @@ namespace Internal {
|
||||
struct PluginBaseClasses {
|
||||
const char *name;
|
||||
const char *module;
|
||||
QStringList pureVirtuals;
|
||||
|
||||
// blank separated list or 0
|
||||
const char *dependentModules;
|
||||
const char *targetDirectory;
|
||||
const char *pluginInterface;
|
||||
};
|
||||
using QSL = QStringList;
|
||||
|
||||
static const PluginBaseClasses pluginBaseClasses[] =
|
||||
{
|
||||
{"QAccessiblePlugin", "QtGui", "QtCore", "accessible", "QAccessibleFactoryInterface"},
|
||||
{"QDecorationPlugin", "QtGui", "QtCore", nullptr, nullptr}, // Qt 4 only.
|
||||
{"QGenericPlugin", "QtGui", "QtCore", "generic", "QGenericPluginFactoryInterface"},
|
||||
{"QIconEnginePluginV2", "QtGui", "QtCore", "imageformats", nullptr}, // Qt 4 only.
|
||||
{"QIconEnginePlugin", "QtGui", "QtCore", "imageformats", "QIconEngineFactoryInterface"},
|
||||
{"QImageIOPlugin", "QtGui", "QtCore", "imageformats", "QImageIOHandlerFactoryInterface"},
|
||||
{"QScriptExtensionPlugin", "QtScript", "QtCore", nullptr, "QScriptExtensionInterface"},
|
||||
{"QSqlDriverPlugin", "QtSql", "QtCore", "sqldrivers", "QSqlDriverFactoryInterface"},
|
||||
{"QStylePlugin", "QtGui", "QtCore", "styles", "QStyleFactoryInterface"},
|
||||
{"QTextCodecPlugin", "QtCore", nullptr, "codecs", nullptr} // Qt 4 only.
|
||||
{"QAccessiblePlugin", "QtGui",
|
||||
QSL{"QAccessibleInterface * create(const QString &key, QObject *object)"},
|
||||
"QtCore", "accessible", "QAccessibleFactoryInterface"},
|
||||
{"QGenericPlugin", "QtGui", QSL{"QObject *create(const QString &name, const QString &spec)"},
|
||||
"QtCore", "generic", "QGenericPluginFactoryInterface"},
|
||||
{"QIconEnginePlugin", "QtGui", QSL{"QIconEngine *create(const QString &filename)"},
|
||||
"QtCore", "imageformats", "QIconEngineFactoryInterface"},
|
||||
{"QImageIOPlugin", "QtGui",
|
||||
QSL{"QImageIOPlugin::Capabilities capabilities(QIODevice *device, const QByteArray &format) const",
|
||||
"QImageIOHandler *create(QIODevice *device, const QByteArray &format) const"},
|
||||
"QtCore", "imageformats", "QImageIOHandlerFactoryInterface"},
|
||||
{"QScriptExtensionPlugin", "QtScript",
|
||||
QSL{"void initialize(const QString &key, QScriptEngine *engine)", "QStringList keys() const"},
|
||||
"QtCore", nullptr, "QScriptExtensionInterface"},
|
||||
{"QSqlDriverPlugin", "QtSql", QSL{"QSqlDriver *create(const QString &key)"},
|
||||
"QtCore", "sqldrivers", "QSqlDriverFactoryInterface"},
|
||||
{"QStylePlugin", "QtWidgets", QSL{"QStyle *create(const QString &key)"},
|
||||
"QtCore", "styles", "QStyleFactoryInterface"},
|
||||
};
|
||||
|
||||
enum { defaultPluginBaseClass = 2 };
|
||||
enum { defaultPluginBaseClass = 1 };
|
||||
|
||||
static const PluginBaseClasses *findPluginBaseClass(const QString &name)
|
||||
{
|
||||
@@ -114,7 +125,7 @@ LibraryIntroPage::LibraryIntroPage(QWidget *parent) :
|
||||
m_typeCombo->addItem(LibraryWizardDialog::tr("Statically Linked Library"),
|
||||
QVariant(QtProjectParameters::StaticLibrary));
|
||||
m_typeCombo->addItem(LibraryWizardDialog::tr("Qt Plugin"),
|
||||
QVariant(QtProjectParameters::Qt4Plugin));
|
||||
QVariant(QtProjectParameters::QtPlugin));
|
||||
insertControl(0, new QLabel(LibraryWizardDialog::tr("Type")), m_typeCombo);
|
||||
}
|
||||
|
||||
@@ -197,7 +208,7 @@ bool LibraryWizardDialog::isModulesPageSkipped() const
|
||||
{
|
||||
// When leaving the intro or target page, the modules page is skipped
|
||||
// in the case of a plugin since it knows its dependencies by itself.
|
||||
return type() == QtProjectParameters::Qt4Plugin;
|
||||
return type() == QtProjectParameters::QtPlugin;
|
||||
}
|
||||
|
||||
int LibraryWizardDialog::skipModulesPageIfNeeded() const
|
||||
@@ -249,7 +260,7 @@ QtProjectParameters LibraryWizardDialog::parameters() const
|
||||
rc.type = type();
|
||||
rc.fileName = projectName();
|
||||
rc.path = path();
|
||||
if (rc.type == QtProjectParameters::Qt4Plugin) {
|
||||
if (rc.type == QtProjectParameters::QtPlugin) {
|
||||
// Plugin: Dependencies & Target directory
|
||||
if (const PluginBaseClasses *plb = findPluginBaseClass(m_filesPage->baseClassName())) {
|
||||
rc.selectedModules = pluginDependencies(plb);
|
||||
@@ -277,7 +288,7 @@ void LibraryWizardDialog::slotCurrentIdChanged(int id)
|
||||
void LibraryWizardDialog::setupFilesPage()
|
||||
{
|
||||
switch (type()) {
|
||||
case QtProjectParameters::Qt4Plugin:
|
||||
case QtProjectParameters::QtPlugin:
|
||||
if (!m_pluginBaseClassesInitialized) {
|
||||
if (debugLibWizard)
|
||||
qDebug("initializing for plugins");
|
||||
@@ -309,8 +320,15 @@ LibraryParameters LibraryWizardDialog::libraryParameters() const
|
||||
{
|
||||
LibraryParameters rc;
|
||||
rc.className = m_filesPage->className();
|
||||
rc.baseClassName = type() == QtProjectParameters::Qt4Plugin ?
|
||||
m_filesPage->baseClassName() : QString();
|
||||
if (type() == QtProjectParameters::QtPlugin) {
|
||||
rc.baseClassName = m_filesPage->baseClassName();
|
||||
for (const PluginBaseClasses &c : pluginBaseClasses) {
|
||||
if (QLatin1String(c.name) == rc.baseClassName) {
|
||||
rc.pureVirtualSignatures = c.pureVirtuals;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rc.sourceFileName = m_filesPage->sourceFileName();
|
||||
rc.headerFileName = m_filesPage->headerFileName();
|
||||
return rc;
|
||||
|
@@ -100,14 +100,14 @@ void QtProjectParameters::writeProFile(QTextStream &str) const
|
||||
case SharedLibrary:
|
||||
str << "TEMPLATE = lib\n\nDEFINES += " << libraryMacro(fileName) << '\n';
|
||||
break;
|
||||
case Qt4Plugin:
|
||||
case QtPlugin:
|
||||
str << "TEMPLATE = lib\nCONFIG += plugin\n";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!targetDirectory.isEmpty())
|
||||
if (!targetDirectory.isEmpty() && !targetDirectory.contains("QT_INSTALL_"))
|
||||
str << "\nDESTDIR = " << targetDirectory << '\n';
|
||||
|
||||
if (qtVersionSupport != SupportQt4Only) {
|
||||
|
@@ -42,7 +42,7 @@ QString createMacro(const QString &name, const QString &suffix);
|
||||
// write a .pro-file section.
|
||||
|
||||
struct QtProjectParameters {
|
||||
enum Type { ConsoleApp, GuiApp, StaticLibrary, SharedLibrary, Qt4Plugin, EmptyProject };
|
||||
enum Type { ConsoleApp, GuiApp, StaticLibrary, SharedLibrary, QtPlugin, EmptyProject };
|
||||
enum QtVersionSupport { SupportQt4And5, SupportQt4Only, SupportQt5Only };
|
||||
enum Flags { WidgetsRequiredFlag = 0x1 };
|
||||
|
||||
|
Reference in New Issue
Block a user