MythTV  0.26-pre
searchview.cpp
Go to the documentation of this file.
00001 #include <iostream>
00002 #include <cstdlib>
00003 
00004 // qt
00005 #include <QKeyEvent>
00006 
00007 // myth
00008 #include <mythdialogbox.h>
00009 #include <mythuitextedit.h>
00010 #include <mythuibuttonlist.h>
00011 #include <mythdb.h>
00012 
00013 // mythmusic
00014 #include "musiccommon.h"
00015 #include "searchview.h"
00016 
00017 SearchView::SearchView(MythScreenStack *parent)
00018          :MusicCommon(parent, "searchview"),
00019             m_playTrack(false), m_fieldList(NULL), m_criteriaEdit(NULL),
00020             m_matchesText(NULL), m_tracksList(NULL)
00021 {
00022     m_currentView = MV_SEARCH;
00023 }
00024 
00025 SearchView::~SearchView()
00026 {
00027 }
00028 
00029 bool SearchView::Create(void)
00030 {
00031     bool err = false;
00032 
00033     // Load the theme for this screen
00034     err = LoadWindowFromXML("music-ui.xml", "searchview", this);
00035 
00036     if (!err)
00037         return false;
00038 
00039     // find common widgets available on any view
00040     err = CreateCommon();
00041 
00042     // find widgets specific to this view
00043     UIUtilE::Assign(this, m_fieldList,    "field_list",    &err);
00044     UIUtilE::Assign(this, m_criteriaEdit, "criteria_edit", &err);
00045     UIUtilW::Assign(this, m_matchesText,  "matches_text",  &err);
00046     UIUtilE::Assign(this, m_tracksList,   "tracks_list",   &err);
00047 
00048     if (err)
00049     {
00050         LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'searchview'");
00051         return false;
00052     }
00053 
00054     BuildFocusList();
00055 
00056     new MythUIButtonListItem(m_fieldList, tr("All Fields"),
00057                                 qVariantFromValue(0));
00058     new MythUIButtonListItem(m_fieldList, tr("Artist"),
00059                                 qVariantFromValue(1));
00060     new MythUIButtonListItem(m_fieldList, tr("Album"),
00061                                 qVariantFromValue(2));
00062     new MythUIButtonListItem(m_fieldList, tr("Title"),
00063                                 qVariantFromValue(3));
00064     new MythUIButtonListItem(m_fieldList, tr("Genre"),
00065                                 qVariantFromValue(4));
00066     //new MythUIButtonListItem(m_fieldList, tr("Tags"),
00067     //                            qVariantFromValue(5));
00068 
00069     connect(m_fieldList, SIGNAL(itemSelected(MythUIButtonListItem*)),
00070             this, SLOT(fieldSelected(MythUIButtonListItem*)));
00071 
00072     connect(m_tracksList, SIGNAL(itemClicked(MythUIButtonListItem*)),
00073             this, SLOT(trackClicked(MythUIButtonListItem*)));
00074 
00075     connect(m_tracksList, SIGNAL(itemVisible(MythUIButtonListItem*)),
00076             this, SLOT(trackVisible(MythUIButtonListItem*)));
00077 
00078     connect(m_criteriaEdit, SIGNAL(valueChanged()), this, SLOT(criteriaChanged()));
00079 
00080     updateTracksList();
00081 
00082     return true;
00083 }
00084 
00085 void SearchView::customEvent(QEvent *event)
00086 {
00087     bool handled = false;
00088 
00089     if (event->type() == MusicPlayerEvent::TrackRemovedEvent ||
00090         event->type() == MusicPlayerEvent::TrackAddedEvent)
00091     {
00092         MusicPlayerEvent *mpe = dynamic_cast<MusicPlayerEvent *>(event);
00093 
00094         if (!mpe)
00095             return;
00096 
00097         int trackID = mpe->TrackID;
00098 
00099         for (int x = 0; x < m_tracksList->GetCount(); x++)
00100         {
00101             MythUIButtonListItem *item = m_tracksList->GetItemAt(x);
00102             Metadata *mdata = qVariantValue<Metadata*> (item->GetData());
00103             if (mdata && (mdata->ID() == (Metadata::IdType) trackID || trackID == -1))
00104             {
00105                 if (gPlayer->getPlaylist()->checkTrack(mdata->ID()))
00106                     item->DisplayState("on", "selectedstate");
00107                 else
00108                     item->DisplayState("off", "selectedstate");
00109             }
00110         }
00111 
00112         // call the default handler in MusicCommon so the playlist and UI is updated
00113         MusicCommon::customEvent(event);
00114         handled = true;
00115 
00116         if (m_playTrack)
00117         {
00118             m_playTrack = false;
00119 
00120             if (event->type() == MusicPlayerEvent::TrackAddedEvent)
00121             {
00122                 // make the added track current and play it
00123                 m_currentPlaylist->SetItemCurrent(m_currentPlaylist->GetCount() - 1);
00124                 playlistItemClicked(m_currentPlaylist->GetItemCurrent());
00125             }
00126         }
00127     }
00128     else if (event->type() == MusicPlayerEvent::AllTracksRemovedEvent)
00129     {
00130         for (int x = 0; x < m_tracksList->GetCount(); x++)
00131         {
00132             MythUIButtonListItem *item = m_tracksList->GetItemAt(x);
00133             if (item)
00134                 item->DisplayState("off", "selectedstate");
00135         }
00136     }
00137     else if (event->type() == MusicPlayerEvent::MetadataChangedEvent)
00138     {
00139         MusicPlayerEvent *mpe = dynamic_cast<MusicPlayerEvent *>(event);
00140 
00141         if (!mpe)
00142             return;
00143 
00144         uint trackID = mpe->TrackID;
00145 
00146         for (int x = 0; x < m_tracksList->GetCount(); x++)
00147         {
00148             MythUIButtonListItem *item = m_tracksList->GetItemAt(x);
00149             Metadata *mdata = qVariantValue<Metadata*> (item->GetData());
00150             if (mdata && mdata->ID() == trackID)
00151             {
00152                 MetadataMap metadataMap;
00153                 mdata->toMap(metadataMap);
00154                 item->SetTextFromMap(metadataMap);
00155             }
00156         }
00157 
00158 //        if (trackID == gPlayer->getCurrentMetadata()->ID())
00159 //            updateTrackInfo(gPlayer->getCurrentMetadata());
00160     }
00161     else if (event->type() == DialogCompletionEvent::kEventType)
00162     {
00163         DialogCompletionEvent *dce = static_cast<DialogCompletionEvent *>(event);
00164 
00165         // make sure the user didn't ESCAPE out of the menu
00166         if (dce->GetResult() < 0)
00167             return;
00168 
00169         QString resultid   = dce->GetId();
00170         QString resulttext = dce->GetResultText();
00171         if (resultid == "searchviewmenu")
00172         {
00173             if (resulttext == tr("Add To Playlist") || resulttext == tr("Remove From Playlist"))
00174             {
00175                 if (GetFocusWidget() == m_tracksList)
00176                 {
00177                     MythUIButtonListItem *item = m_tracksList->GetItemCurrent();
00178                     if (item)
00179                     {
00180                         m_playTrack = false;
00181                         trackClicked(item);
00182                     }
00183                 }
00184             }
00185             else if (resulttext == tr("Add To Playlist And Play"))
00186             {
00187                 if (GetFocusWidget() == m_tracksList)
00188                 {
00189                     MythUIButtonListItem *item = m_tracksList->GetItemCurrent();
00190                     if (item)
00191                     {
00192                         m_playTrack = true;
00193                         trackClicked(item);
00194                     }
00195                 }
00196             }
00197             else if (resulttext == tr("Search List..."))
00198                 searchButtonList();
00199         }
00200     }
00201 
00202     if (!handled)
00203         MusicCommon::customEvent(event);
00204 }
00205 
00206 bool SearchView::keyPressEvent(QKeyEvent *event)
00207 {
00208     if (!m_moveTrackMode && GetFocusWidget() && GetFocusWidget()->keyPressEvent(event))
00209         return true;
00210 
00211     bool handled = false;
00212     QStringList actions;
00213     handled = GetMythMainWindow()->TranslateKeyPress("Music", event, actions);
00214 
00215     for (int i = 0; i < actions.size() && !handled; i++)
00216     {
00217         QString action = actions[i];
00218         handled = true;
00219 
00220         if (action == "INFO" || action == "EDIT")
00221         {
00222             if (GetFocusWidget() == m_tracksList)
00223             {
00224                 if (m_tracksList->GetItemCurrent())
00225                 {
00226                     Metadata *mdata = qVariantValue<Metadata*> (m_tracksList->GetItemCurrent()->GetData());
00227                     if (mdata)
00228                     {
00229                         if (action == "INFO")
00230                             showTrackInfo(mdata);
00231                         else
00232                             editTrackInfo(mdata);
00233                     }
00234                 }
00235             }
00236             else
00237                 handled = false;
00238         }
00239         else if (action == "PLAY" || action == "PAUSE")
00240         {
00241             if (GetFocusWidget() == m_tracksList)
00242             {
00243                 MythUIButtonListItem *item = m_tracksList->GetItemCurrent();
00244                 if (item)
00245                 {
00246                     m_playTrack = true;
00247                     trackClicked(item);
00248                 }
00249             }
00250             else
00251                 handled = false;
00252         }
00253         else
00254             handled = false;
00255     }
00256 
00257     if (!handled && MusicCommon::keyPressEvent(event))
00258         handled = true;
00259 
00260     if (!handled && MythScreenType::keyPressEvent(event))
00261         handled = true;
00262 
00263     return handled;
00264 }
00265 
00266 void SearchView::ShowMenu(void)
00267 {
00268     if (GetFocusWidget() == m_tracksList)
00269     {
00270         QString label = tr("Search Actions");
00271 
00272         MythMenu *menu = new MythMenu(label, this, "searchviewmenu");
00273 
00274         MythUIButtonListItem *item = m_tracksList->GetItemCurrent();
00275         if (item)
00276         {
00277             Metadata *mdata = qVariantValue<Metadata*> (item->GetData());
00278             if (mdata)
00279             {
00280                 if (gPlayer->getPlaylist()->checkTrack(mdata->ID()))
00281                     menu->AddItem(tr("Remove From Playlist"));
00282                 else
00283                 {
00284                     menu->AddItem(tr("Add To Playlist"));
00285                     menu->AddItem(tr("Add To Playlist And Play"));
00286                 }
00287             }
00288         }
00289 
00290         if (GetFocusWidget() == m_tracksList || GetFocusWidget() == m_currentPlaylist)
00291             menu->AddItem(tr("Search List..."));
00292 
00293         menu->AddItem(tr("More Options"), NULL, createMainMenu());
00294 
00295         MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
00296 
00297         MythDialogBox *menuPopup = new MythDialogBox(menu, popupStack, "actionmenu");
00298 
00299         if (menuPopup->Create())
00300             popupStack->AddScreen(menuPopup);
00301         else
00302             delete menu;
00303     }
00304     else
00305         MusicCommon::ShowMenu();
00306 }
00307 
00308 void SearchView::fieldSelected(MythUIButtonListItem *item)
00309 {
00310     (void) item;
00311     updateTracksList();
00312 }
00313 
00314 void SearchView::criteriaChanged(void)
00315 {
00316     updateTracksList();
00317 }
00318 
00319 void SearchView::updateTracksList(void)
00320 {
00321     m_tracksList->Reset();
00322 
00323     MythUIButtonListItem *item = m_fieldList->GetItemCurrent();
00324 
00325     if (!item)
00326         return;
00327 
00328     QString searchStr = m_criteriaEdit->GetText();
00329     int field = item->GetData().toInt();
00330 
00331     QString sql;
00332     MSqlQuery query(MSqlQuery::InitCon());
00333 
00334     if (searchStr.isEmpty())
00335     {
00336         sql = "SELECT song_id "
00337               "FROM music_songs ";
00338 
00339         query.prepare(sql);
00340     }
00341     else
00342     {
00343         switch(field)
00344         {
00345             case 1: // artist
00346             {
00347                 sql = "SELECT song_id "
00348                       "FROM music_songs "
00349                       "LEFT JOIN music_artists ON "
00350                       "    music_songs.artist_id=music_artists.artist_id "
00351                       "WHERE music_artists.artist_name LIKE '%" + searchStr + "%' ";
00352                 query.prepare(sql);
00353                 break;
00354             }
00355             case 2: // album
00356             {
00357                 sql = "SELECT song_id "
00358                       "FROM music_songs "
00359                       "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id "
00360                       "WHERE music_albums.album_name LIKE '%" + searchStr + "%' ";
00361                 query.prepare(sql);
00362                 break;
00363             }
00364             case 3: // title
00365             {
00366                 sql = "SELECT song_id "
00367                       "FROM music_songs "
00368                       "WHERE music_songs.name LIKE '%" + searchStr + "%' ";
00369                 query.prepare(sql);
00370                 break;
00371             }
00372             case 4: // genre
00373             {
00374                 sql = "SELECT song_id "
00375                       "FROM music_songs "
00376                       "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id "
00377                       "WHERE music_genres.genre LIKE '%" + searchStr + "%' ";
00378                 query.prepare(sql);
00379                 break;
00380             }
00381             case 5: // tags
00382             {
00383                 //TODO add tag query
00384             }
00385             case 0: // all fields
00386             default:
00387             {
00388                 sql = "SELECT song_id "
00389                       "FROM music_songs "
00390                       "LEFT JOIN music_artists ON "
00391                       "    music_songs.artist_id=music_artists.artist_id "
00392                       "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id "
00393                       "LEFT JOIN music_artists AS music_comp_artists ON "
00394                       "    music_albums.artist_id=music_comp_artists.artist_id "
00395                       "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id "
00396                       "WHERE music_songs.name LIKE '%" + searchStr + "%' "
00397                       "OR music_artists.artist_name LIKE '%" + searchStr + "%' "
00398                       "OR music_albums.album_name LIKE '%" + searchStr + "%' "
00399                       "OR music_genres.genre LIKE '%" + searchStr + "%' ";
00400 
00401                 query.prepare(sql);
00402             }
00403         }
00404     }
00405 
00406     if (!query.exec() || !query.isActive())
00407     {
00408         MythDB::DBError("Search music database", query);
00409         return;
00410     }
00411 
00412     while (query.next())
00413     {
00414         int trackid = query.value(0).toInt();
00415 
00416         Metadata *mdata = gMusicData->all_music->getMetadata(trackid);
00417         if (mdata)
00418         {
00419             MythUIButtonListItem *newitem = new MythUIButtonListItem(m_tracksList, "");
00420             newitem->SetData(qVariantFromValue(mdata));
00421             MetadataMap metadataMap;
00422             mdata->toMap(metadataMap);
00423             newitem->SetTextFromMap(metadataMap);
00424 
00425             if (gPlayer->getPlaylist()->checkTrack(mdata->ID()))
00426                 newitem->DisplayState("on", "selectedstate");
00427             else
00428                 newitem->DisplayState("off", "selectedstate");
00429 
00430             // TODO rating state etc
00431         }
00432     }
00433 
00434     trackVisible(m_tracksList->GetItemCurrent());
00435 
00436     if (m_matchesText)
00437         m_matchesText->SetText(QString("%1").arg(m_tracksList->GetCount()));
00438 }
00439 
00440 void SearchView::trackClicked(MythUIButtonListItem *item)
00441 {
00442     Metadata *mdata = qVariantValue<Metadata*> (item->GetData());
00443     if (mdata)
00444     {
00445         if (gPlayer->getPlaylist()->checkTrack(mdata->ID()))
00446             gPlayer->getPlaylist()->removeTrack(mdata->ID());
00447         else
00448             gPlayer->getPlaylist()->addTrack(mdata->ID(), true);
00449     }
00450 }
00451 
00452 void SearchView::trackVisible(MythUIButtonListItem *item)
00453 {
00454 
00455     if (!item)
00456         return;
00457 
00458     if (item->GetImage().isEmpty())
00459     {
00460         Metadata *mdata = qVariantValue<Metadata*> (item->GetData());
00461         if (mdata)
00462         {
00463             QString artFile = mdata->getAlbumArtFile();
00464             if (artFile.isEmpty())
00465                 item->SetImage("mm_nothumb.png");
00466             else
00467                 item->SetImage(mdata->getAlbumArtFile());
00468         }
00469         else
00470             item->SetImage("mm_nothumb.png");
00471     }
00472 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends