### Supporting Progress Indicators

You will typically customize move or copy operations rather than create your own file operation. See Creating Your Own File Operation below for information about subclassing IFileOperation to create an entirely new file system operation.

You can support progress indicators by subclassing the appropriate file system operation class and overriding reportProgress. Return true if the operation should continue or false if it should terminate. In the following example, the file system copier IMyCopier prints a message to cout each time reportProgress is called. The definitions of trivial functions such as constructors and destructors have been omitted.

    class IMyCopier : public IFileSystemCopier {
    public:
        IMyCopier(EFailureAction action,
            unsigned int tellMeTimes);

    protected:
        virtual bool reportProgress(double fractionDone,
                        const IFileSystemEntity& currentEntity);
    };

    bool
    IMyCopier::reportProgress(
        double fractionDone,
        const IFileSystemEntity& currentEntity)
    {
        cout << fractionDone << "% complete\n";
        return !terminatedByUser();
    }

The tellMeTimes parameter to the IMyCopier constructor is passed to the base class IFileSystemCopier. This parameter specifies the number of times that reportProgress should be called during the operation. For example, if you want to display a "% copied" indicator, pass 100 in this parameter. If you have a progress indicator that is 210 pixels wide, pass 210 in this parameter.

### Resolving Filename Conflicts

You can implement file name-conflict resolution during move or copy operations by subclassing a file operation class, such as IFileSystemCopier or IFileSystemMover, and overriding renameNeeded. The following example is a custom IFileSystemMover subclass, IMyMover, that calls the external function GetNewName to prompt the user for a new filename. It then returns true to indicate that a new name was entered and the file operation should continue, or false to indicate that a new name was not entered and the operation must stop. The definitions of trivial functions such as constructors and destructors have been omitted.

    class IMyMover : public IFileSystemMover {
    public:
        IMyMover(EFailureAction action = kContinue,
            unsigned int tellMeTimes = 0);

    protected:
        virtual bool renameNeeded(IFileName& modifyThisName,
                        const IFileSystemEntity& currentEntity);
    };

    bool
    IMyMover::renameNeeded(
        IFileName& modifyThisName,
        const IFileSystemEntity& currentEntity)
    {
        bool gotNewName = GetNewName(currentEntity.name(),
            modifyThisName);
        return gotNewName;
    }

### Handling Exceptions and Other Failures

Any exceptions other than name-conflict errors are passed back to the file operation object for handling. The default implementation rethrows the exception. You can subclass a file operation class and override handleFailure to handle any exceptions that occur during the execution of your file operation:

    class IMyCopier : public IFileSystemCopier {
    public:
        IMyCopier(EFailureAction action = kStop,
            unsigned int tellMeTimes = 0);

    protected:
        virtual bool handleFailure(IException& reason,
                        const IFileSystemEntity& currentEntity);
    };

    bool
    IMyCopier::handleFailure(
        IException& reason,
        const IFileSystemEntity& currentEntity)
    {
        // display an alert window
        return errorHandledSuccessfully;
    }

### Creating Your Own File System Operation

You will not normally need to create an entirely new type of file system operation, but it is easy to do. Subclass IFileOperation and override the pure virtual function doOneEntity:

    class IMyOperation : public IFileOperation {
    public:
        IMyOperation(EFailureAction action,
            unsigned int tellMeTimes);

    protected:
        virtual IFileSystemEntity
            doOneEntity(const IFileSystemEntity& entity,
                IDirectory& target,
                const IFileName& newName);
    };

    IFileSystemEntity
    IMyOperation::doOneEntity(
        const IFileSystemEntity& entity,
        IDirectory& target,
        const IFileName& newName)
    {
        // perform operation here and return appropriate
        // IFileSystemEntity
    }

Introduction to the File System
Overview of File System Entities
Mover and Copier Classes
File System Exceptions

Copying a File or Directory Using IFileSystemEntity::copyTo
Moving a File or Directory Using IFileSystemEntity::moveTo
Using the IFileSystemCopier and IFileSystemMover Classes Directly