45 {
"Artist",
"music_artists.artist_name",
ftString, 0, 0, 0 },
46 {
"Album",
"music_albums.album_name",
ftString, 0, 0, 0 },
47 {
"Title",
"music_songs.name",
ftString, 0, 0, 0 },
48 {
"Genre",
"music_genres.genre",
ftString, 0, 0, 0 },
49 {
"Year",
"music_songs.year",
ftNumeric, 1900, 2099, 2000 },
50 {
"Track No.",
"music_songs.track",
ftNumeric, 0, 99, 0 },
51 {
"Rating",
"music_songs.rating",
ftNumeric, 0, 10, 0 },
52 {
"Play Count",
"music_songs.numplays",
ftNumeric, 0, 9999, 0 },
53 {
"Compilation",
"music_albums.compilation",
ftBoolean, 0, 0, 0 },
54 {
"Comp. Artist",
"music_comp_artists.artist_name",
ftString, 0, 0, 0 },
55 {
"Last Play",
"FROM_DAYS(TO_DAYS(music_songs.lastplay))",
57 {
"Date Imported",
"FROM_DAYS(TO_DAYS(music_songs.date_entered))",
71 {
"is equal to", 1,
false,
true },
72 {
"is not equal to", 1,
false,
true },
73 {
"is greater than", 1,
false,
false },
74 {
"is less than", 1,
false,
false },
75 {
"starts with", 1,
true,
false },
76 {
"ends with", 1,
true,
false },
77 {
"contains", 1,
true,
false },
78 {
"does not contain", 1,
true,
false },
79 {
"is between", 2,
false,
false },
80 {
"is set", 0,
false,
false },
81 {
"is not set", 0,
false,
false },
109 QSqlField field(
"", value.type());
113 field.setValue(value);
116 QString result = QString::fromUtf8(query.
driver()->formatValue(field).toAscii().data());
122 if (sDate.startsWith(
"$DATE"))
126 if (sDate.length() > 9)
128 bool bNegative =
false;
132 if (sDate.endsWith(
" days"))
133 sDate = sDate.left(sDate.length() - 5);
135 int nDays = sDate.mid(8).toInt();
139 date = date.addDays(nDays);
149 QString value1, QString value2)
153 if (fieldName.isEmpty())
176 value1 = (value1 ==
"Yes") ?
"1":
"0";
177 value2 = (value2 ==
"Yes") ?
"1":
"0";
185 if (Operator->
name ==
"is equal to")
189 else if (Operator->
name ==
"is not equal to")
193 else if (Operator->
name ==
"is greater than")
197 else if (Operator->
name ==
"is less than")
201 else if (Operator->
name ==
"starts with")
205 else if (Operator->
name ==
"ends with")
209 else if (Operator->
name ==
"contains")
213 else if (Operator->
name ==
"does not contain")
217 else if (Operator->
name ==
"is between")
222 else if (Operator->
name ==
"is set")
224 result = result +
" IS NOT NULL";
226 else if (Operator->
name ==
"is not set")
228 result = result +
" IS NULL";
233 LOG(VB_GENERAL, LOG_ERR,
234 QString(
"getCriteriaSQL(): invalid operator '%1'")
235 .arg(Operator->
name));
243 if (orderByFields.isEmpty())
246 QStringList list = orderByFields.split(
",");
247 QString fieldName, result, order;
250 for (
int x = 0;
x < list.count();
x++)
252 fieldName = list[
x].trimmed();
254 Field =
lookupField(fieldName.left(fieldName.length() - 4));
257 if (fieldName.right(3) ==
"(D)")
265 result =
" ORDER BY " + Field->
sqlName + order;
268 result +=
", " + Field->
sqlName + order;
292 const QString &_Value1,
const QString &_Value2)
295 Operator = _Operator;
301 Field(
""), Operator(
""), Value1(
""), Value2(
"")
312 return QString::null;
330 query.
prepare(
"INSERT INTO music_smartplaylist_items (smartplaylistid, field, operator,"
332 "VALUES (:SMARTPLAYLISTID, :FIELD, :OPERATOR, :VALUE1, :VALUE2);");
333 query.
bindValue(
":SMARTPLAYLISTID", smartPlaylistID);
361 result +=
" " + QObject::tr(
"and") +
" " +
Value2;
376 m_tempCriteriaRow(NULL), m_matchesCount(0),
377 m_newPlaylist(
false), m_playlistIsValid(
false),
378 m_categorySelector(NULL), m_categoryButton(NULL),
379 m_titleEdit(NULL), m_matchSelector(NULL),
380 m_criteriaList(NULL), m_orderBySelector(NULL),
381 m_orderByButton(NULL), m_matchesText(NULL),
382 m_limitSpin(NULL), m_cancelButton(NULL),
383 m_saveButton(NULL), m_showResultsButton(NULL)
387 SmartPlaylistEditor::~SmartPlaylistEditor(
void)
389 while (!m_criteriaRows.empty())
391 delete m_criteriaRows.back();
392 m_criteriaRows.pop_back();
395 if (m_tempCriteriaRow)
396 delete m_tempCriteriaRow;
400 bool SmartPlaylistEditor::Create(
void)
402 if (!LoadWindowFromXML(
"music-ui.xml",
"smartplaylisteditor",
this))
423 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'smartplaylisteditor'");
427 getSmartPlaylistCategories();
441 m_limitSpin->SetRange(0, 9999, 10);
443 connect(m_orderByButton, SIGNAL(Clicked()), SLOT(orderByClicked()));
444 connect(m_saveButton, SIGNAL(Clicked()), SLOT(saveClicked()));
445 connect(m_cancelButton, SIGNAL(Clicked()), SLOT(Close()));
446 connect(m_categoryButton, SIGNAL(Clicked()), SLOT(showCategoryMenu()));
447 connect(m_showResultsButton, SIGNAL(Clicked()), SLOT(showResultsClicked()));
455 bool SmartPlaylistEditor::keyPressEvent(QKeyEvent *event)
457 if (GetFocusWidget() && GetFocusWidget()->keyPressEvent(event))
460 bool handled =
false;
464 for (
int i = 0; i < actions.size() && !handled; i++)
466 QString
action = actions[i];
469 if (action ==
"MENU")
473 else if (action ==
"DELETE" && GetFocusWidget() == m_criteriaList)
477 else if (action ==
"EDIT" && GetFocusWidget() == m_criteriaList)
491 void SmartPlaylistEditor::customEvent(QEvent *event)
501 QString resultid = dce->
GetId();
503 if (resultid ==
"categorymenu")
505 if (resulttext == tr(
"New Category"))
508 QString label = tr(
"Enter Name Of New Category");
512 connect(input, SIGNAL(haveResult(QString)),
513 SLOT(newCategory(QString)));
520 else if (resulttext == tr(
"Delete Category"))
521 startDeleteCategory(m_categorySelector->GetValue());
522 else if (resulttext == tr(
"Rename Category"))
525 QString label = tr(
"Enter New Name For Category: %1").arg(m_categorySelector->GetValue());
529 connect(input, SIGNAL(haveResult(QString)),
530 SLOT(renameCategory(QString)));
541 void SmartPlaylistEditor::editCriteria(
void)
543 if (m_tempCriteriaRow)
545 delete m_tempCriteriaRow;
546 m_tempCriteriaRow = NULL;
569 connect(editor, SIGNAL(criteriaChanged()), SLOT(criteriaChanged()));
574 void SmartPlaylistEditor::deleteCriteria(
void)
582 ShowOkPopup(tr(
"Delete Criteria?"),
this, SLOT(doDeleteCriteria(
bool)),
true);
585 void SmartPlaylistEditor::doDeleteCriteria(
bool doit)
598 m_criteriaRows.removeAll(row);
599 m_criteriaList->RemoveItem(item);
605 void SmartPlaylistEditor::addCriteria(
void)
618 if (m_tempCriteriaRow)
619 delete m_tempCriteriaRow;
633 connect(editor, SIGNAL(criteriaChanged()), SLOT(criteriaChanged()));
638 void SmartPlaylistEditor::criteriaChanged()
642 if (m_tempCriteriaRow)
645 m_criteriaRows.append(m_tempCriteriaRow);
648 qVariantFromValue(m_tempCriteriaRow));
650 m_criteriaList->SetItemCurrent(item);
652 m_tempCriteriaRow = NULL;
657 item = m_criteriaList->GetItemCurrent();
672 void SmartPlaylistEditor::showCategoryMenu(
void)
674 QString label = tr(
"Category Actions");
688 menu->
AddButton(tr(
"New Category"), NULL);
689 menu->
AddButton(tr(
"Delete Category"), NULL);
690 menu->
AddButton(tr(
"Rename Category"), NULL);
695 void SmartPlaylistEditor::showCriteriaMenu(
void)
697 QString label = tr(
"Criteria Actions");
714 menu->
AddButton(tr(
"Edit Criteria"), SLOT(editCriteria()));
716 menu->
AddButton(tr(
"Add Criteria"), SLOT(addCriteria()));
719 menu->
AddButton(tr(
"Delete Criteria"), SLOT(deleteCriteria()));
724 void SmartPlaylistEditor::titleChanged(
void)
726 m_saveButton->SetEnabled((m_playlistIsValid && !m_titleEdit->GetText().isEmpty()));
729 void SmartPlaylistEditor::updateMatches(
void)
734 "LEFT JOIN music_artists ON "
735 " music_songs.artist_id=music_artists.artist_id "
736 "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id "
737 "LEFT JOIN music_artists AS music_comp_artists ON "
738 " music_albums.artist_id=music_comp_artists.artist_id "
739 "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id ";
741 sql += getWhereClause();
746 if (!query.exec(sql))
748 else if (query.next())
749 m_matchesCount = query.value(0).toInt();
751 m_matchesText->SetText(QString::number(m_matchesCount));
753 m_playlistIsValid = (m_matchesCount > 0);
754 m_showResultsButton->SetEnabled((m_matchesCount > 0));
758 void SmartPlaylistEditor::saveClicked(
void)
762 QString
name = m_titleEdit->GetText();
763 QString category = m_categorySelector->GetValue();
764 QString matchType = (m_matchSelector->GetValue() == tr(
"All") ?
"All" :
"Any");
765 QString orderBy = m_orderBySelector->GetValue();
766 QString limit = m_limitSpin->GetValue();
769 int categoryid = SmartPlaylistEditor::lookupCategoryID(category);
773 SmartPlaylistEditor::deleteSmartPlaylist(m_originalCategory, m_originalName);
775 SmartPlaylistEditor::deleteSmartPlaylist(category, name);
779 query.prepare(
"INSERT INTO music_smartplaylists (name, categoryid, matchtype, orderby, limitto) "
780 "VALUES (:NAME, :CATEGORYID, :MATCHTYPE, :ORDERBY, :LIMIT);");
781 query.bindValue(
":NAME", name);
782 query.bindValue(
":CATEGORYID", categoryid);
783 query.bindValue(
":MATCHTYPE", matchType);
784 query.bindValue(
":ORDERBY", orderBy);
785 query.bindValue(
":LIMIT", limit);
795 query.prepare(
"SELECT smartplaylistid FROM music_smartplaylists "
796 "WHERE categoryid = :CATEGORYID AND name = :NAME;");
797 query.bindValue(
":CATEGORYID", categoryid);
798 query.bindValue(
":NAME", name);
801 if (query.isActive() && query.size() > 0)
804 ID = query.value(0).toInt();
808 LOG(VB_GENERAL, LOG_ERR,
809 QString(
"Failed to find ID for smartplaylist: %1").arg(name));
820 for (
int x = 0;
x < m_criteriaRows.size();
x++)
821 m_criteriaRows[
x]->saveToDatabase(ID);
823 emit smartPLChanged(category, name);
828 void SmartPlaylistEditor::newSmartPlaylist(QString category)
830 m_categorySelector->SetValue(category);
831 m_titleEdit->Reset();
832 m_originalCategory = category;
833 m_originalName.clear();
835 m_newPlaylist =
true;
840 void SmartPlaylistEditor::editSmartPlaylist(QString category, QString name)
842 m_originalCategory = category;
843 m_originalName =
name;
844 m_newPlaylist =
false;
845 loadFromDatabase(category, name);
849 void SmartPlaylistEditor::loadFromDatabase(QString category, QString name)
852 int categoryid = SmartPlaylistEditor::lookupCategoryID(category);
857 query.prepare(
"SELECT smartplaylistid, name, categoryid, matchtype, orderby, limitto "
858 "FROM music_smartplaylists WHERE name = :NAME AND categoryid = :CATEGORYID;");
859 query.bindValue(
":NAME", name);
860 query.bindValue(
":CATEGORYID", categoryid);
863 if (query.isActive() && query.size() > 0)
866 ID = query.value(0).toInt();
867 m_titleEdit->SetText(name);
868 m_categorySelector->SetValue(category);
869 if (query.value(3).toString() ==
"All")
870 m_matchSelector->SetValue(tr(
"All"));
872 m_matchSelector->SetValue(tr(
"Any"));
874 QString orderBy = query.value(4).toString();
875 if (!m_orderBySelector->Find(orderBy))
879 m_orderBySelector->SetValue(orderBy);
882 m_limitSpin->SetValue(query.value(5).toInt());
886 LOG(VB_GENERAL, LOG_ERR,
887 QString(
"Cannot find smartplaylist: %1").arg(name));
897 m_criteriaList->Reset();
902 query.prepare(
"SELECT field, operator, value1, value2 "
903 "FROM music_smartplaylist_items WHERE smartplaylistid = :ID "
904 "ORDER BY smartplaylistitemid;");
905 query.bindValue(
":ID", ID);
909 if (query.size() > 0)
913 QString Field = query.value(0).toString();
914 QString Operator = query.value(1).toString();
915 QString Value1 = query.value(2).toString();
916 QString Value2 = query.value(3).toString();
918 m_criteriaRows.append(row);
925 LOG(VB_GENERAL, LOG_WARNING,
926 QString(
"Got no smartplaylistitems for ID: ").arg(ID));
930 void SmartPlaylistEditor::newCategory(
const QString &category)
935 query.prepare(
"INSERT INTO music_smartplaylist_categories (name) "
937 query.bindValue(
":NAME", category);
945 getSmartPlaylistCategories();
946 m_categorySelector->SetValue(category);
949 void SmartPlaylistEditor::startDeleteCategory(
const QString &category)
951 if (category.isEmpty())
958 tr(
"Are you sure you want to delete this Category?")
959 +
"\n\n\"" + category +
"\"\n\n"
960 + tr(
"It will also delete any Smart Playlists belonging to this category."),
964 SmartPlaylistEditor::deleteCategory(category);
966 getSmartPlaylistCategories();
967 m_titleEdit->Reset();
970 void SmartPlaylistEditor::renameCategory(
const QString &category)
972 if (m_categorySelector->GetValue() == category)
977 query.prepare(
"UPDATE music_smartplaylist_categories SET name = :NEW_CATEGORY "
978 "WHERE name = :OLD_CATEGORY;");
979 query.bindValue(
":OLD_CATEGORY", m_categorySelector->GetValue());
980 query.bindValue(
":NEW_CATEGORY", category);
986 m_originalCategory = m_categorySelector->GetValue();
988 getSmartPlaylistCategories();
989 m_categorySelector->SetValue(category);
992 QString SmartPlaylistEditor::getSQL(QString fields)
994 QString sql, whereClause, orderByClause, limitClause;
995 sql =
"SELECT " + fields +
" FROM music_songs "
996 "LEFT JOIN music_artists ON music_songs.artist_id=music_artists.artist_id "
997 "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id "
998 "LEFT JOIN music_artists AS music_comp_artists ON music_albums.artist_id=music_comp_artists.artist_id "
999 "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id ";
1001 whereClause = getWhereClause();
1002 orderByClause = getOrderByClause();
1003 if (m_limitSpin->GetIntValue() > 0)
1004 limitClause =
" LIMIT " + m_limitSpin->GetValue();
1006 sql = sql + whereClause + orderByClause + limitClause;
1011 QString SmartPlaylistEditor::getOrderByClause(
void)
1016 QString SmartPlaylistEditor::getWhereClause(
void)
1019 QString sql =
"WHERE ";
1021 for (
int x = 0;
x < m_criteriaRows.size();
x++)
1023 QString criteria = m_criteriaRows[
x]->getSQL();
1024 if (criteria.isEmpty())
1034 if (m_matchSelector->GetValue() == tr(
"Any"))
1035 sql +=
" OR " + criteria;
1037 sql +=
" AND " + criteria;
1044 void SmartPlaylistEditor::showResultsClicked(
void)
1046 QString sql = getSQL(
"song_id, music_artists.artist_name, album_name, "
1047 "name, genre, music_songs.year, track");
1053 if (!resultViewer->
Create())
1055 delete resultViewer;
1059 resultViewer->
setSQL(sql);
1064 void SmartPlaylistEditor::orderByClicked(
void)
1070 if (!orderByDialog->
Create())
1072 delete orderByDialog;
1076 orderByDialog->
setFieldList(m_orderBySelector->GetValue());
1078 connect(orderByDialog, SIGNAL(orderByChanged(QString)), SLOT(orderByChanged(QString)));
1083 void SmartPlaylistEditor::orderByChanged(QString orderBy)
1085 if (m_orderBySelector->MoveToNamedPosition(orderBy))
1090 m_orderBySelector->SetValue(orderBy);
1093 void SmartPlaylistEditor::getSmartPlaylistCategories(
void)
1095 m_categorySelector->Reset();
1098 if (query.exec(
"SELECT name FROM music_smartplaylist_categories ORDER BY name;"))
1100 if (query.isActive() && query.size() > 0)
1102 while (query.next())
1107 LOG(VB_GENERAL, LOG_ERR,
1108 "Could not find any smartplaylist categories");
1118 bool SmartPlaylistEditor::deleteSmartPlaylist(QString category, QString name)
1121 int categoryid = SmartPlaylistEditor::lookupCategoryID(category);
1127 query.prepare(
"SELECT smartplaylistid FROM music_smartplaylists WHERE name = :NAME "
1128 "AND categoryid = :CATEGORYID;");
1129 query.bindValue(
":NAME", name);
1130 query.bindValue(
":CATEGORYID", categoryid);
1133 if (query.isActive() && query.size() > 0)
1136 ID = query.value(0).toInt();
1152 query.prepare(
"DELETE FROM music_smartplaylist_items WHERE smartplaylistid = :ID;");
1153 query.bindValue(
":ID", ID);
1158 query.prepare(
"DELETE FROM music_smartplaylists WHERE smartplaylistid = :ID;");
1159 query.bindValue(
":ID", ID);
1168 bool SmartPlaylistEditor::deleteCategory(QString category)
1170 int categoryid = SmartPlaylistEditor::lookupCategoryID(category);
1174 query.prepare(
"SELECT name FROM music_smartplaylists "
1175 "WHERE categoryid = :CATEGORYID;");
1176 query.bindValue(
":CATEGORYID", categoryid);
1183 if (query.isActive() && query.size() > 0)
1185 while (query.next())
1187 SmartPlaylistEditor::deleteSmartPlaylist(category, query.value(0).toString());
1192 query.prepare(
"DELETE FROM music_smartplaylist_categories WHERE categoryid = :ID;");
1193 query.bindValue(
":ID", categoryid);
1201 int SmartPlaylistEditor::lookupCategoryID(QString category)
1205 query.prepare(
"SELECT categoryid FROM music_smartplaylist_categories "
1206 "WHERE name = :CATEGORY;");
1207 query.bindValue(
":CATEGORY", category);
1211 if (query.isActive() && query.size() > 0)
1214 ID = query.value(0).toInt();
1218 LOG(VB_GENERAL, LOG_ERR,
1219 QString(
"Failed to find smart playlist category: %1")
1233 void SmartPlaylistEditor::getCategoryAndName(QString &category, QString &name)
1235 category = m_categorySelector->GetValue();
1236 name = m_titleEdit->GetText();
1245 m_criteriaRow(NULL), m_fieldSelector(NULL),
1246 m_operatorSelector(NULL), m_value1Edit(NULL),
1247 m_value2Edit(NULL), m_value1Selector(NULL),
1248 m_value2Selector(NULL), m_value1Spinbox(NULL),
1249 m_value2Spinbox(NULL), m_value1Button(NULL),
1250 m_value2Button(NULL), m_andText(NULL),
1251 m_cancelButton(NULL), m_saveButton(NULL)
1282 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'criteriaroweditor'");
1385 bool enabled =
false;
1393 if (Field && Operator)
1399 if (Operator->noOfArguments == 0)
1409 if (Operator->noOfArguments == 0)
1505 if (currentValue < Field->minValue || currentValue > Field->
maxValue)
1515 if (currentValue < Field->minValue || currentValue > Field->
maxValue)
1582 QStringList searchList;
1587 msg = tr(
"Select an Artist");
1592 msg = tr(
"Select a Compilation Artist");
1597 msg = tr(
"Select an Album");
1602 msg = tr(
"Select a Genre");
1607 msg = tr(
"Select a Title");
1624 if (!searchDlg->
Create())
1630 connect(searchDlg, SIGNAL(haveResult(QString)), SLOT(
setValue(QString)));
1657 connect(dateDlg, SIGNAL(dateChanged(QString)), SLOT(
setDate(QString)));
1691 m_trackList(NULL), m_positionText(NULL)
1711 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'smartplresultviewer'");
1730 bool handled =
false;
1731 QStringList actions;
1734 for (
int i = 0; i < actions.size() && !handled; i++)
1736 QString action = actions[i];
1739 if (action ==
"INFO")
1762 if (artFile.isEmpty())
1809 if (query.
exec(sql))
1811 while (query.
next())
1817 mdata->
toMap(metadataMap);
1835 m_fieldList(NULL), m_orderSelector(NULL), m_addButton(NULL),
1836 m_deleteButton(NULL), m_moveUpButton(NULL), m_moveDownButton(NULL),
1837 m_ascendingButton(NULL), m_descendingButton(NULL), m_cancelButton(NULL),
1866 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'orderbydialog'");
1915 QStringList list = fieldList.split(
",");
1917 for (
int x = 0;
x < list.count();
x++)
1920 QString state = list[
x].contains(
"(A)") ?
"ascending" :
"descending";
2060 m_updating(
false), m_fixedRadio(NULL), m_daySpin(NULL),
2061 m_monthSpin(NULL), m_yearSpin(NULL), m_nowRadio(NULL),
2062 m_addDaysSpin(NULL), m_statusText(NULL),
2063 m_cancelButton(NULL), m_okButton(NULL)
2087 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'dateeditordialog'");
2135 month =
"0" + month;
2147 if (date.startsWith(
"$DATE"))
2152 if (date.length() > 9)
2154 bool bNegative =
false;
2158 if (date.endsWith(
" days"))
2159 date = date.left(date.length() - 5);
2161 int nDays = date.mid(8).toInt();
2174 int nYear = date.mid(0, 4).toInt();
2175 int nMonth = date.mid(5, 2).toInt();
2176 int nDay = date.mid(8, 2).toInt();
2234 bool bValidDate =
true;
2244 month =
"0" + month;
2262 days = QString(
"$DATE");
2264 days = QString(
"$DATE - %1 days").arg(