File indexing completed on 2023-05-30 11:30:51

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 <QLineEdit>
0034 #include <QPushButton>
0035 
0036 using namespace ActionCollection;
0037 
0038 ////////////////////////////////////////////////////////////////////////////////
0039 // SearchLine public methods
0040 ////////////////////////////////////////////////////////////////////////////////
0041 
0042 SearchLine::SearchLine(QWidget *parent, bool simple)
0043     : QWidget(parent),
0044     m_simple(simple),
0045     m_searchFieldsBox(0)
0046 {
0047     QHBoxLayout *layout = new QHBoxLayout(this);
0048     layout->setContentsMargins(0, 0, 0, 0);
0049     layout->setSpacing(5);
0050 
0051     if(!m_simple) {
0052         m_searchFieldsBox = new QComboBox(this);
0053         layout->addWidget(m_searchFieldsBox);
0054         m_searchFieldsBox->setObjectName( QLatin1String( "searchFields" ) );
0055         connect(m_searchFieldsBox, SIGNAL(activated(int)),
0056                 this, SIGNAL(signalQueryChanged()));
0057     }
0058 
0059     m_lineEdit = new QLineEdit(this);
0060     layout->addWidget(m_lineEdit);
0061     m_lineEdit->setClearButtonEnabled(true);
0062     m_lineEdit->installEventFilter(this);
0063     setFocusProxy(m_lineEdit);
0064     connect(m_lineEdit, SIGNAL(textChanged(QString)),
0065             this, SIGNAL(signalQueryChanged()));
0066     connect(m_lineEdit, SIGNAL(returnPressed()),
0067             this, SLOT(slotActivate()));
0068 
0069     if(!m_simple) {
0070         m_caseSensitive = new QComboBox(this);
0071         layout->addWidget(m_caseSensitive);
0072         m_caseSensitive->addItem(i18n("Normal Matching"));
0073         m_caseSensitive->addItem(i18n("Case Sensitive"));
0074         m_caseSensitive->addItem(i18n("Pattern Matching"));
0075         connect(m_caseSensitive, SIGNAL(activated(int)),
0076                 this, SIGNAL(signalQueryChanged()));
0077     }
0078     else
0079         m_caseSensitive = 0;
0080 
0081     updateColumns();
0082 }
0083 
0084 PlaylistSearch::Component SearchLine::searchComponent() const
0085 {
0086     QString query = m_lineEdit->text();
0087     bool caseSensitive = m_caseSensitive && m_caseSensitive->currentIndex() == CaseSensitive;
0088 
0089     Playlist *playlist = CollectionList::instance();
0090 
0091     QVector<int> searchedColumns;
0092 
0093     if(!m_searchFieldsBox || m_searchFieldsBox->currentIndex() == 0) {
0094         foreach(int column, m_columnList) {
0095             if(!playlist->isColumnHidden(column))
0096                 searchedColumns.append(column);
0097         }
0098     }
0099     else
0100         searchedColumns.append(m_columnList[m_searchFieldsBox->currentIndex() - 1]);
0101 
0102     if(m_caseSensitive && m_caseSensitive->currentIndex() == Pattern)
0103         return PlaylistSearch::Component(QRegExp(query), searchedColumns);
0104     else
0105         return PlaylistSearch::Component(query, caseSensitive, searchedColumns);
0106 }
0107 
0108 void SearchLine::setSearchComponent(const PlaylistSearch::Component &component)
0109 {
0110     if(component == searchComponent())
0111         return;
0112 
0113     if(m_simple || !component.isPatternSearch()) {
0114         m_lineEdit->setText(component.query());
0115         if(m_caseSensitive)
0116             m_caseSensitive->setCurrentIndex(component.isCaseSensitive() ? CaseSensitive : Default);
0117     }
0118     else {
0119         m_lineEdit->setText(component.pattern().pattern());
0120         if(m_caseSensitive)
0121             m_caseSensitive->setCurrentIndex(Pattern);
0122     }
0123 
0124     if(!m_simple) {
0125         if(component.columns().isEmpty() || component.columns().size() > 1)
0126             m_searchFieldsBox->setCurrentIndex(0);
0127         else
0128             m_searchFieldsBox->setCurrentIndex(component.columns().constFirst() + 1);
0129     }
0130 }
0131 
0132 void SearchLine::clear()
0133 {
0134     // We don't want to emit the signal if it's already empty.
0135     if(!m_lineEdit->text().isEmpty())
0136         m_lineEdit->clear();
0137 }
0138 
0139 bool SearchLine::eventFilter(QObject *watched, QEvent *e)
0140 {
0141     if(watched != m_lineEdit || e->type() != QEvent::KeyPress)
0142         return QWidget::eventFilter(watched, e);
0143 
0144     QKeyEvent *key = static_cast<QKeyEvent *>(e);
0145     if(key->key() == Qt::Key_Down)
0146         emit signalDownPressed();
0147 
0148     return QWidget::eventFilter(watched, e);
0149 }
0150 
0151 void SearchLine::slotActivate()
0152 {
0153     action("stop")->trigger();
0154     action("playFirst")->trigger();
0155 }
0156 
0157 void SearchLine::updateColumns()
0158 {
0159     QString currentText;
0160 
0161     if(m_searchFieldsBox) {
0162         currentText = m_searchFieldsBox->currentText();
0163         m_searchFieldsBox->clear();
0164     }
0165 
0166     QStringList columnHeaders;
0167 
0168     columnHeaders.append(QString("<%1>").arg(i18n("All Visible")));
0169 
0170     Playlist *playlist = CollectionList::instance();
0171 
0172     int selection = -1;
0173     m_columnList.clear();
0174 
0175     for(int i = 0; i < playlist->columnCount(); i++) {
0176         m_columnList.append(i);
0177         QString text = playlist->headerItem()->text(i);
0178         columnHeaders.append(text);
0179         if(currentText == text)
0180             selection = m_columnList.size() - 1;
0181     }
0182 
0183     if(m_searchFieldsBox) {
0184         m_searchFieldsBox->addItems(columnHeaders);
0185         m_searchFieldsBox->setCurrentIndex(selection + 1);
0186     }
0187 }
0188 
0189 ////////////////////////////////////////////////////////////////////////////////
0190 // SearchWidget public methods
0191 ////////////////////////////////////////////////////////////////////////////////
0192 
0193 SearchWidget::SearchWidget(QWidget *parent)
0194     : SearchLine(parent, true)
0195 {
0196     new SearchAdaptor(this);
0197     QDBusConnection::sessionBus().registerObject("/Search", this);
0198 
0199     m_lineEdit->setPlaceholderText(i18n("Search..."));
0200 
0201     connect(m_lineEdit, SIGNAL(returnPressed()), this, SIGNAL(returnPressed()));
0202     setFocusProxy(m_lineEdit);
0203 
0204     updateColumns();
0205 }
0206 
0207 void SearchWidget::setSearch(const PlaylistSearch* search)
0208 {
0209     PlaylistSearch::ComponentList components = search->components();
0210 
0211     if(components.isEmpty()) {
0212         clear();
0213         return;
0214     }
0215 
0216     setSearchComponent(*components.begin());
0217 }
0218 
0219 QString SearchWidget::searchText() const
0220 {
0221     return searchComponent().query();
0222 }
0223 
0224 void SearchWidget::setSearchText(const QString &text)
0225 {
0226     setSearchComponent(PlaylistSearch::Component(text));
0227 }
0228 
0229 PlaylistSearch* SearchWidget::search(const PlaylistList &playlists) const
0230 {
0231     PlaylistSearch::ComponentList components;
0232     components.append(searchComponent());
0233     return new PlaylistSearch(std::move(playlists), std::move(components));
0234 }
0235 
0236 PlaylistSearch* SearchWidget::search(Playlist *playlist) const
0237 {
0238     PlaylistSearch::ComponentList components;
0239     components.append(searchComponent());
0240 
0241     PlaylistList playlists = (PlaylistList{} << playlist);
0242     return new PlaylistSearch(std::move(playlists), std::move(components));
0243 }
0244 
0245 ////////////////////////////////////////////////////////////////////////////////
0246 // SearchWidget public slots
0247 ////////////////////////////////////////////////////////////////////////////////
0248 
0249 void SearchWidget::setEnabled(bool enable)
0250 {
0251     emit signalShown(enable);
0252     setVisible(enable);
0253 }
0254 
0255 // vim: set et sw=4 tw=0 sta: