Commit 35cb3793 authored by Christian Kamm's avatar Christian Kamm

QmlJS: Implement renaming of usages.

Task-number: QTCREATORBUG-3669
Change-Id: I2c600cae5ac445ca80eafe6557ba276c14a77a73
Reviewed-on: http://codereview.qt.nokia.com/1413Reviewed-by: default avatarFawzi Mohamed <fawzi.mohamed@nokia.com>
parent 4285b484
......@@ -1333,6 +1333,11 @@ void QmlJSTextEditorWidget::findUsages()
m_findReferences->findUsages(file()->fileName(), textCursor().position());
}
void QmlJSTextEditorWidget::renameUsages()
{
m_findReferences->renameUsages(file()->fileName(), textCursor().position());
}
void QmlJSTextEditorWidget::showContextPane()
{
if (m_contextPane && m_semanticInfo.isValid()) {
......
......@@ -168,6 +168,7 @@ public slots:
void forceSemanticRehighlight();
void followSymbolUnderCursor();
void findUsages();
void renameUsages();
void showContextPane();
virtual void setFontSettings(const TextEditor::FontSettings &);
......
......@@ -52,6 +52,7 @@ const char * const TASK_SEARCH = "QmlJSEditor.TaskSearch";
const char * const FOLLOW_SYMBOL_UNDER_CURSOR = "QmlJSEditor.FollowSymbolUnderCursor";
const char * const FIND_USAGES = "QmlJSEditor.FindUsages";
const char * const RENAME_USAGES = "QmlJSEditor.RenameUsages";
const char * const SHOW_QT_QUICK_HELPER = "QmlJSEditor.ShowQtQuickHelper";
const char * const QML_MIMETYPE = "application/x-qml";
......
......@@ -180,6 +180,13 @@ bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *e
contextMenu->addAction(cmd);
qmlToolsMenu->addAction(cmd);
QAction *renameUsagesAction = new QAction(tr("Rename Usages"), this);
cmd = am->registerAction(renameUsagesAction, Constants::RENAME_USAGES, context);
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+R")));
connect(renameUsagesAction, SIGNAL(triggered()), this, SLOT(renameUsages()));
contextMenu->addAction(cmd);
qmlToolsMenu->addAction(cmd);
QAction *showQuickToolbar = new QAction(tr("Show Qt Quick Toolbar"), this);
cmd = am->registerAction(showQuickToolbar, Constants::SHOW_QT_QUICK_HELPER, context);
#ifdef Q_WS_MACX
......@@ -281,6 +288,13 @@ void QmlJSEditorPlugin::findUsages()
editor->findUsages();
}
void QmlJSEditorPlugin::renameUsages()
{
Core::EditorManager *em = Core::EditorManager::instance();
if (QmlJSTextEditorWidget *editor = qobject_cast<QmlJSTextEditorWidget*>(em->currentEditor()->widget()))
editor->renameUsages();
}
void QmlJSEditorPlugin::showContextPane()
{
Core::EditorManager *em = Core::EditorManager::instance();
......
......@@ -94,6 +94,7 @@ public:
public Q_SLOTS:
void followSymbolUnderCursor();
void findUsages();
void renameUsages();
void showContextPane();
private Q_SLOTS:
......
......@@ -795,7 +795,8 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
const ModelManagerInterface::WorkingCopy workingCopy,
Snapshot snapshot,
const QString fileName,
quint32 offset)
quint32 offset,
QString replacement)
{
// update snapshot from workingCopy to make sure it's up to date
// ### remove?
......@@ -832,6 +833,8 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
const QString &name = findTarget.name();
if (name.isEmpty())
return;
if (!replacement.isNull() && replacement.isEmpty())
replacement = name;
QStringList files;
foreach (const Document::Ptr &doc, snapshot) {
......@@ -841,12 +844,14 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
future.setProgressRange(0, files.size());
// report a dummy usage to indicate the search is starting
FindReferences::Usage searchStarting(replacement, QString(), 0, 0, 0);
if (findTarget.typeKind() == findTarget.TypeKind){
const ObjectValue *typeValue = value_cast<const ObjectValue*>(findTarget.targetValue());
if (!typeValue)
return;
// report a dummy usage to indicate the search is starting
future.reportResult(FindReferences::Usage());
future.reportResult(searchStarting);
SearchFileForType process(context, name, typeValue);
UpdateUI reduce(&future);
......@@ -859,8 +864,7 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
scope->lookupMember(name, &context, &scope);
if (!scope)
return;
// report a dummy usage to indicate the search is starting
future.reportResult(FindReferences::Usage());
future.reportResult(searchStarting);
ProcessFile process(context, name, scope);
UpdateUI reduce(&future);
......@@ -872,17 +876,29 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
void FindReferences::findUsages(const QString &fileName, quint32 offset)
{
findAll_helper(fileName, offset);
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
QFuture<Usage> result = QtConcurrent::run(
&find_helper, modelManager->workingCopy(),
modelManager->snapshot(), fileName, offset,
QString());
m_watcher.setFuture(result);
}
void FindReferences::findAll_helper(const QString &fileName, quint32 offset)
void FindReferences::renameUsages(const QString &fileName, quint32 offset,
const QString &replacement)
{
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
// an empty non-null string asks the future to use the current name as base
QString newName = replacement;
if (newName.isNull())
newName = QLatin1String("");
QFuture<Usage> result = QtConcurrent::run(
&find_helper, modelManager->workingCopy(),
modelManager->snapshot(), fileName, offset);
modelManager->snapshot(), fileName, offset,
newName);
m_watcher.setFuture(result);
}
......@@ -890,7 +906,18 @@ void FindReferences::displayResults(int first, int last)
{
// the first usage is always a dummy to indicate we now start searching
if (first == 0) {
Find::SearchResult *search = _resultWindow->startNewSearch(Find::SearchResultWindow::SearchOnly);
Usage dummy = m_watcher.future().resultAt(0);
QString replacement = dummy.path;
Find::SearchResult *search;
if (replacement.isEmpty()) {
search = _resultWindow->startNewSearch(Find::SearchResultWindow::SearchOnly);
} else {
search = _resultWindow->startNewSearch(Find::SearchResultWindow::SearchAndReplace);
_resultWindow->setTextToReplace(replacement);
connect(search, SIGNAL(replaceButtonClicked(QString,QList<Find::SearchResultItem>)),
SLOT(onReplaceButtonClicked(QString,QList<Find::SearchResultItem>)));
}
connect(search, SIGNAL(activated(Find::SearchResultItem)),
this, SLOT(openEditor(Find::SearchResultItem)));
_resultWindow->popup(true);
......@@ -930,3 +957,26 @@ void FindReferences::openEditor(const Find::SearchResultItem &item)
Core::EditorManager::instance()->openEditor(item.text, QString(), Core::EditorManager::ModeSwitch);
}
}
void FindReferences::onReplaceButtonClicked(const QString &text, const QList<Find::SearchResultItem> &items)
{
const QStringList fileNames = TextEditor::BaseFileFind::replaceAll(text, items);
// files that are opened in an editor are changed, but not saved
QStringList changedOnDisk;
QStringList changedUnsavedEditors;
Core::EditorManager *editorManager = Core::EditorManager::instance();
foreach (const QString &fileName, fileNames) {
if (editorManager->editorsForFileName(fileName).isEmpty())
changedOnDisk += fileName;
else
changedUnsavedEditors += fileName;
}
if (!changedOnDisk.isEmpty())
QmlJS::ModelManagerInterface::instance()->updateSourceFiles(changedOnDisk, true);
if (!changedUnsavedEditors.isEmpty())
QmlJS::ModelManagerInterface::instance()->updateSourceFiles(changedUnsavedEditors, false);
_resultWindow->hide();
}
......@@ -81,14 +81,14 @@ Q_SIGNALS:
public:
void findUsages(const QString &fileName, quint32 offset);
void renameUsages(const QString &fileName, quint32 offset,
const QString &replacement = QString());
private Q_SLOTS:
void displayResults(int first, int last);
void searchFinished();
void openEditor(const Find::SearchResultItem &item);
private:
void findAll_helper(const QString &fileName, quint32 offset);
void onReplaceButtonClicked(const QString &text, const QList<Find::SearchResultItem> &items);
private:
Find::SearchResultWindow *_resultWindow;
......
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