improve search entry behaviour
We improve the search entry by trying to do what the user wants:
* if a user explicitly specifies the scheme ("sip:" or "ring:")
then we always use a corresponding account type (use
currentDefaultAccount() with the scheme type)
* if a user doesn't specify the scheme, then we decide based on the
user selected account; if SIP account then we assume its a SIP
URI; if RING account then we check if its a ringID, otherwise we
perform a name lookup.
Additionally, the use of currentDefaultAccount() in all cases makes
sure that we automatically switch to the correct account so that
the search result is always visible.
Change-Id: I2ad4e5472c06dedc5912a4ffbb4d6906d5d6f84a
Reviewed-by: Nicolas Jäger <nicolas.jager@savoirfairelinux.com>
diff --git a/src/ringmainwindow.cpp b/src/ringmainwindow.cpp
index 7d222a2..983d223 100644
--- a/src/ringmainwindow.cpp
+++ b/src/ringmainwindow.cpp
@@ -136,7 +136,6 @@
/* Pending ring usernames lookup for the search entry */
QMetaObject::Connection username_lookup;
- std::string* pending_username_lookup;
/* The webkit_chat_container is created once, then reused for all chat views */
GtkWidget *webkit_chat_container;
@@ -512,11 +511,11 @@
}
static void
-process_search_entry_contact_method(RingMainWindow *self, const URI& uri, Account* accountOrNullptr)
+activate_contact_method(RingMainWindow *self, URI uri, Account *account)
{
auto priv = RING_MAIN_WINDOW_GET_PRIVATE(self);
- auto cm = PhoneDirectoryModel::instance().getNumber(uri, accountOrNullptr);
+ auto cm = PhoneDirectoryModel::instance().getNumber(uri, account);
if (g_settings_get_boolean(priv->settings, "search-entry-places-call")) {
place_new_call(cm);
@@ -529,12 +528,126 @@
cm->setLastUsed(QDateTime::currentDateTime().toTime_t());
// select cm
- RecentModel::instance().selectionModel()->setCurrentIndex(RecentModel::instance().getIndex(cm), QItemSelectionModel::ClearAndSelect);
+ RecentModel::instance().selectionModel()->setCurrentIndex(
+ RecentModel::instance().getIndex(cm),
+ QItemSelectionModel::ClearAndSelect
+ );
}
gtk_entry_set_text(GTK_ENTRY(priv->search_entry), "");
}
static void
+lookup_username(RingMainWindow *self, URI uri, Account *account)
+{
+ auto priv = RING_MAIN_WINDOW_GET_PRIVATE(self);
+
+ gtk_spinner_start(GTK_SPINNER(priv->spinner_lookup));
+ gtk_entry_set_text(GTK_ENTRY(priv->search_entry), "");
+
+ // we need to strip the Scheme section, or else some will contain "sip:"
+ QString querry = uri.format(URI::Section::USER_INFO|URI::Section::HOSTNAME|URI::Section::PORT);
+
+ /* disconect previous lookup */
+ QObject::disconnect(priv->username_lookup);
+
+ /* connect new lookup */
+ priv->username_lookup = QObject::connect(
+ &NameDirectory::instance(),
+ &NameDirectory::registeredNameFound,
+ [self, priv, querry] (Account* account, NameDirectory::LookupStatus status, const QString& address, const QString& name) {
+
+ g_debug("lookup results for %s is %s",
+ querry.toUtf8().constData(),
+ name.toUtf8().constData()
+ );
+
+ if ( name.compare(querry, Qt::CaseInsensitive) != 0 ) {
+ g_debug("not from the same lookup match");
+ return; // doesn't match
+ }
+
+ gtk_entry_set_text(GTK_ENTRY(priv->search_entry), "");
+
+ switch(status)
+ {
+ case NameDirectory::LookupStatus::SUCCESS:
+ {
+ URI result = URI("ring:" + address);
+ activate_contact_method(self, result, account);
+ break;
+ }
+ case NameDirectory::LookupStatus::INVALID_NAME:
+ {
+ //Can't be a ring username, could be something else.
+ auto dialog = gtk_message_dialog_new(
+ GTK_WINDOW(self),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("Invalid Ring username: %s"),
+ name.toUtf8().constData()
+ );
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ break;
+ }
+ case NameDirectory::LookupStatus::ERROR:
+ {
+ auto dialog = gtk_message_dialog_new(
+ GTK_WINDOW(self),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("Error resolving username, nameserver is possibly unreachable")
+ );
+
+ gtk_dialog_run(GTK_DIALOG (dialog));
+ gtk_widget_destroy(dialog);
+ break;
+ }
+ case NameDirectory::LookupStatus::NOT_FOUND:
+ {
+ auto dialog = gtk_message_dialog_new(
+ GTK_WINDOW(self),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("Could not resolve Ring username: %s"),
+ name.toUtf8().constData()
+ );
+
+ gtk_dialog_run(GTK_DIALOG (dialog));
+ gtk_widget_destroy(dialog);
+ break;
+ }
+ }
+ gtk_spinner_stop(GTK_SPINNER(priv->spinner_lookup));
+ }
+ );
+
+ /* lookup */
+ NameDirectory::instance().lookupName(account, "", querry);
+}
+
+/**
+ * This is called when someone activates the search entry (clicks enter or on the button).
+ * At this point the list is already filtered but on clicking enter we want to either contact a new
+ * number or perform a search on the name service. Here we must decide which one the user wants.
+ * We'll use the following rules to decide:
+ * * if a user explicitly specifies the scheme ("sip:" or "ring:") then we always use a
+ * corresponding account type (use currentDefaultAccount() with the scheme type)
+ * * if a user doesn't specify the scheme, then we decide based on the user selected account; if
+ * SIP account then we assume its a SIP URI; if RING account then we check if its a ringID,
+ * otherwise we perform a name lookup.
+ *
+ * Additionally, we need to make sure that the CM found/created either has the same account set as
+ * selected by the user, no account set, or else we need to switch the user selected account to the
+ * account of the CM (eg: in the case we're switching protocols), or else the item will not be
+ * visible in the Converstations list to the user. This is accomplished via the use of
+ * currentDefaultAccount().
+ */
+static void
search_entry_activated(RingMainWindow *self)
{
auto priv = RING_MAIN_WINDOW_GET_PRIVATE(self);
@@ -543,93 +656,34 @@
URI uri = URI(querry);
- /* we don't want to lookup a ring id and we require to have a ring account chosen */
- if (uri.protocolHint() != URI::ProtocolHint::RING && get_active_ring_account()) {
- *priv->pending_username_lookup = querry;
+ /* get account to use */
+ Account *account = nullptr;
+ if (uri.schemeType() != URI::SchemeType::NONE) {
+ /* explicit SIP, SIPS, or RING; make sure account is of right type */
+ account = AvailableAccountModel::instance().currentDefaultAccount(uri.schemeType());
+ if (!account) {
+ const gchar *type = uri.schemeType() == URI::SchemeType::RING ? "RING" : "SIP";
+ g_warning("entered %s uri, but no active %s accounts", type, type);
+ }
+ } else {
+ /* just take the user selected account */
+ account = AvailableAccountModel::instance().currentDefaultAccount();
+ }
- gtk_spinner_start(GTK_SPINNER(priv->spinner_lookup));
- gtk_entry_set_text(GTK_ENTRY(priv->search_entry), "");
+ if (!account) {
+ g_critical("could not get an account for uri: %s", uri.full().toUtf8().constData());
+ return;
+ }
- QString username_to_lookup = uri.format(URI::Section::USER_INFO|URI::Section::HOSTNAME|URI::Section::PORT);
-
- /* disconect previous lookup */
- QObject::disconnect(priv->username_lookup);
-
- /* connect new lookup */
- priv->username_lookup = QObject::connect(
- &NameDirectory::instance(),
- &NameDirectory::registeredNameFound,
- [self, priv, username_to_lookup] (Account* account, NameDirectory::LookupStatus status, const QString& address, const QString& name) {
-
- auto name_qbarray = name.toLatin1();
- if ( strcmp(priv->pending_username_lookup->data(), name_qbarray.data()) != 0 )
- return;
-
- gtk_entry_set_text(GTK_ENTRY(priv->search_entry), "");
-
- switch(status)
- {
- case NameDirectory::LookupStatus::SUCCESS:
- {
- URI uri = URI("ring:" + address);
- process_search_entry_contact_method(self, uri, account);
- break;
- }
- case NameDirectory::LookupStatus::INVALID_NAME:
- {
- //Can't be a ring username, could be something else.
- auto dialog = gtk_message_dialog_new(
- GTK_WINDOW(self),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- _("Invalid Ring username: %s"),
- name.toUtf8().constData()
- );
-
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- break;
- }
- case NameDirectory::LookupStatus::ERROR:
- {
- auto dialog = gtk_message_dialog_new(
- GTK_WINDOW(self),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- _("Error resolving username, nameserver is possibly unreachable")
- );
-
- gtk_dialog_run(GTK_DIALOG (dialog));
- gtk_widget_destroy(dialog);
- break;
- }
- case NameDirectory::LookupStatus::NOT_FOUND:
- {
- auto dialog = gtk_message_dialog_new(
- GTK_WINDOW(self),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- _("Could not resolve Ring username: %s"),
- name.toUtf8().constData()
- );
-
- gtk_dialog_run(GTK_DIALOG (dialog));
- gtk_widget_destroy(dialog);
- break;
- }
- }
- *priv->pending_username_lookup = "";
- gtk_spinner_stop(GTK_SPINNER(priv->spinner_lookup));
- }
- );
-
- /* lookup */
- NameDirectory::instance().lookupName(get_active_ring_account(), QString(), username_to_lookup);
- }else // no lookup
- process_search_entry_contact_method(self, uri, nullptr);
+ /* if RING and not RingID, perform lookup */
+ if (account->protocol() == Account::Protocol::RING &&
+ uri.protocolHint() != URI::ProtocolHint::RING)
+ {
+ lookup_username(self, uri, account);
+ } else {
+ /* no lookup, simply use the URI as is */
+ activate_contact_method(self, uri, account);
+ }
}
static gboolean
@@ -1194,8 +1248,6 @@
RingMainWindowPrivate *priv = RING_MAIN_WINDOW_GET_PRIVATE(win);
gtk_widget_init_template(GTK_WIDGET(win));
- priv->pending_username_lookup = new std::string; // see object finilize for delete
-
/* bind to window size settings */
priv->settings = g_settings_new_full(get_ring_schema(), nullptr, nullptr);
auto width = g_settings_get_int(priv->settings, "window-width");
@@ -1413,9 +1465,6 @@
g_clear_object(&priv->settings);
- delete priv->pending_username_lookup;
- priv->pending_username_lookup = nullptr;
-
G_OBJECT_CLASS(ring_main_window_parent_class)->finalize(object);
}