Index: mythvideo/mythvideo/video-ui.xml
===================================================================
--- mythvideo/mythvideo/video-ui.xml	(revision 9776)
+++ mythvideo/mythvideo/video-ui.xml	(working copy)
@@ -1102,6 +1102,12 @@
                 <value>Unique Player Command:</value>
             </textarea>
 
+            <textarea name="title_sort_key_text" draworder="0" align="right">
+                <area>50,490,250,40</area>
+                <font>display</font>
+                <value>Title-Sort Key:</value>
+            </textarea>
+
             <!--
                     Widgets
             -->
@@ -1167,8 +1173,12 @@
                 <area>310,445,300,40</area>
             </blackhole>
 
+            <blackhole name="title_sort_key_hack" draworder="0">
+                <area>310,490,300,40</area>
+            </blackhole>
+
             <textbutton name="done_button" draworder="0">
-                <position>310,505</position>
+                <position>310,550</position>
                 <font>display</font>
                 <image function="on" filename="mv_large_text_button_on.png"></image>
                 <image function="off" filename="mv_large_text_button_off.png"></image>
Index: mythvideo/mythvideo/metadata.cpp
===================================================================
--- mythvideo/mythvideo/metadata.cpp	(revision 9776)
+++ mythvideo/mythvideo/metadata.cpp	(working copy)
@@ -204,7 +204,7 @@
     MSqlQuery query(MSqlQuery::InitCon());
     query.prepare("SELECT title,director,plot,rating,year,userrating,"
                   "length,filename,showlevel,coverfile,inetref,childid,"
-                  "browse,playcommand, videocategory.category "
+                  "browse,playcommand, videocategory.category,titlesortkey "
                   " FROM videometadata LEFT JOIN videocategory"
                   " ON videometadata.category = videocategory.intid"
                   "  WHERE videometadata.intid= :ID ;");
@@ -232,6 +232,7 @@
         browse = query.value(12).toBool();
         playcommand = query.value(13).toString();
         category = query.value(14).toString();
+        titleSortKey = query.value(15).toString();
 
         // Genres
         fillGenres();
@@ -276,13 +277,14 @@
         userrating = 0.0;
 
     MSqlQuery a_query(MSqlQuery::InitCon());
-    a_query.prepare("INSERT INTO videometadata (title,director,plot,"
-                    "rating,year,userrating,length,filename,showlevel,"
-                    "coverfile,inetref,browse) VALUES (:TITLE, :DIRECTOR, "
-                    ":PLOT, :RATING, :YEAR, :USERRATING, :LENGTH, "
+    a_query.prepare("INSERT INTO videometadata (title,titlesortkey,director,"
+                    "plot,rating,year,userrating,length,filename,showlevel,"
+                    "coverfile,inetref,browse) VALUES (:TITLE, :TITLESORTKEY, "
+                    ":DIRECTOR, :PLOT, :RATING, :YEAR, :USERRATING, :LENGTH, "
                     ":FILENAME, :SHOWLEVEL, :COVERFILE, :INETREF, "
                     ":BROWSE );");
     a_query.bindValue(":TITLE", title.utf8());
+    a_query.bindValue(":TITLESORTKEY", titleSortKey.utf8());
     a_query.bindValue(":DIRECTOR", director.utf8());
     a_query.bindValue(":PLOT", plot.utf8());
     a_query.bindValue(":RATING", rating.utf8());
@@ -379,10 +381,23 @@
     }
 }
 
