Index: mythmusic/metadata.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythmusic/mythmusic/metadata.cpp,v
retrieving revision 1.34
diff -u -d -r1.34 metadata.cpp
--- mythmusic/metadata.cpp	10 Apr 2005 05:17:15 -0000	1.34
+++ mythmusic/metadata.cpp	10 Apr 2005 13:59:42 -0000
@@ -1,5 +1,5 @@
-#include <iostream> 
-#include <qregexp.h> 
+#include <iostream>
+#include <qregexp.h>
 #include <qdatetime.h>
 #include <qdir.h>
 
@@ -17,7 +17,7 @@
 };
 
 static FieldSplitInfo splitArray[] =
-{ 
+{
   {"ABCDE", " (A B C D E)"},
   {"FGHIJ", " (F G H I J)"},
   {"KLMNO", " (K L M N O)"},
@@ -104,7 +104,7 @@
     if (query.exec() && query.isActive() && query.size() > 0)
     {
         query.next();
-  
+
         artist = QString::fromUtf8(query.value(0).toString());
         compilation_artist = QString::fromUtf8(query.value(1).toString());
         album = QString::fromUtf8(query.value(2).toString());
@@ -118,7 +118,7 @@
         playcount = query.value(10).toInt();
         lastplay = query.value(11).toString();
         compilation = (query.value(12).toInt() > 0);
-        
+
         retval = true;
     }
 
@@ -178,7 +178,7 @@
     query.bindValue(":FILENAME", sqlfilename.utf8());
     query.bindValue(":COMPILATION", compilation);
     query.bindValue(":DATE_ADDED", QDate::currentDate());
-    
+
     query.exec();
 
     // easiest way to ensure we've got 'id' filled.
@@ -199,35 +199,35 @@
 void Metadata::setArtistAndTrackFormats()
 {
     QString tmp;
-    
+
     tmp = gContext->GetSetting("MusicFormatNormalFileArtist");
     if (!tmp.isEmpty())
         formatnormalfileartist = tmp;
-    
+
     tmp = gContext->GetSetting("MusicFormatNormalFileTrack");
     if (!tmp.isEmpty())
         formatnormalfiletrack = tmp;
-        
+
     tmp = gContext->GetSetting("MusicFormatNormalCDArtist");
     if (!tmp.isEmpty())
         formatnormalcdartist = tmp;
-        
+
     tmp = gContext->GetSetting("MusicFormatNormalCDTrack");
     if (!tmp.isEmpty())
         formatnormalcdtrack = tmp;
-        
+
     tmp = gContext->GetSetting("MusicFormatCompilationFileArtist");
     if (!tmp.isEmpty())
         formatcompilationfileartist = tmp;
-        
+
     tmp = gContext->GetSetting("MusicFormatCompilationFileTrack");
     if (!tmp.isEmpty())
         formatcompilationfiletrack = tmp;
-        
+
     tmp = gContext->GetSetting("MusicFormatCompilationCDArtist");
     if (!tmp.isEmpty())
         formatcompilationcdartist = tmp;
-        
+
     tmp = gContext->GetSetting("MusicFormatCompilationCDTrack");
     if (!tmp.isEmpty())
         formatcompilationcdtrack = tmp;
@@ -235,8 +235,8 @@
 
 
 bool Metadata::determineIfCompilation(bool cd)
-{ 
-    compilation = (!compilation_artist.isEmpty() 
+{
+    compilation = (!compilation_artist.isEmpty()
                    && artist != compilation_artist);
     setCompilationFormatting(cd);
     return compilation;
@@ -257,7 +257,7 @@
 inline void Metadata::setCompilationFormatting(bool cd)
 {
     QString format_artist, format_title;
-    
+
     if (!compilation
         || "" == compilation_artist
         || artist == compilation_artist)
@@ -270,7 +270,7 @@
         else
         {
           format_artist = formatnormalcdartist;
-          format_title  = formatnormalcdtrack;          
+          format_title  = formatnormalcdtrack;
         }
     }
     else
@@ -283,13 +283,13 @@
         else
         {
           format_artist = formatcompilationcdartist;
-          format_title  = formatcompilationcdtrack;          
+          format_title  = formatcompilationcdtrack;
         }
     }
 
     // NB Could do some comparisons here to save memory with shallow copies...
     formattedartist = formatReplaceSymbols(format_artist);
-      
+
     formattedtitle = formatReplaceSymbols(format_title);
 }
 
@@ -298,7 +298,7 @@
 {
     if (formattedartist.isEmpty())
         setCompilationFormatting();
-        
+
     return formattedartist;
 }
 
@@ -314,7 +314,7 @@
 
 void Metadata::updateDatabase(QString startdir)
 {
-    startdir = startdir; 
+    startdir = startdir;
     // only save to DB if something changed
     //if (!hasChanged())
     //    return;
@@ -333,7 +333,7 @@
     query.prepare("UPDATE musicmetadata SET artist = :ARTIST, album = :ALBUM, "
                   "compilation_artist = :COMPILATION_ARTIST, "
                   "title = :TITLE, genre = :GENRE, year = :YEAR, "
-                  "tracknum = :TRACKNUM, rating = :RATING, " 
+                  "tracknum = :TRACKNUM, rating = :RATING, "
                   "compilation = :COMPILATION "
                   "WHERE intid = :ID;");
     query.bindValue(":ARTIST", artist.utf8());
@@ -358,7 +358,7 @@
         artist = data;
     // myth@colin.guthr.ie: Not sure what calls this method as I can't seem
     //                      to find anything that does!
-    //                      I've added the compilation_artist stuff here for 
+    //                      I've added the compilation_artist stuff here for
     //                      completeness.
     else if (field == "compilation_artist")
       compilation_artist = data;
@@ -378,7 +378,7 @@
         length = data.toInt();
     else if (field == "compilation")
         compilation = (data.toInt() > 0);
-    
+
     else
     {
         cerr << "metadata.o: Something asked me to return data about a field called " << field << endl ;
@@ -413,15 +413,15 @@
 {
     if(paths == "directory")
     {
-        //  Return directory values as if they were 
+        //  Return directory values as if they were
         //  real metadata/TAG values
-        
+
         QString working = filename;
         working.replace(QRegExp(startdir), QString(""));
         working.replace(QRegExp("/[^/]*$"), QString(""));
 
-        working = working.section('/', depth, depth);        
-        
+        working = working.section('/', depth, depth);
+
         *data = working;
     }
     else
@@ -518,16 +518,16 @@
 }
 
 void Metadata::fillDataFromID()
-{       
+{
     if (id == 0)
-        return; 
-        
+        return;
+
     MSqlQuery query(MSqlQuery::InitCon());
     query.prepare("SELECT title,artist,compilation_artist,album,title,genre,year,tracknum,"
                   "length,filename,rating,playcount,lastplay,compilation FROM "
                   "musicmetadata WHERE intid = :ID ;");
     query.bindValue(":ID", id);
-        
+
     if (query.exec() && query.isActive() && query.numRowsAffected() > 0)
     {
         query.next();
@@ -609,7 +609,7 @@
 void MetadataLoadingThread::run()
 {
     //if you want to simulate a big music collection load
-    //sleep(3); 
+    //sleep(3);
     parent->resync();
 }
 
@@ -617,7 +617,7 @@
 {
     startdir = a_startdir;
     done_loading = false;
-    
+
     cd_title = QObject::tr("CD -- none");
 
     //  How should we sort?
@@ -631,14 +631,15 @@
     //  Start a thread to do data
     //  loading and sorting
     //
-    
+
     metadata_loader = new MetadataLoadingThread(this);
     metadata_loader->start();
 
     all_music.setAutoDelete(true);
     top_nodes.setAutoDelete(true);
-    
+
     last_listed = -1;
+    field_sep = gContext->GetSetting("FieldSeparator", "");
 }
 
 AllMusic::~AllMusic()
@@ -657,7 +658,7 @@
     //  If this is still running, the user
     //  probably selected mythmusic and then
     //  escaped out right away
-    
+
     if(metadata_loader->finished())
     {
         return true;
@@ -685,7 +686,7 @@
     query.exec(aquery);
 
     all_music.clear();
-    
+
     if (query.isActive() && query.size() > 0)
     {
         while (query.next())
@@ -728,26 +729,26 @@
     }
     else
     {
-        cerr << "metadata.o: You don't seem to have any tracks. That's ok with me if it's ok with you." << endl; 
-    }    
- 
+        cerr << "metadata.o: You don't seem to have any tracks. That's ok with me if it's ok with you." << endl;
+    }
+
     //  To find this data quickly, build a map
     //  (a map to pointers!)
-    
+
     QPtrListIterator<Metadata> an_iterator( all_music );
     Metadata *map_add;
 
     music_map.clear();
     while ( (map_add = an_iterator.current()) != 0 )
     {
-        music_map[map_add->ID()] = map_add; 
+        music_map[map_add->ID()] = map_add;
         ++an_iterator;
     }
-    
-    //  Build a tree to reflect current state of 
+
+    //  Build a tree to reflect current state of
     //  the metadata. Once built, sort it.
-    
-    buildTree(); 
+
+    buildTree();
     //printTree();
     sortTree();
     //printTree();
@@ -761,9 +762,9 @@
     bool something_changed;
     QString Title1;
     QString Title2;
-    
+
     //  sort top level nodes
-    
+
     something_changed = false;
     if(top_nodes.count() > 1)
     {
@@ -781,7 +782,7 @@
                 Title1 = Title1.mid(4);
             if (Title2.left(4) == thePrefix)
                 Title2 = Title2.mid(4);
-           
+
             if(qstrcmp(Title1, Title2) > 0)
             {
                 something_changed = true;
@@ -794,8 +795,8 @@
             }
         }
     }
-    
-    //  tell top level nodes to sort from themselves 
+
+    //  tell top level nodes to sort from themselves
     //  downwards
 
     QPtrListIterator<MusicNode> iter(top_nodes);
@@ -829,14 +830,14 @@
     //  build a tree (nodes, leafs, and all)
     //  that reflects the desired structure
     //  of the metadata. This is a structure
-    //  that makes it easy (and QUICK) to 
+    //  that makes it easy (and QUICK) to
     //  display metadata on (for example) a
     //  Select Music screen
     //
-    
+
     top_nodes.clear();
     root_node->clearTracks();
-    
+
     QPtrListIterator<Metadata> an_iterator( all_music );
     Metadata *inserter;
     while ( (inserter = an_iterator.current()) != 0 )
@@ -853,7 +854,7 @@
     sub_node->setAttribute(1, 0);
     sub_node->setAttribute(2, 0);
     sub_node->setAttribute(3, 0);
-    
+
 
     QPtrListIterator<MusicNode> iter( top_nodes );
     MusicNode *traverse;
@@ -890,7 +891,7 @@
     {
         if (last_listed < 0)
             last_listed = 0;
-        
+
         QPtrListIterator<MusicNode> iter(top_nodes);
         MusicNode *traverse;
         iter += last_listed;
@@ -936,27 +937,40 @@
         }
         QString title_temp = QString(QObject::tr("%1 - %2")).arg((*anit).Track()).arg(title_string);
         QString level_temp = QObject::tr("title");
-        CDCheckItem *new_item = new CDCheckItem(where, title_temp, level_temp, 
+        CDCheckItem *new_item = new CDCheckItem(where, title_temp, level_temp,
                                                 -(*anit).Track());
-        new_item->setCheck(false); //  Avoiding -Wall     
-    }  
+        new_item->setCheck(false); //  Avoiding -Wall
+    }
 }
 
 
 void AllMusic::intoTree(Metadata* inserter)
 {
-    MusicNode *insertion_point = findRightNode(inserter, 0);
-    insertion_point->insert(inserter);
+    QString a_field = "";
+    inserter->getField(tree_levels.first(), &a_field, paths, startdir, 0);
+
+    if(field_sep == "")
+    {
+        MusicNode *insertion_point = findRightNode(inserter, a_field, 0);
+        insertion_point->insert(inserter);
+    }
+    else
+    {
+        QStringList lst( QStringList::split( field_sep, a_field ) );
+
+        for (QStringList::Iterator it = lst.begin() ; it != lst.end(); ++it ) {
+           MusicNode *insertion_point = findRightNode(inserter, *it, 0);
+           insertion_point->insert(inserter);
+        }
+    }
 }
 
-MusicNode* AllMusic::findRightNode(Metadata* inserter, uint depth)
+MusicNode* AllMusic::findRightNode(Metadata* inserter, QString &a_field, uint depth)
 {
-    QString a_field = "";
-
     //  Use metadata to find pre-exisiting insertion
     //  point or (recursively) create nodes as needed
     //  and return ultimate insertion point
-    
+
     if(inserter->areYouFinished(depth, tree_levels.count(), paths, startdir))
     {
         //  special case, track is at root level
@@ -964,8 +978,7 @@
         //  paths=directory
         return root_node;
     }
-    
-    inserter->getField(tree_levels.first(), &a_field, paths, startdir, depth);
+
     QPtrListIterator<MusicNode> iter( top_nodes );
     MusicNode *search;
     while ( (search = iter.current()) != 0 )
@@ -977,7 +990,7 @@
         ++iter;
     }
     //  If we made it here, no appropriate top level node exists
-    
+
     MusicNode *new_one = new MusicNode(a_field, tree_levels, 0);
     top_nodes.append(new_one);
     return ( new_one->findRightNode(tree_levels, inserter, depth + 1) );
@@ -988,18 +1001,18 @@
     QString a_label = "";
     if(an_id > 0)
     {
-   
+
         if (!music_map.contains(an_id))
         {
             a_label = QString(QObject::tr("Missing database entry: %1")).arg(an_id);
             *error_flag = true;
             return a_label;
         }
-      
+
         a_label += music_map[an_id]->FormatArtist();
         a_label += QObject::tr(" ~ ");
         a_label += music_map[an_id]->FormatTitle();
-    
+
 
         if(a_label.length() < 1)
         {
@@ -1037,7 +1050,7 @@
     {
         if (music_map.contains(an_id))
         {
-            return music_map[an_id];    
+            return music_map[an_id];
         }
     }
     else if(an_id < 0)
@@ -1062,7 +1075,7 @@
         if (mdata)
         {
             *mdata = the_track;
-            return true;    
+            return true;
         }
     }
     return false;
@@ -1070,10 +1083,10 @@
 
 void AllMusic::save()
 {
-    //  Check each Metadata entry and save those that 
+    //  Check each Metadata entry and save those that
     //  have changed (ratings, etc.)
-    
-    
+
+
     QPtrListIterator<Metadata> an_iterator( all_music );
     Metadata *searcher;
     while ( (searcher = an_iterator.current()) != 0 )
@@ -1121,7 +1134,7 @@
             return true;
         }
 
-    }  
+    }
     return false;
 }
 
@@ -1141,14 +1154,14 @@
     {
         if( *it != "genre"  &&
             *it != "artist" &&
-            *it != "splitartist" && 
+            *it != "splitartist" &&
             *it != "album"  &&
             *it != "title")
         {
-            cerr << "metadata.o: I don't understand the expression \"" << *it 
-                 << "\" as a tree level in a music hierarchy " << endl ; 
+            cerr << "metadata.o: I don't understand the expression \"" << *it
+                 << "\" as a tree level in a music hierarchy " << endl ;
         }
-            
+
     }
 }
 
@@ -1168,7 +1181,7 @@
             my_level = "I am confused";
             cerr << "metadata.o: Something asked me to look up a StringList entry that doesn't exist" << endl ;
         }
-       
+
     }
 
     my_subnodes.setAutoDelete(true);
@@ -1197,13 +1210,13 @@
     m_LastPlayWeight = gContext->GetNumSetting("IntelliLastPlayWeight", 2);
     m_RandomWeight = gContext->GetNumSetting("IntelliRandomWeight", 2);
 }
