Tuesday, February 16, 2016

Create pdf from context menu with pdf-generate

Source.



sudo apt-get install imagemagick unoconv ghostscript zenity libfile-mimeinfo-perl
 
 
 
 gedit ~/.config/pdf-generate.conf
 
 
And paste this:


[general]
compression=95 
density=200


So if you want to modify any default parameter, just edit this file before running the tool.

 Main script in charge of the PDF generation k=job should be placed under /usr/local/bin/pdf-generate. See source link to see its content. (Also here.)


# mkdir --parents $HOME/.config
# wget --header='Accept-Encoding:none' -O $HOME/.config/pdf-generate.conf https://raw.githubusercontent.com/NicolasBernaerts/ubuntu-scripts/master/pdf/pdf-generate.conf
# sudo wget --header='Accept-Encoding:none' -O /usr/local/bin/pdf-generate https://raw.githubusercontent.com/NicolasBernaerts/ubuntu-scripts/master/pdf/pdf-generate
# sudo chmod +x /usr/local/bin/pdf-generate
 
In case that expires:

sudo gedit /usr/local/bin/pdf-generate



and paste this:


#!/bin/bash
# --------------------------------------------
#  Generate a PDF document from a given list of documents
#  Documents are added in final document following
#  alphabetical order
#
#  Setup procedure : http://bernaerts.dyndns.org/linux/74-ubuntu/338-ubuntu-generate-pdf-from-documents
#
#  Depends on :
#   * imagemagick
#   * unoconv
#   * ghostscript
#   * mimetype
#
#  Parameters : full path of documents
#
#  Revision history :
#   05/07/2015, V1.0 - Creation by N. Bernaerts
#   15/08/2015, V1.1 - Force jpeg quality to 95
#   25/09/2015, V1.2 - Add configuration file
#   02/10/2015, V2.0 - Code rewrite to handle progress and notification
# ---------------------------------------------------

# -------------------------------------------------------
# check tools availability
# -------------------------------------------------------

command -v bc >/dev/null 2>&1 || { zenity --error --text="Please install bc"; exit 1; }
command -v mimetype >/dev/null 2>&1 || { zenity --error --text="Please install mimetype"; exit 1; }
command -v convert >/dev/null 2>&1 || { zenity --error --text="Please install convert [imagemagick]"; exit 1; }
command -v unoconv >/dev/null 2>&1 || { zenity --error --text="Please install unoconv"; exit 1; }
command -v gs >/dev/null 2>&1 || { zenity --error --text="Please install gs utility [ghostscript]"; exit 1; }

# ---------------------------------------------------------
#   Read and calculate parameters from configuration file
# ---------------------------------------------------------

# Configuration file : ~/.config/pdf-generate.conf
FILE_CONF="$HOME/.config/pdf-generate.conf"

# check configuration file
[ -f "$FILE_CONF" ] || { zenity --error --text="Please create and configure ${FILE_CONF}"; exit 1; }

# Load configuration file
COMPRESSION=$(cat "${FILE_CONF}" | grep "compression" | cut -d'=' -f2)
DENSITY=$(cat "${FILE_CONF}" | grep "density" | cut -d'=' -f2)

# calculate page size
PAGE_WIDTH=$(echo "${DENSITY} * 8.27" | bc)
PAGE_HEIGHT=$(echo "${DENSITY} * 11.7" | bc)

# -------------------------------------------------------
#          Retrieve or select input files
# -------------------------------------------------------

# set separator as carriage return
IFS=$'\n'

# loop thru arguments to load candidate files
for ARGUMENT
do
  [ -f "${ARGUMENT}" ] && ARR_FILE=("${ARR_FILE[@]}" "${ARGUMENT}")
  [ -d "${ARGUMENT}" ] && ARR_FILE=("${ARR_FILE[@]}" $(find "${ARGUMENT}" -maxdepth 1 -type f) )
done

