Commit a4337db4 authored by Nikolai Kosjar's avatar Nikolai Kosjar
Browse files

Designer: Fix "Go to slot..." for project-less "Qt Designer Form Class"es



Task-number: QTCREATORBUG-9653
Change-Id: Ia50c295ee474d08b3fb0574a4f759a8ab901876a
Reviewed-by: default avatarFriedemann Kleint <Friedemann.Kleint@digia.com>
parent fd9293dd
......@@ -62,6 +62,11 @@ SOURCES += formeditorplugin.cpp \
qtdesignerformclasscodegenerator.cpp \
designerxmleditorwidget.cpp
equals(TEST, 1) {
SOURCES += gotoslot_test.cpp
DEFINES += SRCDIR=\\\"$$PWD\\\"
}
RESOURCES += designer.qrc
OTHER_FILES += README.txt
import qbs.base 1.0
import qbs.FileInfo
import "../QtcPlugin.qbs" as QtcPlugin
import "../../../qbs/defaults.js" as Defaults
QtcPlugin {
name: "Designer"
......@@ -72,4 +74,13 @@ QtcPlugin {
"formclasswizardparameters.cpp", "formclasswizardparameters.h",
]
}
Group {
name: "Tests"
condition: Defaults.testsEnabled(qbs)
files: [ "gotoslot_test.cpp" ]
cpp.defines: outer.concat(['SRCDIR="' + FileInfo.path(filePath) + '"'])
}
}
......@@ -50,6 +50,11 @@ public:
private:
void initializeTemplates();
private slots:
#ifdef WITH_TESTS
void test_gotoslot_withoutProject();
#endif
};
} // namespace Internal
......
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "formeditorplugin.h"
#include "formeditorw.h"
#include <coreplugin/testdatadir.h>
#include <coreplugin/editormanager/editormanager.h>
#include <cpptools/cppmodelmanager.h>
#include <cplusplus/CppDocument.h>
#include <cplusplus/Overview.h>
#include <QDesignerFormEditorInterface>
#include <QDesignerIntegrationInterface>
#include <QStringList>
#include <QtTest>
using namespace Core;
using namespace Core::Internal::Tests;
using namespace CppTools;
using namespace CPlusPlus;
using namespace Designer;
using namespace Designer::Internal;
namespace {
class MyTestDataDir : public Core::Internal::Tests::TestDataDir {
public:
MyTestDataDir(const QString &dir)
: TestDataDir(QLatin1String(SRCDIR "/../../../tests/designer/") + dir)
{}
};
bool containsSymbol(Scope *scope, const QString &functionName)
{
Overview oo;
for (int i = 0, end = scope->memberCount(); i < end; ++i) {
Symbol *symbol = scope->memberAt(i);
const QString symbolName = oo.prettyName(symbol->name());
if (symbolName == functionName)
return true;
}
return false;
}
class GoToSlotTest
{
public:
GoToSlotTest() : m_modelManager(CppModelManagerInterface::instance()) { cleanup(); }
~GoToSlotTest() { cleanup(); }
void run() const
{
MyTestDataDir testData(QLatin1String("gotoslot_withoutProject"));
const QString cppFile = testData.file(QLatin1String("form.cpp"));
const QString hFile = testData.file(QLatin1String("form.h"));
const QString uiFile = testData.file(QLatin1String("form.ui"));
const QStringList files = QStringList() << cppFile << hFile << uiFile;
const QString functionName = QLatin1String("on_pushButton_clicked");
const QString qualifiedFunctionName = QLatin1String("Form::") + functionName;
foreach (const QString &file, files)
QVERIFY(EditorManager::openEditor(file));
QCOMPARE(EditorManager::documentModel()->openedDocuments().size(), files.size());
while (!m_modelManager->snapshot().contains(cppFile)
|| !m_modelManager->snapshot().contains(hFile)) {
QApplication::processEvents();
}
// Checks before
Document::Ptr cppDocumentBefore = m_modelManager->snapshot().document(cppFile);
QCOMPARE(cppDocumentBefore->globalSymbolCount(), 2U);
QVERIFY(!containsSymbol(cppDocumentBefore->globalNamespace(), qualifiedFunctionName));
Document::Ptr hDocumentBefore = m_modelManager->snapshot().document(hFile);
QCOMPARE(hDocumentBefore->globalSymbolAt(1)->asScope()->memberCount(), 3U);
QVERIFY(!containsSymbol(hDocumentBefore->globalSymbolAt(1)->asScope(), functionName));
// Execute "Go To Slot"
FormEditorW *few = FormEditorW::instance();
QDesignerIntegrationInterface *integration = few->designerEditor()->integration();
QVERIFY(integration);
integration->emitNavigateToSlot(QLatin1String("pushButton"), QLatin1String("clicked()"),
QStringList());
QApplication::processEvents();
// Checks after
m_modelManager->updateSourceFiles(QStringList() << cppFile << hFile).waitForFinished();
QCOMPARE(EditorManager::currentDocument()->filePath(), cppFile);
QVERIFY(EditorManager::currentDocument()->isModified());
Document::Ptr cppDocumentAfter = m_modelManager->snapshot().document(cppFile);
QCOMPARE(cppDocumentAfter->globalSymbolCount(), 3U);
QVERIFY(containsSymbol(cppDocumentAfter->globalNamespace(), qualifiedFunctionName));
Document::Ptr hDocumentAfter = m_modelManager->snapshot().document(hFile);
QCOMPARE(hDocumentAfter->globalSymbolAt(1)->asScope()->memberCount(), 4U);
QVERIFY(containsSymbol(hDocumentAfter->globalSymbolAt(1)->asScope(), functionName));
}
private:
void cleanup()
{
EditorManager::instance()->closeAllEditors(/*askAboutModifiedEditors =*/ false);
QVERIFY(EditorManager::documentModel()->openedDocuments().isEmpty());
m_modelManager->GC();
QVERIFY(m_modelManager->snapshot().isEmpty());
}
private:
CppModelManagerInterface *m_modelManager;
};
} // anonymous namespace
/// Check: Executes "Go To Slot..." on a QPushButton in a *.ui file and checks if the respective
/// header and source files are updated.
void FormEditorPlugin::test_gotoslot_withoutProject()
{
GoToSlotTest test;
test.run();
}
......@@ -34,6 +34,7 @@
#include "editordata.h"
#include <widgethost.h>
#include <cpptools/cppmodelmanagerinterface.h>
#include <cpptools/cpptoolsconstants.h>
#include <cpptools/insertionpointlocator.h>
#include <cpptools/symbolfinder.h>
......@@ -131,15 +132,16 @@ static QList<Document::Ptr> findDocumentsIncluding(const Snapshot &docTable,
{
QList<Document::Ptr> docList;
foreach (const Document::Ptr &doc, docTable) { // we go through all documents
const QStringList includes = doc->includedFiles();
foreach (const QString &include, includes) {
const QList<Document::Include> includes = doc->resolvedIncludes()
+ doc->unresolvedIncludes();
foreach (const Document::Include &include, includes) {
if (checkFileNameOnly) {
const QFileInfo fi(include);
const QFileInfo fi(include.unresolvedFileName());
if (fi.fileName() == fileName) { // we are only interested in docs which includes fileName only
docList.append(doc);
}
} else {
if (include == fileName)
if (include.resolvedFileName() == fileName)
docList.append(doc);
}
}
......@@ -530,21 +532,29 @@ bool QtCreatorIntegration::navigateToSlot(const QString &objectName,
const QString uiFolder = fi.absolutePath();
const QString uicedName = QLatin1String("ui_") + fi.completeBaseName() + QLatin1String(".h");
// Retrieve code model snapshot restricted to project of ui file.
const ProjectExplorer::Project *uiProject = ProjectExplorer::ProjectExplorerPlugin::instance()->session()->projectForFile(currentUiFile);
if (!uiProject) {
*errorMessage = tr("Internal error: No project could be found for %1.").arg(currentUiFile);
return false;
}
// Retrieve code model snapshot restricted to project of ui file or the working copy.
Snapshot docTable = CppTools::CppModelManagerInterface::instance()->snapshot();
Snapshot newDocTable;
for (Snapshot::iterator it = docTable.begin(); it != docTable.end(); ++it) {
const ProjectExplorer::Project *project = ProjectExplorer::ProjectExplorerPlugin::instance()->session()->projectForFile(it.key());
if (project == uiProject)
newDocTable.insert(it.value());
ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
const ProjectExplorer::Project *uiProject = pe->session()->projectForFile(currentUiFile);
if (uiProject) {
Snapshot::const_iterator end = docTable.end();
for (Snapshot::iterator it = docTable.begin(); it != end; ++it) {
const ProjectExplorer::Project *project = pe->session()->projectForFile(it.key());
if (project == uiProject)
newDocTable.insert(it.value());
}
} else {
const CppTools::CppModelManagerInterface::WorkingCopy workingCopy =
CppTools::CppModelManagerInterface::instance()->workingCopy();
QHashIterator<QString, QPair<QString, unsigned> > it = workingCopy.iterator();
while (it.hasNext()) {
it.next();
const QString fileName = it.key();
if (fileName != CppTools::CppModelManagerInterface::configurationFileName())
newDocTable.insert(docTable.document(fileName));
}
}
docTable = newDocTable;
// take all docs, find the ones that include the ui_xx.h.
......
// Copyright header
#include "form.h"
#include "ui_form.h"
Form::Form(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form)
{
ui->setupUi(this);
}
Form::~Form()
{
delete ui;
}
// Copyright header
#ifndef FORM_H
#define FORM_H
#include <QWidget>
namespace Ui {
class Form;
}
class Form : public QWidget
{
Q_OBJECT
public:
explicit Form(QWidget *parent = 0);
~Form();
private:
Ui::Form *ui;
};
#endif // FORM_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>50</x>
<y>60</y>
<width>87</width>
<height>27</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment