/*************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Qt Software Information (qt-info@nokia.com) ** ** ** Non-Open Source Usage ** ** Licensees may use this file in accordance with the Qt Beta Version ** License Agreement, Agreement version 2.2 provided with the Software or, ** alternatively, in accordance with the terms contained in a written ** agreement between you and Nokia. ** ** GNU General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU General ** Public License versions 2.0 or 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the packaging ** of this file. Please review the following information to ensure GNU ** General Public Licensing requirements will be met: ** ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and ** http://www.gnu.org/copyleft/gpl.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt GPL Exception ** version 1.3, included in the file GPL_EXCEPTION.txt in this package. ** ***************************************************************************/ #include "formtemplatewizardpage.h" #include "formeditorw.h" #include #include #include #include #include #include #include #include #include #ifdef USE_XSLT # include #else # include #endif namespace Designer { namespace Internal { // ----------------- FormTemplateWizardPagePage FormTemplateWizardPagePage::FormTemplateWizardPagePage(QWidget * parent) : QWizardPage(parent), m_newFormWidget(QDesignerNewFormWidgetInterface::createNewFormWidget(FormEditorW::instance()->designerEditor())), m_templateSelected(m_newFormWidget->hasCurrentTemplate()) { setTitle(tr("Choose a form template")); QVBoxLayout *layout = new QVBoxLayout; connect(m_newFormWidget, SIGNAL(currentTemplateChanged(bool)), this, SLOT(slotCurrentTemplateChanged(bool))); connect(m_newFormWidget, SIGNAL(templateActivated()), this, SIGNAL(templateActivated())); layout->addWidget(m_newFormWidget); setLayout(layout); } bool FormTemplateWizardPagePage::isComplete() const { return m_templateSelected; } void FormTemplateWizardPagePage::slotCurrentTemplateChanged(bool templateSelected) { if (m_templateSelected == templateSelected) return; m_templateSelected = templateSelected; emit completeChanged(); } bool FormTemplateWizardPagePage::validatePage() { QString errorMessage; m_templateContents = m_newFormWidget->currentTemplate(&errorMessage); if (m_templateContents.isEmpty()) { QMessageBox::critical(this, tr("%1 - Error").arg(title()), errorMessage); return false; } return true; } QString FormTemplateWizardPagePage::stripNamespaces(const QString &className) { QString rc = className; const int namespaceIndex = rc.lastIndexOf(QLatin1String("::")); if (namespaceIndex != -1) rc.remove(0, namespaceIndex + 2); return rc; } bool FormTemplateWizardPagePage::getUIXmlData(const QString &uiXml, QString *formBaseClass, QString *uiClassName) { // Parse UI xml to determine // 1) The ui class name from "Designer::Internal::FormClassWizardPage" // 2) the base class from: widget class="QWizardPage"... QXmlStreamReader reader(uiXml); while (!reader.atEnd()) { if (reader.readNext() == QXmlStreamReader::StartElement) { if (reader.name() == QLatin1String("class")) { *uiClassName = reader.readElementText(); } else { if (reader.name() == QLatin1String("widget")) { const QXmlStreamAttributes attrs = reader.attributes(); *formBaseClass = reader.attributes().value(QLatin1String("class")).toString(); return !uiClassName->isEmpty() && !formBaseClass->isEmpty(); } } } } return false; } #ifdef USE_XSLT // Change the UI class name in UI xml: This occurs several times, as contents // of the element, as name of the first element, and possibly // in the signal/slot connections static const char *classNameChangingSheetFormatC = "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" " \n" " \n" " \n" "\n" "\n" "\n" "\n" " \n" " %1\n" " \n" "\n" "\n" "\n" "\n" "\n" "%1\n" "\n" "\n" "\n" "\n" "\n" " \n" " %1\n" " \n" "\n" "\n" " \n" " %1\n" " \n" "\n" "\n"; QString FormTemplateWizardPagePage::changeUiClassName(const QString &uiXml, const QString &newUiClassName) { // Prepare I/O: Sheet const QString xsltSheet = QString::fromLatin1(classNameChangingSheetFormatC).arg(newUiClassName); QByteArray xsltSheetBA = xsltSheet.toUtf8(); QBuffer xsltSheetBuffer(&xsltSheetBA); xsltSheetBuffer.open(QIODevice::ReadOnly); // Prepare I/O: Xml QByteArray xmlBA = uiXml.toUtf8(); QBuffer xmlBuffer(&xmlBA); xmlBuffer.open(QIODevice::ReadOnly); // Prepare I/O: output QBuffer outputBuffer; outputBuffer.open(QIODevice::WriteOnly); // Run query QXmlQuery query(QXmlQuery::XSLT20); query.setFocus(&xmlBuffer); query.setQuery(&xsltSheetBuffer); if (!query.evaluateTo(&outputBuffer)) { qWarning("Unable to change the ui class name in a form template.\n%s\nUsing:\n%s\n", xmlBA.constData(), xsltSheetBA.constData()); return uiXml; } outputBuffer.close(); return QString::fromUtf8(outputBuffer.data()); } #else // Change the contents of a DOM element to a new value if it matches // a predicate template bool changeDomElementContents(const QDomElement &element, Predicate p, const QString &newValue, QString *ptrToOldValue = 0) { // Find text in "text" const QDomNodeList children = element.childNodes(); if (children.size() != 1) return false; const QDomNode first = children.at(0); if (first.nodeType() != QDomNode::TextNode) return false; QDomCharacterData data = first.toCharacterData(); const QString oldValue = data.data(); if (p(oldValue)) { if (ptrToOldValue) *ptrToOldValue = oldValue; data.setData(newValue); return true; } return false; } namespace { bool truePredicate(const QString &) { return true; } // Predicate that matches a string value class MatchPredicate { public: MatchPredicate(const QString &m) : m_match(m) {} bool operator()(const QString &s) const { return s == m_match; } private: const QString m_match; }; // Change and in a Dom UI list // if they match the class name passed on void changeDomConnectionList(const QDomElement &connectionsNode, const QString &oldClassName, const QString &newClassName) { const MatchPredicate oldClassPredicate(oldClassName); const QString senderTag = QLatin1String("sender"); const QString receiverTag = QLatin1String("receiver"); const QDomNodeList connections = connectionsNode.childNodes(); const int connectionsCount = connections.size(); // Loop for (int c = 0; c < connectionsCount; c++) { const QDomNodeList connectionElements = connections.at(c).childNodes(); const int connectionElementCount = connectionElements.count(); // Loop , , , for (int ce = 0; ce < connectionElementCount; ce++) { const QDomNode connectionElementNode = connectionElements.at(ce); if (connectionElementNode.isElement()) { const QDomElement connectionElement = connectionElementNode.toElement(); const QString tagName = connectionElement.tagName(); if (tagName == senderTag || tagName == receiverTag) changeDomElementContents(connectionElement, oldClassPredicate, newClassName); } } } } } // Change the UI class name in UI xml: This occurs several times, as contents // of the element, as name of the first element, and possibly // in the signal/slot connections QString FormTemplateWizardPagePage::changeUiClassName(const QString &uiXml, const QString &newUiClassName) { QDomDocument domUi; if (!domUi.setContent(uiXml)) { qWarning("Failed to parse:\n%s", uiXml.toUtf8().constData()); return uiXml; } bool firstWidgetElementFound = false; QString oldClassName; // Loop first level children. First child is const QDomNodeList children = domUi.firstChildElement().childNodes(); const QString classTag = QLatin1String("class"); const QString widgetTag = QLatin1String("widget"); const QString connectionsTag = QLatin1String("connections"); const int count = children.size(); for (int i = 0; i < count; i++) { const QDomNode node = children.at(i); if (node.isElement()) { // Replace element text QDomElement element = node.toElement(); const QString name = element.tagName(); if (name == classTag) { if (!changeDomElementContents(element, truePredicate, newUiClassName, &oldClassName)) { qWarning("Unable to change the element:\n%s", uiXml.toUtf8().constData()); return uiXml; } } else { // Replace first element name attribute if (!firstWidgetElementFound && name == widgetTag) { firstWidgetElementFound = true; const QString nameAttribute = QLatin1String("name"); if (element.hasAttribute(nameAttribute)) element.setAttribute(nameAttribute, newUiClassName); } else { // Replace , tags of dialogs. if (name == connectionsTag) changeDomConnectionList(element, oldClassName, newUiClassName); } } } } const QString rc = domUi.toString(); return rc; } #endif // USE_XSLT } // namespace Internal } // namespace Designer