ome.formats.importer.gui.FileQueueHandler.java Source code

Java tutorial

Introduction

Here is the source code for ome.formats.importer.gui.FileQueueHandler.java

Source

/*
 * ome.formats.importer.gui.AddDatasetDialog
 *
 *------------------------------------------------------------------------------
 *  Copyright (C) 2006-2008 University of Dundee. All rights reserved.
 *
 *
 *  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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *------------------------------------------------------------------------------
 */

package ome.formats.importer.gui;

import info.clearthought.layout.TableLayout;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicInteger;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSplitPane;
import javax.swing.WindowConstants;
import javax.swing.filechooser.FileFilter;

import loci.formats.IFormatReader;
import loci.formats.gui.FormatFileFilter;
import ome.formats.OMEROMetadataStoreClient;
import ome.formats.importer.IObservable;
import ome.formats.importer.IObserver;
import ome.formats.importer.ImportCandidates;
import ome.formats.importer.ImportConfig;
import ome.formats.importer.ImportContainer;
import ome.formats.importer.ImportEvent;
import ome.formats.importer.ImportLibrary;
import ome.formats.importer.OMEROWrapper;
import omero.model.Dataset;
import omero.model.IObject;
import omero.model.Screen;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author Brian Loranger brain at lifesci.dundee.ac.uk
 *
 */
public class FileQueueHandler extends JPanel implements ActionListener, PropertyChangeListener, IObserver {
    /** Logger for this class */
    private static final Log log = LogFactory.getLog(FileQueueHandler.class);

    public final static String ADD = "add";
    public final static String REMOVE = "remove";
    public final static String CLEARDONE = "clear_done";
    public final static String CLEARFAILED = "clear_failed";
    public final static String IMPORT = "import";
    public final static String REFRESH = "refresh";

    private final ImportConfig config;
    private final OMEROWrapper importReader, scanReader;
    private final GuiImporter viewer;

    private final FileQueueChooser fileChooser;
    private final FileQueueTable qTable;

    private final HistoryTable historyTable;

    private final AtomicInteger count = new AtomicInteger(0);
    private final ScheduledExecutorService scanEx;
    private final ScheduledExecutorService importEx;
    private JProgressBar directoryProgressBar;
    private JDialog progressDialog;

    protected boolean cancelScan = false;

    private boolean candidatesFormatException = false;

    /**
     * @param scanEx ScheduledExecutorService for scanning
     * @param importEx ScheduledExecutorService for importing
     * @param viewer Parent viewer class
     * @param config ImportConfig
     */
    FileQueueHandler(ScheduledExecutorService scanEx, ScheduledExecutorService importEx, GuiImporter viewer,
            ImportConfig config) {
        this.scanEx = scanEx;
        this.importEx = importEx;
        this.config = config;
        this.viewer = viewer;
        this.historyTable = viewer.getHistoryTable();
        this.importReader = new OMEROWrapper(config);
        this.scanReader = new OMEROWrapper(config);

        //reader.setChannelStatCalculationStatus(true);

        setLayout(new BorderLayout());
        fileChooser = new FileQueueChooser(config, scanReader);
        fileChooser.addActionListener(this);
        fileChooser.addPropertyChangeListener(this);

        qTable = new FileQueueTable();
        qTable.addPropertyChangeListener(this);

        // Functionality to allows the reimport button to work
        if (historyTable != null) {
            historyTable.addObserver(this);
            addPropertyChangeListener(historyTable);
        }

        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, fileChooser, qTable);

        splitPane.setResizeWeight(0.1);

