searchresultwindow.cpp 23.1 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
9
**
10
** GNU Lesser General Public License Usage
11
**
hjk's avatar
hjk committed
12 13 14 15 16 17
** 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.
18
**
con's avatar
con committed
19
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
con's avatar
con committed
21 22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23 24 25 26 27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
con's avatar
con committed
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
con's avatar
con committed
30
**
31
**************************************************************************/
hjk's avatar
hjk committed
32

con's avatar
con committed
33
#include "searchresultwindow.h"
34
#include "searchresultwidget.h"
35
#include "findtoolwindow.h"
con's avatar
con committed
36

37
#include <coreplugin/icore.h>
38 39 40 41
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icontext.h>
42
#include <utils/qtcassert.h>
43

44 45 46 47 48 49 50 51 52
#include <QFile>
#include <QSettings>
#include <QDebug>
#include <QVBoxLayout>
#include <QFont>
#include <QAction>
#include <QComboBox>
#include <QScrollArea>
#include <QStackedWidget>
con's avatar
con committed
53

54 55
static const char SETTINGSKEYSECTIONNAME[] = "SearchResults";
static const char SETTINGSKEYEXPANDRESULTS[] = "ExpandResults";
Eike Ziller's avatar
Eike Ziller committed
56
static const int MAX_SEARCH_HISTORY = 12;
con's avatar
con committed
57

58
namespace Find {
con's avatar
con committed
59

con's avatar
con committed
60 61
namespace Internal {

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
    class InternalScrollArea : public QScrollArea
    {
        Q_OBJECT
    public:
        explicit InternalScrollArea(QWidget *parent)
            : QScrollArea(parent)
        {
            setFrameStyle(QFrame::NoFrame);
            setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
            setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
        }

        QSize sizeHint() const
        {
            if (widget())
                return widget()->size();
            return QScrollArea::sizeHint();
        }
    };

    class SearchResultWindowPrivate : public QObject
    {
84 85 86 87 88
        Q_OBJECT
    public:
        SearchResultWindowPrivate(SearchResultWindow *window);
        bool isSearchVisible() const;
        int visibleSearchIndex() const;
89
        void setCurrentIndex(int index, bool focus);
con's avatar
con committed
90

91 92
        SearchResultWindow *q;
        QList<Internal::SearchResultWidget *> m_searchResultWidgets;
93 94
        QToolButton *m_expandCollapseButton;
        QAction *m_expandCollapseAction;
con's avatar
con committed
95
        static const bool m_initiallyExpand = false;
96 97
        QWidget *m_spacer;
        QComboBox *m_recentSearchesBox;
98
        QStackedWidget *m_widget;
99 100
        QList<SearchResult *> m_searchResults;
        int m_currentIndex;
101
        QFont m_font;
102 103 104

    public slots:
        void setCurrentIndex(int index);
Eike Ziller's avatar
Eike Ziller committed
105
        void moveWidgetToTop();
106
        void popupRequested(bool focus);
con's avatar
con committed
107 108
    };

109 110 111 112 113 114 115 116 117 118 119
    SearchResultWindowPrivate::SearchResultWindowPrivate(SearchResultWindow *window)
        : q(window)
    {
    }

    bool SearchResultWindowPrivate::isSearchVisible() const
    {
        return m_currentIndex > 0;
    }

