Closes #4633. Geary will now handle mailto links and can be set up as the default email client.

This commit is contained in:
Nate Lillich 2012-04-24 18:28:45 -07:00
parent 94e909d3ca
commit a56014ce38
8 changed files with 119 additions and 19 deletions

View file

@ -23,6 +23,20 @@ add_subdirectory(icons)
add_subdirectory(sql)
add_subdirectory(ui)
#
# Install geary.desktop
#
install(
FILES
geary.desktop
DESTINATION
share/applications
)
install(
CODE
"execute_process (COMMAND update-desktop-database)"
)
#
# Uninstall target
#
@ -38,5 +52,7 @@ add_custom_target(
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
COMMAND
${glib_schema_compiler} ${GSETTINGS_DIR}
COMMAND
update-desktop-database
)

13
geary.desktop Normal file
View file

@ -0,0 +1,13 @@
[Desktop Entry]
Encoding=UTF-8
Icon=geary
Name=Geary
GenericName=Email Client
Comment=Send and receive email
TryExec=geary
Exec=geary %U
Type=Application
Terminal=false
Categories=GNOME;GTK;Network;Office;Email
MimeType=x-scheme-handler/mailto

View file

@ -2,6 +2,7 @@ set(ICONS_DEST share/geary/icons)
install(FILES archive-icon.png DESTINATION ${ICONS_DEST})
install(FILES geary.png DESTINATION ${ICONS_DEST})
install(FILES geary.png DESTINATION share/icons/hicolor/scalable/apps)
install(FILES multiple-tags.png DESTINATION ${ICONS_DEST})
install(FILES non-starred-grey.png DESTINATION ${ICONS_DEST})
install(FILES one-tag.png DESTINATION ${ICONS_DEST})

View file

@ -122,6 +122,7 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
} else {
Log.set_handler(null, LogLevelFlags.LEVEL_DEBUG, log_ignore);
}
return 0;
}
@ -134,20 +135,20 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
return result;
}
public override void activate() {
public override void activate(string[] args) {
// If Geary is already running, show the main window and return.
if (controller != null && controller.main_window != null) {
controller.main_window.present();
handle_args(args);
return;
}
// Start Geary.
Geary.Engine.init(get_user_data_directory(), get_resource_directory());
config = new Configuration();
controller = new GearyController();
login();
handle_args(args);
return;
}
@ -324,5 +325,13 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
public Gtk.Window get_main_window() {
return controller.main_window;
}
private void handle_args(string[] args) {
foreach(string arg in args) {
if (arg.has_prefix("mailto:")) {
controller.compose_mailto(arg);
}
}
}
}

View file