-    
+
 void MusicNode::insert(Metadata* inserter)
 {
     my_tracks.append(inserter);
 }
 
-MusicNode* MusicNode::findRightNode(QStringList tree_levels, 
+MusicNode* MusicNode::findRightNode(QStringList tree_levels,
                                     Metadata *inserter, uint depth)
 {
     QString a_field = "";
@@ -1243,7 +1256,7 @@
         }
         MusicNode *new_one = new MusicNode(a_field, tree_levels, depth);
         my_subnodes.append(new_one);
-        return (new_one->findRightNode(tree_levels, inserter, depth + 1) );                
+        return (new_one->findRightNode(tree_levels, inserter, depth + 1) );
     }
 }
 
@@ -1273,10 +1286,10 @@
         TreeCheckItem *new_item = new TreeCheckItem(current_parent, title_temp,
                                                     level_temp, a_track->ID());
         ++anit;
-        new_item->setCheck(false); //  Avoiding -Wall     
-    }  
+        new_item->setCheck(false); //  Avoiding -Wall
+    }
+
 
-    
     QPtrListIterator<MusicNode> iter(my_subnodes);
     MusicNode *sub_traverse;
     while ((sub_traverse = iter.current() ) != 0)
@@ -1284,18 +1297,18 @@
         sub_traverse->putYourselfOnTheListView(current_parent, true);
         ++iter;
     }
