diff --git a/share/qtcreator/templates/wizards/classes/cpp/file.h b/share/qtcreator/templates/wizards/classes/cpp/file.h index aa2fa7faaf5..67e4dfd4d1c 100644 --- a/share/qtcreator/templates/wizards/classes/cpp/file.h +++ b/share/qtcreator/templates/wizards/classes/cpp/file.h @@ -6,6 +6,7 @@ #define %{GUARD} @endif +%{JS: Cpp.includeStatement('%{Base}', Util.preferredSuffix('text/x-c++hdr'), ['QObject', 'QWidget', 'QMainWindow', 'QQuickItem', 'QSharedData'], '%{TargetPath}')}\ %{JS: QtSupport.qtIncludes([ ( '%{IncludeQObject}' ) ? 'QtCore/%{IncludeQObject}' : '', ( '%{IncludeQWidget}' ) ? 'QtGui/%{IncludeQWidget}' : '', ( '%{IncludeQMainWindow}' ) ? 'QtGui/%{IncludeQMainWindow}' : '', diff --git a/src/plugins/cpptools/cpptoolsjsextension.cpp b/src/plugins/cpptools/cpptoolsjsextension.cpp index 4c283fc644f..03a0d3df99d 100644 --- a/src/plugins/cpptools/cpptoolsjsextension.cpp +++ b/src/plugins/cpptools/cpptoolsjsextension.cpp @@ -29,10 +29,15 @@ #include +#include +#include +#include + #include #include #include +#include #include namespace CppTools { @@ -113,5 +118,69 @@ QString CppToolsJsExtension::closeNamespaces(const QString &klass) const return result; } +QString CppToolsJsExtension::includeStatement( + const QString &fullyQualifiedClassName, + const QString &suffix, + const QString &specialClasses, + const QString &pathOfIncludingFile + ) +{ + if (fullyQualifiedClassName.isEmpty()) + return {}; + const QString className = parts(fullyQualifiedClassName).last(); + if (className.isEmpty() || specialClasses.contains(className)) + return {}; + if (className.startsWith('Q') && className.length() > 2 && className.at(1).isUpper()) + return "#include <" + className + ">\n"; + const auto withUnderScores = [&className] { + QString baseName = className; + baseName[0] = baseName[0].toLower(); + for (int i = 1; i < baseName.length(); ++i) { + if (baseName[i].isUpper()) { + baseName.insert(i, '_'); + baseName[i + 1] = baseName[i + 1].toLower(); + ++i; + } + } + return baseName; + }; + QStringList candidates{className + '.' + suffix}; + bool hasUpperCase = false; + bool hasLowerCase = false; + for (int i = 0; i < className.length() && (!hasUpperCase || !hasLowerCase); ++i) { + if (className.at(i).isUpper()) + hasUpperCase = true; + if (className.at(i).isLower()) + hasLowerCase = true; + } + if (hasUpperCase) + candidates << className.toLower() + '.' + suffix; + if (hasUpperCase && hasLowerCase) + candidates << withUnderScores() + '.' + suffix; + candidates.removeDuplicates(); + using namespace ProjectExplorer; + const auto nodeMatchesFileName = [&candidates](Node *n) { + if (const FileNode * const fileNode = n->asFileNode()) { + if (fileNode->fileType() == FileType::Header + && candidates.contains(fileNode->filePath().fileName())) { + return true; + } + } + return false; + }; + for (const Project * const p : SessionManager::projects()) { + const Node *theNode = p->rootProjectNode()->findNode(nodeMatchesFileName); + if (theNode) { + const bool sameDir = pathOfIncludingFile == theNode->filePath().toFileInfo().path(); + return QString("#include ") + .append(sameDir ? '"' : '<') + .append(theNode->filePath().fileName()) + .append(sameDir ? '"' : '>') + .append('\n'); + } + } + return {}; +} + } // namespace Internal } // namespace CppTools diff --git a/src/plugins/cpptools/cpptoolsjsextension.h b/src/plugins/cpptools/cpptoolsjsextension.h index b5281910337..065e0ca8d5e 100644 --- a/src/plugins/cpptools/cpptoolsjsextension.h +++ b/src/plugins/cpptools/cpptoolsjsextension.h @@ -55,6 +55,14 @@ public: Q_INVOKABLE QString classToHeaderGuard(const QString &klass, const QString &extension) const; Q_INVOKABLE QString openNamespaces(const QString &klass) const; Q_INVOKABLE QString closeNamespaces(const QString &klass) const; + + // Find header file for class. + Q_INVOKABLE QString includeStatement( + const QString &fullyQualifiedClassName, + const QString &suffix, + const QString &specialClasses, + const QString &pathOfIncludingFile + ); }; } // namespace Internal