Go to the documentation of this file.
27 const QString &name,
const QString &
action,
69 item->setDrawArrow(
true);
72 item->setDrawArrow(
true);
84 #define LOC QString("PlaylistEditorView: ")
85 #define LOC_WARN QString("PlaylistEditorView, Warning: ")
86 #define LOC_ERR QString("PlaylistEditorView, Error: ")
89 const QString &layout,
bool restorePosition)
90 :
MusicCommon(parent, parentScreen,
"playlisteditorview"),
91 m_layout(layout), m_restorePosition(restorePosition)
118 windowName =
"playlisteditorview_gallery";
123 windowName =
"playlisteditorview_tree";
146 LOG(VB_GENERAL, LOG_ERR, QString(
"Cannot load screen '%1'").
arg(windowName));
203 auto *me =
dynamic_cast<MythEvent*
>(event);
207 if (me->Message().startsWith(
"MUSIC_RESYNC_FINISHED"))
209 QStringList list = me->
Message().simplified().split(
' ');
210 if (list.size() == 4)
212 int added = list[1].toInt();
213 int removed = list[2].toInt();
214 int changed = list[3].toInt();
217 if (added || removed || changed)
227 if ((dce ==
nullptr) || (dce->GetResult() < 0))
230 QString resultid = dce->
GetId();
231 QString resulttext = dce->GetResultText();
233 if (resultid ==
"smartplaylistmenu")
246 if (resulttext == tr(
"New Smart Playlist"))
249 if (mnode->getAction() ==
"smartplaylistcategory")
255 if (!editor->Create())
268 else if (resulttext == tr(
"Remove Smart Playlist"))
270 QString
category = mnode->getParent()->GetText();
271 QString name = mnode->GetText();
273 ShowOkPopup(tr(
"Are you sure you want to delete this Smart Playlist?\n"
277 else if (resulttext == tr(
"Edit Smart Playlist"))
279 QString
category = mnode->getParent()->GetText();
280 QString name = mnode->GetText();
285 if (!editor->Create())
291 editor->editSmartPlaylist(
category, name);
298 else if (resulttext == tr(
"Replace Tracks"))
304 else if (resulttext == tr(
"Add Tracks"))
311 else if (resultid ==
"treeplaylistmenu")
324 if (resulttext == tr(
"Remove Playlist"))
326 QString name = mnode->
GetText();
328 ShowOkPopup(tr(
"Are you sure you want to delete this Playlist?\n"
329 "Name: %1").
arg(name),
332 else if (resulttext == tr(
"Replace Tracks"))
338 else if (resulttext == tr(
"Add Tracks"))
364 for (
int i = 0; i < actions.size() && !handled; i++)
366 QString
action = actions[i];
379 if (mnode->getAction() ==
"smartplaylist" &&
action ==
"EDIT")
381 QString
category = mnode->getParent()->GetText();
382 QString name = mnode->GetText();
387 if (!editor->Create())
393 editor->editSmartPlaylist(
category, name);
401 else if (mnode->getAction() ==
"smartplaylistcategory" &&
action ==
"EDIT")
403 QString
category = mnode->GetText();
408 if (!editor->Create())
423 else if (mnode->getAction() ==
"trackid")
449 if (mnode->getAction() ==
"smartplaylist")
451 QString
category = mnode->getParent()->GetText();
452 QString name = mnode->GetText();
454 ShowOkPopup(tr(
"Are you sure you want to delete this Smart Playlist?\n"
459 else if (mnode->getAction() ==
"playlist")
461 QString name = mnode->GetText();
463 ShowOkPopup(tr(
"Are you sure you want to delete this Playlist?\n"
464 "Name: %1").
arg(name),
471 else if (
action ==
"MARK")
528 node->
getAction() ==
"smartplaylistcategory")
535 else if (node->
getAction() ==
"all tracks" ||
547 for (
int x = 0; x < allTracksNode->childCount(); x++)
567 if (allTracksNode->childCount() == 0)
570 for (
int x = 0; x < allTracksNode->childCount(); x++)
578 else if (node->
getAction() ==
"smartplaylist")
582 for (
int x = 0; x < children->count(); x++)
588 else if (node->
getAction() ==
"playlist")
591 int playlistID = node->
getInt();
612 for (
int x = 0; x < tracks->count(); x++)
633 if (mnode->getAction() ==
"smartplaylists" ||
634 mnode->getAction() ==
"smartplaylistcategory" ||
635 mnode->getAction() ==
"smartplaylist")
639 else if (mnode->getAction() ==
"playlists" ||
640 mnode->getAction() ==
"playlist")
644 else if ((mnode->getAction() ==
"trackid") ||
645 (mnode->getAction() ==
"error"))
664 if (menuPopup->Create())
687 if (mnode->getAction() ==
"playlist")
689 menu =
new MythMenu(tr(
"Playlist Actions"),
this,
"treeplaylistmenu");
690 menu->AddItem(tr(
"Replace Tracks"));
691 menu->AddItem(tr(
"Add Tracks"));
692 menu->AddItem(tr(
"Remove Playlist"));
710 if (mnode->getAction() ==
"smartplaylists" || mnode->getAction() ==
"smartplaylistcategory")
712 QString label = tr(
"Smart Playlist Actions");
716 menu->AddItem(tr(
"New Smart Playlist"));
718 else if (mnode->getAction() ==
"smartplaylist")
720 menu =
new MythMenu(tr(
"Smart Playlist Actions"),
this,
"smartplaylistmenu");
722 menu->AddItem(tr(
"Replace Tracks"));
723 menu->AddItem(tr(
"Add Tracks"));
725 menu->AddItem(tr(
"Edit Smart Playlist"));
726 menu->AddItem(tr(
"New Smart Playlist"));
727 menu->AddItem(tr(
"Remove Smart Playlist"));
740 node->setDrawArrow(
true);
744 node->setDrawArrow(
true);
748 node->setDrawArrow(
true);
752 node->setDrawArrow(
true);
756 node->setDrawArrow(
true);
757 node->SetData(QVariant::fromValue(
gMusicData->all_music->getAllMetadata()));
760 node->setDrawArrow(
true);
764 node->setDrawArrow(
true);
768 node->setDrawArrow(
true);
774 for (
int x = 0; x < alltracks->count(); x++)
780 compTracks->append(mdata);
783 node->SetData(QVariant::fromValue(compTracks));
788 node->setDrawArrow(
true);
793 node->setDrawArrow(
true);
797 node->setDrawArrow(
true);
800 node->setDrawArrow(
true);
811 if (mnode->getAction() ==
"trackid")
839 if (item->
GetText(
"*").isEmpty())
845 if (mnode->getAction() ==
"trackid")
851 else if (mnode->getAction() ==
"album")
855 for (
int x = 0; x < tracks->count(); x++)
861 if (!artFile.isEmpty())
866 else if (mnode->getAction() ==
"compartist")
868 artFile =
findIcon(
"artist", mnode->GetText().toLower());
870 else if (mnode->getAction() ==
"all tracks" || mnode->getAction() ==
"genres" ||
871 mnode->getAction() ==
"albums" || mnode->getAction() ==
"artists" ||
872 mnode->getAction() ==
"compartists"|| mnode->getAction() ==
"ratings" ||
873 mnode->getAction() ==
"years" || mnode->getAction() ==
"compilations" ||
874 mnode->getAction() ==
"cd" || mnode->getAction() ==
"directory" ||
875 mnode->getAction() ==
"playlists" || mnode->getAction() ==
"smartplaylists")
877 artFile =
"blank.png";
881 artFile =
findIcon(mnode->getAction(), mnode->GetText().toLower());
884 QString state =
"default";
886 if (mnode->getAction() ==
"all tracks")
888 else if (mnode->getAction() ==
"genres")
890 else if (mnode->getAction() ==
"albums")
892 else if (mnode->getAction() ==
"artists")
894 else if (mnode->getAction() ==
"compartists")
895 state =
"compartists";
896 else if (mnode->getAction() ==
"ratings")
898 else if (mnode->getAction() ==
"years")
900 else if (mnode->getAction() ==
"compilations")
901 state =
"compilations";
902 else if (mnode->getAction() ==
"cd")
904 else if (mnode->getAction() ==
"directory")
906 else if (mnode->getAction() ==
"playlists")
908 else if (mnode->getAction() ==
"smartplaylists")
909 state =
"smartplaylists";
913 if (artFile.isEmpty())
929 route = route.remove(
"Root Music Node -> ");
939 if (mnode->childCount() > 0 || mnode->getAction() ==
"trackid")
942 if (mnode->getAction() ==
"smartplaylists")
946 else if (mnode->getAction() ==
"smartplaylistcategory")
950 else if (mnode->getAction() ==
"smartplaylist")
954 else if (mnode->getAction() ==
"playlists")
958 else if (mnode->getAction() ==
"playlist")
962 else if (mnode->getAction() ==
"cd")
979 QMultiMap<QString, int> map;
981 bool isAlbum =
false;
985 isAlbum = parentNode->
getAction() ==
"album";
987 for (
int x = 0; x < tracks->count(); x++)
992 QString key = mdata->
Title();
995 if (isAlbum && mdata->
Track() > 0)
997 key.prepend(QString::number(mdata->
Track()) +
" - ");
998 if (mdata->
Track() < 10)
1004 key.prepend(QString::number(mdata->
DiscNumber()) +
"/");
1009 map.insert(key, mdata->
ID());
1013 QMap<QString, int>::const_iterator i = map.constBegin();
1014 while (i != map.constEnd())
1017 newnode->setInt(i.value());
1018 newnode->setDrawArrow(
false);
1026 else if (node->
getAction() ==
"artists")
1028 QMap<QString, MetadataPtrList*> map;
1030 for (
int x = 0; x < tracks->count(); x++)
1035 if (map.contains(mdata->
Artist()))
1038 filteredTracks->append(mdata);
1044 filteredTracks->append(mdata);
1045 map.insert(mdata->
Artist(), filteredTracks);
1050 QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1051 while (i != map.constEnd())
1054 newnode->SetData(QVariant::fromValue(i.value()));
1060 else if (node->
getAction() ==
"compartists")
1062 QMap<QString, MetadataPtrList*> map;
1064 for (
int x = 0; x < tracks->count(); x++)
1074 filteredTracks->append(mdata);
1080 filteredTracks->append(mdata);
1087 QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1088 while (i != map.constEnd())
1091 newnode->SetData(QVariant::fromValue(i.value()));
1099 QMap<QString, MetadataPtrList*> map;
1101 for (
int x = 0; x < tracks->count(); x++)
1106 if (map.contains(mdata->
Album()))
1109 filteredTracks->append(mdata);
1115 filteredTracks->append(mdata);
1116 map.insert(mdata->
Album(), filteredTracks);
1121 QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1122 while (i != map.constEnd())
1125 newnode->SetData(QVariant::fromValue(i.value()));
1133 QMap<QString, MetadataPtrList*> map;
1135 for (
int x = 0; x < tracks->count(); x++)
1140 if (map.contains(mdata->
Genre()))
1143 filteredTracks->append(mdata);
1149 filteredTracks->append(mdata);
1150 map.insert(mdata->
Genre(), filteredTracks);
1155 QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1156 while (i != map.constEnd())
1159 newnode->SetSortText(i.key());
1160 newnode->SetData(QVariant::fromValue(i.value()));
1166 else if (node->
getAction() ==
"ratings")
1168 QMap<QString, MetadataPtrList*> map;
1170 for (
int x = 0; x < tracks->count(); x++)
1175 QString ratingStr = tr(
"%n Star(s)",
"", mdata->
Rating());
1176 if (map.contains(ratingStr))
1179 filteredTracks->append(mdata);
1185 filteredTracks->append(mdata);
1186 map.insert(ratingStr, filteredTracks);
1191 QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1192 while (i != map.constEnd())
1195 newnode->SetData(QVariant::fromValue(i.value()));
1201 QMap<QString, MetadataPtrList*> map;
1203 for (
int x = 0; x < tracks->count(); x++)
1208 QString yearStr = QString(
"%1").arg(mdata->
Year());
1209 if (map.contains(yearStr))
1212 filteredTracks->append(mdata);
1218 filteredTracks->append(mdata);
1219 map.insert(yearStr, filteredTracks);
1224 QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1225 while (i != map.constEnd())
1228 newnode->SetData(QVariant::fromValue(i.value()));
1232 else if (node->
getAction() ==
"directory")
1234 QMap<QString, MetadataPtrList*> map;
1246 QString top2 =
"Root Music Node/" + tr(
"Directory") +
'/';
1247 if (
dir.startsWith(top2))
1248 dir =
dir.mid(top2.length());
1250 for (
int x = 0; x < tracks->count(); x++)
1260 QStringList dirs =
filename.split(
"/");
1262 QString key = dirs.count() > 1 ? dirs[0] :
"[TRACK]" + dirs[0];
1263 if (map.contains(key))
1266 filteredTracks->append(mdata);
1272 filteredTracks->append(mdata);
1273 map.insert(key, filteredTracks);
1279 QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1280 while (i != map.constEnd())
1282 if (!i.key().startsWith(
"[TRACK]"))
1285 newnode->SetData(QVariant::fromValue(i.value()));
1291 i = map.constBegin();
1292 while (i != map.constEnd())
1294 if (i.key().startsWith(
"[TRACK]"))
1297 newnode->setInt(i.value()->at(0)->ID());
1298 newnode->setDrawArrow(
false);
1319 auto *newnode =
new MusicGenericTree(node, tr(
"All Tracks"),
"all tracks");
1320 newnode->setDrawArrow(
true);
1321 newnode->SetData(node->
GetData());
1323 if (!fields.contains(
"albums"))
1326 newnode->setDrawArrow(
true);
1327 newnode->SetData(node->
GetData());
1330 if (!fields.contains(
"artists"))
1333 newnode->setDrawArrow(
true);
1334 newnode->SetData(node->
GetData());
1337 if (!fields.contains(
"compartists"))
1340 bool showCompArtists =
false;
1344 if (mnode->
getAction() ==
"compilations")
1346 showCompArtists =
true;
1357 for (
int x = 0; x < tracks2->count(); x++)
1370 if (showCompArtists && found)
1372 newnode =
new MusicGenericTree(node, tr(
"Compilation Artists"),
"compartists");
1373 newnode->setDrawArrow(
true);
1374 newnode->SetData(node->
GetData());
1378 if (!fields.contains(
"genres"))
1381 newnode->setDrawArrow(
true);
1382 newnode->SetData(node->
GetData());
1385 if (!fields.contains(
"tags"))
1388 newnode->setDrawArrow(
true);
1389 newnode->SetData(node->
GetData());
1392 if (!fields.contains(
"ratings"))
1395 newnode->setDrawArrow(
true);
1396 newnode->SetData(node->
GetData());
1399 if (!fields.contains(
"years"))
1402 newnode->setDrawArrow(
true);
1403 newnode->SetData(node->
GetData());
1412 if (
query.
exec(
"SELECT categoryid, name FROM music_smartplaylist_categories ORDER BY name;"))
1435 int categoryid = node->
getInt();
1438 query.
prepare(
"SELECT smartplaylistid, name FROM music_smartplaylists WHERE categoryid = :CATEGORYID "
1469 query.
prepare(
"SELECT smartplaylistid, matchtype, orderby, limitto "
1470 "FROM music_smartplaylists "
1471 "WHERE smartplaylistid = :SMARTPLAYLISTID;");
1479 matchType = (
query.
value(1).toString() ==
"All") ?
" AND " :
" OR ";
1485 LOG(VB_GENERAL, LOG_WARNING,
1486 LOC + QString(
"Cannot find smartplaylist: %1").
arg(playlistID));
1497 QString whereClause =
"WHERE ";
1499 query.
prepare(
"SELECT field, operator, value1, value2 "
1500 "FROM music_smartplaylist_items "
1501 "WHERE smartplaylistid = :ID;");
1508 QString fieldName =
query.
value(0).toString();
1509 QString operatorName =
query.
value(1).toString();
1515 operatorName, value1, value2);
1531 whereClause +=
" LIMIT " + QString::number(limitTo);
1537 theQuery =
"SELECT song_id, name FROM music_songs "
1538 "LEFT JOIN music_directories ON"
1539 " music_songs.directory_id=music_directories.directory_id "
1540 "LEFT JOIN music_artists ON"
1541 " music_songs.artist_id=music_artists.artist_id "
1542 "LEFT JOIN music_albums ON"
1543 " music_songs.album_id=music_albums.album_id "
1544 "LEFT JOIN music_genres ON"
1545 " music_songs.genre_id=music_genres.genre_id "
1546 "LEFT JOIN music_artists AS music_comp_artists ON "
1547 "music_albums.artist_id=music_comp_artists.artist_id ";
1548 if (whereClause.length() > 0)
1549 theQuery += whereClause;
1562 newnode->setDrawArrow(
false);
1572 newnode->setDrawArrow(
false);
1581 for (
int x =0; x < playlists->count(); x++)
1583 Playlist *playlist = playlists->at(x);
1588 newnode->setInt(playlist->
getID());
1596 for (
int x = 0; x < tracks->count(); x++)
1601 newnode->setInt(mdata->
ID());
1602 newnode->setDrawArrow(
false);
1620 newnode->setInt(mdata->
ID());
1621 newnode->setDrawArrow(
false);
1633 newnode->setDrawArrow(
false);
1649 if (mnode->getAction() ==
"trackid")
1656 if (mnode->childCount())
1682 if (route.count() < 2)
1687 for (
int x = 1 ; x < route.count(); x++)
1715 route <<
"Root Music Node" << tr(
"Smart Playlists") <<
category << name;
1730 if (mnode->getAction() ==
"smartplaylist")
1732 QString
category = mnode->getParent()->GetText();
1733 QString name = mnode->GetText();
1753 if (mnode->getAction() ==
"playlist")
1755 int id = mnode->
getInt();
bool isActive(void) const
void setDrawArrow(bool flag)
void setCheck(MythUIButtonListItem::CheckState state)
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
QSqlQuery wrapper that fetches a DB connection from the connection pool.
MythScreenStack * GetMainStack()
static void editTrackInfo(MusicMetadata *mdata)
void updateSonglist(MusicGenericTree *node)
QString findIcon(const QString &type, const QString &name, bool ignoreCache)
find an image for a artist or genre
MusicGenericTree(MusicGenericTree *parent, const QString &name, const QString &action="", MythUIButtonListItem::CheckState check=MythUIButtonListItem::CantCheck, bool showArrow=true)
static void getSmartPlaylistCategories(MusicGenericTree *node)
MusicMetadata * getSongAt(int pos) const
static Type MythEventMessage
static bool deleteSmartPlaylist(const QString &category, const QString &name)
QString GetText(const QString &name="") const
QString getOrderBySQL(const QString &orderByFields)
void treeItemClicked(MythUIButtonListItem *item)
MetadataPtrList * getAllCDMetadata(void)
MythMenu * createPlaylistOptionsMenu(void)
bool keyPressEvent(QKeyEvent *e) override
Key event handler.
QPointer< MusicButtonItem > m_buttonItem
PlaylistEditorView(MythScreenStack *parent, MythScreenType *parentScreen, const QString &layout, bool restorePosition=false)
uint visibleChildCount() const
InsertPLOption insertPLOption
This class is used as a container for messages.
QVariant value(int i) const
arg(title).arg(filename).arg(doDelete))
QVariant GetData(void) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void doUpdatePlaylist(void)
static Type TrackAddedEvent
bool Create(void) override
MythGenericTree * getChildByName(const QString &a_name) const
static void getSmartPlaylistTracks(MusicGenericTree *node, int playlistID)
void deletePlaylist(int kill_me)
static void showTrackInfo(MusicMetadata *mdata)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Screen in which all other widgets are contained and rendered.
static Type MetadataChangedEvent
Playlist * getCurrentPlaylist(void)
static void getPlaylists(MusicGenericTree *node)
void removeListener(QObject *listener)
void prepare(void) override
static MythThemedMenu * menu
const QString & Message() const
void updateSelectedTracks(void)
MythUIType * GetFocusWidget(void) const
MetadataPtrList * getAllMetadata(void)
void smartPLChanged(const QString &category, const QString &name)
QString getCriteriaSQL(const QString &fieldName, const QString &operatorName, QString value1, QString value2)
PlaylistOptions m_playlistOptions
QList< MetadataPtrList * > m_deleteList
void ShowMenu(void) override
MythGenericTree * getChildAt(uint reference) const
MythGenericTree * addNode(const QString &a_string, int an_int=0, bool selectable_flag=false, bool visible=true)
void addListener(QObject *listener)
Add a listener to the observable.
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
MythUIButtonListItem * CreateListButton(MythUIButtonList *list) override
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
void deletePlaylist(bool ok)
bool first(void)
Wrap QSqlQuery::first() so we can display the query results.
QStringList getRouteByString(void)
Basic menu dialog, message and a list of options.
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
QString getAction(void) const
static void DBError(const QString &where, const MSqlQuery &query)
void BuildFocusList(void)
QString getCDTitle(void) const
int childCount(void) const
Playlist * getPlaylist(int id)
@ MV_PLAYLISTEDITORGALLERY
void stopVisualizer(void)
int getCDTrackCount(void) const
MainVisual * m_mainvisual
void setSelectable(bool flag)
void deleteSmartPlaylist(bool ok)
bool checkTrack(MusicMetadata::IdType trackID) const
MusicMetadata * getMetadata(int an_id)
void removeTrack(int trackID)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
PlaylistContainer * m_all_playlists
~PlaylistEditorView(void) override
static Type AllTracksRemovedEvent
QList< MythGenericTree * > * getAllChildren() const
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
int siblingCount(void) const
static void treeItemVisible(MythUIButtonListItem *item)
MythMenu * createMainMenu(void)
static void getCDTracks(MusicGenericTree *node)
void restoreTreePosition(const QStringList &route)
void customEvent(QEvent *event) override
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
MythGenericTree * getParent(void) const
void addTrack(int trackID, bool updateUI)
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
static Type PlaylistChangedEvent
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
static Type TrackRemovedEvent
virtual void SetText(const QString &text)
MythMenu * createPlaylistMenu(void)
MythMainWindow * GetMythMainWindow(void)
MythUIText * m_positionText
void createRootNode(void)
static Type CDChangedEvent
void saveTreePosition(void)
PlayPLOption playPLOption
MythScreenStack * GetStack(const QString &Stackname)
static void getPlaylistTracks(MusicGenericTree *node, int playlistID)
static void getSmartPlaylists(MusicGenericTree *node)
MythMenu * createSmartPlaylistMenu(void)
void smartPLChanged(const QString &category, const QString &name)
void treeNodeChanged(MythGenericTree *node)
void SaveSetting(const QString &key, int newValue)
QList< Playlist * > * getPlaylists(void)
MythUIButtonTree * m_playlistTree
static Type AlbumArtChangedEvent
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
MSqlQuery query(MSqlQuery::InitCon())
MusicGenericTree * m_rootNode
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
MythUIButtonListItem::CheckState m_check
void customEvent(QEvent *event) override
void removeListener(QObject *listener)
Remove a listener to the observable.
void filterTracks(MusicGenericTree *node)
void ShowMenu(void) override
QString GetSetting(const QString &key, const QString &defaultval="")
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
MythUIText * m_breadcrumbsText