-    
+
 }
 
 void MusicNode::writeTree(GenericTree *tree_to_write_to, int a_counter)
 {
-    
+
     GenericTree *sub_node = tree_to_write_to->addNode(my_title);
     sub_node->setAttribute(0, 0);
     sub_node->setAttribute(1, a_counter);
     sub_node->setAttribute(2, rand());
     sub_node->setAttribute(3, rand());
-    
+
     QPtrListIterator<Metadata>  anit(my_tracks);
     Metadata *a_track;
     int track_counter = 0;
@@ -1327,9 +1340,9 @@
         subsub_node->setAttribute(3, integer_rating);   //  "intelligent" order
         ++track_counter;
         ++anit;
-    }  
+    }
+
 
-    
     QPtrListIterator<MusicNode> iter(my_subnodes);
     MusicNode *sub_traverse;
     int another_counter = 0;
@@ -1353,7 +1366,7 @@
     QString Title1, Title2;
 
     //  Sort any tracks
-    
+
     something_changed = false;
     if(my_tracks.count() > 1)
     {
@@ -1378,7 +1391,7 @@
     }
 
     //  Sort any subnodes
-    
+
     something_changed = false;
     if(my_subnodes.count() > 1)
     {
@@ -1409,7 +1422,7 @@
             }
         }
     }
