Clean up EmailEntry API

Move into composer namespace and rename to match. Update API for
consistency with style guide. Remove uneeded fields and clarify when
::modified is true. Fix call sites.
This commit is contained in:
Michael Gratton 2020-01-25 16:48:47 +11:00 committed by Michael James Gratton
parent 19fc5eced3
commit b3fa1446c1
5 changed files with 138 additions and 133 deletions

View file

@ -51,6 +51,7 @@ src/client/components/status-bar.vala
src/client/components/stock.vala
src/client/composer/composer-box.vala
src/client/composer/composer-container.vala
src/client/composer/composer-email-entry.vala
src/client/composer/composer-embed.vala
src/client/composer/composer-headerbar.vala
src/client/composer/composer-link-popover.vala
@ -58,7 +59,6 @@ src/client/composer/composer-web-view.vala
src/client/composer/composer-widget.vala
src/client/composer/composer-window.vala
src/client/composer/contact-entry-completion.vala
src/client/composer/email-entry.vala
src/client/composer/spell-check-popover.vala
src/client/conversation-list/conversation-list-cell-renderer.vala
src/client/conversation-list/conversation-list-store.vala

View file

@ -0,0 +1,113 @@
/*
* Copyright 2016 Software Freedom Conservancy Inc.
* Copyright 2020 Michael Gratton <mike@vee.net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
/**
* A GTK entry for entering email addresses.
*/
public class Composer.EmailEntry : Gtk.Entry {
/** The entry's list of possibly valid email addresses. */
public Geary.RFC822.MailboxAddresses addresses {
get { return this._addresses; }
set {
this._addresses = value;
validate_addresses();
this.is_modified = false;
this.text = value.to_full_display();
}
}
private Geary.RFC822.MailboxAddresses _addresses = new Geary.RFC822.MailboxAddresses();
/** Determines if the entry contains only valid email addresses. */
public bool is_valid { get; private set; default = false; }
/** Determines if the entry contains any email addresses. */
public bool is_empty {
get {
return this._addresses.is_empty;
}
}
/**
* Determines if the entry has been modified.
*
* The entry is considered to be modified only if the text has
* been changed after it as been constructed or if modified after
* setting {@link addresses}.
*/
public bool is_modified { get; private set; default = false; }
private weak Composer.Widget composer;
public EmailEntry(Composer.Widget composer) {
changed.connect(on_changed);
key_press_event.connect(on_key_press);
this.composer = composer;
show();
}
/** Marks the entry as being modified. */
public void set_modified() {
this.is_modified = true;
}
private void validate_addresses() {
bool is_valid = !this.addresses.is_empty;
foreach (Geary.RFC822.MailboxAddress address in this.addresses) {
if (!address.is_valid()) {
is_valid = false;
return;
}
}
this.is_valid = is_valid;
}
private void on_changed() {
this.is_modified = true;
ContactEntryCompletion? completion =
get_completion() as ContactEntryCompletion;
if (completion != null) {
completion.update_model();
}
if (Geary.String.is_empty(text.strip())) {
this.addresses = new Geary.RFC822.MailboxAddresses();
this.is_valid = false;
} else {
this.addresses =
new Geary.RFC822.MailboxAddresses.from_rfc822_string(text);
this.is_valid = true;
}
}
private bool on_key_press(Gtk.Widget widget, Gdk.EventKey event) {
bool ret = Gdk.EVENT_PROPAGATE;
if (event.keyval == Gdk.Key.Tab) {
ContactEntryCompletion? completion = (
get_completion() as ContactEntryCompletion
);
if (completion != null) {
completion.trigger_selection();
composer.child_focus(Gtk.DirectionType.TAB_FORWARD);
ret = Gdk.EVENT_STOP;
}
} else {
// Keyboard shortcuts for undo/redo won't work when the
// completion UI is visible unless we explicitly check for
// them there. This may be related to the
// single-key-shortcut handling hack in the MainWindow.
Gtk.Window? window = get_toplevel() as Gtk.Window;
if (window != null) {
ret = window.activate_key(event);
}
}
return ret;
}
}

