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: