|
MythTV
0.26-pre
|
00001 // c/c++ 00002 #include <unistd.h> 00003 #include <iostream> 00004 using namespace std; 00005 00006 // qt 00007 #include <QSqlDriver> 00008 #include <QKeyEvent> 00009 #include <QSqlField> 00010 00011 // mythtv 00012 #include <mythcontext.h> 00013 #include <mythmainwindow.h> 00014 #include <mythdb.h> 00015 #include <mythuihelper.h> 00016 #include <mythscreentype.h> 00017 #include <mythuitext.h> 00018 #include <mythuitextedit.h> 00019 #include <mythuibuttonlist.h> 00020 #include <mythuibutton.h> 00021 #include <mythuispinbox.h> 00022 #include <mythuicheckbox.h> 00023 #include <mythdialogbox.h> 00024 00025 // mythmusic 00026 #include "smartplaylist.h" 00027 #include "metadata.h" 00028 #include "musiccommon.h" 00029 00030 struct SmartPLField 00031 { 00032 QString name; 00033 QString sqlName; 00034 SmartPLFieldType type; 00035 int minValue; 00036 int maxValue; 00037 int defaultValue; 00038 }; 00039 00040 static SmartPLField SmartPLFields[] = 00041 { 00042 { "", "", ftString, 0, 0, 0 }, 00043 { "Artist", "music_artists.artist_name", ftString, 0, 0, 0 }, 00044 { "Album", "music_albums.album_name", ftString, 0, 0, 0 }, 00045 { "Title", "music_songs.name", ftString, 0, 0, 0 }, 00046 { "Genre", "music_genres.genre", ftString, 0, 0, 0 }, 00047 { "Year", "music_songs.year", ftNumeric, 1900, 2099, 2000 }, 00048 { "Track No.", "music_songs.track", ftNumeric, 0, 99, 0 }, 00049 { "Rating", "music_songs.rating", ftNumeric, 0, 10, 0 }, 00050 { "Play Count", "music_songs.numplays", ftNumeric, 0, 9999, 0 }, 00051 { "Compilation", "music_albums.compilation", ftBoolean, 0, 0, 0 }, 00052 { "Comp. Artist", "music_comp_artists.artist_name", ftString, 0, 0, 0 }, 00053 { "Last Play", "FROM_DAYS(TO_DAYS(music_songs.lastplay))", 00054 ftDate, 0, 0, 0 }, 00055 { "Date Imported", "FROM_DAYS(TO_DAYS(music_songs.date_entered))", 00056 ftDate, 0, 0, 0 }, 00057 }; 00058 00059 struct SmartPLOperator 00060 { 00061 QString name; 00062 int noOfArguments; 00063 bool stringOnly; 00064 bool validForBoolean; 00065 }; 00066 00067 static SmartPLOperator SmartPLOperators[] = 00068 { 00069 { "is equal to", 1, false, true }, 00070 { "is not equal to", 1, false, true }, 00071 { "is greater than", 1, false, false }, 00072 { "is less than", 1, false, false }, 00073 { "starts with", 1, true, false }, 00074 { "ends with", 1, true, false }, 00075 { "contains", 1, true, false }, 00076 { "does not contain", 1, true, false }, 00077 { "is between", 2, false, false }, 00078 { "is set", 0, false, false }, 00079 { "is not set", 0, false, false }, 00080 }; 00081 00082 static int SmartPLOperatorsCount = sizeof(SmartPLOperators) / sizeof(SmartPLOperators[0]); 00083 static int SmartPLFieldsCount = sizeof(SmartPLFields) / sizeof(SmartPLFields[0]); 00084 00085 static SmartPLOperator *lookupOperator(QString name) 00086 { 00087 for (int x = 0; x < SmartPLOperatorsCount; x++) 00088 { 00089 if (SmartPLOperators[x].name == name) 00090 return &SmartPLOperators[x]; 00091 } 00092 return NULL; 00093 } 00094 00095 static SmartPLField *lookupField(QString name) 00096 { 00097 for (int x = 0; x < SmartPLFieldsCount; x++) 00098 { 00099 if (SmartPLFields[x].name == name) 00100 return &SmartPLFields[x]; 00101 } 00102 return NULL; 00103 } 00104 00105 QString formattedFieldValue(const QVariant &value) 00106 { 00107 QSqlField field("", value.type()); 00108 if (value.isNull()) 00109 field.clear(); 00110 else 00111 field.setValue(value); 00112 00113 MSqlQuery query(MSqlQuery::InitCon()); 00114 QString result = QString::fromUtf8(query.driver()->formatValue(field).toAscii().data()); 00115 return result; 00116 } 00117 00118 static QString evaluateDateValue(QString sDate) 00119 { 00120 if (sDate.startsWith("$DATE")) 00121 { 00122 QDate date = QDate::currentDate(); 00123 00124 if (sDate.length() > 9) 00125 { 00126 bool bNegative = false; 00127 if (sDate[6] == '-') 00128 bNegative = true; 00129 00130 if (sDate.endsWith(" days")) 00131 sDate = sDate.left(sDate.length() - 5); 00132 00133 int nDays = sDate.mid(8).toInt(); 00134 if (bNegative) 00135 nDays = -nDays; 00136 00137 date = date.addDays(nDays); 00138 } 00139 00140 return date.toString(Qt::ISODate); 00141 } 00142 00143 return sDate; 00144 } 00145 00146 QString getCriteriaSQL(QString fieldName, QString operatorName, 00147 QString value1, QString value2) 00148 { 00149 QString result; 00150 00151 if (fieldName.isEmpty()) 00152 return result; 00153 00154 SmartPLField *Field; 00155 Field = lookupField(fieldName); 00156 if (!Field) 00157 { 00158 return ""; 00159 } 00160 00161 result = Field->sqlName; 00162 00163 SmartPLOperator *Operator; 00164 Operator = lookupOperator(operatorName); 00165 if (!Operator) 00166 { 00167 return QString(); 00168 } 00169 00170 // convert boolean and date values 00171 if (Field->type == ftBoolean) 00172 { 00173 // compilation field uses 0 = false; 1 = true 00174 value1 = (value1 == "Yes") ? "1":"0"; 00175 value2 = (value2 == "Yes") ? "1":"0"; 00176 } 00177 else if (Field->type == ftDate) 00178 { 00179 value1 = evaluateDateValue(value1); 00180 value2 = evaluateDateValue(value2); 00181 } 00182 00183 if (Operator->name == "is equal to") 00184 { 00185 result = result + " = " + formattedFieldValue(value1); 00186 } 00187 else if (Operator->name == "is not equal to") 00188 { 00189 result = result + " != " + formattedFieldValue(value1); 00190 } 00191 else if (Operator->name == "is greater than") 00192 { 00193 result = result + " > " + formattedFieldValue(value1); 00194 } 00195 else if (Operator->name == "is less than") 00196 { 00197 result = result + " < " + formattedFieldValue(value1); 00198 } 00199 else if (Operator->name == "starts with") 00200 { 00201 result = result + " LIKE " + formattedFieldValue(QString("%") + value1); 00202 } 00203 else if (Operator->name == "ends with") 00204 { 00205 result = result + " LIKE " + formattedFieldValue(value1 + "%"); 00206 } 00207 else if (Operator->name == "contains") 00208 { 00209 result = result + " LIKE " + formattedFieldValue(QString("%") + value1 + "%"); 00210 } 00211 else if (Operator->name == "does not contain") 00212 { 00213 result = result + " NOT LIKE " + formattedFieldValue(QString("%") + value1 + "%"); 00214 } 00215 else if (Operator->name == "is between") 00216 { 00217 result = result + " BETWEEN " + formattedFieldValue(value1) + 00218 " AND " + formattedFieldValue(value2); 00219 } 00220 else if (Operator->name == "is set") 00221 { 00222 result = result + " IS NOT NULL"; 00223 } 00224 else if (Operator->name == "is not set") 00225 { 00226 result = result + " IS NULL"; 00227 } 00228 else 00229 { 00230 result.clear(); 00231 LOG(VB_GENERAL, LOG_ERR, 00232 QString("getCriteriaSQL(): invalid operator '%1'") 00233 .arg(Operator->name)); 00234 } 00235 00236 return result; 00237 } 00238 00239 QString getOrderBySQL(QString orderByFields) 00240 { 00241 if (orderByFields.isEmpty()) 00242 return QString(); 00243 00244 QStringList list = orderByFields.split(","); 00245 QString fieldName, result, order; 00246 bool bFirst = true; 00247 00248 for (int x = 0; x < list.count(); x++) 00249 { 00250 fieldName = list[x].trimmed(); 00251 SmartPLField *Field; 00252 Field = lookupField(fieldName.left(fieldName.length() - 4)); 00253 if (Field) 00254 { 00255 if (fieldName.right(3) == "(D)") 00256 order = " DESC"; 00257 else 00258 order = " ASC"; 00259 00260 if (bFirst) 00261 { 00262 bFirst = false; 00263 result = " ORDER BY " + Field->sqlName + order; 00264 } 00265 else 00266 result += ", " + Field->sqlName + order; 00267 } 00268 } 00269 00270 return result; 00271 } 00272 00273 QString getSQLFieldName(QString fieldName) 00274 { 00275 SmartPLField *Field; 00276 Field = lookupField(fieldName); 00277 if (!Field) 00278 { 00279 return ""; 00280 } 00281 00282 return Field->sqlName; 00283 } 00284 00285 /* 00287 */ 00288 00289 SmartPLCriteriaRow::SmartPLCriteriaRow(const QString &_Field, const QString &_Operator, 00290 const QString &_Value1, const QString &_Value2) 00291 { 00292 Field = _Field; 00293 Operator = _Operator; 00294 Value1 = _Value1; 00295 Value2 = _Value2; 00296 } 00297 00298 SmartPLCriteriaRow::SmartPLCriteriaRow(void) : 00299 Field(""), Operator(""), Value1(""), Value2("") 00300 { 00301 } 00302 00303 SmartPLCriteriaRow::~SmartPLCriteriaRow() 00304 { 00305 } 00306 00307 QString SmartPLCriteriaRow::getSQL(void) 00308 { 00309 if (Field.isEmpty()) 00310 return QString::null; 00311 00312 QString result; 00313 00314 result = getCriteriaSQL(Field, Operator, Value1, Value2); 00315 00316 return result; 00317 } 00318 00319 // return false on error 00320 bool SmartPLCriteriaRow::saveToDatabase(int smartPlaylistID) 00321 { 00322 // save playlistitem to database 00323 00324 if (Field.isEmpty()) 00325 return true; 00326 00327 MSqlQuery query(MSqlQuery::InitCon()); 00328 query.prepare("INSERT INTO music_smartplaylist_items (smartplaylistid, field, operator," 00329 " value1, value2)" 00330 "VALUES (:SMARTPLAYLISTID, :FIELD, :OPERATOR, :VALUE1, :VALUE2);"); 00331 query.bindValue(":SMARTPLAYLISTID", smartPlaylistID); 00332 query.bindValue(":FIELD", Field); 00333 query.bindValue(":OPERATOR", Operator); 00334 query.bindValue(":VALUE1", Value1); 00335 query.bindValue(":VALUE2", Value2); 00336 00337 if (!query.exec()) 00338 { 00339 MythDB::DBError("Inserting new smartplaylist item", query); 00340 return false; 00341 } 00342 00343 return true; 00344 } 00345 00346 QString SmartPLCriteriaRow::toString(void) 00347 { 00348 SmartPLOperator *PLOperator = lookupOperator(Operator); 00349 if (PLOperator) 00350 { 00351 QString result; 00352 if (PLOperator->noOfArguments == 0) 00353 result = Field + " " + Operator; 00354 else if (PLOperator->noOfArguments == 1) 00355 result = Field + " " + Operator + " " + Value1; 00356 else 00357 { 00358 result = Field + " " + Operator + " " + Value1; 00359 result += " " + QObject::tr("and") + " " + Value2; 00360 } 00361 00362 return result; 00363 } 00364 00365 return QString(); 00366 } 00367 00368 /* 00369 --------------------------------------------------------------------- 00370 */ 00371 00372 SmartPlaylistEditor::SmartPlaylistEditor(MythScreenStack *parent) 00373 : MythScreenType(parent, "smartplaylisteditor"), 00374 m_tempCriteriaRow(NULL), m_matchesCount(0), 00375 m_newPlaylist(false), m_playlistIsValid(false), 00376 m_categorySelector(NULL), m_categoryButton(NULL), 00377 m_titleEdit(NULL), m_matchSelector(NULL), 00378 m_criteriaList(NULL), m_orderBySelector(NULL), 00379 m_orderByButton(NULL), m_matchesText(NULL), 00380 m_limitSpin(NULL), m_cancelButton(NULL), 00381 m_saveButton(NULL), m_showResultsButton(NULL) 00382 { 00383 } 00384 00385 SmartPlaylistEditor::~SmartPlaylistEditor(void) 00386 { 00387 while (!m_criteriaRows.empty()) 00388 { 00389 delete m_criteriaRows.back(); 00390 m_criteriaRows.pop_back(); 00391 } 00392 00393 if (m_tempCriteriaRow) 00394 delete m_tempCriteriaRow; 00395 } 00396 00397 00398 bool SmartPlaylistEditor::Create(void) 00399 { 00400 if (!LoadWindowFromXML("music-ui.xml", "smartplaylisteditor", this)) 00401 return false; 00402 00403 bool err = false; 00404 00405 UIUtilE::Assign(this, m_categorySelector, "categoryselector", &err); 00406 UIUtilE::Assign(this, m_categoryButton, "categorybutton", &err); 00407 UIUtilE::Assign(this, m_titleEdit, "titleedit", &err); 00408 UIUtilE::Assign(this, m_matchSelector, "matchselector", &err); 00409 UIUtilE::Assign(this, m_criteriaList, "criterialist", &err); 00410 UIUtilE::Assign(this, m_orderBySelector, "orderbyselector", &err); 00411 UIUtilE::Assign(this, m_orderByButton, "orderbybutton", &err); 00412 UIUtilE::Assign(this, m_matchesText, "matchestext", &err); 00413 UIUtilE::Assign(this, m_limitSpin, "limitspin", &err); 00414 00415 UIUtilE::Assign(this, m_cancelButton, "cancelbutton", &err); 00416 UIUtilE::Assign(this, m_saveButton, "savebutton", &err); 00417 UIUtilE::Assign(this, m_showResultsButton, "showresultsbutton", &err); 00418 00419 if (err) 00420 { 00421 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'smartplaylisteditor'"); 00422 return false; 00423 } 00424 00425 getSmartPlaylistCategories(); 00426 00427 new MythUIButtonListItem(m_matchSelector, tr("All")); 00428 new MythUIButtonListItem(m_matchSelector, tr("Any")); 00429 connect(m_matchSelector, SIGNAL(itemSelected(MythUIButtonListItem*)), SLOT(updateMatches())); 00430 00431 for (int x = 0; x < SmartPLFieldsCount; x++) 00432 { 00433 if (SmartPLFields[x].name == "") 00434 new MythUIButtonListItem(m_orderBySelector, SmartPLFields[x].name); 00435 else 00436 new MythUIButtonListItem(m_orderBySelector, SmartPLFields[x].name + " (A)"); 00437 } 00438 00439 m_limitSpin->SetRange(0, 9999, 10); 00440 00441 connect(m_orderByButton, SIGNAL(Clicked()), SLOT(orderByClicked())); 00442 connect(m_saveButton, SIGNAL(Clicked()), SLOT(saveClicked())); 00443 connect(m_cancelButton, SIGNAL(Clicked()), SLOT(Close())); 00444 connect(m_categoryButton, SIGNAL(Clicked()), SLOT(showCategoryMenu())); 00445 connect(m_showResultsButton, SIGNAL(Clicked()), SLOT(showResultsClicked())); 00446 connect(m_criteriaList, SIGNAL(itemClicked(MythUIButtonListItem*)), SLOT(editCriteria())); 00447 00448 BuildFocusList(); 00449 00450 return true; 00451 } 00452 00453 bool SmartPlaylistEditor::keyPressEvent(QKeyEvent *event) 00454 { 00455 if (GetFocusWidget() && GetFocusWidget()->keyPressEvent(event)) 00456 return true; 00457 00458 bool handled = false; 00459 QStringList actions; 00460 handled = GetMythMainWindow()->TranslateKeyPress("Music", event, actions); 00461 00462 for (int i = 0; i < actions.size() && !handled; i++) 00463 { 00464 QString action = actions[i]; 00465 handled = true; 00466 00467 if (action == "MENU") 00468 { 00469 showCriteriaMenu(); 00470 } 00471 else if (action == "DELETE" && GetFocusWidget() == m_criteriaList) 00472 { 00473 deleteCriteria(); 00474 } 00475 else if (action == "EDIT" && GetFocusWidget() == m_criteriaList) 00476 { 00477 editCriteria(); 00478 } 00479 else 00480 handled = false; 00481 } 00482 00483 if (!handled && MythScreenType::keyPressEvent(event)) 00484 handled = true; 00485 00486 return handled; 00487 } 00488 00489 void SmartPlaylistEditor::customEvent(QEvent *event) 00490 { 00491 if (event->type() == DialogCompletionEvent::kEventType) 00492 { 00493 DialogCompletionEvent *dce = (DialogCompletionEvent*)(event); 00494 00495 // make sure the user didn't ESCAPE out of the menu 00496 if (dce->GetResult() < 0) 00497 return; 00498 00499 QString resultid = dce->GetId(); 00500 QString resulttext = dce->GetResultText(); 00501 if (resultid == "categorymenu") 00502 { 00503 if (resulttext == tr("New Category")) 00504 { 00505 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 00506 QString label = tr("Enter Name Of New Category"); 00507 00508 MythTextInputDialog *input = new MythTextInputDialog(popupStack, label); 00509 00510 connect(input, SIGNAL(haveResult(QString)), 00511 SLOT(newCategory(QString))); 00512 00513 if (input->Create()) 00514 popupStack->AddScreen(input); 00515 else 00516 delete input; 00517 } 00518 else if (resulttext == tr("Delete Category")) 00519 startDeleteCategory(m_categorySelector->GetValue()); 00520 else if (resulttext == tr("Rename Category")) 00521 { 00522 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 00523 QString label = tr("Enter New Name For Category: %1").arg(m_categorySelector->GetValue()); 00524 00525 MythTextInputDialog *input = new MythTextInputDialog(popupStack, label); 00526 00527 connect(input, SIGNAL(haveResult(QString)), 00528 SLOT(renameCategory(QString))); 00529 00530 if (input->Create()) 00531 popupStack->AddScreen(input); 00532 else 00533 delete input; 00534 } 00535 } 00536 } 00537 } 00538 00539 void SmartPlaylistEditor::editCriteria(void) 00540 { 00541 if (m_tempCriteriaRow) 00542 { 00543 delete m_tempCriteriaRow; 00544 m_tempCriteriaRow = NULL; 00545 } 00546 00547 MythUIButtonListItem *item = m_criteriaList->GetItemCurrent(); 00548 00549 if (!item) 00550 return; 00551 00552 SmartPLCriteriaRow *row = qVariantValue<SmartPLCriteriaRow*> (item->GetData()); 00553 00554 if (!row) 00555 return; 00556 00557 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 00558 00559 CriteriaRowEditor *editor = new CriteriaRowEditor(popupStack, row); 00560 00561 if (!editor->Create()) 00562 { 00563 delete editor; 00564 return; 00565 } 00566 00567 connect(editor, SIGNAL(criteriaChanged()), SLOT(criteriaChanged())); 00568 00569 popupStack->AddScreen(editor); 00570 } 00571 00572 void SmartPlaylistEditor::deleteCriteria(void) 00573 { 00574 // make sure we have something to delete 00575 MythUIButtonListItem *item = m_criteriaList->GetItemCurrent(); 00576 00577 if (!item) 00578 return; 00579 00580 ShowOkPopup(tr("Delete Criteria?"), this, SLOT(doDeleteCriteria(bool)), true); 00581 } 00582 00583 void SmartPlaylistEditor::doDeleteCriteria(bool doit) 00584 { 00585 if (doit) 00586 { 00587 MythUIButtonListItem *item = m_criteriaList->GetItemCurrent(); 00588 if (!item) 00589 return; 00590 00591 SmartPLCriteriaRow *row = qVariantValue<SmartPLCriteriaRow*> (item->GetData()); 00592 00593 if (!row) 00594 return; 00595 00596 m_criteriaRows.removeAll(row); 00597 m_criteriaList->RemoveItem(item); 00598 00599 criteriaChanged(); 00600 } 00601 } 00602 00603 void SmartPlaylistEditor::addCriteria(void) 00604 { 00605 /* 00606 SmartPLCriteriaRow *row = new SmartPLCriteriaRow(); 00607 m_criteriaRows.append(row); 00608 00609 MythUIButtonListItem *item = new MythUIButtonListItem(m_criteriaList, row->toString(), qVariantFromValue(row)); 00610 00611 m_criteriaList->SetItemCurrent(item); 00612 00613 editCriteria(); 00614 */ 00615 00616 if (m_tempCriteriaRow) 00617 delete m_tempCriteriaRow; 00618 00619 m_tempCriteriaRow = new SmartPLCriteriaRow(); 00620 00621 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 00622 00623 CriteriaRowEditor *editor = new CriteriaRowEditor(popupStack, m_tempCriteriaRow); 00624 00625 if (!editor->Create()) 00626 { 00627 delete editor; 00628 return; 00629 } 00630 00631 connect(editor, SIGNAL(criteriaChanged()), SLOT(criteriaChanged())); 00632 00633 popupStack->AddScreen(editor); 00634 } 00635 00636 void SmartPlaylistEditor::criteriaChanged() 00637 { 00638 MythUIButtonListItem *item = NULL; 00639 00640 if (m_tempCriteriaRow) 00641 { 00642 // this is a new row so add it to the list 00643 m_criteriaRows.append(m_tempCriteriaRow); 00644 00645 item = new MythUIButtonListItem(m_criteriaList, m_tempCriteriaRow->toString(), 00646 qVariantFromValue(m_tempCriteriaRow)); 00647 00648 m_criteriaList->SetItemCurrent(item); 00649 00650 m_tempCriteriaRow = NULL; 00651 } 00652 else 00653 { 00654 // update the existing row 00655 item = m_criteriaList->GetItemCurrent(); 00656 if (!item) 00657 return; 00658 00659 SmartPLCriteriaRow *row = qVariantValue<SmartPLCriteriaRow*> (item->GetData()); 00660 00661 if (!row) 00662 return; 00663 00664 item->SetText(row->toString()); 00665 } 00666 00667 updateMatches(); 00668 } 00669 00670 void SmartPlaylistEditor::showCategoryMenu(void) 00671 { 00672 QString label = tr("Category Actions"); 00673 00674 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 00675 00676 MythDialogBox *menu = new MythDialogBox(label, popupStack, "actionmenu"); 00677 00678 if (!menu->Create()) 00679 { 00680 delete menu; 00681 return; 00682 } 00683 00684 menu->SetReturnEvent(this, "categorymenu"); 00685 00686 menu->AddButton(tr("New Category"), NULL); 00687 menu->AddButton(tr("Delete Category"), NULL); 00688 menu->AddButton(tr("Rename Category"), NULL); 00689 00690 popupStack->AddScreen(menu); 00691 } 00692 00693 void SmartPlaylistEditor::showCriteriaMenu(void) 00694 { 00695 QString label = tr("Criteria Actions"); 00696 00697 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 00698 00699 MythDialogBox *menu = new MythDialogBox(label, popupStack, "actionmenu"); 00700 00701 if (!menu->Create()) 00702 { 00703 delete menu; 00704 return; 00705 } 00706 00707 menu->SetReturnEvent(this, "criteriamenu"); 00708 00709 MythUIButtonListItem *item = m_criteriaList->GetItemCurrent(); 00710 00711 if (item) 00712 menu->AddButton(tr("Edit Criteria"), SLOT(editCriteria())); 00713 00714 menu->AddButton(tr("Add Criteria"), SLOT(addCriteria())); 00715 00716 if (item) 00717 menu->AddButton(tr("Delete Criteria"), SLOT(deleteCriteria())); 00718 00719 popupStack->AddScreen(menu); 00720 } 00721 00722 void SmartPlaylistEditor::titleChanged(void) 00723 { 00724 m_saveButton->SetEnabled((m_playlistIsValid && !m_titleEdit->GetText().isEmpty())); 00725 } 00726 00727 void SmartPlaylistEditor::updateMatches(void) 00728 { 00729 QString sql = 00730 "SELECT count(*) " 00731 "FROM music_songs " 00732 "LEFT JOIN music_artists ON " 00733 " music_songs.artist_id=music_artists.artist_id " 00734 "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id " 00735 "LEFT JOIN music_artists AS music_comp_artists ON " 00736 " music_albums.artist_id=music_comp_artists.artist_id " 00737 "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id "; 00738 00739 sql += getWhereClause(); 00740 00741 m_matchesCount = 0; 00742 00743 MSqlQuery query(MSqlQuery::InitCon()); 00744 if (!query.exec(sql)) 00745 MythDB::DBError("SmartPlaylistEditor::updateMatches", query); 00746 else if (query.next()) 00747 m_matchesCount = query.value(0).toInt(); 00748 00749 m_matchesText->SetText(QString::number(m_matchesCount)); 00750 00751 m_playlistIsValid = (m_matchesCount > 0); 00752 m_showResultsButton->SetEnabled((m_matchesCount > 0)); 00753 titleChanged(); 00754 } 00755 00756 void SmartPlaylistEditor::saveClicked(void) 00757 { 00758 // save smartplaylist to database 00759 00760 QString name = m_titleEdit->GetText(); 00761 QString category = m_categorySelector->GetValue(); 00762 QString matchType = (m_matchSelector->GetValue() == tr("All") ? "All" : "Any"); 00763 QString orderBy = m_orderBySelector->GetValue(); 00764 QString limit = m_limitSpin->GetValue(); 00765 00766 // lookup categoryid 00767 int categoryid = SmartPlaylistEditor::lookupCategoryID(category); 00768 00769 // easier to delete any existing smartplaylist and recreate a new one 00770 if (!m_newPlaylist) 00771 SmartPlaylistEditor::deleteSmartPlaylist(m_originalCategory, m_originalName); 00772 else 00773 SmartPlaylistEditor::deleteSmartPlaylist(category, name); 00774 00775 MSqlQuery query(MSqlQuery::InitCon()); 00776 // insert new smartplaylist 00777 query.prepare("INSERT INTO music_smartplaylists (name, categoryid, matchtype, orderby, limitto) " 00778 "VALUES (:NAME, :CATEGORYID, :MATCHTYPE, :ORDERBY, :LIMIT);"); 00779 query.bindValue(":NAME", name); 00780 query.bindValue(":CATEGORYID", categoryid); 00781 query.bindValue(":MATCHTYPE", matchType); 00782 query.bindValue(":ORDERBY", orderBy); 00783 query.bindValue(":LIMIT", limit); 00784 00785 if (!query.exec()) 00786 { 00787 MythDB::DBError("Inserting new playlist", query); 00788 return; 00789 } 00790 00791 // get smartplaylistid 00792 int ID; 00793 query.prepare("SELECT smartplaylistid FROM music_smartplaylists " 00794 "WHERE categoryid = :CATEGORYID AND name = :NAME;"); 00795 query.bindValue(":CATEGORYID", categoryid); 00796 query.bindValue(":NAME", name); 00797 if (query.exec()) 00798 { 00799 if (query.isActive() && query.size() > 0) 00800 { 00801 query.first(); 00802 ID = query.value(0).toInt(); 00803 } 00804 else 00805 { 00806 LOG(VB_GENERAL, LOG_ERR, 00807 QString("Failed to find ID for smartplaylist: %1").arg(name)); 00808 return; 00809 } 00810 } 00811 else 00812 { 00813 MythDB::DBError("Getting smartplaylist ID", query); 00814 return; 00815 } 00816 00817 // save smartplaylist items 00818 for (int x = 0; x < m_criteriaRows.size(); x++) 00819 m_criteriaRows[x]->saveToDatabase(ID); 00820 00821 emit smartPLChanged(category, name); 00822 00823 Close(); 00824 } 00825 00826 void SmartPlaylistEditor::newSmartPlaylist(QString category) 00827 { 00828 m_categorySelector->SetValue(category); 00829 m_titleEdit->Reset(); 00830 m_originalCategory = category; 00831 m_originalName.clear(); 00832 00833 m_newPlaylist = true; 00834 00835 updateMatches(); 00836 } 00837 00838 void SmartPlaylistEditor::editSmartPlaylist(QString category, QString name) 00839 { 00840 m_originalCategory = category; 00841 m_originalName = name; 00842 m_newPlaylist = false; 00843 loadFromDatabase(category, name); 00844 updateMatches(); 00845 } 00846 00847 void SmartPlaylistEditor::loadFromDatabase(QString category, QString name) 00848 { 00849 // load smartplaylist from database 00850 int categoryid = SmartPlaylistEditor::lookupCategoryID(category); 00851 00852 MSqlQuery query(MSqlQuery::InitCon()); 00853 int ID; 00854 00855 query.prepare("SELECT smartplaylistid, name, categoryid, matchtype, orderby, limitto " 00856 "FROM music_smartplaylists WHERE name = :NAME AND categoryid = :CATEGORYID;"); 00857 query.bindValue(":NAME", name); 00858 query.bindValue(":CATEGORYID", categoryid); 00859 if (query.exec()) 00860 { 00861 if (query.isActive() && query.size() > 0) 00862 { 00863 query.first(); 00864 ID = query.value(0).toInt(); 00865 m_titleEdit->SetText(name); 00866 m_categorySelector->SetValue(category); 00867 if (query.value(3).toString() == "All") 00868 m_matchSelector->SetValue(tr("All")); 00869 else 00870 m_matchSelector->SetValue(tr("Any")); 00871 00872 QString orderBy = query.value(4).toString(); 00873 if (!m_orderBySelector->Find(orderBy)) 00874 { 00875 // not found so add it to the selector 00876 new MythUIButtonListItem(m_orderBySelector, orderBy); 00877 m_orderBySelector->SetValue(orderBy); 00878 } 00879 00880 m_limitSpin->SetValue(query.value(5).toInt()); 00881 } 00882 else 00883 { 00884 LOG(VB_GENERAL, LOG_ERR, 00885 QString("Cannot find smartplaylist: %1").arg(name)); 00886 return; 00887 } 00888 } 00889 else 00890 { 00891 MythDB::DBError("Load smartplaylist", query); 00892 return; 00893 } 00894 00895 m_criteriaList->Reset(); 00896 00897 // load smartplaylist items 00898 SmartPLCriteriaRow *row; 00899 00900 query.prepare("SELECT field, operator, value1, value2 " 00901 "FROM music_smartplaylist_items WHERE smartplaylistid = :ID " 00902 "ORDER BY smartplaylistitemid;"); 00903 query.bindValue(":ID", ID); 00904 if (!query.exec()) 00905 MythDB::DBError("Load smartplaylist items", query); 00906 00907 if (query.size() > 0) 00908 { 00909 while (query.next()) 00910 { 00911 QString Field = query.value(0).toString(); 00912 QString Operator = query.value(1).toString(); 00913 QString Value1 = query.value(2).toString(); 00914 QString Value2 = query.value(3).toString(); 00915 row = new SmartPLCriteriaRow(Field, Operator, Value1, Value2); 00916 m_criteriaRows.append(row); 00917 00918 new MythUIButtonListItem(m_criteriaList, row->toString(), qVariantFromValue(row)); 00919 } 00920 } 00921 else 00922 { 00923 LOG(VB_GENERAL, LOG_WARNING, 00924 QString("Got no smartplaylistitems for ID: ").arg(ID)); 00925 } 00926 } 00927 00928 void SmartPlaylistEditor::newCategory(const QString &category) 00929 { 00930 // insert new smartplaylistcategory 00931 00932 MSqlQuery query(MSqlQuery::InitCon()); 00933 query.prepare("INSERT INTO music_smartplaylist_categories (name) " 00934 "VALUES (:NAME);"); 00935 query.bindValue(":NAME", category); 00936 00937 if (!query.exec()) 00938 { 00939 MythDB::DBError("Inserting new smartplaylist category", query); 00940 return; 00941 } 00942 00943 getSmartPlaylistCategories(); 00944 m_categorySelector->SetValue(category); 00945 } 00946 00947 void SmartPlaylistEditor::startDeleteCategory(const QString &category) 00948 { 00949 if (category.isEmpty()) 00950 return; 00951 00952 //FIXME:: 00953 #if 0 00954 if (!MythPopupBox::showOkCancelPopup(GetMythMainWindow(), 00955 "Delete Category", 00956 tr("Are you sure you want to delete this Category?") 00957 + "\n\n\"" + category + "\"\n\n" 00958 + tr("It will also delete any Smart Playlists belonging to this category."), 00959 false)) 00960 return; 00961 00962 SmartPlaylistEditor::deleteCategory(category); 00963 #endif 00964 getSmartPlaylistCategories(); 00965 m_titleEdit->Reset(); 00966 } 00967 00968 void SmartPlaylistEditor::renameCategory(const QString &category) 00969 { 00970 if (m_categorySelector->GetValue() == category) 00971 return; 00972 00973 // change the category 00974 MSqlQuery query(MSqlQuery::InitCon()); 00975 query.prepare("UPDATE music_smartplaylist_categories SET name = :NEW_CATEGORY " 00976 "WHERE name = :OLD_CATEGORY;"); 00977 query.bindValue(":OLD_CATEGORY", m_categorySelector->GetValue()); 00978 query.bindValue(":NEW_CATEGORY", category); 00979 00980 if (!query.exec()) 00981 MythDB::DBError("Rename smartplaylist", query); 00982 00983 if (!m_newPlaylist) 00984 m_originalCategory = m_categorySelector->GetValue(); 00985 00986 getSmartPlaylistCategories(); 00987 m_categorySelector->SetValue(category); 00988 } 00989 00990 QString SmartPlaylistEditor::getSQL(QString fields) 00991 { 00992 QString sql, whereClause, orderByClause, limitClause; 00993 sql = "SELECT " + fields + " FROM music_songs " 00994 "LEFT JOIN music_artists ON music_songs.artist_id=music_artists.artist_id " 00995 "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id " 00996 "LEFT JOIN music_artists AS music_comp_artists ON music_albums.artist_id=music_comp_artists.artist_id " 00997 "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id "; 00998 00999 whereClause = getWhereClause(); 01000 orderByClause = getOrderByClause(); 01001 if (m_limitSpin->GetIntValue() > 0) 01002 limitClause = " LIMIT " + m_limitSpin->GetValue(); 01003 01004 sql = sql + whereClause + orderByClause + limitClause; 01005 01006 return sql; 01007 } 01008 01009 QString SmartPlaylistEditor::getOrderByClause(void) 01010 { 01011 return getOrderBySQL(m_orderBySelector->GetValue()); 01012 } 01013 01014 QString SmartPlaylistEditor::getWhereClause(void) 01015 { 01016 bool bFirst = true; 01017 QString sql = "WHERE "; 01018 01019 for (int x = 0; x < m_criteriaRows.size(); x++) 01020 { 01021 QString criteria = m_criteriaRows[x]->getSQL(); 01022 if (criteria.isEmpty()) 01023 continue; 01024 01025 if (bFirst) 01026 { 01027 sql += criteria; 01028 bFirst = false; 01029 } 01030 else 01031 { 01032 if (m_matchSelector->GetValue() == tr("Any")) 01033 sql += " OR " + criteria; 01034 else 01035 sql += " AND " + criteria; 01036 } 01037 } 01038 01039 return sql; 01040 } 01041 01042 void SmartPlaylistEditor::showResultsClicked(void) 01043 { 01044 QString sql = getSQL("song_id, music_artists.artist_name, album_name, " 01045 "name, genre, music_songs.year, track"); 01046 01047 MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); 01048 01049 SmartPLResultViewer *resultViewer = new SmartPLResultViewer(mainStack); 01050 01051 if (!resultViewer->Create()) 01052 { 01053 delete resultViewer; 01054 return; 01055 } 01056 01057 resultViewer->setSQL(sql); 01058 01059 mainStack->AddScreen(resultViewer); 01060 } 01061 01062 void SmartPlaylistEditor::orderByClicked(void) 01063 { 01064 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 01065 01066 SmartPLOrderByDialog *orderByDialog = new SmartPLOrderByDialog(popupStack); 01067 01068 if (!orderByDialog->Create()) 01069 { 01070 delete orderByDialog; 01071 return; 01072 } 01073 01074 orderByDialog->setFieldList(m_orderBySelector->GetValue()); 01075 01076 connect(orderByDialog, SIGNAL(orderByChanged(QString)), SLOT(orderByChanged(QString))); 01077 01078 popupStack->AddScreen(orderByDialog); 01079 } 01080 01081 void SmartPlaylistEditor::orderByChanged(QString orderBy) 01082 { 01083 if (m_orderBySelector->MoveToNamedPosition(orderBy)) 01084 return; 01085 01086 // not found so add it to the selector 01087 new MythUIButtonListItem(m_orderBySelector, orderBy); 01088 m_orderBySelector->SetValue(orderBy); 01089 } 01090 01091 void SmartPlaylistEditor::getSmartPlaylistCategories(void) 01092 { 01093 m_categorySelector->Reset(); 01094 MSqlQuery query(MSqlQuery::InitCon()); 01095 01096 if (query.exec("SELECT name FROM music_smartplaylist_categories ORDER BY name;")) 01097 { 01098 if (query.isActive() && query.size() > 0) 01099 { 01100 while (query.next()) 01101 new MythUIButtonListItem(m_categorySelector, query.value(0).toString()); 01102 } 01103 else 01104 { 01105 LOG(VB_GENERAL, LOG_ERR, 01106 "Could not find any smartplaylist categories"); 01107 } 01108 } 01109 else 01110 { 01111 MythDB::DBError("Load smartplaylist categories", query); 01112 } 01113 } 01114 01115 // static function to delete a smartplaylist and any associated smartplaylist items 01116 bool SmartPlaylistEditor::deleteSmartPlaylist(QString category, QString name) 01117 { 01118 // get categoryid 01119 int categoryid = SmartPlaylistEditor::lookupCategoryID(category); 01120 01121 MSqlQuery query(MSqlQuery::InitCon()); 01122 01123 // get playlist ID 01124 int ID; 01125 query.prepare("SELECT smartplaylistid FROM music_smartplaylists WHERE name = :NAME " 01126 "AND categoryid = :CATEGORYID;"); 01127 query.bindValue(":NAME", name); 01128 query.bindValue(":CATEGORYID", categoryid); 01129 if (query.exec()) 01130 { 01131 if (query.isActive() && query.size() > 0) 01132 { 01133 query.first(); 01134 ID = query.value(0).toInt(); 01135 } 01136 else 01137 { 01138 // not always an error maybe we are trying to delete a playlist 01139 // that does not exist 01140 return true; 01141 } 01142 } 01143 else 01144 { 01145 MythDB::DBError("Delete smartplaylist", query); 01146 return false; 01147 } 01148 01149 //delete smartplaylist items 01150 query.prepare("DELETE FROM music_smartplaylist_items WHERE smartplaylistid = :ID;"); 01151 query.bindValue(":ID", ID); 01152 if (!query.exec()) 01153 MythDB::DBError("Delete smartplaylist items", query); 01154 01155 //delete smartplaylist 01156 query.prepare("DELETE FROM music_smartplaylists WHERE smartplaylistid = :ID;"); 01157 query.bindValue(":ID", ID); 01158 if (!query.exec()) 01159 MythDB::DBError("Delete smartplaylist", query); 01160 01161 return true; 01162 } 01163 01164 // static function to delete all smartplaylists belonging to the given category 01165 // will also delete any associated smartplaylist items 01166 bool SmartPlaylistEditor::deleteCategory(QString category) 01167 { 01168 int categoryid = SmartPlaylistEditor::lookupCategoryID(category); 01169 MSqlQuery query(MSqlQuery::InitCon()); 01170 01171 //delete all smartplaylists with the selected category 01172 query.prepare("SELECT name FROM music_smartplaylists " 01173 "WHERE categoryid = :CATEGORYID;"); 01174 query.bindValue(":CATEGORYID", categoryid); 01175 if (!query.exec()) 01176 { 01177 MythDB::DBError("Delete SmartPlaylist Category", query); 01178 return false; 01179 } 01180 01181 if (query.isActive() && query.size() > 0) 01182 { 01183 while (query.next()) 01184 { 01185 SmartPlaylistEditor::deleteSmartPlaylist(category, query.value(0).toString()); 01186 } 01187 } 01188 01189 // delete the category 01190 query.prepare("DELETE FROM music_smartplaylist_categories WHERE categoryid = :ID;"); 01191 query.bindValue(":ID", categoryid); 01192 if (!query.exec()) 01193 MythDB::DBError("Delete smartplaylist category", query); 01194 01195 return true; 01196 } 01197 01198 // static function to lookup the categoryid given its name 01199 int SmartPlaylistEditor::lookupCategoryID(QString category) 01200 { 01201 int ID; 01202 MSqlQuery query(MSqlQuery::InitCon()); 01203 query.prepare("SELECT categoryid FROM music_smartplaylist_categories " 01204 "WHERE name = :CATEGORY;"); 01205 query.bindValue(":CATEGORY", category); 01206 01207 if (query.exec()) 01208 { 01209 if (query.isActive() && query.size() > 0) 01210 { 01211 query.first(); 01212 ID = query.value(0).toInt(); 01213 } 01214 else 01215 { 01216 LOG(VB_GENERAL, LOG_ERR, 01217 QString("Failed to find smart playlist category: %1") 01218 .arg(category)); 01219 ID = -1; 01220 } 01221 } 01222 else 01223 { 01224 MythDB::DBError("Getting category ID", query); 01225 ID = -1; 01226 } 01227 01228 return ID; 01229 } 01230 01231 void SmartPlaylistEditor::getCategoryAndName(QString &category, QString &name) 01232 { 01233 category = m_categorySelector->GetValue(); 01234 name = m_titleEdit->GetText(); 01235 } 01236 01237 /* 01238 --------------------------------------------------------------------- 01239 */ 01240 01241 CriteriaRowEditor::CriteriaRowEditor(MythScreenStack* parent, SmartPLCriteriaRow* row) 01242 : MythScreenType(parent, "CriteriaRowEditor"), 01243 m_criteriaRow(NULL), m_fieldSelector(NULL), 01244 m_operatorSelector(NULL), m_value1Edit(NULL), 01245 m_value2Edit(NULL), m_value1Selector(NULL), 01246 m_value2Selector(NULL), m_value1Spinbox(NULL), 01247 m_value2Spinbox(NULL), m_value1Button(NULL), 01248 m_value2Button(NULL), m_andText(NULL), 01249 m_cancelButton(NULL), m_saveButton(NULL) 01250 { 01251 m_criteriaRow = row; 01252 } 01253 01254 CriteriaRowEditor::~CriteriaRowEditor(void) 01255 { 01256 } 01257 01258 bool CriteriaRowEditor::Create(void) 01259 { 01260 if (!LoadWindowFromXML("music-ui.xml", "criteriaroweditor", this)) 01261 return false; 01262 01263 bool err = false; 01264 01265 UIUtilE::Assign(this, m_fieldSelector, "fieldselector", &err); 01266 UIUtilE::Assign(this, m_operatorSelector, "operatorselector", &err); 01267 UIUtilE::Assign(this, m_value1Edit, "value1edit", &err); 01268 UIUtilE::Assign(this, m_value2Edit, "value2edit", &err); 01269 UIUtilE::Assign(this, m_value1Selector, "value1selector", &err); 01270 UIUtilE::Assign(this, m_value2Selector, "value2selector", &err); 01271 UIUtilE::Assign(this, m_value1Spinbox, "value1spinbox", &err); 01272 UIUtilE::Assign(this, m_value2Spinbox, "value2spinbox", &err); 01273 UIUtilE::Assign(this, m_value1Button, "value1button", &err); 01274 UIUtilE::Assign(this, m_value2Button, "value2button", &err); 01275 UIUtilE::Assign(this, m_cancelButton, "cancelbutton", &err); 01276 UIUtilE::Assign(this, m_saveButton, "savebutton", &err); 01277 01278 if (err) 01279 { 01280 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'criteriaroweditor'"); 01281 return false; 01282 } 01283 01284 updateFields(); 01285 updateOperators(); 01286 updateValues(); 01287 01288 connect(m_fieldSelector, SIGNAL(itemSelected(MythUIButtonListItem*)), SLOT(fieldChanged())); 01289 connect(m_operatorSelector, SIGNAL(itemSelected(MythUIButtonListItem*)), SLOT(operatorChanged())); 01290 01291 connect(m_value1Edit, SIGNAL(valueChanged()), SLOT(valueEditChanged())); 01292 connect(m_value2Edit, SIGNAL(valueChanged()), SLOT(valueEditChanged())); 01293 connect(m_value1Selector, SIGNAL(itemSelected(MythUIButtonListItem*)), SLOT(valueEditChanged())); 01294 connect(m_value2Selector, SIGNAL(itemSelected(MythUIButtonListItem*)), SLOT(valueEditChanged())); 01295 01296 connect(m_value1Button, SIGNAL(Clicked()), SLOT(valueButtonClicked())); 01297 connect(m_value2Button, SIGNAL(Clicked()), SLOT(valueButtonClicked())); 01298 01299 connect(m_cancelButton, SIGNAL(Clicked()), SLOT(Close())); 01300 connect(m_saveButton, SIGNAL(Clicked()), SLOT(saveClicked())); 01301 01302 BuildFocusList(); 01303 01304 return true; 01305 } 01306 01307 void CriteriaRowEditor::updateFields(void) 01308 { 01309 for (int x = 0; x < SmartPLFieldsCount; x++) 01310 new MythUIButtonListItem(m_fieldSelector, SmartPLFields[x].name); 01311 01312 m_fieldSelector->SetValue(m_criteriaRow->Field); 01313 } 01314 01315 void CriteriaRowEditor::updateOperators(void) 01316 { 01317 for (int x = 0; x < SmartPLOperatorsCount; x++) 01318 new MythUIButtonListItem(m_operatorSelector, SmartPLOperators[x].name); 01319 01320 m_operatorSelector->SetValue(m_criteriaRow->Operator); 01321 } 01322 01323 void CriteriaRowEditor::valueEditChanged(void) 01324 { 01325 enableSaveButton(); 01326 } 01327 01328 void CriteriaRowEditor::updateValues(void) 01329 { 01330 m_value1Edit->SetText(m_criteriaRow->Value1); 01331 m_value2Edit->SetText(m_criteriaRow->Value2); 01332 m_value1Spinbox->SetValue(m_criteriaRow->Value1); 01333 m_value2Spinbox->SetValue(m_criteriaRow->Value2); 01334 01335 if (!m_value1Selector->MoveToNamedPosition(m_criteriaRow->Value1)) 01336 { 01337 // not found so add it to the selector 01338 new MythUIButtonListItem(m_value1Selector, m_criteriaRow->Value1); 01339 m_value1Selector->SetValue(m_criteriaRow->Value1); 01340 } 01341 01342 if (!m_value2Selector->MoveToNamedPosition(m_criteriaRow->Value2)) 01343 { 01344 // not found so add it to the selector 01345 new MythUIButtonListItem(m_value2Selector, m_criteriaRow->Value2); 01346 m_value2Selector->SetValue(m_criteriaRow->Value2); 01347 } 01348 } 01349 01350 void CriteriaRowEditor::saveClicked() 01351 { 01352 SmartPLField *Field; 01353 Field = lookupField(m_fieldSelector->GetValue()); 01354 if (!Field) 01355 return; 01356 01357 m_criteriaRow->Field = m_fieldSelector->GetValue(); 01358 m_criteriaRow->Operator = m_operatorSelector->GetValue(); 01359 01360 if (Field->type == ftNumeric) 01361 { 01362 m_criteriaRow->Value1 = m_value1Spinbox->GetValue(); 01363 m_criteriaRow->Value2 = m_value2Spinbox->GetValue(); 01364 } 01365 else if (Field->type == ftBoolean || Field->type == ftDate) 01366 { 01367 m_criteriaRow->Value1 = m_value1Selector->GetValue(); 01368 m_criteriaRow->Value2 = m_value2Selector->GetValue(); 01369 } 01370 else // ftString 01371 { 01372 m_criteriaRow->Value1 = m_value1Edit->GetText(); 01373 m_criteriaRow->Value2 = m_value2Edit->GetText(); 01374 } 01375 01376 emit criteriaChanged(); 01377 01378 Close(); 01379 } 01380 01381 void CriteriaRowEditor::enableSaveButton() 01382 { 01383 bool enabled = false; 01384 01385 SmartPLField *Field; 01386 Field = lookupField(m_fieldSelector->GetValue()); 01387 01388 SmartPLOperator *Operator; 01389 Operator = lookupOperator(m_operatorSelector->GetValue()); 01390 01391 if (Field && Operator) 01392 { 01393 if (Field->type == ftNumeric || Field->type == ftBoolean) 01394 enabled = true; 01395 else if (Field->type == ftDate) 01396 { 01397 if (Operator->noOfArguments == 0) 01398 enabled = true; 01399 else if (Operator->noOfArguments == 1 && !m_value1Selector->GetValue().isEmpty()) 01400 enabled = true; 01401 else if (Operator->noOfArguments == 2 && !m_value1Selector->GetValue().isEmpty() 01402 && !m_value2Selector->GetValue().isEmpty()) 01403 enabled = true; 01404 } 01405 else // ftString 01406 { 01407 if (Operator->noOfArguments == 0) 01408 enabled = true; 01409 else if (Operator->noOfArguments == 1 && !m_value1Edit->GetText().isEmpty()) 01410 enabled = true; 01411 else if (Operator->noOfArguments == 2 && !m_value1Edit->GetText().isEmpty() 01412 && !m_value2Edit->GetText().isEmpty()) 01413 enabled = true; 01414 } 01415 } 01416 01417 m_saveButton->SetEnabled(enabled); 01418 } 01419 01420 void CriteriaRowEditor::fieldChanged(void) 01421 { 01422 SmartPLField *Field; 01423 Field = lookupField(m_fieldSelector->GetValue()); 01424 if (!Field) 01425 return; 01426 01427 if (Field->type == ftBoolean) 01428 { 01429 // add yes / no items to combo 01430 m_value1Selector->Reset(); 01431 new MythUIButtonListItem(m_value1Selector, "No"); 01432 new MythUIButtonListItem(m_value1Selector, "Yes"); 01433 m_value2Selector->Reset(); 01434 new MythUIButtonListItem(m_value2Selector, "No"); 01435 new MythUIButtonListItem(m_value2Selector, "Yes"); 01436 } 01437 else if (Field->type == ftDate) 01438 { 01439 // add a couple of date values to the combo 01440 m_value1Selector->Reset(); 01441 new MythUIButtonListItem(m_value1Selector, "$DATE"); 01442 new MythUIButtonListItem(m_value1Selector, "$DATE - 30 days"); 01443 new MythUIButtonListItem(m_value1Selector, "$DATE - 60 days"); 01444 01445 if (!m_value1Selector->MoveToNamedPosition(m_criteriaRow->Value1)) 01446 { 01447 // not found so add it to the selector 01448 new MythUIButtonListItem(m_value1Selector, m_criteriaRow->Value1); 01449 m_value1Selector->SetValue(m_criteriaRow->Value1); 01450 } 01451 01452 01453 m_value2Selector->Reset(); 01454 new MythUIButtonListItem(m_value2Selector, "$DATE"); 01455 new MythUIButtonListItem(m_value2Selector, "$DATE - 30 days"); 01456 new MythUIButtonListItem(m_value2Selector, "$DATE - 60 days"); 01457 01458 if (!m_value2Selector->MoveToNamedPosition(m_criteriaRow->Value2)) 01459 { 01460 // not found so add it to the selector 01461 new MythUIButtonListItem(m_value2Selector, m_criteriaRow->Value2); 01462 m_value2Selector->SetValue(m_criteriaRow->Value2); 01463 } 01464 } 01465 01466 // get list of operators valid for this field type 01467 getOperatorList(Field->type); 01468 01469 enableSaveButton(); 01470 } 01471 01472 void CriteriaRowEditor::operatorChanged(void) 01473 { 01474 SmartPLField *Field; 01475 Field = lookupField(m_fieldSelector->GetValue()); 01476 if (!Field) 01477 return; 01478 01479 SmartPLOperator *Operator; 01480 Operator = lookupOperator(m_operatorSelector->GetValue()); 01481 if (!Operator) 01482 return; 01483 01484 // hide all widgets 01485 m_value1Edit->Hide(); 01486 m_value2Edit->Hide(); 01487 m_value1Button->Hide(); 01488 m_value2Button->Hide(); 01489 m_value1Selector->Hide(); 01490 m_value2Selector->Hide(); 01491 m_value1Spinbox->Hide(); 01492 m_value2Spinbox->Hide(); 01493 01494 // show spin edits 01495 if (Field->type == ftNumeric) 01496 { 01497 if (Operator->noOfArguments >= 1) 01498 { 01499 m_value1Spinbox->Show(); 01500 int currentValue = m_value1Spinbox->GetIntValue(); 01501 m_value1Spinbox->SetRange(Field->minValue, Field->maxValue, 1); 01502 01503 if (currentValue < Field->minValue || currentValue > Field->maxValue) 01504 m_value1Spinbox->SetValue(Field->defaultValue); 01505 } 01506 01507 if (Operator->noOfArguments == 2) 01508 { 01509 m_value2Spinbox->Show(); 01510 int currentValue = m_value2Spinbox->GetIntValue(); 01511 m_value2Spinbox->SetRange(Field->minValue, Field->maxValue, 1); 01512 01513 if (currentValue < Field->minValue || currentValue > Field->maxValue) 01514 m_value2Spinbox->SetValue(Field->defaultValue); 01515 } 01516 } 01517 else if (Field->type == ftBoolean) 01518 { 01519 // only show value1combo 01520 m_value1Selector->Show(); 01521 } 01522 else if (Field->type == ftDate) 01523 { 01524 if (Operator->noOfArguments >= 1) 01525 { 01526 m_value1Selector->Show(); 01527 m_value1Button->Show(); 01528 } 01529 01530 if (Operator->noOfArguments == 2) 01531 { 01532 m_value2Selector->Show(); 01533 m_value2Button->Show(); 01534 } 01535 } 01536 else // ftString 01537 { 01538 if (Operator->noOfArguments >= 1) 01539 { 01540 m_value1Edit->Show(); 01541 m_value1Button->Show(); 01542 } 01543 01544 if (Operator->noOfArguments == 2) 01545 { 01546 m_value2Edit->Show(); 01547 m_value2Button->Show(); 01548 } 01549 } 01550 01551 enableSaveButton(); 01552 } 01553 01554 void CriteriaRowEditor::getOperatorList(SmartPLFieldType fieldType) 01555 { 01556 QString currentOperator = m_operatorSelector->GetValue(); 01557 01558 m_operatorSelector->Reset(); 01559 01560 for (int x = 0; x < SmartPLOperatorsCount; x++) 01561 { 01562 // don't add operators that only work with string fields 01563 if (fieldType != ftString && SmartPLOperators[x].stringOnly) 01564 continue; 01565 01566 // don't add operators that only work with boolean fields 01567 if (fieldType == ftBoolean && !SmartPLOperators[x].validForBoolean) 01568 continue; 01569 01570 new MythUIButtonListItem(m_operatorSelector, SmartPLOperators[x].name); 01571 } 01572 01573 // try to set the operatorCombo to the same operator or else the first item 01574 m_operatorSelector->SetValue(currentOperator); 01575 } 01576 01577 void CriteriaRowEditor::valueButtonClicked(void) 01578 { 01579 QString msg; 01580 QStringList searchList; 01581 QString s = GetFocusWidget() == m_value1Button ? m_value1Edit->GetText() : m_value2Edit->GetText(); 01582 01583 if (m_fieldSelector->GetValue() == "Artist") 01584 { 01585 msg = tr("Select an Artist"); 01586 searchList = Metadata::fillFieldList("artist"); 01587 } 01588 else if (m_fieldSelector->GetValue() == "Comp. Artist") 01589 { 01590 msg = tr("Select a Compilation Artist"); 01591 searchList = Metadata::fillFieldList("compilation_artist"); 01592 } 01593 else if (m_fieldSelector->GetValue() == "Album") 01594 { 01595 msg = tr("Select an Album"); 01596 searchList = Metadata::fillFieldList("album"); 01597 } 01598 else if (m_fieldSelector->GetValue() == "Genre") 01599 { 01600 msg = tr("Select a Genre"); 01601 searchList = Metadata::fillFieldList("genre"); 01602 } 01603 else if (m_fieldSelector->GetValue() == "Title") 01604 { 01605 msg = tr("Select a Title"); 01606 searchList = Metadata::fillFieldList("title"); 01607 } 01608 else if (m_fieldSelector->GetValue() == "Last Play") 01609 { 01610 editDate(); 01611 return; 01612 } 01613 else if (m_fieldSelector->GetValue() == "Date Imported") 01614 { 01615 editDate(); 01616 return; 01617 } 01618 01619 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 01620 MythUISearchDialog *searchDlg = new MythUISearchDialog(popupStack, msg, searchList, false, s); 01621 01622 if (!searchDlg->Create()) 01623 { 01624 delete searchDlg; 01625 return; 01626 } 01627 01628 connect(searchDlg, SIGNAL(haveResult(QString)), SLOT(setValue(QString))); 01629 01630 popupStack->AddScreen(searchDlg); 01631 } 01632 01633 void CriteriaRowEditor::setValue(QString value) 01634 { 01635 if (GetFocusWidget() && GetFocusWidget() == m_value1Button) 01636 m_value1Edit->SetText(value); 01637 else 01638 m_value2Edit->SetText(value); 01639 } 01640 01641 void CriteriaRowEditor::editDate(void) 01642 { 01643 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 01644 SmartPLDateDialog *dateDlg = new SmartPLDateDialog(popupStack); 01645 QString date = GetFocusWidget() == m_value1Button ? m_value1Selector->GetValue() : m_value2Selector->GetValue(); 01646 01647 if (!dateDlg->Create()) 01648 { 01649 delete dateDlg; 01650 return; 01651 } 01652 01653 dateDlg->setDate(date); 01654 01655 connect(dateDlg, SIGNAL(dateChanged(QString)), SLOT(setDate(QString))); 01656 01657 popupStack->AddScreen(dateDlg); 01658 } 01659 01660 void CriteriaRowEditor::setDate(QString date) 01661 { 01662 if (GetFocusWidget() && GetFocusWidget() == m_value1Button) 01663 { 01664 if (m_value1Selector->MoveToNamedPosition(date)) 01665 return; 01666 01667 // not found so add it to the selector 01668 new MythUIButtonListItem(m_value1Selector, date); 01669 m_value1Selector->SetValue(date); 01670 } 01671 else 01672 { 01673 if (m_value2Selector->MoveToNamedPosition(date)) 01674 return; 01675 01676 // not found so add it to the selector 01677 new MythUIButtonListItem(m_value2Selector, date); 01678 m_value2Selector->SetValue(date); 01679 } 01680 } 01681 01682 /* 01683 --------------------------------------------------------------------- 01684 */ 01685 01686 01687 SmartPLResultViewer::SmartPLResultViewer(MythScreenStack *parent) 01688 : MythScreenType(parent, "SmartPLResultViewer"), 01689 m_trackList(NULL), m_positionText(NULL) 01690 { 01691 } 01692 01693 SmartPLResultViewer::~SmartPLResultViewer() 01694 { 01695 } 01696 01697 bool SmartPLResultViewer::Create(void) 01698 { 01699 if (!LoadWindowFromXML("music-ui.xml", "smartplresultviewer", this)) 01700 return false; 01701 01702 bool err = false; 01703 01704 UIUtilE::Assign(this, m_trackList, "tracklist", &err); 01705 UIUtilW::Assign(this, m_positionText, "position", &err); 01706 01707 if (err) 01708 { 01709 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'smartplresultviewer'"); 01710 return false; 01711 } 01712 01713 connect(m_trackList, SIGNAL(itemVisible(MythUIButtonListItem*)), 01714 this, SLOT(trackVisible(MythUIButtonListItem*))); 01715 connect(m_trackList, SIGNAL(itemSelected(MythUIButtonListItem*)), 01716 this, SLOT(trackSelected(MythUIButtonListItem*))); 01717 01718 BuildFocusList(); 01719 01720 return true; 01721 } 01722 01723 bool SmartPLResultViewer::keyPressEvent(QKeyEvent *event) 01724 { 01725 if (GetFocusWidget() && GetFocusWidget()->keyPressEvent(event)) 01726 return true; 01727 01728 bool handled = false; 01729 QStringList actions; 01730 handled = GetMythMainWindow()->TranslateKeyPress("Music", event, actions); 01731 01732 for (int i = 0; i < actions.size() && !handled; i++) 01733 { 01734 QString action = actions[i]; 01735 handled = true; 01736 01737 if (action == "INFO") 01738 showTrackInfo(); 01739 else 01740 handled = false; 01741 } 01742 01743 if (!handled && MythScreenType::keyPressEvent(event)) 01744 handled = true; 01745 01746 return handled; 01747 } 01748 01749 void SmartPLResultViewer::trackVisible(MythUIButtonListItem *item) 01750 { 01751 if (!item) 01752 return; 01753 01754 if (item->GetImage().isEmpty()) 01755 { 01756 Metadata *mdata = qVariantValue<Metadata*> (item->GetData()); 01757 if (mdata) 01758 { 01759 QString artFile = mdata->getAlbumArtFile(); 01760 if (artFile.isEmpty()) 01761 item->SetImage("mm_nothumb.png"); 01762 else 01763 item->SetImage(mdata->getAlbumArtFile()); 01764 } 01765 else 01766 item->SetImage("mm_nothumb.png"); 01767 } 01768 } 01769 01770 void SmartPLResultViewer::trackSelected(MythUIButtonListItem *item) 01771 { 01772 if (!item || !m_positionText) 01773 return; 01774 01775 m_positionText->SetText(QString(tr("%1 of %2")) 01776 .arg(m_trackList->GetCurrentPos() + 1) 01777 .arg(m_trackList->GetCount())); 01778 } 01779 void SmartPLResultViewer::showTrackInfo(void) 01780 { 01781 MythUIButtonListItem *item = m_trackList->GetItemCurrent(); 01782 if (!item) 01783 return; 01784 01785 Metadata *mdata = qVariantValue<Metadata*> (item->GetData()); 01786 if (!mdata) 01787 return; 01788 01789 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 01790 01791 TrackInfoDialog *dlg = new TrackInfoDialog(popupStack, mdata, "trackinfopopup"); 01792 01793 if (!dlg->Create()) 01794 { 01795 delete dlg; 01796 return; 01797 } 01798 01799 popupStack->AddScreen(dlg); 01800 } 01801 01802 void SmartPLResultViewer::setSQL(QString sql) 01803 { 01804 m_trackList->Reset();; 01805 01806 MSqlQuery query(MSqlQuery::InitCon()); 01807 01808 if (query.exec(sql)) 01809 { 01810 while (query.next()) 01811 { 01812 Metadata *mdata = gMusicData->all_music->getMetadata(query.value(0).toInt()); 01813 if (mdata) 01814 { 01815 MetadataMap metadataMap; 01816 mdata->toMap(metadataMap); 01817 01818 MythUIButtonListItem *item = new MythUIButtonListItem(m_trackList, "", qVariantFromValue(mdata)); 01819 item->SetTextFromMap(metadataMap); 01820 } 01821 } 01822 } 01823 01824 trackSelected(m_trackList->GetItemCurrent()); 01825 } 01826 01827 01828 /* 01829 --------------------------------------------------------------------- 01830 */ 01831 01832 SmartPLOrderByDialog::SmartPLOrderByDialog(MythScreenStack *parent) 01833 :MythScreenType(parent, "SmartPLOrderByDialog"), 01834 m_fieldList(NULL), m_orderSelector(NULL), m_addButton(NULL), 01835 m_deleteButton(NULL), m_moveUpButton(NULL), m_moveDownButton(NULL), 01836 m_ascendingButton(NULL), m_descendingButton(NULL), m_cancelButton(NULL), 01837 m_okButton(NULL) 01838 { 01839 } 01840 01841 SmartPLOrderByDialog::~SmartPLOrderByDialog(void) 01842 { 01843 } 01844 01845 bool SmartPLOrderByDialog::Create(void) 01846 { 01847 if (!LoadWindowFromXML("music-ui.xml", "orderbydialog", this)) 01848 return false; 01849 01850 bool err = false; 01851 01852 UIUtilE::Assign(this, m_fieldList, "fieldlist", &err); 01853 UIUtilE::Assign(this, m_orderSelector, "fieldselector", &err); 01854 UIUtilE::Assign(this, m_addButton, "addbutton", &err); 01855 UIUtilE::Assign(this, m_deleteButton, "deletebutton", &err); 01856 UIUtilE::Assign(this, m_moveUpButton, "moveupbutton", &err); 01857 UIUtilE::Assign(this, m_moveDownButton, "movedownbutton", &err); 01858 UIUtilE::Assign(this, m_ascendingButton, "ascendingbutton", &err); 01859 UIUtilE::Assign(this, m_descendingButton, "descendingbutton", &err); 01860 UIUtilE::Assign(this, m_cancelButton, "cancelbutton", &err); 01861 UIUtilE::Assign(this, m_okButton, "okbutton", &err); 01862 01863 if (err) 01864 { 01865 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'orderbydialog'"); 01866 return false; 01867 } 01868 01869 connect(m_addButton, SIGNAL(Clicked()), this, SLOT(addPressed())); 01870 connect(m_deleteButton, SIGNAL(Clicked()), this, SLOT(deletePressed())); 01871 connect(m_moveUpButton, SIGNAL(Clicked()), this, SLOT(moveUpPressed())); 01872 connect(m_moveDownButton, SIGNAL(Clicked()), this, SLOT(moveDownPressed())); 01873 connect(m_ascendingButton, SIGNAL(Clicked()), this, SLOT(ascendingPressed())); 01874 connect(m_descendingButton, SIGNAL(Clicked()), this, SLOT(descendingPressed())); 01875 connect(m_cancelButton, SIGNAL(Clicked()), this, SLOT(Close())); 01876 connect(m_okButton, SIGNAL(Clicked()), this, SLOT(okPressed())); 01877 01878 connect(m_orderSelector, SIGNAL(itemSelected(MythUIButtonListItem*)), 01879 this, SLOT(orderByChanged(void))); 01880 connect(m_fieldList, SIGNAL(itemSelected(MythUIButtonListItem*)), 01881 this, SLOT(fieldListSelectionChanged(MythUIButtonListItem*))); 01882 01883 getOrderByFields(); 01884 01885 orderByChanged(); 01886 01887 BuildFocusList(); 01888 01889 return true; 01890 } 01891 01892 QString SmartPLOrderByDialog::getFieldList(void) 01893 { 01894 QString result; 01895 bool bFirst = true; 01896 01897 for (int i = 0; i < m_fieldList->GetCount(); i++) 01898 { 01899 if (bFirst) 01900 { 01901 bFirst = false; 01902 result = m_fieldList->GetItemAt(i)->GetText(); 01903 } 01904 else 01905 result += ", " + m_fieldList->GetItemAt(i)->GetText(); 01906 } 01907 01908 return result; 01909 } 01910 01911 void SmartPLOrderByDialog::setFieldList(const QString &fieldList) 01912 { 01913 m_fieldList->Reset(); 01914 QStringList list = fieldList.split(","); 01915 01916 for (int x = 0; x < list.count(); x++) 01917 { 01918 MythUIButtonListItem *item = new MythUIButtonListItem(m_fieldList, list[x].trimmed()); 01919 QString state = list[x].contains("(A)") ? "ascending" : "descending"; 01920 item->DisplayState(state, "sortstate"); 01921 } 01922 01923 orderByChanged(); 01924 } 01925 01926 void SmartPLOrderByDialog::fieldListSelectionChanged(MythUIButtonListItem *item) 01927 { 01928 if (!item) 01929 return; 01930 01931 m_orderSelector->SetValue(item->GetText().left(item->GetText().length() - 4)); 01932 } 01933 01934 void SmartPLOrderByDialog::ascendingPressed(void) 01935 { 01936 if (!m_fieldList->GetItemCurrent()) 01937 return; 01938 01939 m_fieldList->GetItemCurrent()->SetText(m_orderSelector->GetValue() + " (A)"); 01940 m_fieldList->GetItemCurrent()->DisplayState("ascending", "sortstate"); 01941 01942 orderByChanged(); 01943 SetFocusWidget(m_descendingButton); 01944 } 01945 01946 void SmartPLOrderByDialog::descendingPressed(void) 01947 { 01948 if (!m_fieldList->GetItemCurrent()) 01949 return; 01950 01951 m_fieldList->GetItemCurrent()->SetText(m_orderSelector->GetValue() + " (D)"); 01952 m_fieldList->GetItemCurrent()->DisplayState("descending", "sortstate"); 01953 01954 orderByChanged(); 01955 SetFocusWidget(m_ascendingButton); 01956 } 01957 01958 void SmartPLOrderByDialog::addPressed(void) 01959 { 01960 MythUIButtonListItem *item = new MythUIButtonListItem(m_fieldList, m_orderSelector->GetValue() + " (A)"); 01961 item->DisplayState("ascending", "sortstate"); 01962 01963 orderByChanged(); 01964 SetFocusWidget(m_orderSelector); 01965 } 01966 01967 void SmartPLOrderByDialog::deletePressed(void) 01968 { 01969 m_fieldList->RemoveItem(m_fieldList->GetItemCurrent()); 01970 orderByChanged(); 01971 01972 if (!m_deleteButton->IsEnabled()) 01973 SetFocusWidget(m_addButton); 01974 else 01975 SetFocusWidget(m_deleteButton); 01976 } 01977 01978 void SmartPLOrderByDialog::moveUpPressed(void) 01979 { 01980 MythUIButtonListItem *item = m_fieldList->GetItemCurrent(); 01981 01982 if (item) 01983 item->MoveUpDown(true); 01984 01985 orderByChanged(); 01986 01987 if (!m_moveUpButton->IsEnabled()) 01988 SetFocusWidget(m_moveDownButton); 01989 else 01990 SetFocusWidget(m_moveUpButton); 01991 } 01992 01993 void SmartPLOrderByDialog::moveDownPressed(void) 01994 { 01995 MythUIButtonListItem *item = m_fieldList->GetItemCurrent(); 01996 01997 if (item) 01998 item->MoveUpDown(false); 01999 02000 orderByChanged(); 02001 02002 if (!m_moveDownButton->IsEnabled()) 02003 SetFocusWidget(m_moveUpButton); 02004 else 02005 SetFocusWidget(m_moveDownButton); 02006 } 02007 02008 void SmartPLOrderByDialog::okPressed(void) 02009 { 02010 emit orderByChanged(getFieldList()); 02011 Close(); 02012 } 02013 02014 void SmartPLOrderByDialog::orderByChanged(void) 02015 { 02016 bool found = false; 02017 for (int i = 0 ; i < m_fieldList->GetCount() ; ++i) 02018 { 02019 if (m_fieldList->GetItemAt(i)->GetText().startsWith(m_orderSelector->GetValue())) 02020 { 02021 m_fieldList->SetItemCurrent(i); 02022 found = true; 02023 } 02024 } 02025 02026 if (found) 02027 { 02028 m_addButton->SetEnabled(false); 02029 m_deleteButton->SetEnabled(true); 02030 m_moveUpButton->SetEnabled((m_fieldList->GetCurrentPos() != 0)); 02031 m_moveDownButton->SetEnabled((m_fieldList->GetCurrentPos() != m_fieldList->GetCount() - 1) ); 02032 m_ascendingButton->SetEnabled((m_fieldList->GetValue().right(3) == "(D)") ); 02033 m_descendingButton->SetEnabled((m_fieldList->GetValue().right(3) == "(A)")); 02034 } 02035 else 02036 { 02037 m_addButton->SetEnabled(true); 02038 m_deleteButton->SetEnabled(false); 02039 m_moveUpButton->SetEnabled(false); 02040 m_moveDownButton->SetEnabled(false); 02041 m_ascendingButton->SetEnabled(false); 02042 m_descendingButton->SetEnabled(false); 02043 } 02044 } 02045 02046 void SmartPLOrderByDialog::getOrderByFields(void) 02047 { 02048 m_orderSelector->Reset(); 02049 for (int x = 1; x < SmartPLFieldsCount; x++) 02050 new MythUIButtonListItem(m_orderSelector, SmartPLFields[x].name); 02051 } 02052 02053 #if 0 02054 /* 02055 --------------------------------------------------------------------- 02056 */ 02057 02058 SmartPlaylistDialog::SmartPlaylistDialog(MythMainWindow *parent, const char *name) 02059 :MythPopupBox(parent, name) 02060 { 02061 bool keyboard_accelerators = gCoreContext->GetNumSetting("KeyboardAccelerators", 1); 02062 02063 // we have to create a parentless layout because otherwise MythPopupbox 02064 // complains about already having a layout 02065 vbox = new Q3VBoxLayout((QWidget *) 0, (int)(10 * hmult)); 02066 02067 Q3HBoxLayout *hbox = new Q3HBoxLayout(vbox, (int)(10 * wmult)); 02068 02069 // create the widgets 02070 02071 caption = new QLabel(QString(tr("Smart Playlists")), this); 02072 QFont font = caption->font(); 02073 font.setPointSize(int (font.pointSize() * 1.2)); 02074 font.setBold(true); 02075 caption->setFont(font); 02076 caption->setPaletteForegroundColor(QColor("yellow")); 02077 caption->setBackgroundOrigin(ParentOrigin); 02078 caption->setAlignment(Qt::AlignCenter); 02079 caption->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); 02080 caption->setMinimumWidth((int)(600 * hmult)); 02081 caption->setMaximumWidth((int)(600 * hmult)); 02082 hbox->addWidget(caption); 02083 02084 // category 02085 hbox = new Q3HBoxLayout(vbox, (int)(10 * hmult)); 02086 categoryCombo = new MythComboBox(false, this, "categoryCombo"); 02087 categoryCombo->setFocus(); 02088 connect(categoryCombo, SIGNAL(highlighted(int)), this, SLOT(categoryChanged(void))); 02089 connect(categoryCombo, SIGNAL(activated(int)), this, SLOT(categoryChanged(void))); 02090 hbox->addWidget(categoryCombo); 02091 getSmartPlaylistCategories(); 02092 02093 // listbox 02094 hbox = new Q3HBoxLayout(vbox, (int)(5 * hmult)); 02095 listbox = new Q3MythListBox(this); 02096 listbox->setScrollBar(false); 02097 listbox->setBottomScrollBar(false); 02098 hbox->addWidget(listbox); 02099 02100 hbox = new Q3HBoxLayout(vbox, (int)(5 * wmult)); 02101 selectButton = new MythPushButton(this, "selectbutton"); 02102 if (keyboard_accelerators) 02103 selectButton->setText(tr("1 Select")); 02104 else 02105 selectButton->setText(tr("Select")); 02106 hbox->addWidget(selectButton); 02107 02108 newButton = new MythPushButton(this, "newbutton"); 02109 if (keyboard_accelerators) 02110 newButton->setText(tr("2 New")); 02111 else 02112 newButton->setText(tr("New")); 02113 hbox->addWidget(newButton); 02114 02115 hbox = new Q3HBoxLayout(vbox, (int)(5 * wmult)); 02116 editButton = new MythPushButton(this, "editbutton"); 02117 if (keyboard_accelerators) 02118 editButton->setText(tr("3 Edit")); 02119 else 02120 editButton->setText(tr("Edit")); 02121 hbox->addWidget(editButton); 02122 02123 deleteButton = new MythPushButton(this, "deletebutton"); 02124 if (keyboard_accelerators) 02125 deleteButton->setText(tr("4 Delete")); 02126 else 02127 deleteButton->setText(tr("Delete")); 02128 hbox->addWidget(deleteButton); 02129 02130 addLayout(vbox); 02131 02132 connect(newButton, SIGNAL(clicked()), this, SLOT(newPressed())); 02133 connect(editButton, SIGNAL(clicked()), this, SLOT(editPressed())); 02134 connect(deleteButton, SIGNAL(clicked()), this, SLOT(deletePressed())); 02135 connect(selectButton, SIGNAL(clicked()), this, SLOT(selectPressed())); 02136 02137 categoryChanged(); 02138 } 02139 02140 void SmartPlaylistDialog::setSmartPlaylist(QString Category, QString Name) 02141 { 02142 // try to set the current playlist 02143 for (int x = 0; x < categoryCombo->count(); x++) 02144 { 02145 if (categoryCombo->text(x) == Category) 02146 { 02147 categoryCombo->setCurrentItem(x); 02148 categoryChanged(); 02149 listbox->setCurrentItem(Name); 02150 listbox->setFocus(); 02151 return; 02152 } 02153 } 02154 02155 // can't find the smartplaylist just select the first item 02156 categoryCombo->setCurrentItem(0); 02157 listbox->setCurrentItem(0); 02158 } 02159 02160 SmartPlaylistDialog::~SmartPlaylistDialog(void) 02161 { 02162 if (vbox) 02163 { 02164 delete vbox; 02165 vbox = NULL; 02166 } 02167 } 02168 02169 void SmartPlaylistDialog::keyPressEvent(QKeyEvent *e) 02170 { 02171 bool handled = false; 02172 QStringList actions; 02173 handled = GetMythMainWindow()->TranslateKeyPress("qt", e, actions); 02174 02175 for (int i = 0; i < actions.size() && !handled; i++) 02176 { 02177 QString action = actions[i]; 02178 if (action == "ESCAPE") 02179 { 02180 handled = true; 02181 reject(); 02182 } 02183 else if (action == "LEFT") 02184 { 02185 handled = true; 02186 focusNextPrevChild(false); 02187 } 02188 else if (action == "RIGHT") 02189 { 02190 handled = true; 02191 focusNextPrevChild(true); 02192 } 02193 else if (action == "UP") 02194 { 02195 handled = true; 02196 focusNextPrevChild(false); 02197 } 02198 else if (action == "DOWN") 02199 { 02200 handled = true; 02201 focusNextPrevChild(true); 02202 } 02203 else if (action == "1") 02204 { 02205 handled = true; 02206 selectPressed(); 02207 } 02208 else if (action == "2") 02209 { 02210 handled = true; 02211 newPressed(); 02212 } 02213 else if (action == "3") 02214 { 02215 handled = true; 02216 editPressed(); 02217 } 02218 else if (action == "4") 02219 { 02220 handled = true; 02221 deletePressed(); 02222 } 02223 else if (action == "SELECT" && listbox->hasFocus()) 02224 { 02225 handled = true; 02226 selectPressed(); 02227 } 02228 02229 } 02230 02231 if (!handled) 02232 MythPopupBox::keyPressEvent(e); 02233 } 02234 02235 void SmartPlaylistDialog::newPressed(void) 02236 { 02237 #if 0 02238 SmartPlaylistEditor* editor = new SmartPlaylistEditor(GetMythMainWindow(), "SmartPlaylistEditor"); 02239 editor->newSmartPlaylist(categoryCombo->currentText()); 02240 02241 editor->exec(); 02242 QString category; 02243 QString name; 02244 editor->getCategoryAndName(category, name); 02245 02246 delete editor; 02247 02248 getSmartPlaylistCategories(); 02249 02250 // try to select the correct category and name 02251 categoryCombo->setCurrentText(category); 02252 categoryChanged(); 02253 listbox->setCurrentItem(name); 02254 listbox->setFocus(); 02255 #endif 02256 } 02257 02258 void SmartPlaylistDialog::selectPressed(void) 02259 { 02260 accept(); 02261 } 02262 02263 void SmartPlaylistDialog::deletePressed(void) 02264 { 02265 if (!listbox->selectedItem()) 02266 return; 02267 02268 QString category = categoryCombo->currentText(); 02269 QString name = listbox->selectedItem()->text(); 02270 02271 if (!MythPopupBox::showOkCancelPopup(GetMythMainWindow(), 02272 "Delete SmartPlaylist", 02273 tr("Are you sure you want to delete this SmartPlaylist?") 02274 + "\n\n\"" + name + "\"", false)) 02275 { 02276 deleteButton->setFocus(); 02277 return; 02278 } 02279 02280 SmartPlaylistEditor::deleteSmartPlaylist(category, name); 02281 02282 //refresh lists 02283 getSmartPlaylistCategories(); 02284 categoryCombo->setCurrentText(category); 02285 categoryChanged(); 02286 02287 if (listbox->count() > 0) 02288 deleteButton->setFocus(); 02289 else 02290 newButton->setFocus(); 02291 } 02292 02293 void SmartPlaylistDialog::editPressed(void) 02294 { 02295 #if 0 02296 QString category = categoryCombo->currentText(); 02297 QString name = listbox->currentText(); 02298 02299 SmartPlaylistEditor* editor = new SmartPlaylistEditor(GetMythMainWindow(), "SmartPlaylistEditor"); 02300 editor->editSmartPlaylist(category, name); 02301 02302 editor->exec(); 02303 editor->getCategoryAndName(category, name); 02304 getSmartPlaylistCategories(); 02305 categoryChanged(); 02306 02307 delete editor; 02308 02309 // try to select the correct category and name 02310 categoryCombo->setCurrentText(category); 02311 listbox->setCurrentItem(name); 02312 listbox->setFocus(); 02313 #endif 02314 } 02315 02316 void SmartPlaylistDialog::categoryChanged(void) 02317 { 02318 getSmartPlaylists(categoryCombo->currentText()); 02319 } 02320 02321 void SmartPlaylistDialog::getSmartPlaylistCategories(void) 02322 { 02323 categoryCombo->clear(); 02324 MSqlQuery query(MSqlQuery::InitCon()); 02325 02326 if (query.exec("SELECT name FROM music_smartplaylist_categories ORDER BY name;")) 02327 { 02328 if (query.isActive() && query.size() > 0) 02329 { 02330 while (query.next()) 02331 categoryCombo->insertItem(query.value(0).toString()); 02332 } 02333 } 02334 else 02335 { 02336 MythDB::DBError("Load smartplaylist categories", query); 02337 } 02338 } 02339 02340 void SmartPlaylistDialog::getSmartPlaylists(QString category) 02341 { 02342 int categoryid = SmartPlaylistEditor::lookupCategoryID(category); 02343 02344 listbox->clear(); 02345 02346 MSqlQuery query(MSqlQuery::InitCon()); 02347 query.prepare("SELECT name FROM music_smartplaylists WHERE categoryid = :CATEGORYID " 02348 "ORDER BY name;"); 02349 query.bindValue(":CATEGORYID", categoryid); 02350 if (query.exec()) 02351 { 02352 if (query.isActive() && query.size() > 0) 02353 { 02354 while (query.next()) 02355 { 02356 listbox->insertItem(query.value(0).toString()); 02357 } 02358 02359 listbox->setCurrentItem(0); 02360 listbox->setTopItem(0); 02361 } 02362 } 02363 else 02364 MythDB::DBError("Load smartplaylist names", query); 02365 02366 02367 deleteButton->setEnabled( (listbox->count() > 0) ); 02368 selectButton->setEnabled( (listbox->count() > 0) ); 02369 editButton->setEnabled( (listbox->count() > 0) ); 02370 } 02371 02372 void SmartPlaylistDialog::getSmartPlaylist(QString &category, QString &name) 02373 { 02374 category = categoryCombo->currentText(); 02375 name = listbox->currentText(); 02376 } 02377 02378 #endif 02379 /* 02380 --------------------------------------------------------------------- 02381 */ 02382 02383 SmartPLDateDialog::SmartPLDateDialog(MythScreenStack *parent) 02384 :MythScreenType(parent, "SmartPLDateDialog"), 02385 m_updating(false), m_fixedRadio(NULL), m_daySpin(NULL), 02386 m_monthSpin(NULL), m_yearSpin(NULL), m_nowRadio(NULL), 02387 m_addDaysSpin(NULL), m_statusText(NULL), 02388 m_cancelButton(NULL), m_okButton(NULL) 02389 { 02390 m_updating = false; 02391 } 02392 02393 bool SmartPLDateDialog::Create(void) 02394 { 02395 if (!LoadWindowFromXML("music-ui.xml", "dateeditordialog", this)) 02396 return false; 02397 02398 bool err = false; 02399 02400 UIUtilE::Assign(this, m_fixedRadio, "fixeddatecheck", &err); 02401 UIUtilE::Assign(this, m_daySpin, "dayspinbox", &err); 02402 UIUtilE::Assign(this, m_monthSpin, "monthspinbox", &err); 02403 UIUtilE::Assign(this, m_yearSpin, "yearspinbox", &err); 02404 UIUtilE::Assign(this, m_nowRadio, "nowcheck", &err); 02405 UIUtilE::Assign(this, m_addDaysSpin, "adddaysspinbox", &err); 02406 UIUtilE::Assign(this, m_statusText, "statustext", &err); 02407 UIUtilE::Assign(this, m_cancelButton, "cancelbutton", &err); 02408 UIUtilE::Assign(this, m_okButton, "okbutton", &err); 02409 02410 if (err) 02411 { 02412 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'dateeditordialog'"); 02413 return false; 02414 } 02415 02416 m_daySpin->SetRange(1, 31, 1); 02417 m_monthSpin->SetRange(1, 12, 1); 02418 m_yearSpin->SetRange(1900, 2099, 1); 02419 m_addDaysSpin->SetRange(-9999, 9999, 1); 02420 02421 02422 connect(m_fixedRadio, SIGNAL(toggled(bool)), this, SLOT(fixedCheckToggled(bool))); 02423 connect(m_nowRadio, SIGNAL(toggled(bool)), this, SLOT(nowCheckToggled(bool))); 02424 //connect(addDaysCheck, SIGNAL(toggled(bool)), this, SLOT(addDaysCheckToggled(bool))); 02425 connect(m_addDaysSpin, SIGNAL(itemSelected(MythUIButtonListItem*)), 02426 this, SLOT(valueChanged(void))); 02427 connect(m_daySpin, SIGNAL(itemSelected(MythUIButtonListItem*)), 02428 this, SLOT(valueChanged(void))); 02429 connect(m_monthSpin, SIGNAL(itemSelected(MythUIButtonListItem*)), 02430 this, SLOT(valueChanged(void))); 02431 connect(m_yearSpin, SIGNAL(itemSelected(MythUIButtonListItem*)), 02432 this, SLOT(valueChanged(void))); 02433 02434 connect(m_cancelButton, SIGNAL(Clicked()), this, SLOT(Close())); 02435 connect(m_okButton, SIGNAL(Clicked()), this, SLOT(okPressed())); 02436 02437 valueChanged(); 02438 02439 BuildFocusList(); 02440 02441 return true; 02442 } 02443 02444 SmartPLDateDialog::~SmartPLDateDialog(void) 02445 { 02446 } 02447 02448 QString SmartPLDateDialog::getDate(void) 02449 { 02450 QString sResult; 02451 02452 if (m_fixedRadio->GetBooleanCheckState()) 02453 { 02454 QString day = m_daySpin->GetValue(); 02455 if (m_daySpin->GetIntValue() < 10) 02456 day = "0" + day; 02457 02458 QString month = m_monthSpin->GetValue(); 02459 if (m_monthSpin->GetIntValue() < 10) 02460 month = "0" + month; 02461 02462 sResult = m_yearSpin->GetValue() + "-" + month + "-" + day; 02463 } 02464 else 02465 sResult = m_statusText->GetText(); 02466 02467 return sResult; 02468 } 02469 02470 void SmartPLDateDialog::setDate(QString date) 02471 { 02472 if (date.startsWith("$DATE")) 02473 { 02474 m_nowRadio->SetCheckState(true); 02475 m_fixedRadio->SetCheckState(false); 02476 02477 if (date.length() > 9) 02478 { 02479 bool bNegative = false; 02480 if (date[6] == '-') 02481 bNegative = true; 02482 02483 if (date.endsWith(" days")) 02484 date = date.left(date.length() - 5); 02485 02486 int nDays = date.mid(8).toInt(); 02487 if (bNegative) 02488 nDays = -nDays; 02489 02490 m_addDaysSpin->SetValue(nDays); 02491 } 02492 else 02493 m_addDaysSpin->SetValue(0); 02494 02495 nowCheckToggled(true); 02496 } 02497 else 02498 { 02499 int nYear = date.mid(0, 4).toInt(); 02500 int nMonth = date.mid(5, 2).toInt(); 02501 int nDay = date.mid(8, 2).toInt(); 02502 02503 m_daySpin->SetValue(nDay); 02504 m_monthSpin->SetValue(nMonth); 02505 m_yearSpin->SetValue(nYear); 02506 02507 fixedCheckToggled(true); 02508 } 02509 } 02510 02511 void SmartPLDateDialog::fixedCheckToggled(bool on) 02512 { 02513 if (m_updating) 02514 return; 02515 02516 m_updating = true; 02517 m_daySpin->SetEnabled(on); 02518 m_monthSpin->SetEnabled(on); 02519 m_yearSpin->SetEnabled(on); 02520 02521 m_nowRadio->SetCheckState(!on); 02522 m_addDaysSpin->SetEnabled(!on); 02523 02524 valueChanged(); 02525 02526 m_updating = false; 02527 } 02528 02529 void SmartPLDateDialog::nowCheckToggled(bool on) 02530 { 02531 if (m_updating) 02532 return; 02533 02534 m_updating = true; 02535 02536 m_fixedRadio->SetCheckState(!on); 02537 m_daySpin->SetEnabled(!on); 02538 m_monthSpin->SetEnabled(!on); 02539 m_yearSpin->SetEnabled(!on); 02540 02541 m_addDaysSpin->SetEnabled(on); 02542 02543 valueChanged(); 02544 02545 m_updating = false; 02546 } 02547 02548 void SmartPLDateDialog::okPressed(void ) 02549 { 02550 QString date = getDate(); 02551 02552 emit dateChanged(date); 02553 02554 Close(); 02555 } 02556 02557 void SmartPLDateDialog::valueChanged(void) 02558 { 02559 bool bValidDate = true; 02560 02561 if (m_fixedRadio->GetBooleanCheckState()) 02562 { 02563 QString day = m_daySpin->GetValue(); 02564 if (m_daySpin->GetIntValue() < 10) 02565 day = "0" + day; 02566 02567 QString month = m_monthSpin->GetValue(); 02568 if (m_monthSpin->GetIntValue() < 10) 02569 month = "0" + month; 02570 02571 QString sDate = m_yearSpin->GetValue() + "-" + month + "-" + day; 02572 QDate date = QDate::fromString(sDate, Qt::ISODate); 02573 if (date.isValid()) 02574 m_statusText->SetText(date.toString("dddd, d MMMM yyyy")); 02575 else 02576 { 02577 bValidDate = false; 02578 m_statusText->SetText(tr("Invalid Date")); 02579 } 02580 } 02581 else if (m_nowRadio->GetBooleanCheckState()) 02582 { 02583 QString days; 02584 if (m_addDaysSpin->GetIntValue() > 0) 02585 days = QString("$DATE + %1 days").arg(m_addDaysSpin->GetIntValue()); 02586 else if (m_addDaysSpin->GetIntValue() == 0) 02587 days = QString("$DATE"); 02588 else 02589 days = QString("$DATE - %1 days").arg( 02590 m_addDaysSpin->GetValue().right(m_addDaysSpin->GetValue().length() - 1)); 02591 02592 m_statusText->SetText(days); 02593 } 02594 02595 if (bValidDate) 02596 m_statusText->SetFontState("valid"); 02597 else 02598 m_statusText->SetFontState("error"); 02599 02600 m_okButton->SetEnabled(bValidDate); 02601 } 02602
1.7.6.1