symbolsfindfilter.cpp 12.7 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3 4
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8 9 10 11
** 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
12 13 14
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
15
**
16 17 18 19 20 21 22
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
con's avatar
con committed
23
**
hjk's avatar
hjk committed
24
****************************************************************************/
25 26 27

#include "symbolsfindfilter.h"
#include "cppmodelmanager.h"
28
#include "cpptoolsconstants.h"
29 30

#include <coreplugin/icore.h>
31 32
#include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h>
33
#include <coreplugin/editormanager/editormanager.h>
34 35
#include <coreplugin/find/searchresultwindow.h>
#include <projectexplorer/project.h>
36 37
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h>
38 39

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

42 43 44 45
#include <QSet>
#include <QGridLayout>
#include <QLabel>
#include <QButtonGroup>
46

47
using namespace Core;
48

49 50 51 52 53 54
namespace CppTools {
namespace Internal {

const char SETTINGS_GROUP[] = "CppSymbols";
const char SETTINGS_SYMBOLTYPES[] = "SymbolsToSearchFor";
const char SETTINGS_SEARCHSCOPE[] = "SearchScope";
55 56 57

SymbolsFindFilter::SymbolsFindFilter(CppModelManager *manager)
    : m_manager(manager),
58 59
      m_enabled(true),
      m_symbolsToSearch(SearchSymbols::AllTypes),
60
      m_scope(SymbolSearcher::SearchProjectsOnly)
61 62
{
    // for disabling while parser is running
63 64 65 66
    connect(ProgressManager::instance(), &ProgressManager::taskStarted,
            this, &SymbolsFindFilter::onTaskStarted);
    connect(ProgressManager::instance(), &ProgressManager::allTasksFinished,
            this, &SymbolsFindFilter::onAllTasksFinished);
67 68 69 70 71 72 73 74 75 76 77 78 79 80
}

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

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

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

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

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

103
FindFlags SymbolsFindFilter::supportedFindFlags() const
104
{
105
    return FindCaseSensitively | FindRegularExpression | FindWholeWords;
106 107
}

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

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

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

139
    QFutureWatcher<SearchResultItem> *watcher = new QFutureWatcher<SearchResultItem>();
140
    m_watchers.insert(watcher, search);
141 142 143 144
    connect(watcher, &QFutureWatcherBase::finished,
            this, &SymbolsFindFilter::finish);
    connect(watcher, &QFutureWatcherBase::resultsReadyAt,
            this, &SymbolsFindFilter::addResults);
145
    SymbolSearcher *symbolSearcher = m_manager->indexingSupport()->createSymbolSearcher(parameters, projectFileNames);
146 147
    connect(watcher, &QFutureWatcherBase::finished,
            symbolSearcher, &QObject::deleteLater);
148 149
    watcher->setFuture(Utils::runAsync(m_manager->sharedThreadPool(),
                                       &SymbolSearcher::runSearch, symbolSearcher));
150
    FutureProgress *progress = ProgressManager::addTask(watcher->future(), tr("Searching for Symbol"),
151
                                                        Core::Constants::TASK_SEARCH);
152
    connect(progress, &FutureProgress::clicked, search, &SearchResult::popup);
153 154 155 156
}

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

void SymbolsFindFilter::finish()
{
173 174 175
    QFutureWatcher<SearchResultItem> *watcher =
            static_cast<QFutureWatcher<SearchResultItem> *>(sender());
    SearchResult *search = m_watchers.value(watcher);
176
    if (search)
177
        search->finishSearch(watcher->isCanceled());
178 179
    m_watchers.remove(watcher);
    watcher->deleteLater();
180 181
}

182
void SymbolsFindFilter::openEditor(const SearchResultItem &item)
183
{
184
    if (!item.userData.canConvert<IndexItem::Ptr>())
185
        return;
186
    IndexItem::Ptr info = item.userData.value<IndexItem::Ptr>();
187
    EditorManager::openEditorAt(info->fileName(), info->line(), info->column());
188 189 190 191 192 193 194 195 196 197
}

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

void SymbolsFindFilter::writeSettings(QSettings *settings)
{
    settings->beginGroup(QLatin1String(SETTINGS_GROUP));
198 199
    settings->setValue(QLatin1String(SETTINGS_SYMBOLTYPES), (int)m_symbolsToSearch);
    settings->setValue(QLatin1String(SETTINGS_SEARCHSCOPE), (int)m_scope);
200 201 202 203 204 205
    settings->endGroup();
}

void SymbolsFindFilter::readSettings(QSettings *settings)
{
    settings->beginGroup(QLatin1String(SETTINGS_GROUP));
206
    m_symbolsToSearch = (SearchSymbols::SymbolTypes)settings->value(QLatin1String(SETTINGS_SYMBOLTYPES),
207
                                        (int)SearchSymbols::AllTypes).toInt();
208
    m_scope = (SearchScope)settings->value(QLatin1String(SETTINGS_SEARCHSCOPE),
209
                                           (int)SymbolSearcher::SearchProjectsOnly).toInt();
210 211 212 213
    settings->endGroup();
    emit symbolsToSearchChanged();
}

214
void SymbolsFindFilter::onTaskStarted(Id type)
215
{
216
    if (type == CppTools::Constants::TASK_INDEX) {
217
        m_enabled = false;
218
        emit enabledChanged(m_enabled);
219 220 221
    }
}

222
void SymbolsFindFilter::onAllTasksFinished(Id type)
223
{
224
    if (type == CppTools::Constants::TASK_INDEX) {
225
        m_enabled = true;
226
        emit enabledChanged(m_enabled);
227 228 229
    }
}

230 231
void SymbolsFindFilter::searchAgain()
{
232
    SearchResult *search = qobject_cast<SearchResult *>(sender());
233
    QTC_ASSERT(search, return);
234
    search->restart();
235 236 237
    startSearch(search);
}

238 239 240 241 242
QString SymbolsFindFilter::label() const
{
    return tr("C++ Symbols:");
}

243
QString SymbolsFindFilter::toolTip(FindFlags findFlags) const
244 245
{
    QStringList types;
246
    if (m_symbolsToSearch & SymbolSearcher::Classes)
247
        types.append(tr("Classes"));
248
    if (m_symbolsToSearch & SymbolSearcher::Functions)
249
        types.append(tr("Functions"));
250
    if (m_symbolsToSearch & SymbolSearcher::Enums)
251
        types.append(tr("Enums"));
252
    if (m_symbolsToSearch & SymbolSearcher::Declarations)
253 254
        types.append(tr("Declarations"));
    return tr("Scope: %1\nTypes: %2\nFlags: %3")
255
            .arg(searchScope() == SymbolSearcher::SearchGlobal ? tr("All") : tr("Projects"))
256
            .arg(types.join(tr(", ")))
257
            .arg(IFindFilter::descriptionForFindFlags(findFlags));
258 259
}

260 261 262 263 264
// #pragma mark -- SymbolsFindFilterConfigWidget

SymbolsFindFilterConfigWidget::SymbolsFindFilterConfigWidget(SymbolsFindFilter *filter)
    : m_filter(filter)
{
265 266
    connect(m_filter, &SymbolsFindFilter::symbolsToSearchChanged,
            this, &SymbolsFindFilterConfigWidget::getState);
267 268 269 270 271 272 273 274 275 276 277

    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);

278
    m_typeMethods = new QCheckBox(tr("Functions"));
279 280 281 282 283 284 285 286 287 288 289 290 291 292
    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);

293 294 295 296 297 298 299 300
    connect(m_typeClasses, &QAbstractButton::clicked,
            this, &SymbolsFindFilterConfigWidget::setState);
    connect(m_typeMethods, &QAbstractButton::clicked,
            this, &SymbolsFindFilterConfigWidget::setState);
    connect(m_typeEnums, &QAbstractButton::clicked,
            this, &SymbolsFindFilterConfigWidget::setState);
    connect(m_typeDeclarations, &QAbstractButton::clicked,
            this, &SymbolsFindFilterConfigWidget::setState);
301

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
    layout->addWidget(m_searchGlobal, 2, 2);

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

312 313 314 315
    connect(m_searchProjectsOnly, &QAbstractButton::clicked,
            this, &SymbolsFindFilterConfigWidget::setState);
    connect(m_searchGlobal, &QAbstractButton::clicked,
            this, &SymbolsFindFilterConfigWidget::setState);
316 317 318 319 320
}

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
}
349 350 351

} // namespace Internal
} // namespace CppTools