00001
00002 #include <qlayout.h>
00003 #include <qfontmetrics.h>
00004 #include <qpainter.h>
00005
00006
00007 #include <mythtv/mythcontext.h>
00008 #include <mythtv/mythdbcon.h>
00009
00010
00011 #include "search.h"
00012
00013 SearchDialog::SearchDialog(MythMainWindow *parent, const char *name)
00014 : MythPopupBox(parent, name)
00015 {
00016
00017
00018
00019 caption = addLabel(QString(tr("Search Music Database")));
00020 QFont font = caption->font();
00021 font.setPointSize(int (font.pointSize() * 1.2));
00022 font.setBold(true);
00023 caption->setFont(font);
00024 caption->setPaletteForegroundColor(QColor("yellow"));
00025 caption->setBackgroundOrigin(ParentOrigin);
00026 caption->setAlignment(Qt::AlignCenter);
00027 caption->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,
00028 QSizePolicy::Fixed));
00029 caption->setMinimumWidth((int)(600 * hmult));
00030 caption->setMaximumWidth((int)(600 * hmult));
00031
00032
00033 searchText = new MythLineEdit(this);
00034 searchText->setRW();
00035 searchText->setFocus();
00036 searchText->setPopupPosition(VK_POSBOTTOMDIALOG);
00037 connect(searchText, SIGNAL(textChanged(const QString &)),
00038 this, SLOT(searchTextChanged(const QString &)));
00039 addWidget(searchText);
00040
00041
00042 listbox = new MythListBox(this);
00043 listbox->setScrollBar(false);
00044 listbox->setBottomScrollBar(false);
00045 connect(listbox, SIGNAL(accepted(int)), this, SLOT(itemSelected(int)));
00046 addWidget(listbox);
00047
00048
00049 okButton = addButton(tr("OK"), this, SLOT(accept()));
00050 cancelButton = addButton(tr("Cancel"), this, SLOT(reject()));
00051
00052
00053 runQuery("");
00054 }
00055
00056 void SearchDialog::searchTextChanged(const QString &searchText)
00057 {
00058 runQuery(searchText);
00059 }
00060
00061 const char *mapping[] =
00062 {
00063 "[0 ]", "1", "[2abc]", "[3def]", "[4ghi]",
00064 "[5jkl]", "[6mno]", "[7pqrs]", "[8tuv]", "[9wxyz]"
00065 };
00066
00067 void SearchDialog::runQuery(QString searchText)
00068 {
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 bool substringSearch = true;
00081 bool isNumber = false;
00082 searchText.toULongLong(&isNumber);
00083 QString searchLimit = gContext->GetSetting("MaxSearchResults");
00084 searchText.replace("'", "''");
00085 searchText = searchText.utf8();
00086
00087 if (!isNumber)
00088 {
00089 QString testString = searchText;
00090 testString.replace(">","");
00091 testString.toULongLong(&isNumber);
00092 }
00093
00094 if (isNumber)
00095 {
00096
00097 for (int i = 0; i < 10; i++)
00098 {
00099 char c = '0' + i;
00100 searchText.replace(QChar(c), QString(mapping[i]));
00101 }
00102 substringSearch = false;
00103 }
00104
00105 listbox->clear();
00106
00107 MSqlQuery query(MSqlQuery::InitCon());
00108
00109 QString queryString("SELECT filename, music_artists.artist_name, album_name, name, song_id "
00110 "FROM music_songs "
00111 "LEFT JOIN music_artists ON music_songs.artist_id=music_artists.artist_id "
00112 "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id ");
00113
00114 QStringList list = QStringList::split(QRegExp("[>,]"), searchText);
00115 whereClause = "";
00116 if (!searchText.isEmpty())
00117 {
00118 if (substringSearch)
00119 {
00120 for (uint i = 0; i < list.count(); i++)
00121 {
00122 QString stxt = list[i];
00123 whereClause += (i) ? " AND ( " : "WHERE (";
00124 whereClause +=
00125 "filename LIKE '%" + stxt + "%' OR "
00126 "music_artists.artist_name LIKE '%" + stxt + "%' OR "
00127 "album_name LIKE '%" + stxt + "%' OR "
00128 "name LIKE '%" + stxt + "%')";
00129 }
00130 }
00131 else
00132 {
00133 for (uint i = 0; i < list.count(); i++)
00134 {
00135 QString stxt = list[i].stripWhiteSpace();
00136 whereClause += (i) ? " AND ( " : "WHERE (";
00137 whereClause +=
00138 "filename REGEXP '" + stxt + "' OR "
00139 "music_artists.artist_name REGEXP '" + stxt + "' OR "
00140 "album_name REGEXP '" + stxt + "' OR "
00141 "name REGEXP '" + stxt + "')";
00142 }
00143 }
00144 }
00145
00146 queryString += whereClause;
00147 queryString += " ORDER BY music_artists.artist_name, album_name, name, song_id, filename ";
00148 queryString += "LIMIT ";
00149 queryString += searchLimit;
00150 query.prepare(queryString);
00151
00152 bool has_entries = true;
00153 if (!query.exec() || !query.isActive())
00154 {
00155 MythContext::DBError("Search music database", query);
00156 has_entries = false;
00157 }
00158 has_entries &= (query.numRowsAffected() > 0);
00159
00160 uint matchCount = 0;
00161
00162 while (has_entries && query.next())
00163 {
00164 QString aComposer(query.value(1).toString());
00165 QString aTitle(query.value(2).toString());
00166 aTitle.truncate( 30 );
00167
00168 QString text(aComposer + ": " + aTitle + "; " +
00169 query.value(3).toString() );
00170
00171
00172 if(!searchText.isEmpty())
00173 {
00174 if (substringSearch)
00175 {
00176 for (uint i = 0; i < list.count(); i++)
00177 {
00178 QString stxt = list[i];
00179 stxt.replace("''", "'");
00180 int index = -1;
00181 while( (index = text.findRev(stxt, index, false)) != -1 )
00182 {
00183 text.insert(index + stxt.length(), "]");
00184 text.insert(index, "[");
00185 }
00186 }
00187 }
00188 else
00189 {
00190 for (uint i = 0; i < list.count(); i++)
00191 {
00192 QString stxt = list[i].stripWhiteSpace();
00193 int index = -1;
00194 while( (index = text.findRev(QRegExp(stxt, false), index)) != -1 )
00195 {
00196 text.insert(index + stxt.contains('['), "]");
00197 text.insert(index, "[");
00198 }
00199 }
00200 }
00201 }
00202
00203
00204 listbox->insertItem(new SearchListBoxItem(
00205 QString::fromUtf8(text),
00206 query.value(4).toUInt()));
00207
00208 matchCount++;
00209 }
00210
00211 if (!has_entries)
00212 {
00213 listbox->setCurrentItem(0);
00214 listbox->setTopItem(0);
00215 }
00216
00217 QString captionText =
00218 tr("Search Music Database (%1 matches)").arg(matchCount);
00219 caption->setText(captionText);
00220 }
00221
00222 void SearchDialog::itemSelected(int i)
00223 {
00224 unsigned int id = ((SearchListBoxItem*)listbox->item(i))->getId();
00225 whereClause = QString("WHERE song_id='%1';").arg(id);
00226 accept();
00227 }
00228
00229
00230 void SearchDialog::getWhereClause(QString &whereClause)
00231 {
00232 whereClause = this->whereClause;
00233 }
00234
00235 SearchDialog::~SearchDialog()
00236 {
00237 }
00238
00239 void SearchListBoxItem::paint(QPainter *p)
00240 {
00241 int itemHeight = height(listBox());
00242 QFontMetrics fm = p->fontMetrics();
00243 int yPos = ((itemHeight - fm.height()) / 2) + fm.ascent();
00244
00245 QColor normalColor = p->pen().color();
00246 QColor highlightColor = QColor("yellow");
00247
00248 QString sText = text();
00249 int xPos = 3;
00250 int start, end;
00251 int index = 0;
00252 QString sNormal, sHighlight;
00253
00254 while (index < (int) sText.length())
00255 {
00256 start = sText.find('[', index);
00257 end = sText.find(']', start);
00258
00259 if (start != -1 && end != -1)
00260 {
00261 sNormal = sText.mid(index, start - index);
00262 sHighlight = sText.mid(start + 1, end - start -1);
00263 index = end + 1;
00264 }
00265 else
00266 {
00267 sNormal = sText.mid(index, 0xffffffff);
00268 sHighlight = "";
00269 index = sText.length();
00270 }
00271
00272 if (sNormal != "")
00273 {
00274 p->setPen(normalColor);
00275 p->drawText(xPos, yPos, sNormal);
00276 xPos += fm.width(sNormal);
00277 }
00278
00279 if (sHighlight != "")
00280 {
00281 p->setPen(highlightColor);
00282 p->drawText(xPos, yPos, sHighlight);
00283 xPos += fm.width(sHighlight);
00284 }
00285 }
00286 }