+void Metadata::guessTitleSortKey()
+{
+    QRegExp prefixes = QObject::tr("^(The |A |An )");
+    // Start with the title
+    titleSortKey = title;
+    // Remove indefinite articles from the title
+    titleSortKey.remove(prefixes);
+    // Make the comparison case-insensitive regardless of locale's LC_COLLATE
+    titleSortKey = titleSortKey.lower();
+}
+
 void Metadata::updateDatabase()
 {
     if (title == "")
         guessTitle();
+    if (titleSortKey == "")
+        guessTitleSortKey();
     if (director == "")
         director = QObject::tr("Unknown");
     if (plot == "")
@@ -398,6 +413,7 @@
 
     MSqlQuery query(MSqlQuery::InitCon());
     query.prepare("UPDATE videometadata SET title = :TITLE, "
+                  "titlesortkey = :TITLESORTKEY, "
                   "director = :DIRECTOR, plot = :PLOT, rating= :RATING, "
                   "year = :YEAR, userrating = :USERRATING, length = :LENGTH, "
                   "filename = :FILENAME, showlevel = :SHOWLEVEL, "
@@ -406,6 +422,7 @@
                   "childid = :CHILDID, category = :CATEGORY "
                   "WHERE intid = :INTID");
     query.bindValue(":TITLE", title.utf8());
+    query.bindValue(":TITLESORTKEY", titleSortKey.utf8());
     query.bindValue(":DIRECTOR", director.utf8());
     query.bindValue(":PLOT", plot.utf8());
     query.bindValue(":RATING", rating.utf8());
Index: mythvideo/mythvideo/dbcheck.cpp
===================================================================
--- mythvideo/mythvideo/dbcheck.cpp	(revision 9776)
+++ mythvideo/mythvideo/dbcheck.cpp	(working copy)
@@ -8,7 +8,7 @@
 #include "mythtv/mythcontext.h"
 #include "mythtv/mythdbcon.h"
 
-const QString currentDatabaseVersion = "1008";
+const QString currentDatabaseVersion = "1009";
 
 static void UpdateDBVersionNumber(const QString &newnumber)
 {
@@ -216,4 +216,17 @@
         performActualUpdate(updates, "1008", dbver);
     }
 
+    if (dbver == "1008")
+    {
+        const QString updates[] = {
+"ALTER TABLE videometadata ADD titlesortkey VARCHAR(255);",
+"UPDATE videometadata SET titlesortkey = TRIM(LEADING ' ' FROM "
+"(IF(title REGEXP '" + QObject::tr("^(The |A |An )") + "', "
+"TRIM(LEADING SUBSTRING_INDEX(title,' ',1) FROM title),title)));",
+""
+};
+
+        performActualUpdate(updates, "1009", dbver);
+    }
+
 }
Index: mythvideo/mythvideo/editmetadata.h
===================================================================
--- mythvideo/mythvideo/editmetadata.h	(revision 9776)
+++ mythvideo/mythvideo/editmetadata.h	(working copy)
@@ -45,6 +45,7 @@
     void takeFocusAwayFromEditor(bool up_or_down);
     void saveAndExit();
     void setTitle(QString new_title);
+    void setTitleSortKey(QString new_title_sort_key);
     void setCategory(int new_category);
     void setPlayer(QString new_player);
     void setLevel(int new_level);
@@ -64,6 +65,9 @@
     MythRemoteLineEdit  *title_editor;
     UIBlackHoleType     *title_hack;
 
+    MythRemoteLineEdit  *title_sort_key_editor;
+    UIBlackHoleType     *title_sort_key_hack;
+
     MythRemoteLineEdit  *player_editor;
     UIBlackHoleType     *player_hack;
 
Index: mythvideo/mythvideo/videomanager.cpp
===================================================================
--- mythvideo/mythvideo/videomanager.cpp	(revision 9776)
+++ mythvideo/mythvideo/videomanager.cpp	(working copy)
@@ -437,6 +437,7 @@
         curitem->setUserRating(data["UserRating"].toFloat());
         curitem->setRating(data["MovieRating"]);
         curitem->setLength(data["Runtime"].toInt());
+        curitem->guessTitleSortKey();
         
         //movieGenres
         movieGenres.clear();
@@ -1479,6 +1480,7 @@
     QString coverFile = tr("No Cover");
 
     curitem->guessTitle();
+    curitem->guessTitleSortKey();
     curitem->setCoverFile(coverFile);
     curitem->setYear(1895);
     curitem->setInetRef("00000000");
Index: mythvideo/mythvideo/videolist.cpp
===================================================================
--- mythvideo/mythvideo/videolist.cpp	(revision 9776)
+++ mythvideo/mythvideo/videolist.cpp	(working copy)
@@ -175,45 +175,6 @@
     }
 
     //
