summaryrefslogtreecommitdiffstats
path: root/onlineupdate/source/update/updater/progressui_gtk.cxx
blob: fecd98a8730abe28ad5cd89c656f4e3efca30d9b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#if defined(UNIX) || defined(MACOSX)
#include <stdio.h>
#include <gtk/gtk.h>
#include <unistd.h>
#include "progressui.h"
#include "readstrings.h"
#include "errors.h"

#define TIMER_INTERVAL 100

static float    sProgressVal;  // between 0 and 100
static gboolean sQuit = FALSE;
static gboolean sEnableUI;
static guint    sTimerID;

static GtkWidget *sWin;
static GtkWidget *sLabel;
static GtkWidget *sProgressBar;

static const char *sProgramPath;

static gboolean
UpdateDialog(gpointer /*data*/)
{
    if (sQuit)
    {
        gtk_widget_hide(sWin);
        gtk_main_quit();
    }

    float progress = sProgressVal;

    gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(sProgressBar),
                                  progress / 100.0);

    return TRUE;
}

static gboolean
OnDeleteEvent(GtkWidget * /*widget*/, GdkEvent * /*event*/, gpointer /*user_data*/)
{
    return TRUE;
}

int
InitProgressUI(int *pargc, char ***pargv)
{
    sProgramPath = (*pargv)[0];

    sEnableUI = gtk_init_check(pargc, pargv);
    return 0;
}

int
ShowProgressUI()
{
    if (!sEnableUI)
        return -1;

    // Only show the Progress UI if the process is taking a significant amount of
    // time where a significant amount of time is defined as .5 seconds after
    // ShowProgressUI is called sProgress is less than 70.
    usleep(500000);

    if (sQuit || sProgressVal > 70.0f)
        return 0;

    char ini_path[PATH_MAX];
    snprintf(ini_path, sizeof(ini_path), "%s.ini", sProgramPath);

    StringTable strings;
    if (ReadStrings(ini_path, &strings) != OK)
        return -1;

    sWin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    if (!sWin)
        return -1;

    static GdkPixbuf *pixbuf;
    char icon_path[PATH_MAX];
    snprintf(icon_path, sizeof(icon_path), "%s.png", sProgramPath);

    g_signal_connect(G_OBJECT(sWin), "delete_event",
                     G_CALLBACK(OnDeleteEvent), nullptr);

    gtk_window_set_title(GTK_WINDOW(sWin), strings.title);
    gtk_window_set_type_hint(GTK_WINDOW(sWin), GDK_WINDOW_TYPE_HINT_DIALOG);
    gtk_window_set_position(GTK_WINDOW(sWin), GTK_WIN_POS_CENTER_ALWAYS);
    gtk_window_set_resizable(GTK_WINDOW(sWin), FALSE);
    gtk_window_set_decorated(GTK_WINDOW(sWin), TRUE);
    gtk_window_set_deletable(GTK_WINDOW(sWin),FALSE);
    pixbuf = gdk_pixbuf_new_from_file (icon_path, nullptr);
    gtk_window_set_icon(GTK_WINDOW(sWin), pixbuf);
    g_object_unref(pixbuf);

    GtkWidget *vbox = gtk_vbox_new(TRUE, 6);
    sLabel = gtk_label_new(strings.info);
    gtk_misc_set_alignment(GTK_MISC(sLabel), 0.0f, 0.0f);
    sProgressBar = gtk_progress_bar_new();

    gtk_box_pack_start(GTK_BOX(vbox), sLabel, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), sProgressBar, TRUE, TRUE, 0);

    sTimerID = g_timeout_add(TIMER_INTERVAL, UpdateDialog, nullptr);

    gtk_container_set_border_width(GTK_CONTAINER(sWin), 10);
    gtk_container_add(GTK_CONTAINER(sWin), vbox);
    gtk_widget_show_all(sWin);

    gtk_main();
    return 0;
}

// Called on a background thread
void
QuitProgressUI()
{
    sQuit = TRUE;
}

// Called on a background thread
void
UpdateProgressUI(float progress)
{
    sProgressVal = progress;  // 32-bit writes are atomic
}
#endif  // defined(UNIX) || defined(MACOSX)