...
  View open merge request
Commits (5)
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
/* this file is part of evince, a gnome document viewer
*
* Copyright (C) 2018, Evangelos Rigas <erigas@rnd2.org>
......@@ -28,6 +27,7 @@
#include <poppler.h>
#include <poppler-document.h>
#include <poppler-page.h>
#include <poppler-features.h>
#ifdef HAVE_CAIRO_PDF
#include <cairo-pdf.h>
#endif
......@@ -68,6 +68,12 @@
#define HAVE_CAIRO_PRINT
#endif
#if POPPLER_CHECK_VERSION (0, 67, 0)
#define HAVE_POPPLER_LOAD_FD
#else
#error too old
#endif
/* fields from the XMP Rights Management Schema, XMP Specification Sept 2005, pag. 45 */
#define LICENSE_MARKED "/rdf:RDF/rdf:Description/xmpRights:Marked"
#define LICENSE_TEXT "/rdf:RDF/rdf:Description/dc:rights/rdf:Alt/rdf:li[lang('%s')]"
......@@ -345,6 +351,32 @@ pdf_document_load_gfile (EvDocument *document,
return TRUE;
}
#ifdef HAVE_POPPLER_LOAD_FD
static gboolean
pdf_document_load_fd (EvDocument *document,
int fd,
EvDocumentLoadFlags flags,
GCancellable *cancellable,
GError **error)
{
GError *err = NULL;
PdfDocument *pdf_document = PDF_DOCUMENT (document);
/* Note: this consumes @fd */
pdf_document->document =
poppler_document_new_from_fd (fd,
pdf_document->password,
&err);
if (pdf_document->document == NULL) {
convert_error (err, error);
return FALSE;
}
return TRUE;
}
#endif
static int
pdf_document_get_n_pages (EvDocument *document)
{
......@@ -1238,6 +1270,9 @@ pdf_document_class_init (PdfDocumentClass *klass)
ev_document_class->get_info = pdf_document_get_info;
ev_document_class->get_backend_info = pdf_document_get_backend_info;
ev_document_class->support_synctex = pdf_document_support_synctex;
#ifdef HAVE_POPPLER_LOAD_FD
ev_document_class->load_fd = pdf_document_load_fd;
#endif
}
/* EvDocumentSecurity */
......
......@@ -29,6 +29,10 @@
#include "ev-file-exporter.h"
#include "ev-document-misc.h"
#if SPECTRE_VERSION >= 209
#define HAVE_LOAD_FD
#endif
struct _PSDocument {
EvDocument object;
......@@ -108,6 +112,31 @@ ps_document_load (EvDocument *document,
return TRUE;
}
#ifdef HAVE_LOAD_FD
static gboolean
ps_document_load_fd (EvDocument *document,
int fd,
EvDocumentLoadFlags flags,
GCancellable *cancellable,
GError **error)
{
PSDocument *ps = PS_DOCUMENT (document);
ps->doc = spectre_document_new ();
spectre_document_load_from_fd (ps->doc, fd);
if (spectre_document_status (ps->doc)) {
g_set_error_literal (error,
G_FILE_ERROR,
G_FILE_ERROR_FAILED,
_("Failed to load document"));
return FALSE;
}
return TRUE;
}
#endif
static gboolean
ps_document_save (EvDocument *document,
const char *uri,
......@@ -357,6 +386,9 @@ ps_document_class_init (PSDocumentClass *klass)
ev_document_class->get_info = ps_document_get_info;
ev_document_class->get_backend_info = ps_document_get_backend_info;
ev_document_class->render = ps_document_render;
#ifdef HAVE_LOAD_FD
ev_document_class->load_fd = ps_document_load_fd;
#endif
}
/* EvFileExporterIface */
......
......@@ -368,6 +368,7 @@ ev_document_get_backend_info
ev_document_load
ev_document_load_stream
ev_document_load_gfile
ev_document_load_fd
ev_document_save
ev_document_get_n_pages
ev_document_get_page
......@@ -775,6 +776,7 @@ ev_document_fonts_get_type
ev_document_factory_get_document
ev_document_factory_get_document_for_gfile
ev_document_factory_get_document_for_stream
ev_document_factory_get_document_for_fd
ev_document_factory_add_filters
</SECTION>
......
......@@ -183,6 +183,8 @@ EvJobLoadStream
EvJobLoadStreamClass
EvJobLoadGFile
EvJobLoadGFileClass
EvJobLoadFd
EvJobLoadFdClass
EvJobSave
EvJobSaveClass
EvJobFind
......@@ -225,12 +227,20 @@ ev_job_load_set_uri
ev_job_load_set_password
ev_job_load_stream_new
ev_job_load_stream_set_stream
ev_job_load_stream_set_mime_type
ev_job_load_stream_set_load_flags
ev_job_load_stream_set_password
ev_job_load_gfile_new
ev_job_load_gfile_set_gfile
ev_job_load_gfile_set_load_flags
ev_job_load_gfile_set_password
ev_job_load_fd_new
ev_job_load_fd_new_take
ev_job_load_fd_set_fd
ev_job_load_fd_take_fd
ev_job_load_fd_set_set_mime_type
ev_job_load_fd_set_load_flags
ev_job_load_fd_set_password
ev_job_save_new
ev_job_find_new
ev_job_find_get_n_results
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
/*
* Copyright (C) 2005, Red Hat, Inc.
* Copyright (C) 2005, Red Hat, Inc.
* Copyright © 2018 Christian Persch
*
* 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
......@@ -536,6 +536,66 @@ ev_document_factory_get_document_for_stream (GInputStream *stream,
return document;
}
/**
* ev_document_factory_get_document_for_fd:
* @stream: a file descriptor
* @mime_type: the mime type
* @flags: flags from #EvDocumentLoadFlags
* @cancellable: (allow-none): a #GCancellable, or %NULL
* @error: (allow-none): a #GError location to store an error, or %NULL
*
* Synchronously creates a #EvDocument for the document from @fd using the backend
* for loading documents of type @mime_type; or, if the backend does not support
* loading from file descriptors, or an error occurred on opening the document,
* returns %NULL and fills in @error.
* If the document is encrypted, it is returned but also @error is set to
* %EV_DOCUMENT_ERROR_ENCRYPTED.
*
* If the mime type cannot be inferred from the file descriptor, and @mime_type is %NULL,
* an error is returned.
*
* Note that this function takes ownership of @fd; you must not ever
* operate on it again. It will be closed automatically if the document
* is destroyed, or if this function returns %NULL.
*
* Returns: (transfer full): a new #EvDocument, or %NULL
*
* Since: 3.30
*/
EvDocument*
ev_document_factory_get_document_for_fd (int fd,
const char *mime_type,
EvDocumentLoadFlags flags,
GCancellable *cancellable,
GError **error)
{
EvDocument *document;
g_return_val_if_fail (fd != -1, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
if (mime_type == NULL) {
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"Cannot query mime type from file descriptor");
close (fd);
return NULL;
}
document = ev_document_factory_new_document_for_mime_type (mime_type, error);
if (document == NULL) {
close (fd);
return NULL;
}
if (!ev_document_load_fd (document, fd, flags, cancellable, error)) {
/* fd is now consumed */
g_object_unref (document);
return NULL;
}
return document;
}
static void
file_filter_add_mime_types (EvBackendInfo *info, GtkFileFilter *filter)
{
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
/*
* Copyright (C) 2005, Red Hat, Inc.
* Copyright (C) 2005, Red Hat, Inc.
*
* 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
......@@ -47,6 +46,11 @@ EvDocument* ev_document_factory_get_document_for_stream (GInputStream *stream,
EvDocumentLoadFlags flags,
GCancellable *cancellable,
GError **error);
EvDocument* ev_document_factory_get_document_for_fd (int fd,
const char *mime_type,
EvDocumentLoadFlags flags,
GCancellable *cancellable,
GError **error);
void ev_document_factory_add_filters (GtkWidget *chooser, EvDocument *document);
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
/*
* Copyright (C) 2009 Carlos Garcia Campos
* Copyright (C) 2004 Marco Pesenti Gritti
* Copyright © 2018 Christian Persch
*
* 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
......@@ -23,6 +23,9 @@
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include "ev-document.h"
#include "ev-document-misc.h"
......@@ -567,6 +570,92 @@ ev_document_load_gfile (EvDocument *document,
return TRUE;
}
/**
* ev_document_load_fd:
* @document: a #EvDocument
* @fd: a file descriptor
* @flags: flags from #EvDocumentLoadFlags
* @cancellable: (allow-none): a #GCancellable, or %NULL
* @error: (allow-none): a #GError location to store an error, or %NULL
*
* Synchronously loads the document from @fd, which must refer to
* a regular file.
*
* Note that this function takes ownership of @fd; you must not ever
* operate on it again. It will be closed automatically if the document
* is destroyed, or if this function returns %NULL.
*
* See ev_document_load() for more information.
*
* Returns: %TRUE if loading succeeded, or %FALSE on error with @error filled in
*
* Since: 3.30
*/
gboolean
ev_document_load_fd (EvDocument *document,
int fd,
EvDocumentLoadFlags flags,
GCancellable *cancellable,
GError **error)
{
EvDocumentClass *klass;
struct stat statbuf;
int fd_flags;
g_return_val_if_fail (EV_IS_DOCUMENT (document), FALSE);
g_return_val_if_fail (fd != -1, FALSE);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
klass = EV_DOCUMENT_GET_CLASS (document);
if (!klass->load_fd) {
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"Backend does not support loading from file descriptor");
close (fd);
return FALSE;
}
if (fstat(fd, &statbuf) == -1 ||
(fd_flags = fcntl (fd, F_GETFL, &flags)) == -1) {
int errsv = errno;
g_set_error_literal(error, G_FILE_ERROR,
g_file_error_from_errno(errsv),
g_strerror(errsv));
close (fd);
return FALSE;
}
if (!S_ISREG(statbuf.st_mode)) {
g_set_error_literal(error, G_FILE_ERROR, G_FILE_ERROR_BADF,
"Not a regular file.");
close (fd);
return FALSE;
}
switch (fd_flags & O_ACCMODE) {
case O_RDONLY:
case O_RDWR:
break;
case O_WRONLY:
default:
g_set_error_literal(error, G_FILE_ERROR, G_FILE_ERROR_BADF,
"Not a readable file descriptor.");
close (fd);
return FALSE;
}
if (!klass->load_fd (document, fd, flags, cancellable, error))
return FALSE;
document->priv->info = _ev_document_get_info (document);
document->priv->n_pages = _ev_document_get_n_pages (document);
if (!(flags & EV_DOCUMENT_LOAD_FLAG_NO_CACHE))
ev_document_setup_cache (document);
return TRUE;
}
/**
* ev_document_save:
* @document: a #EvDocument
......@@ -574,7 +663,7 @@ ev_document_load_gfile (EvDocument *document,
* @error: a #GError location to store an error, or %NULL
*
* Saves @document to @uri.
*
*
* Returns: %TRUE on success, or %FALSE on error with @error filled in
*/
gboolean
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
/*
* Copyright (C) 2009 Carlos Garcia Campos
* Copyright (C) 2000-2003 Marco Pesenti Gritti
......@@ -132,6 +131,11 @@ struct _EvDocumentClass
GError **error);
cairo_surface_t * (* get_thumbnail_surface) (EvDocument *document,
EvRenderContext *rc);
gboolean (* load_fd) (EvDocument *document,
int fd,
EvDocumentLoadFlags flags,
GCancellable *cancellable,
GError **error);
};
GType ev_document_get_type (void) G_GNUC_CONST;
......@@ -172,6 +176,11 @@ gboolean ev_document_load_gfile (EvDocument *document,
EvDocumentLoadFlags flags,
GCancellable *cancellable,
GError **error);
gboolean ev_document_load_fd (EvDocument *document,
int fd,
EvDocumentLoadFlags flags,
GCancellable *cancellable,
GError **error);
gboolean ev_document_save (EvDocument *document,
const char *uri,
GError **error);
......
......@@ -43,6 +43,7 @@
#include <glib/gstdio.h>
#include <glib/gi18n-lib.h>
#include <unistd.h>
#include <fcntl.h>
static void ev_job_init (EvJob *job);
static void ev_job_class_init (EvJobClass *class);
......@@ -102,6 +103,7 @@ G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobLoadStream, ev_job_load_stream, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobLoadGFile, ev_job_load_gfile, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobLoadFd, ev_job_load_fd, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobSave, ev_job_save, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobFind, ev_job_find, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobLayers, ev_job_layers, EV_TYPE_JOB)
......@@ -1206,6 +1208,8 @@ ev_job_load_stream_dispose (GObject *object)
job->stream = NULL;
}
g_free (job->mime_type);
job->mime_type = NULL;
g_free (job->password);
job->password = NULL;
......@@ -1244,7 +1248,7 @@ ev_job_load_stream_run (EvJob *job)
&error);
} else {
job->document = ev_document_factory_get_document_for_stream (job_load_stream->stream,
NULL /* mime-type FIXME? */,
job_load_stream->mime_type,
job_load_stream->flags,
job->cancellable,
&error);
......@@ -1298,6 +1302,16 @@ ev_job_load_stream_set_stream (EvJobLoadStream *job,
job->stream = stream;
}
void
ev_job_load_stream_set_mime_type (EvJobLoadStream *job,
const char *mime_type)
{
g_return_if_fail (EV_IS_JOB_LOAD_STREAM (job));
g_free (job->mime_type);
job->mime_type = g_strdup (mime_type);
}
void
ev_job_load_stream_set_load_flags (EvJobLoadStream *job,
EvDocumentLoadFlags flags)
......@@ -1464,6 +1478,282 @@ ev_job_load_gfile_set_password (EvJobLoadGFile *job,
g_free (old_password);
}
/* EvJobLoadFd */
/**
* EvJobLoadFd:
*
* A job class to load a #EvDocument from a file descriptor
* referring to a regular file.
*
* Since: 3.30
*/
static int
ev_dupfd (int fd,
GError **error)
{
int new_fd;
new_fd = fcntl (fd, F_DUPFD_CLOEXEC, 3);
if (new_fd == -1) {
int errsv = errno;
g_set_error_literal (error, G_FILE_ERROR, g_file_error_from_errno (errsv),
g_strerror (errsv));
}
return new_fd;
}
static void
ev_job_load_fd_init (EvJobLoadFd *job)
{
job->flags = EV_DOCUMENT_LOAD_FLAG_NONE;
job->fd = -1;
EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
}
static void
ev_job_load_fd_dispose (GObject *object)
{
EvJobLoadFd *job = EV_JOB_LOAD_FD (object);
if (job->fd != -1) {
close (job->fd);
job->fd = -1;
}
g_free (job->mime_type);
job->mime_type = NULL;
g_free (job->password);
job->password = NULL;
G_OBJECT_CLASS (ev_job_load_fd_parent_class)->dispose (object);
}
static gboolean
ev_job_load_fd_run (EvJob *job)
{
EvJobLoadFd *job_load_fd = EV_JOB_LOAD_FD (job);
GError *error = NULL;
int fd;
if (job_load_fd->fd == -1) {
g_set_error_literal (&error, G_FILE_ERROR, G_FILE_ERROR_BADF,
"Invalid file descriptor");
goto out;
}
/* We need to dup the FD here since we may need to pass it again
* to ev_document_load_fd() if the document is encrypted,
* and the previous call to it consumes the FD.
*/
fd = ev_dupfd (job_load_fd->fd, &error);
if (fd == -1)
goto out;
ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
ev_document_fc_mutex_lock ();
/* This job may already have a document even if the job didn't complete
because, e.g., a password is required - if so, just reload_fd rather than
creating a new instance */
if (job->document) {
if (job_load_fd->password) {
ev_document_security_set_password (EV_DOCUMENT_SECURITY (job->document),
job_load_fd->password);
}
job->failed = FALSE;
job->finished = FALSE;
g_clear_error (&job->error);
ev_document_load_fd (job->document,
fd,
job_load_fd->flags,
job->cancellable,
&error);
fd = -1; /* consumed */
} else {
job->document = ev_document_factory_get_document_for_fd (fd,
job_load_fd->mime_type,
job_load_fd->flags,
job->cancellable,
&error);
fd = -1; /* consumed */
}
ev_document_fc_mutex_unlock ();
out:
if (error) {
ev_job_failed_from_error (job, error);
g_error_free (error);
} else {
ev_job_succeeded (job);
}
return FALSE;
}
static void
ev_job_load_fd_class_init (EvJobLoadFdClass *class)
{
GObjectClass *oclass = G_OBJECT_CLASS (class);
EvJobClass *job_class = EV_JOB_CLASS (class);
oclass->dispose = ev_job_load_fd_dispose;
job_class->run = ev_job_load_fd_run;
}
/**
* ev_job_load_fd_new:
* @fd: (transfer none):
* @mime_type:
* @flags:
* @error: (nullable): a location to store a #GError, or %NULL
*
* Creates a new #EvJobLoadFd for @fd. If duplicating @fd fails,
* returns %NULL with @error filled in.
*
* Returns: (tranfer full): the new #EvJobLoadFd, or %NULL
*
* Since: 3.30
*/
EvJob *
ev_job_load_fd_new (int fd,
const char *mime_type,
EvDocumentLoadFlags flags,
GError **error)
{
EvJobLoadFd *job;
job = g_object_new (EV_TYPE_JOB_LOAD_FD, NULL);
if (!ev_job_load_fd_set_fd (job, fd, error)) {
g_object_unref (job);
return NULL;
}
ev_job_load_fd_set_mime_type (job, mime_type);
ev_job_load_fd_set_load_flags (job, flags);
return EV_JOB (job);
}
/**
* ev_job_load_new_take:
* @fd: (transfer full):
* @mime_type:
* @flags:
*
* Creates a new #EvJobLoadFd for @fd.
* Note that the job takes ownership of @fd; you must not do anything
* with it afterwards.
*
* Returns: (tranfer full): the new #EvJobLoadFd
*
* Since: 3.30
*/
EvJob *
ev_job_load_fd_new_take (int fd,
const char *mime_type,
EvDocumentLoadFlags flags)
{
EvJobLoadFd *job;
job = g_object_new (EV_TYPE_JOB_LOAD_FD, NULL);
ev_job_load_fd_take_fd (job, fd);
ev_job_load_fd_set_mime_type (job, mime_type);
ev_job_load_fd_set_load_flags (job, flags);
return EV_JOB (job);
}
/**
* ev_job_load_fd_set_fd:
* @job:
* @fd: (transfer none):
* @error: (nullable): a location to store a #GError, or %NULL
*
* Sets @fd as the file descriptor in @job. If duplicating @fd fails,
* returns %FALSE with @error filled in.
*
* Returns: %TRUE if the file descriptor could be set
*
* Since: 3.30
*/
gboolean
ev_job_load_fd_set_fd (EvJobLoadFd *job,
int fd,
GError **error)
{
g_return_val_if_fail (EV_IS_JOB_LOAD_FD (job), FALSE);
g_return_val_if_fail (fd != -1, FALSE);
job->fd = ev_dupfd (fd, error);
return job->fd != -1;
}
/**
* ev_job_load_fd_set_fd:
* @job:
* @fd: (transfer full):
*
* Sets @fd as the file descriptor in @job.
* Note that @job takes ownership of @fd; you must not do anything
* with it afterwards.
*
* Since: 3.30
*/
void
ev_job_load_fd_take_fd (EvJobLoadFd *job,
int fd)
{
g_return_if_fail (EV_IS_JOB_LOAD_FD (job));
g_return_if_fail (fd != -1);
job->fd = fd;
}
void
ev_job_load_fd_set_mime_type (EvJobLoadFd *job,
const char *mime_type)
{
g_return_if_fail (EV_IS_JOB_LOAD_FD (job));
g_return_if_fail (mime_type != NULL);
g_free (job->mime_type);
job->mime_type = g_strdup (mime_type);
}
void
ev_job_load_fd_set_load_flags (EvJobLoadFd *job,
EvDocumentLoadFlags flags)
{
g_return_if_fail (EV_IS_JOB_LOAD_FD (job));
job->flags = flags;
}
void
ev_job_load_fd_set_password (EvJobLoadFd *job,
const char *password)
{
char *old_password;
ev_debug_message (DEBUG_JOBS, NULL);
g_return_if_fail (EV_IS_JOB_LOAD_FD (job));
old_password = job->password;
job->password = g_strdup (password);
g_free (old_password);
}
/* EvJobSave */
static void
ev_job_save_init (EvJobSave *job)
......
......@@ -66,6 +66,9 @@ typedef struct _EvJobLoadStreamClass EvJobLoadStreamClass;
typedef struct _EvJobLoadGFile EvJobLoadGFile;
typedef struct _EvJobLoadGFileClass EvJobLoadGFileClass;
typedef struct _EvJobLoadFd EvJobLoadFd;
typedef struct _EvJobLoadFdClass EvJobLoadFdClass;
typedef struct _EvJobSave EvJobSave;
typedef struct _EvJobSaveClass EvJobSaveClass;
......@@ -159,6 +162,13 @@ typedef struct _EvJobPrintClass EvJobPrintClass;
#define EV_IS_JOB_LOAD_GFILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_JOB_LOAD_GFILE))
#define EV_JOB_LOAD_GFILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_JOB_LOAD_GFILE, EvJobLoadGFileClass))
#define EV_TYPE_JOB_LOAD_FD (ev_job_load_fd_get_type())
#define EV_JOB_LOAD_FD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_JOB_LOAD_FD, EvJobLoadFd))
#define EV_IS_JOB_LOAD_FD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_JOB_LOAD_FD))
#define EV_JOB_LOAD_FD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_JOB_LOAD_FD, EvJobLoadFdClass))
#define EV_IS_JOB_LOAD_FD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_JOB_LOAD_FD))
#define EV_JOB_LOAD_FD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_JOB_LOAD_FD, EvJobLoadFdClass))
#define EV_TYPE_JOB_SAVE (ev_job_save_get_type())
#define EV_JOB_SAVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_JOB_SAVE, EvJobSave))
#define EV_IS_JOB_SAVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_JOB_SAVE))
......@@ -392,6 +402,7 @@ struct _EvJobLoadStream
{
EvJob parent;
char *mime_type;
char *password;
GInputStream *stream;
EvDocumentLoadFlags flags;
......@@ -416,6 +427,21 @@ struct _EvJobLoadGFileClass
EvJobClass parent_class;
};
struct _EvJobLoadFd
{
EvJob parent;
char *mime_type;
char *password;
int fd;
EvDocumentLoadFlags flags;
};
struct _EvJobLoadFdClass
{
EvJobClass parent_class;
};
struct _EvJobSave
{
EvJob parent;
......@@ -573,6 +599,8 @@ EvJob *ev_job_load_stream_new (GInputStream *stream,
EvDocumentLoadFlags flags);
void ev_job_load_stream_set_stream (EvJobLoadStream *job,
GInputStream *stream);
void ev_job_load_stream_set_mime_type (EvJobLoadStream *job,
const char *mime_type);
void ev_job_load_stream_set_load_flags (EvJobLoadStream *job,
EvDocumentLoadFlags flags);
void ev_job_load_stream_set_password (EvJobLoadStream *job,
......@@ -589,6 +617,28 @@ void ev_job_load_gfile_set_load_flags (EvJobLoadGFile *job,
void ev_job_load_gfile_set_password (EvJobLoadGFile *job,
const gchar *password);
/* EvJobLoadFd */
GType ev_job_load_fd_get_type (void) G_GNUC_CONST;
EvJob *ev_job_load_fd_new (int fd,
const char *mime_type,
EvDocumentLoadFlags flags,
GError **error);
EvJob *ev_job_load_fd_new_take (int fd,
const char *mime_type,
EvDocumentLoadFlags flags);
gboolean ev_job_load_fd_set_fd (EvJobLoadFd *job,
int fd,
GError **error);
void ev_job_load_fd_take_fd (EvJobLoadFd *job,
int fd);
void ev_job_load_fd_set_mime_type (EvJobLoadFd *job,
const char *mime_type);
void ev_job_load_fd_set_load_flags (EvJobLoadFd *job,
EvDocumentLoadFlags flags);
void ev_job_load_fd_set_password (EvJobLoadFd *job,
const gchar *password);
/* EvJobSave */
GType ev_job_save_get_type (void) G_GNUC_CONST;
EvJob *ev_job_save_new (EvDocument *document,
......
......@@ -21,6 +21,8 @@
#include <config.h>
#include <fcntl.h>
#if GTKUNIXPRINT_ENABLED
#include <gtk/gtkunixprint.h>
#endif
......@@ -34,6 +36,7 @@
struct _EvPreviewerWindow {
GtkApplicationWindow base_instance;
EvJob *job;
EvDocumentModel *model;
EvDocument *document;
......@@ -48,6 +51,7 @@ struct _EvPreviewerWindow {
#endif
gchar *print_job_title;
gchar *source_file;
int source_fd;
};
struct _EvPreviewerWindowClass {
......@@ -56,7 +60,7 @@ struct _EvPreviewerWindowClass {
enum {
PROP_0,
PROP_MODEL
PROP_JOB
};
#define MIN_SCALE 0.05409
......@@ -73,7 +77,6 @@ get_screen_dpi (EvPreviewerWindow *window)
return ev_document_misc_get_screen_dpi (screen);
}
#if GTKUNIXPRINT_ENABLED
static void
ev_previewer_window_error_dialog_run (EvPreviewerWindow *window,
GError *error)
......@@ -91,7 +94,6 @@ ev_previewer_window_error_dialog_run (EvPreviewerWindow *window,
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}
#endif
static void
ev_previewer_window_close (GSimpleAction *action,
......@@ -195,15 +197,28 @@ static void
ev_previewer_window_do_print (EvPreviewerWindow *window)
{
GtkPrintJob *job;
gboolean rv = FALSE;
GError *error = NULL;
job = gtk_print_job_new (window->print_job_title ?
window->print_job_title :
(window->source_file ? window->source_file : _("Evince")),
window->source_file,
window->printer,
window->print_settings,
window->print_page_setup);
if (gtk_print_job_set_source_file (job, window->source_file, &error)) {
#if GTK_CHECK_VERSION (3, 22, 0)
if (window->source_fd != -1)
rv = gtk_print_job_set_source_fd (job, window->source_fd, &error);
else
#endif
if (window->source_file != NULL)
rv = gtk_print_job_set_source_file (job, window->source_file, &error);
else
g_set_error_literal (&error, GTK_PRINT_ERROR, GTK_PRINT_ERROR_GENERAL,
"Neither file nor FD to print.");
if (rv) {
gtk_print_job_send (job,
(GtkPrintJobCompleteFunc)ev_previewer_window_print_finished,
window, NULL);
......@@ -322,15 +337,26 @@ view_sizing_mode_changed (EvDocumentModel *model,
}
static void
ev_previewer_window_set_document (EvPreviewerWindow *window,
GParamSpec *pspec,
EvDocumentModel *model)
load_job_finished_cb (EvJob *job,
EvPreviewerWindow *window)
{
EvDocument *document = ev_document_model_get_document (model);
g_assert (job == window->job);
if (ev_job_is_failed (job)) {
ev_previewer_window_error_dialog_run (window, job->error);
g_object_unref (window->job);
window->job = NULL;
return;
}
window->document = g_object_ref (job->document);
window->document = g_object_ref (document);
g_object_unref (window->job);
window->job = NULL;
g_signal_connect (model, "notify::sizing-mode",
ev_document_model_set_document (window->model, window->document);
g_signal_connect (window->model, "notify::sizing-mode",
G_CALLBACK (view_sizing_mode_changed),
window);
}
......@@ -340,6 +366,11 @@ ev_previewer_window_dispose (GObject *object)
{
EvPreviewerWindow *window = EV_PREVIEWER_WINDOW (object);
if (window->job) {
g_object_unref (window->job);
window->job = NULL;
}
if (window->model) {
g_object_unref (window->model);
window->model = NULL;
......@@ -376,13 +407,18 @@ ev_previewer_window_dispose (GObject *object)
g_free (window->source_file);
window->source_file = NULL;
}
if (window->source_fd != -1) {
close (window->source_fd);
window->source_fd = -1;
}
G_OBJECT_CLASS (ev_previewer_window_parent_class)->dispose (object);
}
static void
ev_previewer_window_init (EvPreviewerWindow *window)
{
window->source_fd = -1;
gtk_window_set_default_size (GTK_WINDOW (window), 600, 600);
g_action_map_add_action_entries (G_ACTION_MAP (window),
......@@ -390,23 +426,6 @@ ev_previewer_window_init (EvPreviewerWindow *window)
window);
}
static void
ev_previewer_window_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EvPreviewerWindow *window = EV_PREVIEWER_WINDOW (object);
switch (prop_id) {
case PROP_MODEL:
window->model = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static gboolean
_gtk_css_provider_load_from_resource (GtkCssProvider *provider,
const char *resource_path,
......@@ -428,31 +447,24 @@ _gtk_css_provider_load_from_resource (GtkCssProvider *provider,
return retval;
}
static GObject *
ev_previewer_window_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_params)
static void
ev_previewer_window_constructed (GObject *object)
{
GObject *object;
EvPreviewerWindow *window;
EvPreviewerWindow *window = EV_PREVIEWER_WINDOW (object);
GtkWidget *vbox;
GtkWidget *swindow;
GError *error = NULL;
gdouble dpi;
GtkCssProvider *css_provider;
object = G_OBJECT_CLASS (ev_previewer_window_parent_class)->constructor (type,
n_construct_properties,
construct_params);
window = EV_PREVIEWER_WINDOW (object);
object = G_OBJECT_CLASS (ev_previewer_window_parent_class)->constructed (object);
window->model = ev_document_model_new ();
dpi = get_screen_dpi (window);
ev_document_model_set_min_scale (window->model, MIN_SCALE * dpi / 72.0);
ev_document_model_set_max_scale (window->model, MAX_SCALE * dpi / 72.0);
ev_document_model_set_sizing_mode (window->model, EV_SIZING_AUTOMATIC);
g_signal_connect_swapped (window->model, "notify::document",
G_CALLBACK (ev_previewer_window_set_document),
window);
css_provider = gtk_css_provider_new ();
_gtk_css_provider_load_from_resource (css_provider,
......@@ -498,8 +510,6 @@ ev_previewer_window_constructor (GType type,
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show (vbox);
return object;
}
......@@ -508,95 +518,160 @@ ev_previewer_window_class_init (EvPreviewerWindowClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->constructor = ev_previewer_window_constructor;
gobject_class->set_property = ev_previewer_window_set_property;
gobject_class->constructed = ev_previewer_window_constructed;
gobject_class->dispose = ev_previewer_window_dispose;
g_object_class_install_property (gobject_class,
PROP_MODEL,
g_param_spec_object ("model",
"Model",
"The document model",
EV_TYPE_DOCUMENT_MODEL,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY));
}
/* Public methods */
EvPreviewerWindow *
ev_previewer_window_new (EvDocumentModel *model)
ev_previewer_window_new (void)
{
return g_object_new (EV_TYPE_PREVIEWER_WINDOW,
"application", g_application_get_default (),
"model", model,
NULL);
}
void
ev_previewer_window_set_print_settings (EvPreviewerWindow *window,
const gchar *print_settings)
ev_previewer_window_set_job (EvPreviewerWindow *window,
const gchar *print_settings)
{
g_return_if_fail (EV_IS_PREVIEWER_WINDOW (window));
g_return_if_fail (EV_IS_JOB (job));
g_clear_object (&window->job);
window->job = g_object_ref (job);
g_signal_connect_object (window->job, "finished",
G_CALLBACK (load_job_finished_cb),
window, 0);
ev_job_scheduler_push_job (window->job, EV_JOB_PRIORITY_NONE);
}
static gboolean
ev_previewer_window_set_print_settings_take_file (EvPreviewerWindow *window,
GMappedFile *file,
GError **error)
{
GBytes *bytes;
GKeyFile *key_file;
GtkPrintSettings *psettings;
GtkPageSetup *psetup;
char *job_name;
gboolean rv;
if (window->print_settings)
g_object_unref (window->print_settings);
if (window->print_page_setup)
g_object_unref (window->print_page_setup);
if (window->print_job_title)
g_free (window->print_job_title);
g_free (window->print_job_title);
bytes = g_mapped_file_get_bytes (file);
key_file = g_key_file_new ();
rv = g_key_file_load_from_bytes (key_file, bytes, G_KEY_FILE_NONE, error);
g_bytes_unref (bytes);
g_mapped_file_unref (file);
if (!rv) {
window->print_settings = gtk_print_settings_new ();
window->print_page_setup = gtk_page_setup_new ();
window->print_job_title = g_strdup (_("Evince"));
return FALSE;
}
psettings = gtk_print_settings_new_from_key_file (key_file,
"Print Settings",
NULL);
window->print_settings = psettings ? psettings : gtk_print_settings_new ();
psetup = gtk_page_setup_new_from_key_file (key_file,
"Page Setup",
NULL);
window->print_page_setup = psetup ? psetup : gtk_page_setup_new ();
job_name = g_key_file_get_string (key_file,
"Print Job", "title",
NULL);
if (job_name) {
window->print_job_title = job_name;
gtk_window_set_title (GTK_WINDOW (window), job_name);
} else {
window->print_job_title = g_strdup (_("Evince"));
}
if (print_settings && g_file_test (print_settings, G_FILE_TEST_IS_REGULAR)) {
GKeyFile *key_file;
GError *error = NULL;
key_file = g_key_file_new ();
g_key_file_load_from_file (key_file,
print_settings,
G_KEY_FILE_KEEP_COMMENTS |
G_KEY_FILE_KEEP_TRANSLATIONS,
&error);
if (!error) {
GtkPrintSettings *psettings;
GtkPageSetup *psetup;
gchar *job_name;
psettings = gtk_print_settings_new_from_key_file (key_file,
"Print Settings",
NULL);
window->print_settings = psettings ? psettings : gtk_print_settings_new ();
psetup = gtk_page_setup_new_from_key_file (key_file,
"Page Setup",
NULL);
window->print_page_setup = psetup ? psetup : gtk_page_setup_new ();
job_name = g_key_file_get_string (key_file,
"Print Job", "title",
NULL);
if (job_name) {
window->print_job_title = job_name;
gtk_window_set_title (GTK_WINDOW (window), job_name);
}
} else {
window->print_settings = gtk_print_settings_new ();
window->print_page_setup = gtk_page_setup_new ();
g_error_free (error);
}
g_key_file_free (key_file);
} else {
window->print_settings = gtk_print_settings_new ();
window->print_page_setup = gtk_page_setup_new ();
}
g_key_file_free (key_file);
return TRUE;
}
gboolean
ev_previewer_window_set_print_settings (EvPreviewerWindow *window,
const gchar *print_settings,
GError **error)
{
GMappedFile *file;
g_return_val_if_fail (EV_IS_PREVIEWER_WINDOW (window), FALSE);
g_return_val_if_fail (print_settings != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
file = g_mapped_file_new (print_settings, FALSE, error);
if (file == NULL)
return FALSE;
return ev_previewer_window_set_print_settings_take_file (window, file, error);
}
gboolean
ev_previewer_window_set_print_settings_fd (EvPreviewerWindow *window,
int fd,
GError **error)
{
GMappedFile *file;
g_return_val_if_fail (EV_IS_PREVIEWER_WINDOW (window), FALSE);
g_return_val_if_fail (fd != -1, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
file = g_mapped_file_new_from_fd (fd, FALSE, error);
if (file == NULL)
return FALSE;
return ev_previewer_window_set_print_settings_take_file (window, file, error);
}
void
ev_previewer_window_set_source_file (EvPreviewerWindow *window,
const gchar *source_file)
{
if (window->source_file)
g_free (window->source_file);
g_return_if_fail (EV_IS_PREVIEWER_WINDOW (window));
g_free (window->source_file);
window->source_file = g_strdup (source_file);
}
void
ev_previewer_window_set_source_fd (EvPreviewerWindow *window,
int fd)
{
g_return_if_fail (EV_IS_PREVIEWER_WINDOW (window));
if (window->source_fd != -1)
close (window->source_fd);
window->source_fd = fcntl (fd, F_DUPFD_CLOEXEC, 3);
}
void
ev_previewer_window_take_source_fd (EvPreviewerWindow *window,
int fd /* transfer full */)
{
g_return_if_fail (EV_IS_PREVIEWER_WINDOW (window));
if (window->source_fd != -1)
close (window->source_fd);
window->source_fd = fd;
}
EvDocumentModel *
ev_previewer_window_get_document_model (EvPreviewerWindow *window)
{
......
......@@ -39,14 +39,24 @@ typedef struct _EvPreviewerWindow EvPreviewerWindow;
typedef struct _EvPreviewerWindowClass EvPreviewerWindowClass;
GType ev_previewer_window_get_type (void) G_GNUC_CONST;
EvPreviewerWindow *ev_previewer_window_new (EvDocumentModel *model);
EvPreviewerWindow *ev_previewer_window_new (void);
EvDocumentModel *ev_previewer_window_get_document_model (EvPreviewerWindow *window);
void ev_previewer_window_set_print_settings (EvPreviewerWindow *window,
const gchar *print_settings);
void ev_previewer_window_set_source_file (EvPreviewerWindow *window,
const gchar *source_file);
void ev_previewer_window_set_job (EvPreviewerWindow *window,
EvJob *job);
gboolean ev_previewer_window_set_print_settings (EvPreviewerWindow *window,
const gchar *print_settings,
GError **error);
gboolean ev_previewer_window_set_print_settings_fd (EvPreviewerWindow *window,
int fd,
GError **error);
void ev_previewer_window_set_source_file (EvPreviewerWindow *window,
const gchar *source_file);
void ev_previewer_window_set_source_fd (EvPreviewerWindow *window,
int fd);
void ev_previewer_window_take_source_fd (EvPreviewerWindow *window,
int fd);
G_END_DECLS
......
......@@ -2,7 +2,7 @@
* this file is part of evince, a gnome document viewer
*
* Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
* Copyright © 2012 Christian Persch
* Copyright © 2012, 2018 Christian Persch
*
* Evince is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
......@@ -21,6 +21,12 @@
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <evince-document.h>
......@@ -38,12 +44,24 @@
#endif
static gboolean unlink_temp_file = FALSE;
static gchar *print_settings = NULL;
static int input_fd = -1;
static char *input_file = NULL;
static char *input_mime_type = NULL;
static int print_settings_fd = -1;
static gchar *print_settings_file = NULL;
static EvPreviewerWindow *window = NULL;
static const GOptionEntry goption_options[] = {
{ "unlink-tempfile", 'u', 0, G_OPTION_ARG_NONE, &unlink_temp_file, N_("Delete the temporary file"), NULL },
{ "print-settings", 'p', 0, G_OPTION_ARG_FILENAME, &print_settings, N_("File specifying print settings"), N_("FILE") },
{ "unlink-tempfile", 'u', 0, G_OPTION_ARG_NONE, &unlink_temp_file,
N_("Delete the temporary file"), NULL },
{ "print-settings", 'p', 0, G_OPTION_ARG_FILENAME, &print_settings_file,
N_("File specifying print settings"), N_("FILE") },
{ "fd", 0, 0, G_OPTION_ARG_INT, &input_fd,
N_("File descriptor of input file"), N_("FD") },
{ "mime-type", 0, 0, G_OPTION_ARG_STRING, &input_mime_type,
N_("MIME type of input file"), N_("TYPE") },
{ "print-settings-fd", 0, 0, G_OPTION_ARG_INT, &print_settings_fd,
N_("File descriptor of print settings file"), N_("FD") },
{ NULL }
};
......@@ -63,35 +81,6 @@ ev_previewer_unlink_tempfile (const gchar *filename)
g_object_unref (tempdir);
}
static void
ev_previewer_load_job_finished (EvJob *job,
EvDocumentModel *model)
{
if (ev_job_is_failed (job)) {
g_object_unref (job);
return;
}
ev_document_model_set_document (model, job->document);
g_object_unref (job);
}
static void
ev_previewer_load_document (GFile *file,
EvDocumentModel *model)
{
EvJob *job;
gchar *uri;
uri = g_file_get_uri (file);
job = ev_job_load_new (uri);
g_signal_connect (job, "finished",
G_CALLBACK (ev_previewer_load_job_finished),
model);
ev_job_scheduler_push_job (job, EV_JOB_PRIORITY_NONE);
g_free (uri);
}
static void
activate_cb (GApplication *application,
gpointer user_data)
......@@ -102,35 +91,140 @@ activate_cb (GApplication *application,
}
static void
open_cb (GApplication *application,
GFile **files,
gint n_files,
const gchar *hint,
gpointer user_data)
startup_cb (GApplication *application,
gpointer data)
{
EvDocumentModel *model;
GFile *file;
char *path;
EvJob *job;
GError *ps_error = NULL;
gboolean ps_ok = TRUE;
g_assert (input_fd != -1 || input_file != NULL);
if (n_files != 1) {
g_application_quit (application);
return;
window = ev_previewer_window_new ();
if (print_settings_fd != -1) {
ps_ok = ev_previewer_window_set_print_settings_fd (EV_PREVIEWER_WINDOW (window), print_settings_fd, &ps_error);
close (print_settings_fd);
print_settings_fd = -1;
} else if (print_settings_file != NULL) {
ps_ok = ev_previewer_window_set_print_settings (EV_PREVIEWER_WINDOW (window), print_settings_file, &ps_error);
g_free (print_settings_file);
print_settings_file = NULL;
}
if (!ps_ok) {
g_printerr ("Failed to load print settings: %s\n", ps_error->message);
g_error_free (ps_error);
}
file = files[0];
if (input_fd != -1) {
ev_previewer_window_set_source_fd (EV_PREVIEWER_WINDOW (window), input_fd);
job = ev_job_load_fd_new_take (input_fd, input_mime_type,
EV_DOCUMENT_LOAD_FLAG_NO_CACHE);
input_fd = -1;
} else {
GFile *file;
char *uri;
char *path
file = g_file_new_for_commandline_arg (input_file);
uri = g_file_get_uri (file);
path = g_file_get_path (file);
ev_previewer_window_set_source_file (EV_PREVIEWER_WINDOW (window), path);
job = ev_job_load_new (uri);
g_free (uri);
g_free (path);
g_object_unref (file);
g_free (input_file);
input_file = NULL;
}
model = ev_document_model_new ();
ev_previewer_load_document (file, model);
ev_previewer_window_set_job (window, job);
g_object_unref (job);
window = ev_previewer_window_new (model);
g_object_unref (model);
/* Window will be presented by 'activate' signal */
}
ev_previewer_window_set_print_settings (EV_PREVIEWER_WINDOW (window), print_settings);
path = g_file_get_path (file);
ev_previewer_window_set_source_file (EV_PREVIEWER_WINDOW (window), path);
g_free (path);
static gboolean
check_arguments (int argc,
char** argv,
GError **error)
{
if (input_fd != -1) {
struct stat statbuf;
int flags;
if (fstat (input_fd, &statbuf) == -1 ||
(flags = fcntl (input_fd, F_GETFL, &flags)) == -1) {
int errsv = errno;
g_set_error_literal (error, G_FILE_ERROR,
g_file_error_from_errno(errsv),
g_strerror(errsv));
return FALSE;
}
if (!S_ISREG (statbuf.st_mode)) {
g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_BADF,
"Not a regular file.");
return FALSE;
}
switch (flags & O_ACCMODE) {
case O_RDONLY:
case O_RDWR:
break;
case O_WRONLY:
default:
g_set_error_literal(error, G_FILE_ERROR, G_FILE_ERROR_BADF,
"Not a readable file descriptor.");
return FALSE;
}
if (argc > 1) {
g_set_error_literal (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
"Too many arguments");
return FALSE;
}
if (input_mime_type == NULL) {
g_set_error_literal (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
"Must specify --mime-type");
return FALSE;
}
if (unlink_temp_file) {
g_set_error_literal (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
"Must not specify --unlink-tempfile");
return FALSE;
}
} else {
char *path;
if (argc != 2) {
g_set_error_literal (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
"Need exactly one argument");
return FALSE;
}
if (input_mime_type != NULL) {
g_set_error_literal (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
"Must not specify --mime-type");
return FALSE;
}
path = g_filename_from_uri (argv[1], NULL, NULL);
if (!g_file_test (argv[1], G_FILE_TEST_IS_REGULAR) && !g_file_test (path, G_FILE_TEST_IS_REGULAR)) {
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT,
"File \"%s\" does not exist or is not a regular file\n", argv[1]);
g_free (path);
return FALSE;
}
g_free (path);
input_file = g_strdup (argv[1]);
}
gtk_window_present (GTK_WINDOW (window));
return TRUE;
}
gint
......@@ -139,7 +233,6 @@ main (gint argc, gchar **argv)
GtkApplication *application;
GOptionContext *context;
GError *error = NULL;
gchar *path;
int status = 1;
const gchar *action_accels[] = {
......@@ -185,13 +278,16 @@ main (gint argc, gchar **argv)
textdomain (GETTEXT_PACKAGE);
#endif
g_set_prgname ("evince-previewer");
context = g_option_context_new (_("GNOME Document Previewer"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
g_option_context_add_main_entries (context, goption_options, GETTEXT_PACKAGE);
g_option_context_add_group (context, gtk_get_option_group (TRUE));
if (!g_option_context_parse (context, &argc, &argv, &error)) {
if (!g_option_context_parse (context, &argc, &argv, &error) ||
!check_arguments (argc, argv, &error)) {
g_printerr ("Error parsing command line arguments: %s\n", error->message);
g_error_free (error);
g_option_context_free (context);
......@@ -199,21 +295,6 @@ main (gint argc, gchar **argv)
}
g_option_context_free (context);
if (argc < 2) {
g_printerr ("File argument is required\n");
return 1;
} else if (argc > 2) {
g_printerr ("Too many files\n");
return 1;
}
path = g_filename_from_uri (argv[1], NULL, NULL);
if (!g_file_test (argv[1], G_FILE_TEST_IS_REGULAR) && !g_file_test (path, G_FILE_TEST_IS_REGULAR)) {
g_printerr ("Filename \"%s\" does not exist or is not a regular file\n", argv[1]);
return 1;
}
g_free (path);
if (!ev_init ())
return 1;
......@@ -222,21 +303,19 @@ main (gint argc, gchar **argv)
g_set_application_name (_("GNOME Document Previewer"));
gtk_window_set_default_icon_name ("org.gnome.Evince");
application = gtk_application_new (NULL,
G_APPLICATION_NON_UNIQUE |
G_APPLICATION_HANDLES_OPEN);
application = gtk_application_new (NULL, G_APPLICATION_NON_UNIQUE);
g_signal_connect (application, "startup", G_CALLBACK (startup_cb), NULL);
g_signal_connect (application, "activate", G_CALLBACK (activate_cb), NULL);
g_signal_connect (application, "open", G_CALLBACK (open_cb), NULL);
for (it = action_accels; it[0]; it += g_strv_length ((gchar **)it) + 1)
gtk_application_set_accels_for_action (GTK_APPLICATION (application), it[0], &it[1]);
status = g_application_run (G_APPLICATION (application), argc, argv);
status = g_application_run (G_APPLICATION (application), 0, NULL);
if (unlink_temp_file)
ev_previewer_unlink_tempfile (argv[1]);
if (print_settings)
ev_previewer_unlink_tempfile (print_settings);