    int SearchResultWindowPrivate::visibleSearchIndex() const
con's avatar
con committed
120
    {
121 122 123
        return m_currentIndex - 1;
    }

124
    void SearchResultWindowPrivate::setCurrentIndex(int index, bool focus)
125 126 127 128 129 130 131
    {
        if (isSearchVisible())
            m_searchResultWidgets.at(visibleSearchIndex())->notifyVisibilityChanged(false);
        m_currentIndex = index;
        m_widget->setCurrentIndex(index);
        m_recentSearchesBox->setCurrentIndex(index);
        if (!isSearchVisible()) {
132 133
            if (focus)
                m_widget->currentWidget()->setFocus();
134 135
            m_expandCollapseButton->setEnabled(false);
        } else {
136 137
            if (focus)
                m_searchResultWidgets.at(visibleSearchIndex())->setFocusInternally();
138 139 140 141
            m_searchResultWidgets.at(visibleSearchIndex())->notifyVisibilityChanged(true);
            m_expandCollapseButton->setEnabled(true);
        }
        q->navigateStateChanged();
con's avatar
con committed
142
    }
Eike Ziller's avatar
Eike Ziller committed
143

144 145 146 147 148
    void SearchResultWindowPrivate::setCurrentIndex(int index)
    {
        setCurrentIndex(index, true/*focus*/);
    }

Eike Ziller's avatar
Eike Ziller committed
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
    void SearchResultWindowPrivate::moveWidgetToTop()
    {
        SearchResultWidget *widget = qobject_cast<SearchResultWidget *>(sender());
        QTC_ASSERT(widget, return);
        int index = m_searchResultWidgets.indexOf(widget);
        if (index == 0)
            return; // nothing to do
        int internalIndex = index + 1/*account for "new search" entry*/;
        QString searchEntry = m_recentSearchesBox->itemText(internalIndex);

        m_searchResultWidgets.removeAt(index);
        m_widget->removeWidget(widget);
        m_recentSearchesBox->removeItem(internalIndex);
        SearchResult *result = m_searchResults.takeAt(index);

        m_searchResultWidgets.prepend(widget);
        m_widget->insertWidget(1, widget);
        m_recentSearchesBox->insertItem(1, searchEntry);
        m_searchResults.prepend(result);

        // adapt the current index
        if (index == visibleSearchIndex()) {
            // was visible, so we switch
            // this is the default case
            m_currentIndex = 1;
            m_widget->setCurrentIndex(1);
            m_recentSearchesBox->setCurrentIndex(1);
        } else if (visibleSearchIndex() < index) {
            // academical case where the widget moved before the current widget
            // only our internal book keeping needed
            ++m_currentIndex;
        }
    }
182 183 184 185 186 187 188 189 190

