Logo Search packages:      
Sourcecode: jabref version File versions  Download package

EntryTableTransferHandler.java

/*
 All programs in this directory and subdirectories are published under the 
 GNU General Public License as described below.

 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., 59 
 Temple Place, Suite 330, Boston, MA 02111-1307 USA

 Further information about the GNU GPL is available at:
 http://www.gnu.org/copyleft/gpl.ja.html
 */

package net.sf.jabref.groups;

import java.awt.datatransfer.*;
import java.awt.dnd.DnDConstants;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.TransferHandler;

import net.sf.jabref.BasePanel;
import net.sf.jabref.Globals;
import net.sf.jabref.JabRefFrame;
import net.sf.jabref.external.DroppedFileHandler;
import net.sf.jabref.external.ExternalFileType;
import net.sf.jabref.external.TransferableFileLinkSelection;
import net.sf.jabref.gui.MainTable;
import net.sf.jabref.gui.MainTableFormat;
import net.sf.jabref.imports.ImportMenuItem;
import net.sf.jabref.imports.OpenDatabaseAction;
import net.sf.jabref.imports.ParserResult;
import net.sf.jabref.net.URLDownload;

public class EntryTableTransferHandler extends TransferHandler {

      protected final MainTable entryTable;

      protected JabRefFrame frame;

      private BasePanel panel;

      protected DataFlavor urlFlavor;

      protected DataFlavor stringFlavor;

      protected static boolean DROP_ALLOWED = true;

      /**
       * Construct the transfer handler.
       * 
       * @param entryTable
       *            The table this transfer handler should operate on. This
       *            argument is allowed to equal
       * @null, in which case the transfer handler can assume that it works for a
       *        JabRef instance with no databases open, attached to the empty
       *        tabbed pane.
       * @param frame
       *            The JabRefFrame instance.
       * @param panel
       *            The BasePanel this transferhandler works for.
       */
      public EntryTableTransferHandler(MainTable entryTable, JabRefFrame frame, BasePanel panel) {
            this.entryTable = entryTable;
            this.frame = frame;
            this.panel = panel;
            stringFlavor = DataFlavor.stringFlavor;
            try {
                  urlFlavor = new DataFlavor("application/x-java-url; class=java.net.URL");
            } catch (ClassNotFoundException e) {
                  Globals.logger("Unable to configure drag and drop for main table");
                  e.printStackTrace();
            }
      }

      /**
       * Overriden to indicate which types of drags are supported (only LINK).
       * 
       * @override
       */
      public int getSourceActions(JComponent c) {
            return DnDConstants.ACTION_LINK;
      }

      /**
       * This method is called when dragging stuff *from* the table.
       */
      public Transferable createTransferable(JComponent c) {
        if (!draggingFile) {
            /* so we can assume it will never be called if entryTable==null: */
            return new TransferableEntrySelection(entryTable.getSelectedEntries());
        }
        else {
            draggingFile = false;
            return (new TransferableFileLinkSelection
                    (panel, entryTable.getSelectedEntries()));//.getTransferable();
        }
      }

      /**
       * This method is called when stuff is drag to the component.
       * 
       * Imports the dropped URL or plain text as a new entry in the current
       * database.
       * 
       */
      public boolean importData(JComponent comp, Transferable t) {

            // If the drop target is the main table, we want to record which
            // row the item was dropped on, to identify the entry if needed:
            int dropRow = -1;
            if (comp instanceof JTable) {
                  dropRow = ((JTable) comp).getSelectedRow();
            }

            try {

                  // This flavor is used for dragged file links in Windows:
                  if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                        // JOptionPane.showMessageDialog(null, "Received
                        // javaFileListFlavor");
                        @SuppressWarnings("unchecked")
                        List<File> l = (List<File>) t.getTransferData(DataFlavor.javaFileListFlavor);
                        return handleDraggedFiles(l, dropRow);
                  }

                  if (t.isDataFlavorSupported(urlFlavor)) {
                        URL dropLink = (URL) t.getTransferData(urlFlavor);
                        return handleDropTransfer(dropLink, dropRow);
                  }

                  if (t.isDataFlavorSupported(stringFlavor)) {
                        // JOptionPane.showMessageDialog(null, "Received stringFlavor:
                        // "+dropStr);
                        String dropStr = (String) t.getTransferData(stringFlavor);
                        return handleDropTransfer(dropStr, dropRow);
                  }

            } catch (IOException ioe) {
                  System.err.println("failed to read dropped data: " + ioe.toString());
            } catch (UnsupportedFlavorException ufe) {
                  System.err.println("drop type error: " + ufe.toString());
            }

            // all supported flavors failed
            System.err.println("can't transfer input: ");
            DataFlavor inflavs[] = t.getTransferDataFlavors();
            for (int i = 0; i < inflavs.length; i++) {
                  System.out.println("  " + inflavs[i].toString());
            }

