8#include <customwidgetsinfo.h>
15#include <QtCore/qdir.h>
16#include <QtCore/qfileinfo.h>
17#include <QtCore/qtextstream.h>
23using namespace Qt::StringLiterals;
62static void insertClass(
const QString &module,
const QString &className,
63 WriteImports::ClassesPerModule *c)
65 auto usedIt = c->find(module);
66 if (usedIt == c->end())
67 c->insert(module, {className});
68 else if (!usedIt.value().contains(className))
69 usedIt.value().append(className);
75 std::sort(classList.begin(), classList.end());
77 const qsizetype size = classList.size();
80 for (qsizetype i = 0; i < size; ++i) {
82 str << (i % 4 == 0 ?
",\n " :
", ");
83 QString name = language::fixClassName(classList.at(i));
84 if (
const auto dotPos = name.indexOf(u'.'); dotPos != -1)
85 name.truncate(dotPos);
92static void formatClasses(QTextStream &str,
const WriteImports::ClassesPerModule &c,
93 bool useStarImports =
false,
94 const QByteArray &modulePrefix = {})
96 for (
auto it = c.cbegin(), end = c.cend(); it != end; ++it) {
97 str <<
"from " << modulePrefix << it.key() <<
" import ";
99 str <<
"* # type: ignore";
101 formatImportClasses(str, it.value());
109 for (
const auto &e : classInfoEntries())
110 m_classToModule.insert(QLatin1StringView(e.klass), QLatin1StringView(e.module));
117 auto &output = uic()->output();
118 const bool useStarImports = uic()->driver()->option().useStarImports;
120 const QByteArray qtPrefix = QByteArrayLiteral(
"PySide")
121 + QByteArray::number(QT_VERSION_MAJOR) +
'.';
123 formatClasses(output, m_qtClasses, useStarImports, qtPrefix);
125 if (!m_customWidgets.isEmpty() || !m_plainCustomWidgets.isEmpty()) {
127 formatClasses(output, m_customWidgets, useStarImports);
128 for (
const auto &w : m_plainCustomWidgets)
129 output <<
"import " << w <<
'\n';
132 if (
auto *resources = node->elementResources()) {
133 const auto &includes = resources->elementInclude();
134 for (
auto *include : includes) {
135 if (include->hasAttributeLocation())
136 writeResourceImport(include->attributeLocation());
142QString
WriteImports::resourceAbsolutePath(QString resource)
const
147 const auto &options = uic()->option();
148 if (!options.inputFile.isEmpty() && !options.pythonRoot.isEmpty()) {
149 resource = QDir::cleanPath(QFileInfo(options.inputFile).canonicalPath() + u'/' + resource);
150 if (resource.size() > options.pythonRoot.size())
151 resource.remove(0, options.pythonRoot.size() + 1);
154 while (resource.startsWith(u"../"))
155 resource.remove(0, 3);
156 resource.replace(u'/', u'.');
160void WriteImports::writeResourceImport(
const QString &module)
162 const auto &options = uic()->option();
163 auto &str = uic()->output();
165 QString resource = QDir::cleanPath(module);
166 if (resource.endsWith(u".qrc"))
168 const qsizetype basePos = resource.lastIndexOf(u'/') + 1;
171 if (options.rcPrefix)
172 resource.insert(basePos, u"rc_");
174 resource.append(u"_rc");
176 switch (options.pythonResourceImport) {
177 case Option::PythonResourceImport::Default:
178 str <<
"import " << QStringView{resource}.sliced(basePos) <<
'\n';
180 case Option::PythonResourceImport::FromDot:
181 str <<
"from . import " << QStringView{resource}.sliced(basePos) <<
'\n';
183 case Option::PythonResourceImport::Absolute:
184 str <<
"import " << resourceAbsolutePath(resource) <<
'\n';
189void WriteImports::doAdd(
const QString &className,
const DomCustomWidget *dcw)
192 if (cwi->extends(className,
"QListWidget"))
194 else if (cwi->extends(className,
"QTreeWidget"))
196 else if (cwi->extends(className,
"QTableWidget"))
199 if (dcw !=
nullptr) {
200 addPythonCustomWidget(className, dcw);
204 if (!addQtClass(className))
205 qWarning(
"WriteImports::add(): Unknown Qt class %s",
qPrintable(className));
211 if (className == u"QVariant" || className == u"Qt")
214 const auto moduleIt = m_classToModule.constFind(className);
215 const bool result = moduleIt != m_classToModule.cend();
217 insertClass(moduleIt.value(), className, &m_qtClasses);
221void WriteImports::addPythonCustomWidget(
const QString &className,
const DomCustomWidget *node)
223 if (addQtClass(className))
228 if (!node->elementHeader() || node->elementHeader()->text().isEmpty()) {
229 m_plainCustomWidgets.append(className);
231 QString modulePath = node->elementHeader()->text();
233 modulePath.replace(u'/', u'.');
235 if (modulePath.endsWith(
".h"_L1, Qt::CaseInsensitive))
237 else if (modulePath.endsWith(
".hh"_L1))
239 else if (modulePath.endsWith(
".hpp"_L1))
241 insertClass(modulePath, className, &m_customWidgets);
247 switch (node->kind()) {
248 case DomProperty::Enum:
249 addEnumBaseClass(node->elementEnum());
251 case DomProperty::Set:
252 addEnumBaseClass(node->elementSet());
264 const auto colonPos = v.indexOf(u"::");
266 const QString base = v.left(colonPos);
267 if (base.startsWith(u'Q') && base != u"Qt")
void acceptUI(DomUI *node) override
void acceptProperty(DomProperty *node) override
WriteIncludesBase(Uic *uic)
void acceptUI(DomUI *node) override
void acceptProperty(DomProperty *node) override
static void formatImportClasses(QTextStream &str, QStringList classList)
static void insertClass(const QString &module, const QString &className, WriteImports::ClassesPerModule *c)
static void formatClasses(QTextStream &str, const WriteImports::ClassesPerModule &c, bool useStarImports=false, const QByteArray &modulePrefix={})
static WriteImports::ClassesPerModule defaultClasses()
Combined button and popup list for selecting options.
const QString & asString(const QString &s)
#define qPrintable(string)
#define QStringLiteral(str)