    void SearchResultWindowPrivate::popupRequested(bool focus)
    {
        SearchResultWidget *widget = qobject_cast<SearchResultWidget *>(sender());
        QTC_ASSERT(widget, return);
        int internalIndex = m_searchResultWidgets.indexOf(widget) + 1/*account for "new search" entry*/;
        setCurrentIndex(internalIndex, focus);
        q->popup(focus);
    }
191
}
192

con's avatar
con committed
193 194
using namespace Find::Internal;

195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
/*!
    \enum Find::SearchResultWindow::SearchMode
    Specifies if a search should show the replace UI or not.

    \value SearchOnly
           The search doesn't support replace.
    \value SearchAndReplace
           The search supports replace, so show the UI for it.
*/

/*!
    \class Find::SearchResult
    \brief Reports user interaction like activation of a search result item.

    Whenever a new search is initiated via startNewSearch, an instance of this
    class is returned to provide the initiator with the hooks for handling user
    interaction.
*/

/*!
    \fn void SearchResult::activated(const Find::SearchResultItem &item)
    \brief Sent if the user activated (e.g. double-clicked) a search result
    \a item.
*/

/*!
    \fn void SearchResult::replaceButtonClicked(const QString &replaceText, const QList<Find::SearchResultItem> &checkedItems)
    \brief Sent when the user initiated a replace, e.g. by pressing the replace
    all button.

    The signal reports the text to use for replacement in \a replaceText,
    and the list of search result items that were selected by the user
    in \a checkedItems.
    The handler of this signal should apply the replace only on the selected
    items.
*/

/*!
    \class Find::SearchResultWindow
    \brief The SearchResultWindow class is the implementation of a commonly
    shared \gui{Search Results} output pane. Use it to show search results
    to a user.

    Whenever you want to show the user a list of search results, or want
    to present UI for a global search and replace, use the single instance
    of this class.

    Except for being an implementation of a output pane, the
    SearchResultWindow has a few methods and one enum that allows other
    plugins to show their search results and hook into the user actions for
    selecting an entry and performing a global replace.

    Whenever you start a search, call startNewSearch(SearchMode) to initialize
    the search result window. The parameter determines if the GUI for
    replacing should be shown.
    The method returns a SearchResult object that is your
    hook into the signals from user interaction for this search.
    When you produce search results, call addResults or addResult to add them
    to the search result window.
    After the search has finished call finishSearch to inform the search
    result window about it.

257
    You will get activated signals via your SearchResult instance when
258 259 260 261 262 263 264 265 266 267
    the user selects a search result item, and, if you started the search
    with the SearchAndReplace option, the replaceButtonClicked signal
    when the user requests a replace.
*/

/*!
    \fn QString SearchResultWindow::displayName() const
    \internal
*/

268 269
SearchResultWindow *SearchResultWindow::m_instance = 0;

270 271 272 273
/*!
    \fn SearchResultWindow::SearchResultWindow()
    \internal
*/
274
SearchResultWindow::SearchResultWindow(QWidget *newSearchPanel)
275
    : d(new SearchResultWindowPrivate(this))
276
{
277
    m_instance = this;
278 279 280 281 282 283 284
    d->m_spacer = new QWidget;
    d->m_spacer->setMinimumWidth(30);
    d->m_recentSearchesBox = new QComboBox;
    d->m_recentSearchesBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
    d->m_recentSearchesBox->addItem(tr("New Search"));
    connect(d->m_recentSearchesBox, SIGNAL(activated(int)), d, SLOT(setCurrentIndex(int)));

285
    d->m_widget = new QStackedWidget;
286
    d->m_widget->setWindowTitle(displayName());
287

288
    InternalScrollArea *newSearchArea = new InternalScrollArea(d->m_widget);
289
    newSearchArea->setWidget(newSearchPanel);
290
    newSearchArea->setFocusProxy(newSearchPanel);
291
    d->m_widget->addWidget(newSearchArea);
292
    d->m_currentIndex = 0;
293

294 295 296 297 298 299
    d->m_expandCollapseButton = new QToolButton(d->m_widget);
    d->m_expandCollapseButton->setAutoRaise(true);

    d->m_expandCollapseAction = new QAction(tr("Expand All"), this);
    d->m_expandCollapseAction->setCheckable(true);
    d->m_expandCollapseAction->setIcon(QIcon(QLatin1String(":/find/images/expand.png")));
Eike Ziller's avatar
Eike Ziller committed
300
    Core::Command *cmd = Core::ActionManager::registerAction(
hjk's avatar
hjk committed
301
            d->m_expandCollapseAction, "Find.ExpandAll",
302
            Core::Context(Core::Constants::C_GLOBAL));
303
    cmd->setAttribute(Core::Command::CA_UpdateText);
304
    d->m_expandCollapseButton->setDefaultAction(cmd->action());
305

306
    connect(d->m_expandCollapseAction, SIGNAL(toggled(bool)), this, SLOT(handleExpandCollapseToolButton(bool)));
con's avatar
con committed
307 308 309
    readSettings();
}

310 311 312 313
/*!
    \fn SearchResultWindow::~SearchResultWindow()
    \internal
*/
con's avatar
con committed
314 315 316
SearchResultWindow::~SearchResultWindow()
{
    writeSettings();
317
    qDeleteAll(d->m_searchResults);
318 319 320
    delete d->m_widget;
    d->m_widget = 0;
    delete d;
con's avatar
con committed
321 322
}

323 324 325 326
/*!
    \fn SearchResultWindow *SearchResultWindow::instance()
    \brief Returns the single shared instance of the Search Results window.
*/
327 328 329 330 331
SearchResultWindow *SearchResultWindow::instance()
{
    return m_instance;
}

332 333 334 335
/*!
    \fn void SearchResultWindow::visibilityChanged(bool)
    \internal
*/
336
void SearchResultWindow::visibilityChanged(bool visible)
con's avatar
con committed
337
{
338 339
    if (d->isSearchVisible())
        d->m_searchResultWidgets.at(d->visibleSearchIndex())->notifyVisibilityChanged(visible);
con's avatar
con committed
340 341
}

342 343 344 345
/*!
    \fn QWidget *SearchResultWindow::outputWidget(QWidget *)
    \internal
*/
con's avatar
con committed
346 347
QWidget *SearchResultWindow::outputWidget(QWidget *)
{
348
    return d->m_widget;
con's avatar
con committed
349 350
}

351 352 353 354
/*!
    \fn QList<QWidget*> SearchResultWindow::toolBarWidgets() const
    \internal
*/
Thorbjørn Lindeijer's avatar
Thorbjørn Lindeijer committed
355
QList<QWidget*> SearchResultWindow::toolBarWidgets() const
con's avatar
con committed
356
{
357
    return QList<QWidget*>() << d->m_expandCollapseButton << d->m_spacer << d->m_recentSearchesBox;
con's avatar
con committed
358 359
}

360 361 362
/*!
    \brief Tells the search results window to start a new search.

363 364 365 366 367 368
    The \a label should be a string that shortly describes the type of
    search, i.e. search filter and possibly a most relevant search option, followed by a colon ':'.
    E.g. \code{Project 'myproject':}
    The \a searchTerm will be shown behind the colon.
    The \a toolTip should elaborate on the search parameters, like file patterns that are searched and
    find flags.
369 370 371
    If \a cfgGroup is not empty, it will be used for storing the "do not ask again"
    setting of a "this change cannot be undone" warning (which is implicitly requested
    by passing a non-empty group).
372 373
    Returns a SearchResult object that is used for signaling user interaction
    with the results of this search.
374 375 376 377 378
    The search result window owns the returned SearchResult
    and might delete it any time, even while the search is running
    (e.g. when the user clears the search result pane, or if the user opens so many other searches
    that this search falls out of the history).

379
*/
380 381 382 383 384
SearchResult *SearchResultWindow::startNewSearch(const QString &label,
                                                 const QString &toolTip,
                                                 const QString &searchTerm,
                                                 SearchMode searchOrSearchAndReplace,
                                                 const QString &cfgGroup)
385
{
Eike Ziller's avatar
Eike Ziller committed
386
    if (d->m_searchResults.size() >= MAX_SEARCH_HISTORY) {
387
        d->m_searchResultWidgets.last()->notifyVisibilityChanged(false);
388
        // widget first, because that might send interesting signals to SearchResult
389
        delete d->m_searchResultWidgets.takeLast();
390
        delete d->m_searchResults.takeLast();
391
        d->m_recentSearchesBox->removeItem(d->m_recentSearchesBox->count()-1);
392 393 394 395
        if (d->m_currentIndex >= d->m_recentSearchesBox->count()) {
            // temporarily set the index to the last existing
            d->m_currentIndex = d->m_recentSearchesBox->count() - 1;
        }
396 397 398 399 400
    }
    Internal::SearchResultWidget *widget = new Internal::SearchResultWidget;
    d->m_searchResultWidgets.prepend(widget);
    d->m_widget->insertWidget(1, widget);
    connect(widget, SIGNAL(navigateStateChanged()), this, SLOT(navigateStateChanged()));
Eike Ziller's avatar
Eike Ziller committed
401
    connect(widget, SIGNAL(restarted()), d, SLOT(moveWidgetToTop()));
402
    connect(widget, SIGNAL(requestPopup(bool)), d, SLOT(popupRequested(bool)));
403
    widget->setTextEditorFont(d->m_font);
404
    widget->setShowReplaceUI(searchOrSearchAndReplace != SearchOnly);
405
    widget->setAutoExpandResults(d->m_expandCollapseAction->isChecked());
406 407 408 409 410 411 412 413 414 415
    widget->setInfo(label, toolTip, searchTerm);
    if (searchOrSearchAndReplace == SearchAndReplace)
        widget->setDontAskAgainGroup(cfgGroup);
    SearchResult *result = new SearchResult(widget);
    d->m_searchResults.prepend(result);
    d->m_recentSearchesBox->insertItem(1, tr("%1 %2").arg(label, searchTerm));
    if (d->m_currentIndex > 0)
        ++d->m_currentIndex; // so setCurrentIndex still knows about the right "currentIndex" and its widget
    d->setCurrentIndex(1);
    return result;
416 417
}

418 419 420 421
/*!
    \fn void SearchResultWindow::clearContents()
    \brief Clears the current contents in the search result window.
*/
con's avatar
con committed
422 423
void SearchResultWindow::clearContents()
{
424 425 426 427 428 429 430 431 432 433 434 435
    for (int i = d->m_recentSearchesBox->count() - 1; i > 0 /* don't want i==0 */; --i)
        d->m_recentSearchesBox->removeItem(i);
    foreach (Internal::SearchResultWidget *widget, d->m_searchResultWidgets)
        widget->notifyVisibilityChanged(false);
    qDeleteAll(d->m_searchResultWidgets);
    d->m_searchResultWidgets.clear();
    qDeleteAll(d->m_searchResults);
    d->m_searchResults.clear();

    d->m_currentIndex = 0;
    d->m_widget->currentWidget()->setFocus();
    d->m_expandCollapseButton->setEnabled(false);
436
    navigateStateChanged();
con's avatar
con committed
437 438
}

439 440 441 442
/*!
    \fn bool SearchResultWindow::hasFocus()
    \internal
*/
443
bool SearchResultWindow::hasFocus() const
444
{
445
    return d->m_widget->focusWidget() && d->m_widget->focusWidget()->hasFocus();
446 447
}

448 449 450 451
/*!
    \fn bool SearchResultWindow::canFocus()
    \internal
*/
452
bool SearchResultWindow::canFocus() const
453
{
454 455 456
    if (d->isSearchVisible())
        return d->m_searchResultWidgets.at(d->visibleSearchIndex())->canFocusInternally();
    return true;
457 458
}

459 460 461 462
/*!
    \fn void SearchResultWindow::setFocus()
    \internal
*/
463 464
void SearchResultWindow::setFocus()
{
465
    if (!d->isSearchVisible())
466 467
        d->m_widget->currentWidget()->setFocus();
    else
468
        d->m_searchResultWidgets.at(d->visibleSearchIndex())->setFocusInternally();
469 470
}

471 472 473 474
/*!
    \fn void SearchResultWindow::setTextEditorFont(const QFont &font)
    \internal
*/
475 476
void SearchResultWindow::setTextEditorFont(const QFont &font)
{
477
    d->m_font = font;
478 479
    foreach (Internal::SearchResultWidget *widget, d->m_searchResultWidgets)
        widget->setTextEditorFont(font);
480 481
}

482 483
void SearchResultWindow::openNewSearchPanel()
{
484
    d->setCurrentIndex(0);
485
    popup(true/*focus*/, true/*sizeHint*/);
486 487
}

488 489 490 491
/*!
    \fn void SearchResultWindow::handleExpandCollapseToolButton(bool checked)
    \internal
*/
con's avatar
con committed
492 493
void SearchResultWindow::handleExpandCollapseToolButton(bool checked)
{
494 495 496
    if (!d->isSearchVisible())
        return;
    d->m_searchResultWidgets.at(d->visibleSearchIndex())->setAutoExpandResults(checked);
497 498
    if (checked) {
        d->m_expandCollapseAction->setText(tr("Collapse All"));
499
        d->m_searchResultWidgets.at(d->visibleSearchIndex())->expandAll();
500 501
    } else {
        d->m_expandCollapseAction->setText(tr("Expand All"));
502
        d->m_searchResultWidgets.at(d->visibleSearchIndex())->collapseAll();
503
    }
con's avatar
con committed
504 505
}

506 507 508 509
/*!
    \fn void SearchResultWindow::readSettings()
    \internal
*/
Thorbjørn Lindeijer's avatar
Thorbjørn Lindeijer committed
510
void SearchResultWindow::readSettings()
con's avatar
con committed
511
{
hjk's avatar
hjk committed
512
    QSettings *s = Core::ICore::settings();
513
    if (s) {
514
        s->beginGroup(QLatin1String(SETTINGSKEYSECTIONNAME));
515
        d->m_expandCollapseAction->setChecked(s->value(QLatin1String(SETTINGSKEYEXPANDRESULTS), d->m_initiallyExpand).toBool());
con's avatar
con committed
516 517 518 519
        s->endGroup();
    }
}

520 521 522 523
/*!
    \fn void SearchResultWindow::writeSettings()
    \internal
*/
Thorbjørn Lindeijer's avatar
Thorbjørn Lindeijer committed
524
void SearchResultWindow::writeSettings()
con's avatar
con committed
525
{
hjk's avatar
hjk committed
526
    QSettings *s = Core::ICore::settings();
527
    if (s) {
528
        s->beginGroup(QLatin1String(SETTINGSKEYSECTIONNAME));
529
        s->setValue(QLatin1String(SETTINGSKEYEXPANDRESULTS), d->m_expandCollapseAction->isChecked());
con's avatar
con committed
530 531 532 533
        s->endGroup();
    }
}

534 535 536 537
/*!
    \fn int SearchResultWindow::priorityInStatusBar() const
    \internal
*/
con's avatar
con committed
538 539 540 541
int SearchResultWindow::priorityInStatusBar() const
{
    return 80;
}
542

543 544 545 546
/*!
    \fn bool SearchResultWindow::canNext()
    \internal
*/
547
bool SearchResultWindow::canNext() const
548
{
549 550 551
    if (d->isSearchVisible())
        return d->m_searchResultWidgets.at(d->visibleSearchIndex())->count() > 0;
    return false;
552 553
}

554 555 556 557
/*!
    \fn bool SearchResultWindow::canPrevious()
    \internal
*/
558
bool SearchResultWindow::canPrevious() const
559
{
560
    return canNext();
561 562
}

563 564 565 566
/*!
    \fn void SearchResultWindow::goToNext()
    \internal
*/
567 568
void SearchResultWindow::goToNext()
{
569 570 571
    int index = d->m_widget->currentIndex();
    if (index != 0)
        d->m_searchResultWidgets.at(index-1)->goToNext();
572
}
573 574 575 576 577

/*!
    \fn void SearchResultWindow::goToPrev()
    \internal
*/
578 579
void SearchResultWindow::goToPrev()
{
580 581 582
    int index = d->m_widget->currentIndex();
    if (index != 0)
        d->m_searchResultWidgets.at(index-1)->goToPrevious();
583 584
}

585 586 587 588
/*!
    \fn bool SearchResultWindow::canNavigate()
    \internal
*/
589
bool SearchResultWindow::canNavigate() const
590 591 592
{
    return true;
}
593

594 595 596 597 598 599 600 601 602 603 604
/*!
    \fn SearchResult::SearchResult(SearchResultWidget *widget)
    \internal
*/
SearchResult::SearchResult(SearchResultWidget *widget)
    : m_widget(widget)
{
    connect(widget, SIGNAL(activated(Find::SearchResultItem)),
            this, SIGNAL(activated(Find::SearchResultItem)));
    connect(widget, SIGNAL(replaceButtonClicked(QString,QList<Find::SearchResultItem>)),
            this, SIGNAL(replaceButtonClicked(QString,QList<Find::SearchResultItem>)));
605 606
    connect(widget, SIGNAL(cancelled()),
            this, SIGNAL(cancelled()));
607 608
    connect(widget, SIGNAL(paused(bool)),
            this, SIGNAL(paused(bool)));
609 610
    connect(widget, SIGNAL(visibilityChanged(bool)),
            this, SIGNAL(visibilityChanged(bool)));
611 612
    connect(widget, SIGNAL(searchAgainRequested()),
            this, SIGNAL(searchAgainRequested()));
613 614
}

615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
/*!
    \fn void SearchResult::setUserData(const QVariant &data)
    \brief Attach some random \a data to this search, that you can use later.

    \sa userData()
*/
void SearchResult::setUserData(const QVariant &data)
{
    m_userData = data;
}

/*!
    \fn void SearchResult::userData()
    \brief Return the data that was attached to this search by calling setUserData().

    \sa setUserData()
*/
QVariant SearchResult::userData() const
{
    return m_userData;
}

/*!
    \fn QString SearchResult::textToReplace() const
    \brief Returns the text that should replace the text in search results.
*/
QString SearchResult::textToReplace() const
{
643
    return m_widget->textToReplace();
644 645
}

646 647 648 649 650
int SearchResult::count() const
{
    return m_widget->count();
}

651 652 653 654 655
void SearchResult::setSearchAgainSupported(bool supported)
{
    m_widget->setSearchAgainSupported(supported);
}

656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
/*!
    \fn void SearchResult::addResult(const QString &fileName, int lineNumber, const QString &rowText, int searchTermStart, int searchTermLength, const QVariant &userData)
    \brief Adds a single result line to the search results.

    The \a fileName, \a lineNumber and \a rowText are shown in the result line.
    \a searchTermStart and \a searchTermLength specify the region that
    should be visually marked (string position and length in \a rowText).
    You can attach arbitrary \a userData to the search result, which can
    be used e.g. when reacting to the signals of the SearchResult for your search.

    \sa addResults()
*/
void SearchResult::addResult(const QString &fileName, int lineNumber, const QString &lineText,
                             int searchTermStart, int searchTermLength, const QVariant &userData)
{
671 672
    m_widget->addResult(fileName, lineNumber, lineText,
                        searchTermStart, searchTermLength, userData);
673
    emit countChanged(m_widget->count());
674 675 676 677 678 679 680 681 682 683 684
}

/*!
    \fn void SearchResult::addResults(const QList<SearchResultItem> &items, SearchResult::AddMode mode)
    \brief Adds all of the given search result \a items to the search
    results window.

    \sa addResult()
*/
void SearchResult::addResults(const QList<SearchResultItem> &items, AddMode mode)
{
685
    m_widget->addResults(items, mode);
686
    emit countChanged(m_widget->count());
687 688 689 690 691 692 693
}

/*!
    \fn void SearchResult::finishSearch()
    \brief Notifies the search result window that the current search
    has finished, and the UI should reflect that.
*/
Eike Ziller's avatar
Eike Ziller committed
694
void SearchResult::finishSearch(bool canceled)
695
{
Eike Ziller's avatar
Eike Ziller committed
696
    m_widget->finishSearch(canceled);
697 698 699 700 701 702 703 704 705
}

/*!
    \fn void SearchResult::setTextToReplace(const QString &textToReplace)
    \brief Sets the value in the UI element that allows the user to type
    the text that should replace text in search results to \a textToReplace.
*/
void SearchResult::setTextToReplace(const QString &textToReplace)
{
706
    m_widget->setTextToReplace(textToReplace);
707 708
}

709 710 711
/*!
 * \brief Removes all search results.
 */
Eike Ziller's avatar
Eike Ziller committed
712
void SearchResult::restart()
713
{
Eike Ziller's avatar
Eike Ziller committed
714
    m_widget->restart();
715 716
}

717 718 719 720 721
void SearchResult::setSearchAgainEnabled(bool enabled)
{
    m_widget->setSearchAgainEnabled(enabled);
}

722 723 724 725 726 727 728 729
/*!
 * \brief Pops up the search result panel with this search.
 */
void SearchResult::popup()
{
    m_widget->sendRequestPopup();
}

730
} // namespace Find
731 732

#include "searchresultwindow.moc"