|
MythTV
0.25-pre
|
00001 #include <mythcontext.h> 00002 #include "treebuilders.h" 00003 00004 typedef struct { 00005 QString field; 00006 MetadataPtrList list; 00007 } Branch; 00008 00009 typedef struct { 00010 QString testStr; 00011 QString dispStr; 00012 } FieldSplitInfo; 00013 00014 // arrays for different level of granularity in the tree 00015 // choose between them by using a global setting. In an ideal 00016 // world we would generate these dynamically, but that turned 00017 // into more change than it was worth 00018 static FieldSplitInfo splitArray4[] = 00019 { 00020 {"!\"#$%&'()*+,-./:;<=>?@[\\]^_{|}~", " (...)"}, 00021 {"01234", " (0 1 2 3 4)" }, 00022 {"56789", " (5 6 7 8 9)" }, 00023 {"ABCDE", " (A B C D E)"}, 00024 {"FGHIJ", " (F G H I J)"}, 00025 {"KLMNO", " (K L M N O)"}, 00026 {"PQRST", " (P Q R S T)"}, 00027 {"UVWXYZ", " (U V W X Y Z)"} 00028 }; 00029 00030 static FieldSplitInfo splitArray16[] = 00031 { 00032 {"!\"#$%&'()*+,-./:;<=>?@[\\]^_{|}~", " (...)"}, 00033 {"01234", " (0 1 2 3 4)" }, 00034 {"56789", " (5 6 7 8 9)" }, 00035 {"AB", " (A B)"}, 00036 {"CD", " (C D)"}, 00037 {"EF", " (E F)"}, 00038 {"GH", " (G H)"}, 00039 {"IJ", " (I J)"}, 00040 {"KL", " (K L)"}, 00041 {"MN", " (M N)"}, 00042 {"OP", " (O P)"}, 00043 {"QR", " (Q R)"}, 00044 {"ST", " (S T)"}, 00045 {"UV", " (U V)"}, 00046 {"WX", " (W X)"}, 00047 {"YZ", " (Y Z)"} 00048 }; 00049 00050 static FieldSplitInfo splitArray29[] = 00051 { 00052 {"!\"#$%&'()*+,-./:;<=>?@[\\]^_{|}~", " (...)"}, 00053 {"01234", " (0 1 2 3 4)" }, 00054 {"56789", " (5 6 7 8 9)" }, 00055 {"A", " A"}, 00056 {"B", " B"}, 00057 {"C", " C"}, 00058 {"D", " D"}, 00059 {"E", " E"}, 00060 {"F", " F"}, 00061 {"G", " G"}, 00062 {"H", " H"}, 00063 {"I", " I"}, 00064 {"J", " J"}, 00065 {"K", " K"}, 00066 {"L", " L"}, 00067 {"M", " M"}, 00068 {"N", " N"}, 00069 {"O", " O"}, 00070 {"P", " P"}, 00071 {"Q", " Q"}, 00072 {"R", " R"}, 00073 {"S", " S"}, 00074 {"T", " T"}, 00075 {"U", " U"}, 00076 {"V", " V"}, 00077 {"W", " W"}, 00078 {"X", " X"}, 00079 {"Y", " Y"}, 00080 {"Z", " Z"} 00081 }; 00082 00083 const int kSplitArray4_Max = sizeof splitArray4 / sizeof splitArray4[0]; 00084 const int kSplitArray16_Max = sizeof splitArray16 / sizeof splitArray16[0]; 00085 const int kSplitArray29_Max = sizeof splitArray29 / sizeof splitArray29[0]; 00086 00087 static QString thePrefix = "the "; 00088 00089 MusicTreeBuilder::MusicTreeBuilder() 00090 { 00091 m_depth = -1; 00092 } 00093 00094 MusicTreeBuilder::~MusicTreeBuilder() 00095 { 00096 } 00097 00098 void MusicTreeBuilder::makeTree(MusicNode *root, const MetadataPtrList &metas) 00099 { 00100 m_depth++; 00101 00102 typedef QMap<QString, Branch*> BranchMap; 00103 BranchMap branches; 00104 00105 MetadataPtrList::const_iterator it = metas.begin(); 00106 for (; it != metas.end(); ++it) 00107 { 00108 Metadata *meta = *it; 00109 if (isLeafDone(meta)) 00110 { 00111 root->addLeaf(meta); 00112 } 00113 else 00114 { 00115 QString field = getField(meta); 00116 QString field_key = field.toLower(); 00117 00118 if (field_key.left(4) == thePrefix) 00119 field_key = field_key.mid(4); 00120 00121 Branch *branch = branches[field_key]; 00122 if (branch == NULL) 00123 { 00124 branch = new Branch; 00125 branch->field = field; 00126 branches[field_key] = branch; 00127 } 00128 branch->list.append(meta); 00129 } 00130 } 00131 00132 for (BranchMap::iterator it = branches.begin(); it != branches.end(); ++it) 00133 { 00134 Branch *branch = *it; 00135 MusicNode *sub_node = createNode(branch->field); 00136 root->addChild(sub_node); 00137 makeTree(sub_node, branch->list); 00138 delete branch; 00139 } 00140 00141 m_depth--; 00142 } 00143 00144 class MusicFieldTreeBuilder : public MusicTreeBuilder 00145 { 00146 public: 00147 MusicFieldTreeBuilder(const QString &paths) 00148 { 00149 m_paths = paths.split(' ', QString::SkipEmptyParts); 00150 } 00151 00152 ~MusicFieldTreeBuilder() 00153 { 00154 } 00155 00156 void makeTree(MusicNode *root, const MetadataPtrList &metas) 00157 { 00158 if (getDepth() + 2 >= m_paths.size()) 00159 { 00160 root->setLeaves(metas); 00161 return; 00162 } 00163 00164 MusicTreeBuilder::makeTree(root, metas); 00165 } 00166 00167 protected: 00168 MusicNode *createNode(const QString &title) 00169 { 00170 return new MusicNode(title, m_paths[getDepth()]); 00171 } 00172 00173 bool isLeafDone(Metadata *) 00174 { 00175 return false; 00176 } 00177 00178 QString getField(Metadata *meta) 00179 { 00180 QString field = m_paths[getDepth()]; 00181 00182 if (field == "splitartist1" || 00183 field == "splitartist") 00184 { 00185 return getSplitField(meta, field); 00186 } 00187 00188 QString data; 00189 meta->getField(field, &data); 00190 return data; 00191 } 00192 00193 private: 00194 QStringList m_paths; 00195 QMap<QChar, QString> m_split_map; 00196 00197 QString getSplitField(Metadata *meta, const QString &field) 00198 { 00199 QString firstchar_str = meta->FormatArtist().trimmed(); 00200 00201 if (firstchar_str.left(4).toLower() == thePrefix) 00202 firstchar_str = firstchar_str.mid(4,1).toUpper(); 00203 else 00204 firstchar_str = firstchar_str.left(1).toUpper(); 00205 00206 QChar firstchar = firstchar_str[0]; 00207 QString split = m_split_map[firstchar]; 00208 00209 if (split.isEmpty()) 00210 { 00211 if (field == "splitartist1") 00212 { 00213 split = QObject::tr("Artists") + " (" + firstchar + ")"; 00214 m_split_map[firstchar] = split; 00215 } 00216 else 00217 { 00218 QString artistGrouping = gCoreContext->GetSetting("ArtistTreeGroups", "none"); 00219 if (artistGrouping == "2") 00220 { 00221 int split_max = kSplitArray29_Max; 00222 FieldSplitInfo *splits = splitArray29; 00223 00224 for(int i = 0; i < split_max; i++) 00225 { 00226 if (splits[i].testStr.contains(firstchar)) 00227 { 00228 split = QObject::tr("Artists") + splits[i].dispStr; 00229 m_split_map[firstchar] = split; 00230 break; 00231 } 00232 } 00233 } 00234 else 00235 { 00236 if (artistGrouping == "1") 00237 { 00238 int split_max = kSplitArray16_Max; 00239 FieldSplitInfo *splits = splitArray16; 00240 00241 for(int i = 0; i < split_max; i++) 00242 { 00243 if (splits[i].testStr.contains(firstchar)) 00244 { 00245 split = QObject::tr("Artists") + splits[i].dispStr; 00246 m_split_map[firstchar] = split; 00247 break; 00248 } 00249 } 00250 } 00251 else 00252 { 00253 // old behaviour is the default 00254 int split_max = kSplitArray4_Max; 00255 FieldSplitInfo *splits = splitArray4; 00256 00257 for(int i = 0; i < split_max; i++) 00258 { 00259 if (splits[i].testStr.contains(firstchar)) 00260 { 00261 split = QObject::tr("Artists") + splits[i].dispStr; 00262 m_split_map[firstchar] = split; 00263 break; 00264 } 00265 } 00266 } 00267 } 00268 } 00269 } 00270 00271 if (split.isEmpty()) 00272 { 00273 split = QObject::tr("Artists") + " (" + firstchar + ")"; 00274 m_split_map[firstchar] = split; 00275 } 00276 00277 return split; 00278 } 00279 }; 00280 00281 class MusicDirectoryTreeBuilder : public MusicTreeBuilder 00282 { 00283 public: 00284 MusicDirectoryTreeBuilder() 00285 { 00286 m_startdir = gCoreContext->GetSetting("MusicLocation"); 00287 } 00288 00289 ~MusicDirectoryTreeBuilder() 00290 { 00291 for (MetaMap::iterator it = m_map.begin(); it != m_map.end(); ++it) 00292 delete *it; 00293 } 00294 00295 protected: 00296 MusicNode *createNode(const QString &title) 00297 { 00298 return new MusicNode(title, "directory"); 00299 } 00300 00301 bool isLeafDone(Metadata *meta) 00302 { 00303 return getDepth() + 1 >= getPathsForMeta(meta)->size(); 00304 } 00305 00306 QString getField(Metadata *meta) 00307 { 00308 return getPathsForMeta(meta)->operator[](getDepth()); 00309 } 00310 00311 private: 00312 inline QString getStartdir(void) { return m_startdir; } 00313 00314 QStringList* getPathsForMeta(Metadata *meta) 00315 { 00316 QStringList *paths = m_map[meta]; 00317 00318 if (paths) 00319 return paths; 00320 00321 QString filename = meta->Filename().remove(0, getStartdir().length()); 00322 paths = new QStringList(filename.split('/')); 00323 m_map[meta] = paths; 00324 00325 return paths; 00326 } 00327 00328 typedef QMap<Metadata*,QStringList*> MetaMap; 00329 MetaMap m_map; 00330 QString m_startdir; 00331 00332 }; 00333 00334 MusicTreeBuilder *MusicTreeBuilder::createBuilder(const QString &paths) 00335 { 00336 if (paths == "directory") 00337 return new MusicDirectoryTreeBuilder(); 00338 00339 return new MusicFieldTreeBuilder(paths); 00340 } 00341
1.7.6.1