void FileSystemScanner::testIfFolderIsAddable(QDir* dir, bool recursive) const throw(EngineException*)
{
    tracer->sinvoked(__func__) << dir->absPath() << ", recursive: " << recursive << "..." << endl;

    // test if the given folder is already added
    Folder* folder;
    for (folder = m_engine->sourceDirs()->first(); folder; folder = m_engine->sourceDirs()->next() ) {

        if (*(folder->dir()) == *dir) {
            QString detailMsg = QString(i18n("The folder you have chosen is already added to KPhotoBook.\n"
                    "Folder: %1")).arg(folder->dir()->absPath());
            throw new EngineException(
                    i18n("You cannot add the same folder more than once to KPhotoBook."),
                    detailMsg
            );
        }

        QString folderPath = folder->dir()->absPath();
        QString newFolderPath = dir->absPath();

        if (folder->recursive()) {
            // test if the new folder is a subfolder of the current sourceFolder
            if (newFolderPath.startsWith(folderPath)) {
                QString detailMsg = QString(i18n("The folder you have chosen is a subfolder of a recursively added folder.\n"
                        "Folder: %1\nNew folder: %2")).arg(folderPath).arg(newFolderPath);
                throw new EngineException(
                        i18n("You cannot add a folder which is a subfolder of an already recursively added folder because"
                        "the chosen folder is already added implicitely."),
                        detailMsg
                 );
            }
        }

        if (recursive) {
            // test if the current folder is a subfolder of the new folder
            if (folderPath.startsWith(newFolderPath)) {
                QString detailMsg = QString(i18n("The folder you have chosen to add recursively is the parentfolder of at least "
                        "one already added folders.\nFolder: %1\nNew folder: %2")).arg(folderPath).arg(newFolderPath);
                throw new EngineException(
                        i18n("You cannot add the parentfolder of an already added folder recursively."),
                        detailMsg
                 );
            }
        }
    }

    tracer->debug(__func__, "ended");
}
void FileSystemScanner::rescanFolders(QPtrList<Folder>* folders, bool forceEXIF, bool fast)
{
    Folder* folder = 0;
    for (folder = folders->first(); folder; folder = folders->next()) {
        QString currentFolderPath = folder->dir()->absPath();

        tracer->sdebug(__func__) << "rescanning folder: " << folder->id() << ": " << currentFolderPath << endl;

        if (folder->dir()->exists()) {

            folder->setFound(true);

            if (!fast) {
                rescanFolder(folder, forceEXIF);
                if (m_cancel) {
                    return;
                }
            }

            if (folder->children() && folder->children()->count()) {
                rescanFolders(folder->children(), forceEXIF, fast);
            }

            // scan the filesystem for new folders
            if (!fast && folder->recursive()) {
                delete m_loopDetectionHelper;
                m_loopDetectionHelper = new QPtrList<QString>;
                m_loopDetectionHelper->setAutoDelete(true);
                m_loopDetectionHelper->append(new QString(folder->dir()->canonicalPath()));

                addFolders(folder);
            }
        } else {
            folder->setFound(false);

            tracer->sdebug(__func__) << "folder: " << folder->id() << ": '" << currentFolderPath << "' not found" << endl;
            emit(progress_folderNotFound(currentFolderPath));
        }
    }
}
void ImageImporter::initData() {
    const KMountPoint::List lst = KMountPoint::possibleMountPoints(KMountPoint::NeedMountOptions);
    for ( KMountPoint::List::ConstIterator it = lst.begin() ; it != lst.end() ; ++it ) {
        //so, I only show devices that are mountable by a user
        if (getuid() == 0 || (*it)->mountOptions().grep("user").size() > 0) {
            QString x = QString("%1 (%2)").arg((*it)->mountedFrom()).arg((*it)->mountPoint());
            m_cmbSourceDevice->insertItem(x);
        }
    }
    //after adding all available mountpoints, check the status of the current
    slotUpdateMountStatus();

    m_cmbSourceFolder->insertItem(Settings::imageImporterSourceFolder());
    m_cmbSourceFolder->setCurrentText(Settings::imageImporterSourceFolder());
    m_cmbSourceDevice->setCurrentText(Settings::imageImporterSourceDevice());
    m_txtSourceFilename->setText(Settings::imageImporterSourceFilenameRegexp());
    m_chkIgnoreCase->setChecked(Settings::imageImporterFilenameIgnoreCase());
    m_chkSrcIncludeSubfolders->setChecked(Settings::imageImporterSourceIncludeSubfolders());
    m_chkSrcRemoveFilesFromSrc->setChecked(Settings::imageImporterSourceRemoveAfterTransfer());

    m_groupArchive->setChecked(Settings::imageImporterArchiveImages());
    m_txtArchiveBaseFolder->setText(Settings::imageImporterArchiveBaseFolder());
    m_txtArchiveSubfolders->setText(Settings::imageImporterArchiveSubfolders());
    m_txtArchiveFilename->setText(Settings::imageImporterArchiveFilename());
    m_chkArchiveLowercase->setChecked(Settings::imageImporterArchiveLowercaseFilenames());

    //add all dirs from the album to the list of target folders
    Folder* sourceDir;
    for (
          sourceDir = m_photobook->engine()->sourceDirs()->first();
          sourceDir;
          sourceDir = m_photobook->engine()->sourceDirs()->next()
        )
    {
        m_cmbDestBasefolder->insertItem(sourceDir->dir()->absPath());
    }

	if (m_cmbDestBasefolder->count() == 0) {
		QMessageBox::information( this, "No Folders Available",
                                  "There are no Folders in your album!<br>"
                                  "Either create a new album and add Folders to "
                                  "it, or open another available album." );
		
	}
    //m_cmbDestBasefolder->insertItem(Settings::imageImporterDestBaseFolder());
	
    m_cmbDestBasefolder->setCurrentText(Settings::imageImporterDestBaseFolder());
    m_txtDestSubfolders->setText(Settings::imageImporterDestSubfolders());
    m_txtDestFilename->setText(Settings::imageImporterDestFilenames());
    m_chkDestLowercase->setChecked(Settings::imageImporterDestLowercaseFilenames());

}
Folder* FileSystemScanner::addFolder(QDir* dir, bool recursive) throw(EngineException*)
{
    // test if the given folder is addable
    testIfFolderIsAddable(dir, recursive);

    tracer->sdebug(__func__) << "adding folder: " << dir->absPath() << ", recursive: " << recursive << "..." << endl;

    reset();

    m_engine->dirtyfy();

    Folder* folder = new Folder(m_engine->m_nextSourceDirId++, dir, recursive);
    folder->setFound(true);
    m_engine->m_sourceDirs->append(folder);
    m_engine->m_sourceDirDict->insert(folder->id(), folder);

    // add all files in the folder
    rescanFolder(folder, false);
    
    emit(newFolder(folder));

    if (m_cancel) {
        return folder;
    }
    
    // add all folders below the given folder
    if (recursive) {
        delete m_loopDetectionHelper;
        m_loopDetectionHelper = new QPtrList<QString>;
        m_loopDetectionHelper->setAutoDelete(true);
        m_loopDetectionHelper->append(new QString(folder->dir()->canonicalPath()));

        addFolders(folder);
    }

    return folder;
}
void FileSystemScanner::addFolders(Folder* parent)
{
    tracer->sinvoked(__func__) << "with folder: " << parent->dir()->absPath() << endl;

    // get all folders in the current directory
    const QFileInfoList* subfolderlist = parent->dir()->entryInfoList(QDir::Dirs);

    if (subfolderlist) {
        QFileInfoListIterator iterator(*subfolderlist);
        QFileInfo* fileInfo = 0;
        while ((fileInfo = iterator.current()) != 0) {

            // ignore ./.. and hidden folders (beginning with .)
            // and ignore folders called 'ThumbNails'
            if (!fileInfo->fileName().startsWith(".")
                && mustHandleFolder(fileInfo->fileName())
                ) {

                QDir subfolder(fileInfo->absFilePath());

                tracer->sdebug(__func__) << "handling subfolder: " << subfolder.absPath() << endl;

                bool loopDetected = false;

                // we have to test if this folder is part of a loop or if it is the superfolder of an already added dir
                QString* alreadyAddedFolder;
                for (alreadyAddedFolder = m_loopDetectionHelper->first(); alreadyAddedFolder; alreadyAddedFolder = m_loopDetectionHelper->next()) {

                    if (*alreadyAddedFolder == subfolder.canonicalPath()) {
                        loopDetected = true;
                        tracer->swarning(__func__) << "loop detected, not adding folder again: '" << fileInfo->absFilePath()
                                << "' is pointing to '" << *alreadyAddedFolder << "'" << endl;
                        emit(progress_loopDetected(fileInfo->absFilePath(), *alreadyAddedFolder));
                        break;
                    }
                    if ((*alreadyAddedFolder).startsWith(subfolder.canonicalPath(), true)) {
                        loopDetected = true;
                        tracer->swarning(__func__) << "loop detected, not adding folder because it is a super directory ("
                                << subfolder.canonicalPath() << ") of an already added folder: '" << *alreadyAddedFolder << "'" << endl;
                        emit(progress_loopDetected(subfolder.canonicalPath(), *alreadyAddedFolder));
                        break;
                    }
                }

                if (!loopDetected) {
                    Folder* existingFolder = 0;

                    // we have to test if the folder is already processed to prevent endless loops
                    QIntDictIterator<Folder> it(*m_engine->m_sourceDirDict);
                    while (!existingFolder && it.current()) {

                        Folder* current = it.current();

                        if (current->dir()->canonicalPath() == subfolder.canonicalPath()) {
                            existingFolder = current;
                            tracer->sdebug(__func__) << "folder is already added: " << current->dir()->canonicalPath() << endl;
                            emit(progress_folderAlreadyAdded(current->dir()->canonicalPath()));
                        }

                        ++it;
                    }

                    if (existingFolder) {

                        // add the directory to the list of handled directories for detecting loops
                        m_loopDetectionHelper->append(new QString(existingFolder->dir()->canonicalPath()));

                        // make recursive call
                        addFolders(existingFolder);
                    } else {
                        tracer->sdebug(__func__) << "found new folder to add " << fileInfo->absFilePath() << endl;

                        // create the new folder
                        Folder* child = new Folder(m_engine->m_nextSourceDirId++, new QDir(fileInfo->absFilePath()), false);
                        child->setFound(true);

                        // add the current directory to the tree
                        child->setParent(parent);

                        // put the folder into the folder dictionary (id to folder map)
                        m_engine->m_sourceDirDict->insert(child->id(), child);

                        // add the directory to the list of handled directories for detcting loops
                        m_loopDetectionHelper->append(new QString(child->dir()->canonicalPath()));

                        // add all files in the current folder
                        rescanFolder(child, false);

                        emit(newFolder(child));
                        
                        if (m_cancel) {
                            return;
                        }

                        // make recursive call
                        addFolders(child);
                    }
                }
            }
            ++iterator;
        }
    }
}