symbolsfindfilter.cpp 12.9 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8 9 10 11 12 13 14
** 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.
15 16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17 18 19 20 21 22 23 24 25
** 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
con's avatar
con committed
26 27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
29 30 31

#include "symbolsfindfilter.h"
#include "cppmodelmanager.h"
32
#include "cpptoolsconstants.h"
33 34

#include <coreplugin/icore.h>
35 36
#include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h>
37 38
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h>
39 40

#include <utils/runextensions.h>
41
#include <utils/qtcassert.h>
42

43 44 45 46
#include <QSet>
#include <QGridLayout>
#include <QLabel>
#include <QButtonGroup>
47 48 49 50 51 52 53 54

using namespace CppTools;
using namespace CppTools::Internal;

namespace {
    const char * const SETTINGS_GROUP = "CppSymbols";
    const char * const SETTINGS_SYMBOLTYPES = "SymbolsToSearchFor";
    const char * const SETTINGS_SEARCHSCOPE = "SearchScope";
55
} // anonymous namespace
56 57 58

SymbolsFindFilter::SymbolsFindFilter(CppModelManager *manager)
    : m_manager(manager),
59 60
      m_enabled(true),
      m_symbolsToSearch(SearchSymbols::AllTypes),
61
      m_scope(SymbolSearcher::SearchProjectsOnly)
62 63
{
    // for disabling while parser is running
hjk's avatar
hjk committed
64
    connect(Core::ICore::progressManager(), SIGNAL(taskStarted(QString)),
65
            this, SLOT(onTaskStarted(QString)));
hjk's avatar
hjk committed
66
    connect(Core::ICore::progressManager(), SIGNAL(allTasksFinished(QString)),
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
            this, SLOT(onAllTasksFinished(QString)));
}

QString SymbolsFindFilter::id() const
{
    return QLatin1String("CppSymbols");
}

QString SymbolsFindFilter::displayName() const
{
    return tr("C++ Symbols");
}

bool SymbolsFindFilter::isEnabled() const
{
82
    return m_enabled;
83 84
}

dt's avatar
dt committed
85 86
void SymbolsFindFilter::cancel()
{
87 88 89 90 91
    Find::SearchResult *search = qobject_cast<Find::SearchResult *>(sender());
    QTC_ASSERT(search, return);
    QFutureWatcher<Find::SearchResultItem> *watcher = m_watchers.key(search);
    QTC_ASSERT(watcher, return);
    watcher->cancel();
dt's avatar
dt committed
92 93
}

94 95 96 97 98 99 100 101 102 103
void SymbolsFindFilter::setPaused(bool paused)
{
    Find::SearchResult *search = qobject_cast<Find::SearchResult *>(sender());
    QTC_ASSERT(search, return);
    QFutureWatcher<Find::SearchResultItem> *watcher = m_watchers.key(search);
    QTC_ASSERT(watcher, return);
    if (!paused || watcher->isRunning()) // guard against pausing when the search is finished
        watcher->setPaused(paused);
}

104 105 106 107 108 109 110 111
Find::FindFlags SymbolsFindFilter::supportedFindFlags() const
{
    return Find::FindCaseSensitively | Find::FindRegularExpression | Find::FindWholeWords;
}

void SymbolsFindFilter::findAll(const QString &txt, Find::FindFlags findFlags)
{
    Find::SearchResultWindow *window = Find::SearchResultWindow::instance();
112
    Find::SearchResult *search = window->startNewSearch(label(), toolTip(findFlags), txt);
113 114 115
    search->setSearchAgainSupported(true);
    connect(search, SIGNAL(activated(Find::SearchResultItem)),
            this, SLOT(openEditor(Find::SearchResultItem)));
116
    connect(search, SIGNAL(cancelled()), this, SLOT(cancel()));
117
    connect(search, SIGNAL(paused(bool)), this, SLOT(setPaused(bool)));
118 119
    connect(search, SIGNAL(searchAgainRequested()), this, SLOT(searchAgain()));
    connect(this, SIGNAL(enabledChanged(bool)), search, SLOT(setSearchAgainEnabled(bool)));
120
    window->popup(Core::IOutputPane::ModeSwitch | Core::IOutputPane::WithFocus);
121

122
    SymbolSearcher::Parameters parameters;
123 124 125 126 127 128 129 130 131 132
    parameters.text = txt;
    parameters.flags = findFlags;
    parameters.types = m_symbolsToSearch;
    parameters.scope = m_scope;
    search->setUserData(qVariantFromValue(parameters));
    startSearch(search);
}

