diff --git a/CMakeLists.txt b/CMakeLists.txt
index e1be78d1..a6933f23 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,3 +15,4 @@ add_subdirectory(src)
add_subdirectory(icons)
add_subdirectory(man)
add_subdirectory(rc)
+add_subdirectory(po)
diff --git a/cmake/Vala_CMake b/cmake/Vala_CMake
index 285255b4..37e01c1a 160000
--- a/cmake/Vala_CMake
+++ b/cmake/Vala_CMake
@@ -1 +1 @@
-Subproject commit 285255b42ad8a88993d8fe40ebb209cbe87ec4b8
+Subproject commit 37e01c1a2ace2a456c20efea44b253027ae914d3
diff --git a/icons/CMakeLists.txt b/icons/CMakeLists.txt
index f901b544..deba925e 100644
--- a/icons/CMakeLists.txt
+++ b/icons/CMakeLists.txt
@@ -6,3 +6,8 @@ DESTINATION
share/pixmaps/pdfpc
)
+install(FILES
+ pdfpc.svg
+DESTINATION
+ share/pixmaps
+)
diff --git a/icons/pdfpc.svg b/icons/pdfpc.svg
new file mode 100644
index 00000000..3b25da90
--- /dev/null
+++ b/icons/pdfpc.svg
@@ -0,0 +1,463 @@
+
+
+
+
diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt
new file mode 100644
index 00000000..19e0fb2c
--- /dev/null
+++ b/po/CMakeLists.txt
@@ -0,0 +1,21 @@
+file(GLOB list_po RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.po)
+
+foreach(file_po ${list_po})
+ string(REPLACE ".po" ".mo" file_mo ${file_po})
+ add_custom_target(${file_mo} ALL
+ DEPENDS ${file_po}
+ COMMAND msgfmt ${file_po} -o ${file_mo}
+ )
+endforeach()
+
+foreach(file_po ${list_po})
+ string(REPLACE ".po" ".mo" file_mo ${file_po})
+ string(REPLACE ".mo" "" file_lang ${file_mo})
+ install(FILES
+ ${file_mo}
+ DESTINATION
+ share/locale/${file_lang}/LC_MESSAGES
+ RENAME pdfpc.mo
+ )
+endforeach()
+
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 00000000..0b1f4832
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,5 @@
+src/pdfpc.vala
+src/classes/timer_label.vala
+[type: gettext/glade]src/ui/about.ui
+[type: gettext/glade]src/ui/main.ui
+[type: gettext/glade]src/ui/settings.ui
diff --git a/po/es.po b/po/es.po
new file mode 100644
index 00000000..3336fd6c
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,85 @@
+# Copyright (C) 2012
+# This file is distributed under the same license as the pdf_presenter_console package.
+# FULL NAME , 2012.
+# Sergio Costas , 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: 2.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-07-15 13:54+0200\n"
+"PO-Revision-Date: 2012-07-15 13:54+0200\n"
+"Last-Translator: Sergio Costas \n"
+"Language-Team: Español; Castellano \n"
+"Language: spanish\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bits\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+
+#: ../src/pdfpc.vala:427
+#, c-format
+msgid "Invalid parameter in config file %s (line %d)\n"
+msgstr "Parámetro no válido en el fichero de configuración %s (línea %d)\n"
+
+#: ../src/pdfpc.vala:546
+msgid "All"
+msgstr "Todos"
+
+#: ../src/classes/timer_label.vala:317 ../src/classes/timer_label.vala:323
+msgid "Until %H:%M"
+msgstr "Hasta las %H:%M"
+
+#: ../src/ui/about.ui.h:1
+msgid ""
+"2009-2011 Jakob Westhoff\n"
+"2012 David Vilar Torres"
+msgstr ""
+"2009-2011 Jakob Westhoff\n"
+"2012 David Vilar Torres"
+
+#: ../src/ui/main.ui.h:1
+msgid "PDF Presentation Console"
+msgstr "PDF Presentation Console"
+
+#: ../src/ui/main.ui.h:2
+msgid "Presentation file: "
+msgstr "Presentación:"
+
+#: ../src/ui/main.ui.h:3
+msgid "Alert time (in minutes):"
+msgstr "Instante de alerta (en minutos):"
+
+#: ../src/ui/main.ui.h:4
+msgid "Duration (in minutes): "
+msgstr "Duración (en minutos):"
+
+#: ../src/ui/main.ui.h:5
+msgid "End time:"
+msgstr "Hora de fin:"
+
+#: ../src/ui/main.ui.h:6
+msgid ":"
+msgstr ":"
+
+#: ../src/ui/main.ui.h:7
+msgid "Add additional slide in black at the end"
+msgstr "Añadir al final una diapositiva en negro"
+
+#: ../src/ui/settings.ui.h:1
+msgid "Settings"
+msgstr "Preferencias"
+
+#: ../src/ui/settings.ui.h:2
+msgid "Switch screens"
+msgstr "Intercambiar pantallas"
+
+#: ../src/ui/settings.ui.h:3
+msgid "Size for current slide (percentage):"
+msgstr "Tamaño para diapositiva actual (porcentaje):"
+
+#~ msgid "PDF PC"
+#~ msgstr "PDF PC"
+
+#~ msgid "Advanced options"
+#~ msgstr "Opciones avanzadas"
diff --git a/po/gl.po b/po/gl.po
new file mode 100644
index 00000000..231c9228
--- /dev/null
+++ b/po/gl.po
@@ -0,0 +1,85 @@
+# Copyright (C) 2012
+# This file is distributed under the same license as the pdf_presenter_console package.
+# FULL NAME , 2012.
+# Sergio Costas , 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: 2.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-07-15 13:54+0200\n"
+"PO-Revision-Date: 2012-07-15 13:54+0200\n"
+"Last-Translator: Sergio Costas \n"
+"Language-Team: Español; Castellano \n"
+"Language: spanish\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bits\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+
+#: ../src/pdfpc.vala:427
+#, c-format
+msgid "Invalid parameter in config file %s (line %d)\n"
+msgstr "Parámetro non válido no arquivo de configurazón %s (liña %d)\n"
+
+#: ../src/pdfpc.vala:546
+msgid "All"
+msgstr "Todos"
+
+#: ../src/classes/timer_label.vala:317 ../src/classes/timer_label.vala:323
+msgid "Until %H:%M"
+msgstr "Ata as %H:%M"
+
+#: ../src/ui/about.ui.h:1
+msgid ""
+"2009-2011 Jakob Westhoff\n"
+"2012 David Vilar Torres"
+msgstr ""
+"2009-2011 Jakob Westhoff\n"
+"2012 David Vilar Torres"
+
+#: ../src/ui/main.ui.h:1
+msgid "PDF Presentation Console"
+msgstr "Pdf Presentation Console"
+
+#: ../src/ui/main.ui.h:2
+msgid "Presentation file: "
+msgstr "Presentación: "
+
+#: ../src/ui/main.ui.h:3
+msgid "Alert time (in minutes):"
+msgstr "Instante de alerta (en minutos):"
+
+#: ../src/ui/main.ui.h:4
+msgid "Duration (in minutes): "
+msgstr "Durazón (en minutos):"
+
+#: ../src/ui/main.ui.h:5
+msgid "End time:"
+msgstr "Hora de fin:"
+
+#: ../src/ui/main.ui.h:6
+msgid ":"
+msgstr ":"
+
+#: ../src/ui/main.ui.h:7
+msgid "Add additional slide in black at the end"
+msgstr "Engadir ó final unha diapositiva en negro"
+
+#: ../src/ui/settings.ui.h:1
+msgid "Settings"
+msgstr "Preferencias"
+
+#: ../src/ui/settings.ui.h:2
+msgid "Switch screens"
+msgstr "Intercambiar pantaias"
+
+#: ../src/ui/settings.ui.h:3
+msgid "Size for current slide (percentage):"
+msgstr "Tamaño para a diapositiva actual (porcentaxe):"
+
+#~ msgid "PDF PC"
+#~ msgstr "PDF PC"
+
+#~ msgid "Advanced options"
+#~ msgstr "Opcións avanzadas"
diff --git a/po/untitled.pot b/po/untitled.pot
new file mode 100644
index 00000000..848297e4
--- /dev/null
+++ b/po/untitled.pot
@@ -0,0 +1,77 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-07-15 13:54+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../src/pdfpc.vala:427
+#, c-format
+msgid "Invalid parameter in config file %s (line %d)\n"
+msgstr ""
+
+#: ../src/pdfpc.vala:546
+msgid "All"
+msgstr ""
+
+#: ../src/classes/timer_label.vala:317 ../src/classes/timer_label.vala:323
+msgid "Until %H:%M"
+msgstr ""
+
+#: ../src/ui/about.ui.h:1
+msgid ""
+"2009-2011 Jakob Westhoff\n"
+"2012 David Vilar Torres"
+msgstr ""
+
+#: ../src/ui/main.ui.h:1
+msgid "PDF Presentation Console"
+msgstr ""
+
+#: ../src/ui/main.ui.h:2
+msgid "Presentation file: "
+msgstr ""
+
+#: ../src/ui/main.ui.h:3
+msgid "Alert time (in minutes):"
+msgstr ""
+
+#: ../src/ui/main.ui.h:4
+msgid "Duration (in minutes): "
+msgstr ""
+
+#: ../src/ui/main.ui.h:5
+msgid "End time:"
+msgstr ""
+
+#: ../src/ui/main.ui.h:6
+msgid ":"
+msgstr ""
+
+#: ../src/ui/main.ui.h:7
+msgid "Add additional slide in black at the end"
+msgstr ""
+
+#: ../src/ui/settings.ui.h:1
+msgid "Settings"
+msgstr ""
+
+#: ../src/ui/settings.ui.h:2
+msgid "Switch screens"
+msgstr ""
+
+#: ../src/ui/settings.ui.h:3
+msgid "Size for current slide (percentage):"
+msgstr ""
diff --git a/po/update_mo_files b/po/update_mo_files
new file mode 100755
index 00000000..b5fb80af
--- /dev/null
+++ b/po/update_mo_files
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+echo es
+msgfmt es.po -o es.mo
+echo gl
+msgfmt gl.po -o gl.mo
diff --git a/po/update_po_files b/po/update_po_files
new file mode 100755
index 00000000..34c8d6a7
--- /dev/null
+++ b/po/update_po_files
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+echo "es (spanish)"
+intltool-update es
+echo "gl (galego)"
+intltool-update gl
diff --git a/rc/CMakeLists.txt b/rc/CMakeLists.txt
index ca4b9926..15ca7556 100644
--- a/rc/CMakeLists.txt
+++ b/rc/CMakeLists.txt
@@ -3,3 +3,9 @@ install(FILES
DESTINATION
${SYSCONFDIR}
)
+
+install(FILES
+ pdfpc.desktop
+DESTINATION
+ share/applications
+)
diff --git a/rc/pdfpc.desktop b/rc/pdfpc.desktop
new file mode 100644
index 00000000..9f89c64c
--- /dev/null
+++ b/rc/pdfpc.desktop
@@ -0,0 +1,17 @@
+[Desktop Entry]
+Encoding=UTF-8
+X-MultipleArgs=false
+Type=Application
+Name=PDFPC
+GenericName=A dual-screen presentation tool
+X-GNOME-FullName=PDFPC, dual-screen presentations
+X-GNOME-FullName[es]=PDFPC, presentaciones a doble pantalla
+X-GNOME-FullName[gl]=PDFPC, presentazóns a dobre pantaia
+Comment=Allows to play PDF files in presentation mode, using dual-screen to show extra information
+Comment[es]=Permite reproducir ficheros PDF en modo presentación, usando doble pantalla para mostrar información extra
+Comment[gl]=Permite reproducir arquivos PDF en modo presentazón, usando dobre pantaia para amosar informazón extra
+TryExec=pdfpc
+Exec=pdfpc %f
+Categories=Graphics;
+Icon=pdfpc
+MimeType=text/pdf;text/x-pdf;application/pdf;application/x-pdf;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3495433a..b39d48c2 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -16,7 +16,9 @@ set(CFLAGS
${GTHREAD_CFLAGS} ${GTHREAD_CFLAGS_OTHER}
${RSVG_CFLAGS} ${RSVG_CFLAGS_OTHER}
)
+
add_definitions(${CFLAGS})
+add_definitions( -D'GETTEXT_PACKAGE="pdfpc"' )
set(LIBS
${GOBJECT_LIBRARIES}
@@ -82,3 +84,12 @@ add_library(pdf_presenter_console_test_library
EXCLUDE_FROM_ALL
${VALA_C} presenter.h presenter.vapi
)
+
+install(FILES
+ ui/main.ui
+ ui/about.ui
+ ui/settings.ui
+DESTINATION
+ share/pdfpc
+)
+
diff --git a/src/classes/configFileReader.vala b/src/classes/configFileReader.vala
index d36d0ccb..bfcc44fc 100644
--- a/src/classes/configFileReader.vala
+++ b/src/classes/configFileReader.vala
@@ -158,6 +158,9 @@ namespace pdfpc {
case "switch-screens":
Options.display_switch = !Options.display_switch;
break;
+ case "no-gui":
+ Options.run_now = !Options.run_now;
+ break;
default:
stderr.printf("Warning: Unknown command line \"%s\"\n", uncommentedLine);
break;
diff --git a/src/classes/options.vala b/src/classes/options.vala
index 3f91367d..3dc81392 100644
--- a/src/classes/options.vala
+++ b/src/classes/options.vala
@@ -26,12 +26,24 @@ namespace pdfpc {
* information and their default values.
*/
public class Options: GLib.Object {
+
+ /**
+ * Commandline option to force launching the presentation without showing the GUI
+ */
+ public static bool run_now = false;
+
/**
* Commandline option specifying if the presenter and presentation screen
* should be switched.
*/
public static bool display_switch = false;
+ /**
+ * Commandline option specifying if the presenter and presentation screen
+ * should not be switched.
+ */
+ public static bool display_unswitch = false;
+
/**
* Commandline option to force using only one screen.
*/
diff --git a/src/classes/presentation_controller.vala b/src/classes/presentation_controller.vala
index f3ddcac2..d18b9f69 100644
--- a/src/classes/presentation_controller.vala
+++ b/src/classes/presentation_controller.vala
@@ -674,6 +674,22 @@ namespace pdfpc {
}
}
+ /**
+ * Callback to be notified when a presentation window has been closed by the user
+ */
+
+ public void closed_window() {
+
+ signal_close_presentation ();
+
+ }
+
+ /**
+ * This signal is emited when the user wants to exit the presentation
+ */
+
+ public signal void signal_close_presentation();
+
/**
* Notify the controllables that they have to update the view
*/
@@ -828,7 +844,7 @@ namespace pdfpc {
protected void quit() {
this.metadata.save_to_disk();
- Gtk.main_quit();
+ signal_close_presentation ();
}
/**
diff --git a/src/classes/timer_label.vala b/src/classes/timer_label.vala
index 7173ae57..4580570a 100644
--- a/src/classes/timer_label.vala
+++ b/src/classes/timer_label.vala
@@ -314,13 +314,13 @@ namespace pdfpc {
public override void stop() {
base.stop();
- this.set_text(this.end_time_object.format("Until %H:%M"));
+ this.set_text(this.end_time_object.format(_("Until %H:%M")));
}
public override void reset() {
base.reset();
if ( this.timeout == 0 )
- this.set_text(this.end_time_object.format("Until %H:%M"));
+ this.set_text(this.end_time_object.format(_("Until %H:%M")));
}
public override bool on_timeout() {
diff --git a/src/classes/window/presentation.vala b/src/classes/window/presentation.vala
index f7772f90..00c5f993 100644
--- a/src/classes/window/presentation.vala
+++ b/src/classes/window/presentation.vala
@@ -48,7 +48,7 @@ namespace pdfpc.Window {
base( screen_num );
this.destroy.connect( (source) => {
- Gtk.main_quit();
+ this.presentation_controller.closed_window();
} );
this.presentation_controller = presentation_controller;
diff --git a/src/classes/window/presenter.vala b/src/classes/window/presenter.vala
index a8079448..4a2e69c0 100644
--- a/src/classes/window/presenter.vala
+++ b/src/classes/window/presenter.vala
@@ -141,7 +141,7 @@ namespace pdfpc.Window {
base( screen_num );
this.destroy.connect( (source) => {
- Gtk.main_quit();
+ this.presentation_controller.closed_window();
} );
this.presentation_controller = presentation_controller;
diff --git a/src/pdfpc.vala b/src/pdfpc.vala
index e2f1b517..7ef3c96f 100644
--- a/src/pdfpc.vala
+++ b/src/pdfpc.vala
@@ -30,6 +30,13 @@ namespace pdfpc {
* initializing the application, like commandline parsing and window creation.
*/
public class Application: GLib.Object {
+
+ /**
+ * This string contains the path where the UI is stored
+ */
+
+ string basepath;
+
/**
* Window which shows the current slide in fullscreen
*
@@ -57,6 +64,23 @@ namespace pdfpc {
*/
private CacheStatus cache_status;
+ /**
+ * Interface elements
+ */
+
+ private Gtk.Window main_w;
+ private Gtk.Button ui_go;
+ private Gtk.Button ui_exit;
+ private Gtk.Button ui_about;
+ private Gtk.Button ui_settings;
+ private Gtk.CheckButton ui_add_black_slide;
+ private Gtk.SpinButton ui_duration;
+ private Gtk.SpinButton ui_alert;
+ private Gtk.FileChooserButton ui_file;
+ private Gtk.SpinButton ui_end_hour;
+ private Gtk.SpinButton ui_end_minute;
+ private Gtk.RadioButton ui_use_duration;
+
/**
* Commandline option parser entry definitions
*/
@@ -68,12 +92,14 @@ namespace pdfpc {
{ "current-size", 'u', 0, OptionArg.INT, ref Options.current_size, "Percentage of the presenter screen to be used for the current slide. (Default 60)", "N" },
{ "overview-min-size", 'o', 0, OptionArg.INT, ref Options.min_overview_width, "Minimum width for the overview miniatures, in pixels. (Default 150)", "N" },
{ "switch-screens", 's', 0, 0, ref Options.display_switch, "Switch the presentation and the presenter screen.", null },
+ { "no-switch-screens", 'n', 0, 0, ref Options.display_unswitch, "Unswitch the presentation and the presenter screen. It disables a previous -s parameter.", null },
{ "disable-cache", 'c', 0, 0, ref Options.disable_caching, "Disable caching and pre-rendering of slides to save memory at the cost of speed.", null },
{ "disable-compression", 'z', 0, 0, ref Options.disable_cache_compression, "Disable the compression of slide images to trade memory consumption for speed. (Avg. factor 30)", null },
{ "black-on-end", 'b', 0, 0, ref Options.black_on_end, "Add an additional black slide at the end of the presentation", null },
{ "single-screen", 'S', 0, 0, ref Options.single_screen, "Force to use only one screen", null },
{ "list-actions", 'L', 0, 0, ref Options.list_actions, "List actions supported in the config file(s)", null},
{ "windowed", 'w', 0, 0, ref Options.windowed, "Run in windowed mode (devel tool)", null},
+ { "run-now", 'r', 0, 0, ref Options.run_now, "Launch the presentation directly, without showing the user interface", null},
{ null }
};
@@ -81,7 +107,7 @@ namespace pdfpc {
* Parse the commandline and apply all found options to there according
* static class members.
*
- * Returns the name of the pdf file to open (or null if not present)
+ * Returns the name of the pdf file to open (or null if not present)
*/
protected string? parse_command_line_options( string[] args ) {
var context = new OptionContext( "" );
@@ -97,10 +123,10 @@ namespace pdfpc {
Posix.exit( 1 );
}
if ( args.length < 2 ) {
- return null;
+ return null;
} else {
- return args[1];
- }
+ return args[1];
+ }
}
/**
@@ -128,36 +154,70 @@ namespace pdfpc {
}
/**
- * Main application function, which instantiates the windows and
- * initializes the Gtk system.
+ * This callback kills the current presentation and shows the main window
*/
- public void run( string[] args ) {
- stdout.printf( "pdfpc v3.1.1\n"
- + "(C) 2012 David Vilar\n"
- + "(C) 2009-2011 Jakob Westhoff\n\n" );
- Gdk.threads_init();
- Gtk.init( ref args );
+ public void kill_presentation() {
- string pdfFilename = this.parse_command_line_options( args );
- if (Options.list_actions) {
- stdout.printf("Config file commands accepted by pdfpc:\n");
- string[] actions = PresentationController.getActionDescriptions();
- for (int i = 0; i < actions.length; i+=2) {
- string tabAlignment = "\t";
- if (actions[i].length < 8)
- tabAlignment += "\t";
- stdout.printf("\t%s%s=> %s\n", actions[i], tabAlignment, actions[i+1]);
- }
- return;
+ this.controller.signal_close_presentation.disconnect(this.kill_presentation);
+ if (this.presentation_window!=null) {
+ this.presentation_window.destroy();
+ this.presentation_window=null;
+ }
+ if (this.presenter_window!=null) {
+ this.presenter_window.destroy();
+ this.presenter_window=null;
+ }
+ // controller and cache status should have a destructor method, to ensure
+ // that all the memory is freed here (I'm not sure, but seems to be a little
+ // memory leak when launching a presentation over and over again)
+ this.controller=null;
+ this.cache_status=null;
+
+ if (Options.run_now) {
+ // If we are running the presentation directly, now we have to exit
+ Gtk.main_quit();
+ } else {
+ // If not, we have to show the main window
+ this.main_w.show();
}
- if (pdfFilename == null) {
- stderr.printf( "Error: No pdf file given\n");
- Posix.exit(1);
+ }
+
+
+ /**
+ * This callback starts a presentation from the main window
+ */
+
+ public void start_presentation() {
+
+ this.main_w.hide();
+
+ // Update internal options acording to the ones in the GUI
+ Options.black_on_end = this.ui_add_black_slide.active;
+ Options.last_minutes = this.ui_alert.get_value_as_int();
+ if (this.ui_use_duration.active) {
+ Options.duration = this.ui_duration.get_value_as_int();
+ Options.end_time = null;
+ } else {
+ Options.duration = 987654321u;
+ Options.end_time = "%d:%d".printf(this.ui_end_hour.get_value_as_int(),this.ui_end_minute.get_value_as_int());
}
- // Initialize the application wide mutex objects
- MutexLocks.init();
+ // And launch the presentation
+ this.do_slide (this.ui_file.get_file().get_uri());
+
+ }
+
+ /**
+ * Main application function, which instantiates the windows and
+ * initializes the Gtk system.
+ */
+
+ public void do_slide( string pdfFilename ) {
+ if (pdfFilename == null) {
+ stderr.printf( "Error: No pdf file given\n");
+ Posix.exit(1);
+ }
stdout.printf( "Initializing rendering...\n" );
@@ -169,10 +229,12 @@ namespace pdfpc {
// crosscutting concerns between the different windows.
this.controller = new PresentationController( metadata, Options.black_on_end );
this.cache_status = new CacheStatus();
+ this.controller.signal_close_presentation.connect(this.kill_presentation);
ConfigFileReader configFileReader = new ConfigFileReader(this.controller);
- configFileReader.readConfig(etc_path + "/pdfpcrc");
- configFileReader.readConfig(Environment.get_home_dir() + "/.pdfpcrc");
+ configFileReader.readConfig(GLib.Path.build_filename(etc_path, "pdfpcrc"));
+ configFileReader.readConfig(GLib.Path.build_filename(Environment.get_home_dir(),".pdfpcrc"));
+ configFileReader.readConfig(GLib.Path.build_filename(Environment.get_home_dir(),".config","pdfpc","pdfpcrc"));
var screen = Gdk.Screen.get_default();
if ( !Options.windowed && !Options.single_screen && screen.get_n_monitors() > 1 ) {
@@ -211,10 +273,348 @@ namespace pdfpc {
this.presenter_window.show_all();
this.presenter_window.update();
}
+ }
+
+ public void refresh_status() {
+
+ var fname = this.ui_file.get_file();
+ if (fname!=null) {
+ var uri = fname.get_uri();
+ if (uri==null) {
+ this.ui_go.sensitive=false;
+ } else {
+ this.ui_go.sensitive=true;
+ }
+ }else {
+ this.ui_go.sensitive=false;
+ }
+
+ if (this.ui_use_duration.active) {
+ this.ui_duration.sensitive=true;
+ this.ui_end_hour.sensitive=false;
+ this.ui_end_minute.sensitive=false;
+ } else {
+ this.ui_duration.sensitive=false;
+ this.ui_end_hour.sensitive=true;
+ this.ui_end_minute.sensitive=true;
+ }
+ }
+
+ public void refresh_file() {
+
+ var fname=this.ui_file.get_file();
+ string pdf_basefname = fname.get_basename();
+ int extension_index = pdf_basefname.last_index_of(".");
+ string pdfpc_basefname = pdf_basefname[0:extension_index] + ".pdfpc";
+ var pdfpc_file = fname.get_parent().get_child(pdfpc_basefname);
+
+ File file;
+ uint8[] raw_datau8;
+
+ try {
+ file = File.new_for_uri(pdfpc_file.get_uri());
+ file.load_contents(null, out raw_datau8, null);
+ GLib.stdout.printf("Found metadata file\n");
+ } catch {
+ GLib.stdout.printf("No metadata file found\n");
+ this.refresh_status ();
+ return;
+ }
+
+ string[] lines = ((string) raw_datau8).split("\n");
+ bool found=false;
+
+ for (int i=0; i < lines.length; ++i) {
+ string l = lines[i].strip();
+ if (found) {
+ GLib.stdout.printf("Found duration in metadata\n");
+ Options.duration = int.parse(l);
+ break;
+ } else {
+ if (l == "[duration]") {
+ found=true;
+ }
+ }
+ }
+
+ if (found) {
+ this.ui_duration.value=Options.duration;
+ this.ui_use_duration.set_active(true);
+ }
+ this.refresh_status ();
+ }
+
+ private int read_configuration() {
+
+ /****************************************************************************************
+ * This function will read the configuration from the file ~/.pdf_presenter.cfg *
+ * If not, it will use that file to get the configuration *
+ * Returns: *
+ * 0: on success *
+ * -1: the config file doesn't exists *
+ * -2: can't read the config file *
+ * +N: parse error at line N in config file *
+ ****************************************************************************************/
+
+ bool failed=false;
+ FileInputStream file_read;
+
+ string home=Environment.get_home_dir();
+ var config_file = File.new_for_path (GLib.Path.build_filename(home,".config","pdfpc","pdfpc.cfg"));
+
+ if (!config_file.query_exists(null)) {
+ return -1;
+ }
+
+ try {
+ file_read=config_file.read(null);
+ } catch {
+ return -2;
+ }
+ var in_stream = new DataInputStream (file_read);
+ string line;
+ int line_counter=0;
+
+ while ((line = in_stream.read_line (null, null)) != null) {
+ line_counter++;
+
+ // ignore comments
+ if (line[0]=='#') {
+ continue;
+ }
+
+ // remove unwanted blank spaces
+ line.strip();
+
+ // ignore empty lines
+ if (line.length==0) {
+ continue;
+ }
+
+ if (line.has_prefix("switch_screens ")) {
+ if (line.substring(15)=="1") {
+ Options.display_switch=true;
+ } else {
+ Options.display_switch=false;
+ }
+ continue;
+ }
+ if (line.has_prefix("duration ")) { // old option. Don't use it any more
+ continue;
+ }
+ if (line.has_prefix("last_minutes ")) {
+ Options.last_minutes=int.parse(line.substring(13).strip());
+ continue;
+ }
+ if (line.has_prefix("current_size ")) {
+ Options.current_size=int.parse(line.substring(13).strip());
+ continue;
+ }
+ failed=true;
+ break;
+ }
+
+ try {
+ in_stream.close(null);
+ } catch {
+ }
+ try {
+ file_read.close(null);
+ } catch {
+ }
+
+ if (failed) {
+ GLib.stderr.printf(_("Invalid parameter in config file %s (line %d)\n"),config_file.get_path(),line_counter);
+ return line_counter;
+ }
+
+ return 0;
+ }
+
+ public int write_configuration() {
+
+ try {
+ FileOutputStream file_write;
+
+ var home=Environment.get_home_dir();
+
+ var cfg_path=GLib.Path.build_filename(home,".config","pdfpc");
+ GLib.DirUtils.create_with_parents(cfg_path,493); // 493 = 755 in octal (for directory permissions)
+ var config_file = File.new_for_path (GLib.Path.build_filename(cfg_path,"pdfpc.cfg"));
+
+ try {
+ file_write=config_file.replace(null,false,0,null);
+ } catch {
+ return -2;
+ }
+
+ var out_stream = new DataOutputStream (file_write);
+
+ if (Options.display_switch) {
+ out_stream.put_string("switch_screens 1\n",null);
+ } else {
+ out_stream.put_string("switch_screens 0\n",null);
+ }
+ out_stream.put_string("last_minutes %u\n".printf(Options.last_minutes));
+ out_stream.put_string("current_size %u\n".printf(Options.current_size));
+
+ } catch (IOError e) {
+ }
+ return 0;
+ }
+
+
+ /**
+ * Main application function, which instantiates the windows and
+ * initializes the Gtk system.
+ */
+ public void run( string[] args ) {
+
+ stdout.printf( "pdfpc v3.2 beta2\n"
+ + "(C) 2012 David Vilar\n"
+ + "(C) 2009-2011 Jakob Westhoff\n\n" );
+
+ Gdk.threads_init();
+ Gtk.init( ref args );
+
+ // First, read the configuration with the last options used (to remember if we
+ // have to switch screens and so on)
+ this.read_configuration ();
+
+ // Now, read the command line options, overwriting the ones set by the
+ // READ_CONFIGURATION function
+ string pdfFilename = this.parse_command_line_options( args );
+ if (Options.list_actions) {
+ stdout.printf("Config file commands accepted by pdfpc:\n");
+ string[] actions = PresentationController.getActionDescriptions();
+ for (int i = 0; i < actions.length; i+=2) {
+ string tabAlignment = "\t";
+ if (actions[i].length < 8)
+ tabAlignment += "\t";
+ stdout.printf("\t%s%s=> %s\n", actions[i], tabAlignment, actions[i+1]);
+ }
+ return;
+ }
+
+ // This option is needed because the previously stored configuration could mandate
+ // to switch the screens, but now the user doesn't want to do it from command line
+ if (Options.display_unswitch) {
+ Options.display_switch=false;
+ }
+
+ // Find where the GUI definition files are (/usr or /usr/local) and set locale
+ var file=File.new_for_path("/usr/share/pdfpc/main.ui");
+ if (file.query_exists()) {
+ this.basepath="/usr/share/pdfpc/";
+ Intl.bindtextdomain( "pdfpc", "/usr/share/locale");
+ } else {
+ this.basepath="/usr/local/share/pdfpc/";
+ Intl.bindtextdomain( "pdfpc", "/usr/local/share/locale");
+ }
+ Intl.textdomain("pdfpc");
+ Intl.bind_textdomain_codeset( "pdfpc", "UTF-8" );
+
+ // Initialize the application wide mutex objects
+ MutexLocks.init();
+
+ var builder = new Builder();
+ builder.add_from_file(GLib.Path.build_filename(this.basepath,"main.ui"));
+ this.main_w = (Gtk.Window)builder.get_object("main_window");
+
+ // Get access to all the important widgets in the GUI
+ this.ui_go = (Gtk.Button)builder.get_object("button_go");
+ this.ui_exit = (Gtk.Button)builder.get_object("button_exit");
+ this.ui_about = (Gtk.Button)builder.get_object("button_about");
+ this.ui_settings = (Gtk.Button)builder.get_object("button_settings");
+ this.ui_add_black_slide = (Gtk.CheckButton)builder.get_object("add_black_slide");
+ this.ui_duration = (Gtk.SpinButton)builder.get_object("duration_time");
+ this.ui_alert = (Gtk.SpinButton)builder.get_object("alert_time");
+ this.ui_file = (Gtk.FileChooserButton)builder.get_object("pdf_file");
+ this.ui_end_hour = (Gtk.SpinButton)builder.get_object("end_hour_time");
+ this.ui_end_minute = (Gtk.SpinButton)builder.get_object("end_minute_time");
+ this.ui_use_duration = (Gtk.RadioButton)builder.get_object("use_duration_time");
+
+ var filter = new FileFilter();
+ filter.set_name("PDF");
+ filter.add_mime_type("text/pdf");
+ filter.add_mime_type("text/x-pdf");
+ filter.add_mime_type("application/pdf");
+ filter.add_mime_type("application/x-pdf");
+ this.ui_file.add_filter(filter);
+
+ var filter2 = new FileFilter();
+ filter2.set_name(_("All"));
+ filter2.add_pattern("*");
+ this.ui_file.add_filter(filter2);
+
+ this.ui_file.file_set.connect(this.refresh_file);
+ this.ui_file.selection_changed.connect(this.refresh_file);
+ this.ui_go.clicked.connect(this.start_presentation);
+ this.ui_use_duration.toggled.connect(this.refresh_status);
+
+ this.main_w.destroy.connect( (source) => {
+ Gtk.main_quit();
+ } );
+ this.ui_exit.clicked.connect( (source) => {
+ Gtk.main_quit();
+ } );
+
+ this.ui_about.clicked.connect( (source) => {
+
+ var builder2 = new Builder();
+ builder2.add_from_file(GLib.Path.build_filename(this.basepath,"about.ui"));
+ var about_w = (Gtk.Dialog)builder2.get_object("aboutdialog");
+
+ about_w.show();
+ about_w.run();
+ about_w.hide();
+ about_w.destroy();
+ } );
+
+ this.ui_settings.clicked.connect( (source) => {
+
+ var builder3 = new Builder();
+ builder3.add_from_file(GLib.Path.build_filename(this.basepath,"settings.ui"));
+ var settings_w = (Gtk.Dialog)builder3.get_object("settings_dialog");
+
+ var ui_sw_scr = (Gtk.CheckButton)builder3.get_object("switch_screens");
+ var ui_size = (Gtk.SpinButton)builder3.get_object("size_slide");
+
+ ui_sw_scr.active=Options.display_switch;
+ ui_size.value=Options.current_size;
+
+ settings_w.show();
+ if (settings_w.run()>0) {
+ Options.display_switch=ui_sw_scr.active;
+ Options.current_size=ui_size.get_value_as_int();
+ this.write_configuration ();
+ }
+ settings_w.hide();
+ settings_w.destroy();
+ } );
+
+
+ Gdk.threads_enter();
+
+ if (pdfFilename!=null) {
+ var fname = File.new_for_path(pdfFilename);
+ this.ui_file.set_file(fname);
+ }
+
+ if (Options.run_now) {
+ // If the user set the -r option, launch the presentation just now
+ this.do_slide (pdfFilename);
+ } else {
+ // Set the GUI options acording to the ones currently active
+ this.ui_add_black_slide.active=Options.black_on_end;
+ this.ui_duration.value=Options.duration;
+ this.ui_alert.value=Options.last_minutes;
+ main_w.show();
+ this.refresh_status();
+ }
// Enter the Glib eventloop
// Everything from this point on is completely signal based
- Gdk.threads_enter();
Gtk.main();
Gdk.threads_leave();
}
diff --git a/src/ui/about.ui b/src/ui/about.ui
new file mode 100644
index 00000000..8e5fdb1d
--- /dev/null
+++ b/src/ui/about.ui
@@ -0,0 +1,39 @@
+
+
+
+
+
+
diff --git a/src/ui/main.ui b/src/ui/main.ui
new file mode 100644
index 00000000..780f4060
--- /dev/null
+++ b/src/ui/main.ui
@@ -0,0 +1,353 @@
+
+
+
+
+
+ 999
+ 5
+ 1
+ 10
+
+
+ 1
+ 999
+ 45
+ 1
+ 10
+
+
+ 23
+ 1
+ 10
+
+
+ 59
+ 1
+ 10
+
+
+ 600
+ 300
+ False
+ PDF Presentation Console
+ center
+
+
+ True
+ False
+ 4
+
+
+ True
+ False
+ 2
+
+
+ True
+ False
+ Presentation file:
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+
+
+ True
+ True
+ 1
+
+
+
+
+ False
+ True
+ 6
+ 0
+
+
+
+
+ True
+ False
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ Alert time (in minutes):
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ 3
+ •
+ True
+ False
+ False
+ True
+ True
+ adjustment_alert
+
+
+ False
+ True
+ 4
+ 1
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ True
+ False
+
+
+ Duration (in minutes):
+ True
+ True
+ False
+ False
+ True
+ True
+
+
+ False
+ False
+ 0
+
+
+
+
+ True
+ True
+ 3
+ •
+ True
+ False
+ False
+ True
+ True
+ adjustment_duration
+
+
+ False
+ True
+ 4
+ 1
+
+
+
+
+ False
+ True
+ 3
+
+
+
+
+ True
+ False
+
+
+ End time:
+ True
+ True
+ False
+ False
+ True
+ use_duration_time
+
+
+ False
+ False
+ 0
+
+
+
+
+ True
+ True
+ •
+ False
+ False
+ True
+ True
+ end_hour
+
+
+ False
+ False
+ 1
+
+
+
+
+ True
+ False
+ :
+
+
+ False
+ False
+ 3
+ 2
+
+
+
+
+ True
+ True
+ •
+ False
+ False
+ True
+ True
+ end_minute
+
+
+ False
+ False
+ 3
+
+
+
+
+ False
+ True
+ 4
+
+
+
+
+ Add additional slide in black at the end
+ True
+ True
+ False
+ False
+ True
+
+
+ False
+ True
+ 5
+
+
+
+
+ True
+ False
+
+
+ True
+ True
+ 6
+
+
+
+
+ True
+ False
+ end
+
+
+ gtk-about
+ True
+ True
+ True
+ False
+ True
+
+
+ False
+ False
+ 0
+ True
+
+
+
+
+ gtk-quit
+ True
+ True
+ True
+ False
+ True
+
+
+ False
+ False
+ 1
+
+
+
+
+ gtk-media-play
+ True
+ True
+ True
+ False
+ True
+
+
+ False
+ False
+ 2
+
+
+
+
+ gtk-preferences
+ True
+ True
+ True
+ False
+ True
+
+
+ False
+ False
+ 3
+ True
+
+
+
+
+ False
+ True
+ 7
+
+
+
+
+
+
diff --git a/src/ui/settings.ui b/src/ui/settings.ui
new file mode 100644
index 00000000..18854cc5
--- /dev/null
+++ b/src/ui/settings.ui
@@ -0,0 +1,129 @@
+
+
+
+
+
+ 10
+ 90
+ 1
+ 10
+
+
+ False
+ 5
+ Settings
+ True
+ center
+ dialog
+
+
+ True
+ False
+ 2
+
+
+ True
+ False
+ end
+
+
+ gtk-cancel
+ True
+ True
+ True
+ False
+ True
+
+
+ False
+ False
+ 0
+
+
+
+
+ gtk-apply
+ True
+ True
+ True
+ False
+ True
+
+
+ False
+ False
+ 1
+
+
+
+
+ False
+ True
+ end
+ 0
+
+
+
+
+ Switch screens
+ True
+ True
+ False
+ False
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ Size for current slide (percentage):
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ •
+ True
+ False
+ False
+ True
+ True
+ adjustment_size_slide
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+
+ button1
+ button2
+
+
+