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 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + False + 5 + dialog + PDF Presenter + 2.1 + 2009-2011 Jakob Westhoff +2012 David Vilar Torres + Jakob Westhoff +David Vilar Torres + + + True + False + 2 + + + True + False + end + + + False + True + end + 0 + + + + + + + + + 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 + + +