@ -917,10 +917,7 @@ public class GearyController {
public void on_link_selected(string link) {
const string MAILTO = "mailto:";
if (link.down().has_prefix(MAILTO)) {
// TODO: handle more complex mailto links (subject, body, etc.)
create_compose_window(new Geary.ComposedEmail(new DateTime.now_local(),
get_from(), new Geary.RFC822.MailboxAddresses.single(
new Geary.RFC822.MailboxAddress(null, link.substring(MAILTO.length)))));
compose_mailto(link);
} else {
open_uri(link);
}
@ -946,5 +943,9 @@ public class GearyController {
GearyApplication.instance.actions.get_action(ACTION_DELETE_MESSAGE).sensitive = sensitive;
GearyApplication.instance.actions.get_action(ACTION_MARK_AS_MENU).sensitive = sensitive;
}
public void compose_mailto(string mailto) {
create_compose_window(new Geary.ComposedEmail.from_mailto(mailto, get_from()));
}
}

View file

@ -37,7 +37,7 @@ public abstract class YorbaApplication {
return 0;
}
public virtual signal void activate() {
public virtual signal void activate(string[] args) {
}
public virtual signal void exiting(bool panicked) {
@ -65,7 +65,10 @@ public abstract class YorbaApplication {
// If app already running, activate it and exit
if (unique_app.is_running()) {
unique_app.send_message((int) Unique.Command.ACTIVATE, null);
Unique.MessageData data = new Unique.MessageData();
string argstr = string.joinv(", ", args);
data.set_text(argstr, argstr.length);
unique_app.send_message((int) Unique.Command.ACTIVATE, data);
return false;
}
@ -79,7 +82,7 @@ public abstract class YorbaApplication {
Unique.MessageData data, uint timestamp) {
switch (command) {
case Unique.Command.ACTIVATE:
activate();
activate(data.get_text().split(", "));
break;
default:
@ -112,7 +115,7 @@ public abstract class YorbaApplication {
error("Unable to register application: %s", e.message);
}
activate();
activate(args);
// enter the main loop
if (exitcode == 0)

View file

@ -29,10 +29,14 @@ public class Geary.ComposedEmail : Object {
public string? mailer { get; set; default = null; }
public ComposedEmail(DateTime date, RFC822.MailboxAddresses from,
RFC822.MailboxAddresses? to = null) {
RFC822.MailboxAddresses? to = null, RFC822.MailboxAddresses? cc = null,
RFC822.MailboxAddresses? bcc = null, RFC822.Subject? subject = null) {
this.date = date;
this.from = from;
this.to = to;
this.cc = cc;
this.bcc = bcc;
this.subject = subject;
}
public ComposedEmail.as_reply(DateTime date, RFC822.MailboxAddresses from, Geary.Email source) {
@ -77,6 +81,58 @@ public class Geary.ComposedEmail : Object {
Geary.RFC822.Utils.quote_email_for_forward(source, true)));
}
public ComposedEmail.from_mailto(string mailto, RFC822.MailboxAddresses default_from) {
DateTime date = new DateTime.now_local();
RFC822.MailboxAddresses from = default_from;
RFC822.MailboxAddresses? to = null;
RFC822.MailboxAddresses? cc = null;
RFC822.MailboxAddresses? bcc = null;
RFC822.Subject? subject = null;
if (mailto.length > "mailto:".length) {
// Parse the mailto link.
string[] parts = mailto.substring("mailto:".length).split("?", 2);
string email = Uri.unescape_string(parts[0]);
string[] params = parts.length == 2 ? parts[1].split("&") : new string[0];
Gee.HashMap<string, string> headers = new Gee.HashMap<string, string>();
foreach (string param in params) {
string[] param_parts = param.split("=", 2);
if (param_parts.length == 2) {
headers.set(Uri.unescape_string(param_parts[0]).down(),
Uri.unescape_string(param_parts[1]));
}
}
// Assemble the headers.
if (headers.has_key("from")) {
from = new RFC822.MailboxAddresses.from_rfc822_string(headers.get("from"));
}
if (email.length > 0 && headers.has_key("to")) {
to = new RFC822.MailboxAddresses.from_rfc822_string("%s,%s".printf(email, headers.get("to")));
} else if (email.length > 0) {
to = new RFC822.MailboxAddresses.from_rfc822_string(email);
} else if (headers.has_key("to")) {
to = new RFC822.MailboxAddresses.from_rfc822_string(headers.get("to"));
}
if (headers.has_key("cc")) {
cc = new RFC822.MailboxAddresses.from_rfc822_string(headers.get("cc"));
}
if (headers.has_key("bcc")) {
bcc = new RFC822.MailboxAddresses.from_rfc822_string(headers.get("bcc"));
}
if (headers.has_key("subject")) {
subject = new RFC822.Subject(headers.get("subject"));
}
}
// And construct!
this(date, from, to, cc, bcc, subject);
}
private void set_reply_references(Geary.Email source) {
in_reply_to = source.message_id;
reply_to_email = source;

View file

@ -52,12 +52,13 @@ namespace Unique {
public unowned Gdk.Screen get_screen ();
public unowned string get_startup_id ();
public unowned string get_text ();
public unowned string get_uris ();
[CCode (array_length = false)]
public unowned string[] get_uris ();
public uint get_workspace ();
public void @set (uchar[] data, ssize_t length);
public void set_filename (string filename);
public bool set_text (string str, ssize_t length);
public bool set_uris (string uris);
public bool set_uris ([CCode (array_length = false)] string[] uris);
}
[CCode (cprefix = "UNIQUE_", cheader_filename = "unique/uniqueenumtypes.h")]
public enum Command {