        add(splitPane, BorderLayout.CENTER);
    }

    /**
     * @return qTable;
     */
    public FileQueueTable getTable() {
        return qTable;
    }

    /**
     * @return OMEROMetadataStoreClient
     */
    protected OMEROMetadataStoreClient getOMEROMetadataStoreClient() {
        return viewer.getLoginHandler().getMetadataStore();
    }

    /* (non-Javadoc)
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent event) {
        final String action = event.getActionCommand();
        //final File[] files = fileChooser.getSelectedFiles();

        //If the directory changed, don't show an image.
        if (action.equals(JFileChooser.APPROVE_SELECTION)) {
            doSelection(true);
        }
    }

    private void addEnabled(boolean enabled) {
        if (enabled)
            viewer.setCursor(Cursor.getDefaultCursor());
        else
            viewer.setCursor(java.awt.Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

        qTable.addBtn.setEnabled(enabled);
        qTable.removeBtn.setEnabled(enabled);
    }

    /**
     * @param enterDirectories -if True, will enter a directory rather then import it
     * This is used to allow 'normal' functionality for JFileChooser.APPROVE_SELECTION
     * using the VK_ENTER key.
     */
    private void doSelection(boolean enterDirectories) {
        boolean filesOnly = true;

        for (File file : fileChooser.getSelectedFiles()) {
            if (file.isDirectory())
                filesOnly = false;
        }

        if (enterDirectories && !filesOnly && fileChooser.getSelectedFiles().length == 1)
            fileChooser.setCurrentDirectory(fileChooser.getSelectedFile());
        else
            addSelectedFiles();
    }

    /**
     * Add all files that are selected in the JFileChooser
     * 
     */
    private void addSelectedFiles() {

        boolean filesOnly = true;

        final File[] _files = fileChooser.getSelectedFiles();

        if (_files == null) {
            mustSelectFile();
            return;
        }

        final String[] paths = new String[_files.length];
        for (int i = 0; i < paths.length; i++) {
            paths[i] = _files[i].getAbsolutePath();
        }

        final int which = count.incrementAndGet();
        final String msg = Arrays.toString(paths);
        log.info(String.format("Scheduling candidate calculations(%s)=%s", which, msg));
        final IObserver self = this;

        for (File file : fileChooser.getSelectedFiles()) {
            if (file.isDirectory())
                filesOnly = false;
        }

        addEnabled(false);

        if (filesOnly) {
            boolean isSPW = false;
            final List<ImportContainer> containers = new ArrayList<ImportContainer>();
            boolean runCandidates = false;
            for (File file : fileChooser.getSelectedFiles()) {
                String fileStr = file.toString();
                String fileExt = fileStr.substring(fileStr.lastIndexOf('.') + 1, fileStr.length());
                fileExt = fileExt.toLowerCase();
                if (fileExt.equals("flex") || fileExt.equals("xdce") || fileExt.equals("mea")
                        || fileExt.equals("res") || fileExt.equals("htd") || fileExt.equals("dib")
                        || fileExt.equals("c01") || fileExt.equals("pnl")) {
                    isSPW = true;
                } else if (fileExt.equals("txt") || fileExt.startsWith("tif") || fileExt.startsWith("dat")
                        || fileExt.equals("xml") || fileExt.equals("exp") || fileExt.equals("log")
                        || fileExt.equals("ini")) { // arbitrary file extension so we must do candidates
                    runCandidates = true;
                    break;
                }

                ImportContainer container = new ImportContainer(file, null, null, false, null, null, null, isSPW);
                containers.add(container);
            }

            if (!runCandidates) {
                log.info(String.format("Handling import containers(%s)=%s", which, msg));
                handleFiles(containers);
                return;
            }
        }

        Runnable run = new Runnable() {
            public void run() {
                log.info(String.format("Background: calculating candidates(%s)=%s", which, msg));
                final ImportCandidates candidates = new ImportCandidates(scanReader, paths, self);
                final List<ImportContainer> containers = candidates.getContainers();
                javax.swing.SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        log.info(String.format("Handling import containers(%s)=%s", which, msg));
                        handleFiles(containers);
                    }
                });
            }
        };
        scanEx.execute(run);
    }

    /**
     * Retrieve the file chooser's selected reader then iterate over
     * each of our supplied containers filtering out those whose format
     * do not match those of the selected reader.
     * 
     * @param allContainers List of ImporterContainers
     */
    private void handleFiles(List<ImportContainer> allContainers) {
        FileFilter selectedFilter = fileChooser.getFileFilter();
        IFormatReader selectedReader = null;

        if (selectedFilter instanceof FormatFileFilter) {
            log.debug("Selected file filter: " + selectedFilter);
            selectedReader = ((FormatFileFilter) selectedFilter).getReader();
        }

        List<ImportContainer> containers = new ArrayList<ImportContainer>();
        for (ImportContainer ic : allContainers) {
            if (selectedReader == null) {
                // The user selected "All supported file types"
                containers = allContainers;
                break;
            }
            String a = selectedReader.getFormat();
            String b = ic.getReader();
            if (a.equals(b) || b == null) {
                containers.add(ic);
            } else {
                log.debug(String.format("Skipping %s (%s != %s)", ic.getFile().getAbsoluteFile(), a, b));
            }
        }

        Boolean spw = spwOrNull(containers);

        if (containers.size() == 0 && !candidatesFormatException) {
            final JOptionPane optionPane = new JOptionPane("\nNo importable files found in this selection.",
                    JOptionPane.WARNING_MESSAGE);
            final JDialog errorDialog = new JDialog(viewer, "No Importable Files Found", true);
            errorDialog.setContentPane(optionPane);

            optionPane.addPropertyChangeListener(new PropertyChangeListener() {
                public void propertyChange(PropertyChangeEvent e) {
                    String prop = e.getPropertyName();

                    if (errorDialog.isVisible() && (e.getSource() == optionPane)
                            && (prop.equals(JOptionPane.VALUE_PROPERTY))) {
                        errorDialog.dispose();
                    }
                }
            });

            errorDialog.toFront();
            errorDialog.pack();
            errorDialog.setLocationRelativeTo(viewer);
            errorDialog.setVisible(true);
        }

        if (candidatesFormatException) {
            viewer.candidateErrorsCollected(viewer);
            candidatesFormatException = false;
        }

        if (spw == null) {
            addEnabled(true);
            containers.clear();
            return; // Invalid containers.
        }

        if (getOMEROMetadataStoreClient() != null && spw.booleanValue()) {
            addEnabled(true);
            SPWDialog dialog = new SPWDialog(config, viewer, "Screen Import", true, getOMEROMetadataStoreClient());
            if (dialog.cancelled == true || dialog.screen == null)
                return;
            for (ImportContainer ic : containers) {
                ic.setTarget(dialog.screen);
                String title = dialog.screen.getName().getValue();
                addFileToQueue(ic, title, false, 0);
            }

            qTable.centerOnRow(qTable.getQueue().getRowCount() - 1);
            qTable.importBtn.requestFocus();

        } else if (getOMEROMetadataStoreClient() != null) {
            addEnabled(true);
            ImportDialog dialog = new ImportDialog(config, viewer, "Image Import", true,
                    getOMEROMetadataStoreClient());
            if (dialog.cancelled == true || dialog.dataset == null)
                return;

            Double[] pixelSizes = new Double[] { dialog.pixelSizeX, dialog.pixelSizeY, dialog.pixelSizeZ };
            Boolean useFullPath = config.useFullPath.get();
            if (dialog.useCustomNamingChkBox.isSelected() == false)
                useFullPath = null; //use the default bio-formats naming

            for (ImportContainer ic : containers) {
                ic.setTarget(dialog.dataset);
                ic.setUserPixels(pixelSizes);
                ic.setArchive(dialog.archiveImage.isSelected());
                String title = "";
                if (dialog.project.getId() != null) {
                    ic.setProjectID(dialog.project.getId().getValue());
                    title = dialog.project.getName().getValue() + " / " + dialog.dataset.getName().getValue();
                } else {
                    title = "none / " + dialog.dataset.getName().getValue();
                }

                addFileToQueue(ic, title, useFullPath, config.numOfDirectories.get());
            }

            qTable.centerOnRow(qTable.getQueue().getRowCount() - 1);
            qTable.importBtn.requestFocus();
        } else {
            addEnabled(true);
            JOptionPane.showMessageDialog(viewer,
                    "Due to an error the application is unable to \n"
                            + "retrieve an OMEROMetadataStore and cannot continue."
                            + "The most likely cause for this error is that you"
                            + "are not logged in. Please try to login again.");
        }
    }

    /**
     * Dialog 'must select at least one importable file'
     */
    private void mustSelectFile() {
        JOptionPane.showMessageDialog(viewer, "You must select at least one importable file to\n"
                + "add to the import queue. Choose an image in the\n" + "left-hand panel first before continuing.");
    }

    /* (non-Javadoc)
     * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
     */
    public void propertyChange(PropertyChangeEvent e) {
        String prop = e.getPropertyName();
        if (prop.equals(ADD)) {
            doSelection(false);
        }

        else if (prop.equals(REMOVE)) {
            int[] rows = qTable.getQueue().getSelectedRows();

            if (rows.length == 0) {
                JOptionPane.showMessageDialog(viewer, "You must select at least one file in the queue to\n"
                        + "remove. Choose an image in the right-hand panel \n" + "first before removing.");
                return;
            }

            while (rows.length > 0) {
                if (qTable.getQueue().getValueAt(rows[0], 2) == "added"
                        || qTable.getQueue().getValueAt(rows[0], 2) == "pending") {
                    removeFileFromQueue(rows[0]);
                    rows = qTable.getQueue().getSelectedRows();
                }
            }
        }

        else if (prop.equals(CLEARDONE)) {
            int numRows = qTable.getQueue().getRowCount();

            for (int i = (numRows - 1); i >= 0; i--) {
                if (qTable.getQueue().getValueAt(i, 2) == "done") {
                    removeFileFromQueue(i);
                }
            }
            qTable.clearDoneBtn.setEnabled(false);
        }

        else if (prop.equals(CLEARFAILED)) {
            int numRows = qTable.getQueue().getRowCount();

            for (int i = (numRows - 1); i >= 0; i--) {
                if (qTable.getQueue().getValueAt(i, 2) == "failed"
                        || qTable.getQueue().getValueAt(i, 2) == "unreadable") {
                    removeFileFromQueue(i);
                }
            }
            qTable.clearFailedBtn.setEnabled(false);
        }

        else if (prop.equals(IMPORT)) {
            if (viewer.getLoggedIn() == false) {
                JOptionPane.showMessageDialog(viewer, "You must be logged in before you can import.");
                return;
            }

            qTable.clearDoneBtn.setEnabled(false);
            qTable.clearFailedBtn.setEnabled(false);
            try {
                if (qTable.importing == false) {
                    ImportContainer[] candidates = qTable.getImportContainersFromTable();

                    if (candidates != null) {
                        ImportLibrary library = new ImportLibrary(getOMEROMetadataStoreClient(), importReader);
                        library.addObserver(new LoggingImportMonitor());

                        if (getOMEROMetadataStoreClient() != null) {
                            ImportHandler importHandler = new ImportHandler(importEx, viewer, qTable, config,
                                    library, candidates);
                            importHandler.addObserver(viewer);
                            importHandler.addObserver(qTable);
                        }
                    }
                    qTable.importing = true;
                    qTable.getQueue().setRowSelectionAllowed(false);
                    qTable.removeBtn.setEnabled(false);
                } else {
                    qTable.importBtn.setText("Wait...");
                    qTable.importBtn.setEnabled(false);
                    viewer.getStatusBar().setStatusIcon("gfx/import_cancelling_16.png",
                            "Cancelling import... please wait.");
                    //JOptionPane.showMessageDialog(viewer, 
                    //        "You import will be cancelled after the " +
                    //        "current file has finished importing.");
                    if (cancelImportDialog(viewer) == true) {
                        qTable.cancel = true;
                        qTable.abort = true;
                        qTable.importing = false;
                        System.exit(0);
                    } else {
                        qTable.cancel = true;
                        qTable.importing = false;
                    }
                }
            } catch (Exception ex) {
                log.error("Generic error while updating GUI for import.", ex);
                return;
            }
        }

        else if (prop.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) {
            config.savedDirectory.set(new File(fileChooser.getCurrentDirectory().getAbsolutePath()));
        }

        else if (prop.equals(REFRESH)) {
            fileChooser.setVisible(false);
            fileChooser.rescanCurrentDirectory();
            fileChooser.setVisible(true);
        }
    }

    public void enableImports(boolean b) {
        qTable.addBtn.setEnabled(b);
        qTable.removeBtn.setEnabled(b);
        if (b == true && qTable.getTable().getRowCount() > 0)
            qTable.importBtn.setEnabled(true);
        else if (b == false)
            qTable.importBtn.setEnabled(false);
    }

    /**
     * Checks whether all the candidate imports in the list are either SPW or
     * not SPW. If there is a mismatch, then a warning is shown and null returned,
     * otherwise a Boolean of whether or not this is a SPW import will be returned.
     */
    private Boolean spwOrNull(final List<ImportContainer> containers) {
        Boolean isSPW = null;

        for (ImportContainer importContainer : containers) {

            /*
            // Temporary fix for ome.tiff and ome.xml to dataset and not spw 
            if (importContainer.reader.equals("OME-TIFF") || 
                importContainer.reader.equals("OME-XML")) 
            return false;
            */

            if (isSPW != null && importContainer.getIsSPW() != isSPW.booleanValue()) {
                JOptionPane.showMessageDialog(viewer, "You have chosen some Screen-based images and some \n "
                        + "non-screen-based images. Please import only one type at a time.");
                log.debug("Directory import found SPW and non-SPW data:");
                for (ImportContainer ic2 : containers) {
                    log.debug(String.format("  Spw? %5s\t%s", ic2.getIsSPW(), ic2.getFile()));
                }
                return null;
            }
            isSPW = importContainer.getIsSPW();
        }
        return isSPW;
    }

    /**
     * Import cancelled dialog
     * 
     * @param frame parent frame
     * @return - true / false if import cancelled
     */
    private boolean cancelImportDialog(Component frame) {
        String s1 = "OK";
        String s2 = "Force Quit Now";
        Object[] options = { s1, s2 };
        int n = JOptionPane.showOptionDialog(frame, "Click 'OK' to cancel after the current file has\n"
                + "finished importing, or click 'Force Quit Now' to\n"
                + "force the importer to quit importing immediately.\n\n"
                + "You should only force quit the importer if there\n"
                + "has been an import problem, as this leaves partial\n" + "files in your server dataset.\n\n",
                "Cancel Import", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, s1);
        if (n == JOptionPane.NO_OPTION) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Return a stipped down string containing the file name and X number of directories above it.
     * Used for display purposes.
     * @param file
     * @param useFullPath
     * @param numOfDirectories
     * @return
     */
    private String getImageName(File file, Boolean useFullPath, int numOfDirectories) {
        // standardize the format of files from window '\' to unix '/' 
        String path = file.getAbsolutePath().replace('\\', '/');

        if (useFullPath == true)
            return path;
        else if (numOfDirectories == 0)
            return file.getName();
        else {
            String[] directories = splitDirectories(path);
            if (numOfDirectories > directories.length - 1)
                numOfDirectories = directories.length - 1;

            int start = directories.length - numOfDirectories - 1;

            StringBuffer buf = new StringBuffer();

            for (int i = start; i < directories.length - 1; i++) {
                //viewer.appendToDebugLn(directories[i]);
                if (directories[i].length() != 0) {
                    if (i == start) {
                        buf.append(directories[i]);
                    } else {
                        buf.append("/");
                        buf.append(directories[i]);
                    }
                }
            }

            buf.append("/");
            buf.append(file.getName());
            return buf.toString();
        }
    }

    /**
     * Split the directories by file seperator character ("/" or "\")
     * @param path
     * @return
     */
    private String[] splitDirectories(String path) {
        //viewer.appendToDebugLn(path);
        String[] fields = path.split("/");
        //Integer length = fields.length;
        //viewer.appendToDebugLn(length.toString());

        return fields;
    }

    /**
     * Remove file from Queue
     * 
     * @param row - row index of file to remove
     */
    private void removeFileFromQueue(int row) {
        qTable.getTable().removeRow(row);
        //qTable.table.fireTableRowsDeleted(row, row);
        if (qTable.getTable().getRowCount() == 0)
            qTable.importBtn.setEnabled(false);
    }

    /* (non-Javadoc)
     * @see ome.formats.importer.IObserver#update(ome.formats.importer.IObservable, ome.formats.importer.ImportEvent)
     */
    @SuppressWarnings("unchecked")
    public void update(IObservable observable, ImportEvent event) {
        final OMEROMetadataStoreClient store = viewer.getLoginHandler().getMetadataStore();

        if (event instanceof ome.formats.importer.util.ErrorHandler.EXCEPTION_EVENT) {
            viewer.getErrorHandler().update(observable, event);

            if (event instanceof ome.formats.importer.util.ErrorHandler.UNKNOWN_FORMAT
                    && fileChooser.getSelectedFiles().length == 1 && fileChooser.getSelectedFile().isFile()) {
                JOptionPane.showMessageDialog(viewer,
                        "This file's format is not recognized. \n" + "Perhaps the file is damaged?",
                        "Unknown Format", JOptionPane.WARNING_MESSAGE);
            }

            if (event instanceof ome.formats.importer.util.ErrorHandler.FILE_EXCEPTION) {
                candidatesFormatException = true;
            }
        }

        if (event instanceof ome.formats.importer.util.ErrorHandler.MISSING_LIBRARY) {
            JOptionPane.showMessageDialog(viewer, "You appear to be missing a required library needed for \n"
                    + "this file import. See the debug log messages for details.");
        }

        else if (event instanceof ImportCandidates.SCANNING) {
            addEnabled(false);

            ImportCandidates.SCANNING ev = (ImportCandidates.SCANNING) event;
            if (scanEx.isShutdown() || cancelScan) {
                log.info("Cancelling scan");
                ev.cancel();
                cancelScan = false;
            }

            if (ev.totalFiles < 0) {
                if (progressDialog == null) {
                    double layoutTable[][] = { { 10, 180, 100, 10 }, // columns
                            { 5, 20, 5, 30, 5 } }; // rows

                    progressDialog = new JDialog(viewer, "Processing Files");
                    progressDialog.setSize(300, 90);
                    progressDialog.setLocationRelativeTo(viewer);
                    TableLayout layout = new TableLayout(layoutTable);
                    progressDialog.setLayout(layout);
                    directoryProgressBar = new JProgressBar();
                    directoryProgressBar.setString("Please wait.");
                    directoryProgressBar.setStringPainted(true);
                    directoryProgressBar.setIndeterminate(true);
                    progressDialog.add(directoryProgressBar, "1,1,2,1");
                    JButton cancelBtn = new JButton("Cancel");

                    progressDialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);

                    cancelBtn.addActionListener(new ActionListener() {

                        public void actionPerformed(ActionEvent event) {
                            cancelScan = true;
                            progressDialog.dispose();
                            progressDialog = null;
                            addEnabled(true);
                        }
                    });

                    progressDialog.add(cancelBtn, "2,3,R,C");
                    progressDialog.getRootPane().setDefaultButton(cancelBtn);
                    progressDialog.setVisible(true);
                    progressDialog.toFront();
                }
            } else {
                if (progressDialog != null) {
                    updateProgress(ev.totalFiles, ev.numFiles);
                }

                if (ev.totalFiles == ev.numFiles && progressDialog != null) {
                    progressDialog.dispose();
                    progressDialog = null;
                    addEnabled(true);
                }
            }

            viewer.appendToOutput(
                    "Processing files: Scanned " + ev.numFiles + " of " + ev.totalFiles + " total.\n");

            log.debug(ev.toLog());

        }

        else if (event instanceof ImportEvent.REIMPORT) {

            String objectName = "", projectName = "", fileName = "";
            Long objectID = 0L, projectID = 0L;
            File file = null;
            Integer finalCount = 0;
            IObject object;

            int[] selectedRows = null;

            if (historyTable != null)
                selectedRows = historyTable.eTable.getSelectedRows();

            for (int r : selectedRows) {
                Vector row = new Vector();

                objectID = (Long) historyTable.table.getValueAt(r, 5);
                projectID = (Long) historyTable.table.getValueAt(r, 6);

                fileName = (String) historyTable.table.getValueAt(r, 0);
                file = new File((String) historyTable.table.getValueAt(r, 4));

                if (projectID == null || projectID == 0) {
                    object = null;

                    try {
                        object = store.getTarget(Screen.class, objectID);
                        objectName = ((Screen) object).getName().getValue();
                    } catch (Exception e) {
                        log.warn("Failed to retrieve screen: " + objectID, e);
                        continue;
                    }
                } else {
                    object = null;
                    try {
                        object = store.getTarget(Dataset.class, objectID);
                        objectName = ((Dataset) object).getName().getValue();
                    } catch (Exception e) {
                        log.warn("Failed to retrieve dataset: " + objectID, e);
                        continue;
                    }

                    try {
                        projectName = store.getProject(projectID).getName().getValue();
                    } catch (Exception e) {
                        log.warn("Failed to retrieve project: " + projectID, e);
                        continue;
                    }
                }

                // TODO: The 6th parameter should be 'format', not 'fileName'!
                ImportContainer container = new ImportContainer(file, projectID, object, cancelScan, null, fileName,
                        null, cancelScan);

                finalCount = finalCount + 1;

                Double[] pixelSizes = new Double[] { 1.0, 1.0, 1.0 };

                row.add(fileName);
                if (projectID == null || projectID == 0) {
                    row.add(objectName);
                } else {
                    row.add(projectName + "/" + objectName);
                }
                // WHY ISN'T THIS CODE USING addFiletoQueue?!!?
                row.add("added");
                row.add(container);
                row.add(file);
                row.add(false);
                row.add(projectID);
                row.add(pixelSizes);
                qTable.getTable().addRow(row);
            }

            if (finalCount == 0) {
                JOptionPane.showMessageDialog(viewer,
                        "None of the images in this history\n" + "list can be reimported.");
            } else if (finalCount == 1) {
                JOptionPane.showMessageDialog(viewer, "One of the images in this history list has been\n"
                        + "re-added to the import queue for reimport.");
            } else if (finalCount > 1) {
                JOptionPane.showMessageDialog(viewer,
                        finalCount + " images in this history list have been re-added\n"
                                + "to the import queue for reimport.");
            }

            if (qTable.getTable().getRowCount() > 0)
                qTable.importBtn.setEnabled(true);
            qTable.importBtn.doClick();
        }
    }

    /**
     * Add file to queue
     * 
     * @param container - container for file adding
     * @param pdsString - project/dataset/screen string
     * @param useFullPath - use full path / partial path for name
     * @param numOfDirectories how many directories to use for partial path
     */
    @SuppressWarnings("unchecked")
    private void addFileToQueue(ImportContainer container, String pdsString, Boolean useFullPath,
            int numOfDirectories) {
        Vector row = new Vector();
        String imageName;

        if (useFullPath != null) {
            imageName = getImageName(container.getFile(), useFullPath, numOfDirectories);
            container.setCustomImageName(imageName);
        } else {
            imageName = container.getFile().getAbsolutePath();
        }

        row.add(imageName);
        row.add(pdsString);
        row.add("added");
        row.add(container);
        qTable.getTable().addRow(row);
        if (qTable.getTable().getRowCount() == 1)
            qTable.importBtn.setEnabled(true);
    }

    /**
     * Update progress 
     * 
     * @param totalFiles
     * @param numFiles
     */
    private void updateProgress(final int totalFiles, final int numFiles) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                directoryProgressBar.setIndeterminate(false);
                directoryProgressBar.setMaximum(totalFiles);
                directoryProgressBar.setMinimum(0);
                directoryProgressBar.setValue(numFiles);
                directoryProgressBar.setString("Scanned " + numFiles + " of " + totalFiles);
            }
        });
    }
}