void SymbolsFindFilter::startSearch(Find::SearchResult *search)
{
133
    SymbolSearcher::Parameters parameters = search->userData().value<SymbolSearcher::Parameters>();
134
    QSet<QString> projectFileNames;
135
    if (parameters.scope == SymbolSearcher::SearchProjectsOnly) {
136 137 138 139 140 141
        foreach (ProjectExplorer::Project *project,
                 ProjectExplorer::ProjectExplorerPlugin::instance()->session()->projects()) {
            projectFileNames += project->files(ProjectExplorer::Project::AllFiles).toSet();
        }
    }

142 143 144 145 146
    QFutureWatcher<Find::SearchResultItem> *watcher = new QFutureWatcher<Find::SearchResultItem>();
    m_watchers.insert(watcher, search);
    connect(watcher, SIGNAL(finished()),
            this, SLOT(finish()));
    connect(watcher, SIGNAL(resultsReadyAt(int,int)),
Robert Loehning's avatar
Robert Loehning committed
147
            this, SLOT(addResults(int,int)));
148 149 150 151
    SymbolSearcher *symbolSearcher = m_manager->indexingSupport()->createSymbolSearcher(parameters, projectFileNames);
    connect(watcher, SIGNAL(finished()),
            symbolSearcher, SLOT(deleteLater()));
    watcher->setFuture(QtConcurrent::run(&SymbolSearcher::runSearch, symbolSearcher));
152
    Core::FutureProgress *progress = Core::ICore::progressManager()->addTask(watcher->future(),
153
                                                        tr("Searching"),
154
                                                        QLatin1String(Find::Constants::TASK_SEARCH));
155
    connect(progress, SIGNAL(clicked()), search, SLOT(popup()));
156 157 158 159
}

void SymbolsFindFilter::addResults(int begin, int end)
{
160 161 162 163 164 165
    QFutureWatcher<Find::SearchResultItem> *watcher =
            static_cast<QFutureWatcher<Find::SearchResultItem> *>(sender());
    Find::SearchResult *search = m_watchers.value(watcher);
    if (!search) {
        // search was removed from search history while the search is running
        watcher->cancel();
166 167
        return;
    }
168 169
    QList<Find::SearchResultItem> items;
    for (int i = begin; i < end; ++i)
170 171
        items << watcher->resultAt(i);
    search->addResults(items, Find::SearchResult::AddSorted);
172 173 174 175
}

void SymbolsFindFilter::finish()
{
176 177 178 179
    QFutureWatcher<Find::SearchResultItem> *watcher =
            static_cast<QFutureWatcher<Find::SearchResultItem> *>(sender());
    Find::SearchResult *search = m_watchers.value(watcher);
    if (search)
Eike Ziller's avatar
Eike Ziller committed
180
        search->finishSearch(watcher->isCanceled());
181 182
    m_watchers.remove(watcher);
    watcher->deleteLater();
183 184 185 186 187 188 189
}

void SymbolsFindFilter::openEditor(const Find::SearchResultItem &item)
{
    if (!item.userData.canConvert<ModelItemInfo>())
        return;
    ModelItemInfo info = item.userData.value<ModelItemInfo>();
190
    TextEditor::BaseTextEditorWidget::openEditorAt(info.fileName,
191 192 193 194 195 196 197 198 199 200 201 202
                                             info.line,
                                             info.column);
}

QWidget *SymbolsFindFilter::createConfigWidget()
{
    return new SymbolsFindFilterConfigWidget(this);
}

void SymbolsFindFilter::writeSettings(QSettings *settings)
{
    settings->beginGroup(QLatin1String(SETTINGS_GROUP));
203 204
    settings->setValue(QLatin1String(SETTINGS_SYMBOLTYPES), (int)m_symbolsToSearch);
    settings->setValue(QLatin1String(SETTINGS_SEARCHSCOPE), (int)m_scope);
205 206 207 208 209 210
    settings->endGroup();
}

void SymbolsFindFilter::readSettings(QSettings *settings)
{
    settings->beginGroup(QLatin1String(SETTINGS_GROUP));
211
    m_symbolsToSearch = (SearchSymbols::SymbolTypes)settings->value(QLatin1String(SETTINGS_SYMBOLTYPES),
212
                                        (int)SearchSymbols::AllTypes).toInt();
213
    m_scope = (SearchScope)settings->value(QLatin1String(SETTINGS_SEARCHSCOPE),
214
                                           (int)SymbolSearcher::SearchProjectsOnly).toInt();
215 216 217 218 219 220
    settings->endGroup();
    emit symbolsToSearchChanged();
}

void SymbolsFindFilter::onTaskStarted(const QString &type)
{
221
    if (type == QLatin1String(CppTools::Constants::TASK_INDEX)) {
222
        m_enabled = false;
223
        emit enabledChanged(m_enabled);
224 225 226 227 228
    }
}

void SymbolsFindFilter::onAllTasksFinished(const QString &type)
{
229
    if (type == QLatin1String(CppTools::Constants::TASK_INDEX)) {
230
        m_enabled = true;
231
        emit enabledChanged(m_enabled);
232 233 234
    }
}

235 236 237 238
void SymbolsFindFilter::searchAgain()
{
    Find::SearchResult *search = qobject_cast<Find::SearchResult *>(sender());
    QTC_ASSERT(search, return);
Eike Ziller's avatar
Eike Ziller committed
239
    search->restart();
240 241 242
    startSearch(search);
}

