dbuserrorhandler.cpp 5.71 KB
Newer Older
1
/*
Sébastien Blin's avatar
Sébastien Blin committed
2
 *  Copyright (C) 2015-2019 Savoir-faire Linux Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *  Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 */
#include "dbuserrorhandler.h"

#include <glib/gi18n.h>
#include <globalinstances.h>
#include "../ring_client.h"
24
#include <api/lrc.h>
25 26 27 28 29 30 31 32 33 34 35

namespace Interfaces {

static GtkWidget*
dring_crash_dialog()
{
    GtkWidget *dialog = gtk_dialog_new();
    gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE);
    gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
    gtk_window_set_decorated(GTK_WINDOW(dialog), FALSE);
    gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
Philippe Gorley's avatar
Philippe Gorley committed
36
    gtk_window_set_title(GTK_WINDOW(dialog), C_("Name of error window (dialog)","Jami Error"));
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

    /* get the main window */
    if (auto app = g_application_get_default()) {
        auto win = ring_client_get_main_window(RING_CLIENT(app));
        if (win) {
            gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(win));
            gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
        } else {
            gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
        }
    } else {
        g_warning("no default GApplication exists");
    }

    GtkWidget *content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
    gtk_box_set_spacing(GTK_BOX(content_area), 10);
    gtk_widget_set_size_request(content_area, 250, -1);
    gtk_widget_set_margin_top(content_area, 25);

    auto message = gtk_label_new(
Philippe Gorley's avatar
Philippe Gorley committed
57
        _("Trying to reconnect to the Jami daemon (dring)…")
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
    );

    gtk_box_pack_start(GTK_BOX(content_area), message, FALSE, TRUE, 0);

    GtkWidget *spinner = gtk_spinner_new();
    gtk_spinner_start(GTK_SPINNER(spinner));

    gtk_box_pack_start(GTK_BOX(content_area), spinner, FALSE, TRUE, 0);

    gtk_widget_show_all(content_area);

    return dialog;
}

static GtkWidget*
ring_quitting_dialog()
{
    /* get the main window */
    GtkWindow *win = NULL;
    if (auto app = g_application_get_default()) {
        win = ring_client_get_main_window(RING_CLIENT(app));
    } else {
        g_warning("no default GApplication exists");
    }

    GtkWidget *dialog = gtk_message_dialog_new(
        win,
        (GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
        GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
Philippe Gorley's avatar
Philippe Gorley committed
87
        _("Could not re-connect to the Jami daemon (dring).\nJami will now quit.")
88 89 90 91 92 93 94
    );

    if (win) {
        gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
    } else {
        gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
    }
Philippe Gorley's avatar
Philippe Gorley committed
95
    gtk_window_set_title(GTK_WINDOW(dialog), C_("Name of error window (dialog)","Jami Error"));
96 97 98 99 100 101 102 103 104 105 106 107
    gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);

    return dialog;
}

static gboolean
check_connection_cb(GtkWidget *warning_dialog)
{
    g_return_val_if_fail(GTK_IS_DIALOG(warning_dialog), G_SOURCE_REMOVE);

    gtk_widget_destroy(warning_dialog);

108
    if ((!lrc::api::Lrc::isConnected()) || (!lrc::api::Lrc::dbusIsValid())) {
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
        g_warning("could not reconnect to the daemon");

        auto quit_dialog = ring_quitting_dialog();

        /* wait for the user to exit the dialog */
        gtk_dialog_run(GTK_DIALOG(quit_dialog));
        gtk_widget_destroy(quit_dialog);

        /* quit */
        if (auto app = g_application_get_default()) {
            auto quit_action = G_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "quit"));
            g_action_activate(quit_action, NULL);
        } else {
            g_warning("no default GApplication exists");
        }
    } else {
        /* we're done handling the error */
        static_cast<DBusErrorHandler&>(GlobalInstances::dBusErrorHandler()).finishedHandlingError();
    }

    return G_SOURCE_REMOVE;
}

static gboolean
error_cb(G_GNUC_UNUSED gpointer user_data)
{
    g_warning("dring has possibly crashed, or has been killed... will wait 2.5 seconds and try to reconnect");

    auto warning_dialog = dring_crash_dialog();
    gtk_window_present(GTK_WINDOW(warning_dialog));

    /* allow 2.5 seconds for the daemon to restart and then see if we're re-connected */
    g_timeout_add(2500, (GSourceFunc)check_connection_cb, warning_dialog);

    return G_SOURCE_REMOVE;
}

void
DBusErrorHandler::connectionError(const QString& error)
{
    g_warning("%s", error.toUtf8().constData());

    if (!handlingError) {
        handlingError = true;
        /* the error may come from a different thread other than the main loop,
         * we use an idle function to run events on the main loop */
        g_idle_add((GSourceFunc)error_cb, NULL);
    }
}

void
DBusErrorHandler::invalidInterfaceError(const QString& error)
{
    g_warning("%s", error.toUtf8().constData());

    if (!handlingError) {
        handlingError = true;
        /* the error may come from a different thread other than the main loop,
         * we use an idle function to run events on the main loop */
        g_idle_add((GSourceFunc)error_cb, NULL);
    }
}

void
DBusErrorHandler::finishedHandlingError()
{
    handlingError = false;
}

} // namespace Interfaces