scancontroller.cpp

来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 554 行 · 第 1/2 页

CPP
554
字号
/*************************************************************************** *   Copyright (C) 2003-2005 by The Amarok Developers                      * *                                                                         * *   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 of the License, 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.                          * *                                                                         * *   You should have received a copy of the GNU General Public License     * *   along with this program; if not, write to the                         * *   Free Software Foundation, Inc.,                                       * *   51 Franklin Steet, Fifth Floor, Boston, MA  02111-1307, USA.          * ***************************************************************************/#define DEBUG_PREFIX "ScanController"#include "amarok.h"#include "amarokconfig.h"#include "collectiondb.h"#include "debug.h"#include "metabundle.h"#include "mountpointmanager.h"#include "playlist.h"#include "playlistbrowser.h"#include "scancontroller.h"#include "statusbar.h"#include <qdeepcopy.h>#include <qfileinfo.h>#include <qtextcodec.h>#include <dcopref.h>#include <kapplication.h>#include <klocale.h>#include <kmessagebox.h>////////////////////////////////////////////////////////////////////////////////// class ScanController////////////////////////////////////////////////////////////////////////////////ScanController* ScanController::currController = 0;ScanController* ScanController::instance(){    return currController;}void ScanController::setInstance( ScanController* curr ){    currController = curr;}ScanController::ScanController( CollectionDB* parent, bool incremental, const QStringList& folders )    : DependentJob( parent, "CollectionScanner" )    , QXmlDefaultHandler()    , m_scanner( new Amarok::ProcIO() )    , m_folders( QDeepCopy<QStringList>( folders ) )    , m_incremental( incremental )    , m_hasChanged( false )    , m_source( new QXmlInputSource() )    , m_reader( new QXmlSimpleReader() )    , m_waitingBundle( 0 )    , m_lastCommandPaused( false )    , m_isPaused( false )    , m_tablesCreated( false )    , m_scanCount( 0 ){    DEBUG_BLOCK    ScanController::setInstance( this );    m_reader->setContentHandler( this );    m_reader->parse( m_source, true );    connect( this, SIGNAL( scanDone( bool ) ), MountPointManager::instance(), SLOT( updateStatisticsURLs( bool ) ) );    connect( m_scanner, SIGNAL( readReady( KProcIO* ) ), SLOT( slotReadReady() ) );    *m_scanner << "amarokcollectionscanner";    *m_scanner << "--nocrashhandler"; // We want to be able to catch SIGSEGV    // KProcess must be started from the GUI thread, so we're invoking the scanner    // here in the ctor:    if( incremental )    {        setDescription( i18n( "Updating Collection" ) );        initIncremental();    }    else    {        setDescription( i18n( "Building Collection" ) );        *m_scanner << "-p";        if( AmarokConfig::scanRecursively() ) *m_scanner << "-r";        *m_scanner << m_folders;        m_scanner->start();    }}ScanController::~ScanController(){    DEBUG_BLOCK    if( !isAborted() && !m_crashedFiles.empty() ) {        KMessageBox::information( 0, i18n( "<p>The Collection Scanner was unable to process these files:</p>" ) +                                  "<i>" + m_crashedFiles.join( "<br>" ) + "</i>",                                  i18n( "Collection Scan Report" ) );    }    else if( m_crashedFiles.size() >= MAX_RESTARTS ) {        KMessageBox::error( 0, i18n( "<p>Sorry, the Collection Scan was aborted, since too many problems were encountered.</p>" ) +                            "<p>Advice: A common source for this problem is a broken 'TagLib' package on your computer. Replacing this package may help fixing the issue.</p>"                            "<p>The following files caused problems:</p>" +                            "<i>" + m_crashedFiles.join( "<br>" ) + "</i>",                            i18n( "Collection Scan Error" ) );    }    m_scanner->kill();    delete m_scanner;    delete m_reader;    delete m_source;    ScanController::setInstance( 0 );}// Cause the CollectionDB to emit fileDeleted() signalsvoidScanController::completeJob( void ){    m_fileMapsMutex.lock();    QMap<QString,QString>::Iterator it;    if( !m_incremental )    {        CollectionDB::instance()->emitFilesAdded( m_filesAdded );    }    else    {        for( it = m_filesAdded.begin(); it != m_filesAdded.end(); ++it )        {            if( m_filesDeleted.contains( it.key() ) )                m_filesDeleted.remove( it.key() );        }        for( it = m_filesAdded.begin(); it != m_filesAdded.end(); ++it )            CollectionDB::instance()->emitFileAdded( it.data(), it.key() );        for( it = m_filesDeleted.begin(); it != m_filesDeleted.end(); ++it )            CollectionDB::instance()->emitFileDeleted( it.data(), it.key() );    }    m_fileMapsMutex.unlock();    emit scanDone( !m_incremental || m_hasChanged );    ThreadManager::DependentJob::completeJob();}/** * The Incremental Scanner works as follows: Here we check the mtime of every directory in the "directories" * table and store all changed directories in m_folders. * * These directories are then scanned in CollectionReader::doJob(), with m_recursively set according to the * user's preference, so the user can add directories or whole directory trees, too. Since we don't want to * rescan unchanged subdirectories, CollectionReader::readDir() checks if we are scanning recursively and * prevents that. */voidScanController::initIncremental(){    DEBUG_BLOCK    connect( CollectionDB::instance(),             SIGNAL( fileMoved( const QString &, const QString & ) ),             SLOT( slotFileMoved( const QString &, const QString & ) ) );    connect( CollectionDB::instance(),             SIGNAL( fileMoved( const QString &, const QString &, const QString & ) ),             SLOT( slotFileMoved( const QString &, const QString & ) ) );    IdList list = MountPointManager::instance()->getMountedDeviceIds();    QString deviceIds;    foreachType( IdList, list )    {        if ( !deviceIds.isEmpty() ) deviceIds += ',';        deviceIds += QString::number(*it);    }    const QStringList values = CollectionDB::instance()->query(            QString( "SELECT deviceid, dir, changedate FROM directories WHERE deviceid IN (%1);" )            .arg( deviceIds ) );    foreach( values )    {        int id = (*it).toInt();        const QString folder = MountPointManager::instance()->getAbsolutePath( id, (*++it) );        const QString mtime  = *++it;        const QFileInfo info( folder );        if( info.exists() )        {            if( info.lastModified().toTime_t() != mtime.toUInt() )            {                m_folders << folder;                debug() << "Collection dir changed: " << folder << endl;            }        }        else        {            // this folder has been removed            m_folders << folder;            debug() << "Collection dir removed: " << folder << endl;        }        kapp->processEvents(); // Don't block the GUI    }    if ( !m_folders.isEmpty() )    {        debug() << "Collection was modified." << endl;        m_hasChanged = true;        Amarok::StatusBar::instance()->shortMessage( i18n( "Updating Collection..." ) );        // Start scanner process        if( AmarokConfig::scanRecursively() ) *m_scanner << "-r";        *m_scanner << "-i";        *m_scanner << m_folders;        m_scanner->start();    }}boolScanController::doJob(){    DEBUG_BLOCK    if( !CollectionDB::instance()->isConnected() )        return false;    if( m_incremental && !m_hasChanged )        return true;    CollectionDB::instance()->createTables( true );    m_tablesCreated = true;    //For a full rescan, we might not have cleared tags table (for devices not plugged    //in), so preserve the necessary other tables (eg artist)    CollectionDB::instance()->prepareTempTables();    CollectionDB::instance()->invalidateArtistAlbumCache();main_loop:    uint delayCount = 100;    /// Main Loop    while( !isAborted() ) {        if( m_xmlData.isNull() ) {            if( !m_scanner->isRunning() )                delayCount--;            // Wait a bit after process has exited, so that we have time to parse all data            if( delayCount == 0 )                break;            msleep( 15 );        }        else {            m_dataMutex.lock();            QDeepCopy<QString> data = m_xmlData;            m_source->setData( data );            m_xmlData = QString::null;            m_dataMutex.unlock();            if( !m_reader->parseContinue() )                ::warning() << "parseContinue() failed: " << errorString() << endl << data << endl;        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?