mirror of
https://invent.kde.org/graphics/okular
synced 2024-08-24 18:35:37 +00:00
333 lines
9.2 KiB
C++
333 lines
9.2 KiB
C++
/***************************************************************************
|
|
* Copyright (C) 2004 by Enrico Ros <eros.kde@email.it> *
|
|
* Copyright (C) 2007, 2009-2010 by Pino Toscano <pino@kde.org> *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
***************************************************************************/
|
|
|
|
#include "searchlineedit.h"
|
|
|
|
// local includes
|
|
#include "core/document.h"
|
|
|
|
// qt/kde includes
|
|
#include <qapplication.h>
|
|
#include <qlayout.h>
|
|
#include <qtimer.h>
|
|
#include <kcolorscheme.h>
|
|
#include <kiconloader.h>
|
|
#include <kpixmapsequence.h>
|
|
#include <kpixmapsequencewidget.h>
|
|
#include <kmessagebox.h>
|
|
#include <klocalizedstring.h>
|
|
|
|
SearchLineEdit::SearchLineEdit( QWidget * parent, Okular::Document * document )
|
|
: KLineEdit( parent ), m_document( document ), m_minLength( 0 ),
|
|
m_caseSensitivity( Qt::CaseInsensitive ),
|
|
m_searchType( Okular::Document::AllDocument ), m_id( -1 ),
|
|
m_moveViewport( false ), m_changed( false ), m_fromStart( true ),
|
|
m_findAsYouType( true ), m_searchRunning( false )
|
|
{
|
|
setObjectName( QStringLiteral( "SearchLineEdit" ) );
|
|
setClearButtonEnabled( true );
|
|
|
|
// a timer to ensure that we don't flood the document with requests to search
|
|
m_inputDelayTimer = new QTimer(this);
|
|
m_inputDelayTimer->setSingleShot(true);
|
|
connect(m_inputDelayTimer, &QTimer::timeout, this, &SearchLineEdit::startSearch);
|
|
|
|
connect(this, &SearchLineEdit::textChanged, this, &SearchLineEdit::slotTextChanged);
|
|
connect(document, &Okular::Document::searchFinished, this, &SearchLineEdit::searchFinished);
|
|
}
|
|
|
|
void SearchLineEdit::clearText()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
void SearchLineEdit::setSearchCaseSensitivity( Qt::CaseSensitivity cs )
|
|
{
|
|
m_caseSensitivity = cs;
|
|
m_changed = true;
|
|
}
|
|
|
|
void SearchLineEdit::setSearchMinimumLength( int length )
|
|
{
|
|
m_minLength = length;
|
|
m_changed = true;
|
|
}
|
|
|
|
void SearchLineEdit::setSearchType( Okular::Document::SearchType type )
|
|
{
|
|
if ( type == m_searchType )
|
|
return;
|
|
|
|
disconnect(this, &SearchLineEdit::returnPressed, this, &SearchLineEdit::slotReturnPressed);
|
|
|
|
m_searchType = type;
|
|
|
|
// Only connect Enter for next/prev searches, the rest of searches are document global so
|
|
// next/prev search does not make sense for them
|
|
if (m_searchType == Okular::Document::NextMatch || m_searchType == Okular::Document::PreviousMatch) {
|
|
connect(this, &SearchLineEdit::returnPressed, this, &SearchLineEdit::slotReturnPressed);
|
|
}
|
|
|
|
if ( !m_changed )
|
|
m_changed = ( m_searchType != Okular::Document::NextMatch && m_searchType != Okular::Document::PreviousMatch );
|
|
}
|
|
|
|
void SearchLineEdit::setSearchId( int id )
|
|
{
|
|
m_id = id;
|
|
m_changed = true;
|
|
}
|
|
|
|
void SearchLineEdit::setSearchColor( const QColor &color )
|
|
{
|
|
m_color = color;
|
|
m_changed = true;
|
|
}
|
|
|
|
void SearchLineEdit::setSearchMoveViewport( bool move )
|
|
{
|
|
m_moveViewport = move;
|
|
}
|
|
|
|
void SearchLineEdit::setSearchFromStart( bool fromStart )
|
|
{
|
|
m_fromStart = fromStart;
|
|
}
|
|
|
|
void SearchLineEdit::setFindAsYouType( bool findAsYouType )
|
|
{
|
|
m_findAsYouType = findAsYouType;
|
|
}
|
|
|
|
void SearchLineEdit::resetSearch()
|
|
{
|
|
// Stop the currently running search, if any
|
|
stopSearch();
|
|
|
|
// Clear highlights
|
|
if ( m_id != -1 )
|
|
m_document->resetSearch( m_id );
|
|
|
|
// Make sure that the search will be reset at the next one
|
|
m_changed = true;
|
|
|
|
// Reset input box color
|
|
prepareLineEditForSearch();
|
|
}
|
|
|
|
bool SearchLineEdit::isSearchRunning() const
|
|
{
|
|
return m_searchRunning;
|
|
}
|
|
|
|
void SearchLineEdit::restartSearch()
|
|
{
|
|
m_inputDelayTimer->stop();
|
|
m_inputDelayTimer->start( 700 );
|
|
m_changed = true;
|
|
}
|
|
|
|
void SearchLineEdit::stopSearch()
|
|
{
|
|
if ( m_id == -1 || !m_searchRunning )
|
|
return;
|
|
|
|
m_inputDelayTimer->stop();
|
|
// ### this should just cancel the search with id m_id, not all of them
|
|
m_document->cancelSearch();
|
|
// flagging as "changed" so the search will be reset at the next one
|
|
m_changed = true;
|
|
}
|
|
|
|
void SearchLineEdit::findNext()
|
|
{
|
|
if ( m_id == -1 || m_searchType != Okular::Document::NextMatch )
|
|
return;
|
|
|
|
if ( !m_changed )
|
|
{
|
|
emit searchStarted();
|
|
m_searchRunning = true;
|
|
m_document->continueSearch( m_id, m_searchType );
|
|
}
|
|
else
|
|
startSearch();
|
|
}
|
|
|
|
void SearchLineEdit::findPrev()
|
|
{
|
|
if ( m_id == -1 || m_searchType != Okular::Document::PreviousMatch )
|
|
return;
|
|
|
|
if ( !m_changed )
|
|
{
|
|
emit searchStarted();
|
|
m_searchRunning = true;
|
|
m_document->continueSearch( m_id, m_searchType );
|
|
}
|
|
else
|
|
startSearch();
|
|
}
|
|
|
|
void SearchLineEdit::slotTextChanged( const QString & text )
|
|
{
|
|
Q_UNUSED(text);
|
|
|
|
prepareLineEditForSearch();
|
|
|
|
if ( m_findAsYouType )
|
|
restartSearch();
|
|
else
|
|
m_changed = true;
|
|
}
|
|
|
|
void SearchLineEdit::prepareLineEditForSearch()
|
|
{
|
|
QPalette pal = palette();
|
|
const int textLength = text().length();
|
|
if ( textLength > 0 && textLength < m_minLength )
|
|
{
|
|
const KColorScheme scheme( QPalette::Active, KColorScheme::View );
|
|
pal.setBrush( QPalette::Base, scheme.background( KColorScheme::NegativeBackground ) );
|
|
pal.setBrush( QPalette::Text, scheme.foreground( KColorScheme::NegativeText ) );
|
|
}
|
|
else
|
|
{
|
|
const QPalette qAppPalette = QApplication::palette();
|
|
pal.setColor( QPalette::Base, qAppPalette.color( QPalette::Base ) );
|
|
pal.setColor( QPalette::Text, qAppPalette.color( QPalette::Text ) );
|
|
}
|
|
setPalette( pal );
|
|
}
|
|
|
|
void SearchLineEdit::slotReturnPressed( const QString &text )
|
|
{
|
|
Q_UNUSED(text);
|
|
|
|
m_inputDelayTimer->stop();
|
|
prepareLineEditForSearch();
|
|
if ( QApplication::keyboardModifiers() == Qt::ShiftModifier )
|
|
{
|
|
m_searchType = Okular::Document::PreviousMatch;
|
|
findPrev();
|
|
}
|
|
else
|
|
{
|
|
m_searchType = Okular::Document::NextMatch;
|
|
findNext();
|
|
}
|
|
}
|
|
|
|
void SearchLineEdit::startSearch()
|
|
{
|
|
if ( m_id == -1 || !m_color.isValid() )
|
|
return;
|
|
|
|
if ( m_changed && ( m_searchType == Okular::Document::NextMatch || m_searchType == Okular::Document::PreviousMatch ) )
|
|
{
|
|
m_document->resetSearch( m_id );
|
|
}
|
|
m_changed = false;
|
|
// search text if have more than 3 chars or else clear search
|
|
QString thistext = text();
|
|
if ( thistext.length() >= qMax( m_minLength, 1 ) )
|
|
{
|
|
emit searchStarted();
|
|
m_searchRunning = true;
|
|
m_document->searchText( m_id, thistext, m_fromStart, m_caseSensitivity,
|
|
m_searchType, m_moveViewport, m_color );
|
|
}
|
|
else
|
|
m_document->resetSearch( m_id );
|
|
}
|
|
|
|
void SearchLineEdit::searchFinished( int id, Okular::Document::SearchStatus endStatus )
|
|
{
|
|
// ignore the searches not started by this search edit
|
|
if ( id != m_id )
|
|
return;
|
|
|
|
// if not found, use warning colors
|
|
if ( endStatus == Okular::Document::NoMatchFound )
|
|
{
|
|
QPalette pal = palette();
|
|
const KColorScheme scheme( QPalette::Active, KColorScheme::View );
|
|
pal.setBrush( QPalette::Base, scheme.background( KColorScheme::NegativeBackground ) );
|
|
pal.setBrush( QPalette::Text, scheme.foreground( KColorScheme::NegativeText ) );
|
|
setPalette( pal );
|
|
}
|
|
else
|
|
{
|
|
QPalette pal = palette();
|
|
const QPalette qAppPalette = QApplication::palette();
|
|
pal.setColor( QPalette::Base, qAppPalette.color( QPalette::Base ) );
|
|
pal.setColor( QPalette::Text, qAppPalette.color( QPalette::Text ) );
|
|
setPalette( pal );
|
|
}
|
|
|
|
m_searchRunning = false;
|
|
emit searchStopped();
|
|
}
|
|
|
|
|
|
SearchLineWidget::SearchLineWidget( QWidget * parent, Okular::Document * document )
|
|
: QWidget( parent )
|
|
{
|
|
QHBoxLayout *layout = new QHBoxLayout( this );
|
|
layout->setMargin( 0 );
|
|
|
|
m_edit = new SearchLineEdit( this, document );
|
|
layout->addWidget( m_edit );
|
|
|
|
m_anim = new KPixmapSequenceWidget( this );
|
|
m_anim->setFixedSize( 22, 22 );
|
|
layout->addWidget( m_anim );
|
|
m_anim->hide();
|
|
|
|
m_timer = new QTimer( this );
|
|
m_timer->setSingleShot( true );
|
|
connect(m_timer, &QTimer::timeout, this, &SearchLineWidget::slotTimedout);
|
|
|
|
connect(m_edit, &SearchLineEdit::searchStarted, this, &SearchLineWidget::slotSearchStarted);
|
|
connect(m_edit, &SearchLineEdit::searchStopped, this, &SearchLineWidget::slotSearchStopped);
|
|
}
|
|
|
|
SearchLineEdit* SearchLineWidget::lineEdit() const
|
|
{
|
|
return m_edit;
|
|
}
|
|
|
|
void SearchLineWidget::slotSearchStarted()
|
|
{
|
|
m_timer->start( 100 );
|
|
}
|
|
|
|
void SearchLineWidget::slotSearchStopped()
|
|
{
|
|
m_timer->stop();
|
|
m_anim->hide();
|
|
}
|
|
|
|
void SearchLineWidget::slotTimedout()
|
|
{
|
|
if ( m_anim->sequence().isEmpty() )
|
|
{
|
|
const KPixmapSequence seq = KIconLoader::global()->loadPixmapSequence(QStringLiteral("process-working"), 22);
|
|
if ( seq.frameCount() > 0 )
|
|
{
|
|
m_anim->setInterval( 1000 / seq.frameCount() );
|
|
m_anim->setSequence( seq );
|
|
}
|
|
}
|
|
m_anim->show();
|
|
}
|
|
|
|
#include "moc_searchlineedit.cpp"
|