Example #1
0
  private void doRenamePDFs(BibtexEntry entry, NamedCompound ce) {
    // Extract the path
    String oldValue = entry.getField(Globals.FILE_FIELD);
    if (oldValue == null) {
      return;
    }
    FileListTableModel flModel = new FileListTableModel();
    flModel.setContent(oldValue);
    if (flModel.getRowCount() == 0) {
      return;
    }
    boolean changed = false;

    for (int i = 0; i < flModel.getRowCount(); i++) {
      String realOldFilename = flModel.getEntry(i).getLink();

      if (cleanUpRenamePDFonlyRelativePaths.isSelected()
          && (new File(realOldFilename).isAbsolute())) {
        continue;
      }

      String newFilename = Util.getLinkedFileName(panel.database(), entry);
      // String oldFilename = bes.getField(GUIGlobals.FILE_FIELD); // would have to be stored for
      // undoing purposes

      // Add extension to newFilename
      newFilename = newFilename + "." + flModel.getEntry(i).getType().getExtension();

      // get new Filename with path
      // Create new Path based on old Path and new filename
      File expandedOldFile =
          FileUtil.expandFilename(
              realOldFilename, panel.metaData().getFileDirectory(Globals.FILE_FIELD));
      if (expandedOldFile.getParent() == null) {
        // something went wrong. Just skip this entry
        continue;
      }
      String newPath =
          expandedOldFile
              .getParent()
              .concat(System.getProperty("file.separator"))
              .concat(newFilename);

      if (new File(newPath).exists()) {
        // we do not overwrite files
        // TODO: we could check here if the newPath file is linked with the current entry. And if
        // not, we could add a link
        continue;
      }

      // do rename
      boolean renameSuccessful = FileUtil.renameFile(expandedOldFile.toString(), newPath);

      if (renameSuccessful) {
        changed = true;

        // Change the path for this entry
        String description = flModel.getEntry(i).getDescription();
        ExternalFileType type = flModel.getEntry(i).getType();
        flModel.removeEntry(i);

        // we cannot use "newPath" to generate a FileListEntry as newPath is absolute, but we want
        // to keep relative paths whenever possible
        File parent = (new File(realOldFilename)).getParentFile();
        String newFileEntryFileName;
        if (parent == null) {
          newFileEntryFileName = newFilename;
        } else {
          newFileEntryFileName =
              parent.toString().concat(System.getProperty("file.separator")).concat(newFilename);
        }
        flModel.addEntry(i, new FileListEntry(description, newFileEntryFileName, type));
      } else {
        unsuccessfulRenames++;
      }
    }

    if (changed) {
      String newValue = flModel.getStringRepresentation();
      assert (!oldValue.equals(newValue));
      entry.setField(Globals.FILE_FIELD, newValue);
      // we put an undo of the field content here
      // the file is not being renamed back, which leads to inconsistencies
      // if we put a null undo object here, the change by "doMakePathsRelative" would overwrite the
      // field value nevertheless.
      ce.addEdit(new UndoableFieldChange(entry, Globals.FILE_FIELD, oldValue, newValue));
    }
  }
  @Override
  public void run() {
    if (!goOn) {
      panel.output(
          Localization.lang("This operation requires one or more entries to be selected."));
      return;
    }
    entriesChangedCount = 0;
    panel.frame().setProgressBarValue(0);
    panel.frame().setProgressBarVisible(true);
    int weightAutoSet = 10; // autoSet takes 10 (?) times longer than checkExisting
    int progressBarMax =
        (autoSet ? weightAutoSet * sel.size() : 0) + (checkExisting ? sel.size() : 0);
    panel.frame().setProgressBarMaximum(progressBarMax);
    int progress = 0;
    final NamedCompound ce = new NamedCompound(Localization.lang("Automatically set file links"));

    Set<BibEntry> changedEntries = new HashSet<>();

    // First we try to autoset fields
    if (autoSet) {
      Collection<BibEntry> entries = new ArrayList<>(sel);

      // Start the automatically setting process:
      Runnable r =
          AutoSetLinks.autoSetLinks(
              entries, ce, changedEntries, null, panel.getBibDatabaseContext(), null, null);
      JabRefExecutorService.INSTANCE.executeAndWait(r);
    }
    progress += sel.size() * weightAutoSet;
    panel.frame().setProgressBarValue(progress);
    // The following loop checks all external links that are already set.
    if (checkExisting) {
      boolean removeAllBroken = false;
      mainLoop:
      for (BibEntry aSel : sel) {
        panel.frame().setProgressBarValue(progress++);
        final String old = aSel.getField(Globals.FILE_FIELD);
        // Check if a extension is set:
        if ((old != null) && !(old.isEmpty())) {
          FileListTableModel tableModel = new FileListTableModel();
          tableModel.setContentDontGuessTypes(old);

          // We need to specify which directories to search in for Util.expandFilename:
          List<String> dirsS = panel.getBibDatabaseContext().getFileDirectory();
          List<File> dirs = new ArrayList<>();
          for (String dirs1 : dirsS) {
            dirs.add(new File(dirs1));
          }

          for (int j = 0; j < tableModel.getRowCount(); j++) {
            FileListEntry flEntry = tableModel.getEntry(j);
            // See if the link looks like an URL:
            boolean httpLink = flEntry.link.toLowerCase(Locale.ENGLISH).startsWith("http");
            if (httpLink) {
              continue; // Don't check the remote file.
              // TODO: should there be an option to check remote links?
            }

            // A variable to keep track of whether this link gets deleted:
            boolean deleted = false;

            // Get an absolute path representation:
            Optional<File> file = FileUtil.expandFilename(flEntry.link, dirsS);
            if ((!file.isPresent()) || !file.get().exists()) {
              int answer;
              if (removeAllBroken) {
                answer = 2; // We should delete this link.
              } else {
                answer =
                    JOptionPane.showOptionDialog(
                        panel.frame(),
                        Localization.lang(
                            "<HTML>Could not find file '%0'<BR>linked from entry '%1'</HTML>",
                            flEntry.link, aSel.getCiteKey()),
                        Localization.lang("Broken link"),
                        JOptionPane.YES_NO_CANCEL_OPTION,
                        JOptionPane.QUESTION_MESSAGE,
                        null,
                        brokenLinkOptions,
                        brokenLinkOptions[0]);
              }
              switch (answer) {
                case 1:
                  // Assign new file.
                  FileListEntryEditor flEditor =
                      new FileListEntryEditor(
                          panel.frame(), flEntry, false, true, panel.getBibDatabaseContext());
                  flEditor.setVisible(true, true);
                  break;
                case 2:
                  // Clear field:
                  tableModel.removeEntry(j);
                  deleted = true; // Make sure we don't investigate this link further.
                  j--; // Step back in the iteration, because we removed an entry.
                  break;
                case 3:
                  // Clear field:
                  tableModel.removeEntry(j);
                  deleted = true; // Make sure we don't investigate this link further.
                  j--; // Step back in the iteration, because we removed an entry.
                  removeAllBroken = true; // Notify for further cases.
                  break;
                default:
                  // Cancel
                  break mainLoop;
              }
            }

            // Unless we deleted this link, see if its file type is recognized:
            if (!deleted
                && flEntry.type.isPresent()
                && (flEntry.type.get() instanceof UnknownExternalFileType)) {
              String[] options =
                  new String[] {
                    Localization.lang("Define '%0'", flEntry.type.get().getName()),
                    Localization.lang("Change file type"),
                    Localization.lang("Cancel")
                  };
              String defOption = options[0];
              int answer =
                  JOptionPane.showOptionDialog(
                      panel.frame(),
                      Localization.lang(
                          "One or more file links are of the type '%0', which is undefined. What do you want to do?",
                          flEntry.type.get().getName()),
                      Localization.lang("Undefined file type"),
                      JOptionPane.YES_NO_CANCEL_OPTION,
                      JOptionPane.QUESTION_MESSAGE,
                      null,
                      options,
                      defOption);
              if (answer == JOptionPane.CANCEL_OPTION) {
                // User doesn't want to handle this unknown link type.
              } else if (answer == JOptionPane.YES_OPTION) {
                // User wants to define the new file type. Show the dialog:
                ExternalFileType newType =
                    new ExternalFileType(
                        flEntry.type.get().getName(),
                        "",
                        "",
                        "",
                        "new",
                        IconTheme.JabRefIcon.FILE.getSmallIcon());
                ExternalFileTypeEntryEditor editor =
                    new ExternalFileTypeEntryEditor(panel.frame(), newType);
                editor.setVisible(true);
                if (editor.okPressed()) {
                  // Get the old list of types, add this one, and update the list in prefs:
                  List<ExternalFileType> fileTypes =
                      new ArrayList<>(
                          ExternalFileTypes.getInstance().getExternalFileTypeSelection());
                  fileTypes.add(newType);
                  Collections.sort(fileTypes);
                  ExternalFileTypes.getInstance().setExternalFileTypes(fileTypes);
                  panel.getMainTable().repaint();
                }
              } else {
                // User wants to change the type of this link.
                // First get a model of all file links for this entry:
                FileListEntryEditor editor =
                    new FileListEntryEditor(
                        panel.frame(), flEntry, false, true, panel.getBibDatabaseContext());
                editor.setVisible(true, false);
              }
            }
          }

          if (!tableModel.getStringRepresentation().equals(old)) {
            // The table has been modified. Store the change:
            String toSet = tableModel.getStringRepresentation();
            if (toSet.isEmpty()) {
              ce.addEdit(new UndoableFieldChange(aSel, Globals.FILE_FIELD, old, null));
              aSel.clearField(Globals.FILE_FIELD);
            } else {
              ce.addEdit(new UndoableFieldChange(aSel, Globals.FILE_FIELD, old, toSet));
              aSel.setField(Globals.FILE_FIELD, toSet);
            }
            changedEntries.add(aSel);
          }
        }
      }
    }

    if (!changedEntries.isEmpty()) {
      // Add the undo edit:
      ce.end();
      panel.getUndoManager().addEdit(ce);
      panel.markBaseChanged();
      entriesChangedCount = changedEntries.size();
    }
  }