|
|
|
/* ============================================================
|
|
|
|
*
|
|
|
|
* This file is a part of digiKam project
|
|
|
|
* http://www.digikam.org
|
|
|
|
*
|
|
|
|
* Date : 2005-01-01
|
|
|
|
* Description : scan pictures interface.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2005-2006 by Tom Albers <tomalbers@kde.nl>
|
|
|
|
* Copyright (C) 2007-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it
|
|
|
|
* and/or modify it under the terms of the GNU General
|
|
|
|
* Public License as published by the Free Software Foundation;
|
|
|
|
* either version 2, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* ============================================================ */
|
|
|
|
|
|
|
|
// C Ansi includes.
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
#include <sys/time.h>
|
|
|
|
}
|
|
|
|
|
|
|
|
// C++ includes.
|
|
|
|
|
|
|
|
#include <ctime>
|
|
|
|
#include <cstdlib>
|
|
|
|
|
|
|
|
// TQt includes.
|
|
|
|
|
|
|
|
#include <tqapplication.h>
|
|
|
|
#include <tqstring.h>
|
|
|
|
#include <tqstringlist.h>
|
|
|
|
#include <tqmap.h>
|
|
|
|
#include <tqdir.h>
|
|
|
|
#include <tqfileinfo.h>
|
|
|
|
#include <tqwhatsthis.h>
|
|
|
|
#include <tqpixmap.h>
|
|
|
|
|
|
|
|
// KDE includes.
|
|
|
|
|
|
|
|
#include <kprogress.h>
|
|
|
|
#include <tdemessagebox.h>
|
|
|
|
#include <tdeapplication.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
|
|
|
|
// Local includes.
|
|
|
|
|
|
|
|
#include "ddebug.h"
|
|
|
|
#include "dprogressdlg.h"
|
|
|
|
#include "dmetadata.h"
|
|
|
|
#include "albumdb.h"
|
|
|
|
#include "albummanager.h"
|
|
|
|
#include "splashscreen.h"
|
|
|
|
#include "scanlib.h"
|
|
|
|
|
|
|
|
/** @file scanlib.cpp*/
|
|
|
|
|
|
|
|
namespace Digikam
|
|
|
|
{
|
|
|
|
|
|
|
|
ScanLib::ScanLib(SplashScreen *splash)
|
|
|
|
{
|
|
|
|
m_splash = splash;
|
|
|
|
m_progressBar = new DProgressDlg(0);
|
|
|
|
m_progressBar->setInitialSize(TQSize(500, 100), true);
|
|
|
|
m_progressBar->setActionListVSBarVisible(false);
|
|
|
|
TQWhatsThis::add( m_progressBar, i18n("This shows the progress of the "
|
|
|
|
"scan. During the scan, all files on disk are registered in a "
|
|
|
|
"database. This is required for sorting by exif-date, and also speeds up "
|
|
|
|
"the overall performance of digiKam.") );
|
|
|
|
|
|
|
|
// these two lines prevent the dialog to be shown in
|
|
|
|
// findFoldersWhichDoNotExist() method.
|
|
|
|
m_progressBar->progressBar()->setTotalSteps(1);
|
|
|
|
m_progressBar->progressBar()->setProgress(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
ScanLib::~ScanLib()
|
|
|
|
{
|
|
|
|
delete m_progressBar;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanLib::startScan()
|
|
|
|
{
|
|
|
|
struct timeval tv1, tv2;
|
|
|
|
TQPixmap pix = TDEApplication::kApplication()->iconLoader()->loadIcon(
|
|
|
|
"system-run", TDEIcon::NoGroup, 32);
|
|
|
|
|
|
|
|
TQString message = i18n("Finding non-existent Albums");
|
|
|
|
if (m_splash) m_splash->message(message);
|
|
|
|
else m_progressBar->addedAction(pix, message);
|
|
|
|
gettimeofday(&tv1, 0);
|
|
|
|
findFoldersWhichDoNotExist();
|
|
|
|
gettimeofday(&tv2, 0);
|
|
|
|
timing(message, tv1, tv2);
|
|
|
|
|
|
|
|
message = i18n("Finding items not in database");
|
|
|
|
if (m_splash) m_splash->message(message);
|
|
|
|
else m_progressBar->addedAction(pix, message);
|
|
|
|
gettimeofday(&tv1, 0);
|
|
|
|
findMissingItems();
|
|
|
|
gettimeofday(&tv2, 0);
|
|
|
|
timing(message, tv1, tv2);
|
|
|
|
|
|
|
|
message = i18n("Updating items without a date");
|
|
|
|
if (m_splash) m_splash->message(message);
|
|
|
|
else m_progressBar->addedAction(pix, message);
|
|
|
|
gettimeofday(&tv1, 0);
|
|
|
|
updateItemsWithoutDate();
|
|
|
|
gettimeofday(&tv2, 0);
|
|
|
|
timing(message, tv1, tv2);
|
|
|
|
|
|
|
|
deleteStaleEntries();
|
|
|
|
|
|
|
|
AlbumDB* db = AlbumManager::instance()->albumDB();
|
|
|
|
db->setSetting("Scanned", TQDateTime::currentDateTime().toString(Qt::ISODate));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanLib::findFoldersWhichDoNotExist()
|
|
|
|
{
|
|
|
|
TQMap<TQString, int> toBeDeleted;
|
|
|
|
TQString basePath(AlbumManager::instance()->getLibraryPath());
|
|
|
|
|
|
|
|
AlbumDB* db = AlbumManager::instance()->albumDB();
|
|
|
|
AlbumInfo::List aList = db->scanAlbums();
|
|
|
|
|
|
|
|
for (AlbumInfo::List::iterator it = aList.begin(); it != aList.end(); ++it)
|
|
|
|
{
|
|
|
|
AlbumInfo info = *it;
|
|
|
|
info.url = TQDir::cleanDirPath(info.url);
|
|
|
|
TQFileInfo fi(basePath + info.url);
|
|
|
|
if (!fi.exists() || !fi.isDir())
|
|
|
|
{
|
|
|
|
toBeDeleted[info.url] = info.id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
kapp->processEvents();
|
|
|
|
|
|
|
|
if (!toBeDeleted.isEmpty())
|
|
|
|
{
|
|
|
|
int rc = KMessageBox::warningYesNoList(0,
|
|
|
|
i18n("<p>There is an album in the database which does not appear to "
|
|
|
|
"be on disk. This album should be removed from the database, "
|
|
|
|
"however you may lose information because all images "
|
|
|
|
"associated with this album will be removed from the database "
|
|
|
|
"as well.<p>"
|
|
|
|
"digiKam cannot continue without removing the items "
|
|
|
|
"from the database because all views depend on the information "
|
|
|
|
"in the database. Do you want them to be removed from the "
|
|
|
|
"database?",
|
|
|
|
"<p>There are %n albums in the database which do not appear to "
|
|
|
|
"be on disk. These albums should be removed from the database, "
|
|
|
|
"however you may lose information because all images "
|
|
|
|
"associated with these albums will be removed from the database "
|
|
|
|
"as well.<p>"
|
|
|
|
"digiKam cannot continue without removing the items "
|
|
|
|
"from the database because all views depend on the information "
|
|
|
|
"in the database. Do you want them to be removed from the "
|
|
|
|
"database?",
|
|
|
|
toBeDeleted.count()),
|
|
|
|
toBeDeleted.keys(),
|
|
|
|
i18n("Albums are Missing"));
|
|
|
|
|
|
|
|
if (rc != KMessageBox::Yes)
|
|
|
|
exit(0);
|
|
|
|
|
|
|
|
TQMapIterator<TQString,int> it;
|
|
|
|
for (it = toBeDeleted.begin() ; it != toBeDeleted.end(); ++it)
|
|
|
|
{
|
|
|
|
DDebug() << "Removing Album: " << it.key() << endl;
|
|
|
|
db->deleteAlbum( it.data() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanLib::findMissingItems(const TQString &path)
|
|
|
|
{
|
|
|
|
allFiles(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanLib::findMissingItems()
|
|
|
|
{
|
|
|
|
TQString albumPath = AlbumManager::instance()->getLibraryPath();
|
|
|
|
albumPath = TQDir::cleanDirPath(albumPath);
|
|
|
|
|
|
|
|
m_progressBar->setAllowCancel( false );
|
|
|
|
m_progressBar->showCancelButton (false );
|
|
|
|
m_progressBar->progressBar()->setProgress( 0 );
|
|
|
|
m_progressBar->setLabel(i18n("Scanning items, please wait..."));
|
|
|
|
m_progressBar->progressBar()->setTotalSteps( countItemsInFolder( albumPath ) );
|
|
|
|
if (!m_splash) m_progressBar->show();
|
|
|
|
kapp->processEvents();
|
|
|
|
|
|
|
|
TQDir dir(albumPath);
|
|
|
|
TQStringList fileList(dir.entryList(TQDir::Dirs));
|
|
|
|
TQPixmap pix = TDEApplication::kApplication()->iconLoader()->loadIcon(
|
|
|
|
"folder_image", TDEIcon::NoGroup, 32);
|
|
|
|
|
|
|
|
AlbumDB* db = AlbumManager::instance()->albumDB();
|
|
|
|
db->beginTransaction();
|
|
|
|
|
|
|
|
for (TQStringList::iterator it = fileList.begin(); it != fileList.end(); ++it)
|
|
|
|
{
|
|
|
|
if ((*it) == "." || (*it) == "..")
|
|
|
|
continue;
|
|
|
|
|
|
|
|
TQString path = albumPath + '/' + (*it);
|
|
|
|
allFiles(path);
|
|
|
|
m_progressBar->addedAction(pix, path);
|
|
|
|
}
|
|
|
|
db->commitTransaction();
|
|
|
|
|
|
|
|
m_progressBar->hide();
|
|
|
|
kapp->processEvents();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanLib::updateItemsWithoutDate()
|
|
|
|
{
|
|
|
|
AlbumDB* db = AlbumManager::instance()->albumDB();
|
|
|
|
TQStringList urls = db->getAllItemURLsWithoutDate();
|
|
|
|
|
|
|
|
if (urls.isEmpty())
|
|
|
|
{
|
|
|
|
m_progressBar->progressBar()->setTotalSteps(1);
|
|
|
|
m_progressBar->progressBar()->setProgress(1);
|
|
|
|
m_progressBar->hide();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_progressBar->setAllowCancel( false );
|
|
|
|
m_progressBar->showCancelButton (false );
|
|
|
|
m_progressBar->progressBar()->setProgress(0);
|
|
|
|
m_progressBar->progressBar()->setTotalSteps(urls.count());
|
|
|
|
m_progressBar->setLabel(i18n("Updating items, please wait..."));
|
|
|
|
m_progressBar->show();
|
|
|
|
kapp->processEvents();
|
|
|
|
|
|
|
|
TQString basePath = AlbumManager::instance()->getLibraryPath();
|
|
|
|
basePath = TQDir::cleanDirPath(basePath);
|
|
|
|
|
|
|
|
db->beginTransaction();
|
|
|
|
|
|
|
|
int counter=0;
|
|
|
|
for (TQStringList::iterator it = urls.begin(); it != urls.end(); ++it)
|
|
|
|
{
|
|
|
|
m_progressBar->progressBar()->advance(1);
|
|
|
|
++counter;
|
|
|
|
if ( counter % 30 == 0 )
|
|
|
|
{
|
|
|
|
kapp->processEvents();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQFileInfo fi(*it);
|
|
|
|
TQString albumURL = fi.dirPath();
|
|
|
|
albumURL = TQDir::cleanDirPath(albumURL.remove(basePath));
|
|
|
|
|
|
|
|
int albumID = db->getOrCreateAlbumId(albumURL);
|
|
|
|
|
|
|
|
if (albumID <= 0)
|
|
|
|
{
|
|
|
|
DWarning() << "Album ID == -1: " << albumURL << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fi.exists())
|
|
|
|
{
|
|
|
|
updateItemDate(albumURL, fi.fileName(), albumID);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TQPair<TQString, int> fileID = tqMakePair(fi.fileName(),albumID);
|
|
|
|
|
|
|
|
if (m_filesToBeDeleted.findIndex(fileID) == -1)
|
|
|
|
{
|
|
|
|
m_filesToBeDeleted.append(fileID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
db->commitTransaction();
|
|
|
|
|
|
|
|
m_progressBar->hide();
|
|
|
|
kapp->processEvents();
|
|
|
|
}
|
|
|
|
|
|
|
|
int ScanLib::countItemsInFolder(const TQString& directory)
|
|
|
|
{
|
|
|
|
int items = 0;
|
|
|
|
|
|
|
|
TQDir dir( directory );
|
|
|
|
if ( !dir.exists() or !dir.isReadable() )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
const TQFileInfoList *list = dir.entryInfoList();
|
|
|
|
TQFileInfoListIterator it( *list );
|
|
|
|
TQFileInfo *fi;
|
|
|
|
|
|
|
|
items += list->count();
|
|
|
|
|
|
|
|
while ( (fi = it.current()) != 0 )
|
|
|
|
{
|
|
|
|
if ( fi->isDir() &&
|
|
|
|
fi->fileName() != "." &&
|
|
|
|
fi->fileName() != "..")
|
|
|
|
{
|
|
|
|
items += countItemsInFolder( fi->filePath() );
|
|
|
|
}
|
|
|
|
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
|
|
|
|
return items;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanLib::allFiles(const TQString& directory)
|
|
|
|
{
|
|
|
|
TQDir dir( directory );
|
|
|
|
if ( !dir.exists() or !dir.isReadable() )
|
|
|
|
{
|
|
|
|
DWarning() << "Folder does not exist or is not readable: "
|
|
|
|
<< directory << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString basePath = AlbumManager::instance()->getLibraryPath();
|
|
|
|
basePath = TQDir::cleanDirPath(basePath);
|
|
|
|
|
|
|
|
TQString albumURL = directory;
|
|
|
|
albumURL = TQDir::cleanDirPath(albumURL.remove(basePath));
|
|
|
|
|
|
|
|
AlbumDB* db = AlbumManager::instance()->albumDB();
|
|
|
|
|
|
|
|
int albumID = db->getOrCreateAlbumId(albumURL);
|
|
|
|
|
|
|
|
if (albumID <= 0)
|
|
|
|
{
|
|
|
|
DWarning() << "Album ID == -1: " << albumURL << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList filesInAlbum = db->getItemNamesInAlbum( albumID );
|
|
|
|
TQMap<TQString, bool> filesFoundInDB;
|
|
|
|
|
|
|
|
for (TQStringList::iterator it = filesInAlbum.begin();
|
|
|
|
it != filesInAlbum.end(); ++it)
|
|
|
|
{
|
|
|
|
filesFoundInDB.insert(*it, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
const TQFileInfoList *list = dir.entryInfoList();
|
|
|
|
if (!list)
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQFileInfoListIterator it( *list );
|
|
|
|
TQFileInfo *fi;
|
|
|
|
|
|
|
|
m_progressBar->progressBar()->advance(list->count());
|
|
|
|
kapp->processEvents();
|
|
|
|
|
|
|
|
while ( (fi = it.current()) != 0 )
|
|
|
|
{
|
|
|
|
if ( fi->isFile())
|
|
|
|
{
|
|
|
|
if (filesFoundInDB.contains(fi->fileName()) )
|
|
|
|
{
|
|
|
|
filesFoundInDB.erase(fi->fileName());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
storeItemInDatabase(albumURL, fi->fileName(), albumID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( fi->isDir() && fi->fileName() != "." && fi->fileName() != "..")
|
|
|
|
{
|
|
|
|
allFiles( fi->filePath() );
|
|
|
|
}
|
|
|
|
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Removing items from the db which we did not see on disk.
|
|
|
|
if (!filesFoundInDB.isEmpty())
|
|
|
|
{
|
|
|
|
TQMapIterator<TQString,bool> it;
|
|
|
|
for (it = filesFoundInDB.begin(); it != filesFoundInDB.end(); ++it)
|
|
|
|
{
|
|
|
|
if (m_filesToBeDeleted.findIndex(tqMakePair(it.key(),albumID)) == -1)
|
|
|
|
{
|
|
|
|
m_filesToBeDeleted.append(tqMakePair(it.key(),albumID));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanLib::storeItemInDatabase(const TQString& albumURL,
|
|
|
|
const TQString& filename,
|
|
|
|
int albumID)
|
|
|
|
{
|
|
|
|
// Do not store items found in the root of the albumdb
|
|
|
|
if (albumURL.isEmpty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQString comment;
|
|
|
|
TQStringList keywords;
|
|
|
|
TQDateTime datetime;
|
|
|
|
int rating;
|
|
|
|
|
|
|
|
TQString filePath( AlbumManager::instance()->getLibraryPath());
|
|
|
|
filePath += albumURL + '/' + filename;
|
|
|
|
|
|
|
|
DMetadata metadata(filePath);
|
|
|
|
|
|
|
|
// Try to get comments from image :
|
|
|
|
// In first, from standard JPEG comments, or
|
|
|
|
// In second, from EXIF comments tag, or
|
|
|
|
// In third, from IPTC comments tag.
|
|
|
|
|
|
|
|
comment = metadata.getImageComment();
|
|
|
|
|
|
|
|
// Try to get date and time from image :
|
|
|
|
// In first, from EXIF date & time tags, or
|
|
|
|
// In second, from IPTC date & time tags.
|
|
|
|
|
|
|
|
datetime = metadata.getImageDateTime();
|
|
|
|
|
|
|
|
// Try to get image rating from IPTC Urgency tag
|
|
|
|
// else use file system time stamp.
|
|
|
|
rating = metadata.getImageRating();
|
|
|
|
|
|
|
|
if ( !datetime.isValid() )
|
|
|
|
{
|
|
|
|
TQFileInfo info( filePath );
|
|
|
|
datetime = info.lastModified();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to get image tags from IPTC keywords tags.
|
|
|
|
|
|
|
|
keywords = metadata.getImageKeywords();
|
|
|
|
|
|
|
|
AlbumDB* dbstore = AlbumManager::instance()->albumDB();
|
|
|
|
dbstore->addItem(albumID, filename, datetime, comment, rating, keywords);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanLib::updateItemDate(const TQString& albumURL,
|
|
|
|
const TQString& filename,
|
|
|
|
int albumID)
|
|
|
|
{
|
|
|
|
TQDateTime datetime;
|
|
|
|
|
|
|
|
TQString filePath( AlbumManager::instance()->getLibraryPath());
|
|
|
|
filePath += albumURL + '/' + filename;
|
|
|
|
|
|
|
|
DMetadata metadata(filePath);
|
|
|
|
|
|
|
|
// Trying to get date and time from image :
|
|
|
|
// In first, from EXIF date & time tags, or
|
|
|
|
// In second, from IPTC date & time tags.
|
|
|
|
|
|
|
|
datetime = metadata.getImageDateTime();
|
|
|
|
|
|
|
|
if ( !datetime.isValid() )
|
|
|
|
{
|
|
|
|
TQFileInfo info( filePath );
|
|
|
|
datetime = info.lastModified();
|
|
|
|
}
|
|
|
|
|
|
|
|
AlbumDB* dbstore = AlbumManager::instance()->albumDB();
|
|
|
|
dbstore->setItemDate(albumID, filename, datetime);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanLib::deleteStaleEntries()
|
|
|
|
{
|
|
|
|
TQStringList listToBeDeleted;
|
|
|
|
TQValueList< TQPair<TQString,int> >::iterator it;
|
|
|
|
|
|
|
|
for (it = m_filesToBeDeleted.begin() ; it != m_filesToBeDeleted.end(); ++it)
|
|
|
|
{
|
|
|
|
AlbumDB* dbstore = AlbumManager::instance()->albumDB();
|
|
|
|
TQString location = " (" + dbstore->getAlbumURL((*it).second) + ')';
|
|
|
|
|
|
|
|
listToBeDeleted.append((*it).first + location);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !m_filesToBeDeleted.isEmpty() )
|
|
|
|
{
|
|
|
|
int rc = KMessageBox::warningYesNoList(0,
|
|
|
|
i18n("<p>There is an item in the database which does not "
|
|
|
|
"appear to be on disk or is located in the root album of "
|
|
|
|
"the path. This file should be removed from the "
|
|
|
|
"database, however you may lose information.<p>"
|
|
|
|
"digiKam cannot continue without removing the item from "
|
|
|
|
"the database because all views depend on the information "
|
|
|
|
"in the database. Do you want it to be removed from the "
|
|
|
|
"database?",
|
|
|
|
"<p>There are %n items in the database which do not "
|
|
|
|
"appear to be on disk or are located in the root album of "
|
|
|
|
"the path. These files should be removed from the "
|
|
|
|
"database, however you may lose information.<p>"
|
|
|
|
"digiKam cannot continue without removing these items from "
|
|
|
|
"the database because all views depend on the information "
|
|
|
|
"in the database. Do you want them to be removed from the "
|
|
|
|
"database?",
|
|
|
|
listToBeDeleted.count()),
|
|
|
|
listToBeDeleted,
|
|
|
|
i18n("Files are Missing"));
|
|
|
|
|
|
|
|
if (rc != KMessageBox::Yes)
|
|
|
|
exit(0);
|
|
|
|
|
|
|
|
AlbumDB* db = AlbumManager::instance()->albumDB();
|
|
|
|
db->beginTransaction();
|
|
|
|
for (it = m_filesToBeDeleted.begin() ; it != m_filesToBeDeleted.end();
|
|
|
|
++it)
|
|
|
|
{
|
|
|
|
DDebug() << "Removing: " << (*it).first << " in "
|
|
|
|
<< (*it).second << endl;
|
|
|
|
db->deleteItem( (*it).second, (*it).first );
|
|
|
|
}
|
|
|
|
db->commitTransaction();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScanLib::timing(const TQString& text, struct timeval tv1, struct timeval tv2)
|
|
|
|
{
|
|
|
|
DDebug() << "ScanLib: "
|
|
|
|
<< text + ": "
|
|
|
|
<< (((tv2.tv_sec-tv1.tv_sec)*1000000 +
|
|
|
|
(tv2.tv_usec-tv1.tv_usec))/1000)
|
|
|
|
<< " ms" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Digikam
|