Package net.sf.jabref.groups

Source Code of net.sf.jabref.groups.EntryTableTransferHandler

/*
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;
  }

}
TOP

Related Classes of net.sf.jabref.groups.EntryTableTransferHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.