            return false;
      }

      /**
       * This method is called to query whether the transfer can be imported.
       * 
       * Will return true for urls, strings, javaFileLists
       * 
       * @override
       */
      public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
            if (!DROP_ALLOWED)
                  return false;

            // accept this if any input flavor matches any of our supported flavors
            for (int i = 0; i < transferFlavors.length; i++) {
                  DataFlavor inflav = transferFlavors[i];
                  if (inflav.match(urlFlavor) || inflav.match(stringFlavor)
                        || inflav.match(DataFlavor.javaFileListFlavor))
                        return true;
            }

            // System.out.println("drop type forbidden");
            // nope, never heard of this type
            return false;
      }
    boolean draggingFile = false;

      public void exportAsDrag(JComponent comp, InputEvent e, int action) {
            /* TODO: add support for dragging file link from table icon into other apps */
        if (e instanceof MouseEvent) {
            MouseEvent me = (MouseEvent)e;
            int col = entryTable.columnAtPoint(me.getPoint());
            String[] res = entryTable.getIconTypeForColumn(col);
            if (res == null) {
                super.exportAsDrag(comp, e, DnDConstants.ACTION_LINK);
                return;
            }
            // We have an icon column:
            if (res == MainTableFormat.FILE) {
                System.out.println("dragging file");
                draggingFile = true;
            }
        }
        super.exportAsDrag(comp, e, DnDConstants.ACTION_LINK);
      }

      protected void exportDone(JComponent source, Transferable data, int action) {
            // default implementation is OK
            super.exportDone(source, data, action);
      }

      public void exportToClipboard(JComponent comp, Clipboard clip, int action) {
            // default implementation is OK
            super.exportToClipboard(comp, clip, action);
      }

      // add-ons -----------------------

      protected boolean handleDropTransfer(String dropStr, final int dropRow) throws IOException {
        if (dropStr.startsWith("file:")) {
                  // This appears to be a dragged file link and not a reference
                  // format. Check if we can map this to a set of files:
                  if (handleDraggedFilenames(dropStr, dropRow))
                        return true;
                  // If not, handle it in the normal way...
            } else if (dropStr.startsWith("http:")) {
                  // This is the way URL links are received on OS X and KDE (Gnome?):
                  URL url = new URL(dropStr);
                  // JOptionPane.showMessageDialog(null, "Making URL:
                  // "+url.toString());
                  return handleDropTransfer(url, dropRow);
            }
            File tmpfile = java.io.File.createTempFile("jabrefimport", "");
            tmpfile.deleteOnExit();
            FileWriter fw = new FileWriter(tmpfile);
            fw.write(dropStr);
            fw.close();

            // System.out.println("importing from " + tmpfile.getAbsolutePath());

            ImportMenuItem importer = new ImportMenuItem(frame, false);
            importer.automatedImport(new String[] { tmpfile.getAbsolutePath() });

            return true;
      }

    /**
       * Translate a String describing a set of files or URLs dragged into JabRef
     * into a List of File objects, taking care of URL special characters.
       *
       * @param s
       *            String describing a set of files or URLs dragged into JabRef
     * @return a List<File> containing the individual file objects.
     *
       */
    public static List<File> getFilesFromDraggedFilesString(String s) {
            // Split into lines:
            String[] lines = s.replaceAll("\r", "").split("\n");
            List<File> files = new ArrayList<File>();
            for (int i = 0; i < lines.length; i++) {
                  String line = lines[i];

            // Try to use url.toURI() to translate URL specific sequences like %20 into
            // standard characters:
            File fl = null;
            try {
                URL url = new URL(line);
                fl = new File(url.toURI());
            } catch(URISyntaxException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }

            // Unless an exception was thrown, we should have the sanitized path:
            if (fl != null)
                line = fl.getPath();
            else if (line.startsWith("file:"))
                        line = line.substring(5);
                  else
                        continue;
            // Under Gnome, the link is given as file:///...., so we
                  // need to strip the extra slashes:
                  if (line.startsWith("//"))
                        line = line.substring(2);

            File f = new File(line);
            if (f.exists()) {
                        files.add(f);
                  }
            }
        return files;
    }

    /**
       * Handle a String describing a set of files or URLs dragged into JabRef.
       * 
       * @param s
       *            String describing a set of files or URLs dragged into JabRef
     * @param dropRow The row in the table where the files were dragged.
     * @return success status for the operation
     *
       */
      private boolean handleDraggedFilenames(String s, final int dropRow) {

            return handleDraggedFiles(getFilesFromDraggedFilesString(s), dropRow);

      }

      /**
       * Handle a List containing File objects for a set of files to import.
       * 
       * @param files
       *            A List containing File instances pointing to files.
       * @param dropRow @param dropRow The row in the table where the files were dragged.
     * @return success status for the operation
       */
      private boolean handleDraggedFiles(List<File> files, final int dropRow) {
            final String[] fileNames = new String[files.size()];
            int i = 0;
            for (Iterator<File> iterator = files.iterator(); iterator.hasNext();) {
                  File file = iterator.next();
                  fileNames[i] = file.getAbsolutePath();
                  i++;
            }
            // Try to load bib files normally, and import the rest into the current
            // database.
            // This process must be spun off into a background thread:
            new Thread(new Runnable() {
                  public void run() {
                        loadOrImportFiles(fileNames, dropRow);
                  }
            }).start();

            return true;
      }

      /**
       * Take a set of filenames. Those with names indicating bib files are opened
       * as such if possible. All other files we will attempt to import into the
       * current database.
       * 
       * @param fileNames
       *            The names of the files to open.
       * @param dropRow success status for the operation
       */
      private void loadOrImportFiles(String[] fileNames, int dropRow) {

            OpenDatabaseAction openAction = new OpenDatabaseAction(frame, false);
            ArrayList<String> notBibFiles = new ArrayList<String>();
            String encoding = Globals.prefs.get("defaultEncoding");
            for (int i = 0; i < fileNames.length; i++) {
                  // Find the file's extension, if any:
            String extension = "";
                  ExternalFileType fileType = null;
                  int index = fileNames[i].lastIndexOf('.');
                  if ((index >= 0) && (index < fileNames[i].length())) {
                        extension = fileNames[i].substring(index + 1).toLowerCase();
                        fileType = Globals.prefs.getExternalFileTypeByExt(extension);
                  }
                  if (extension.equals("bib")) {
                        File f = new File(fileNames[i]);
                        try {
                              ParserResult pr = OpenDatabaseAction.loadDatabase(f, encoding);
                              if ((pr == null) || (pr == ParserResult.INVALID_FORMAT)) {
                                    notBibFiles.add(fileNames[i]);
                              } else {
                                    openAction.addNewDatabase(pr, f, true);
                        frame.getFileHistory().newFile(fileNames[i]);
                    }
                        } catch (IOException e) {
                              notBibFiles.add(fileNames[i]);
                              // No error message, since we want to try importing the
                              // file?
                              //
                              // Util.showQuickErrorDialog(frame, Globals.lang("Open
                              // database"), e);
                        }
                        continue;
                  }

                  /*
                   * This is a linkable file. If the user dropped it on an entry, we
                   * should offer options for autolinking to this files:
                   * 
                   * TODO we should offer an option to highlight the row the user is on too.
                   */
                  if (fileType != null && dropRow >= 0) {

                        /*
                         * TODO: need to signal if this is a local or autodownloaded
                         * file
                         */
                        boolean local = true;

                        /*
                         * TODO: make this an instance variable?
                         */
                        DroppedFileHandler dfh = new DroppedFileHandler(frame, panel);
                        dfh.handleDroppedfile(fileNames[i], fileType, local, entryTable, dropRow);

                        continue;
                  }
/*
                  if (extension.equals("pdf")) {
                        Collection c;
                        try {
                              c = XMPUtil.readXMP(fileNames[i]);
                        } catch (IOException e1) {
                              c = null;
                              frame.output(Globals.lang("No XMP metadata found in " + fileNames[i]));
                        }

                        if (c != null && c.size() > 0) {
                              Iterator it = c.iterator();

                              BasePanel panel = frame.basePanel();

                              if (panel == null) {
                                    // // Create a new, empty, database.
                                    BibtexDatabase database = new BibtexDatabase();
                                    frame.addTab(database, null, null, Globals.prefs.get("defaultEncoding"),
                                          true);
                                    frame.output(Globals.lang("New database created."));
                                    panel = frame.basePanel();
                              }

                              BibtexDatabase database = frame.basePanel().database();

                              NamedCompound ce = new NamedCompound(Globals.lang("Drog PDF"));

                              while (it.hasNext()) {
                                    BibtexEntry e = (BibtexEntry) it.next();

                                    try {
                                          e.setId(Util.createNeutralId());
                                          database.insertEntry(e);
                                          ce.addEdit(new UndoableInsertEntry(database, e, panel));
                                    } catch (Exception e2) {
                                          // Should not happen?
                                    }
                              }

                              ce.end();
                              panel.undoManager.addEdit(ce);
                              panel.markBaseChanged();
                              continue;
                        }
                  }
                  */

                  notBibFiles.add(fileNames[i]);
            }

            if (notBibFiles.size() > 0) {
                  String[] toImport = new String[notBibFiles.size()];
                  notBibFiles.toArray(toImport);

                  // Import into new if entryTable==null, otherwise into current
                  // database:
                  ImportMenuItem importer = new ImportMenuItem(frame, (entryTable == null));
                  importer.automatedImport(toImport);
            }
      }

      protected boolean handleDropTransfer(URL dropLink, int dropRow) throws IOException {
            File tmpfile = java.io.File.createTempFile("jabrefimport", "");
            tmpfile.deleteOnExit();

            // System.out.println("Import url: " + dropLink.toString());
            // System.out.println("Temp file: "+tmpfile.getAbsolutePath());

            new URLDownload(entryTable, dropLink, tmpfile).download();

            // Import into new if entryTable==null, otherwise into current database:
            ImportMenuItem importer = new ImportMenuItem(frame, (entryTable == null));
            importer.automatedImport(new String[] { tmpfile.getAbsolutePath() });

            return true;
      }

}

Generated by  Doxygen 1.6.0   Back to index