View file

@ -255,10 +255,10 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
/** Determines if the composer is completely empty. */
public bool is_blank {
get {
return this.to_entry.empty
&& this.cc_entry.empty
&& this.bcc_entry.empty
&& this.reply_to_entry.empty
return this.to_entry.is_empty
&& this.cc_entry.is_empty
&& this.bcc_entry.is_empty
&& this.reply_to_entry.is_empty
&& this.subject_entry.buffer.length == 0
&& this.editor.is_empty
&& this.attached_files.size == 0;
@ -1017,29 +1017,28 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
else
this.compose_type = ComposeType.REPLY_ALL;
this.to_entry.modified = this.cc_entry.modified = this.bcc_entry.modified = false;
if (!to_entry.addresses.equal_to(reply_to_addresses))
this.to_entry.modified = true;
this.to_entry.set_modified();
if (cc != "" && !cc_entry.addresses.equal_to(reply_cc_addresses))
this.cc_entry.modified = true;
this.cc_entry.set_modified();
if (bcc != "")
this.bcc_entry.modified = true;
this.bcc_entry.set_modified();
// We're in compact inline mode, but there are modified email
// addresses, so set us to use plain inline mode instead so
// the modified addresses can be seen. If there are CC
if (this.current_mode == INLINE_COMPACT && (
this.to_entry.modified ||
this.cc_entry.modified ||
this.bcc_entry.modified ||
this.reply_to_entry.modified)) {
this.to_entry.is_modified ||
this.cc_entry.is_modified ||
this.bcc_entry.is_modified ||
this.reply_to_entry.is_modified)) {
set_mode(INLINE);
}
// If there's a modified header that would normally be hidden,
// show full fields.
if (this.bcc_entry.modified ||
this.reply_to_entry.modified) {
if (this.bcc_entry.is_modified ||
this.reply_to_entry.is_modified) {
this.editor_actions.change_action_state(
ACTION_SHOW_EXTENDED_HEADERS, true
);
@ -1402,7 +1401,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
if (!modify_headers)
return;
bool recipients_modified = this.to_entry.modified || this.cc_entry.modified || this.bcc_entry.modified;
bool recipients_modified = this.to_entry.is_modified || this.cc_entry.is_modified || this.bcc_entry.is_modified;
if (!recipients_modified) {
if (type == ComposeType.REPLY || type == ComposeType.REPLY_ALL)
this.to_entry.addresses = Geary.RFC822.Utils.merge_addresses(to_entry.addresses,
@ -1414,7 +1413,6 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
else
this.cc_entry.addresses = Geary.RFC822.Utils.remove_addresses(this.cc_entry.addresses,
this.to_entry.addresses);
this.to_entry.modified = this.cc_entry.modified = false;
}
if (referred.message_id != null) {
@ -1953,16 +1951,16 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
// To must be valid (and hence non-empty), the other email
// fields must be either empty or valid.
get_action(ACTION_SEND).set_enabled(
this.to_entry.valid &&
(this.cc_entry.empty || this.cc_entry.valid) &&
(this.bcc_entry.empty || this.bcc_entry.valid) &&
(this.reply_to_entry.empty || this.reply_to_entry.valid)
this.to_entry.is_valid &&
(this.cc_entry.is_empty || this.cc_entry.is_valid) &&
(this.bcc_entry.is_empty || this.bcc_entry.is_valid) &&
(this.reply_to_entry.is_empty || this.reply_to_entry.is_valid)
);
}
private void set_compact_header_recipients() {
bool tocc = !this.to_entry.empty && !this.cc_entry.empty,
ccbcc = !(this.to_entry.empty && this.cc_entry.empty) && !this.bcc_entry.empty;
bool tocc = !this.to_entry.is_empty && !this.cc_entry.is_empty,
ccbcc = !(this.to_entry.is_empty && this.cc_entry.is_empty) && !this.bcc_entry.is_empty;
string label = this.to_entry.buffer.text + (tocc ? ", " : "")
+ this.cc_entry.buffer.text + (ccbcc ? ", " : "") + this.bcc_entry.buffer.text;
StringBuilder tooltip = new StringBuilder();
@ -2145,9 +2143,9 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
}
private void update_extended_headers(bool reorder=true) {
bool cc = this.cc_entry.addresses != null;
bool bcc = this.bcc_entry.addresses != null;
bool reply_to = this.reply_to_entry.addresses != null;
bool cc = !this.cc_entry.is_empty;
bool bcc = !this.bcc_entry.is_empty;
bool reply_to = !this.reply_to_entry.is_empty;
if (reorder) {
if (cc) {

View file

@ -1,106 +0,0 @@
/* Copyright 2016 Software Freedom Conservancy Inc.
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
// A custom entry for e-mail addresses
public class EmailEntry : Gtk.Entry {
// Whether this entry contains a valid email address
public bool valid { get; set; default = false; }
public bool empty { get; set; default = true; }
public bool modified = false;
// null or valid addresses
public Geary.RFC822.MailboxAddresses? addresses { get; set; default = null; }
private weak Composer.Widget composer;
private bool updating = false;
public EmailEntry(Composer.Widget composer) {
changed.connect(on_changed);
key_press_event.connect(on_key_press);
this.composer = composer;
notify["addresses"].connect(() => {
validate_addresses();
if (updating)
return;
updating = true;
modified = true;
text = (addresses == null) ? "" : addresses.to_full_display();
updating = false;
});
show();
}
private void on_changed() {
if (updating)
return;
modified = true;
ContactEntryCompletion? completion = get_completion() as ContactEntryCompletion;
if (completion != null) {
completion.update_model();
}
if (Geary.String.is_empty(text.strip())) {
updating = true;
addresses = null;
updating = false;
valid = false;
empty = true;
return;
}
updating = true;
addresses = new Geary.RFC822.MailboxAddresses.from_rfc822_string(text);
updating = false;
}
private void validate_addresses() {
if (addresses == null || addresses.size == 0) {
valid = false;
empty = true;
return;
}
empty = false;
foreach (Geary.RFC822.MailboxAddress address in addresses) {
if (!address.is_valid()) {
valid = false;
return;
}
}
valid = true;
}
private bool on_key_press(Gtk.Widget widget, Gdk.EventKey event) {
bool ret = Gdk.EVENT_PROPAGATE;
if (event.keyval == Gdk.Key.Tab) {
ContactEntryCompletion? completion = (
get_completion() as ContactEntryCompletion
);
if (completion != null) {
completion.trigger_selection();
composer.child_focus(Gtk.DirectionType.TAB_FORWARD);
ret = Gdk.EVENT_STOP;
}
} else {
// Keyboard shortcuts for undo/redo won't work when the
// completion UI is visible unless we explicitly check for
// them there. This may be related to the
// single-key-shortcut handling hack in the MainWindow.
Gtk.Window? window = get_toplevel() as Gtk.Window;
if (window != null) {
ret = window.activate_key(event);
}
}
return ret;
}
}

View file

@ -53,6 +53,7 @@ geary_client_vala_sources = files(
'composer/composer-box.vala',
'composer/composer-container.vala',
'composer/composer-email-entry.vala',
'composer/composer-embed.vala',
'composer/composer-headerbar.vala',
'composer/composer-link-popover.vala',
@ -60,7 +61,6 @@ geary_client_vala_sources = files(
'composer/composer-widget.vala',
'composer/composer-window.vala',
'composer/contact-entry-completion.vala',
'composer/email-entry.vala',
'composer/spell-check-popover.vala',
'conversation-list/conversation-list-cell-renderer.vala',