# if there is no candidate files, open selection dialog
if [ ${#ARR_FILE[@]} -eq 0 ]
then
  # open multiple files selection dialog box
  LST_FILE=$(zenity --file --multiple --title="Select file to merge as PDF")

  # generate video files array
  ARR_FILE=($(echo "${LST_FILE}" | tr "|" "\n"))
fi

# -------------------------------------------------------
# loop thru selected files to check convertibility
# -------------------------------------------------------

for FILE in "${ARR_FILE[@]}"
do
  # document type undefined
  DOCTYPE=""

  # get the file mime type (application/msword, ...)
  MIMETYPE=$(mimetype -b "${FILE}")

  # check if file is a image file (.jpg, .png, .tiff, ...)
  CHECKTYPE=$(echo "${MIMETYPE}" | grep "image/")
  [ "${CHECKTYPE}" != "" ] && DOCTYPE="image"

  # check if file is a libreoffice file (.odt, .ods, ...)
  CHECKTYPE=$(echo "${MIMETYPE}" | grep ".opendocument.")
  [ "${CHECKTYPE}" != "" ] && DOCTYPE="libreoffice"

  # check if file is a microsoft file 2007+ file (.docx, .xlsx, .pptx, ...)
  CHECKTYPE=$(echo "${MIMETYPE}" | grep "vnd.openxmlformats-officedocument.")
  [ "${CHECKTYPE}" != "" ] && DOCTYPE="ms-office"

  # check some specific document types
  case $MIMETYPE in
    # ms-office document (.doc, .xls, .ppt, ...)
    "application/msword" | "application/vnd.ms-word" | "application/vnd.oasis.opendocument.text" | \
    "application/vnd.ms-excel" | "application/vnd.ms-powerpoint" )
      DOCTYPE="ms-office"
      ;;

    # PDF document (.pdf)
    "application/pdf" | "application/x-pdf" | "application/x-bzpdf" | "application/x-gzpdf" )
      DOCTYPE="pdf"
      ;;

    # plain text file (.txt)
    "text/plain" | "application/x-shellscript" )
      DOCTYPE="text"
      ;;

    * )
      ;;
  esac

  # if document type is compatible, add current file as candidate
  [ "${DOCTYPE}" != "" ] && ARR_CANDIDATE=("${ARR_CANDIDATE[@]}" "${FILE}|${DOCTYPE}")

done

# -------------------------------------------------------
#       Confirmation dialog box
# -------------------------------------------------------

# calculate number of files to convert
NBR_FILE=${#ARR_FILE[@]}
NBR_CANDIDATE=${#ARR_CANDIDATE[@]}

# if some candidate file exist, order them and display confirmation dialog
if [ ${NBR_CANDIDATE} -gt 0 ]
then
  # order generated PDF files in alphabetical order
  ARR_CANDIDATE=($(sort <<<"${ARR_CANDIDATE[*]}"))

  # generate final file name
  FILE=$(echo "${ARR_CANDIDATE[0]}" | cut -d'|' -f1)
  FILE_FINAL="$(echo "${FILE}" | sed 's/^\(.*\)\..*$/\1/')-merged.pdf"

  # display confirmation dialog box
  RESULT=$(zenity --question --title="Merge to PDF" --text="${NBR_CANDIDATE} file(s) out of ${NBR_FILE} will be merged to a single PDF file (${DENSITY} DPI)\n\nDo you want to generate ${FILE_FINAL} ?" )
  ACTION=$?

# else display error dialog
else
  # display confirmation dialog box
  RESULT=$(zenity --error --title="Merge to PDF" --text="There is no file compatible with PDF format." )
  ACTION=""

fi

# if action canceled or error, exit
[ "${ACTION}" != "0" ] && exit 1

(

# -------------------------------------------------------
# loop thru candidate files to convert them to PDF
# -------------------------------------------------------

for CANDIDATE in "${ARR_CANDIDATE[@]}"
do
  # retrieve document type and filename
  FILE=$(echo "${CANDIDATE}" | cut -d'|' -f1)
  DOCTYPE=$(echo "${CANDIDATE}" | cut -d'|' -f2)

  # progress display
  echo "# Conversion of ${FILE}"

  # get file name without extension & generate resulting PDF file name
  FILE_BASE="$(echo "${FILE}" | sed 's/^\(.*\)\..*$/\1/')"
  FILE_PDF="${FILE_BASE}.pdf"

  # convert file according to its type
  case $DOCTYPE in
    # PDF files
    "pdf" )
    ARR_PDF=("${ARR_PDF[@]}" "${FILE}")
    ;;

    # image files
    "image" )
    convert "${FILE}" -compress jpeg -quality ${COMPRESSION} -resize ${PAGE_WIDTH}x${PAGE_HEIGHT} -gravity center -extent ${PAGE_WIDTH}x${PAGE_HEIGHT} -units PixelsPerInch -density ${DENSITY}x${DENSITY} "${FILE_PDF}"
    ARR_TMP=("${ARR_TMP[@]}" "${FILE_PDF}")
    ARR_PDF=("${ARR_PDF[@]}" "${FILE_PDF}")
    ;;

    # office files
    "libreoffice" | "ms-office" | "text" )
    unoconv -f pdf -o "${FILE_PDF}" "${FILE}"
    ARR_TMP=("${ARR_TMP[@]}" "${FILE_PDF}")
    ARR_PDF=("${ARR_PDF[@]}" "${FILE_PDF}")
    ;;

    # other formats, not handled
    * )
    ;;
  esac

