diff options
Diffstat (limited to 'src/publishing')
-rw-r--r-- | src/publishing/APIGlue.vala | 6 | ||||
-rw-r--r-- | src/publishing/LoginWelcomePaneWidget.vala | 45 | ||||
-rw-r--r-- | src/publishing/ProgressPaneWidget.vala | 44 | ||||
-rw-r--r-- | src/publishing/Publishing.vala | 7 | ||||
-rw-r--r-- | src/publishing/PublishingPluginHost.vala | 8 | ||||
-rw-r--r-- | src/publishing/PublishingUI.vala | 202 | ||||
-rw-r--r-- | src/publishing/StaticMessagePaneWidget.vala | 62 | ||||
-rw-r--r-- | src/publishing/SuccessPaneWidget.vala | 39 | ||||
-rw-r--r-- | src/publishing/meson.build | 27 |
9 files changed, 269 insertions, 171 deletions
diff --git a/src/publishing/APIGlue.vala b/src/publishing/APIGlue.vala index 23c4e8c..56013a2 100644 --- a/src/publishing/APIGlue.vala +++ b/src/publishing/APIGlue.vala @@ -126,7 +126,11 @@ public class MediaSourcePublishableWrapper : Spit.Publishing.Publishable, GLib.O } public GLib.DateTime get_exposure_date_time() { - return new GLib.DateTime.from_unix_local(wrapped.get_exposure_time()); + return wrapped.get_exposure_time().to_local(); + } + + public uint get_rating() { + return wrapped.get_rating(); } } diff --git a/src/publishing/LoginWelcomePaneWidget.vala b/src/publishing/LoginWelcomePaneWidget.vala new file mode 100644 index 0000000..3e9847b --- /dev/null +++ b/src/publishing/LoginWelcomePaneWidget.vala @@ -0,0 +1,45 @@ +/* Copyright 2016 Software Freedom Conservancy Inc. + * Copyright 2019 Jens Georg <mail@jensge.org> + * + * This software is licensed under the GNU LGPL (version 2.1 or later). + * See the COPYING file in this distribution. + */ + +namespace PublishingUI { + +[GtkTemplate (ui = "/org/gnome/Shotwell/ui/login_welcome_pane_widget.ui")] +public class LoginWelcomePane : Spit.Publishing.DialogPane, Gtk.Box { + [GtkChild] + private unowned Gtk.Button login_button; + [GtkChild] + private unowned Gtk.Label not_logged_in_label; + + public Gtk.Widget get_widget() { + return this; + } + + public Spit.Publishing.DialogPane.GeometryOptions get_preferred_geometry() { + return Spit.Publishing.DialogPane.GeometryOptions.NONE; + } + + public void on_pane_installed() { + } + + public void on_pane_uninstalled() { + } + + public signal void login_requested(); + + public LoginWelcomePane(string service_welcome_message) { + Object(); + + login_button.clicked.connect(on_login_clicked); + not_logged_in_label.set_use_markup(true); + not_logged_in_label.set_markup(service_welcome_message); + } + + private void on_login_clicked() { + login_requested(); + } +} +} // namespace PublishingUI diff --git a/src/publishing/ProgressPaneWidget.vala b/src/publishing/ProgressPaneWidget.vala new file mode 100644 index 0000000..0c89d77 --- /dev/null +++ b/src/publishing/ProgressPaneWidget.vala @@ -0,0 +1,44 @@ +/* Copyright 2016 Software Freedom Conservancy Inc. + * Copyright 2019 Jens Georg <mail@jensge.org> + * + * This software is licensed under the GNU LGPL (version 2.1 or later). + * See the COPYING file in this distribution. + */ + +namespace PublishingUI { + +[GtkTemplate (ui = "/org/gnome/Shotwell/ui/progress_pane_widget.ui")] +public class ProgressPane : Spit.Publishing.DialogPane, Gtk.Box { + [GtkChild] + private unowned Gtk.ProgressBar progress_bar; + + public Gtk.Widget get_widget() { + return this; + } + + public Spit.Publishing.DialogPane.GeometryOptions get_preferred_geometry() { + return Spit.Publishing.DialogPane.GeometryOptions.NONE; + } + + public void on_pane_installed() { + } + + public void on_pane_uninstalled() { + } + + public void set_text(string text) { + progress_bar.set_text(text); + } + + public void set_progress(double progress) { + progress_bar.set_fraction(progress); + } + + public void set_status(string status_text, double progress) { + if (status_text != progress_bar.get_text()) + progress_bar.set_text(status_text); + + set_progress(progress); + } +} +} // namespace PublishingUI diff --git a/src/publishing/Publishing.vala b/src/publishing/Publishing.vala index 455013c..c41e121 100644 --- a/src/publishing/Publishing.vala +++ b/src/publishing/Publishing.vala @@ -8,10 +8,9 @@ namespace Publishing { public void init() throws Error { string[] core_ids = new string[0]; - core_ids += "org.yorba.shotwell.publishing.facebook"; - core_ids += "org.yorba.shotwell.publishing.flickr"; - core_ids += "org.yorba.shotwell.publishing.youtube"; - core_ids += "org.yorba.shotwell.publishing.gnome-photos"; + core_ids += "org.gnome.shotwell.publishing.flickr"; + core_ids += "org.gnome.shotwell.publishing.youtube"; + core_ids += "org.gnome.shotwell.publishing.gnome-photos"; Plugins.register_extension_point(typeof(Spit.Publishing.Service), _("Publishing"), Resources.PUBLISH, core_ids); diff --git a/src/publishing/PublishingPluginHost.vala b/src/publishing/PublishingPluginHost.vala index ca935ab..7804924 100644 --- a/src/publishing/PublishingPluginHost.vala +++ b/src/publishing/PublishingPluginHost.vala @@ -22,7 +22,7 @@ public class ConcretePublishingHost : Plugins.StandardHostInterface, Spit.Publishing.Publisher.MediaType.NONE; public ConcretePublishingHost(Service service, PublishingUI.PublishingDialog dialog, - Publishable[] publishables) { + Publishable[] publishables, Account account) { base(service, "sharing"); this.dialog = dialog; this.publishables = publishables; @@ -30,7 +30,11 @@ public class ConcretePublishingHost : Plugins.StandardHostInterface, foreach (Publishable curr_publishable in publishables) this.media_type |= curr_publishable.get_media_type(); - this.active_publisher = service.create_publisher(this); + this.active_publisher = service.create_publisher_with_account(this, account); + } + + public string get_current_profile_id() { + return Shotwell.ProfileManager.get_instance().id(); } private void on_login_clicked() { diff --git a/src/publishing/PublishingUI.vala b/src/publishing/PublishingUI.vala index d3d4a69..de642a4 100644 --- a/src/publishing/PublishingUI.vala +++ b/src/publishing/PublishingUI.vala @@ -6,134 +6,6 @@ namespace PublishingUI { -public class ConcreteDialogPane : Spit.Publishing.DialogPane, GLib.Object { - protected Gtk.Box pane_widget = null; - protected Gtk.Builder builder = null; - - public ConcreteDialogPane() { - builder = AppWindow.create_builder(); - } - - public Gtk.Widget get_widget() { - return pane_widget; - } - - public Spit.Publishing.DialogPane.GeometryOptions get_preferred_geometry() { - return Spit.Publishing.DialogPane.GeometryOptions.NONE; - } - - public void on_pane_installed() { - } - - public void on_pane_uninstalled() { - } -} - -public class StaticMessagePane : ConcreteDialogPane { - private Gtk.Label msg_label = null; - - public StaticMessagePane(string message_string, bool enable_markup = false) { - base(); - msg_label = builder.get_object("static_msg_label") as Gtk.Label; - pane_widget = builder.get_object("static_msg_pane_widget") as Gtk.Box; - - if (enable_markup) { - msg_label.set_markup(message_string); - msg_label.set_line_wrap(true); - msg_label.set_use_markup(true); - } else { - msg_label.set_label(message_string); - } - } -} - -public class LoginWelcomePane : ConcreteDialogPane { - private Gtk.Button login_button = null; - private Gtk.Label not_logged_in_label = null; - - public signal void login_requested(); - - public LoginWelcomePane(string service_welcome_message) { - base(); - pane_widget = builder.get_object("welcome_pane_widget") as Gtk.Box; - login_button = builder.get_object("login_button") as Gtk.Button; - not_logged_in_label = builder.get_object("not_logged_in_label") as Gtk.Label; - - login_button.clicked.connect(on_login_clicked); - not_logged_in_label.set_use_markup(true); - not_logged_in_label.set_markup(service_welcome_message); - } - - private void on_login_clicked() { - login_requested(); - } -} - -public class ProgressPane : ConcreteDialogPane { - private Gtk.ProgressBar progress_bar = null; - - public ProgressPane() { - base(); - pane_widget = (Gtk.Box) builder.get_object("progress_pane_widget"); - progress_bar = (Gtk.ProgressBar) builder.get_object("publishing_progress_bar"); - } - - public void set_text(string text) { - progress_bar.set_text(text); - } - - public void set_progress(double progress) { - progress_bar.set_fraction(progress); - } - - public void set_status(string status_text, double progress) { - if (status_text != progress_bar.get_text()) - progress_bar.set_text(status_text); - - set_progress(progress); - } -} - -public class SuccessPane : StaticMessagePane { - public SuccessPane(Spit.Publishing.Publisher.MediaType published_media, int num_uploaded = 1) { - string? message_string = null; - - // Here, we check whether more than one item is being uploaded, and if so, display - // an alternate message. - if (published_media == Spit.Publishing.Publisher.MediaType.VIDEO) { - message_string = ngettext ("The selected video was successfully published.", - "The selected videos were successfully published.", - num_uploaded); - } - else if (published_media == Spit.Publishing.Publisher.MediaType.PHOTO) { - message_string = ngettext ("The selected photo was successfully published.", - "The selected photos were successfully published.", - num_uploaded); - } - else if (published_media == (Spit.Publishing.Publisher.MediaType.PHOTO - | Spit.Publishing.Publisher.MediaType.VIDEO)) { - message_string = _("The selected photos/videos were successfully published."); - } - else { - assert_not_reached (); - } - - base(message_string); - } -} - -public class AccountFetchWaitPane : StaticMessagePane { - public AccountFetchWaitPane() { - base(_("Fetching account information…")); - } -} - -public class LoginWaitPane : StaticMessagePane { - public LoginWaitPane() { - base(_("Logging in…")); - } -} - public class PublishingDialog : Gtk.Dialog { private const int LARGE_WINDOW_WIDTH = 860; private const int LARGE_WINDOW_HEIGHT = 688; @@ -205,12 +77,13 @@ public class PublishingDialog : Gtk.Dialog { } set_title(title); - service_selector_box_model = new Gtk.ListStore(2, typeof(Gdk.Pixbuf), typeof(string)); + service_selector_box_model = new Gtk.ListStore(3, typeof(string), typeof(string), + typeof(Spit.Publishing.Account)); service_selector_box = new Gtk.ComboBox.with_model(service_selector_box_model); Gtk.CellRendererPixbuf renderer_pix = new Gtk.CellRendererPixbuf(); service_selector_box.pack_start(renderer_pix,true); - service_selector_box.add_attribute(renderer_pix, "pixbuf", 0); + service_selector_box.add_attribute(renderer_pix, "icon-name", 0); Gtk.CellRendererText renderer_text = new Gtk.CellRendererText(); service_selector_box.pack_start(renderer_text,true); @@ -226,30 +99,26 @@ public class PublishingDialog : Gtk.Dialog { Gtk.TreeIter iter; foreach (Spit.Publishing.Service service in loaded_services) { - service_selector_box_model.append(out iter); - string curr_service_id = service.get_id(); - service.get_info(ref info); + info = service.get_info(); - if (null != info.icons && 0 < info.icons.length) { - // check if the icons object is set -- if set use that icon - service_selector_box_model.set(iter, 0, info.icons[0], 1, - service.get_pluggable_name()); - - // in case the icons object is not set on the next iteration - info.icons[0] = Resources.get_icon(Resources.ICON_GENERIC_PLUGIN); - } else { - // if icons object is null or zero length use a generic icon - service_selector_box_model.set(iter, 0, Resources.get_icon( - Resources.ICON_GENERIC_PLUGIN), 1, service.get_pluggable_name()); - } - - if (last_used_service == null) { - service_selector_box.set_active_iter(iter); - last_used_service = service.get_id(); - } else if (last_used_service == curr_service_id) { - service_selector_box.set_active_iter(iter); + var accounts = service.get_accounts(Shotwell.ProfileManager.get_instance().id()); + + foreach (var account in accounts) { + service_selector_box_model.append(out iter); + + var account_name = account.display_name(); + var display_name = service.get_pluggable_name() + (account_name == "" ? "" : "/" + account_name); + + service_selector_box_model.set(iter, 0, info.icon_name, 1, display_name, 2, account); + + if (last_used_service == null) { + service_selector_box.set_active_iter(iter); + last_used_service = service.get_id(); + } else if (last_used_service == curr_service_id) { + service_selector_box.set_active_iter(iter); + } } } @@ -373,15 +242,17 @@ public class PublishingDialog : Gtk.Dialog { return filtered_services; } - // Because of this bug: http://trac.yorba.org/ticket/3623, we use some extreme measures. The - // bug occurs because, in some cases, when publishing is started asynchronous network - // transactions are performed. The mechanism inside libsoup that we use to perform asynchronous - // network transactions isn't based on threads but is instead based on the GLib event loop. So - // whenever we run a network transaction, the GLib event loop gets spun. One consequence of - // this is that PublishingDialog.go( ) can be called multiple times. Note that since events - // are processed sequentially, PublishingDialog.go( ) is never called re-entrantly. It just - // gets called twice back-to-back in quick succession. So use a timer to do a short circuit - // return if this call to go( ) follows immediately on the heels of another call to go( ). + // Because of this bug: https://bugzilla.gnome.org/show_bug.cgi?id=717505, we use some + // extreme measures. The bug occurs because, in some cases, when publishing is started + // asynchronous network transactions are performed. The mechanism inside libsoup that we + // use to perform asynchronous network transactions isn't based on threads but is instead + // based on the GLib event loop. So whenever we run a network transaction, the GLib event + // loop gets spun. One consequence of this is that PublishingDialog.go( ) can be called + // multiple times. Note that since events are processed sequentially, PublishingDialog.go() + // is never called re-entrantly. It just gets called twice back-to-back in quick + // succession. So use a timer to do a short circuit return if this call to go( ) follows + // immediately on the heels of another call to go( ) + // FIXME: Port publising to async libsoup, then there is no nested main loop anymore. private static Timer since_last_start = null; private static bool elapsed_is_valid = false; public static void go(Gee.Collection<MediaSource> to_publish) { @@ -412,7 +283,7 @@ public class PublishingDialog : Gtk.Dialog { // There are no enabled publishing services that accept this media type, // warn the user. AppWindow.error_message_with_title(_("Unable to publish"), - _("Shotwell cannot publish the selected items because you do not have a compatible publishing plugin enabled. To correct this, choose <b>Edit %s Preferences</b> and enable one or more of the publishing plugins on the <b>Plugins</b> tab.").printf("▸"), + _("Shotwell cannot publish the selected items because you do not have a compatible publishing plugin enabled. To correct this, choose Edit %s Preferences and enable one or more of the publishing plugins on the <b>Plugins</b> tab.").printf("▸"), null, false); return; @@ -458,14 +329,17 @@ public class PublishingDialog : Gtk.Dialog { } Value service_name_val; + Value account_val; service_selector_box_model.get_value(iter, 1, out service_name_val); + service_selector_box_model.get_value(iter, 2, out account_val); string service_name = (string) service_name_val; - + var service_account = (Spit.Publishing.Account) account_val; + Spit.Publishing.Service? selected_service = null; Spit.Publishing.Service[] services = load_all_services(); foreach (Spit.Publishing.Service service in services) { - if (service.get_pluggable_name() == service_name) { + if (service_name.has_prefix(service.get_pluggable_name())) { selected_service = service; break; } @@ -474,7 +348,7 @@ public class PublishingDialog : Gtk.Dialog { Config.Facade.get_instance().set_last_used_service(selected_service.get_id()); - host = new Spit.Publishing.ConcretePublishingHost(selected_service, this, publishables); + host = new Spit.Publishing.ConcretePublishingHost(selected_service, this, publishables, service_account); host.start_publishing(); } diff --git a/src/publishing/StaticMessagePaneWidget.vala b/src/publishing/StaticMessagePaneWidget.vala new file mode 100644 index 0000000..5f8de66 --- /dev/null +++ b/src/publishing/StaticMessagePaneWidget.vala @@ -0,0 +1,62 @@ +/* Copyright 2016 Software Freedom Conservancy Inc. + * Copyright 2019 Jens Georg <mail@jensge.org> + * + * This software is licensed under the GNU LGPL (version 2.1 or later). + * See the COPYING file in this distribution. + */ + +namespace PublishingUI { + +[GtkTemplate (ui = "/org/gnome/Shotwell/ui/static_message_pane_widget.ui")] +public class StaticMessagePane : Spit.Publishing.DialogPane, Gtk.Box { + public bool show_spinner{get; construct; default=false; } + + [GtkChild] + private unowned Gtk.Label static_msg_label; + + [GtkChild] + private unowned Gtk.Spinner spinner; + + public Gtk.Widget get_widget() { + return this; + } + + public Spit.Publishing.DialogPane.GeometryOptions get_preferred_geometry() { + return Spit.Publishing.DialogPane.GeometryOptions.NONE; + } + + public void on_pane_installed() { + } + + public void on_pane_uninstalled() { + } + + public StaticMessagePane(string message_string, bool enable_markup = false, bool show_spinner = false) { + Object(show_spinner: false); + + spinner.active = show_spinner; + + if (enable_markup) { + static_msg_label.set_markup(message_string); + static_msg_label.set_line_wrap(true); + static_msg_label.set_use_markup(true); + } else { + static_msg_label.set_label(message_string); + } + } +} + +public class AccountFetchWaitPane : StaticMessagePane { + public AccountFetchWaitPane() { + base(_("Fetching account information…"), false, true); + } +} + +public class LoginWaitPane : StaticMessagePane { + public LoginWaitPane() { + base(_("Logging in…"), false, true); + } +} + + +} // namespace PublishingUI diff --git a/src/publishing/SuccessPaneWidget.vala b/src/publishing/SuccessPaneWidget.vala new file mode 100644 index 0000000..05b0c16 --- /dev/null +++ b/src/publishing/SuccessPaneWidget.vala @@ -0,0 +1,39 @@ +/* Copyright 2016 Software Freedom Conservancy Inc. + * Copyright 2019 Jens Georg <mail@jensge.org> + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace PublishingUI { + +public class SuccessPane : StaticMessagePane { + public SuccessPane(Spit.Publishing.Publisher.MediaType published_media, int num_uploaded = 1) { + string? message_string = null; + + // Here, we check whether more than one item is being uploaded, and if so, display + // an alternate message. + if (published_media == Spit.Publishing.Publisher.MediaType.VIDEO) { + message_string = ngettext ("The selected video was successfully published.", + "The selected videos were successfully published.", + num_uploaded); + } + else if (published_media == Spit.Publishing.Publisher.MediaType.PHOTO) { + message_string = ngettext ("The selected photo was successfully published.", + "The selected photos were successfully published.", + num_uploaded); + } + else if (published_media == (Spit.Publishing.Publisher.MediaType.PHOTO + | Spit.Publishing.Publisher.MediaType.VIDEO)) { + message_string = _("The selected photos/videos were successfully published."); + } + else { + assert_not_reached (); + } + + base(message_string); + } +} +} + + diff --git a/src/publishing/meson.build b/src/publishing/meson.build new file mode 100644 index 0000000..38178d6 --- /dev/null +++ b/src/publishing/meson.build @@ -0,0 +1,27 @@ +libsw_publishing_gui = static_library( + 'publishing_gui', + [ + 'StaticMessagePaneWidget.vala', + 'ProgressPaneWidget.vala', + 'SuccessPaneWidget.vala', + 'LoginWelcomePaneWidget.vala', + ], + vala_header : 'shotwell-internal-publishing-gui.h', + vala_vapi : 'shotwell-internal-publishing-gui.vapi', + include_directories : config_incdir, + dependencies: [ + gtk, + gee, + sw_plugin + ], + vala_args : [ + '--gresources', + join_paths(meson.project_source_root(), 'data', + 'org.gnome.Shotwell.gresource.xml') + ] +) + +sw_publishing_gui = declare_dependency( + include_directories : include_directories('.'), + link_with : libsw_publishing_gui +) |