Ticket #12961: 0001-SortHelper-and-store-sort-fields-in-db.patch
| File 0001-SortHelper-and-store-sort-fields-in-db.patch, 159.3 KB (added by , 9 years ago) |
|---|
-
mythplugins/mythnetvision/mythnetvision/netsearch.cpp
.../mythnetvision/mythnetvision/netsearch.cpp | 1 + .../mythnetvision/mythnetvision/nettree.cpp | 6 +- mythtv/bindings/perl/MythTV.pm | 6 +- mythtv/bindings/php/MythBackend.php | 6 +- mythtv/libs/libmyth/mythrssmanager.cpp | 6 +- mythtv/libs/libmyth/netutils.cpp | 31 +- mythtv/libs/libmyth/programinfo.cpp | 129 +++++++-- mythtv/libs/libmyth/programinfo.h | 23 +- mythtv/libs/libmyth/rssparse.cpp | 13 +- mythtv/libs/libmyth/rssparse.h | 7 +- .../test/test_programinfo/test_programinfo.h | 53 +++- mythtv/libs/libmythbase/libmythbase.pro | 3 + mythtv/libs/libmythbase/mythsorthelper.cpp | 92 ++++++ mythtv/libs/libmythbase/mythsorthelper.h | 30 ++ mythtv/libs/libmythbase/mythversion.h | 6 +- .../test/test_videometadata/test_videometadata.h | 26 +- mythtv/libs/libmythmetadata/videometadata.cpp | 320 +++++++++++---------- mythtv/libs/libmythmetadata/videometadata.h | 37 +-- .../libmythmetadata/videometadatalistmanager.cpp | 35 ++- .../libmythmetadata/videometadatalistmanager.h | 3 + mythtv/libs/libmythmetadata/videoscan.cpp | 8 +- mythtv/libs/libmythtv/datadirect.cpp | 31 +- mythtv/libs/libmythtv/dbcheck.cpp | 146 +++++++++- mythtv/libs/libmythtv/eithelper.cpp | 8 +- mythtv/libs/libmythtv/programdata.cpp | 86 +++++- mythtv/libs/libmythtv/programdata.h | 25 +- mythtv/libs/libmythtv/recordinginfo.cpp | 37 ++- mythtv/libs/libmythtv/recordinginfo.h | 4 + mythtv/libs/libmythtv/recordingrule.cpp | 37 ++- mythtv/libs/libmythtv/recordingrule.h | 2 + .../test/test_eitfixups/test_eitfixups.cpp | 2 + mythtv/programs/mythbackend/main_helpers.cpp | 5 +- mythtv/programs/mythbackend/scheduler.cpp | 23 +- mythtv/programs/mythbackend/services/video.cpp | 8 +- mythtv/programs/mythfrontend/globalsettings.cpp | 38 +++ mythtv/programs/mythfrontend/main.cpp | 6 +- mythtv/programs/mythfrontend/playbackbox.cpp | 11 +- mythtv/programs/mythfrontend/playbackbox.h | 1 - mythtv/programs/mythfrontend/proglist.cpp | 29 +- .../programs/mythfrontend/programrecpriority.cpp | 77 +++-- mythtv/programs/mythfrontend/videofilter.cpp | 41 +-- mythtv/programs/mythfrontend/videofilter.h | 4 +- mythtv/programs/mythfrontend/videolist.cpp | 53 +--- mythtv/programs/mythpreviewgen/main.cpp | 6 +- 44 files changed, 1094 insertions(+), 427 deletions(-) create mode 100644 mythtv/libs/libmythbase/mythsorthelper.cpp create mode 100644 mythtv/libs/libmythbase/mythsorthelper.h diff --git a/mythplugins/mythnetvision/mythnetvision/netsearch.cpp b/mythplugins/mythnetvision/mythnetvision/netsearch.cpp index 5aa8ad5..e9e0014 100644
a b void NetSearch::SlotItemChanged() 509 509 MythUIButtonListItem *btn = m_siteList->GetItemCurrent(); 510 510 511 511 ResultItem res(btn->GetText(), QString(), QString(), 512 QString(), QString(), 512 513 QString(), QString(), QString(), QString(), 513 514 QDateTime(), 0, 0, -1, QString(), QStringList(), 514 515 QString(), QStringList(), 0, 0, QString(), -
mythplugins/mythnetvision/mythnetvision/nettree.cpp
diff --git a/mythplugins/mythnetvision/mythnetvision/nettree.cpp b/mythplugins/mythnetvision/mythnetvision/nettree.cpp index b140e8a..9027218 100644
a b void NetTree::UpdateResultItem(ResultItem *item) 714 714 void NetTree::UpdateSiteItem(RSSSite *site) 715 715 { 716 716 ResultItem res = 717 ResultItem(site->GetTitle(), QString(), site->GetDescription(), 717 ResultItem(site->GetTitle(), QString(), QString(), QString(), 718 site->GetDescription(), 718 719 site->GetURL(), site->GetImage(), QString(), 719 720 site->GetAuthor(), QDateTime(), 0, 0, -1, QString(), 720 721 QStringList(), QString(), QStringList(), 0, 0, QString(), … … void NetTree::UpdateCurrentItem(void) 758 759 } 759 760 760 761 ResultItem res = 761 ResultItem(title, QString(), QString(), QString(), thumb, QString(), 762 ResultItem(title, QString(), QString(), QString(), QString(), 763 QString(), thumb, QString(), 762 764 QString(), QDateTime(), 0, 0, -1, QString(), 763 765 QStringList(), QString(), QStringList(), 0, 0, QString(), 764 766 0, QStringList(), 0, 0, 0); -
mythtv/bindings/perl/MythTV.pm
diff --git a/mythtv/bindings/perl/MythTV.pm b/mythtv/bindings/perl/MythTV.pm index 80ebd8f..eca6311 100644
a b package MythTV; 107 107 # Note: as of July 21, 2010, this is actually a string, to account for proto 108 108 # versions of the form "58a". This will get used if protocol versions are 109 109 # changed on a fixes branch ongoing. 110 our $PROTO_VERSION = "9 1";111 our $PROTO_TOKEN = " BuzzOff";110 our $PROTO_VERSION = "92"; 111 our $PROTO_TOKEN = "LightSpeed"; 112 112 113 113 # currentDatabaseVersion is defined in libmythtv in 114 114 # mythtv/libs/libmythtv/dbcheck.cpp and should be the current MythTV core … … package MythTV; 120 120 # NUMPROGRAMLINES is defined in mythtv/libs/libmythtv/programinfo.h and is 121 121 # the number of items in a ProgramInfo QStringList group used by 122 122 # ProgramInfo::ToSringList and ProgramInfo::FromStringList. 123 our $NUMPROGRAMLINES = 5 2;123 our $NUMPROGRAMLINES = 54; 124 124 125 125 # Reasons a recording wouldn't be happening (from libs/libmythtv/programinfo.h) 126 126 our %RecStatus_Types = ( -
mythtv/bindings/php/MythBackend.php
diff --git a/mythtv/bindings/php/MythBackend.php b/mythtv/bindings/php/MythBackend.php index aba7bdf..4e43ebb 100644
a b class MythBackend { 11 11 12 12 // MYTH_PROTO_VERSION is defined in libmyth in mythtv/libs/libmyth/mythcontext.h 13 13 // and should be the current MythTV protocol version. 14 static $protocol_version = '9 1';15 static $protocol_token = ' BuzzOff';14 static $protocol_version = '92'; 15 static $protocol_token = 'LightSpeed'; 16 16 17 17 // The character string used by the backend to separate records 18 18 static $backend_separator = '[]:[]'; … … class MythBackend { 20 20 // NUMPROGRAMLINES is defined in mythtv/libs/libmythtv/programinfo.h and is 21 21 // the number of items in a ProgramInfo QStringList group used by 22 22 // ProgramInfo::ToSringList and ProgramInfo::FromStringList. 23 static $program_line_number = 5 2;23 static $program_line_number = 54; 24 24 25 25 private $fp = null; 26 26 private $connected = false; -
mythtv/libs/libmyth/mythrssmanager.cpp
diff --git a/mythtv/libs/libmyth/mythrssmanager.cpp b/mythtv/libs/libmyth/mythrssmanager.cpp index 05a1248..cbbe0b8 100644
a b void RSSSite::process(void) 233 233 for (ResultItem::resultList::iterator i = items.begin(); 234 234 i != items.end(); ++i) 235 235 { 236 insertRSSArticle(new ResultItem((*i)->GetTitle(), 237 QString(), (*i)->GetDescription(), (*i)->GetURL(), 236 insertRSSArticle(new ResultItem( 237 (*i)->GetTitle(), (*i)->GetSortTitle(), 238 (*i)->GetSubtitle(), (*i)->GetSortSubtitle(), 239 (*i)->GetDescription(), (*i)->GetURL(), 238 240 (*i)->GetThumbnail(), (*i)->GetMediaURL(), 239 241 (*i)->GetAuthor(), (*i)->GetDate(), 240 242 (*i)->GetTime(), (*i)->GetRating(), -
mythtv/libs/libmyth/netutils.cpp
diff --git a/mythtv/libs/libmyth/netutils.cpp b/mythtv/libs/libmyth/netutils.cpp index 7582171..5cc1b10 100644
a b bool insertTreeArticleInDB(const QString &feedtitle, const QString &path, 404 404 " title, subtitle, description, url, type, thumbnail, mediaURL, author, " 405 405 "date, time, rating, filesize, player, playerargs, download, " 406 406 "downloadargs, width, height, language, podcast, downloadable, " 407 "customhtml, countries, season, episode ) "407 "customhtml, countries, season, episode, sorttitle, sortsubtitle) " 408 408 "VALUES( :FEEDTITLE, :PATH, :PATHTHUMB, :TITLE, :SUBTITLE, :DESCRIPTION, " 409 409 ":URL, :TYPE, :THUMBNAIL, :MEDIAURL, :AUTHOR, :DATE, :TIME, :RATING, " 410 410 ":FILESIZE, :PLAYER, :PLAYERARGS, :DOWNLOAD, :DOWNLOADARGS, :WIDTH, :HEIGHT, " 411 411 ":LANGUAGE, :PODCAST, :DOWNLOADABLE, :CUSTOMHTML, :COUNTRIES, :SEASON, " 412 ":EPISODE );");412 ":EPISODE, :SORTTITLE, :SORTSUBTITLE);"); 413 413 query.bindValue(":FEEDTITLE", feedtitle); 414 414 query.bindValue(":PATH", path); 415 415 query.bindValue(":PATHTHUMB", paththumb); 416 416 query.bindValue(":TITLE", item->GetTitle()); 417 query.bindValue(":SORTTITLE", item->GetSortTitle()); 417 418 query.bindValue(":SUBTITLE", item->GetSubtitle().isNull() ? "" : item->GetSubtitle()); 419 query.bindValue(":SORTSUBTITLE", item->GetSortSubtitle().isNull() ? "" : item->GetSortSubtitle()); 418 420 query.bindValue(":DESCRIPTION", item->GetDescription()); 419 421 query.bindValue(":URL", item->GetURL()); 420 422 query.bindValue(":TYPE", type); … … QMultiMap<QPair<QString,QString>, ResultItem*> getTreeArticles(const QString &fe 468 470 "rating, filesize, player, playerargs, download, " 469 471 "downloadargs, width, height, language, " 470 472 "downloadable, customhtml, countries, season, episode, " 471 "path, paththumb FROM internetcontentarticles " 473 "path, paththumb, sorttitle, sortsubtitle " 474 "FROM internetcontentarticles " 472 475 "WHERE feedtitle = :FEEDTITLE AND podcast = 0 " 473 476 "AND type = :TYPE ORDER BY title DESC;"); 474 477 query.bindValue(":FEEDTITLE", feedtitle); … … QMultiMap<QPair<QString,QString>, ResultItem*> getTreeArticles(const QString &fe 482 485 while (query.next()) 483 486 { 484 487 QString title = query.value(0).toString(); 488 QString sortTitle = query.value(26).toString(); 485 489 QString subtitle = query.value(1).toString(); 490 QString sortSubtitle = query.value(27).toString(); 486 491 QString desc = query.value(2).toString(); 487 492 QString URL = query.value(3).toString(); 488 493 QString type = query.value(4).toString(); … … QMultiMap<QPair<QString,QString>, ResultItem*> getTreeArticles(const QString &fe 510 515 QString paththumb = query.value(25).toString(); 511 516 512 517 QPair<QString,QString> pair(path,paththumb); 513 ret.insert(pair, new ResultItem(title, subtitle, desc, URL, 518 ret.insert(pair, new ResultItem(title, sortTitle, subtitle, 519 sortSubtitle, desc, URL, 514 520 thumbnail, mediaURL, author, date, time, rating, filesize, 515 521 player, playerargs, download, downloadargs, 516 522 width, height, language, downloadable, countries, … … bool insertRSSArticleInDB(const QString &feedtitle, ResultItem *item, 741 747 "description, url, type, thumbnail, mediaURL, author, date, time, " 742 748 "rating, filesize, player, playerargs, download, " 743 749 "downloadargs, width, height, language, downloadable, countries, " 744 "podcast ) "750 "podcast, subtitle, sorttitle, sortsubtitle) " 745 751 "VALUES( :FEEDTITLE, :TITLE, :DESCRIPTION, :URL, :TYPE, :THUMBNAIL, " 746 752 ":MEDIAURL, :AUTHOR, :DATE, :TIME, :RATING, :FILESIZE, :PLAYER, " 747 753 ":PLAYERARGS, :DOWNLOAD, :DOWNLOADARGS, :WIDTH, :HEIGHT, " 748 ":LANGUAGE, :DOWNLOADABLE, :COUNTRIES, :PODCAST);"); 754 ":LANGUAGE, :DOWNLOADABLE, :COUNTRIES, :PODCAST, " 755 ":SUBTITLE, :SORTTITLE, :SORTSUBTITLE);"); 749 756 query.bindValue(":FEEDTITLE", feedtitle); 750 757 query.bindValue(":TITLE", item->GetTitle()); 758 query.bindValue(":SORTTITLE", item->GetSortTitle()); 759 query.bindValue(":SUBTITLE", item->GetSubtitle()); 760 query.bindValue(":SORTSUBTITLE", item->GetSortSubtitle()); 751 761 query.bindValue(":DESCRIPTION", item->GetDescription()); 752 762 query.bindValue(":URL", item->GetURL()); 753 763 query.bindValue(":TYPE", type); … … ResultItem::resultList getRSSArticles(const QString &feedtitle, 795 805 "thumbnail, mediaURL, author, date, time, " 796 806 "rating, filesize, player, playerargs, download, " 797 807 "downloadargs, width, height, language, " 798 "downloadable, countries, season, episode " 808 "downloadable, countries, season, episode, " 809 "sorttitle, subtitle, sortsubtitle " 799 810 "FROM internetcontentarticles " 800 811 "WHERE feedtitle = :FEEDTITLE AND podcast = 1 " 801 812 "AND type = :TYPE ORDER BY date DESC;"); … … ResultItem::resultList getRSSArticles(const QString &feedtitle, 809 820 while (query.next()) 810 821 { 811 822 QString title = query.value(0).toString(); 823 QString sortTitle = query.value(21).toString(); 824 QString subtitle = query.value(22).toString(); 825 QString sortSubtitle = query.value(23).toString(); 812 826 QString desc = query.value(1).toString(); 813 827 QString URL = query.value(2).toString(); 814 828 QString thumbnail = query.value(3).toString(); … … ResultItem::resultList getRSSArticles(const QString &feedtitle, 830 844 uint season = query.value(19).toUInt(); 831 845 uint episode = query.value(20).toUInt(); 832 846 833 ret.append(new ResultItem(title, QString(), desc, URL, thumbnail, 847 ret.append(new ResultItem(title, sortTitle, subtitle, 848 sortSubtitle, desc, URL, thumbnail, 834 849 mediaURL, author, date, time, rating, filesize, 835 850 player, playerargs, download, downloadargs, 836 851 width, height, language, downloadable, countries, -
mythtv/libs/libmyth/programinfo.cpp
diff --git a/mythtv/libs/libmyth/programinfo.cpp b/mythtv/libs/libmyth/programinfo.cpp index d1f633b..ca861fd 100644
a b using std::min; 31 31 #include "mythdb.h" 32 32 #include "compat.h" 33 33 #include "mythcdrom.h" 34 #include "mythsorthelper.h" 34 35 35 36 #include <unistd.h> // for getpid() 36 37 … … const QString ProgramInfo::kFromRecordedQuery = 80 81 " p.syndicatedepisodenumber, p.partnumber, p.parttotal, "//48-50 81 82 " p.season, p.episode, p.totalepisodes, "//51-53 82 83 " p.category_type, r.recordedid, r.inputname, "//54-56 83 " r.bookmarkupdate "//57-5784 " r.bookmarkupdate, r.sorttitle, r.sortsubtitle "//57-59 84 85 "FROM recorded AS r " 85 86 "LEFT JOIN channel AS c " 86 87 "ON (r.chanid = c.chanid) " … … ProgramInfo::CategoryType string_to_myth_category_type(const QString &category_t 159 160 */ 160 161 ProgramInfo::ProgramInfo(void) : 161 162 title(), 163 sortTitle(), 162 164 subtitle(), 165 sortSubtitle(), 163 166 description(), 164 167 season(0), 165 168 episode(0), … … ProgramInfo::ProgramInfo(void) : 232 235 availableStatus(asAvailable), 233 236 spread(-1), 234 237 startCol(-1), 235 sortTitle(),236 238 237 239 // Private 238 240 inUseForWhat(), 239 241 positionMapDBReplacement(NULL) 240 242 { 243 ensureSortFields(); 241 244 } 242 245 243 246 /** \fn ProgramInfo::ProgramInfo(const ProgramInfo &other) … … ProgramInfo::ProgramInfo(void) : 245 248 */ 246 249 ProgramInfo::ProgramInfo(const ProgramInfo &other) : 247 250 title(other.title), 251 sortTitle(other.sortTitle), 248 252 subtitle(other.subtitle), 253 sortSubtitle(other.sortSubtitle), 249 254 description(other.description), 250 255 season(other.season), 251 256 episode(other.episode), … … ProgramInfo::ProgramInfo(const ProgramInfo &other) : 316 321 availableStatus(other.availableStatus), 317 322 spread(other.spread), 318 323 startCol(other.startCol), 319 sortTitle(other.sortTitle),320 324 321 325 // Private 322 326 inUseForWhat(), 323 327 positionMapDBReplacement(other.positionMapDBReplacement) 324 328 { 329 ensureSortFields(); 325 330 } 326 331 327 332 /** \fn ProgramInfo::ProgramInfo(uint _recordedid) … … ProgramInfo::ProgramInfo(uint _recordedid) 351 356 .arg(_recordedid)); 352 357 clear(); 353 358 } 359 360 ensureSortFields(); 354 361 } 355 362 356 363 /** \fn ProgramInfo::ProgramInfo(uint _chanid, const QDateTime &_recstartts) … … ProgramInfo::ProgramInfo(uint _chanid, const QDateTime &_recstartts) : 362 369 clear(); 363 370 364 371 LoadProgramFromRecorded(_chanid, _recstartts); 372 ensureSortFields(); 365 373 } 366 374 367 375 /** \fn ProgramInfo::ProgramInfo() … … ProgramInfo::ProgramInfo(uint _chanid, const QDateTime &_recstartts) : 370 378 ProgramInfo::ProgramInfo( 371 379 uint _recordedid, 372 380 const QString &_title, 381 const QString &_sortTitle, 373 382 const QString &_subtitle, 383 const QString &_sortSubtitle, 374 384 const QString &_description, 375 385 uint _season, 376 386 uint _episode, … … ProgramInfo::ProgramInfo( 430 440 const QString &_inputname, 431 441 const QDateTime &_bookmarkupdate) : 432 442 title(_title), 443 sortTitle(_sortTitle), 433 444 subtitle(_subtitle), 445 sortSubtitle(_sortSubtitle), 434 446 description(_description), 435 447 season(_season), 436 448 episode(_episode), … … ProgramInfo::ProgramInfo( 504 516 availableStatus(asAvailable), 505 517 spread(-1), 506 518 startCol(-1), 507 sortTitle(),508 519 509 520 // Private 510 521 inUseForWhat(), … … ProgramInfo::ProgramInfo( 514 525 originalAirDate = QDate(); 515 526 516 527 SetPathname(_pathname); 528 ensureSortFields(); 517 529 } 518 530 519 531 /** \fn ProgramInfo::ProgramInfo() … … ProgramInfo::ProgramInfo( 521 533 */ 522 534 ProgramInfo::ProgramInfo( 523 535 const QString &_title, 536 const QString &_sortTitle, 524 537 const QString &_subtitle, 538 const QString &_sortSubtitle, 525 539 const QString &_description, 526 540 uint _season, 527 541 uint _episode, … … ProgramInfo::ProgramInfo( 551 565 552 566 bool duplicate) : 553 567 title(_title), 568 sortTitle(_sortTitle), 554 569 subtitle(_subtitle), 570 sortSubtitle(_sortSubtitle), 555 571 description(_description), 556 572 season(_season), 557 573 episode(_episode), … … ProgramInfo::ProgramInfo( 622 638 availableStatus(asAvailable), 623 639 spread(-1), 624 640 startCol(-1), 625 sortTitle(),626 641 627 642 // Private 628 643 inUseForWhat(), 629 644 positionMapDBReplacement(NULL) 630 645 { 646 ensureSortFields(); 631 647 } 632 648 633 649 /** \fn ProgramInfo::ProgramInfo() … … ProgramInfo::ProgramInfo( 635 651 */ 636 652 ProgramInfo::ProgramInfo( 637 653 const QString &_title, 654 const QString &_sortTitle, 638 655 const QString &_subtitle, 656 const QString &_sortSubtitle, 639 657 const QString &_description, 640 658 const QString &_syndicatedepisode, 641 659 const QString &_category, … … ProgramInfo::ProgramInfo( 679 697 680 698 const ProgramList &schedList) : 681 699 title(_title), 700 sortTitle(_sortTitle), 682 701 subtitle(_subtitle), 702 sortSubtitle(_sortSubtitle), 683 703 description(_description), 684 704 season(_season), 685 705 episode(_episode), … … ProgramInfo::ProgramInfo( 753 773 availableStatus(asAvailable), 754 774 spread(-1), 755 775 startCol(-1), 756 sortTitle(),757 776 758 777 // Private 759 778 inUseForWhat(), … … ProgramInfo::ProgramInfo( 805 824 s.recstatus == RecStatus::Failing) 806 825 recstatus = s.recstatus; 807 826 } 827 ensureSortFields(); 808 828 } 809 829 810 830 /** \fn ProgramInfo::ProgramInfo() … … ProgramInfo::ProgramInfo( 812 832 */ 813 833 ProgramInfo::ProgramInfo( 814 834 const QString &_title, 835 const QString &_sortTitle, 815 836 const QString &_subtitle, 837 const QString &_sortSubtitle, 816 838 const QString &_description, 817 839 uint _season, 818 840 uint _episode, … … ProgramInfo::ProgramInfo( 837 859 const QString &_programid, 838 860 const QString &_inetref) : 839 861 title(_title), 862 sortTitle(_sortTitle), 840 863 subtitle(_subtitle), 864 sortSubtitle(_sortSubtitle), 841 865 description(_description), 842 866 season(_season), 843 867 episode(_episode), … … ProgramInfo::ProgramInfo( 908 932 availableStatus(asAvailable), 909 933 spread(-1), 910 934 startCol(-1), 911 sortTitle(),912 935 913 936 // Private 914 937 inUseForWhat(), 915 938 positionMapDBReplacement(NULL) 916 939 { 940 ensureSortFields(); 917 941 } 918 942 919 943 /** \fn ProgramInfo::ProgramInfo(const QString &_pathname) … … ProgramInfo::ProgramInfo(const QString &_pathname) : 950 974 SetPathname(QFileInfo(_pathname).absoluteFilePath()); 951 975 else 952 976 SetPathname(_pathname); 977 ensureSortFields(); 953 978 } 954 979 955 980 /** \fn ProgramInfo::ProgramInfo() … … ProgramInfo::ProgramInfo(const QString &_pathname) : 958 983 ProgramInfo::ProgramInfo(const QString &_pathname, 959 984 const QString &_plot, 960 985 const QString &_title, 986 const QString &_sortTitle, 961 987 const QString &_subtitle, 988 const QString &_sortSubtitle, 962 989 const QString &_director, 963 990 int _season, int _episode, 964 991 const QString &_inetref, … … ProgramInfo::ProgramInfo(const QString &_pathname, 970 997 clear(); 971 998 972 999 title = _title; 1000 sortTitle = _sortTitle; 973 1001 subtitle = _subtitle; 1002 sortSubtitle = _sortSubtitle; 974 1003 description = _plot; 975 1004 season = _season; 976 1005 episode = _episode; … … ProgramInfo::ProgramInfo(const QString &_pathname, 990 1019 pn = determineURLType(_pathname); 991 1020 992 1021 SetPathname(pn); 1022 ensureSortFields(); 993 1023 } 994 1024 995 1025 /** \fn ProgramInfo::ProgramInfo() … … ProgramInfo::ProgramInfo(const QString &_title, uint _chanid, 1034 1064 1035 1065 description = title = 1036 1066 QString("%1 (%2)").arg(title).arg(QObject::tr("Manual Record")); 1067 ensureSortFields(); 1037 1068 } 1038 1069 1039 1070 /** \fn ProgramInfo::ProgramInfo() … … ProgramInfo::ProgramInfo( 1049 1080 category = _category; 1050 1081 startts = _startts; 1051 1082 endts = _endts; 1083 ensureSortFields(); 1052 1084 } 1053 1085 1054 1086 … … void ProgramInfo::clone(const ProgramInfo &other, 1071 1103 startts == other.startts); 1072 1104 1073 1105 title = other.title; 1106 sortTitle = other.sortTitle; 1074 1107 subtitle = other.subtitle; 1108 sortSubtitle = other.sortSubtitle; 1075 1109 description = other.description; 1076 1110 season = other.season; 1077 1111 episode = other.episode; … … void ProgramInfo::clone(const ProgramInfo &other, 1148 1182 { 1149 1183 spread = other.spread; 1150 1184 startCol = other.startCol; 1151 sortTitle = other.sortTitle;1152 1185 availableStatus = other.availableStatus; 1153 1186 1154 1187 inUseForWhat = other.inUseForWhat; … … void ProgramInfo::clone(const ProgramInfo &other, 1156 1189 } 1157 1190 1158 1191 title.detach(); 1192 sortTitle.detach(); 1159 1193 subtitle.detach(); 1194 sortSubtitle.detach(); 1160 1195 description.detach(); 1161 1196 category.detach(); 1162 1197 … … void ProgramInfo::clone(const ProgramInfo &other, 1176 1211 programid.detach(); 1177 1212 inetref.detach(); 1178 1213 1179 sortTitle.detach();1180 1214 inUseForWhat.detach(); 1181 1215 inputname.detach(); 1182 1216 } … … void ProgramInfo::clone(const ProgramInfo &other, 1184 1218 void ProgramInfo::clear(void) 1185 1219 { 1186 1220 title.clear(); 1221 sortTitle.clear(); 1187 1222 subtitle.clear(); 1223 sortSubtitle.clear(); 1188 1224 description.clear(); 1189 1225 season = 0; 1190 1226 episode = 0; … … void ProgramInfo::clear(void) 1216 1252 inetref.clear(); 1217 1253 catType = kCategoryNone; 1218 1254 1219 sortTitle.clear();1220 1221 1255 recpriority = 0; 1222 1256 1223 1257 filesize = 0ULL; … … void ProgramInfo::clear(void) 1266 1300 positionMapDBReplacement = NULL; 1267 1301 } 1268 1302 1303 /** \fn ProgramInfo::ensureSortFields 1304 * \brief Ensure that the sortTitle and sortSubtitle fields are set. 1305 */ 1306 void ProgramInfo::ensureSortFields(void) 1307 { 1308 SortHelper *sh = new SortHelper; 1309 1310 if (sortTitle.isEmpty() and !title.isEmpty()) 1311 sortTitle = sh->doTitle(title); 1312 if (sortSubtitle.isEmpty() and !subtitle.isEmpty()) 1313 sortSubtitle = sh->doTitle(subtitle); 1314 } 1315 1269 1316 /** \fn ProgramInfo::~ProgramInfo() 1270 1317 * \brief Destructor deletes "record" if it exists. 1271 1318 */ … … ProgramInfo::~ProgramInfo() 1273 1320 { 1274 1321 } 1275 1322 1323 void ProgramInfo::SetTitle(const QString &t, const QString &st) 1324 { 1325 title = t; 1326 title.detach(); 1327 sortTitle = st; 1328 sortTitle.detach(); 1329 } 1330 1331 void ProgramInfo::SetTitle(const QString &t) 1332 { 1333 SortHelper *sh = new SortHelper; 1334 SetTitle(t, sh->doTitle(t)); 1335 } 1336 1337 void ProgramInfo::SetSubtitle(const QString &st, const QString &sst) 1338 { 1339 subtitle = st; 1340 subtitle.detach(); 1341 sortSubtitle = sst; 1342 sortSubtitle.detach(); 1343 } 1344 1345 void ProgramInfo::SetSubtitle(const QString &st) 1346 { 1347 SortHelper *sh = new SortHelper; 1348 SetSubtitle(st, sh->doTitle(st)); 1349 } 1350 1276 1351 /// \brief Creates a unique string that can be used to identify a recording. 1277 1352 QString ProgramInfo::MakeUniqueKey( 1278 1353 uint chanid, const QDateTime &recstartts) … … void ProgramInfo::ToStringList(QStringList &list) const 1437 1512 INT_TO_LIST(recordedid); // 49 1438 1513 STR_TO_LIST(inputname); // 50 1439 1514 DATETIME_TO_LIST(bookmarkupdate); // 51 1515 1516 STR_TO_LIST(sortTitle); // 52 1517 STR_TO_LIST(sortSubtitle); // 53 1440 1518 /* do not forget to update the NUMPROGRAMLINES defines! */ 1441 1519 } 1442 1520 … … bool ProgramInfo::FromStringList(QStringList::const_iterator &it, 1549 1627 STR_FROM_LIST(inputname); // 50 1550 1628 DATETIME_FROM_LIST(bookmarkupdate); // 51 1551 1629 1630 STR_FROM_LIST(sortTitle); // 52 1631 STR_FROM_LIST(sortSubtitle); // 53 1632 1552 1633 if (!origChanid || !origRecstartts.isValid() || 1553 1634 (origChanid != chanid) || (origRecstartts != recstartts)) 1554 1635 { 1555 1636 availableStatus = asAvailable; 1556 1637 spread = -1; 1557 1638 startCol = -1; 1558 sortTitle = QString();1559 1639 inUseForWhat = QString(); 1560 1640 positionMapDBReplacement = NULL; 1561 1641 } 1562 1642 1643 ensureSortFields(); 1644 1563 1645 return true; 1564 1646 } 1565 1647 … … void ProgramInfo::ToMap(InfoMap &progMap, 1584 1666 1585 1667 progMap["title"] = title; 1586 1668 progMap["subtitle"] = subtitle; 1669 progMap["sorttitle"] = sortTitle; 1670 progMap["sortsubtitle"] = sortSubtitle; 1587 1671 1588 1672 QString tempSubTitle = title; 1673 QString tempSortSubtitle = sortTitle; 1589 1674 if (!subtitle.trimmed().isEmpty()) 1590 1675 { 1591 1676 tempSubTitle = QString("%1 - \"%2\"") 1592 1677 .arg(tempSubTitle).arg(subtitle); 1678 tempSortSubtitle = QString("%1 - \"%2\"") 1679 .arg(tempSortSubtitle).arg(sortSubtitle); 1593 1680 } 1594 1681 1595 1682 progMap["titlesubtitle"] = tempSubTitle; 1683 progMap["sorttitlesubtitle"] = tempSortSubtitle; 1596 1684 1597 1685 progMap["description"] = description; 1598 1686 … … bool ProgramInfo::LoadProgramFromRecorded( 2020 2108 2021 2109 // everything below this line (in context) is not serialized 2022 2110 spread = startCol = -1; 2023 sortTitle.clear();2024 2111 availableStatus = asAvailable; 2025 2112 inUseForWhat.clear(); 2026 2113 positionMapDBReplacement = NULL; 2027 2114 } 2028 2115 2029 2116 title = query.value(0).toString(); 2117 sortTitle = query.value(58).toString(); 2030 2118 subtitle = query.value(1).toString(); 2119 sortSubtitle = query.value(59).toString(); 2031 2120 description = query.value(2).toString(); 2032 2121 season = query.value(3).toUInt(); 2033 2122 if (season == 0) … … bool ProgramInfo::LoadProgramFromRecorded( 2151 2240 // Extra stuff which is not serialized and may get lost. 2152 2241 /**/// spread 2153 2242 /**/// startCol 2154 /**/// sortTitle2155 2243 /**/// availableStatus 2156 2244 /**/// inUseForWhat 2157 2245 /**/// postitionMapDBReplacement … … void ProgramInfo::SubstituteMatches(QString &str) 5348 5436 5349 5437 str.replace(QString("%FILE%"), GetBasename()); 5350 5438 str.replace(QString("%TITLE%"), title); 5439 str.replace(QString("%SORTTITLE%"), sortTitle); 5351 5440 str.replace(QString("%SUBTITLE%"), subtitle); 5441 str.replace(QString("%SORTSUBTITLE%"), sortSubtitle); 5352 5442 str.replace(QString("%SEASON%"), QString::number(season)); 5353 5443 str.replace(QString("%EPISODE%"), QString::number(episode)); 5354 5444 str.replace(QString("%TOTALEPISODES%"), QString::number(totalepisodes)); … … static bool FromProgramQuery(const QString &sql, const MSqlBindings &bindings, 5503 5593 "oldrecstatus.findid, program.videoprop+0, program.audioprop+0, " 5504 5594 "program.subtitletypes+0, program.syndicatedepisodenumber, " 5505 5595 "program.partnumber, program.parttotal, " 5506 "program.season, program.episode, program.totalepisodes "); 5596 "program.season, program.episode, program.totalepisodes, " 5597 "program.sorttitle, program.sortsubtitle "); 5507 5598 5508 5599 QString querystr = QString( 5509 5600 "SELECT %1 " … … bool LoadFromProgram( ProgramList &destination, 5681 5772 destination.push_back( 5682 5773 new ProgramInfo( 5683 5774 query.value(3).toString(), // title 5775 query.value(32).toString(), // sortTitle 5684 5776 query.value(4).toString(), // subtitle 5777 query.value(33).toString(), // sortSubtitle 5685 5778 query.value(5).toString(), // description 5686 5779 query.value(26).toString(), // syndicatedepisodenumber 5687 5780 query.value(6).toString(), // category … … bool LoadFromOldRecorded( 5774 5867 " title, subtitle, description, season, episode, category, seriesid, " 5775 5868 " programid, inetref, channel.channum, channel.callsign, " 5776 5869 " channel.name, findid, rectype, recstatus, recordid, " 5777 " duplicate "5870 " duplicate, sorttitle, sortsubtitle " 5778 5871 " FROM oldrecorded " 5779 5872 " LEFT JOIN channel ON oldrecorded.chanid = channel.chanid " 5780 5873 " WHERE oldrecorded.future = 0 " … … bool LoadFromOldRecorded( 5809 5902 5810 5903 destination.push_back(new ProgramInfo( 5811 5904 query.value(3).toString(), 5905 query.value(20).toString(), 5812 5906 query.value(4).toString(), 5907 query.value(21).toString(), 5813 5908 query.value(5).toString(), 5814 5909 query.value(6).toUInt(), 5815 5910 query.value(7).toUInt(), … … bool LoadFromRecorded( 5965 6060 new ProgramInfo( 5966 6061 query.value(55).toUInt(), 5967 6062 query.value(0).toString(), 6063 query.value(58).toString(), 5968 6064 query.value(1).toString(), 6065 query.value(59).toString(), 5969 6066 query.value(2).toString(), 5970 6067 season, 5971 6068 episode, -
mythtv/libs/libmyth/programinfo.h
diff --git a/mythtv/libs/libmyth/programinfo.h b/mythtv/libs/libmyth/programinfo.h index 63eac7a..279e24d 100644
a b 24 24 in mythversion.h need to be bumped, and also follow the instructions in 25 25 myth_version.h about other changes needed when the network protocol changes. 26 26 */ 27 #define NUMPROGRAMLINES 5 227 #define NUMPROGRAMLINES 54 28 28 29 29 class ProgramInfo; 30 30 typedef AutoDeleteDeque<ProgramInfo*> ProgramList; … … class MPUBLIC ProgramInfo 81 81 /// Constructs a ProgramInfo from data in 'recorded' table 82 82 ProgramInfo(uint recordedid, 83 83 const QString &title, 84 const QString &sortTitle, 84 85 const QString &subtitle, 86 const QString &sortSubtitle, 85 87 const QString &description, 86 88 uint season, 87 89 uint episode, … … class MPUBLIC ProgramInfo 144 146 145 147 /// Constructs a ProgramInfo from data in 'oldrecorded' table 146 148 ProgramInfo(const QString &title, 149 const QString &sortTitle, 147 150 const QString &subtitle, 151 const QString &sortSubtitle, 148 152 const QString &description, 149 153 uint season, 150 154 uint episode, … … class MPUBLIC ProgramInfo 176 180 177 181 /// Constructs a ProgramInfo from listings data in 'program' table 178 182 ProgramInfo(const QString &title, 183 const QString &sortTitle, 179 184 const QString &subtitle, 185 const QString &sortSubtitle, 180 186 const QString &description, 181 187 const QString &syndicatedepisode, 182 188 const QString &category, … … class MPUBLIC ProgramInfo 220 226 const ProgramList &schedList); 221 227 /// Constructs a basic ProgramInfo (used by RecordingInfo) 222 228 ProgramInfo(const QString &title, 229 const QString &sortTitle, 223 230 const QString &subtitle, 231 const QString &sortSubtitle, 224 232 const QString &description, 225 233 uint season, 226 234 uint episode, … … class MPUBLIC ProgramInfo 250 258 ProgramInfo(const QString &pathname, 251 259 const QString &plot, 252 260 const QString &title, 261 const QString &sortTitle, 253 262 const QString &subtitle, 263 const QString &sortSubtitle, 254 264 const QString &director, 255 265 int season, int episode, 256 266 const QString &inetref, … … class MPUBLIC ProgramInfo 283 293 ProgramInfo &operator=(const ProgramInfo &other); 284 294 virtual void clone(const ProgramInfo &other, 285 295 bool ignore_non_serialized_data = false); 296 virtual void ensureSortFields(void); 286 297 287 298 virtual void clear(void); 288 299 … … class MPUBLIC ProgramInfo 340 351 bool IsFileReadable(void) const; 341 352 342 353 QString GetTitle(void) const { return title; } 354 QString GetSortTitle(void) const { return sortTitle; } 343 355 QString GetSubtitle(void) const { return subtitle; } 356 QString GetSortSubtitle(void) const { return sortSubtitle; } 344 357 QString GetDescription(void) const { return description; } 345 358 uint GetSeason(void) const { return season; } 346 359 uint GetEpisode(void) const { return episode; } … … class MPUBLIC ProgramInfo 482 495 QString grp = "\"") const; 483 496 484 497 // Quick sets 485 void SetTitle(const QString &t) { title = t; title.detach(); } 498 void SetTitle(const QString &t, const QString &st); 499 void SetTitle(const QString &t); 500 void SetSubtitle(const QString &st, const QString &sst); 501 void SetSubtitle(const QString &st); 486 502 void SetProgramInfoType(ProgramInfoType t) 487 503 { programflags &= ~FL_TYPEMASK; programflags |= ((uint32_t)t<<20); } 488 504 void SetPathname(const QString&) const; … … class MPUBLIC ProgramInfo 715 731 716 732 protected: 717 733 QString title; 734 QString sortTitle; 718 735 QString subtitle; 736 QString sortSubtitle; 719 737 QString description; 720 738 uint season; 721 739 uint episode; … … class MPUBLIC ProgramInfo 790 808 { return (AvailableStatusType) availableStatus; } 791 809 int8_t spread; // only used in guidegrid.cpp 792 810 int8_t startCol; // only used in guidegrid.cpp 793 QString sortTitle; // only use for sorting in frontend794 811 795 812 static const QString kFromRecordedQuery; 796 813 -
mythtv/libs/libmyth/rssparse.cpp
diff --git a/mythtv/libs/libmyth/rssparse.cpp b/mythtv/libs/libmyth/rssparse.cpp index 1db242a..4b16a61 100644
a b 13 13 #include "mythdirs.h" 14 14 #include "mythdate.h" 15 15 #include "programinfo.h" // for format_season_and_episode() 16 #include "mythsorthelper.h" 16 17 17 18 using namespace std; 18 19 19 ResultItem::ResultItem(const QString& title, const QString& subtitle, 20 ResultItem::ResultItem(const QString& title, const QString& sortTitle, 21 const QString& subtitle, const QString& sortSubtitle, 20 22 const QString& desc, const QString& URL, 21 23 const QString& thumbnail, const QString& mediaURL, 22 24 const QString& author, const QDateTime& date, … … ResultItem::ResultItem(const QString& title, const QString& subtitle, 29 31 const uint& season, const uint& episode, 30 32 const bool& customhtml) 31 33 { 34 SortHelper *sh = new SortHelper; 35 32 36 m_title = title; 37 m_sorttitle = sortTitle.isEmpty() ? sh->doTitle(title) : sortTitle; 33 38 m_subtitle = subtitle; 39 m_sortsubtitle = 40 sortSubtitle.isEmpty() ? sh->doTitle(subtitle) : sortSubtitle; 34 41 m_desc = desc; 35 42 m_URL = URL; 36 43 m_thumbnail = thumbnail; … … ResultItem::~ResultItem() 70 77 void ResultItem::toMap(InfoMap &metadataMap) 71 78 { 72 79 metadataMap["title"] = m_title; 80 metadataMap["sorttitle"] = m_sorttitle; 73 81 metadataMap["subtitle"] = m_subtitle; 82 metadataMap["sortsubtitle"] = m_sortsubtitle; 74 83 metadataMap["description"] = m_desc; 75 84 metadataMap["url"] = m_URL; 76 85 metadataMap["thumbnail"] = m_thumbnail; … … ResultItem* Parse::ParseItem(const QDomElement& item) const 929 938 if (mediaURL.isNull() || mediaURL == url) 930 939 downloadable = false; 931 940 932 return(new ResultItem(title, subtitle, description,941 return(new ResultItem(title, QString(), subtitle, QString(), description, 933 942 url, thumbnail, mediaURL, author, date, duration, 934 943 rating, filesize, player, playerargs, 935 944 download, downloadargs, width, height, -
mythtv/libs/libmyth/rssparse.h
diff --git a/mythtv/libs/libmyth/rssparse.h b/mythtv/libs/libmyth/rssparse.h index 0a35dcf..0065b68 100644
a b class MPUBLIC ResultItem 114 114 typedef QList<ResultItem *> resultList; 115 115 typedef std::vector<ResultItem> List; 116 116 117 ResultItem(const QString& title, const QString& subtitle, 117 ResultItem(const QString& title, const QString& sortTitle, 118 const QString& subtitle, const QString& sortSubtitle, 118 119 const QString& desc, const QString& URL, 119 120 const QString& thumbnail, const QString& mediaURL, 120 121 const QString& author, const QDateTime& date, const QString& time, … … class MPUBLIC ResultItem 130 131 void toMap(InfoMap &infoMap); 131 132 132 133 const QString& GetTitle() const { return m_title; } 134 const QString& GetSortTitle() const { return m_sorttitle; } 133 135 const QString& GetSubtitle() const { return m_subtitle; } 136 const QString& GetSortSubtitle() const { return m_sortsubtitle; } 134 137 const QString& GetDescription() const { return m_desc; } 135 138 const QString& GetURL() const { return m_URL; } 136 139 const QString& GetThumbnail() const { return m_thumbnail; } … … class MPUBLIC ResultItem 155 158 156 159 private: 157 160 QString m_title; 161 QString m_sorttitle; 158 162 QString m_subtitle; 163 QString m_sortsubtitle; 159 164 QString m_desc; 160 165 QString m_URL; 161 166 QString m_thumbnail; -
mythtv/libs/libmyth/test/test_programinfo/test_programinfo.h
diff --git a/mythtv/libs/libmyth/test/test_programinfo/test_programinfo.h b/mythtv/libs/libmyth/test/test_programinfo/test_programinfo.h index 0298e99..85a798b 100644
a b class TestProgramInfo : public QObject 37 37 { 38 38 return ProgramInfo ( 39 39 title, /* title */ 40 "", /* sortTitle */ 40 41 "", /* subtitle */ 42 "", /* sortSubtitle */ 41 43 "Its a movie.", /* description */ 42 44 "", /* syndicated episode */ 43 45 "", /* category */ … … class TestProgramInfo : public QObject 83 85 ProgramInfo program ( 84 86 "/pathname", 85 87 "The plot", 86 "The Title", 87 "The Subtitle", 88 "The Title", "title, the", 89 "The Subtitle", "subtitle, the", 88 90 "Director", 89 91 1, 90 92 2, … … class TestProgramInfo : public QObject 142 144 ProgramInfo programH (mockMovie ("", "", "Gone", 2012)); 143 145 QVERIFY (programG.IsSameProgram (programH)); 144 146 } 147 148 void programSorting_test(void) 149 { 150 ProgramInfo flash34 151 (715, 152 "The Flash (2014)", QString(), 153 "The New Rogues", QString(), 154 "Barry continues to train Jesse ...", 155 3, 4, 23, "syndicatedepisode", "Drama", 156 1514, "514", "WNUVDT", "WNUBDT (WNUV-DT)", "", 157 QString("Default"), QString("Default"), 158 "/recordings/1514_20161025235800.ts", 159 "localhost", "Default", 160 "EP01922936", "EP019229360055", "ttvdb.py_279121", 161 ProgramInfo::kCategoryTVShow, 0, 6056109800, 162 MythDate::fromString("2016-10-25 23:58:00"), 163 MythDate::fromString("2016-10-26 01:02:00"), 164 MythDate::fromString("2016-10-25 23:58:00"), 165 MythDate::fromString("2016-10-26 01:02:00"), 166 0.0, 2016, 0, 0, QDate(2016,10,25), 167 QDateTime(QDate(2016,10,26),QTime(1,12,34)), 168 RecStatus::Unknown, 0, 169 kDupsInAll, kDupCheckSubThenDesc, 170 0, 0, 0, 0, 0, "Prime A-1", 171 QDateTime(QDate(0,0,0),QTime(0,0,0))); 172 ProgramInfo supergirl23 173 ("Supergirl", QString(), 174 "Welcome to Earth", QString(), 175 "An attack is made on the President as hot-button...", 176 2, 3, 23, "Drama", 177 1514, "514", "WNUVDT", "WNUBDT (WNUV-DT)", "", 178 QString("Default"), QString("Default"), 179 MythDate::fromString("2016-10-24 23:58:00"), 180 MythDate::fromString("2016-10-25 01:02:00"), 181 MythDate::fromString("2016-10-24 23:58:00"), 182 MythDate::fromString("2016-10-25 01:02:00"), 183 "295759", "5772362", ""); 184 185 QCOMPARE (flash34.GetSortTitle(), QString("flash (2014)")); 186 QCOMPARE (flash34.GetSortSubtitle(), QString("new rogues")); 187 QVERIFY (flash34.GetSortTitle() < supergirl23.GetSortTitle()); 188 QString foo = "%TITLE%|%SORTTITLE%|%SUBTITLE%|%SORTSUBTITLE%"; 189 // Fake out GetPlaybackURL() so it doesn't attempt a database query 190 flash34.SetProgramInfoType(kProgramInfoTypeVideoBD); 191 flash34.SubstituteMatches(foo); 192 QCOMPARE(foo, QString("The Flash (2014)|flash (2014)|The New Rogues|new rogues")); 193 } 145 194 }; -
mythtv/libs/libmythbase/libmythbase.pro
diff --git a/mythtv/libs/libmythbase/libmythbase.pro b/mythtv/libs/libmythbase/libmythbase.pro index aa7ac15..efe32ea 100644
a b HEADERS += threadedfilewriter.h mythsingledownload.h codecutil.h 34 34 HEADERS += mythsession.h 35 35 HEADERS += ../../external/qjsonwrapper/qjsonwrapper/Json.h 36 36 HEADERS += cleanupguard.h portchecker.h 37 HEADERS += mythsorthelper.h 37 38 38 39 SOURCES += mthread.cpp mthreadpool.cpp 39 40 SOURCES += mythsocket.cpp … … SOURCES += threadedfilewriter.cpp mythsingledownload.cpp codecutil.cpp 55 56 SOURCES += mythsession.cpp 56 57 SOURCES += ../../external/qjsonwrapper/qjsonwrapper/Json.cpp 57 58 SOURCES += cleanupguard.cpp portchecker.cpp 59 SOURCES += mythsorthelper.cpp 58 60 59 61 unix { 60 62 SOURCES += mythsystemunix.cpp … … inc.files += plist.h bswap.h signalhandling.h ffmpeg-mmx.h mythdate.h 84 86 inc.files += mythplugin.h mythpluginapi.h mythqtcompat.h 85 87 inc.files += remotefile.h mythsystemlegacy.h mythtypes.h 86 88 inc.files += threadedfilewriter.h mythsingledownload.h mythsession.h 89 inc.files += mythsorthelper.h 87 90 88 91 # Allow both #include <blah.h> and #include <libmythbase/blah.h> 89 92 inc2.path = $${PREFIX}/include/mythtv/libmythbase -
new file mythtv/libs/libmythbase/mythsorthelper.cpp
diff --git a/mythtv/libs/libmythbase/mythsorthelper.cpp b/mythtv/libs/libmythbase/mythsorthelper.cpp new file mode 100644 index 0000000..4a81a9a
- + 1 // -*- Mode: c++ -*- 2 // vim: set expandtab tabstop=4 shiftwidth=4 3 4 #include "mythsorthelper.h" 5 #include "mythcorecontext.h" 6 7 /** \fn SortHelper::SortHelper 8 * \brief Create the object and read settings from the core context. 9 * 10 * Create the object and read settings from the core context. Set of 11 * the various regular expressions and exclusion lists for later 12 * usage. 13 * 14 * Handling the case where the gCoreContext object doesn't exists 15 * (i.e. running under the Qt test harness) allows this code and 16 * objects using it to be tested. 17 */ 18 SortHelper::SortHelper() 19 { 20 QString excludes; 21 QString prefixes(tr("^(The |A |An )", 22 "Regular Expression for what to ignore when sorting")); 23 if (gCoreContext) { 24 // Running code 25 m_ignore_case = gCoreContext->GetNumSetting("SortIgnoreCase", true); 26 m_ignore_prefixes = gCoreContext->GetNumSetting("SortIgnorePrefixes", true); 27 excludes = gCoreContext->GetSetting("SortIgnorePrefixExceptions", ""); 28 } else { 29 // Qt Test Harness 30 m_ignore_case = true; 31 m_ignore_prefixes = true; 32 excludes = "A to Z"; 33 } 34 if (m_ignore_case) 35 { 36 prefixes = prefixes.toLower(); 37 excludes = excludes.toLower(); 38 } 39 m_ign_regex1 = QRegExp(prefixes); 40 m_ign_regex2 = QRegExp(prefixes.replace("^","/")); 41 m_excl_list = excludes.split(";", QString::SkipEmptyParts); 42 for (int i = 0; i < m_excl_list.size(); i++) 43 m_excl_list[i] = m_excl_list[i].trimmed(); 44 m_creator = "unknown"; 45 } 46 47 48 /** \fn SortHelper::doTitle(QString) 49 * \brief Create the sortable form of an title string. 50 * 51 * This function converts a title string to a version that can be 52 * used for sorting. Depending upon user settings, it may ignore the 53 * case of the string (by forcing all strings to lower case) and may 54 * strip the common prefix words "A", "An" and "The" from the 55 * beginning of the string. 56 * 57 * \param title The title of an item. 58 * \return The conversion of the title to use when sorting. 59 */ 60 QString SortHelper::doTitle(QString title) const 61 { 62 if (m_ignore_case) 63 title = title.toLower(); 64 if (not m_ignore_prefixes) 65 return title; 66 if (m_excl_list.contains(title)) 67 return title; 68 return title.remove(m_ign_regex1); 69 } 70 71 /** \fn SortHelper::doPathname(QString) 72 * \brief Create the sortable form of an item. 73 * 74 * This function converts a pathname to a version that can be used 75 * for sorting. Depending upon user settings, it may ignore the case 76 * of the string (by forcing all strings to lower case) and may strip 77 * the common prefix words "A", "An" and "The" from the beginning of 78 * each component in the pathname. 79 * 80 * \param title The pathname of an item. 81 * \return The conversion of the pathname to use when sorting. 82 */ 83 QString SortHelper::doPathname(QString pathname) const 84 { 85 if (m_ignore_case) 86 pathname = pathname.toLower(); 87 if (not m_ignore_prefixes) 88 return pathname; 89 if (m_excl_list.contains(pathname)) 90 return pathname; 91 return pathname.remove(m_ign_regex1).replace(m_ign_regex2, "/"); 92 } -
new file mythtv/libs/libmythbase/mythsorthelper.h
diff --git a/mythtv/libs/libmythbase/mythsorthelper.h b/mythtv/libs/libmythbase/mythsorthelper.h new file mode 100644 index 0000000..496b043
- + 1 // -*- Mode: c++ -*- 2 // vim: set expandtab tabstop=4 shiftwidth=4 3 4 #ifndef MYTHSORTHELPER_H_ 5 #define MYTHSORTHELPER_H_ 6 7 #include <QCoreApplication> 8 #include "mythbaseexp.h" 9 10 class MBASE_PUBLIC SortHelper 11 { 12 Q_DECLARE_TR_FUNCTIONS(SortHelper) 13 14 public: 15 SortHelper(); 16 QString doTitle(QString title) const; 17 QString doPathname(QString filename) const; 18 19 private: 20 bool m_ignore_case; 21 22 bool m_ignore_prefixes; 23 QRegExp m_ign_regex1; // Anchored at the start 24 QRegExp m_ign_regex2; // Following a '/' 25 26 QStringList m_excl_list; 27 QString m_creator; 28 }; 29 30 #endif // MYTHSORTHELPER_H_ -
mythtv/libs/libmythbase/mythversion.h
diff --git a/mythtv/libs/libmythbase/mythversion.h b/mythtv/libs/libmythbase/mythversion.h index 9f0efb7..6a1753d 100644
a b 44 44 * http://www.mythtv.org/wiki/Category:Myth_Protocol_Commands 45 45 * http://www.mythtv.org/wiki/Category:Myth_Protocol 46 46 */ 47 #define MYTH_PROTO_VERSION "9 1"48 #define MYTH_PROTO_TOKEN " BuzzOff"47 #define MYTH_PROTO_VERSION "92" 48 #define MYTH_PROTO_TOKEN "LightSpeed" 49 49 50 50 /** \brief Increment this whenever the MythTV core database schema changes. 51 51 * … … 64 64 * mythtv/bindings/php/MythBackend.php 65 65 */ 66 66 67 #define MYTH_DATABASE_VERSION "134 6"67 #define MYTH_DATABASE_VERSION "1347" 68 68 69 69 70 70 MBASE_PUBLIC const char *GetMythSourceVersion(); -
mythtv/libs/libmythmetadata/test/test_videometadata/test_videometadata.h
diff --git a/mythtv/libs/libmythmetadata/test/test_videometadata/test_videometadata.h b/mythtv/libs/libmythmetadata/test/test_videometadata/test_videometadata.h index 8f4f493..ce36d9e 100644
a b class Testvideometadata: public QObject 345 345 void ProgramWithInetref () 346 346 { 347 347 MSKIP ("Might connect to the database or call the installed metadata grabbers."); 348 ProgramInfo proginfo = ProgramInfo ("", "", "Test Movie", "", "", 0, 0, "tmdb3.py_1234", 0, 0, ""); 348 ProgramInfo proginfo = ProgramInfo ("", "", "Test Movie", "", "", "", 349 "", 0, 0, "tmdb3.py_1234", 0, 0, ""); 349 350 RecordingInfo recinfo = proginfo; 350 351 QCOMPARE (recinfo.GetInetRef(), QString("tmdb3.py_1234")); 351 352 QCOMPARE (GuessLookupType (&recinfo), kProbableMovie); 352 353 353 proginfo = ProgramInfo ("", "", "Test Series", "Test Episode", "", 1, 15, "ttvdb.py_1234", 0, 0, ""); 354 proginfo = ProgramInfo ("", "", "Test Series", "", "Test Episode", "", 355 "", 1, 15, "ttvdb.py_1234", 0, 0, ""); 354 356 recinfo = proginfo; 355 357 QCOMPARE (recinfo.GetInetRef(), QString("ttvdb.py_1234")); 356 358 QCOMPARE (GuessLookupType (&recinfo), kProbableTelevision); … … class Testvideometadata: public QObject 358 360 //QCOMPARE (GuessLookupType (QString ("tmdb3.py_1234")), kProbableMovie); 359 361 //QCOMPARE (GuessLookupType (QString ("ttvdb.py_1234")), kProbableTelevision); 360 362 } 363 364 void testEmbeddedFilnameToMetadata () 365 { 366 MSKIP ("Tries to connect to the database."); 367 VideoMetadata obj = VideoMetadata(QString ("Series Title/Season 1/02x03 Episode Title.mp4")); 368 QCOMPARE (obj.GetTitle(), QString ("Series Title")); 369 QCOMPARE (obj.GetSortTitle(), QString ("series title")); 370 QCOMPARE (obj.GetSubtitle(), QString ("Episode Title")); 371 QCOMPARE (obj.GetSortSubtitle(), QString ("episode title")); 372 QCOMPARE (obj.GetSeason(), 2); 373 QCOMPARE (obj.GetEpisode(), 3); 374 375 obj = VideoMetadata(QString ("The Series Title/Season 1/02x03 The Episode Title.mp4")); 376 QCOMPARE (obj.GetTitle(), QString ("The Series Title")); 377 QCOMPARE (obj.GetSortTitle(), QString ("series title")); 378 QCOMPARE (obj.GetSubtitle(), QString ("The Episode Title")); 379 QCOMPARE (obj.GetSortSubtitle(), QString ("episode title")); 380 QCOMPARE (obj.GetSeason(), 2); 381 QCOMPARE (obj.GetEpisode(), 3); 382 } 361 383 }; -
mythtv/libs/libmythmetadata/videometadata.cpp
diff --git a/mythtv/libs/libmythmetadata/videometadata.cpp b/mythtv/libs/libmythmetadata/videometadata.cpp index 8f4c2b4..dbf41fe 100644
a b 19 19 #include "videometadatalistmanager.h" 20 20 #include "videoutils.h" 21 21 #include "programinfo.h" // for format_season_and_episode 22 #include "mythsorthelper.h" 22 23 23 24 using namespace std; 24 25 25 struct SortData26 {27 SortData(const QString &title, const QString &filename, const QString &id) :28 m_title(title), m_filename(filename), m_id(id)29 {30 }31 32 QString m_title;33 QString m_filename;34 QString m_id;35 };36 37 static bool operator<(const SortData &lhs, const SortData &rhs)38 {39 int ret = naturalCompare(lhs.m_title, rhs.m_title);40 41 if (ret == 0)42 ret = naturalCompare(lhs.m_filename, rhs.m_filename);43 44 if (ret == 0)45 ret = naturalCompare(lhs.m_id, rhs.m_id);46 47 return ret < 0;48 }49 50 VideoMetadata::SortKey::SortKey() : m_sd(NULL)51 {52 }53 54 VideoMetadata::SortKey::SortKey(const SortData &data)55 {56 m_sd = new SortData(data);57 }58 59 VideoMetadata::SortKey::SortKey(const SortKey &other) : m_sd(NULL)60 {61 *this = other;62 }63 64 VideoMetadata::SortKey &VideoMetadata::SortKey::operator=(const SortKey &rhs)65 {66 if (this != &rhs)67 {68 Clear();69 if (rhs.m_sd)70 m_sd = new SortData(*rhs.m_sd);71 }72 73 return *this;74 }75 76 VideoMetadata::SortKey::~SortKey()77 {78 Clear();79 }80 81 bool VideoMetadata::SortKey::isSet() const82 {83 return m_sd != 0;84 }85 86 void VideoMetadata::SortKey::Clear()87 {88 delete m_sd;89 m_sd = 0;90 }91 92 26 class VideoMetadataImp 93 27 { 94 28 public: … … class VideoMetadataImp 97 31 typedef VideoMetadata::cast_list cast_list; 98 32 99 33 public: 100 VideoMetadataImp(const QString &filename, const QString &hash, const QString &trailer, 34 VideoMetadataImp(const QString &filename, const QString &sortFilename, 35 const QString &hash, const QString &trailer, 101 36 const QString &coverfile, const QString &screenshot, const QString &banner, 102 const QString &fanart, const QString &title, const QString &subtitle, 37 const QString &fanart, const QString &title, const QString &sortTitle, 38 const QString &subtitle, const QString &sortSubtitle, 103 39 const QString &tagline, int year, const QDate &releasedate, 104 40 const QString &inetref, int collectionref, const QString &homepage, 105 41 const QString &director, const QString &studio, … … class VideoMetadataImp 115 51 const QString &host = "", 116 52 bool processed = false, 117 53 VideoContentType contenttype = kContentUnknown) : 118 m_title(title), m_subtitle(subtitle), m_tagline(tagline), 54 m_title(title), m_sortTitle(sortTitle), m_subtitle(subtitle), 55 m_sortSubtitle(sortSubtitle), m_tagline(tagline), 119 56 m_inetref(inetref), m_collectionref(collectionref), m_homepage(homepage), 120 57 m_director(director), m_studio(studio), 121 58 m_plot(plot), m_rating(rating), m_playcommand(playcommand), m_category(category), 122 59 m_genres(genres), m_countries(countries), m_cast(cast), 123 m_filename(filename), m_hash(hash), m_trailer(trailer), m_coverfile(coverfile), 60 m_filename(filename), m_sortFilename(sortFilename), m_hash(hash), 61 m_trailer(trailer), m_coverfile(coverfile), 124 62 m_screenshot(screenshot), m_banner(banner), m_fanart(fanart), 125 63 m_host(host), m_categoryID(categoryID), m_childID(childID), 126 64 m_year(year), m_releasedate(releasedate), m_length(length), m_playcount(playcount), … … class VideoMetadataImp 129 67 m_userrating(userrating), m_processed(processed), 130 68 m_contenttype(contenttype) 131 69 { 70 // Try to glean data if none provided. 71 if (title.isEmpty() and subtitle.isEmpty() 72 and season == 0 and episode == 0) 73 { 74 m_title = VideoMetadata::FilenameToMeta(m_filename, 1); 75 m_subtitle = VideoMetadata::FilenameToMeta(m_filename, 4); 76 m_season = VideoMetadata::FilenameToMeta(m_filename, 2).toInt(); 77 m_episode = VideoMetadata::FilenameToMeta(m_filename, 3).toInt(); 78 } 79 80 SortHelper *sh = new SortHelper; 81 if (m_sortFilename.isEmpty()) 82 m_sortFilename = sh->doPathname(m_filename); 83 if (m_sortTitle.isEmpty()) 84 m_sortTitle = sh->doTitle(m_title); 85 if (m_sortSubtitle.isEmpty()) 86 m_sortSubtitle = sh->doTitle(m_subtitle); 87 132 88 VideoCategory::GetCategory().get(m_categoryID, m_category); 133 89 } 134 90 … … class VideoMetadataImp 147 103 if (this != &rhs) 148 104 { 149 105 m_title = rhs.m_title; 106 m_sortTitle = rhs.m_sortTitle; 150 107 m_subtitle = rhs.m_subtitle; 108 m_sortSubtitle = rhs.m_sortSubtitle; 151 109 m_tagline = rhs.m_tagline; 152 110 m_inetref = rhs.m_inetref; 153 111 m_collectionref = rhs.m_collectionref; … … class VideoMetadataImp 162 120 m_countries = rhs.m_countries; 163 121 m_cast = rhs.m_cast; 164 122 m_filename = rhs.m_filename; 123 m_sortFilename = rhs.m_sortFilename; 165 124 m_hash = rhs.m_hash; 166 125 m_trailer = rhs.m_trailer; 167 126 m_coverfile = rhs.m_coverfile; … … class VideoMetadataImp 188 147 m_contenttype = rhs.m_contenttype; 189 148 190 149 // No DB vars 191 m_sort_key = rhs.m_sort_key;192 150 m_prefix = rhs.m_prefix; 193 151 } 194 152 … … class VideoMetadataImp 196 154 } 197 155 198 156 public: 199 bool HasSortKey() const { return m_sort_key.isSet(); }200 const VideoMetadata::SortKey &GetSortKey() const { return m_sort_key; }201 void SetSortKey(const VideoMetadata::SortKey &sort_key)202 {203 m_sort_key = sort_key;204 }205 206 157 const QString &GetPrefix() const { return m_prefix; } 207 158 void SetPrefix(const QString &prefix) { m_prefix = prefix; } 208 159 209 160 const QString &getTitle() const { return m_title; } 210 void SetTitle(const QString& title) 161 const QString &getSortTitle() const { return m_sortTitle; } 162 void SetTitle(const QString& title, const QString& sortTitle) 211 163 { 212 if (gCoreContext->HasGUI())213 m_sort_key.Clear();214 164 m_title = title; 165 m_sortTitle = sortTitle; 166 } 167 void SetTitle(const QString& title) 168 { 169 SortHelper *sh = new SortHelper; 170 SetTitle(title, sh->doTitle(title)); 215 171 } 216 172 217 173 const QString &getSubtitle() const { return m_subtitle; } 218 void SetSubtitle(const QString &subtitle) { m_subtitle = subtitle; } 174 const QString &getSortSubtitle() const { return m_sortSubtitle; } 175 void SetSubtitle(const QString &subtitle, const QString &sortSubtitle) { 176 m_subtitle = subtitle; 177 m_sortSubtitle = sortSubtitle; 178 } 179 void SetSubtitle(const QString &subtitle) { 180 SortHelper *sh = new SortHelper; 181 SetSubtitle(subtitle, sh->doTitle(subtitle)); 182 } 219 183 220 184 const QString &GetTagline() const { return m_tagline; } 221 185 void SetTagline(const QString &tagline) { m_tagline = tagline; } … … class VideoMetadataImp 266 230 void SetHost(const QString &host) { m_host = host; } 267 231 268 232 const QString &getFilename() const { return m_filename; } 269 void SetFilename(const QString &filename) { m_filename = filename; } 233 const QString &getSortFilename() const { return m_sortFilename; } 234 void SetFilename(const QString &filename, const QString &sortFilename); 235 void SetFilename(const QString &filename); 236 bool sortBefore(const VideoMetadataImp *rhs) const; 270 237 271 238 const QString &GetHash() const { return m_hash; } 272 239 void SetHash(const QString &hash) { m_hash = hash; } … … class VideoMetadataImp 367 334 368 335 private: 369 336 QString m_title; 337 QString m_sortTitle; 370 338 QString m_subtitle; 339 QString m_sortSubtitle; 371 340 QString m_tagline; 372 341 QString m_inetref; 373 342 int m_collectionref; … … class VideoMetadataImp 382 351 country_list m_countries; 383 352 cast_list m_cast; 384 353 QString m_filename; 354 QString m_sortFilename; 385 355 QString m_hash; 386 356 QString m_trailer; 387 357 QString m_coverfile; … … class VideoMetadataImp 408 378 VideoContentType m_contenttype; 409 379 410 380 // not in DB 411 VideoMetadata::SortKey m_sort_key;412 381 QString m_prefix; 413 382 }; 414 383 415 384 ///////////////////////////// 416 385 ///////// 417 386 ///////////////////////////// 387 void VideoMetadataImp::SetFilename(const QString &filename, const QString &sortFilename) { 388 m_filename = filename; 389 m_sortFilename = sortFilename; 390 } 391 392 void VideoMetadataImp::SetFilename(const QString &filename) { 393 SortHelper *sh = new SortHelper; 394 SetFilename(filename, sh->doPathname(filename)); 395 } 396 397 /** \fn VideoMetadataImp::sortBefore(const VideoMetadataImp *) 398 * \brief Returns true if the object should appear before the argument. 399 */ 400 bool VideoMetadataImp::sortBefore(const VideoMetadataImp *rhs) const 401 { 402 int ret = naturalCompare(m_sortTitle, rhs->m_sortTitle); 403 if (ret != 0) 404 return (ret == -1); 405 ret = naturalCompare(m_sortFilename, rhs->m_sortFilename); 406 if (ret != 0) 407 return (ret == -1); 408 return (m_id < rhs->m_id); 409 } 410 418 411 bool VideoMetadataImp::removeDir(const QString &dirName) 419 412 { 420 413 QDir d(dirName); … … bool VideoMetadataImp::DeleteFile() 477 470 478 471 void VideoMetadataImp::Reset() 479 472 { 480 VideoMetadataImp tmp(m_filename, VideoMetadata::VideoFileHash(m_filename, m_host), VIDEO_TRAILER_DEFAULT, 473 VideoMetadataImp tmp(m_filename, QString(), 474 VideoMetadata::VideoFileHash(m_filename, m_host), VIDEO_TRAILER_DEFAULT, 481 475 VIDEO_COVERFILE_DEFAULT, VIDEO_SCREENSHOT_DEFAULT, VIDEO_BANNER_DEFAULT, 482 VIDEO_FANART_DEFAULT, VideoMetadata::FilenameToMeta(m_filename, 1), QString(),483 VideoMetadata::FilenameToMeta(m_filename, 4), VIDEO_YEAR_DEFAULT,476 VIDEO_FANART_DEFAULT, QString(), QString(), QString(), QString(), 477 QString(), VIDEO_YEAR_DEFAULT, 484 478 QDate(), VIDEO_INETREF_DEFAULT, -1, QString(), VIDEO_DIRECTOR_DEFAULT, 485 479 QString(), VIDEO_PLOT_DEFAULT, 0.0, 486 480 VIDEO_RATING_DEFAULT, 0, 0, 487 VideoMetadata::FilenameToMeta(m_filename, 2).toInt(), 488 VideoMetadata::FilenameToMeta(m_filename, 3).toInt(), QDate(), m_id, 481 0, 0, QDate(), m_id, 489 482 ParentalLevel::plLowest, 0, -1, true, false, "", "", 490 483 VideoMetadata::genre_list(), VideoMetadata::country_list(), 491 484 VideoMetadata::cast_list(), m_host, false); … … void VideoMetadataImp::fillCast() 557 550 } 558 551 559 552 /// Sets metadata from a DB row 553 /// 554 /// Query in VideoMetadataListManager::loadAllFromDatabase 555 /// 560 556 void VideoMetadataImp::fromDBRow(MSqlQuery &query) 561 557 { 562 558 m_title = query.value(0).toString(); … … void VideoMetadataImp::fromDBRow(MSqlQuery &query) 600 596 601 597 m_contenttype = ContentTypeFromString(query.value(34).toString()); 602 598 599 m_sortTitle = query.value(35).toString(); 600 m_sortSubtitle = query.value(36).toString(); 601 m_sortFilename = query.value(37).toString(); 602 603 603 VideoCategory::GetCategory().get(m_categoryID, m_category); 604 604 605 605 // Genres … … void VideoMetadataImp::fromDBRow(MSqlQuery &query) 614 614 615 615 void VideoMetadataImp::saveToDatabase() 616 616 { 617 SortHelper *sh = new SortHelper; 618 617 619 if (m_title.isEmpty()) 620 { 618 621 m_title = VideoMetadata::FilenameToMeta(m_filename, 1); 622 m_sortTitle = sh->doTitle(m_title); 623 } 619 624 if (m_hash.isEmpty()) 620 625 m_hash = VideoMetadata::VideoFileHash(m_filename, m_host); 621 626 if (m_subtitle.isEmpty()) 627 { 622 628 m_subtitle = VideoMetadata::FilenameToMeta(m_filename, 4); 629 m_sortSubtitle = sh->doTitle(m_subtitle); 630 } 623 631 if (m_director.isEmpty()) 624 632 m_director = VIDEO_DIRECTOR_UNKNOWN; 625 633 if (m_plot.isEmpty()) … … void VideoMetadataImp::saveToDatabase() 670 678 671 679 m_watched = 0; 672 680 673 query.prepare("INSERT INTO videometadata (title,subtitle,tagline,director,studio,plot," 674 "rating,year,userrating,length,season,episode,filename,hash," 681 query.prepare("INSERT INTO videometadata (title,sorttitle,subtitle,sortsubtitle," 682 "tagline,director,studio,plot,rating,year,userrating,length," 683 "season,episode,filename,sortfilename,hash," 675 684 "showlevel,coverfile,inetref,homepage,browse,watched,trailer," 676 "screenshot,banner,fanart,host,processed,contenttype) VALUES (:TITLE, :SUBTITLE, " 685 "screenshot,banner,fanart,host,processed,contenttype) " 686 "VALUES (:TITLE, :TITLESORT, :SUBTITLE, :SUBTITLESORT, " 677 687 ":TAGLINE, :DIRECTOR, :STUDIO, :PLOT, :RATING, :YEAR, :USERRATING, " 678 ":LENGTH, :SEASON, :EPISODE, :FILENAME, : HASH, :SHOWLEVEL, "688 ":LENGTH, :SEASON, :EPISODE, :FILENAME, :SORTFILENAME, :HASH, :SHOWLEVEL, " 679 689 ":COVERFILE, :INETREF, :HOMEPAGE, :BROWSE, :WATCHED, " 680 690 ":TRAILER, :SCREENSHOT, :BANNER, :FANART, :HOST, :PROCESSED, :CONTENTTYPE)"); 681 691 } 682 692 else 683 693 { 684 query.prepare("UPDATE videometadata SET title = :TITLE, subtitle = :SUBTITLE, " 694 query.prepare("UPDATE videometadata SET title = :TITLE, sorttitle = :SORTTITLE, " 695 "subtitle = :SUBTITLE, sortsubtitle = :SORTSUBTITLE, " 685 696 "tagline = :TAGLINE, director = :DIRECTOR, studio = :STUDIO, " 686 697 "plot = :PLOT, rating= :RATING, year = :YEAR, " 687 698 "releasedate = :RELEASEDATE, userrating = :USERRATING, " 688 699 "length = :LENGTH, playcount = :PLAYCOUNT, season = :SEASON, " 689 "episode = :EPISODE, filename = :FILENAME, hash = :HASH, trailer = :TRAILER, " 700 "episode = :EPISODE, filename = :FILENAME, sortfilename = :SORTFILENAME, " 701 "hash = :HASH, trailer = :TRAILER, " 690 702 "showlevel = :SHOWLEVEL, coverfile = :COVERFILE, " 691 703 "screenshot = :SCREENSHOT, banner = :BANNER, fanart = :FANART, " 692 704 "inetref = :INETREF, collectionref = :COLLECTION, homepage = :HOMEPAGE, " … … void VideoMetadataImp::saveToDatabase() 701 713 } 702 714 703 715 query.bindValue(":TITLE", m_title.isNull() ? "" : m_title); 716 query.bindValue(":SORTTITLE", m_sortTitle.isNull() ? "" : m_sortTitle); 704 717 query.bindValue(":SUBTITLE", m_subtitle.isNull() ? "" : m_subtitle); 718 query.bindValue(":SORTSUBTITLE", m_sortSubtitle.isNull() ? "" : m_sortSubtitle); 705 719 query.bindValue(":TAGLINE", m_tagline); 706 720 query.bindValue(":DIRECTOR", m_director.isNull() ? "" : m_director); 707 721 query.bindValue(":STUDIO", m_studio); … … void VideoMetadataImp::saveToDatabase() 715 729 query.bindValue(":SEASON", m_season); 716 730 query.bindValue(":EPISODE", m_episode); 717 731 query.bindValue(":FILENAME", m_filename); 732 query.bindValue(":SORTFILENAME", m_sortFilename); 718 733 query.bindValue(":HASH", m_hash); 719 734 query.bindValue(":TRAILER", m_trailer.isNull() ? "" : m_trailer); 720 735 query.bindValue(":SHOWLEVEL", m_showlevel); … … void VideoMetadataImp::GetImageMap(InfoMap &imageMap) const 960 975 //////////////////////////////////////// 961 976 //// Metadata 962 977 //////////////////////////////////////// 963 VideoMetadata::SortKey VideoMetadata::GenerateDefaultSortKey(const VideoMetadata &m,964 bool ignore_case)965 {966 QString title(ignore_case ? m.GetTitle().toLower() : m.GetTitle());967 title = TrimTitle(title, ignore_case);968 969 return SortKey(SortData(title, m.GetFilename(),970 QString().sprintf("%.7d", m.GetID())));971 }972 973 978 namespace 974 979 { 975 980 QString eatBraces(const QString &title, const QString &left_brace, … … int VideoMetadata::UpdateHashedDBRecord(const QString &hash, 1022 1027 const QString &host) 1023 1028 { 1024 1029 MSqlQuery query(MSqlQuery::InitCon()); 1030 SortHelper *sh = new SortHelper; 1025 1031 1026 1032 query.prepare("SELECT intid,filename FROM videometadata WHERE " 1027 1033 "hash = :HASH"); … … int VideoMetadata::UpdateHashedDBRecord(const QString &hash, 1040 1046 QString oldfilename = query.value(1).toString(); 1041 1047 1042 1048 query.prepare("UPDATE videometadata SET filename = :FILENAME, " 1043 "host = :HOST WHERE intid = :INTID"); 1049 "sortfilename = :SORTFILENAME, host = :HOST " 1050 "WHERE intid = :INTID"); 1044 1051 query.bindValue(":FILENAME", file_name); 1052 query.bindValue(":SORTFILENAME", sh->doPathname(file_name)); 1045 1053 query.bindValue(":HOST", host); 1046 1054 query.bindValue(":INTID", intid); 1047 1055 … … QString VideoMetadata::FilenameToMeta(const QString &file_name, int position) 1172 1180 return QString(); 1173 1181 } 1174 1182 1175 namespace 1176 { 1177 const QRegExp &getTitleTrim(bool ignore_case) 1178 { 1179 static QString pattern(VideoMetadata::tr("^(The |A |An )")); 1180 static QRegExp prefixes_case(pattern, Qt::CaseSensitive); 1181 static QRegExp prefixes_nocase(pattern, Qt::CaseInsensitive); 1182 return ignore_case ? prefixes_nocase : prefixes_case; 1183 } 1184 } 1185 1186 QString VideoMetadata::TrimTitle(const QString &title, bool ignore_case) 1187 { 1188 QString ret(title); 1189 ret.remove(getTitleTrim(ignore_case)); 1190 return ret; 1191 } 1192 1193 VideoMetadata::VideoMetadata(const QString &filename, const QString &hash, 1194 const QString &trailer, const QString &coverfile, 1183 VideoMetadata::VideoMetadata(const QString &filename, const QString &sortFilename, 1184 const QString &hash, const QString &trailer, const QString &coverfile, 1195 1185 const QString &screenshot, const QString &banner, const QString &fanart, 1196 const QString &title, const QString &subtitle, const QString &tagline, 1186 const QString &title, const QString &sortTitle, 1187 const QString &subtitle, const QString &sortSubtitle, const QString &tagline, 1197 1188 int year, const QDate &releasedate, const QString &inetref, int collectionref, 1198 1189 const QString &homepage, const QString &director, const QString &studio, 1199 1190 const QString &plot, float userrating, const QString &rating, … … VideoMetadata::VideoMetadata(const QString &filename, const QString &hash, 1207 1198 const QString &host, bool processed, 1208 1199 VideoContentType contenttype) 1209 1200 { 1210 m_imp = new VideoMetadataImp(filename, hash, trailer, coverfile, screenshot, banner, 1211 fanart, title, subtitle, tagline, year, releasedate, inetref, 1201 m_imp = new VideoMetadataImp(filename, sortFilename, hash, trailer, coverfile, 1202 screenshot, banner, fanart, title, sortTitle, subtitle, 1203 sortSubtitle, tagline, year, releasedate, inetref, 1212 1204 collectionref, homepage, director, studio, plot, userrating, rating, 1213 1205 length, playcount, season, episode, insertdate, id, showlevel, categoryID, 1214 1206 childID, browse, watched, playcommand, category, genres, countries, … … void VideoMetadata::toMap(InfoMap &metadataMap) 1248 1240 GetImageMap(metadataMap); 1249 1241 1250 1242 metadataMap["filename"] = GetFilename(); 1243 metadataMap["sortfilename"] = GetSortFilename(); 1251 1244 metadataMap["title"] = GetTitle(); 1245 metadataMap["sorttitle"] = GetSortTitle(); 1252 1246 metadataMap["subtitle"] = GetSubtitle(); 1247 metadataMap["sortsubtitle"] = GetSortSubtitle(); 1253 1248 metadataMap["tagline"] = GetTagline(); 1254 1249 metadataMap["director"] = GetDirector(); 1255 1250 metadataMap["studio"] = GetStudio(); … … void ClearMap(InfoMap &metadataMap) 1320 1315 metadataMap["bannerfile"] = ""; 1321 1316 metadataMap["fanartfile"] = ""; 1322 1317 metadataMap["filename"] = ""; 1318 metadataMap["sortfilename"] = ""; 1323 1319 metadataMap["title"] = ""; 1320 metadataMap["sorttitle"] = ""; 1324 1321 metadataMap["subtitle"] = ""; 1322 metadataMap["sortsubtitle"] = ""; 1325 1323 metadataMap["tagline"] = ""; 1326 1324 metadataMap["director"] = ""; 1327 1325 metadataMap["studio"] = ""; … … void ClearMap(InfoMap &metadataMap) 1353 1351 metadataMap["processed"] = ""; 1354 1352 } 1355 1353 1356 bool VideoMetadata::HasSortKey() const1357 {1358 return m_imp->HasSortKey();1359 }1360 1361 const VideoMetadata::SortKey &VideoMetadata::GetSortKey() const1362 {1363 return m_imp->GetSortKey();1364 }1365 1366 void VideoMetadata::SetSortKey(const VideoMetadata::SortKey &sort_key)1367 {1368 m_imp->SetSortKey(sort_key);1369 }1370 1371 1354 const QString &VideoMetadata::GetPrefix() const 1372 1355 { 1373 1356 return m_imp->GetPrefix(); … … const QString &VideoMetadata::GetTitle() const 1383 1366 return m_imp->getTitle(); 1384 1367 } 1385 1368 1369 const QString &VideoMetadata::GetSortTitle() const 1370 { 1371 return m_imp->getSortTitle(); 1372 } 1373 1374 void VideoMetadata::SetTitle(const QString &title, const QString &sortTitle) 1375 { 1376 m_imp->SetTitle(title, sortTitle); 1377 } 1378 1386 1379 void VideoMetadata::SetTitle(const QString &title) 1387 1380 { 1388 1381 m_imp->SetTitle(title); … … const QString &VideoMetadata::GetSubtitle() const 1393 1386 return m_imp->getSubtitle(); 1394 1387 } 1395 1388 1389 const QString &VideoMetadata::GetSortSubtitle() const 1390 { 1391 return m_imp->getSortSubtitle(); 1392 } 1393 1394 void VideoMetadata::SetSubtitle(const QString &subtitle, const QString &sortSubtitle) 1395 { 1396 m_imp->SetSubtitle(subtitle, sortSubtitle); 1397 } 1398 1396 1399 void VideoMetadata::SetSubtitle(const QString &subtitle) 1397 1400 { 1398 1401 m_imp->SetSubtitle(subtitle); … … const QString &VideoMetadata::GetFilename() const 1643 1646 return m_imp->getFilename(); 1644 1647 } 1645 1648 1649 const QString &VideoMetadata::GetSortFilename() const 1650 { 1651 return m_imp->getSortFilename(); 1652 } 1653 1646 1654 const QString &VideoMetadata::GetHash() const 1647 1655 { 1648 1656 return m_imp->GetHash(); … … void VideoMetadata::SetHost(const QString &host) 1663 1671 m_imp->SetHost(host); 1664 1672 } 1665 1673 1674 void VideoMetadata::SetFilename(const QString &filename, const QString &sortFilename) 1675 { 1676 m_imp->SetFilename(filename, sortFilename); 1677 } 1678 1666 1679 void VideoMetadata::SetFilename(const QString &filename) 1667 1680 { 1668 1681 m_imp->SetFilename(filename); … … bool VideoMetadata::IsHostSet() const 1831 1844 return m_imp->IsHostSet(); 1832 1845 } 1833 1846 1847 bool VideoMetadata::sortBefore(const VideoMetadata &rhs) const 1848 { 1849 return m_imp->sortBefore(rhs.m_imp); 1850 } 1851 1834 1852 bool operator==(const VideoMetadata& a, const VideoMetadata& b) 1835 1853 { 1836 1854 if (a.GetFilename() == b.GetFilename()) … … bool operator!=(const VideoMetadata& a, const VideoMetadata& b) 1844 1862 return true; 1845 1863 return false; 1846 1864 } 1847 1848 bool operator<(const VideoMetadata::SortKey &lhs, const VideoMetadata::SortKey &rhs)1849 {1850 if (lhs.m_sd && rhs.m_sd)1851 return *lhs.m_sd < *rhs.m_sd;1852 else1853 {1854 LOG(VB_GENERAL, LOG_ERR,1855 "Error: Bug, Metadata item with empty sort key compared");1856 return lhs.m_sd < rhs.m_sd;1857 }1858 } -
mythtv/libs/libmythmetadata/videometadata.h
diff --git a/mythtv/libs/libmythmetadata/videometadata.h b/mythtv/libs/libmythmetadata/videometadata.h index a02587c..5fb8289 100644
a b enum { VIDEO_YEAR_DEFAULT = 1895 }; 19 19 20 20 const QString VIDEO_SUBTITLE_DEFAULT = ""; 21 21 22 struct SortData;23 24 22 typedef QHash<QString,QString> MetadataMap; 25 23 26 24 class META_PUBLIC VideoMetadata … … class META_PUBLIC VideoMetadata 36 34 typedef std::vector<cast_entry> cast_list; 37 35 38 36 public: 39 class META_PUBLIC SortKey40 {41 public:42 SortKey();43 explicit SortKey(const SortData &data);44 SortKey(const SortKey &other);45 SortKey &operator=(const SortKey &rhs);46 ~SortKey();47 48 bool isSet() const;49 void Clear();50 51 public:52 SortData *m_sd;53 };54 55 public:56 static SortKey GenerateDefaultSortKey(const VideoMetadata &m, bool ignore_case);57 37 static int UpdateHashedDBRecord(const QString &hash, const QString &file_name, 58 38 const QString &host); 59 39 static QString VideoFileHash(const QString &file_name, const QString &host); … … class META_PUBLIC VideoMetadata 62 42 63 43 public: 64 44 VideoMetadata(const QString &filename = QString(), 45 const QString &sortFilename = QString(), 65 46 const QString &hash = QString(), 66 47 const QString &trailer = QString(), 67 48 const QString &coverfile = QString(), … … class META_PUBLIC VideoMetadata 69 50 const QString &banner = QString(), 70 51 const QString &fanart = QString(), 71 52 const QString &title = QString(), 53 const QString &sortTitle = QString(), 72 54 const QString &subtitle = QString(), 55 const QString &sortSubtitle = QString(), 73 56 const QString &tagline = QString(), 74 57 int year = VIDEO_YEAR_DEFAULT, 75 58 const QDate &releasedate = QDate(), … … class META_PUBLIC VideoMetadata 104 87 explicit VideoMetadata(MSqlQuery &query); 105 88 VideoMetadata(const VideoMetadata &rhs); 106 89 VideoMetadata &operator=(const VideoMetadata &rhs); 90 bool sortBefore(const VideoMetadata &rhs) const; 107 91 108 92 void toMap(InfoMap &metadataMap); 109 93 void GetStateMap(InfoMap &stateMap); 110 94 void GetImageMap(InfoMap &imageMap); 111 95 112 // returns a string to use when sorting113 bool HasSortKey() const;114 const SortKey &GetSortKey() const;115 void SetSortKey(const SortKey &sort_key);116 117 96 const QString &GetPrefix() const; 118 97 void SetPrefix(const QString &prefix); 119 98 120 99 const QString &GetTitle() const; 100 const QString &GetSortTitle() const; 101 void SetTitle(const QString& title, const QString& sortTitle); 121 102 void SetTitle(const QString& title); 122 103 123 104 const QString &GetSubtitle() const; 105 const QString &GetSortSubtitle() const; 106 void SetSubtitle(const QString &subtitle, const QString &sortSubtitle); 124 107 void SetSubtitle(const QString &subtitle); 125 108 126 109 const QString &GetTagline() const; … … class META_PUBLIC VideoMetadata 199 182 void SetHost(const QString &host); 200 183 201 184 const QString &GetFilename() const; 185 const QString &GetSortFilename() const; 186 void SetFilename(const QString &filename, const QString &sortFilename); 202 187 void SetFilename(const QString &filename); 203 188 204 189 const QString &GetHash() const; … … META_PUBLIC void ClearMap(InfoMap &metadataMap); 258 243 META_PUBLIC bool operator==(const VideoMetadata &a, const VideoMetadata &b); 259 244 META_PUBLIC bool operator!=(const VideoMetadata &a, const VideoMetadata &b); 260 245 261 META_PUBLIC bool operator<(const VideoMetadata::SortKey &lhs, const VideoMetadata::SortKey &rhs);262 263 246 Q_DECLARE_METATYPE(VideoMetadata*) 264 247 265 248 #endif -
mythtv/libs/libmythmetadata/videometadatalistmanager.cpp
diff --git a/mythtv/libs/libmythmetadata/videometadatalistmanager.cpp b/mythtv/libs/libmythmetadata/videometadatalistmanager.cpp index e83198a..854ddb1 100644
a b 2 2 3 3 #include "mythdb.h" 4 4 #include "videometadatalistmanager.h" 5 #include "mythsorthelper.h" 5 6 6 7 class VideoMetadataListManagerImp 7 8 { … … VideoMetadataListManager::loadOneFromDatabase(uint id) 120 121 return VideoMetadataPtr(new VideoMetadata()); 121 122 } 122 123 124 /// Load videometadata database into memory 125 /// 126 /// Query consumed in VideoMetadataImp::fromDBRow 127 /// 123 128 void VideoMetadataListManager::loadAllFromDatabase(metadata_list &items, 124 129 const QString &sql) 125 130 { 126 131 MSqlQuery query(MSqlQuery::InitCon()); 127 132 query.setForwardOnly(true); 128 133 QString BaseMetadataQuery( 129 "SELECT title, director, studio, plot, rating, year, releasedate," 130 "userrating, length, playcount, filename, hash, showlevel, " 131 "coverfile, inetref, collectionref, homepage, childid, browse, watched, " 132 "playcommand, category, intid, trailer, screenshot, banner, fanart, " 133 "subtitle, tagline, season, episode, host, insertdate, processed, " 134 "contenttype FROM videometadata "); 134 "SELECT title, director, studio, plot, rating, year, releasedate," // 0-6 135 "userrating, length, playcount, filename, hash, showlevel, " // 7-12 136 "coverfile, inetref, collectionref, homepage, childid, browse, watched, " // 13-19 137 "playcommand, category, intid, trailer, screenshot, banner, fanart, " // 20-26 138 "subtitle, tagline, season, episode, host, insertdate, processed, " // 27-33 139 "contenttype, sorttitle, sortsubtitle, sortfilename " // 34-37 140 "FROM videometadata "); 135 141 136 142 if (!sql.isEmpty()) 137 143 BaseMetadataQuery.append(sql); … … meta_dir_node::meta_dir_node(const QString &path, const QString &name, 249 255 : meta_node(parent, is_path_root), m_path(path), m_name(name), 250 256 m_host(host), m_prefix(prefix), m_data(data) 251 257 { 258 SortHelper *sh = new SortHelper; 259 m_sortPath = sh->doPathname(m_path); 260 252 261 if (!name.length()) 253 262 m_name = path; 254 263 } … … const QString &meta_dir_node::getPath() const 288 297 return m_path; 289 298 } 290 299 291 void meta_dir_node::setPath(const QString &path) 300 const QString &meta_dir_node::getSortPath() const 301 { 302 return m_sortPath; 303 } 304 305 void meta_dir_node::setPath(const QString &path, const QString &sortPath) 292 306 { 293 307 m_path = path; 308 m_sortPath = sortPath; 309 } 310 311 void meta_dir_node::setPath(const QString &path) 312 { 313 SortHelper *sh = new SortHelper; 314 setPath(path, sh->doPathname(path)); 294 315 } 295 316 296 317 void meta_dir_node::SetData(const QVariant &data) -
mythtv/libs/libmythmetadata/videometadatalistmanager.h
diff --git a/mythtv/libs/libmythmetadata/videometadatalistmanager.h b/mythtv/libs/libmythmetadata/videometadatalistmanager.h index 002f88c..cfc4e1c 100644
a b class META_PUBLIC meta_dir_node : public meta_node 102 102 void SetPrefix(const QString &prefix); 103 103 const QString &GetPrefix() const; 104 104 const QString &getPath() const; 105 const QString &getSortPath() const; 106 void setPath(const QString &path, const QString &sortPath); 105 107 void setPath(const QString &path); 106 108 void SetData(const QVariant &data); 107 109 const QVariant &GetData() const; … … class META_PUBLIC meta_dir_node : public meta_node 146 148 147 149 private: 148 150 QString m_path; 151 QString m_sortPath; 149 152 QString m_name; 150 153 QString m_host; 151 154 QString m_prefix; -
mythtv/libs/libmythmetadata/videoscan.cpp
diff --git a/mythtv/libs/libmythmetadata/videoscan.cpp b/mythtv/libs/libmythmetadata/videoscan.cpp index e40c792..72cf2a0 100644
a b bool VideoScannerThread::updateDB(const FileCheckList &add, const PurgeList &rem 340 340 if (id == -1) 341 341 { 342 342 VideoMetadata newFile( 343 p->first, hash,343 p->first, QString(), hash, 344 344 VIDEO_TRAILER_DEFAULT, 345 345 VIDEO_COVERFILE_DEFAULT, 346 346 VIDEO_SCREENSHOT_DEFAULT, 347 347 VIDEO_BANNER_DEFAULT, 348 348 VIDEO_FANART_DEFAULT, 349 VideoMetadata::FilenameToMeta(p->first, 1), 350 VideoMetadata::FilenameToMeta(p->first, 4), 349 QString(), QString(), QString(), QString(), 351 350 QString(), 352 351 VIDEO_YEAR_DEFAULT, 353 352 QDate::fromString("0000-00-00","YYYY-MM-DD"), 354 353 VIDEO_INETREF_DEFAULT, 0, QString(), 355 354 VIDEO_DIRECTOR_DEFAULT, QString(), VIDEO_PLOT_DEFAULT, 356 355 0.0, VIDEO_RATING_DEFAULT, 0, 0, 357 VideoMetadata::FilenameToMeta(p->first, 2).toInt(), 358 VideoMetadata::FilenameToMeta(p->first, 3).toInt(), 356 0, 0, 359 357 MythDate::current().date(), 360 358 0, ParentalLevel::plLowest); 361 359 -
mythtv/libs/libmythtv/datadirect.cpp
diff --git a/mythtv/libs/libmythtv/datadirect.cpp b/mythtv/libs/libmythtv/datadirect.cpp index 7c62597..fc44eef 100644
a b 26 26 #include "mythdownloadmanager.h" 27 27 #include "mythtvexp.h" 28 28 #include "mythdate.h" 29 #include "mythsorthelper.h" 29 30 30 31 #define LOC QString("DataDirect: ") 31 32 … … bool DDStructureParser::endElement(const QString &pnamespaceuri, 212 213 (void)pnamespaceuri; 213 214 (void)plocalname; 214 215 216 SortHelper *sh = new SortHelper; 215 217 MSqlQuery query(MSqlQuery::DDCon()); 216 218 217 219 if (pqname == "station") … … bool DDStructureParser::endElement(const QString &pnamespaceuri, 336 338 337 339 query.prepare( 338 340 "INSERT INTO dd_program " 339 " ( programid, title, subtitle, " 341 " ( programid, title, sorttitle, " 342 " subtitle, sortsubtitle, " 340 343 " description, showtype, category_type, " 341 344 " mpaarating, starrating, stars, " 342 345 " runtime, year, seriesid, " 343 346 " colorcode, syndicatedepisodenumber, originalairdate) " 344 347 "VALUES " 345 " (:PROGRAMID, :TITLE, :SUBTITLE, " 348 " (:PROGRAMID, :TITLE, :SORTTITLE, " 349 " :SUBTITLE, :SORTSUBTITLE, " 346 350 " :DESCRIPTION, :SHOWTYPE, :CATTYPE, " 347 351 " :MPAARATING, :STARRATING, :STARS, " 348 352 " :RUNTIME, :YEAR, :SERIESID, " … … bool DDStructureParser::endElement(const QString &pnamespaceuri, 350 354 351 355 query.bindValue(":PROGRAMID", curr_program.programid); 352 356 query.bindValue(":TITLE", curr_program.title); 357 query.bindValue(":SORTTITLE", sh->doTitle(curr_program.title)); 353 358 query.bindValue(":SUBTITLE", curr_program.subtitle); 359 query.bindValue(":SORTSUBTITLE",sh->doTitle(curr_program.subtitle)); 354 360 query.bindValue(":DESCRIPTION", curr_program.description); 355 361 query.bindValue(":SHOWTYPE", curr_program.showtype); 356 362 query.bindValue(":CATTYPE", cat_type); … … void DataDirectProcessor::UpdateProgramViewTable(uint sourceid) 635 641 QString qstr = 636 642 "INSERT INTO dd_v_program " 637 643 " ( chanid, starttime, endtime, " 638 " title, subtitle, description, " 644 " title, sorttitle, " 645 " subtitle, sortsubtitle, description, " 639 646 " airdate, stars, previouslyshown, " 640 647 " stereo, dolby, subtitled, " 641 648 " hdtv, closecaptioned, partnumber, " … … void DataDirectProcessor::UpdateProgramViewTable(uint sourceid) 644 651 " syndicatedepisodenumber, tvrating, mpaarating, " 645 652 " programid ) " 646 653 "SELECT chanid, scheduletime, endtime, " 647 " title, subtitle, description, " 654 " title, sorttitle, " 655 " subtitle, sortsubtitle, description, " 648 656 " year, stars, isrepeat, " 649 657 " stereo, dolby, subtitled, " 650 658 " hdtv, closecaptioned, partnumber, " … … void DataDirectProcessor::DataDirectProgramUpdate(void) 840 848 #endif 841 849 query.prepare( 842 850 "INSERT IGNORE INTO program " 843 " ( chanid, starttime, endtime, title, " 844 " subtitle, description, showtype, category, " 851 " ( chanid, starttime, endtime, " 852 " title, sorttitle, subtitle, sortsubtitle, " 853 " description, showtype, category, " 845 854 " category_type, airdate, stars, previouslyshown, " 846 855 " stereo, subtitled, subtitletypes, videoprop, " 847 856 " audioprop, hdtv, closecaptioned, partnumber, " … … void DataDirectProcessor::DataDirectProgramUpdate(void) 852 861 " dd_v_program.chanid, " 853 862 " DATE_ADD(starttime, INTERVAL channel.tmoffset MINUTE), " 854 863 " DATE_ADD(endtime, INTERVAL channel.tmoffset MINUTE), " 855 " title,"856 " subtitle,description, showtype, dd_genre.class, "864 " title, sorttitle, subtitle, sortsubtitle, " 865 " description, showtype, dd_genre.class, " 857 866 " category_type, airdate, stars, previouslyshown, " 858 867 " stereo, subtitled, " 859 868 " (subtitled << 1 ) | closecaptioned, hdtv, " … … void DataDirectProcessor::CreateTempTables() 1306 1315 1307 1316 dd_tables["dd_program"] = 1308 1317 "( programid char(40) NOT NULL, seriesid char(12), " 1309 " title varchar(120), subtitle varchar(150), " 1318 " title varchar(120), sorttitle varchar(120), " 1319 " subtitle varchar(150), sortsubtitle varchar(150), " 1310 1320 " description text, mpaarating char(5), " 1311 1321 " starrating char(5), runtime time, " 1312 1322 " year char(4), showtype char(30), " … … void DataDirectProcessor::CreateTempTables() 1318 1328 dd_tables["dd_v_program"] = 1319 1329 "( chanid int unsigned NOT NULL, starttime datetime NOT NULL, " 1320 1330 " endtime datetime, title varchar(128), " 1321 " subtitle varchar(128), description text, " 1331 " sorttitle varchar(128), subtitle varchar(128), " 1332 " sortsubtitle varchar(128), description text, " 1322 1333 " category varchar(64), category_type varchar(64), " 1323 1334 " airdate year, stars float unsigned, " 1324 1335 " previouslyshown tinyint, isrepeat bool, " -
mythtv/libs/libmythtv/dbcheck.cpp
diff --git a/mythtv/libs/libmythtv/dbcheck.cpp b/mythtv/libs/libmythtv/dbcheck.cpp index a0892ce..b88c179 100644
a b using namespace std; 18 18 #include "recordingprofile.h" 19 19 #include "recordinginfo.h" 20 20 #include "cardutil.h" 21 #include "mythsorthelper.h" 21 22 22 23 // TODO convert all dates to UTC 23 24 … … bool UpgradeTVDatabaseSchema(const bool upgradeAllowed, 542 543 return false; 543 544 } 544 545 546 547 /** \fn populateSortColumn(const char *, const char *) 548 * \brief Called by doUpgradeTVDatabaseSchema() to populate a single 549 * sort column. 550 * 551 * This function populates the information ins a single sort 552 * column. The sort column has the same name as the original column 553 * with the name "sort" appended. I.E. The sort data for the column 554 * "title" is put into column "sorttitle". This function attempts to 555 * be efficient by asking the database to only return distinct 556 * entries. The "ORDER" clause should eventually be dropped. 557 * 558 * \param table The name of the table to update. 559 * 560 * \param column The name of a column whose sort data should be 561 * populated. 562 * 563 * \return true on success, false on failure 564 */ 565 static bool populateSortColumn(const char *table, const char *column, int num = 0, int total = 0) 566 { 567 MSqlQuery select(MSqlQuery::InitCon()); 568 MSqlQuery update(MSqlQuery::InitCon()); 569 SortHelper *sh = new SortHelper; 570 571 QString thequery = QString("SELECT DISTINCT(%1) AS %1 FROM %2 ORDER BY %1") 572 .arg(column).arg(table); 573 QString theupdate = QString("UPDATE %1 SET sort%2=:SORT WHERE %2=:ORIG") 574 .arg(table).arg(column); 575 576 if (!select.exec(thequery)) 577 { 578 MythDB::DBError(QString("Unable to retrieve %1 %2 information.") 579 .arg(table).arg(column), select); 580 return false; 581 } 582 while (select.next()) 583 { 584 update.prepare(theupdate); 585 QString string = select.value(0).toString(); 586 QString sortString = (strcmp(column,"filename") == 0) 587 ? sh->doPathname(string) : sh->doTitle(string); 588 update.bindValue(":ORIG", string); 589 update.bindValue(":SORT", sortString); 590 if (!update.exec()) 591 { 592 MythDB::DBError(QString("Unable to update %1 %2 information.") 593 .arg(table).arg(column), update); 594 return false; 595 } 596 } 597 if (num > 0) 598 LOG(VB_GENERAL, LOG_INFO, QString("Populated %1 table [%2/%3].") 599 .arg(table).arg(num).arg(total)); 600 return true; 601 } 602 603 static bool populateSortColumns(const char *table, const char *column1, const char *column2, int num = 0, int total = 0) 604 { 605 bool result = populateSortColumn(table, column1); 606 result &= populateSortColumn(table, column2); 607 if (num > 0) 608 LOG(VB_GENERAL, LOG_INFO, QString("Populated %1 table [%2/%3].") 609 .arg(table).arg(num).arg(total)); 610 return result; 611 } 612 545 613 /** \fn doUpgradeTVDatabaseSchema(void) 546 614 * \brief This is called by UpgradeTVDatabaseSchema() to actually upgrade 547 615 * the schema to what MythTV expects. … … NULL 3331 3399 return false; 3332 3400 } 3333 3401 3402 if (dbver == "1346") 3403 { 3404 const char *updates[] = { 3405 "ALTER TABLE internetcontentarticles " 3406 " ADD COLUMN sorttitle varchar(255) NOT NULL AFTER title," 3407 " ADD COLUMN sortsubtitle varchar(255) NOT NULL AFTER subtitle", 3408 "ALTER TABLE oldrecorded " 3409 " ADD COLUMN sorttitle varchar(128) NOT NULL AFTER title," 3410 " ADD COLUMN sortsubtitle varchar(128) NOT NULL AFTER subtitle," 3411 " ADD KEY sorttitle (sorttitle)," 3412 " ADD KEY sortsubtitle (sortsubtitle)", 3413 "ALTER TABLE program " 3414 " ADD COLUMN sorttitle varchar(128) NOT NULL AFTER title," 3415 " ADD COLUMN sortsubtitle varchar(128) NOT NULL AFTER subtitle," 3416 " ADD KEY sorttitle (sorttitle)," 3417 " ADD KEY sortsubtitle (sortsubtitle)", 3418 "ALTER TABLE record " 3419 " ADD COLUMN sorttitle varchar(128) NOT NULL AFTER title," 3420 " ADD COLUMN sortsubtitle varchar(128) NOT NULL AFTER subtitle," 3421 " ADD KEY sorttitle (sorttitle)", 3422 "ALTER TABLE recorded " 3423 " ADD COLUMN sorttitle varchar(128) NOT NULL AFTER title," 3424 " ADD COLUMN sortsubtitle varchar(128) NOT NULL AFTER subtitle," 3425 " ADD KEY sorttitle (sorttitle)", 3426 "ALTER TABLE recordedprogram " 3427 " ADD COLUMN sorttitle varchar(128) NOT NULL AFTER title," 3428 " ADD COLUMN sortsubtitle varchar(128) NOT NULL AFTER subtitle," 3429 " ADD KEY sorttitle (sorttitle)", 3430 "ALTER TABLE videometadata " 3431 " ADD COLUMN sorttitle varchar(128) NOT NULL AFTER title," 3432 " ADD COLUMN sortsubtitle varchar(128) NOT NULL AFTER subtitle," 3433 " ADD COLUMN sortfilename text NOT NULL AFTER filename," 3434 " ADD KEY sorttitle (sorttitle)", 3435 NULL 3436 }; 3437 3438 if (!performUpdateSeries(updates)) 3439 return false; 3440 LOG(VB_GENERAL, LOG_INFO, "Populating sort columns. This may take some time."); 3441 if (!populateSortColumns("internetcontentarticles", "title", "subtitle", 1, 8) 3442 or !populateSortColumns("oldrecorded", "title", "subtitle", 2, 8) 3443 or !populateSortColumns("program", "title", "subtitle", 3, 8) 3444 or !populateSortColumns("record", "title", "subtitle", 4, 8) 3445 or !populateSortColumns("recorded", "title", "subtitle", 5, 8) 3446 or !populateSortColumns("recordedprogram", "title", "subtitle", 6, 8) 3447 or !populateSortColumn("videometadata", "filename", 7, 8) 3448 or !populateSortColumns("videometadata", "title", "subtitle", 8, 8)) 3449 return false; 3450 if (!UpdateDBVersionNumber("1347", dbver)) 3451 return false; 3452 } 3453 3334 3454 /* 3335 3455 * TODO the following settings are no more, clean them up with the next schema change 3336 3456 * to avoid confusion by stale settings in the database … … bool InitializeMythSchema(void) 3736 3856 " path text NOT NULL," 3737 3857 " paththumb text NOT NULL," 3738 3858 " title varchar(255) NOT NULL," 3859 " sorttitle varchar(255) NOT NULL," 3739 3860 " subtitle varchar(255) NOT NULL," 3861 " sortsubtitle varchar(255) NOT NULL," 3740 3862 " season smallint(5) NOT NULL DEFAULT '0'," 3741 3863 " episode smallint(5) NOT NULL DEFAULT '0'," 3742 3864 " description text NOT NULL," … … bool InitializeMythSchema(void) 3890 4012 " starttime datetime NOT NULL DEFAULT '0000-00-00 00:00:00'," 3891 4013 " endtime datetime NOT NULL DEFAULT '0000-00-00 00:00:00'," 3892 4014 " title varchar(128) NOT NULL DEFAULT ''," 4015 " sorttitle varchar(128) NOT NULL DEFAULT ''," 3893 4016 " subtitle varchar(128) NOT NULL DEFAULT ''," 4017 " sortsubtitle varchar(128) NOT NULL DEFAULT ''," 3894 4018 " description varchar(16000) NOT NULL DEFAULT ''," 3895 4019 " season smallint(5) NOT NULL," 3896 4020 " episode smallint(5) NOT NULL," … … bool InitializeMythSchema(void) 3910 4034 " PRIMARY KEY (station,starttime,title)," 3911 4035 " KEY endtime (endtime)," 3912 4036 " KEY title (title)," 4037 " KEY sorttitle (sorttitle)," 3913 4038 " KEY seriesid (seriesid)," 3914 4039 " KEY programid (programid)," 3915 4040 " KEY recordid (recordid)," … … bool InitializeMythSchema(void) 3918 4043 " KEY future (future)," 3919 4044 " KEY chanid (chanid,starttime)," 3920 4045 " KEY subtitle (subtitle)," 4046 " KEY sortsubtitle (sortsubtitle)," 3921 4047 " KEY description (description(255))" 3922 4048 ") ENGINE=MyISAM DEFAULT CHARSET=utf8;", 3923 4049 "CREATE TABLE people (" … … bool InitializeMythSchema(void) 3962 4088 " starttime datetime NOT NULL DEFAULT '0000-00-00 00:00:00'," 3963 4089 " endtime datetime NOT NULL DEFAULT '0000-00-00 00:00:00'," 3964 4090 " title varchar(128) NOT NULL DEFAULT ''," 4091 " sorttitle varchar(128) NOT NULL DEFAULT ''," 3965 4092 " subtitle varchar(128) NOT NULL DEFAULT ''," 4093 " sortsubtitle varchar(128) NOT NULL DEFAULT ''," 3966 4094 " description varchar(16000) NOT NULL DEFAULT ''," 3967 4095 " category varchar(64) NOT NULL DEFAULT ''," 3968 4096 " category_type varchar(64) NOT NULL DEFAULT ''," … … bool InitializeMythSchema(void) 3993 4121 " PRIMARY KEY (chanid,starttime,manualid)," 3994 4122 " KEY endtime (endtime)," 3995 4123 " KEY title (title)," 4124 " KEY sorttitle (sorttitle)," 3996 4125 " KEY title_pronounce (title_pronounce)," 3997 4126 " KEY seriesid (seriesid)," 3998 4127 " KEY id_start_end (chanid,starttime,endtime)," … … bool InitializeMythSchema(void) 4001 4130 " KEY programid (programid,starttime)," 4002 4131 " KEY starttime (starttime)," 4003 4132 " KEY subtitle (subtitle)," 4133 " KEY sortsubtitle (sortsubtitle)," 4004 4134 " KEY description (description(255))" 4005 4135 ") ENGINE=MyISAM DEFAULT CHARSET=utf8;", 4006 4136 "CREATE TABLE programgenres (" … … bool InitializeMythSchema(void) 4033 4163 " endtime time NOT NULL DEFAULT '00:00:00'," 4034 4164 " enddate date NOT NULL DEFAULT '0000-00-00'," 4035 4165 " title varchar(128) NOT NULL DEFAULT ''," 4166 " sorttitle varchar(128) NOT NULL DEFAULT ''," 4036 4167 " subtitle varchar(128) NOT NULL DEFAULT ''," 4168 " sortsubtitle varchar(128) NOT NULL DEFAULT ''," 4037 4169 " description varchar(16000) NOT NULL DEFAULT ''," 4038 4170 " season smallint(5) NOT NULL," 4039 4171 " episode smallint(5) NOT NULL," … … bool InitializeMythSchema(void) 4077 4209 " PRIMARY KEY (recordid)," 4078 4210 " KEY chanid (chanid,starttime)," 4079 4211 " KEY title (title)," 4212 " KEY sorttitle (sorttitle)," 4080 4213 " KEY seriesid (seriesid)," 4081 4214 " KEY programid (programid)," 4082 4215 " KEY maxepisodes (maxepisodes)," … … bool InitializeMythSchema(void) 4088 4221 " starttime datetime NOT NULL DEFAULT '0000-00-00 00:00:00'," 4089 4222 " endtime datetime NOT NULL DEFAULT '0000-00-00 00:00:00'," 4090 4223 " title varchar(128) NOT NULL DEFAULT ''," 4224 " sorttitle varchar(128) NOT NULL DEFAULT ''," 4091 4225 " subtitle varchar(128) NOT NULL DEFAULT ''," 4226 " sortsubtitle varchar(128) NOT NULL DEFAULT ''," 4092 4227 " description varchar(16000) NOT NULL DEFAULT ''," 4093 4228 " season smallint(5) NOT NULL," 4094 4229 " episode smallint(5) NOT NULL," … … bool InitializeMythSchema(void) 4130 4265 " KEY seriesid (seriesid)," 4131 4266 " KEY programid (programid)," 4132 4267 " KEY title (title)," 4268 " KEY sorttitle (sorttitle)," 4133 4269 " KEY recordid (recordid)," 4134 4270 " KEY deletepending (deletepending,lastmodified)," 4135 4271 " KEY recgroup (recgroup,endtime)" … … bool InitializeMythSchema(void) 4185 4321 " starttime datetime NOT NULL DEFAULT '0000-00-00 00:00:00'," 4186 4322 " endtime datetime NOT NULL DEFAULT '0000-00-00 00:00:00'," 4187 4323 " title varchar(128) NOT NULL DEFAULT ''," 4324 " sorttitle varchar(128) NOT NULL DEFAULT ''," 4188 4325 " subtitle varchar(128) NOT NULL DEFAULT ''," 4326 " sortsubtitle varchar(128) NOT NULL DEFAULT ''," 4189 4327 " description varchar(16000) NOT NULL DEFAULT ''," 4190 4328 " category varchar(64) NOT NULL DEFAULT ''," 4191 4329 " category_type varchar(64) NOT NULL DEFAULT ''," … … bool InitializeMythSchema(void) 4216 4354 " PRIMARY KEY (chanid,starttime,manualid)," 4217 4355 " KEY endtime (endtime)," 4218 4356 " KEY title (title)," 4357 " KEY sorttitle (sorttitle)," 4219 4358 " KEY title_pronounce (title_pronounce)," 4220 4359 " KEY seriesid (seriesid)," 4221 4360 " KEY programid (programid)," … … bool InitializeMythSchema(void) 4328 4467 " itemproperties varchar(255) NOT NULL DEFAULT ''," 4329 4468 " filepath varchar(512) NOT NULL DEFAULT ''," 4330 4469 " title varchar(255) NOT NULL DEFAULT ''," 4470 " sorttitle varchar(255) NOT NULL DEFAULT ''," 4331 4471 " filename varchar(512) NOT NULL DEFAULT ''," 4332 4472 " coverart varchar(512) NOT NULL DEFAULT ''," 4333 4473 " PRIMARY KEY (intid)," … … bool InitializeMythSchema(void) 4379 4519 "CREATE TABLE videometadata (" 4380 4520 " intid int(10) unsigned NOT NULL AUTO_INCREMENT," 4381 4521 " title varchar(128) NOT NULL," 4522 " sorttitle varchar(128) NOT NULL," 4382 4523 " subtitle text NOT NULL," 4524 " sortsubtitle text NOT NULL," 4383 4525 " tagline varchar(255) DEFAULT NULL," 4384 4526 " director varchar(128) NOT NULL," 4385 4527 " studio varchar(128) DEFAULT NULL," … … bool InitializeMythSchema(void) 4397 4539 " episode smallint(5) unsigned NOT NULL DEFAULT '0'," 4398 4540 " showlevel int(10) unsigned NOT NULL," 4399 4541 " filename text NOT NULL," 4542 " sortFilename text NOT NULL," 4400 4543 " `hash` varchar(128) NOT NULL," 4401 4544 " coverfile text NOT NULL," 4402 4545 " childid int(11) NOT NULL DEFAULT '-1'," … … bool InitializeMythSchema(void) 4414 4557 " contenttype set('MOVIE','TELEVISION','ADULT','MUSICVIDEO','HOMEVIDEO') NOT NULL DEFAULT ''," 4415 4558 " PRIMARY KEY (intid)," 4416 4559 " KEY director (director)," 4417 " KEY title (title)" 4560 " KEY title (title)," 4561 " KEY titlesort (titlesort)" 4418 4562 ") ENGINE=MyISAM DEFAULT CHARSET=utf8;", 4419 4563 "CREATE TABLE videometadatacast (" 4420 4564 " idvideo int(10) unsigned NOT NULL," -
mythtv/libs/libmythtv/eithelper.cpp
diff --git a/mythtv/libs/libmythtv/eithelper.cpp b/mythtv/libs/libmythtv/eithelper.cpp index 5412770..0c57065 100644
a b void EITHelper::AddEIT(const DVBEventInformationTable *eit) 684 684 QDateTime endtime = starttime.addSecs(eit->DurationInSeconds(i)); 685 685 686 686 DBEventEIT *event = new DBEventEIT( 687 chanid, 688 title, subtitle,description,687 chanid, title, QString(), 688 subtitle, QString(), description, 689 689 category, category_type, 690 690 starttime, endtime, fix, 691 691 subtitle_type, … … void EITHelper::AddEIT(const PremiereContentInformationTable *cit) 795 795 QDateTime endtime = starttime.addSecs(cit->DurationInSeconds()); 796 796 797 797 DBEventEIT *event = new DBEventEIT( 798 chanid, 799 title, subtitle,description,798 chanid, title, QString(), 799 subtitle, QString(), description, 800 800 category, category_type, 801 801 starttime, endtime, fix, 802 802 subtitle_type, -
mythtv/libs/libmythtv/programdata.cpp
diff --git a/mythtv/libs/libmythtv/programdata.cpp b/mythtv/libs/libmythtv/programdata.cpp index f99b0d8..3472b83 100644
a b using namespace std; 15 15 #include "mythdb.h" 16 16 #include "mythlogging.h" 17 17 #include "dvbdescriptors.h" 18 #include "mythsorthelper.h" 18 19 19 20 #define LOC QString("ProgramData: ") 20 21 … … uint DBEvent::GetOverlappingPrograms( 363 364 " previouslyshown,listingsource, " 364 365 " stars+0, " 365 366 " season, episode, totalepisodes, " 366 " inetref "367 " inetref, sorttitle, sortsubtitle " 367 368 "FROM program " 368 369 "WHERE chanid = :CHANID AND " 369 370 " manualid = 0 AND " … … uint DBEvent::GetOverlappingPrograms( 391 392 392 393 DBEvent prog( 393 394 query.value(0).toString(), 395 query.value(24).toString(), 394 396 query.value(1).toString(), 397 query.value(25).toString(), 395 398 query.value(2).toString(), 396 399 query.value(3).toString(), 397 400 category_type, … … uint DBEvent::UpdateDB( 617 620 MSqlQuery &query, uint chanid, const DBEvent &match) const 618 621 { 619 622 QString ltitle = title; 623 QString lsortTitle = sortTitle; 620 624 QString lsubtitle = subtitle; 625 QString lsortSubtitle = sortSubtitle; 621 626 QString ldesc = description; 622 627 QString lcategory = category; 623 628 uint16_t lairdate = airdate; … … uint DBEvent::UpdateDB( 627 632 QDate loriginalairdate = originalairdate; 628 633 629 634 if (match.title.length() >= ltitle.length()) 635 { 630 636 ltitle = match.title; 637 lsortTitle = match.sortTitle; 638 } 631 639 632 640 if (match.subtitle.length() >= lsubtitle.length()) 641 { 633 642 lsubtitle = match.subtitle; 643 lsortSubtitle = match.sortSubtitle; 644 } 634 645 635 646 if (match.description.length() >= ldesc.length()) 636 647 ldesc = match.description; … … uint DBEvent::UpdateDB( 694 705 695 706 query.prepare( 696 707 "UPDATE program " 697 "SET title = :TITLE, subtitle = :SUBTITLE, " 708 "SET title = :TITLE, sorttitle = :SORTTITLE, " 709 " subtitle = :SUBTITLE, sortsubtitle = :SORTSUBTITLE, " 698 710 " description = :DESC, " 699 711 " category = :CATEGORY, category_type = :CATTYPE, " 700 712 " starttime = :STARTTIME, endtime = :ENDTIME, " … … uint DBEvent::UpdateDB( 716 728 query.bindValue(":CHANID", chanid); 717 729 query.bindValue(":OLDSTART", match.starttime); 718 730 query.bindValue(":TITLE", denullify(ltitle)); 731 query.bindValue(":SORTTITLE", denullify(lsortTitle)); 719 732 query.bindValue(":SUBTITLE", denullify(lsubtitle)); 733 query.bindValue(":SORTSUBTITLE", denullify(lsortSubtitle)); 720 734 query.bindValue(":DESC", denullify(ldesc)); 721 735 query.bindValue(":CATEGORY", denullify(lcategory)); 722 736 query.bindValue(":CATTYPE", lcattype); … … uint DBEvent::UpdateDB( 745 759 746 760 if (!query.exec()) 747 761 { 748 MythDB::DBError(" InsertDB", query);762 MythDB::DBError("UpdateDB", query); 749 763 return 0; 750 764 } 751 765 … … bool DBEvent::MoveOutOfTheWayDB( 989 1003 return true; 990 1004 } 991 1005 1006 /** 1007 * \brief Insert Callback function when Allow Re-record is pressed in Watch Recordings 1008 */ 992 1009 uint DBEvent::InsertDB(MSqlQuery &query, uint chanid) const 993 1010 { 994 1011 query.prepare( 995 1012 "REPLACE INTO program (" 996 " chanid, title, subtitle, description, " 1013 " chanid, title, sorttitle, " 1014 " subtitle, sortsubtitle, description, " 997 1015 " category, category_type, " 998 1016 " starttime, endtime, " 999 1017 " closecaptioned, stereo, hdtv, subtitled, " … … uint DBEvent::InsertDB(MSqlQuery &query, uint chanid) const 1005 1023 " season, episode, totalepisodes, " 1006 1024 " inetref ) " 1007 1025 "VALUES (" 1008 " :CHANID, :TITLE, :SUBTITLE, :DESCRIPTION, " 1026 " :CHANID, :TITLE, :SORTTITLE, " 1027 " :SUBTITLE, :SORTSUBTITLE, :DESCRIPTION, " 1009 1028 " :CATEGORY, :CATTYPE, " 1010 1029 " :STARTTIME, :ENDTIME, " 1011 1030 " :CC, :STEREO, :HDTV, :HASSUBTITLES, " … … uint DBEvent::InsertDB(MSqlQuery &query, uint chanid) const 1021 1040 QString empty(""); 1022 1041 query.bindValue(":CHANID", chanid); 1023 1042 query.bindValue(":TITLE", denullify(title)); 1043 query.bindValue(":SORTTITLE", denullify(sortTitle)); 1024 1044 query.bindValue(":SUBTITLE", denullify(subtitle)); 1045 query.bindValue(":SORTSUBTITLE", denullify(sortSubtitle)); 1025 1046 query.bindValue(":DESCRIPTION", denullify(description)); 1026 1047 query.bindValue(":CATEGORY", denullify(category)); 1027 1048 query.bindValue(":CATTYPE", cattype); … … void ProgInfo::Squeeze(void) 1129 1150 clumpmax.squeeze(); 1130 1151 } 1131 1152 1153 /** 1154 * \brief Insert a single entry into the "program" database. 1155 * 1156 * This function is called from HandlePrograms, which is called from 1157 * mythfilldatabase. It inserts a single entry into the "program" 1158 * database. The data for this structure is taken from the 'this' 1159 * ProgInfo object. 1160 * 1161 * \param query Any mysql query structure. The contents is ignored 1162 * and the structure is repurposed for local queries. 1163 * \param chanid The channel number for this program. 1164 */ 1132 1165 uint ProgInfo::InsertDB(MSqlQuery &query, uint chanid) const 1133 1166 { 1134 1167 LOG(VB_XMLTV, LOG_INFO, … … uint ProgInfo::InsertDB(MSqlQuery &query, uint chanid) const 1140 1173 1141 1174 query.prepare( 1142 1175 "REPLACE INTO program (" 1143 " chanid, title, subtitle, description, " 1176 " chanid, title, sorttitle, " 1177 " subtitle, sortsubtitle, description, " 1144 1178 " category, category_type, " 1145 1179 " starttime, endtime, " 1146 1180 " closecaptioned, stereo, hdtv, subtitled, " … … uint ProgInfo::InsertDB(MSqlQuery &query, uint chanid) const 1154 1188 " inetref ) " 1155 1189 1156 1190 "VALUES(" 1157 " :CHANID, :TITLE, :SUBTITLE, :DESCRIPTION, " 1191 " :CHANID, :TITLE, :SORTTITLE, " 1192 " :SUBTITLE, :SORTSUBTITLE, :DESCRIPTION, " 1158 1193 " :CATEGORY, :CATTYPE, " 1159 1194 " :STARTTIME, :ENDTIME, " 1160 1195 " :CC, :STEREO, :HDTV, :HASSUBTITLES, " … … uint ProgInfo::InsertDB(MSqlQuery &query, uint chanid) const 1169 1204 1170 1205 QString cattype = myth_category_type_to_string(categoryType); 1171 1206 1207 // Someday mythfilldatabase might pass in sort strings. Until 1208 // then, generate the sort strings here as needed. 1209 SortHelper *sh = new SortHelper; 1210 QString ltitle = denullify(title); 1211 QString lsortTitle = denullify(sortTitle); 1212 QString lsubtitle = denullify(subtitle); 1213 QString lsortSubtitle = denullify(sortSubtitle); 1214 if (lsortTitle.isEmpty()) 1215 lsortTitle = sh->doTitle(ltitle); 1216 if (lsortSubtitle.isEmpty()) 1217 lsortSubtitle = sh->doTitle(lsubtitle); 1218 1172 1219 query.bindValue(":CHANID", chanid); 1173 query.bindValue(":TITLE", denullify(title)); 1174 query.bindValue(":SUBTITLE", denullify(subtitle)); 1220 query.bindValue(":TITLE", ltitle); 1221 query.bindValue(":SORTTITLE", lsortTitle); 1222 query.bindValue(":SUBTITLE", lsubtitle); 1223 query.bindValue(":SORTSUBTITLE", lsortSubtitle); 1175 1224 query.bindValue(":DESCRIPTION", denullify(description)); 1176 1225 query.bindValue(":CATEGORY", denullify(category)); 1177 1226 query.bindValue(":CATTYPE", cattype); … … void ProgramData::FixProgramList(QList<ProgInfo*> &fixlist) 1374 1423 } 1375 1424 } 1376 1425 1426 /** 1427 * \brief Called from mythfilldatabase to bulk insert data into the 1428 * program database. 1429 * 1430 * \param sourceid The data source identifier 1431 * \param proglist A map of all program information keyed by channel 1432 * identifier 1433 */ 1377 1434 void ProgramData::HandlePrograms( 1378 1435 uint sourceid, QMap<QString, QList<ProgInfo> > &proglist) 1379 1436 { … … void ProgramData::HandlePrograms( 1432 1489 .arg(updated) .arg(unchanged)); 1433 1490 } 1434 1491 1492 /** 1493 * \brief Called from HandlePrograms to bulk insert data into the 1494 * program database. 1495 * 1496 * \param query A mysql query related to all channel ids for 1497 * a given source 1498 * \param chanid The specific channel id to process 1499 * \param sortlist A time sorted list of ProgInfo structures 1500 * \param unchanged Set to the number of unchanged programs 1501 * \param updated Set to the number of updated programs 1502 */ 1435 1503 void ProgramData::HandlePrograms(MSqlQuery &query, 1436 1504 uint chanid, 1437 1505 const QList<ProgInfo*> &sortlist, -
mythtv/libs/libmythtv/programdata.h
diff --git a/mythtv/libs/libmythtv/programdata.h b/mythtv/libs/libmythtv/programdata.h index 58db39b..9ee40a4 100644
a b using namespace std; 20 20 #include "listingsources.h" 21 21 #include "programinfo.h" 22 22 #include "eithelper.h" /* for FixupValue */ 23 #include "mythsorthelper.h" 23 24 24 25 class MSqlQuery; 25 26 … … class MTV_PUBLIC DBEvent 75 76 public: 76 77 DBEvent(uint _listingsource) : 77 78 title(), 79 sortTitle(), 78 80 subtitle(), 81 sortSubtitle(), 79 82 description(), 80 83 category(), 81 84 /*starttime, endtime,*/ … … class MTV_PUBLIC DBEvent 98 101 episode(0), 99 102 totalepisodes(0) {} 100 103 101 DBEvent(const QString &_title, const QString &_subtitle, 104 DBEvent(const QString &_title, const QString &_sortTitle, 105 const QString &_subtitle, const QString &_sortSubtitle, 102 106 const QString &_desc, 103 107 const QString &_category, ProgramInfo::CategoryType _category_type, 104 108 const QDateTime &_start, const QDateTime &_end, … … class MTV_PUBLIC DBEvent 110 114 uint32_t _listingsource, 111 115 uint _season, uint _episode, 112 116 uint _totalepisodes ) : 113 title(_title), subtitle(_subtitle), 117 title(_title), sortTitle(_sortTitle), 118 subtitle(_subtitle), sortSubtitle(_sortSubtitle), 114 119 description(_desc), 115 120 category(_category), 116 121 starttime(_start), endtime(_end), … … class MTV_PUBLIC DBEvent 131 136 episode(_episode), 132 137 totalepisodes(_totalepisodes) 133 138 { 139 SortHelper *sh = new SortHelper; 140 if (sortTitle.isEmpty()) 141 sortTitle = sh->doTitle(_title); 142 if (sortSubtitle.isEmpty()) 143 sortSubtitle = sh->doTitle(_sortTitle); 134 144 } 135 145 136 146 virtual ~DBEvent() { delete credits; } … … class MTV_PUBLIC DBEvent 161 171 162 172 public: 163 173 QString title; 174 QString sortTitle; 164 175 QString subtitle; 176 QString sortSubtitle; 165 177 QString description; 166 178 QString category; 167 179 QDateTime starttime; … … class MTV_PUBLIC DBEventEIT : public DBEvent 193 205 { 194 206 public: 195 207 DBEventEIT(uint _chanid, 196 const QString &_title, const QString &_subtitle, 208 const QString &_title, const QString &_sortTitle, 209 const QString &_subtitle, const QString &_sortSubtitle, 197 210 const QString &_desc, 198 211 const QString &_category, ProgramInfo::CategoryType _category_type, 199 212 const QDateTime &_start, const QDateTime &_end, … … class MTV_PUBLIC DBEventEIT : public DBEvent 205 218 const QString &_seriesId, const QString &_programId, 206 219 uint _season, uint _episode, 207 220 uint _totalepisodes ) : 208 DBEvent(_title, _subtitle, _desc, _category, _category_type, 221 DBEvent(_title, _sortTitle, _subtitle, _sortSubtitle, 222 _desc, _category, _category_type, 209 223 _start, _end, _subtitleType, _audioProps, _videoProps, 210 224 _stars, _seriesId, _programId, kListingSourceEIT, 211 225 _season, _episode, _totalepisodes), … … class MTV_PUBLIC DBEventEIT : public DBEvent 220 234 unsigned char _subtitleType, 221 235 unsigned char _audioProps, 222 236 unsigned char _videoProps) : 223 DBEvent(_title, QString(), _desc, QString(), ProgramInfo::kCategoryNone, 237 DBEvent(_title, QString(), QString(), QString(), 238 _desc, QString(), ProgramInfo::kCategoryNone, 224 239 _start, _end, _subtitleType, _audioProps, _videoProps, 225 240 0.0, QString(), QString(), kListingSourceEIT, 0, 0, 0), // Season, Episode and Total Episodes are not set with this constructor! 226 241 chanid(_chanid), fixup(_fixup) -
mythtv/libs/libmythtv/recordinginfo.cpp
diff --git a/mythtv/libs/libmythtv/recordinginfo.cpp b/mythtv/libs/libmythtv/recordinginfo.cpp index 3a87da0..da1cec0 100644
a b 18 18 #include "jobqueue.h" 19 19 #include "mythdb.h" 20 20 #include "mythlogging.h" 21 #include "mythsorthelper.h" 21 22 22 23 #define LOC QString("RecordingInfo(%1): ").arg(GetBasename()) 23 24 … … static const uint kUnknownProgramLength = 30; 32 33 33 34 RecordingInfo::RecordingInfo( 34 35 const QString &_title, 36 const QString &_sortTitle, 35 37 const QString &_subtitle, 38 const QString &_sortSubtitle, 36 39 const QString &_description, 37 40 uint _season, 38 41 uint _episode, … … RecordingInfo::RecordingInfo( 95 98 uint _mplexid, 96 99 uint _sgroupid) : 97 100 ProgramInfo( 98 _title, _subtitle, _description, _season, _episode, _totalepisodes, 101 _title, _sortTitle, _subtitle, _sortSubtitle, 102 _description, _season, _episode, _totalepisodes, 99 103 _category, _chanid, _chanstr, _chansign, _channame, 100 104 QString(), _recgroup, _playgroup, 101 105 _startts, _endts, _recstartts, _recendts, … … RecordingInfo::RecordingInfo( 162 166 163 167 RecordingInfo::RecordingInfo( 164 168 const QString &_title, 169 const QString &_sortTitle, 165 170 const QString &_subtitle, 171 const QString &_sortSubtitle, 166 172 const QString &_description, 167 173 uint _season, 168 174 uint _episode, … … RecordingInfo::RecordingInfo( 198 204 199 205 bool _commfree) : 200 206 ProgramInfo( 201 _title, _subtitle, _description, _season, _episode, 0, 207 _title, _sortTitle, _subtitle, _sortSubtitle, 208 _description, _season, _episode, 0, 202 209 _category, _chanid, _chanstr, _chansign, _channame, 203 210 QString(), _recgroup, _playgroup, 204 211 _startts, _endts, _recstartts, _recendts, … … void RecordingInfo::ApplyRecordRecTitleChange(const QString &newTitle, 755 762 const QString &newSubtitle, const QString &newDescription) 756 763 { 757 764 MSqlQuery query(MSqlQuery::InitCon()); 758 QString sql = "UPDATE recorded SET title = :TITLE, subtitle = :SUBTITLE "; 765 QString sql = "UPDATE recorded SET " 766 " title = :TITLE, sorttitle = :SORTTITLE, " 767 " subtitle = :SUBTITLE, sortsubtitle = :SORTSUBTITLE "; 759 768 if (!newDescription.isNull()) 760 769 sql += ", description = :DESCRIPTION "; 761 770 sql += " WHERE chanid = :CHANID AND starttime = :START ;"; 762 771 772 SortHelper *sh = new SortHelper; 763 773 query.prepare(sql); 764 774 query.bindValue(":TITLE", newTitle); 775 query.bindValue(":SORTTITLE", sh->doTitle(newTitle)); 765 776 query.bindValue(":SUBTITLE", null_to_empty(newSubtitle)); 777 query.bindValue(":SORTSUBTITLE", sh->doTitle(null_to_empty(newSubtitle))); 766 778 if (!newDescription.isNull()) 767 779 query.bindValue(":DESCRIPTION", newDescription); 768 780 query.bindValue(":CHANID", chanid); … … bool RecordingInfo::InsertProgram(RecordingInfo *pg, 1045 1057 1046 1058 query.prepare( 1047 1059 "INSERT INTO recorded " 1048 " (chanid, starttime, endtime, title, " 1049 " subtitle, description, season, episode, " 1060 " (chanid, starttime, endtime, " 1061 " title, sorttitle, subtitle, sortsubtitle, " 1062 " description, season, episode, " 1050 1063 " hostname, category, recgroup, autoexpire, " 1051 1064 " recordid, seriesid, programid, inetref, " 1052 1065 " stars, previouslyshown, originalairdate, " … … bool RecordingInfo::InsertProgram(RecordingInfo *pg, 1054 1067 " basename, progstart, progend, profile, " 1055 1068 " duplicate, storagegroup, inputname, recgroupid) " 1056 1069 "VALUES" 1057 " (:CHANID, :STARTS, :ENDS, :TITLE, " 1058 " :SUBTITLE, :DESC, :SEASON, :EPISODE, " 1070 " (:CHANID, :STARTS, :ENDS, " 1071 " :TITLE, :SORTTITLE, :SUBTITLE, :SORTSUBTITLE, " 1072 " :DESC, :SEASON, :EPISODE, " 1059 1073 " :HOSTNAME, :CATEGORY, :RECGROUP, :AUTOEXP, " 1060 1074 " :RECORDID, :SERIESID, :PROGRAMID, :INETREF, " 1061 1075 " :STARS, :REPEAT, :ORIGAIRDATE, " … … bool RecordingInfo::InsertProgram(RecordingInfo *pg, 1078 1092 query.bindValue(":STARTS", pg->recstartts); 1079 1093 query.bindValue(":ENDS", pg->recendts); 1080 1094 query.bindValue(":TITLE", pg->title); 1095 query.bindValue(":SORTTITLE", pg->sortTitle); 1081 1096 query.bindValue(":SUBTITLE", null_to_empty(pg->subtitle)); 1097 query.bindValue(":SORTSUBTITLE", null_to_empty(pg->sortSubtitle)); 1082 1098 query.bindValue(":DESC", null_to_empty(pg->description)); 1083 1099 query.bindValue(":SEASON", pg->season); 1084 1100 query.bindValue(":EPISODE", pg->episode); … … void RecordingInfo::AddHistory(bool resched, bool forcedup, bool future) 1252 1268 result.prepare("REPLACE INTO oldrecorded (chanid,starttime," 1253 1269 "endtime,title,subtitle,description,season,episode," 1254 1270 "category,seriesid,programid,inetref,findid,recordid," 1255 "station,rectype,recstatus,duplicate,reactivate,future) " 1271 "station,rectype,recstatus,duplicate,reactivate,future," 1272 "sorttitle,sortsubtitle) " 1256 1273 "VALUES(:CHANID,:START,:END,:TITLE,:SUBTITLE,:DESC,:SEASON," 1257 1274 ":EPISODE,:CATEGORY,:SERIESID,:PROGRAMID,:INETREF," 1258 1275 ":FINDID,:RECORDID,:STATION,:RECTYPE,:RECSTATUS,:DUPLICATE," 1259 ":REACTIVATE,:FUTURE );");1276 ":REACTIVATE,:FUTURE,:SORTTITLE,:SORTSUBTITLE);"); 1260 1277 result.bindValue(":CHANID", chanid); 1261 1278 result.bindValue(":START", startts); 1262 1279 result.bindValue(":END", endts); 1263 1280 result.bindValue(":TITLE", title); 1281 result.bindValue(":SORTTITLE", sortTitle); 1264 1282 result.bindValue(":SUBTITLE", null_to_empty(subtitle)); 1283 result.bindValue(":SORTSUBTITLE", null_to_empty(sortSubtitle)); 1265 1284 result.bindValue(":DESC", null_to_empty(description)); 1266 1285 result.bindValue(":SEASON", season); 1267 1286 result.bindValue(":EPISODE", episode); -
mythtv/libs/libmythtv/recordinginfo.h
diff --git a/mythtv/libs/libmythtv/recordinginfo.h b/mythtv/libs/libmythtv/recordinginfo.h index 9502001..c2b4252 100644
a b class MTV_PUBLIC RecordingInfo : public ProgramInfo 110 110 /// used in scheduler.cpp @ ~ 3296 111 111 RecordingInfo( 112 112 const QString &title, 113 const QString &sortTitle, 113 114 const QString &subtitle, 115 const QString &sortSubtitle, 114 116 const QString &description, 115 117 uint season, 116 118 uint episode, … … class MTV_PUBLIC RecordingInfo : public ProgramInfo 177 179 /// user in scheduler.cpp @ ~ 3566 & ~ 3643 178 180 RecordingInfo( 179 181 const QString &title, 182 const QString &sortTitle, 180 183 const QString &subtitle, 184 const QString &sortSubtitle, 181 185 const QString &description, 182 186 uint season, 183 187 uint episode, -
mythtv/libs/libmythtv/recordingrule.cpp
diff --git a/mythtv/libs/libmythtv/recordingrule.cpp b/mythtv/libs/libmythtv/recordingrule.cpp index a206500..d9508b1 100644
a b 12 12 #include "playgroup.h" // For GetInitialName() 13 13 #include "recordingprofile.h" // For constants 14 14 #include "mythdate.h" 15 #include "mythsorthelper.h" 15 16 16 17 static inline QString null_to_empty(const QString &str) 17 18 { … … bool RecordingRule::Load(bool asTemplate) 93 94 "autometadata, parentid, title, subtitle, description, season, episode, " 94 95 "category, starttime, startdate, endtime, enddate, seriesid, programid, " 95 96 "inetref, chanid, station, findday, findtime, findid, " 96 "next_record, last_record, last_delete, avg_delay, filter, recgroupid " 97 "next_record, last_record, last_delete, avg_delay, filter, recgroupid, " 98 "sorttitle,sortsubtitle " 97 99 "FROM record WHERE recordid = :RECORDID ;"); 98 100 99 101 query.bindValue(":RECORDID", m_recordID); … … bool RecordingRule::Load(bool asTemplate) 150 152 if (!asTemplate) 151 153 { 152 154 m_title = query.value(25).toString(); 155 m_sortTitle = query.value(49).toString(); 153 156 m_subtitle = query.value(26).toString(); 157 m_sortSubtitle = query.value(50).toString(); 154 158 m_description = query.value(27).toString(); 155 159 m_season = query.value(28).toUInt(); 156 160 m_episode = query.value(29).toUInt(); … … bool RecordingRule::LoadBySearch(RecSearchType lsearch, QString textname, 258 262 m_searchType = lsearch; 259 263 searchType = SearchTypeToString(m_searchType); 260 264 265 SortHelper *sh = new SortHelper; 261 266 QString ltitle = QString("%1 (%2)").arg(textname).arg(searchType); 262 267 m_title = ltitle; 268 m_sortTitle = sh->doTitle(ltitle); 269 // The caller from customedit.cpp calls here with the subtitle 270 // in the 'from' argument. The other callers from 271 // proglist_helpers.cpp call with an SQL code fragment in the 272 // 'from' field. Impossible to know what's the right way to 273 // create the sortSubtitle field. 263 274 m_subtitle = from; 275 m_sortSubtitle = from; 264 276 m_description = forwhat; 265 277 266 278 if (pginfo) … … bool RecordingRule::MakeTemplate(QString category) 322 334 { 323 335 category = "Default"; 324 336 m_title = tr("Default (Template)"); 337 m_sortTitle = m_title; 325 338 } 326 339 else 327 340 { 328 341 //: %1 is the category 329 342 m_title = tr("%1 (Template)").arg(category); 343 m_sortTitle = m_title; 330 344 } 331 345 332 346 LoadTemplate(category); … … bool RecordingRule::ModifyPowerSearchByID(int rid, QString textname, 351 365 352 366 QString ltitle = QString("%1 (%2)").arg(textname) 353 367 .arg(tr("Power Search")); 368 SortHelper *sh = new SortHelper; 354 369 m_title = ltitle; 370 m_sortTitle = sh->doTitle(ltitle); 355 371 m_subtitle = from; 372 // This doesn't appear to be a subtitle, so copy it verbatim. 373 m_sortSubtitle = from; 356 374 m_description = forwhat; 357 375 358 376 m_loaded = true; … … bool RecordingRule::Save(bool sendSig) 401 419 "autouserjob3 = :AUTOUSERJOB3, " 402 420 "autouserjob4 = :AUTOUSERJOB4, " 403 421 "autometadata = :AUTOMETADATA, " 404 "parentid = :PARENTID, title = :TITLE, " 405 "subtitle = :SUBTITLE, season = :SEASON, episode = :EPISODE, " 422 "parentid = :PARENTID, " 423 "title = :TITLE, sorttitle = :SORTTITLE, " 424 "subtitle = :SUBTITLE, sortsubtitle = :SORTSUBTITLE, " 425 "season = :SEASON, episode = :EPISODE, " 406 426 "description = :DESCRIPTION, category = :CATEGORY, " 407 427 "starttime = :STARTTIME, startdate = :STARTDATE, " 408 428 "endtime = :ENDTIME, enddate = :ENDDATE, seriesid = :SERIESID, " … … bool RecordingRule::Save(bool sendSig) 450 470 query.bindValue(":AUTOMETADATA", m_autoMetadataLookup); 451 471 query.bindValue(":PARENTID", m_parentRecID); 452 472 query.bindValue(":TITLE", m_title); 473 query.bindValue(":SORTTITLE", m_sortTitle); 453 474 query.bindValue(":SUBTITLE", null_to_empty(m_subtitle)); 475 query.bindValue(":SORTSUBTITLE", null_to_empty(m_sortSubtitle)); 454 476 query.bindValue(":DESCRIPTION", null_to_empty(m_description)); 455 477 query.bindValue(":SEASON", m_season); 456 478 query.bindValue(":EPISODE", m_episode); … … bool RecordingRule::Delete(bool sendSig) 542 564 void RecordingRule::ToMap(InfoMap &infoMap) const 543 565 { 544 566 if (m_title == "Default (Template)") 567 { 545 568 infoMap["title"] = tr("Default (Template)"); 569 infoMap["sorttitle"] = tr("Default (Template)"); 570 } 546 571 else 572 { 547 573 infoMap["title"] = m_title; 574 infoMap["sorttitle"] = m_sortTitle; 575 } 548 576 infoMap["subtitle"] = m_subtitle; 577 infoMap["sortsubtitle"] = m_sortSubtitle; 549 578 infoMap["description"] = m_description; 550 579 infoMap["season"] = QString::number(m_season); 551 580 infoMap["episode"] = QString::number(m_episode); … … void RecordingRule::AssignProgramInfo() 736 765 return; 737 766 738 767 m_title = m_progInfo->GetTitle(); 768 m_sortTitle = m_progInfo->GetSortTitle(); 739 769 m_subtitle = m_progInfo->GetSubtitle(); 770 m_sortSubtitle= m_progInfo->GetSortSubtitle(); 740 771 m_description = m_progInfo->GetDescription(); 741 772 m_channelid = m_progInfo->GetChanID(); 742 773 m_station = m_progInfo->GetChannelSchedulingID(); -
mythtv/libs/libmythtv/recordingrule.h
diff --git a/mythtv/libs/libmythtv/recordingrule.h b/mythtv/libs/libmythtv/recordingrule.h index 0ef9c5a..4e10ac0 100644
a b class MTV_PUBLIC RecordingRule 73 73 74 74 // Recording metadata 75 75 QString m_title; 76 QString m_sortTitle; 76 77 QString m_subtitle; 78 QString m_sortSubtitle; 77 79 QString m_description; 78 80 uint m_season; 79 81 uint m_episode; -
mythtv/libs/libmythtv/test/test_eitfixups/test_eitfixups.cpp
diff --git a/mythtv/libs/libmythtv/test/test_eitfixups/test_eitfixups.cpp b/mythtv/libs/libmythtv/test/test_eitfixups/test_eitfixups.cpp index 946a5f7..e9f6f76 100644
a b DBEventEIT *TestEITFixups::SimpleDBEventEIT (FixupValue fixup, QString title, QS 419 419 { 420 420 DBEventEIT *event = new DBEventEIT (1, // channel id 421 421 title, // title 422 QString(), //sortTitle 422 423 subtitle, // subtitle 424 QString(), //sortSubtitle 423 425 description, // description 424 426 "", // category 425 427 ProgramInfo::kCategoryNone, // category_type -
mythtv/programs/mythbackend/main_helpers.cpp
diff --git a/mythtv/programs/mythbackend/main_helpers.cpp b/mythtv/programs/mythbackend/main_helpers.cpp index e4a4089..bb698af 100644
a b int run_backend(MythBackendCommandLineParser &cmdline) 568 568 569 569 if (!UpgradeTVDatabaseSchema(ismaster, ismaster)) 570 570 { 571 LOG(VB_GENERAL, LOG_ERR, "Couldn't upgrade database to new schema"); 571 if (ismaster) 572 LOG(VB_GENERAL, LOG_ERR, "Couldn't upgrade database to new schema on master backend."); 573 else 574 LOG(VB_GENERAL, LOG_ERR, "Couldn't upgrade database to new schema on slave backend."); 572 575 return GENERIC_EXIT_DB_OUTOFDATE; 573 576 } 574 577 -
mythtv/programs/mythbackend/scheduler.cpp
diff --git a/mythtv/programs/mythbackend/scheduler.cpp b/mythtv/programs/mythbackend/scheduler.cpp index 49b2912..e39eb73 100644
a b void Scheduler::UpdateManuals(uint recordid) 3666 3666 MSqlQuery query(dbConn); 3667 3667 3668 3668 query.prepare(QString("SELECT type,title,station,startdate,starttime, " 3669 " enddate,endtime "3669 " enddate,endtime,sorttitle " 3670 3670 "FROM %1 WHERE recordid = :RECORDID").arg(recordTable)); 3671 3671 query.bindValue(":RECORDID", recordid); 3672 3672 if (!query.exec() || query.size() != 1) … … void Scheduler::UpdateManuals(uint recordid) 3680 3680 3681 3681 RecordingType rectype = RecordingType(query.value(0).toInt()); 3682 3682 QString title = query.value(1).toString(); 3683 QString sortTitle = query.value(7).toString(); 3683 3684 QString station = query.value(2).toString() ; 3684 3685 QDateTime startdt = QDateTime(query.value(3).toDate(), 3685 3686 query.value(4).toTime(), Qt::UTC); … … void Scheduler::UpdateManuals(uint recordid) 3749 3750 continue; 3750 3751 3751 3752 query.prepare("REPLACE INTO program (chanid, starttime, endtime," 3752 " title, s ubtitle, manualid, generic) "3753 " title, sorttitle, subtitle, manualid, generic) " 3753 3754 "VALUES (:CHANID, :STARTTIME, :ENDTIME, :TITLE," 3754 " :S UBTITLE, :RECORDID, 1)");3755 " :SORTTITLE, :SUBTITLE, :RECORDID, 1)"); 3755 3756 query.bindValue(":CHANID", chanidlist[i]); 3756 3757 query.bindValue(":STARTTIME", startdt); 3757 3758 query.bindValue(":ENDTIME", startdt.addSecs(duration)); 3758 3759 query.bindValue(":TITLE", title); 3760 query.bindValue(":SORTTITLE", sortTitle); 3759 3761 query.bindValue(":SUBTITLE", startdt.toLocalTime()); 3760 3762 query.bindValue(":RECORDID", recordid); 3761 3763 if (!query.exec()) … … void Scheduler::AddNewRecords(void) 4439 4441 " capturecard.hostname, recordmatch.oldrecstatus, NULL, "//43-45 4440 4442 " oldrecstatus.future, capturecard.schedorder, " //46-47 4441 4443 " p.syndicatedepisodenumber, p.partnumber, p.parttotal, " //48-50 4442 " c.mplexid, ") + //514444 " c.mplexid, p.sorttitle, p.sortsubtitle, ") + //51-53 4443 4445 pwrpri + QString( 4444 4446 "FROM recordmatch " 4445 4447 "INNER JOIN RECTABLE ON (recordmatch.recordid = RECTABLE.recordid) " … … void Scheduler::AddNewRecords(void) 4506 4508 4507 4509 RecordingInfo *p = new RecordingInfo( 4508 4510 title, 4511 result.value(52).toString(),//sorttitle 4509 4512 result.value(5).toString(),//subtitle 4513 result.value(53).toString(),//sortsubtitle 4510 4514 result.value(6).toString(),//description 4511 4515 0, // season 4512 4516 0, // episode … … void Scheduler::AddNotListed(void) { 4709 4713 " RECTABLE.dupin, RECTABLE.dupmethod, " // 22,23 4710 4714 " RECTABLE.findid, " // 24 4711 4715 " RECTABLE.startoffset, RECTABLE.endoffset, " // 25,26 4712 " channel.commmethod " // 27 4716 " channel.commmethod, RECTABLE.sorttitle, " // 27,28 4717 " RECTABLE.sortsubtitle " // 29 4713 4718 "FROM RECTABLE " 4714 4719 "INNER JOIN channel ON (channel.chanid = RECTABLE.chanid) " 4715 4720 "LEFT JOIN recordmatch on RECTABLE.recordid = recordmatch.recordid " … … void Scheduler::AddNotListed(void) { 4768 4773 4769 4774 RecordingInfo *p = new RecordingInfo( 4770 4775 result.value(0).toString(), // Title 4776 result.value(28).toString(), // Title Sort 4771 4777 (sor) ? result.value(1).toString() : QString(), // Subtitle 4778 (sor) ? result.value(29).toString() : QString(), // Subtitle Sort 4772 4779 (sor) ? result.value(2).toString() : QString(), // Description 4773 4780 result.value(3).toUInt(), // Season 4774 4781 result.value(4).toUInt(), // Episode … … void Scheduler::GetAllScheduled(RecList &proglist, SchedSortColumn sortBy, 4865 4872 " record.recordid, record.type, " // 20,21 4866 4873 " record.dupin, record.dupmethod, " // 22,23 4867 4874 " record.findid, " // 24 4868 " channel.commmethod " // 25 4875 " channel.commmethod, " // 25 4876 " record.sorttitle, record.sortsubtitle " // 26,27 4869 4877 "FROM record " 4870 4878 "LEFT JOIN channel ON channel.callsign = record.station " 4871 4879 "GROUP BY recordid " … … void Scheduler::GetAllScheduled(RecList &proglist, SchedSortColumn sortBy, 4897 4905 endts = startts; 4898 4906 4899 4907 proglist.push_back(new RecordingInfo( 4900 result.value(0).toString(), result.value(1).toString(), 4908 result.value(0).toString(), result.value(26).toString(), 4909 result.value(1).toString(), result.value(27).toString(), 4901 4910 result.value(2).toString(), result.value(3).toUInt(), 4902 4911 result.value(4).toUInt(), result.value(5).toString(), 4903 4912 -
mythtv/programs/mythbackend/services/video.cpp
diff --git a/mythtv/programs/mythbackend/services/video.cpp b/mythtv/programs/mythbackend/services/video.cpp index 7f977c2..00c4305 100644
a b bool Video::AddVideo( const QString &sFileName, 347 347 hash = ""; 348 348 } 349 349 350 VideoMetadata newFile(sFileName, hash,350 VideoMetadata newFile(sFileName, QString(), hash, 351 351 VIDEO_TRAILER_DEFAULT, 352 352 VIDEO_COVERFILE_DEFAULT, 353 353 VIDEO_SCREENSHOT_DEFAULT, 354 354 VIDEO_BANNER_DEFAULT, 355 355 VIDEO_FANART_DEFAULT, 356 VideoMetadata::FilenameToMeta(sFileName, 1), 357 VideoMetadata::FilenameToMeta(sFileName, 4), 356 QString(), QString(), QString(), QString(), 358 357 QString(), VIDEO_YEAR_DEFAULT, 359 358 QDate::fromString("0000-00-00","YYYY-MM-DD"), 360 359 VIDEO_INETREF_DEFAULT, 0, QString(), 361 360 VIDEO_DIRECTOR_DEFAULT, QString(), VIDEO_PLOT_DEFAULT, 362 361 0.0, VIDEO_RATING_DEFAULT, 0, 0, 363 VideoMetadata::FilenameToMeta(sFileName, 2).toInt(), 364 VideoMetadata::FilenameToMeta(sFileName, 3).toInt(), 362 0, 0, 365 363 MythDate::current().date(), 0, 366 364 ParentalLevel::plLowest); 367 365 -
mythtv/programs/mythfrontend/globalsettings.cpp
diff --git a/mythtv/programs/mythfrontend/globalsettings.cpp b/mythtv/programs/mythfrontend/globalsettings.cpp index 4e53990..78b7852 100644
a b ChannelGroupSettings::ChannelGroupSettings() : 2756 2756 addTarget("1", new VerticalConfigurationGroup(true,false)); 2757 2757 }; 2758 2758 2759 static HostCheckBox *SortIgnoreCase() 2760 { 2761 HostCheckBox *gc = new HostCheckBox("SortIgnoreCase"); 2762 gc->setLabel(GeneralSettings::tr("Ignore case when sorting")); 2763 gc->setValue(true); 2764 gc->setHelpText(GeneralSettings::tr("If enabled, all sorting will be case-insensitive.")); 2765 return gc; 2766 } 2767 2768 static HostCheckBox *SortIgnorePrefixes() 2769 { 2770 HostCheckBox *gc = new HostCheckBox("SortIgnorePrefixes"); 2771 2772 gc->setLabel(GeneralSettings::tr("Ignore prefixes when sorting")); 2773 gc->setValue(true); 2774 gc->setHelpText(GeneralSettings::tr("If enabled, video listings will " 2775 "ignore common prefixes (The, A, An) when " 2776 "sorting show names.")); 2777 return gc; 2778 } 2779 2780 static HostLineEdit *SortIgnorePrefixExceptions() 2781 { 2782 HostLineEdit *gc = new HostLineEdit("SortIgnorePrefixExceptions"); 2783 2784 gc->setLabel(MainGeneralSettings::tr("Names exempt from prefix removal")); 2785 gc->setValue(""); 2786 gc->setHelpText(MainGeneralSettings::tr("When stripping common prefixes (The, A, An) " 2787 "from filenames, this list of names " 2788 "will be exempt from that process. " 2789 "Enter multiple names separated by ';'.")); 2790 return gc; 2791 } 2792 2793 2759 2794 // General RecPriorities settings 2760 2795 2761 2796 static GlobalComboBox *GRSchedOpenEnd() … … MainGeneralSettings::MainGeneralSettings() 3863 3898 general->setLabel(tr("General")); 3864 3899 general->addChild(UseVirtualKeyboard()); 3865 3900 general->addChild(ScreenShotPath()); 3901 general->addChild(SortIgnoreCase()); 3902 general->addChild(SortIgnorePrefixes()); 3903 general->addChild(SortIgnorePrefixExceptions()); 3866 3904 addChild(general); 3867 3905 3868 3906 VerticalConfigurationGroup *media = -
mythtv/programs/mythfrontend/main.cpp
diff --git a/mythtv/programs/mythfrontend/main.cpp b/mythtv/programs/mythfrontend/main.cpp index f4ed3f2..ef12639 100644
a b static int internal_play_media(const QString &mrl, const QString &plot, 1168 1168 } 1169 1169 1170 1170 ProgramInfo *pginfo = new ProgramInfo( 1171 mrl, plot, title, subtitle, director, season, episode,1172 inetref, lenMins, (year.toUInt()) ? year.toUInt() : 1900,1173 id);1171 mrl, plot, title, QString(), subtitle, QString(), 1172 director, season, episode, inetref, lenMins, 1173 (year.toUInt()) ? year.toUInt() : 1900, id); 1174 1174 1175 1175 pginfo->SetProgramInfoType(pginfo->DiscoverProgramInfoType()); 1176 1176 -
mythtv/programs/mythfrontend/playbackbox.cpp
diff --git a/mythtv/programs/mythfrontend/playbackbox.cpp b/mythtv/programs/mythfrontend/playbackbox.cpp index fea8033..26427a4 100644
a b static PlaybackBox::ViewMask m_viewMaskToggle(PlaybackBox::ViewMask mask, 222 222 223 223 static QString construct_sort_title( 224 224 QString title, PlaybackBox::ViewMask viewmask, 225 PlaybackBox::ViewTitleSort titleSort, int recpriority, 226 const QRegExp &prefixes) 225 PlaybackBox::ViewTitleSort sortType, int recpriority) 227 226 { 228 227 if (title.isEmpty()) 229 228 return title; 230 229 231 230 QString sTitle = title; 232 231 233 sTitle.remove(prefixes);234 232 if (viewmask == PlaybackBox::VIEW_TITLES && 235 titleSort== PlaybackBox::TitleSortRecPriority)233 sortType == PlaybackBox::TitleSortRecPriority) 236 234 { 237 235 // Also incorporate recpriority (reverse numeric sort). In 238 236 // case different episodes of a recording schedule somehow … … void * PlaybackBox::RunPlaybackBox(void * player, bool showTV) 393 391 PlaybackBox::PlaybackBox(MythScreenStack *parent, QString name, 394 392 TV *player, bool showTV) 395 393 : ScheduleCommon(parent, name), 396 m_prefixes(QObject::tr("^(The |A |An )")),397 394 m_titleChaff(" \\(.*\\)$"), 398 395 // UI variables 399 396 m_recgroupList(NULL), … … bool PlaybackBox::UpdateUILists(void) 1757 1754 (pRecgroup != "LiveTV" || m_recGroup == "LiveTV")) 1758 1755 { 1759 1756 sTitle = construct_sort_title( 1760 p->Get Title(), m_viewMask, titleSort,1761 p->GetRecordingPriority() , m_prefixes);1757 p->GetSortTitle(), m_viewMask, titleSort, 1758 p->GetRecordingPriority()); 1762 1759 sTitle = sTitle.toLower(); 1763 1760 1764 1761 if (!sortedList.contains(sTitle)) -
mythtv/programs/mythfrontend/playbackbox.h
diff --git a/mythtv/programs/mythfrontend/playbackbox.h b/mythtv/programs/mythfrontend/playbackbox.h index 6b7e144..07ee0e4 100644
a b class PlaybackBox : public ScheduleCommon 338 338 QString extract_commflag_state(const ProgramInfo &pginfo); 339 339 340 340 341 QRegExp m_prefixes; ///< prefixes to be ignored when sorting342 341 QRegExp m_titleChaff; ///< stuff to remove for search rules 343 342 344 343 MythUIButtonList *m_recgroupList; -
mythtv/programs/mythfrontend/proglist.cpp
diff --git a/mythtv/programs/mythfrontend/proglist.cpp b/mythtv/programs/mythfrontend/proglist.cpp index ccdb95a..cb988c5 100644
a b class plTitleSort : public plCompare 1057 1057 public: 1058 1058 bool operator()(const ProgramInfo *a, const ProgramInfo *b) 1059 1059 { 1060 if (a->sortTitle != b->sortTitle) 1061 return (a->sortTitle < b->sortTitle); 1060 if (a->GetSortTitle() != b->GetSortTitle()) 1061 return (a->GetSortTitle() < b->GetSortTitle()); 1062 if (a->GetSortSubtitle() != b->GetSortSubtitle()) 1063 return (a->GetSortSubtitle() < b->GetSortSubtitle()); 1062 1064 1063 1065 if (a->GetRecordingStatus() == b->GetRecordingStatus()) 1064 1066 return a->GetScheduledStartTime() < b->GetScheduledStartTime(); … … class plPrevTitleSort : public plCompare 1090 1092 1091 1093 bool operator()(const ProgramInfo *a, const ProgramInfo *b) 1092 1094 { 1093 if (a->sortTitle != b->sortTitle) 1094 return (a->sortTitle < b->sortTitle); 1095 if (a->GetSortTitle() != b->GetSortTitle()) 1096 return (a->GetSortTitle() < b->GetSortTitle()); 1097 if (a->GetSortSubtitle() != b->GetSortSubtitle()) 1098 return (a->GetSortSubtitle() < b->GetSortSubtitle()); 1095 1099 1096 1100 if (a->GetProgramID() != b->GetProgramID()) 1097 1101 return a->GetProgramID() < b->GetProgramID(); … … void ProgLister::FillItemList(bool restorePosition, bool updateDisp) 1390 1394 LoadFromProgram(m_itemList, where, bindings, m_schedList); 1391 1395 } 1392 1396 1393 const QRegExp prefixes(1394 tr("^(The |A |An )",1395 "Regular Expression for what to ignore when sorting"));1396 for (uint i = 0; i < m_itemList.size(); i++)1397 {1398 ProgramInfo *s = m_itemList[i];1399 if (s)1400 {1401 s->sortTitle = (m_type == plTitle) ? s->GetSubtitle() : s->GetTitle();1402 s->sortTitle.remove(prefixes);1403 }1404 }1405 1406 1397 if (m_type == plNewListings || m_titleSort) 1407 1398 { 1408 1399 SortList(kTitleSort, m_reverseSort); … … void ProgLister::FillItemList(bool restorePosition, bool updateDisp) 1413 1404 ProgramList::iterator it = m_itemList.begin(); 1414 1405 while (it != m_itemList.end()) 1415 1406 { 1416 if ((*it)-> sortTitle!= curtitle)1407 if ((*it)->GetSortTitle() != curtitle) 1417 1408 { 1418 curtitle = (*it)-> sortTitle;1409 curtitle = (*it)->GetSortTitle(); 1419 1410 ++it; 1420 1411 } 1421 1412 else -
mythtv/programs/mythfrontend/programrecpriority.cpp
diff --git a/mythtv/programs/mythfrontend/programrecpriority.cpp b/mythtv/programs/mythfrontend/programrecpriority.cpp index dc8c5fd..923e658 100644
a b class TitleSort 133 133 bool operator()(const ProgramRecPriorityInfo *a, 134 134 const ProgramRecPriorityInfo *b) const 135 135 { 136 if (a-> sortTitle != b->sortTitle)136 if (a->GetSortTitle() != b->GetSortTitle()) 137 137 { 138 138 if (m_reverse) 139 return (a-> sortTitle > b->sortTitle);139 return (a->GetSortTitle() > b->GetSortTitle()); 140 140 else 141 return (a->sortTitle < b->sortTitle); 141 return (a->GetSortTitle() < b->GetSortTitle()); 142 } 143 144 if (a->GetSortSubtitle() != b->GetSortSubtitle()) 145 { 146 if (m_reverse) 147 return (a->GetSortSubtitle() > b->GetSortSubtitle()); 148 else 149 return (a->GetSortSubtitle() < b->GetSortSubtitle()); 142 150 } 143 151 144 152 int finalA = a->GetRecordingPriority(); … … class ProgramCountSort 288 296 return recCountA > recCountB; 289 297 } 290 298 299 if (a->GetSortTitle() != b->GetSortTitle()) 300 { 301 if (m_reverse) 302 return (a->GetSortTitle() > b->GetSortTitle()); 303 else 304 return (a->GetSortTitle() < b->GetSortTitle()); 305 } 306 291 307 if (m_reverse) 292 return (a-> sortTitle > b->sortTitle);308 return (a->GetSortSubtitle() > b->GetSortSubtitle()); 293 309 else 294 return (a-> sortTitle < b->sortTitle);310 return (a->GetSortSubtitle() < b->GetSortSubtitle()); 295 311 } 296 312 297 313 private: … … class ProgramRecCountSort 327 343 return countA > countB; 328 344 } 329 345 346 if (a->GetSortTitle() != b->GetSortTitle()) 347 { 348 if (m_reverse) 349 return (a->GetSortTitle() > b->GetSortTitle()); 350 else 351 return (a->GetSortTitle() < b->GetSortTitle()); 352 } 353 330 354 if (m_reverse) 331 return (a-> sortTitle > b->sortTitle);355 return (a->GetSortSubtitle() > b->GetSortSubtitle()); 332 356 else 333 return (a-> sortTitle < b->sortTitle);357 return (a->GetSortSubtitle() < b->GetSortSubtitle()); 334 358 } 335 359 336 360 private: … … class ProgramLastRecordSort 356 380 return lastRecA > lastRecB; 357 381 } 358 382 383 if (a->GetSortTitle() != b->GetSortTitle()) 384 { 385 if (m_reverse) 386 return (a->GetSortTitle() > b->GetSortTitle()); 387 else 388 return (a->GetSortTitle() < b->GetSortTitle()); 389 } 390 359 391 if (m_reverse) 360 return (a-> sortTitle > b->sortTitle);392 return (a->GetSortSubtitle() > b->GetSortSubtitle()); 361 393 else 362 return (a-> sortTitle < b->sortTitle);394 return (a->GetSortSubtitle() < b->GetSortSubtitle()); 363 395 } 364 396 365 397 private: … … class ProgramAvgDelaySort 385 417 return avgA < avgB; 386 418 } 387 419 420 if (a->GetSortTitle() != b->GetSortTitle()) 421 { 422 if (m_reverse) 423 return (a->GetSortTitle() > b->GetSortTitle()); 424 else 425 return (a->GetSortTitle() < b->GetSortTitle()); 426 } 427 388 428 if (m_reverse) 389 return (a-> sortTitle > b->sortTitle);429 return (a->GetSortSubtitle() > b->GetSortSubtitle()); 390 430 else 391 return (a-> sortTitle < b->sortTitle);431 return (a->GetSortSubtitle() < b->GetSortSubtitle()); 392 432 } 393 433 394 434 private: … … void ProgramRecPriority::scheduleChanged(int recid) 935 975 ProgramRecPriorityInfo progInfo; 936 976 progInfo.SetRecordingRuleID(record.m_recordID); 937 977 progInfo.SetRecordingRuleType(record.m_type); 938 progInfo.SetTitle(record.m_title); 978 progInfo.SetTitle(record.m_title, record.m_sortTitle); 979 progInfo.SetSubtitle(record.m_subtitle, record.m_sortSubtitle); 939 980 progInfo.SetCategory(record.m_category); 940 981 progInfo.SetRecordingPriority(record.m_recPriority); 941 982 progInfo.recType = record.m_type; 942 progInfo.sortTitle = record.m_title;943 983 progInfo.recstatus = record.m_isInactive ? 944 984 RecStatus::Inactive : RecStatus::Unknown; 945 985 progInfo.profile = record.m_recProfile; … … void ProgramRecPriority::FillList(void) 1177 1217 // it all at once than once per program) 1178 1218 1179 1219 MSqlQuery result(MSqlQuery::InitCon()); 1180 result.prepare("SELECT recordid, title, chanid, starttime, startdate, " 1181 "type, inactive, last_record, avg_delay, profile " 1220 result.prepare("SELECT recordid, title, chanid, starttime, startdate, " // 0-4 1221 "type, inactive, last_record, avg_delay, profile, " // 5-9 1222 "subtitle, sorttitle, sortsubtitle " // 10-12 1182 1223 "FROM record;"); 1183 1224 1184 1225 if (!result.exec()) … … void ProgramRecPriority::FillList(void) 1191 1232 do { 1192 1233 uint recordid = result.value(0).toUInt(); 1193 1234 QString title = result.value(1).toString(); 1235 QString sortTitle = result.value(10).toString(); 1236 QString subtitle = result.value(11).toString(); 1237 QString sortSubtitle = result.value(12).toString(); 1194 1238 QString chanid = result.value(2).toString(); 1195 1239 QString tempTime = result.value(3).toString(); 1196 1240 QString tempDate = result.value(4).toString(); … … void ProgramRecPriority::FillList(void) 1208 1252 { 1209 1253 ProgramRecPriorityInfo *progInfo = &(*it); 1210 1254 1211 progInfo->sortTitle = progInfo->title;1212 progInfo->sortTitle.remove(QRegExp(tr("^(The |A |An )")));1213 1214 1255 progInfo->recType = recType; 1215 1256 progInfo->matchCount = 1216 1257 m_listMatch[progInfo->GetRecordingRuleID()]; -
mythtv/programs/mythfrontend/videofilter.cpp
diff --git a/mythtv/programs/mythfrontend/videofilter.cpp b/mythtv/programs/mythfrontend/videofilter.cpp index 2e82927..86b9e0b 100644
a b bool VideoFilterSettings::matches_filter(const VideoMetadata &mdata) const 389 389 390 390 /// Compares two VideoMetadata instances 391 391 bool VideoFilterSettings::meta_less_than(const VideoMetadata &lhs, 392 const VideoMetadata &rhs, 393 bool sort_ignores_case) const 392 const VideoMetadata &rhs) const 394 393 { 395 394 bool ret = false; 396 395 switch (orderby) 397 396 { 398 397 case kOrderByTitle: 399 398 { 400 VideoMetadata::SortKey lhs_key; 401 VideoMetadata::SortKey rhs_key; 402 if (lhs.HasSortKey() && rhs.HasSortKey()) 403 { 404 lhs_key = lhs.GetSortKey(); 405 rhs_key = rhs.GetSortKey(); 406 } 407 else 408 { 409 lhs_key = VideoMetadata::GenerateDefaultSortKey(lhs, 410 sort_ignores_case); 411 rhs_key = VideoMetadata::GenerateDefaultSortKey(rhs, 412 sort_ignores_case); 413 } 414 ret = lhs_key < rhs_key; 399 ret = lhs.sortBefore(rhs); 415 400 break; 416 401 } 417 402 case kOrderBySeasonEp: … … bool VideoFilterSettings::meta_less_than(const VideoMetadata &lhs, 423 408 && (lhs.GetEpisode() == 0) 424 409 && (rhs.GetEpisode() == 0)) 425 410 { 426 VideoMetadata::SortKey lhs_key; 427 VideoMetadata::SortKey rhs_key; 428 if (lhs.HasSortKey() && rhs.HasSortKey()) 429 { 430 lhs_key = lhs.GetSortKey(); 431 rhs_key = rhs.GetSortKey(); 432 } 433 else 434 { 435 lhs_key = VideoMetadata::GenerateDefaultSortKey(lhs, 436 sort_ignores_case); 437 rhs_key = VideoMetadata::GenerateDefaultSortKey(rhs, 438 sort_ignores_case); 439 } 440 ret = lhs_key < rhs_key; 411 ret = lhs.sortBefore(rhs); 441 412 } 442 413 else if ((lhs.GetSeason() == rhs.GetSeason()) 443 414 && (lhs.GetTitle() == rhs.GetTitle())) … … bool VideoFilterSettings::meta_less_than(const VideoMetadata &lhs, 463 434 } 464 435 case kOrderByFilename: 465 436 { 466 QString lhsfn(sort_ignores_case ? 467 lhs.GetFilename().toLower() : lhs.GetFilename()); 468 QString rhsfn(sort_ignores_case ? 469 rhs.GetFilename().toLower() : rhs.GetFilename()); 437 QString lhsfn = lhs.GetSortFilename(); 438 QString rhsfn = rhs.GetSortFilename(); 470 439 ret = naturalCompare(lhsfn, rhsfn) < 0; 471 440 break; 472 441 } -
mythtv/programs/mythfrontend/videofilter.h
diff --git a/mythtv/programs/mythfrontend/videofilter.h b/mythtv/programs/mythfrontend/videofilter.h index d518abf..4a6a171 100644
a b class VideoFilterSettings 48 48 VideoFilterSettings &operator=(const VideoFilterSettings &rhs); 49 49 50 50 bool matches_filter(const VideoMetadata &mdata) const; 51 bool meta_less_than(const VideoMetadata &lhs, const VideoMetadata &rhs, 52 bool sort_ignores_case) const; 51 bool meta_less_than(const VideoMetadata &lhs, const VideoMetadata &rhs) const; 53 52 54 53 void saveAsDefault(); 55 54 … … class VideoFilterSettings 190 189 const QRegExp re_season; 191 190 const QRegExp re_date; 192 191 193 194 192 unsigned int m_changed_state; 195 193 }; 196 194 -
mythtv/programs/mythfrontend/videolist.cpp
diff --git a/mythtv/programs/mythfrontend/videolist.cpp b/mythtv/programs/mythfrontend/videolist.cpp index 7bcbda0..a80b0dc 100644
a b QString TreeNodeData::GetPrefix(void) const 149 149 /// metadata sort function 150 150 struct metadata_sort 151 151 { 152 metadata_sort(const VideoFilterSettings &vfs, bool sort_ignores_case) : 153 m_vfs(vfs), m_sic(sort_ignores_case) {} 152 metadata_sort(const VideoFilterSettings &vfs) : m_vfs(vfs) {} 154 153 155 154 bool operator()(const VideoMetadata *lhs, const VideoMetadata *rhs) 156 155 { 157 return m_vfs.meta_less_than(*lhs, *rhs , m_sic);156 return m_vfs.meta_less_than(*lhs, *rhs); 158 157 } 159 158 160 159 bool operator()(const smart_meta_node &lhs, const smart_meta_node &rhs) 161 160 { 162 return m_vfs.meta_less_than(*(lhs->getData()), *(rhs->getData()), 163 m_sic); 161 return m_vfs.meta_less_than(*(lhs->getData()), *(rhs->getData())); 164 162 } 165 163 166 164 private: 167 165 const VideoFilterSettings &m_vfs; 168 bool m_sic;169 166 }; 170 167 171 168 struct metadata_path_sort 172 169 { 173 explicit metadata_path_sort( bool ignore_case) : m_ignore_case(ignore_case) {}170 explicit metadata_path_sort(void) {} 174 171 175 172 bool operator()(const VideoMetadata &lhs, const VideoMetadata &rhs) 176 173 { … … struct metadata_path_sort 184 181 185 182 bool operator()(const smart_dir_node &lhs, const smart_dir_node &rhs) 186 183 { 187 return sort(lhs->get Path(), rhs->getPath());184 return sort(lhs->getSortPath(), rhs->getSortPath()); 188 185 } 189 186 190 187 private: 191 188 bool sort(const VideoMetadata *lhs, const VideoMetadata *rhs) 192 189 { 193 return sort(lhs->Get Filename(), rhs->GetFilename());190 return sort(lhs->GetSortFilename(), rhs->GetSortFilename()); 194 191 } 195 192 196 193 bool sort(const QString &lhs, const QString &rhs) 197 194 { 198 QString lhs_comp(lhs); 199 QString rhs_comp(rhs); 200 if (m_ignore_case) 201 { 202 lhs_comp = lhs_comp.toLower(); 203 rhs_comp = rhs_comp.toLower(); 204 } 205 return naturalCompare(lhs_comp, rhs_comp) < 0; 195 return naturalCompare(lhs, rhs) < 0; 206 196 } 207 208 bool m_ignore_case;209 197 }; 210 198 211 199 static QString path_to_node_name(const QString &path) … … void VideoListImp::sort_view_data(bool flat_list) 751 739 if (flat_list) 752 740 { 753 741 sort(m_metadata_view_flat.begin(), m_metadata_view_flat.end(), 754 metadata_sort(m_video_filter , true));742 metadata_sort(m_video_filter)); 755 743 } 756 744 else 757 745 { 758 m_metadata_view_tree.sort(metadata_path_sort(true), 759 metadata_sort(m_video_filter, 760 true)); 746 m_metadata_view_tree.sort(metadata_path_sort(), 747 metadata_sort(m_video_filter)); 761 748 } 762 749 } 763 750 … … void VideoListImp::buildGroupList(metadata_list_type whence) 811 798 transform(m_metadata.getList().begin(), m_metadata.getList().end(), 812 799 mli, to_metadata_ptr()); 813 800 814 metadata_path_sort mps (true);801 metadata_path_sort mps = metadata_path_sort(); 815 802 sort(mlist.begin(), mlist.end(), mps); 816 803 817 804 typedef map<QString, meta_dir_node *> group_to_node_map; … … void VideoListImp::buildTVList(void) 944 931 transform(m_metadata.getList().begin(), m_metadata.getList().end(), 945 932 mli, to_metadata_ptr()); 946 933 947 metadata_path_sort mps (true);934 metadata_path_sort mps = metadata_path_sort(); 948 935 sort(mlist.begin(), mlist.end(), mps); 949 936 950 937 meta_dir_node *video_root = &m_metadata_tree; … … void VideoListImp::buildDbList() 990 977 991 978 // print_meta_list(mlist); 992 979 993 metadata_path_sort mps (true);980 metadata_path_sort mps = metadata_path_sort(); 994 981 sort(mlist.begin(), mlist.end(), mps); 995 982 996 983 // TODO: break out the prefix in the DB so this isn't needed … … void VideoListImp::update_meta_view(bool flat_list) 1145 1132 1146 1133 m_metadata_view_tree.clear(); 1147 1134 1148 // a big punt on setting the sort key1149 // TODO: put this in the DB, half the time in this function is spent1150 // doing this.1151 for (metadata_list::const_iterator si = m_metadata.getList().begin();1152 si != m_metadata.getList().end(); ++si)1153 {1154 if (!(*si)->HasSortKey())1155 {1156 VideoMetadata::SortKey skey =1157 VideoMetadata::GenerateDefaultSortKey(*(*si), true);1158 (*si)->SetSortKey(skey);1159 }1160 }1161 1162 1135 if (flat_list) 1163 1136 { 1164 1137 for (metadata_list::const_iterator p = m_metadata.getList().begin(); -
mythtv/programs/mythpreviewgen/main.cpp
diff --git a/mythtv/programs/mythpreviewgen/main.cpp b/mythtv/programs/mythpreviewgen/main.cpp index 87ea784..36fface 100644
a b int preview_helper(uint chanid, QDateTime starttime, 106 106 return GENERIC_EXIT_NOT_OK; 107 107 } 108 108 pginfo = new ProgramInfo( 109 infile, ""/*plot*/, ""/*title*/, ""/*s ubtitle*/, ""/*director*/,110 0/*season*/, 0/*episode*/, ""/*inetref*/, 120/*length_in_minutes*/,111 1895/*year*/, ""/*id*/);109 infile, ""/*plot*/, ""/*title*/, ""/*sortTitle*/, ""/*subtitle*/, 110 ""/*sortSubtitle*/, ""/*director*/, 0/*season*/, 0/*episode*/, 111 ""/*inetref*/, 120/*length_in_minutes*/, 1895/*year*/, ""/*id*/); 112 112 } 113 113 else 114 114 {
