Ticket #7376: mythgallery.rev22544.patch

File mythgallery.rev22544.patch, 27.5 KB (added by trebor_s@…, 15 years ago)

Patch for mythgallery against trunk 22544

  • mythgallery/galleryutil.h

    Kann nicht anzeigen: Dateityp ist als binÀr angegeben.
    svn:mime-type = application/octet-stream
     
    2121#define EXIFUTIL_H
    2222
    2323#include <QFileInfo>
    24 
    2524#include "iconview.h"
    2625
     26#ifdef EXIF_SUPPORT
     27#include <libexif/exif-data.h>
     28#include <libexif/exif-entry.h>
     29// include "exif.hpp"
     30#endif // EXIF_SUPPORT
     31
    2732class GalleryUtil
    2833{
    2934 public:
     
    3439    static bool IsImage(const QString &filePath);
    3540    static bool IsMovie(const QString &filePath);
    3641    static long GetNaturalRotation(const QString &filePath);
    37 
     42    static long GetNaturalRotationDB(const QString &filePath, bool *ok);
     43    static long GetDateTime(const QString &filePath);
     44    static long GetDateTimeDB(const QString &filePath, bool *ok);
    3845    static QString GetCaption(const QString &filePath);
    3946
     47    static void SetDateTimeDB(const QString &filePath, long dateTime);
     48    static void SetNaturalRotationDB(QString &filePath, long angle);
     49
     50#ifdef EXIF_SUPPORT
     51    static QString GetExifHeaderTag(const QString &filePathString, ExifTag exifHeaderTag);
     52#endif
     53
    4054    static bool LoadDirectory(ThumbList &itemList, const QString &dir,
    4155                              int sortorder, bool recurse,
    4256                              ThumbHash *itemHash, ThumbGenerator *thumbGen);
  • mythgallery/thumbview.cpp

     
    77
    88// MythTV plugin headers
    99#include <mythtv/mythdb.h>
     10#include "mythtv/mythcontext.h"
    1011
    1112// MythGallery headers
    1213#include "thumbview.h"
     
    6162
    6263void ThumbItem::SetRotationAngle(int angle)
    6364{
    64     MSqlQuery query(MSqlQuery::InitCon());
    65     query.prepare(
    66         "REPLACE INTO gallerymetadata "
    67         "SET image = :IMAGE, "
    68         "    angle = :ANGLE");
    69     query.bindValue(":IMAGE", m_path);
    70     query.bindValue(":ANGLE", angle);
    71 
    72     if (!query.exec())
    73         MythDB::DBError("set_rotation_angle", query);
    74 
     65    GalleryUtil::SetNaturalRotationDB(m_path, angle);
    7566    SetPixmap(NULL);
    7667}
    7768
     
    8273    m_pixmap = pixmap;
    8374}
    8475
     76
    8577long ThumbItem::GetRotationAngle(void)
    8678{
    87     MSqlQuery query(MSqlQuery::InitCon());
     79    // Load the rotation in from the database to speed up
     80    // the rotation later. If the data is not available then
     81    // get the rotation information from the exif header.
     82    bool ok = false;
     83    long rotateAngle = GalleryUtil::GetNaturalRotationDB(m_path, &ok);
    8884
    89     // first try to find the exact file
    90     query.prepare(
    91         "SELECT angle "
    92         "FROM gallerymetadata "
    93         "WHERE image = :PATH");
    94     query.bindValue(":PATH", m_path);
     85    if (rotateAngle == -1 || !ok)
     86    {
     87        // we dont have a value. try to get it from the exif header
     88        rotateAngle = GalleryUtil::GetNaturalRotation(m_path);
    9589
    96     if (!query.exec() || !query.isActive())
    97         MythDB::DBError("get_rotation_angle", query);
    98     else if (query.next())
    99         return query.value(0).toInt();
    100 
    101     // second try to find the first image in the same directory
    102     query.prepare(
    103         "SELECT angle, image "
    104         "FROM gallerymetadata "
    105         "WHERE image LIKE :PATH "
    106         "ORDER BY image");
    107     query.bindValue(":PATH", m_path + '%');
    108 
    109     if (!query.exec() || !query.isActive())
    110         MythDB::DBError("get_rotation_angle", query);
    111     else if (query.next())
    112         return query.value(0).toInt();
    113 
    114     return GalleryUtil::GetNaturalRotation(m_path);
     90        // if we have a value then update the database
     91        if ( rotateAngle != -1 )
     92            GalleryUtil::SetNaturalRotationDB(m_path, rotateAngle);
     93    }
     94    return rotateAngle;
    11595}
    11696
     97
    11798QString ThumbItem::GetDescription(const QString &status,
    11899                                  const QSize &sz, int angle) const
    119100{
  • mythgallery/gallerysettings.cpp

     
    4242    gc->addSelection("Reverse Name (Z-A alpha)", QString::number(QDir::Name | QDir::DirsFirst | QDir::IgnoreCase | QDir::Reversed));
    4343    gc->addSelection("Mod Time (earliest first)", QString::number(QDir::Time | QDir::DirsFirst | QDir::IgnoreCase | QDir::Reversed));
    4444    gc->addSelection("Reverse Mod Time (most recent first)", QString::number(QDir::Time | QDir::DirsFirst | QDir::IgnoreCase));
     45#ifdef EXIF_SUPPORT
     46    gc->addSelection("Creation Time (earliest first)", QString::number( 0x1000 | QDir::Reversed) );
     47    gc->addSelection("Reverse Creation Time (most recent first)", QString::number( 0x1000 ) );
     48#endif
    4549    gc->setHelpText(QObject::tr("This is the sort order for the displayed "
    4650                    "picture thumbnails."));
    4751    return gc;
  • mythgallery/dbcheck.cpp

     
    1212// mythgallery
    1313#include "dbcheck.h"
    1414
    15 const QString currentDatabaseVersion = "1003";
     15const QString currentDatabaseVersion = "1004";
    1616
    1717static bool UpdateDBVersionNumber(const QString &newnumber)
    1818{
    19 
    2019    if (!gContext->SaveSettingOnHost("GalleryDBSchemaVer",newnumber,NULL))
    2120    {
    2221        VERBOSE(VB_IMPORTANT,
     
    4544        if (!query.exec(thequery))
    4645        {
    4746            QString msg =
    48                 QString("DB Error (Performing database upgrade): \n"
    49                         "Query was: %1 \nError was: %2 \nnew version: %3")
    50                 .arg(thequery)
    51                 .arg(MythDB::DBErrorMessage(query.lastError()))
    52                 .arg(version);
     47                    QString("DB Error (Performing database upgrade): \n"
     48                            "Query was: %1 \nError was: %2 \nnew version: %3")
     49                    .arg(thequery)
     50                    .arg(MythDB::DBErrorMessage(query.lastError()))
     51                    .arg(version);
    5352            VERBOSE(VB_IMPORTANT, msg);
    5453            return false;
    5554        }
     
    7877                "Inserting MythGallery initial database information.");
    7978
    8079        const QString updates[] = {
    81 "CREATE TABLE IF NOT EXISTS gallerymetadata ("
    82 "  image VARCHAR(255) NOT NULL PRIMARY KEY,"
    83 "  angle INTEGER NOT NULL"
    84 ");",
    85 "INSERT INTO settings VALUES ('GalleryDBSchemaVer', 1000, NULL);",
    86 ""
    87 };
     80            "CREATE TABLE IF NOT EXISTS gallerymetadata ("
     81                    "  image VARCHAR(255) NOT NULL PRIMARY KEY,"
     82                    "  angle INTEGER NOT NULL"
     83                    ");",
     84                    "INSERT INTO settings VALUES ('GalleryDBSchemaVer', 1000, NULL);",
     85                    ""
     86                };
    8887        if (!performActualUpdate(updates, "1000", dbver))
    8988            return false;
    9089    }
    9190
    92 
    93 
    9491    if (dbver == "1000")
    9592    {
    9693        const QString updates[] = {
    97 QString("ALTER DATABASE %1 DEFAULT CHARACTER SET latin1;")
    98         .arg(gContext->GetDatabaseParams().dbName),
    99 "ALTER TABLE gallerymetadata"
    100 "  MODIFY image varbinary(255) NOT NULL;",
    101 ""
    102 };
     94            QString("ALTER DATABASE %1 DEFAULT CHARACTER SET latin1;")
     95                    .arg(gContext->GetDatabaseParams().dbName),
     96                    "ALTER TABLE gallerymetadata"
     97                    "  MODIFY image varbinary(255) NOT NULL;",
     98                    ""
     99                };
    103100
    104101        if (!performActualUpdate(updates, "1001", dbver))
    105102            return false;
    106103    }
    107104
    108 
    109105    if (dbver == "1001")
    110106    {
    111107        const QString updates[] = {
    112 QString("ALTER DATABASE %1 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;")
    113         .arg(gContext->GetDatabaseParams().dbName),
    114 "ALTER TABLE gallerymetadata"
    115 "  DEFAULT CHARACTER SET default,"
    116 "  MODIFY image varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL;",
    117 ""
    118 };
     108            QString("ALTER DATABASE %1 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;")
     109                    .arg(gContext->GetDatabaseParams().dbName),
     110                    "ALTER TABLE gallerymetadata"
     111                    "  DEFAULT CHARACTER SET default,"
     112                    "  MODIFY image varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL;",
     113                    ""
     114                };
    119115
    120116        if (!performActualUpdate(updates, "1002", dbver))
    121117            return false;
     
    124120    if (dbver == "1002")
    125121    {
    126122        const QString updates[] = {
    127 "DELETE FROM keybindings "
    128 " WHERE action = 'DELETE' AND context = 'Gallery';",
    129 ""
    130 };
     123            "DELETE FROM keybindings "
     124                    " WHERE action = 'DELETE' AND context = 'Gallery';",
     125                    ""
     126                };
    131127
    132128        if (!performActualUpdate(updates, "1003", dbver))
    133129            return false;
    134130    }
    135131
     132    if (dbver == "1003")
     133    {
     134        const QString updates[] = {
     135            "ALTER TABLE `gallerymetadata` ADD `datetime` INT NOT NULL DEFAULT '0' AFTER `angle`;",
     136            "ALTER TABLE `gallerymetadata` CHANGE `angle` `angle` INT( 11 ) NOT NULL DEFAULT '-1';",
     137            ""
     138        };
     139        if (!performActualUpdate(updates, "1004", dbver))
     140            return false;
     141    }
     142
    136143    return true;
    137144}
  • mythgallery/iconview.cpp

     
    311311                            .arg(ThumbGenerator::getThumbcacheDir(m_currDir))
    312312                            .arg(item->GetName());
    313313
    314 //         int rotateAngle = 0;
    315 //
    316 //         rotateAngle = item->GetRotationAngle();
    317 //
    318 //         if (rotateAngle != 0)
    319 //         {
    320 //             QMatrix matrix;
    321 //             matrix.rotate(rotateAngle);
    322 //             image = image.xForm(matrix);
    323 //         }
    324314    item->SetImageFilename(imagePath);
    325315}
    326316
     
    414404    m_selectedImage->Load();
    415405}
    416406
    417 
    418407bool IconView::keyPressEvent(QKeyEvent *event)
    419408{
    420409    if (GetFocusWidget()->keyPressEvent(event))
     
    12321221    LoadDirectory(m_currDir);
    12331222}
    12341223
    1235 
    12361224void IconView::HandleRename(void)
    12371225{
    12381226    ThumbItem *thumbitem = GetCurrentThumb();
  • mythgallery/thumbgenerator.cpp

     
    321321    else
    322322    {
    323323#ifdef EXIF_SUPPORT
     324
    324325        // Try to get thumbnail from exif data
    325326        ExifData *ed = exif_data_new_from_file(fi.absoluteFilePath()
    326327                                               .toLocal8Bit().constData());
    327328        if (ed && ed->data)
    328         {
    329329            image.loadFromData(ed->data, ed->size);
    330         }
    331330
    332331        if (ed)
    333332            exif_data_free(ed);
     
    335334        if (image.width() > m_width && image.height() > m_height)
    336335            return;
    337336#endif
     337        // There was no thumbnail image in the exif header.
     338        // Load the image regularily.
     339        image.load(fi.absoluteFilePath());
    338340
    339         image.load(fi.absoluteFilePath());
     341        // Load the rotation in from the database to speed up
     342        // the rotation later. If the data is not available then
     343        // get the rotation information from the exif header and
     344        // rotate the image so we have a correct thumbnail preview.
     345        bool ok = false;
     346        QString filePath = fi.canonicalFilePath();
     347        long rotateAngle = GalleryUtil::GetNaturalRotationDB(filePath, &ok);
     348
     349        if (rotateAngle == -1 || !ok)
     350        {
     351            // we dont have a value. try to get it from the exif header
     352            rotateAngle = GalleryUtil::GetNaturalRotation(filePath);
     353
     354            // if we have a value then update the database
     355            if ( rotateAngle != -1 )
     356            {
     357                GalleryUtil::SetNaturalRotationDB(filePath, rotateAngle);
     358
     359                // rotate the thumbnail image
     360                QMatrix matrix;
     361                matrix.rotate(rotateAngle);
     362                image = image.transformed(matrix);
     363            }
     364        }
    340365    }
    341366}
    342367
  • mythgallery/galleryutil.cpp

     
    3131#include "galleryutil.h"
    3232#include "thumbgenerator.h"
    3333
    34 #ifdef EXIF_SUPPORT
    35 #include <libexif/exif-data.h>
    36 #include <libexif/exif-entry.h>
    37 // include "exif.hpp"
    38 #endif // EXIF_SUPPORT
    39 
    4034#define LOC QString("GalleryUtil:")
    4135#define LOC_ERR QString("GalleryUtil, Error:")
    4236
     
    123117    return false;
    124118}
    125119
    126 long GalleryUtil::GetNaturalRotation(const QString &filePathString)
     120long GalleryUtil::GetNaturalRotation(const QString &filePath)
    127121{
    128     long rotateAngle = 0;
     122    // default value if no value is found
     123    long rotateAngle = -1;
     124
     125#ifdef EXIF_SUPPORT
     126    // get the value from the header. Check also with different languages
     127    // because the value depends on the language used by the camera
     128    QString value = GetExifHeaderTag( filePath, EXIF_TAG_ORIENTATION);
     129
     130    if (value == "left - bottom" ||
     131        value == "links - unten")
     132    {
     133        rotateAngle = -90;
     134    }
     135    else if (value == "right - top" ||
     136             value == "rechts - oben")
     137    {
     138        rotateAngle = 90;
     139    }
     140#endif
     141
     142    return rotateAngle;
     143}
     144
     145long GalleryUtil::GetNaturalRotationDB(const QString &filePath, bool *ok)
     146{
     147    // default value if no value is found
     148    long angle = -1;
     149
     150    *ok = false;
     151    MSqlQuery query(MSqlQuery::InitCon());
     152
     153    // first try to find the exact file
     154    query.prepare(
     155        "SELECT angle "
     156        "FROM gallerymetadata "
     157        "WHERE image = :PATH");
     158    query.bindValue(":PATH", filePath);
     159
     160    if (!query.exec() || !query.isActive())
     161    {
     162        MythDB::DBError("get_rotation_angle", query);
     163    }
     164    else if (query.next())
     165    {
     166        *ok = true;
     167        return query.value(0).toString().toLong();
     168    }
     169
     170    // second try to find the first image in the same directory
     171    query.prepare(
     172        "SELECT angle, image "
     173        "FROM gallerymetadata "
     174        "WHERE image LIKE :PATH "
     175        "ORDER BY image");
     176    query.bindValue(":PATH", filePath + '%');
     177
     178    if (!query.exec() || !query.isActive())
     179    {
     180        MythDB::DBError("get_rotation_angle", query);
     181    }
     182    else if (query.next())
     183    {
     184        *ok = true;
     185        return query.value(0).toString().toLong();
     186    }
     187
     188    return angle;
     189}
     190
     191QString GalleryUtil::GetCaption(const QString &filePath)
     192{
     193    QString caption("");
     194
     195#ifdef EXIF_SUPPORT
     196    // try to get the user comment
     197    caption = GetExifHeaderTag( filePath, EXIF_TAG_USER_COMMENT);
     198
     199    if(!caption.isEmpty())
     200        return caption;
     201
     202    // try to get the tag image description
     203    caption = GetExifHeaderTag( filePath, EXIF_TAG_IMAGE_DESCRIPTION);
     204    if(!caption.isEmpty())
     205        return caption;
     206#endif
     207
     208    return caption;
     209}
     210
     211long GalleryUtil::GetDateTime(const QString &filePath)
     212{
     213    // default value if no value is found
     214    long utcTime = 0;
     215
     216#ifdef EXIF_SUPPORT
     217    QString value = GetExifHeaderTag( filePath, EXIF_TAG_DATE_TIME);
     218
     219    // convert the string into the UTC time. We need to split
     220    // the exif time format, which is this: "2006:07:21 18:54:58"
     221    bool ok;
     222    QDateTime dateTime = QDateTime( QDate( value.mid(0,4).toInt(&ok, 10),
     223                                           value.mid(5,2).toInt(&ok, 10),
     224                                           value.mid(8,2).toInt(&ok, 10)),
     225                                    QTime( value.mid(11,2).toInt(&ok, 10),
     226                                           value.mid(14,2).toInt(&ok, 10),
     227                                           value.mid(17,2).toInt(&ok, 10), 0));
     228
     229    // convert it to the utc time so we can easily compare it later.
     230    utcTime = dateTime.toTime_t();
     231#endif
     232
     233    return utcTime;
     234}
     235
     236long GalleryUtil::GetDateTimeDB(const QString &filePath, bool *ok)
     237{
     238    // default value if no value is found
     239    long dateTime = 0;
     240
     241    *ok = false;
     242    MSqlQuery query(MSqlQuery::InitCon());
     243
     244    // first try to find the exact file
     245    query.prepare(
     246        "SELECT datetime "
     247        "FROM gallerymetadata "
     248        "WHERE image = :PATH");
     249    query.bindValue(":PATH", filePath);
     250
     251    if (!query.exec() || !query.isActive())
     252    {
     253        MythDB::DBError("get_datetime", query);
     254    }
     255    else if (query.next())
     256    {
     257        *ok = true;
     258        return query.value(0).toString().toLong();
     259    }
     260
     261    // second try to find the first image in the same directory
     262    query.prepare(
     263        "SELECT datetime, image "
     264        "FROM gallerymetadata "
     265        "WHERE image LIKE :PATH "
     266        "ORDER BY image");
     267    query.bindValue(":PATH", filePath + '%');
     268
     269    if (!query.exec() || !query.isActive())
     270    {
     271        MythDB::DBError("get_datetime", query);
     272     }
     273    else if (query.next())
     274    {
     275        *ok = true;
     276        return query.value(0).toString().toLong();
     277    }
     278
     279    // if everything fails return the default
     280    return dateTime;
     281}
     282
     283void GalleryUtil::SetDateTimeDB(const QString &filePath, long dateTime)
     284{
     285    MSqlQuery query(MSqlQuery::InitCon());
     286    query.prepare(
     287        "REPLACE INTO gallerymetadata "
     288        "SET image    = :IMAGE, "
     289        "    datetime = :DATETIME");
     290    query.bindValue(":IMAGE", filePath);
     291    query.bindValue(":DATETIME", QString::number(dateTime,10));
     292
     293    if (!query.exec())
     294        MythDB::DBError("set_datetime", query);
     295}
     296
     297void GalleryUtil::SetNaturalRotationDB(QString &filePath, long angle)
     298{
     299    MSqlQuery query(MSqlQuery::InitCon());
     300    query.prepare(
     301        "REPLACE INTO gallerymetadata "
     302        "SET image = :IMAGE, "
     303        "    angle = :ANGLE");
     304    query.bindValue(":IMAGE", filePath);
     305    query.bindValue(":ANGLE", QString::number(angle, 10));
     306
     307    if (!query.exec())
     308        MythDB::DBError("set_rotation_angle", query);
     309}
     310
     311#ifdef EXIF_SUPPORT
     312QString GalleryUtil::GetExifHeaderTag(const QString &filePathString, ExifTag exifHeaderTag)
     313{
     314    QString value("");
    129315    QByteArray filePathBA = filePathString.toLocal8Bit();
     316
    130317    const char *filePath = filePathBA.constData();
    131 
    132318    try
    133319    {
    134 #ifdef EXIF_SUPPORT
     320        // get the exif header from the specified file
    135321        char *exifvalue = new char[1024];
    136322        ExifData *data = exif_data_new_from_file (filePath);
    137323        if (data)
    138324        {
     325            // we have some data, go through all available header
     326            // tags and stop when we have reached the desired tag
    139327            for (int i = 0; i < EXIF_IFD_COUNT; i++)
    140328            {
    141                     ExifEntry *entry = exif_content_get_entry (data->ifd[i],
    142                                                         EXIF_TAG_ORIENTATION);
     329                    ExifEntry *entry = exif_content_get_entry (data->ifd[i], exifHeaderTag);
    143330                    if (entry)
    144331                    {
     332                        // there is data in the desired header tag now get the
     333                        // value either by the new or standard exif library method
    145334#if NEW_LIB_EXIF
    146335                        exif_entry_get_value(entry, exifvalue, 1023);
    147                         QString value = exifvalue;
     336                        value = exifvalue;
    148337#else
    149                         QString value = exif_entry_get_value(entry);
     338                        value = exif_entry_get_value(entry);
    150339#endif
    151                         if (value == "left - bottom")
    152                         {
    153                           rotateAngle = -90;
    154                         }
    155                         else if (value == "right - top")
    156                         {
    157                           rotateAngle = 90;
    158                         }
    159340                        break;
    160341                    }
    161342            }
     
    169350        }
    170351       
    171352        delete [] exifvalue;
    172        
    173         /*
    174         Exiv2::ExifData exifData;
    175          int rc = exifData.read(filePath);
    176         if (!rc)
    177         {
    178             Exiv2::ExifKey key = Exiv2::ExifKey("Exif.Image.Orientation");
    179             Exiv2::ExifData::iterator pos = exifData.findKey(key);
    180             if (pos != exifData.end())
    181             {
    182                 long orientation = pos->toLong();
    183                 switch (orientation)
    184                 {
    185                     case 6:
    186                         rotateAngle = 90;
    187                         break;
    188                     case 8:
    189                         rotateAngle = -90;
    190                         break;
    191                     default:
    192                         rotateAngle = 0;
    193                         break;
    194                 }
    195             }
    196         }
    197         */
    198 #endif // EXIF_SUPPORT
    199353    }
    200354    catch (...)
    201355    {
     
    204358                .arg(filePathString));
    205359    }
    206360
    207     return rotateAngle;
     361    return value;
    208362}
     363#endif
    209364
    210365bool GalleryUtil::LoadDirectory(ThumbList& itemList, const QString& dir,
    211366                                int sortorder, bool recurse,
    212367                                ThumbHash *itemHash, ThumbGenerator* thumbGen)
    213368{
    214     QString blah = dir;
    215     QDir d(blah);
     369    QDir d(dir);
    216370    QString currDir = d.absolutePath();
    217371
    218372    bool isGallery;
     
    224378    if (thumbGen)
    225379        thumbGen->getThumbcacheDir(currDir);
    226380
    227     QFileInfoList list = d.entryInfoList(GetMediaFilter(),
    228                                          QDir::Files | QDir::AllDirs,
    229                                          (QDir::SortFlag)sortorder);
     381    // these are used more than once so declare them here.
     382    QFileInfoList list;
     383    QFileInfoList::const_iterator it;
     384    const QFileInfo *fi;
    230385
     386#ifdef EXIF_SUPPORT
     387    // check if the directories and files should be
     388    // sorted by creation time (exif header information)
     389    if (sortorder < 4096 )
     390    {
     391#endif
     392        // sort the usual way
     393        list = d.entryInfoList(GetMediaFilter(),
     394                            QDir::Files | QDir::AllDirs,
     395                            (QDir::SortFlag)sortorder);
     396#ifdef EXIF_SUPPORT
     397    }
     398    else
     399    {
     400        // These are the lists that will temporarily
     401        // contain the directories and the sorted files.
     402        QFileInfoList dirList;
     403        QFileInfoList fileList;
     404        QFileInfoList fileListExif;
     405        QMap<long, QFileInfo> fileListMap;
     406
     407        // fallback sorting order
     408        int tempsortorder = QDir::Name | QDir::DirsFirst | QDir::IgnoreCase;
     409        list = d.entryInfoList(GetMediaFilter(),
     410                            QDir::Files | QDir::AllDirs,
     411                            (QDir::SortFlag)tempsortorder);
     412
     413        // go through the list and get the exif time for each file
     414        it = list.begin();
     415        while (it != list.end())
     416        {
     417            fi = &(*it);
     418            ++it;
     419
     420            // get the directories alphabetically in the dirlist and
     421            // the files that have time information in the filelistmap.
     422            // The files that have no time information go into the filelist.
     423            // They will later be combined to get the big list again.
     424            if ( fi->isDir() )
     425            {
     426                dirList.append(*fi);
     427            }
     428            else
     429            {
     430                // load the date time from the database to speed up
     431                // the loading and sorting time. If the data is not available
     432                // add the exif header value in the database.
     433                bool ok = false;
     434                long dateTime = GetDateTimeDB(fi->canonicalFilePath(), &ok);
     435
     436                if (dateTime == 0 || !ok)
     437                {
     438                    // we dont have a value. try to get it from the exif header
     439                    dateTime = GetDateTime(fi->canonicalFilePath());
     440
     441                    // if we have a value then update the database
     442                    if ( dateTime > 0 )
     443                        SetDateTimeDB(fi->canonicalFilePath(), dateTime);
     444                }
     445
     446                // if we have the exif time, place the fileinfo object in the qmap
     447                // the map will automatically sort the entries by the time
     448                if ( dateTime > 0 )
     449                    fileListMap.insert(dateTime, *fi);
     450                else
     451                    fileList.append(*fi);
     452            }
     453        }
     454
     455        // the files with the time information will be placed in
     456        // the list in the order specified in the settings screen
     457        QMap<long, QFileInfo>::const_iterator i = fileListMap.constBegin();
     458        while (i != fileListMap.constEnd())
     459        {
     460            if ( sortorder == 0x1000 )
     461                // sort the files oldest first
     462                fileListExif.append( i.value() );
     463            else
     464                // sort the files newest first
     465                fileListExif.prepend( i.value() );
     466
     467            ++i;
     468        }
     469
     470        // the list has already the sorted files with the time
     471        // information in it. save the directories in the front
     472        // and put the remaining files at the end.
     473        list.clear();
     474        list = list.operator +( dirList );
     475        list = list.operator +( fileListExif );
     476        list = list.operator +( fileList );
     477    }
     478#endif
     479
    231480    if (list.isEmpty())
    232481        return false;
    233482
    234     QFileInfoList::const_iterator it = list.begin();
    235     const QFileInfo *fi;
    236 
    237483    if (thumbGen)
    238484    {
    239485        thumbGen->cancel();
    240486        thumbGen->setDirectory(currDir, isGallery);
    241487    }
    242488
     489    it = list.begin();
    243490    while (it != list.end())
    244491    {
    245492        fi = &(*it);
     
    275522                thumbGen->addFile(item->GetName());
    276523        }
    277524    }
    278 
    279525    return isGallery;
    280526}
    281527
    282 QString GalleryUtil::GetCaption(const QString &filePath)
    283 {
    284     QString caption("");
    285 
    286     try
    287     {
    288 #ifdef EXIF_SUPPORT
    289         char *exifvalue = new char[1024];
    290         ExifData *data = exif_data_new_from_file(
    291             filePath.toLocal8Bit().constData());
    292         if (data)
    293         {
    294             for (int i = 0; i < EXIF_IFD_COUNT; i++)
    295             {
    296                 ExifEntry *entry = exif_content_get_entry (data->ifd[i],
    297                                                     EXIF_TAG_USER_COMMENT);
    298                 if (entry)
    299                 {
    300 #if NEW_LIB_EXIF
    301                     exif_entry_get_value(entry, exifvalue, 1023);
    302                     caption = exifvalue;
    303 #else
    304                     caption = exif_entry_get_value(entry);
    305 #endif
    306                     // Found one, done
    307                     if(!caption.isEmpty())
    308                        break;
    309                 }
    310 
    311                 entry = exif_content_get_entry (data->ifd[i],
    312                                                 EXIF_TAG_IMAGE_DESCRIPTION);
    313                 if (entry)
    314                 {
    315 #if NEW_LIB_EXIF
    316                     exif_entry_get_value(entry, exifvalue, 1023);
    317                     caption = exifvalue;
    318 #else
    319                     caption = exif_entry_get_value(entry);
    320 #endif
    321                     // Found one, done
    322                     if(!caption.isEmpty())
    323                        break;
    324                 }
    325             }
    326             exif_data_free(data);
    327         }
    328         else
    329         {
    330            VERBOSE(VB_FILE, LOC_ERR +
    331                    QString("Could not load exif data from '%1'")
    332                    .arg(filePath));
    333         }
    334 
    335         delete [] exifvalue;
    336 #endif // EXIF_SUPPORT
    337     }
    338     catch (...)
    339     {
    340         VERBOSE(VB_IMPORTANT, LOC_ERR +
    341                 QString("Failed to extract EXIF headers from '%1'")
    342                 .arg(filePath));
    343     }
    344 
    345     return caption;
    346 }
    347 
    348528bool GalleryUtil::Copy(const QFileInfo &src, QFileInfo &dst)
    349529{
    350530    if (src.isDir())