File indexing completed on 2024-05-05 04:39:24
0001 /* 0002 SPDX-FileCopyrightText: 2009 Aleix Pol <aleixpol@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "cmakecommandscontents.h" 0008 #include <interfaces/iruntimecontroller.h> 0009 #include <interfaces/iruntime.h> 0010 #include <interfaces/icore.h> 0011 #include <interfaces/idocumentation.h> 0012 #include <interfaces/idocumentationcontroller.h> 0013 #include "cmakebuilderconfig.h" 0014 #include "cmakedoc.h" 0015 #include <QProcess> 0016 #include <KLocalizedString> 0017 0018 #include <array> 0019 0020 static const std::array<QString, 6> args = { 0021 QStringLiteral("--help-command"), 0022 QStringLiteral("--help-variable"), 0023 QStringLiteral("--help-module"), 0024 QStringLiteral("--help-property"), 0025 QStringLiteral("--help-policy"), 0026 QString(), 0027 }; 0028 static const std::array<QString, 5> modules = { 0029 i18nc("@item cmake", "Commands"), 0030 i18nc("@item cmake", "Variables"), 0031 i18nc("@item cmake", "Modules"), 0032 i18nc("@item cmake", "Properties"), 0033 i18nc("@item cmake", "Policies"), 0034 }; 0035 0036 CMakeCommandsContents::CMakeCommandsContents(QObject* parent) 0037 : QAbstractItemModel(parent) 0038 , m_namesForType(CMakeDocumentation::EOType) 0039 { 0040 for (int i = 0; i <= CMakeDocumentation::Policy; ++i) { 0041 const QStringList params = { args[i]+QStringLiteral("-list") }; 0042 0043 auto* process = new QProcess(this); 0044 process->setProperty("type", i); 0045 process->setProgram(CMakeBuilderSettings::self()->cmakeExecutable().toLocalFile()); 0046 process->setArguments(params); 0047 KDevelop::ICore::self()->runtimeController()->currentRuntime()->startProcess(process); 0048 0049 connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), 0050 this, &CMakeCommandsContents::processOutput); 0051 } 0052 } 0053 0054 void CMakeCommandsContents::processOutput(int code) 0055 { 0056 auto* process = qobject_cast<QProcess*>(sender()); 0057 if (code!=0) { 0058 qDebug() << "failed" << process; 0059 return; 0060 } 0061 0062 const CMakeDocumentation::Type type = CMakeDocumentation::Type(process->property("type").toInt()); 0063 0064 QTextStream stream(process); 0065 QString line = stream.readLine(); //discard first line 0066 QVector<QString> names; 0067 while(stream.readLineInto(&line)) { 0068 names += line; 0069 } 0070 0071 beginInsertRows(index(type, 0, {}), 0, names.count()-1); 0072 for (auto& name : qAsConst(names)) { 0073 m_typeForName.insert(name, type); 0074 } 0075 m_namesForType[type] = names; 0076 endInsertRows(); 0077 } 0078 0079 CMakeDocumentation::Type CMakeCommandsContents::typeFor(const QString& identifier) const 0080 { 0081 //TODO can do much better 0082 if(m_typeForName.contains(identifier)) { 0083 return m_typeForName[identifier]; 0084 } else if(m_typeForName.contains(identifier.toLower())) { 0085 return m_typeForName[identifier.toLower()]; 0086 } else if(m_typeForName.contains(identifier.toUpper())) { 0087 return m_typeForName[identifier.toUpper()]; 0088 } 0089 return CMakeDocumentation::EOType; 0090 } 0091 0092 QString CMakeCommandsContents::descriptionForIdentifier(const QString& id, CMakeDocumentation::Type t) const 0093 { 0094 QString desc; 0095 if(args[t].size() != 0) { 0096 desc = CMake::executeProcess(CMakeBuilderSettings::self()->cmakeExecutable().toLocalFile(), { args[t], id.simplified() }); 0097 desc.remove(QLatin1String(":ref:")); 0098 0099 const QString rst2html = QStandardPaths::findExecutable(QStringLiteral("rst2html")); 0100 if (rst2html.isEmpty()) { 0101 desc = (QLatin1String("<html><body><pre><code>") + desc.toHtmlEscaped() + QLatin1String("</code></pre>") 0102 + i18n("<p>For better CMake documentation rendering, install rst2html.</p>") 0103 + QLatin1String("</body></html>")); 0104 } else { 0105 QProcess p; 0106 p.start(rst2html, { QStringLiteral("--no-toc-backlinks"), QStringLiteral("--quiet") }); 0107 p.write(desc.toUtf8()); 0108 p.closeWriteChannel(); 0109 p.waitForFinished(); 0110 desc = QString::fromUtf8(p.readAllStandardOutput()); 0111 } 0112 } 0113 0114 return desc; 0115 } 0116 0117 0118 void CMakeCommandsContents::showItemAt(const QModelIndex& idx) const 0119 { 0120 if(idx.isValid() && int(idx.internalId())>=0) { 0121 QString desc=CMakeDoc::s_provider->descriptionForIdentifier(idx.data().toString(), 0122 (ICMakeDocumentation::Type) idx.parent().row()); 0123 CMakeDoc::Ptr doc(new CMakeDoc(idx.data().toString(), desc)); 0124 0125 KDevelop::ICore::self()->documentationController()->showDocumentation(doc); 0126 } 0127 } 0128 0129 QModelIndex CMakeCommandsContents::parent(const QModelIndex& child) const 0130 { 0131 if(child.isValid() && child.column()==0 && int(child.internalId())>=0) 0132 return createIndex(child.internalId(),0, -1); 0133 return QModelIndex(); 0134 } 0135 0136 QModelIndex CMakeCommandsContents::index(int row, int column, const QModelIndex& parent) const 0137 { 0138 if(row<0 || column!=0) 0139 return QModelIndex(); 0140 if(!parent.isValid() && row==ICMakeDocumentation::EOType) 0141 return QModelIndex(); 0142 0143 return createIndex(row,column, int(parent.isValid() ? parent.row() : -1)); 0144 } 0145 0146 int CMakeCommandsContents::rowCount(const QModelIndex& parent) const 0147 { 0148 if(!parent.isValid()) 0149 return ICMakeDocumentation::EOType; 0150 else if(int(parent.internalId())<0) { 0151 int ss=names((ICMakeDocumentation::Type) parent.row()).size(); 0152 return ss; 0153 } 0154 return 0; 0155 } 0156 0157 QVariant CMakeCommandsContents::data(const QModelIndex& index, int role) const 0158 { 0159 if (index.isValid()) { 0160 if(role==Qt::DisplayRole) { 0161 int internal(index.internalId()); 0162 if(internal>=0) 0163 return m_namesForType[internal].count() > index.row() ? QVariant(m_namesForType[internal].at(index.row())) : QVariant(); 0164 else 0165 return modules[index.row()]; 0166 } 0167 } 0168 return QVariant(); 0169 } 0170 0171 int CMakeCommandsContents::columnCount(const QModelIndex& /*parent*/) const 0172 { 0173 return 1; 0174 } 0175 0176 QVector<QString> CMakeCommandsContents::names(ICMakeDocumentation::Type t) const 0177 { 0178 return m_namesForType[t]; 0179 } 0180 0181 #include "moc_cmakecommandscontents.cpp"