symbolsfindfilter.cpp 12.6 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
Eike Ziller's avatar
Eike Ziller committed
3 4
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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
Eike Ziller's avatar
Eike Ziller committed
12 13
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
Eike Ziller's avatar
Eike Ziller committed
14
** use the contact form at http://www.qt.io/contact-us.
15 16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
** Alternatively, this file may be used under the terms of the GNU Lesser
Eike Ziller's avatar
Eike Ziller committed
18 19 20 21 22 23
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
hjk's avatar
hjk committed
24
**
Eike Ziller's avatar
Eike Ziller committed
25 26
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
con's avatar
con committed
27 28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
29
****************************************************************************/
30 31 32

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

#include <coreplugin/icore.h>
36 37
#include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h>
38
#include <coreplugin/editormanager/editormanager.h>
39 40
#include <coreplugin/find/searchresultwindow.h>
#include <projectexplorer/project.h>
41 42
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h>
43 44

#include <utils/runextensions.h>
45
#include <utils/qtcassert.h>
46

47 48 49 50
#include <QSet>
#include <QGridLayout>
#include <QLabel>
#include <QButtonGroup>
51

52
using namespace Core;
53

54 55 56 57 58 59
namespace CppTools {
namespace Internal {

const char SETTINGS_GROUP[] = "CppSymbols";
const char SETTINGS_SYMBOLTYPES[] = "SymbolsToSearchFor";
const char SETTINGS_SEARCHSCOPE[] = "SearchScope";
60 61 62

SymbolsFindFilter::SymbolsFindFilter(CppModelManager *manager)
    : m_manager(manager),
63 64
      m_enabled(true),
      m_symbolsToSearch(SearchSymbols::AllTypes),
65
      m_scope(SymbolSearcher::SearchProjectsOnly)
66 67
{
    // for disabling while parser is running
68 69 70 71
    connect(ProgressManager::instance(), SIGNAL(taskStarted(Core::Id)),
            this, SLOT(onTaskStarted(Core::Id)));
    connect(ProgressManager::instance(), SIGNAL(allTasksFinished(Core::Id)),
            this, SLOT(onAllTasksFinished(Core::Id)));
72 73 74 75 76 77 78 79 80 81 82 83 84 85
}

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

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

bool SymbolsFindFilter::isEnabled() const
{
86
    return m_enabled;
87 88
}

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

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

108
FindFlags SymbolsFindFilter::supportedFindFlags() const
109
{
110
    return FindCaseSensitively | FindRegularExpression | FindWholeWords;
111 112
}

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

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

135
void SymbolsFindFilter::startSearch(SearchResult *search)
136
{
137
    SymbolSearcher::Parameters parameters = search->userData().value<SymbolSearcher::Parameters>();
138
    QSet<QString> projectFileNames;
139
    if (parameters.scope == SymbolSearcher::SearchProjectsOnly) {
hjk's avatar
hjk committed
140
        foreach (ProjectExplorer::Project *project, ProjectExplorer::SessionManager::projects())
141 142 143
            projectFileNames += project->files(ProjectExplorer::Project::AllFiles).toSet();
    }

144
    QFutureWatcher<SearchResultItem> *watcher = new QFutureWatcher<SearchResultItem>();
145 146 147 148
    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
149
            this, SLOT(addResults(int,int)));
150 151 152 153
    SymbolSearcher *symbolSearcher = m_manager->indexingSupport()->createSymbolSearcher(parameters, projectFileNames);
    connect(watcher, SIGNAL(finished()),
            symbolSearcher, SLOT(deleteLater()));
    watcher->setFuture(QtConcurrent::run(&SymbolSearcher::runSearch, symbolSearcher));
154
    FutureProgress *progress = ProgressManager::addTask(watcher->future(), tr("Searching for Symbol"),
155
                                                        Core::Constants::TASK_SEARCH);
156
    connect(progress, SIGNAL(clicked()), search, SLOT(popup()));
157 158 159 160
}

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

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

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

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

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

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

218
void SymbolsFindFilter::onTaskStarted(Id type)
219
{
220
    if (type == CppTools::Constants::TASK_INDEX) {
221
        m_enabled = false;
222
        emit enabledChanged(m_enabled);
223 224 225
    }
}

226
void SymbolsFindFilter::onAllTasksFinished(Id type)
227
{
228
    if (type == CppTools::Constants::TASK_INDEX) {
229
        m_enabled = true;
230
        emit enabledChanged(m_enabled);
231 232 233
    }
}

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

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

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

264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
// #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);

281
    m_typeMethods = new QCheckBox(tr("Functions"));
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
    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()));

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

304
    m_searchGlobal = new QRadioButton(tr("All files"));
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
    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();
320 321 322 323
    m_typeClasses->setChecked(symbols & SymbolSearcher::Classes);
    m_typeMethods->setChecked(symbols & SymbolSearcher::Functions);
    m_typeEnums->setChecked(symbols & SymbolSearcher::Enums);
    m_typeDeclarations->setChecked(symbols & SymbolSearcher::Declarations);
324 325

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

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

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

} // namespace Internal
} // namespace CppTools