-    //  If sorting by title, re-sort by hand because the SQL sort doesn't
-    //  ignore articles when sorting. This assumes all titles are in English.
-    //  This means a movie with a foreign-language title like "A la carte" will
-    //  be incorrectly alphabetized, because the "A" is actually significant.
-    //  The set of ignored prefixes should be a database option, or each
-    //  video's metadata should include a separate sort key.
-    //
-    if (currentVideoFilter->getOrderby() == VideoFilterSettings::kOrderByTitle)
-    {
-        //
-        //  Pull things off the metaptrs list and put them into the
-        //  "stringsort" qmap (which will automatically sort them by qmap key).
-        //
-        QMap<QString, Metadata*> stringsort;
-        QRegExp prefixes = QObject::tr("^(The |A |An )");
-        while (!metaptrs.isEmpty())
-        {
-            Metadata *myData = metaptrs.take(0);
-            QString sTitle = myData->Title();
-            sTitle.remove(prefixes);
-
-            // Append the video ID to allow multiple videos with the same title
-            sTitle += QString().sprintf("%.7d", myData->ID());
-            stringsort[sTitle] = myData;
-        }
-
-        //
-        //  Now walk through the "stringsort" qmap and put them back on the
-        //  list (in stringsort order).
-        //
-        for (QMap<QString, Metadata*>::iterator it = stringsort.begin();
-                it != stringsort.end();
-                it++)
-        {
-            metaptrs.append(*it);
-        }
-    }
-
-    //
     //  Build list of videos.
     //
     for (unsigned int count = 0; !metaptrs.isEmpty(); count++)
