File indexing completed on 2021-12-21 13:28:00

0001 /**
0002  * Copyright (C) 2003 Richard Lärkäng <nouseforaname@home.se>
0003  * Copyright (C) 2003-2004 Scott Wheeler <wheeler@kde.org>
0004  *
0005  * This program is free software; you can redistribute it and/or modify it under
0006  * the terms of the GNU General Public License as published by the Free Software
0007  * Foundation; either version 2 of the License, or (at your option) any later
0008  * version.
0009  *
0010  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0011  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0012  * PARTICULAR PURPOSE. See the GNU General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU General Public License along with
0015  * this program.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 #include "searchwidget.h"
0019 #include "collectionlist.h"
0020 #include "actioncollection.h"
0021 #include "searchadaptor.h"
0022 #include "juk_debug.h"
0023 
0024 #include <utility>
0025 
0026 #include <KLocalizedString>
0027 
0028 #include <QAction>
0029 #include <QCheckBox>
0030 #include <QComboBox>
0031 #include <QHBoxLayout>
0032 #include <QKeyEvent>
0033 #include <QLabel>
0034 #include <QLineEdit>
0035 #include <QPushButton>
0036 #include <QToolButton>
0037 
0038 using namespace ActionCollection;
0039 
0040 ////////////////////////////////////////////////////////////////////////////////
0041 // SearchLine public methods
0042 ////////////////////////////////////////////////////////////////////////////////
0043 
0044 SearchLine::SearchLine(QWidget *parent, bool simple)
0045     : QWidget(parent),
0046     m_simple(simple),
0047     m_searchFieldsBox(0)
0048 {
0049     QHBoxLayout *layout = new QHBoxLayout(this);
0050     layout->setContentsMargins(0, 0, 0, 0);
0051     layout->setSpacing(5);
0052 
0053     if(!m_simple) {
0054         m_searchFieldsBox = new QComboBox(this);
0055         layout->addWidget(m_searchFieldsBox);
0056         m_searchFieldsBox->setObjectName( QLatin1String( "searchFields" ) );
0057         connect(m_searchFieldsBox, SIGNAL(activated(int)),
0058                 this, SIGNAL(signalQueryChanged()));
0059     }
0060 
0061     m_lineEdit = new QLineEdit(this);
0062     layout->addWidget(m_lineEdit);
0063     m_lineEdit->setClearButtonEnabled(true);
0064     m_lineEdit->installEventFilter(this);
0065     setFocusProxy(m_lineEdit);
0066     connect(m_lineEdit, SIGNAL(textChanged(QString)),
0067             this, SIGNAL(signalQueryChanged()));
0068     connect(m_lineEdit, SIGNAL(returnPressed()),
0069             this, SLOT(slotActivate()));
0070 
0071     if(!m_simple) {
0072         m_caseSensitive = new QComboBox(this);
0073         layout->addWidget(m_caseSensitive);
0074         m_caseSensitive->addItem(i18n("Normal Matching"));
0075         m_caseSensitive->addItem(i18n("Case Sensitive"));
0076         m_caseSensitive->addItem(i18n("Pattern Matching"));
0077         connect(m_caseSensitive, SIGNAL(activated(int)),
0078                 this, SIGNAL(signalQueryChanged()));
0079     }
0080     else
0081         m_caseSensitive = 0;
0082 
0083     updateColumns();
0084 }
0085 
0086 PlaylistSearch::Component SearchLine::searchComponent() const
0087 {
0088     QString query = m_lineEdit->text();
0089     bool caseSensitive = m_caseSensitive && m_caseSensitive->currentIndex() == CaseSensitive;
0090 
0091     Playlist *playlist = CollectionList::instance();
0092 
0093     QVector<int> searchedColumns;
0094 
0095     if(!m_searchFieldsBox || m_searchFieldsBox->currentIndex() == 0) {
0096         foreach(int column, m_columnList) {
0097             if(!playlist->isColumnHidden(column))
0098                 searchedColumns.append(column);
0099         }
0100     }
0101     else
0102         searchedColumns.append(m_columnList[m_searchFieldsBox->currentIndex() - 1]);
0103 
0104     if(m_caseSensitive && m_caseSensitive->currentIndex() == Pattern)
0105         return PlaylistSearch::Component(QRegExp(query), searchedColumns);
0106     else
0107         return PlaylistSearch::Component(query, caseSensitive, searchedColumns);
0108 }
0109 
0110 void SearchLine::setSearchComponent(const PlaylistSearch::Component &component)
0111 {
0112     if(component == searchComponent())
0113         return;
0114 
0115     if(m_simple || !component.isPatternSearch()) {
0116         m_lineEdit->setText(component.query());
0117         if(m_caseSensitive)
0118             m_caseSensitive->setCurrentIndex(component.isCaseSensitive() ? CaseSensitive : Default);
0119     }
0120     else {
0121         m_lineEdit->setText(component.pattern().pattern());
0122         if(m_caseSensitive)
0123             m_caseSensitive->setCurrentIndex(Pattern);
0124     }
0125 
0126     if(!m_simple) {
0127         if(component.columns().isEmpty() || component.columns().size() > 1)
0128             m_searchFieldsBox->setCurrentIndex(0);
0129         else
0130             m_searchFieldsBox->setCurrentIndex(component.columns().constFirst() + 1);
0131     }
0132 }
0133 
0134 void SearchLine::clear()
0135 {
0136     // We don't want to emit the signal if it's already empty.
0137     if(!m_lineEdit->text().isEmpty())
0138         m_lineEdit->clear();
0139 }
0140 
0141 bool SearchLine::eventFilter(QObject *watched, QEvent *e)
0142 {
0143     if(watched != m_lineEdit || e->type() != QEvent::KeyPress)
0144         return QWidget::eventFilter(watched, e);
0145 
0146     QKeyEvent *key = static_cast<QKeyEvent *>(e);
0147     if(key->key() == Qt::Key_Down)
0148         emit signalDownPressed();
0149 
0150     return QWidget::eventFilter(watched, e);
0151 }
0152 
0153 void SearchLine::slotActivate()
0154 {
0155     action("stop")->trigger();
0156     action("playFirst")->trigger();
0157 }
0158 
0159 void SearchLine::updateColumns()
0160 {
0161     QString currentText;
0162 
0163     if(m_searchFieldsBox) {
0164         currentText = m_searchFieldsBox->currentText();
0165         m_searchFieldsBox->clear();
0166     }
0167 
0168     QStringList columnHeaders;
0169 
0170     columnHeaders.append(QString("<%1>").arg(i18n("All Visible")));
0171 
0172     Playlist *playlist = CollectionList::instance();
0173 
0174     int selection = -1;
0175     m_columnList.clear();
0176 
0177     for(int i = 0; i < playlist->columnCount(); i++) {
0178         m_columnList.append(i);
0179         QString text = playlist->headerItem()->text(i);
0180         columnHeaders.append(text);
0181         if(currentText == text)
0182             selection = m_columnList.size() - 1;
0183     }
0184 
0185     if(m_searchFieldsBox) {
0186         m_searchFieldsBox->addItems(columnHeaders);
0187         m_searchFieldsBox->setCurrentIndex(selection + 1);
0188     }
0189 }
0190 
0191 ////////////////////////////////////////////////////////////////////////////////
0192 // SearchWidget public methods
0193 ////////////////////////////////////////////////////////////////////////////////
0194 
0195 SearchWidget::SearchWidget(QWidget *parent)
0196     : SearchLine(parent, true)
0197 {
0198     new SearchAdaptor(this);
0199     QDBusConnection::sessionBus().registerObject("/Search", this);
0200 
0201     m_lineEdit->setPlaceholderText(i18n("Search..."));
0202 
0203     connect(m_lineEdit, SIGNAL(returnPressed()), this, SIGNAL(returnPressed()));
0204     setFocusProxy(m_lineEdit);
0205 
0206     updateColumns();
0207 }
0208 
0209 void SearchWidget::setSearch(const PlaylistSearch* search)
0210 {
0211     PlaylistSearch::ComponentList components = search->components();
0212 
0213     if(components.isEmpty()) {
0214         clear();
0215         return;
0216     }
0217 
0218     setSearchComponent(*components.begin());
0219 }
0220 
0221 QString SearchWidget::searchText() const
0222 {
0223     return searchComponent().query();
0224 }
0225 
0226 void SearchWidget::setSearchText(const QString &text)
0227 {
0228     setSearchComponent(PlaylistSearch::Component(text));
0229 }
0230 
0231 PlaylistSearch* SearchWidget::search(const PlaylistList &playlists) const
0232 {
0233     PlaylistSearch::ComponentList components;
0234     components.append(searchComponent());
0235     return new PlaylistSearch(std::move(playlists), std::move(components));
0236 }
0237 
0238 PlaylistSearch* SearchWidget::search(Playlist *playlist) const
0239 {
0240     PlaylistSearch::ComponentList components;
0241     components.append(searchComponent());
0242 
0243     PlaylistList playlists = (PlaylistList{} << playlist);
0244     return new PlaylistSearch(std::move(playlists), std::move(components));
0245 }
0246 
0247 ////////////////////////////////////////////////////////////////////////////////
0248 // SearchWidget public slots
0249 ////////////////////////////////////////////////////////////////////////////////
0250 
0251 void SearchWidget::setEnabled(bool enable)
0252 {
0253     emit signalShown(enable);
0254     setVisible(enable);
0255 }
0256 
0257 // vim: set et sw=4 tw=0 sta: