blob: 1219d597da278aa1449116fc2adcbaa4ee084cd5 [file] [log] [blame]
Stepan Salenikovichbe6550c2015-08-21 16:16:03 -04001/*
Guillaume Roguez2a6150d2017-07-19 18:24:47 -04002 * Copyright (C) 2015-2017 Savoir-faire Linux Inc.
Stepan Salenikovichbe6550c2015-08-21 16:16:03 -04003 * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Stepan Salenikovichbe6550c2015-08-21 16:16:03 -040018 */
19#include "dbuserrorhandler.h"
20
21#include <glib/gi18n.h>
22#include <callmodel.h>
23#include <globalinstances.h>
24#include "../ring_client.h"
25
26namespace Interfaces {
27
28static GtkWidget*
29dring_crash_dialog()
30{
31 GtkWidget *dialog = gtk_dialog_new();
32 gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE);
33 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
34 gtk_window_set_decorated(GTK_WINDOW(dialog), FALSE);
35 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
36 gtk_window_set_title(GTK_WINDOW(dialog), C_("Name of error window (dialog)","Ring Error"));
37
38 /* get the main window */
39 if (auto app = g_application_get_default()) {
40 auto win = ring_client_get_main_window(RING_CLIENT(app));
41 if (win) {
42 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(win));
43 gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
44 } else {
45 gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
46 }
47 } else {
48 g_warning("no default GApplication exists");
49 }
50
51 GtkWidget *content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
52 gtk_box_set_spacing(GTK_BOX(content_area), 10);
53 gtk_widget_set_size_request(content_area, 250, -1);
54 gtk_widget_set_margin_top(content_area, 25);
55
56 auto message = gtk_label_new(
57 _("Trying to reconnect to the Ring daemon (dring)...")
58 );
59
60 gtk_box_pack_start(GTK_BOX(content_area), message, FALSE, TRUE, 0);
61
62 GtkWidget *spinner = gtk_spinner_new();
63 gtk_spinner_start(GTK_SPINNER(spinner));
64
65 gtk_box_pack_start(GTK_BOX(content_area), spinner, FALSE, TRUE, 0);
66
67 gtk_widget_show_all(content_area);
68
69 return dialog;
70}
71
72static GtkWidget*
73ring_quitting_dialog()
74{
75 /* get the main window */
76 GtkWindow *win = NULL;
77 if (auto app = g_application_get_default()) {
78 win = ring_client_get_main_window(RING_CLIENT(app));
79 } else {
80 g_warning("no default GApplication exists");
81 }
82
83 GtkWidget *dialog = gtk_message_dialog_new(
84 win,
85 (GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
86 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
87 _("Could not re-connect to the Ring daemon (dring).\nRing will now quit.")
88 );
89
90 if (win) {
91 gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
92 } else {
93 gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
94 }
95 gtk_window_set_title(GTK_WINDOW(dialog), C_("Name of error window (dialog)","Ring Error"));
96 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
97
98 return dialog;
99}
100
101static gboolean
102check_connection_cb(GtkWidget *warning_dialog)
103{
104 g_return_val_if_fail(GTK_IS_DIALOG(warning_dialog), G_SOURCE_REMOVE);
105
106 gtk_widget_destroy(warning_dialog);
107
Guillaume Roguez5d1514b2015-10-22 15:55:31 -0400108 if ((!CallModel::instance().isConnected()) || (!CallModel::instance().isValid())) {
Stepan Salenikovichbe6550c2015-08-21 16:16:03 -0400109 g_warning("could not reconnect to the daemon");
110
111 auto quit_dialog = ring_quitting_dialog();
112
113 /* wait for the user to exit the dialog */
114 gtk_dialog_run(GTK_DIALOG(quit_dialog));
115 gtk_widget_destroy(quit_dialog);
116
117 /* quit */
118 if (auto app = g_application_get_default()) {
119 auto quit_action = G_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "quit"));
120 g_action_activate(quit_action, NULL);
121 } else {
122 g_warning("no default GApplication exists");
123 }
124 } else {
125 /* we're done handling the error */
126 static_cast<DBusErrorHandler&>(GlobalInstances::dBusErrorHandler()).finishedHandlingError();
127 }
128
129 return G_SOURCE_REMOVE;
130}
131
132static gboolean
133error_cb(G_GNUC_UNUSED gpointer user_data)
134{
135 g_warning("dring has possibly crashed, or has been killed... will wait 2.5 seconds and try to reconnect");
136
137 auto warning_dialog = dring_crash_dialog();
138 gtk_window_present(GTK_WINDOW(warning_dialog));
139
140 /* allow 2.5 seconds for the daemon to restart and then see if we're re-connected */
141 g_timeout_add(2500, (GSourceFunc)check_connection_cb, warning_dialog);
142
143 return G_SOURCE_REMOVE;
144}
145
146void
147DBusErrorHandler::connectionError(const QString& error)
148{
149 g_warning("%s", error.toUtf8().constData());
150
151 if (!handlingError) {
152 handlingError = true;
153 /* the error may come from a different thread other than the main loop,
154 * we use an idle function to run events on the main loop */
155 g_idle_add((GSourceFunc)error_cb, NULL);
156 }
157}
158
159void
160DBusErrorHandler::invalidInterfaceError(const QString& error)
161{
162 g_warning("%s", error.toUtf8().constData());
163
164 if (!handlingError) {
165 handlingError = true;
166 /* the error may come from a different thread other than the main loop,
167 * we use an idle function to run events on the main loop */
168 g_idle_add((GSourceFunc)error_cb, NULL);
169 }
170}
171
172void
173DBusErrorHandler::finishedHandlingError()
174{
175 handlingError = false;
176}
177
178} // namespace Interfaces