Index: mythvideo/mythvideo/videoscan.cpp
===================================================================
--- mythvideo/mythvideo/videoscan.cpp	(revision 9776)
+++ mythvideo/mythvideo/videoscan.cpp	(working copy)
@@ -103,12 +103,13 @@
     {
         if (*iter == kFileSystem)
         {
-            Metadata newFile(iter.key(), QObject::tr("No Cover"), "", 1895, 
+            Metadata newFile(iter.key(), QObject::tr("No Cover"), "", "", 1895,
                              "00000000", QObject::tr("Unknown"), 
                              QObject::tr("None"), 0.0, QObject::tr("NR"), 
                              0, 0, 1);
             
             newFile.guessTitle();
+            newFile.guessTitleSortKey();
             newFile.dumpToDatabase();
         }
         
Index: mythvideo/mythvideo/videofilter.cpp
===================================================================
--- mythvideo/mythvideo/videofilter.cpp	(revision 9776)
+++ mythvideo/mythvideo/videofilter.cpp	(working copy)
@@ -179,7 +179,7 @@
     switch (orderby)
     {
         case kOrderByTitle : 
-            return " ORDER BY title";
+            return " ORDER BY titlesortkey";
         case kOrderByYearDescending : 
             return " ORDER BY year DESC";
         case kOrderByUserRatingDescending : 
Index: mythvideo/mythvideo/metadata.h
===================================================================
--- mythvideo/mythvideo/metadata.h	(revision 9776)
+++ mythvideo/mythvideo/metadata.h	(working copy)
@@ -12,7 +12,8 @@
 {
   public:
     Metadata(const QString& lfilename = "", const QString& lcoverfile = "", 
-             const QString& ltitle = "", int lyear = 0, const QString& linetref = "", 
+             const QString& ltitle = "", const QString& ltitleSortKey = "",
+             int lyear = 0, const QString& linetref = "",
              const QString& ldirector = "", const QString& lplot = "", 
              float luserrating = 0.0, const QString& lrating = "", int llength = 0, 
              int lid = 0, int lshowlevel = 1, int lchildID = -1,
@@ -26,6 +27,7 @@
         filename = lfilename;
         coverfile = lcoverfile;
         title = ltitle;
+        titleSortKey = ltitleSortKey;
         year = lyear;
         inetref = linetref;
         director = ldirector;
@@ -52,6 +54,7 @@
         filename = other.filename;
         coverfile = other.coverfile;
         title = other.title;
+        titleSortKey = other.titleSortKey;
         year = other.year;
         inetref = other.inetref;
         director = other.director;
@@ -83,6 +86,7 @@
         filename    = "";
         coverfile   = "";
         title       = "";
+        titleSortKey= "";
         inetref     = "";
         director    = "";
         plot        = "";
@@ -113,6 +117,10 @@
     const QString& Title() const { return title; }
     void setTitle(const QString& _title) { title = _title; }
     
+    const QString& TitleSortKey() const { return titleSortKey; }
+    void setTitleSortKey(const QString& _titleSortKey)
+        { titleSortKey = _titleSortKey; }
+
     int Year() const { return year; }
     void setYear(int _year) { year = _year; }
 
@@ -179,6 +187,8 @@
     void guessTitle();
     void eatBraces(const QString& left_brace, const QString& right_brace);
 
+    void guessTitleSortKey();
+
     void dumpToDatabase();
     void updateDatabase();
     bool fillDataFromID();
@@ -202,6 +212,7 @@
     
 
     QString title;
+    QString titleSortKey;
     QString inetref;
     QString director;
     QString plot;
Index: mythvideo/mythvideo/editmetadata.cpp
===================================================================
--- mythvideo/mythvideo/editmetadata.cpp	(revision 9776)
+++ mythvideo/mythvideo/editmetadata.cpp	(working copy)
@@ -37,6 +37,7 @@
     
 
     title_hack = NULL;
+    title_sort_key_hack = NULL;
     player_hack = NULL;
     category_select = NULL;
     level_select = NULL;
@@ -47,6 +48,7 @@
     coverart_text = NULL;
     done_button = NULL;
     title_editor = NULL; 
+    title_sort_key_editor = NULL;
     player_editor = NULL; 
     
     wireUpTheme();
@@ -60,6 +62,11 @@
     {
         title_editor->setText(working_metadata->Title());
     }
+
+    if(title_sort_key_editor)
+    {
+        title_sort_key_editor->setText(working_metadata->TitleSortKey());
+    }
     
     if (category_select)
     {
@@ -102,7 +109,7 @@
         child_select->addItem(0, tr("None"));
 
         QString q_string = QString("SELECT intid, title FROM videometadata "
-                                   "ORDER BY title ;");
+                                   "ORDER BY titlesortkey ;");
         MSqlQuery a_query(MSqlQuery::InitCon());
         a_query.exec(q_string);
 
@@ -366,6 +373,11 @@
     working_metadata->setTitle(new_title);
 }
 
+void EditMetadataDialog::setTitleSortKey(QString new_title_sort_key)
+{
+    working_metadata->setTitleSortKey(new_title_sort_key);
+}
+
 void EditMetadataDialog::setCategory(int new_category)
 {
     working_metadata->setCategoryID(new_category);
@@ -453,6 +465,22 @@
                 this, SLOT(setTitle(QString)));
     }
 
+    title_sort_key_hack = getUIBlackHoleType("title_sort_key_hack");
+    if(title_sort_key_hack)
+    {
+        title_sort_key_hack->allowFocus(true);
+        QFont f = gContext->GetMediumFont();
+        title_sort_key_editor = new MythRemoteLineEdit(&f, this);
+        title_sort_key_editor->setFocusPolicy(QWidget::NoFocus);
+        title_sort_key_editor->setGeometry(title_sort_key_hack->getScreenArea());
+        connect(title_sort_key_hack, SIGNAL(takingFocus()), 
+                title_sort_key_editor, SLOT(setFocus()));
+        connect(title_sort_key_editor, SIGNAL(tryingToLooseFocus(bool)), 
+                this, SLOT(takeFocusAwayFromEditor(bool)));
+        connect(title_sort_key_editor, SIGNAL(textChanged(QString)),
+                this, SLOT(setTitleSortKey(QString)));
+    }
+
     category_select = getUISelectorType("category_select");
     if(category_select)
     {
@@ -529,6 +557,10 @@
     {
         delete title_editor;
     }
+    if(title_sort_key_editor)
+    {
+        delete title_sort_key_editor;
+    }
     if(player_editor)
     {
         delete player_editor;