243 244 245 246 247 248 249 250
QString SymbolsFindFilter::label() const
{
    return tr("C++ Symbols:");
}

QString SymbolsFindFilter::toolTip(Find::FindFlags findFlags) const
{
    QStringList types;
251
    if (m_symbolsToSearch & SymbolSearcher::Classes)
252
        types.append(tr("Classes"));
253
    if (m_symbolsToSearch & SymbolSearcher::Functions)
254
        types.append(tr("Methods"));
255
    if (m_symbolsToSearch & SymbolSearcher::Enums)
256
        types.append(tr("Enums"));
257
    if (m_symbolsToSearch & SymbolSearcher::Declarations)
258 259
        types.append(tr("Declarations"));
    return tr("Scope: %1\nTypes: %2\nFlags: %3")
260
            .arg(searchScope() == SymbolSearcher::SearchGlobal ? tr("All") : tr("Projects"))
261 262 263 264
            .arg(types.join(tr(", ")))
            .arg(Find::IFindFilter::descriptionForFindFlags(findFlags));
}

265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
// #pragma mark -- SymbolsFindFilterConfigWidget

SymbolsFindFilterConfigWidget::SymbolsFindFilterConfigWidget(SymbolsFindFilter *filter)
    : m_filter(filter)
{
    connect(m_filter, SIGNAL(symbolsToSearchChanged()), this, SLOT(getState()));

    QGridLayout *layout = new QGridLayout(this);
    setLayout(layout);
    layout->setMargin(0);

    QLabel *typeLabel = new QLabel(tr("Types:"));
    layout->addWidget(typeLabel, 0, 0);

    m_typeClasses = new QCheckBox(tr("Classes"));
    layout->addWidget(m_typeClasses, 0, 1);

    m_typeMethods = new QCheckBox(tr("Methods"));
    layout->addWidget(m_typeMethods, 0, 2);

    m_typeEnums = new QCheckBox(tr("Enums"));
    layout->addWidget(m_typeEnums, 1, 1);

    m_typeDeclarations = new QCheckBox(tr("Declarations"));
    layout->addWidget(m_typeDeclarations, 1, 2);

    // hacks to fix layouting:
    typeLabel->setMinimumWidth(80);
    typeLabel->setAlignment(Qt::AlignRight);
    m_typeClasses->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    m_typeMethods->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    connect(m_typeClasses, SIGNAL(clicked(bool)), this, SLOT(setState()));
    connect(m_typeMethods, SIGNAL(clicked(bool)), this, SLOT(setState()));
    connect(m_typeEnums, SIGNAL(clicked(bool)), this, SLOT(setState()));
    connect(m_typeDeclarations, SIGNAL(clicked(bool)), this, SLOT(setState()));

302
    m_searchProjectsOnly = new QRadioButton(tr("Projects only"));
303 304
    layout->addWidget(m_searchProjectsOnly, 2, 1);

305
    m_searchGlobal = new QRadioButton(tr("All files"));
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
    layout->addWidget(m_searchGlobal, 2, 2);

    m_searchGroup = new QButtonGroup(this);
    m_searchGroup->addButton(m_searchProjectsOnly);
    m_searchGroup->addButton(m_searchGlobal);

    connect(m_searchProjectsOnly, SIGNAL(clicked(bool)),
            this, SLOT(setState()));
    connect(m_searchGlobal, SIGNAL(clicked(bool)),
            this, SLOT(setState()));
}

void SymbolsFindFilterConfigWidget::getState()
{
    SearchSymbols::SymbolTypes symbols = m_filter->symbolsToSearch();
321 322 323 324
    m_typeClasses->setChecked(symbols & SymbolSearcher::Classes);
    m_typeMethods->setChecked(symbols & SymbolSearcher::Functions);
    m_typeEnums->setChecked(symbols & SymbolSearcher::Enums);
    m_typeDeclarations->setChecked(symbols & SymbolSearcher::Declarations);
325 326

    SymbolsFindFilter::SearchScope scope = m_filter->searchScope();
327 328
    m_searchProjectsOnly->setChecked(scope == SymbolSearcher::SearchProjectsOnly);
    m_searchGlobal->setChecked(scope == SymbolSearcher::SearchGlobal);
329 330 331 332 333 334
}

void SymbolsFindFilterConfigWidget::setState() const
{
    SearchSymbols::SymbolTypes symbols;
    if (m_typeClasses->isChecked())
335
        symbols |= SymbolSearcher::Classes;
336
    if (m_typeMethods->isChecked())
337
        symbols |= SymbolSearcher::Functions;
338
    if (m_typeEnums->isChecked())
339
        symbols |= SymbolSearcher::Enums;
340
    if (m_typeDeclarations->isChecked())
341
        symbols |= SymbolSearcher::Declarations;
342 343 344
    m_filter->setSymbolsToSearch(symbols);

    if (m_searchProjectsOnly->isChecked())
345
        m_filter->setSearchScope(SymbolSearcher::SearchProjectsOnly);
346
    else
347
        m_filter->setSearchScope(SymbolSearcher::SearchGlobal);
348
}