done

# -------------------------------------------------------
#   Final merge
# -------------------------------------------------------

if [ ${#ARR_PDF[@]} -gt 0 ]
then
  # progress display
  echo "# Final assembly of ${FILE_FINAL}"

  # generate resulting PDF
  gs -q -dNOPAUSE -dBATCH -dSAFER -sPAPERSIZE=a4 -dPDFFitPage -dCompatibilityLevel=1.4 -sDEVICE=pdfwrite -sOutputFile="${FILE_FINAL}" ${ARR_PDF[@]}
fi

# -------------------------------------------------------
#   Temporary files clean-up
# -------------------------------------------------------

# loop to remove temporary files
for TMP_FILE in "${ARR_TMP[@]}"
do
  rm "${TMP_FILE}"
done

) | zenity --width=500 --height=25 --progress --pulsate --auto-close --title "Merge to PDF"

# -------------------------------------------------------
#   End of job notification
# -------------------------------------------------------

[ ${#ARR_CANDIDATE[@]} -gt 0 ] && zenity --notification --window-icon="evince" --text="${FILE_FINAL} generated." \
                               || zenity --notification --window-icon="error" --text="Document type was not compatible for PDF generation."






Then make it executable:

sudo chmod +x /usr/local/bin/pdf-generate


To fully integrate this PDF generation tool in your desktop environment:
gedit /usr/share/applications/pdf-generate.desktop. 
 
 
Nautilus-Gnome content:
 
 
 [Desktop Entry]
Type=Application
Exec=pdf-generate
Hidden=false
NoDisplay=false
Icon=evince
Keywords=pdf;generate;image;office;document;merge
X-GNOME-Autostart-enabled=true
Name[en_US]=Generate PDF document
Name[en]=Generate PDF document
Name[C]=Generate PDF document
Name[fr_FR]=Génération d'un PDF
Comment=Tool to merge a set of documents to a PDF file.
Comment[en_US]=Tool to merge a set of documents to a PDF file.
Comment[fr_FR]=Outil de concaténation de documents en un fichier PDF.
MimeType=image/bmp;image/gif;image/jpeg;image/jpg;image/png;image/tiff;application/pdf;application/x-pdf;application/x-bzpdf;application/x-gzpdf;application/msword;application/vnd.ms-word;application/vnd.oasis.opendocument.text;application/vnd.openxmlformats-officedocument.wordprocessingml.document;application/vnd.ms-excel;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.spreadsheetml.template;application/vnd.ms-powerpoint;application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.openxmlformats-officedocument.presentationml.template;application/vnd.openxmlformats-officedocument.presentationml.slideshow;text/plain;
Categories=GNOME;GTK;Graphics;Conversion;Utility;

 KDE-Dolphin content

[Desktop Entry]
Actions=pdf-generate
Encoding=UTF8
Icon=pdf
MimeType=MimeTypes=image/bmp;image/gif;image/jpeg;image/jpg;image/png;image/tiff;application/pdf;application/x-pdf;application/x-bzpdf;application/x-gzpdf;application/msword;application/vnd.ms-word;application/vnd.oasis.opendocument.text;application/vnd.openxmlformats-officedocument.wordprocessingml.document;application/vnd.ms-excel;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.spreadsheetml.template;application/vnd.ms-powerpoint;application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.openxmlformats-officedocument.presentationml.template;application/vnd.openxmlformats-officedocument.presentationml.slideshow;text/plain;inode/directory;application/pdf
ServiceTypes=KonqPopupMenu/Plugin,image/jpeg
Type=Service
#X-KDE-Submenu=Convert all in folder

[Desktop Action pdf-generate]
Exec=pdf-generate %F
Icon=pdf
Name=Create pdf file


To get a full desktop integration, this PDF generation tool should be available from a custom action in your file manager context menu.

For Nautilus you need to declare the new custom action in a .desktop file placed under ~/.local/share/file-manager/actions

[Desktop Entry]
Type=Action
Icon=evince
Name[C]=Generate PDF document
Name[en]=Generate PDF document
Name[en_US]=Generate PDF document
Name[fr_FR]=Génération d'un PDF
Tooltip[C]=Tool to merge a set of documents to a PDF file
Tooltip[en]=Tool to merge a set of documents to a PDF file
Tooltip[en_US]=Tool to merge a set of documents to a PDF file
Tooltip[fr_FR]=Outil de concaténation de documents en un fichier PDF
Profiles=pdf_generate;

[X-Action-Profile pdf_generate]
Exec=pdf-generate %F
MimeTypes=image/bmp;image/gif;image/jpeg;image/jpg;image/png;image/tiff;application/pdf;application/x-pdf;application/x-bzpdf;application/x-gzpdf;application/msword;application/vnd.ms-word;application/vnd.oasis.opendocument.text;application/vnd.openxmlformats-officedocument.wordprocessingml.document;application/vnd.ms-excel;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.spreadsheetml.template;application/vnd.ms-powerpoint;application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.openxmlformats-officedocument.presentationml.template;application/vnd.openxmlformats-officedocument.presentationml.slideshow;text/plain;inode/directory;
Name[C]=Default profile
Name[en]=Default profile
Name[en_US]=Default profile
Name[fr_FR]=Profil par défaut

 For Dolphin/KDE it is in ~/.kde/share/kde4/services/ServiceMenus/

 Therefore,


gedit ~/.kde/share/kde4/services/ServiceMenus/pdf-generate.desktop

with the content:
 
[Desktop Entry]
Actions=pdf-generate
Encoding=UTF8
Icon=pdf
MimeType=MimeTypes=image/bmp;image/gif;image/jpeg;image/jpg;image/png;image/tiff;application/pdf;application/x-pdf;application/x-bzpdf;application/x-gzpdf;application/msword;application/vnd.ms-word;application/vnd.oasis.opendocument.text;application/vnd.openxmlformats-officedocument.wordprocessingml.document;application/vnd.ms-excel;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.spreadsheetml.template;application/vnd.ms-powerpoint;application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.openxmlformats-officedocument.presentationml.template;application/vnd.openxmlformats-officedocument.presentationml.slideshow;text/plain;inode/directory;application/pdf
ServiceTypes=KonqPopupMenu/Plugin
Type=Service


[Desktop Action pdf-generate]
Exec=pdf-generate %F
Icon=pdf
Name=Create pdf file
 After re-login, a context menu option will appear for selected files as indicated in the source link. For my KDE/Dolphin configuration, this works for selected files if they have the same extension. Otherwise, the best way it just to put all needed files in one folder and then execute the command from the right-click context menu of that folder.

Also here.