-    
+
     //  Tell any subnodes to sort themselves
 
     QPtrListIterator<MusicNode> iter(my_subnodes);
@@ -1438,11 +1451,11 @@
         for(int j = 0; j < (indent_level + 1) * 4; j++)
         {
             cout << " " ;
-        } 
+        }
         cout << a_track->Title() << endl ;
         ++anit;
-    }       
-    
+    }
+
     QPtrListIterator<MusicNode> iter(my_subnodes);
     MusicNode *print;
     while( (print = iter.current() ) != 0)
Index: mythmusic/metadata.h
===================================================================
RCS file: /var/lib/mythcvs/mythmusic/mythmusic/metadata.h,v
retrieving revision 1.17
diff -u -d -r1.17 metadata.h
--- mythmusic/metadata.h	23 Feb 2005 20:41:08 -0000	1.17
+++ mythmusic/metadata.h	10 Apr 2005 13:59:42 -0000
@@ -15,7 +15,7 @@
 class Metadata
 {
   public:
-    Metadata(QString lfilename = "", QString lartist = "", QString lcompilation_artist = "", 
+    Metadata(QString lfilename = "", QString lartist = "", QString lcompilation_artist = "",
              QString lalbum = "", QString ltitle = "", QString lgenre = "",
              int lyear = 0, int ltracknum = 0, int llength = 0, int lid = 0,
              int lrating = 0, int lplaycount = 0, QString llastplay = "",
@@ -40,7 +40,7 @@
                 changed = false;
             }
 
-    Metadata(const Metadata &other) 
+    Metadata(const Metadata &other)
             {
                 filename = other.filename;
                 artist = other.artist;
@@ -65,10 +65,10 @@
 
     QString Artist() { return artist; }
     void setArtist(const QString &lartist) { artist = lartist; formattedartist = formattedtitle = ""; }
-    
+
     QString CompilationArtist() { return compilation_artist; }
     void setCompilationArtist(const QString &lcompilation_artist) { compilation_artist = lcompilation_artist; formattedartist = formattedtitle = ""; }
-    
+
     QString Album() { return album; }
     void setAlbum(const QString &lalbum) { album = lalbum; formattedartist = formattedtitle = ""; }
 
@@ -83,7 +83,7 @@
 
     int Year() { return year; }
     void setYear(int lyear) { year = lyear; }
- 
+
     int Track() { return tracknum; }
     void setTrack(int ltrack) { tracknum = ltrack; }
 
@@ -95,10 +95,10 @@
 
     unsigned int ID() { return id; }
     void setID(int lid) { id = lid; }
-    
+
     QString Filename() const { return filename; }
     void setFilename(QString &lfilename) { filename = lfilename; }
-    
+
     int Rating() { return rating; }
     void decRating();
     void incRating();
@@ -114,7 +114,7 @@
     bool Compilation() { return compilation; }
     void setCompilation(bool state) { compilation = state; formattedartist = formattedtitle = ""; }
     bool determineIfCompilation(bool cd = false);
-    
+
     bool isInDatabase(QString startdir);
     void dumpToDatabase(QString startdir);
     void updateDatabase(QString startdir);
@@ -148,7 +148,7 @@
     QString lastplay;
     int playcount;
     bool compilation;
-     
+
     unsigned int id;
     QString filename;
     bool    changed;
@@ -175,15 +175,15 @@
     //  Not a root of the music tree, and
     //  not a leaf, but anything in the
     //  middle
-    
+
   public:
-  
+
     MusicNode(QString a_title, QStringList tree_levels, uint depth);
    ~MusicNode();
 
     void        insert(Metadata* inserter);
     QString     getTitle(){return my_title;}
-    MusicNode*  findRightNode(QStringList tree_levels, Metadata *inserter, 
+    MusicNode*  findRightNode(QStringList tree_levels, Metadata *inserter,
                 uint depth);
     void        printYourself(int indent_amount);   // debugging
     void        clearTracks() { my_tracks.clear(); }
@@ -196,9 +196,9 @@
     void        setLastPlayMax(double tmp_max) { lastplayMax = tmp_max; }
 
     static void SetStaticData(const QString &startdir, const QString &paths);
- 
+
   private:
-  
+
     QPtrList<Metadata>  my_tracks;
     QPtrList<MusicNode> my_subnodes;
     QString             my_title;
@@ -224,9 +224,9 @@
 
     MetadataLoadingThread(AllMusic *parent_ptr);
     virtual void run();
-    
+
   private:
-  
+
     AllMusic *parent;
 };
 
@@ -236,7 +236,7 @@
     //  And save any changes at mythmusic stop
 
   public:
-  
+
     AllMusic(QString path_assignment, QString a_startdir);
     ~AllMusic();
 
@@ -256,7 +256,7 @@
     void        sortTree();
     void        writeTree(GenericTree *tree_to_write_to);
     void        intoTree(Metadata* inserter);
-    MusicNode*  findRightNode(Metadata* inserter, uint depth);
+    MusicNode*  findRightNode(Metadata* inserter, QString &a_field, uint depth);
     void        setSorting(QString a_paths);
     bool        putYourselfOnTheListView(TreeCheckItem *where, int how_many);
     void        putCDOnTheListView(CDCheckItem *where);
@@ -264,14 +264,14 @@
     bool        cleanOutThreads();
     int         getCDTrackCount(){return cd_data.count();}
     void        resetListings(){last_listed = -1;}
-    
+
   private:
-  
+
     QPtrList<Metadata>  all_music;
     QPtrList<MusicNode> top_nodes;
     MusicNode           *root_node;
-    
-    
+
+
 
     //  NB: While a QMap is VALUE BASED the
     //  values we are copying here are pointers,
@@ -280,7 +280,7 @@
     //  you NEED to clear and rebuild the map
     typedef QMap<int, Metadata*> MusicMap;
     MusicMap music_map;
-    
+
     typedef QValueList<Metadata>  ValueMetadata;
     ValueMetadata                 cd_data; //  More than one cd player?
     QString                       cd_title;
@@ -288,8 +288,8 @@
     QString     startdir;
     QString     paths;
     QStringList tree_levels;
-    
-    
+
+    QString     field_sep;
     MetadataLoadingThread   *metadata_loader;
     bool                     done_loading;
     int                      last_listed;
