Statistics
| Revision:

root / trunk / client / gui / main.c @ 1913

History | View | Annotate | Download (24.5 KB)

1
/* 
2
    Copyright (C) 2005-2010  Erik van Pienbroek
3

                
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8

                
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13

                
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18

                
19
#include 
20
#include 
21
#include 
22
#include 
23
#include "gui.h"
24
#include "config_gui.h"
25
#include "donate.xpm"
26

                
27
#ifdef HAVE_LIBPEAS
28
#include 
29
#endif
30

                
31
#ifdef DARWIN
32
#include 
33
#endif
34

                
35
#ifdef WIN32
36
#include 
37
#endif
38

                
39
NntpgrabGlue *glue = NULL;
40

                
41
#if GTK_CHECK_VERSION(3,0,0)
42
static GtkApplication *app = NULL;
43
#endif
44

                
45
void debug_initialize(void);
46
void info_initialize(void);
47
void config_initialize(void);
48
void config_gui_initialize(void);
49
void config_display_initialize(void);
50
void queue_initialize(void);
51
void callbacks_initialize(void);
52
void nzb_initialize(void);
53
void connections_initialize(void);
54
void notify_initialize(void);
55
void monitor_initialize(void);
56
void gui_par2_initialize(void);
57
void nzbcreator_initialize(void);
58
void auto_import_initialize(void);
59
void autoshutdown_initialize(void);
60
void gui_plugins_initialize(void);
61
void gui_plugins_cleanup(void);
62

                
63
// auto_import.c
64
void    disable_auto_import(void);
65

                
66
static const char *nzb_file = NULL;
67
static gboolean initialized = FALSE;
68

                
69
G_MODULE_EXPORT void
70
on_btnQuit_clicked(GtkWidget *caller, gpointer data)
71
{
72
    GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
73

                
74
    gtk_widget_hide(windowMain);
75

                
76
#if GTK_CHECK_VERSION(3,0,0)
77
    gtk_application_remove_window(app, GTK_WINDOW(windowMain));
78
#else
79
    gtk_main_quit();
80
#endif
81
}
82

                
83
static void
84
load_auto_load_plugins(void)
85
{
86
    ConfigGUIOpts opts = config_gui_get_opts();
87
    NNTPGrabPluginInfo info;
88
    GList *list;
89

                
90
    list = opts.auto_load_plugins;
91
    while (list) {
92
        char *errmsg = NULL;
93
        const char *plugin_name = list->data;
94

                
95
        if (!nntpgrab_glue_plugins_get_plugin_info(glue, plugin_name, &info) ||
96
            info.is_loaded == TRUE) {
97

                
98
            /* Plugin isn't found or is already loaded. Ignore */
99
            list = g_list_next(list);
100
            continue;
101
        }
102

                
103
        if (!nntpgrab_glue_plugins_load_plugin(glue, plugin_name, &errmsg)) {
104
            GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
105
            char msg[1024];
106

                
107
            memset(&msg, 0, sizeof(msg));
108
            snprintf(msg, sizeof(msg) - 1, _("Unable to load plugin '%s': %s"), plugin_name, errmsg);
109
            nntpgrab_gui_base_dialog_show(windowMain, msg, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK);
110
            g_free(errmsg);
111
        }
112

                
113
        list = g_list_next(list);
114
    }
115
}
116

                
117
static void
118
bring_to_front_cb(void *user_data)
119
{
120
    GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
121

                
122
    gtk_window_deiconify(GTK_WINDOW(windowMain));
123
    gtk_widget_show(windowMain);
124
    gtk_window_present(GTK_WINDOW(windowMain));
125
}
126

                
127
static gboolean
128
register_frontend(void)
129
{
130
    char *errmsg = NULL;
131

                
132
    /* Try to register this NNTPGrab instance */
133
    if (!nntpgrab_utils_register_frontend(do_open_nzb_file, bring_to_front_cb, NULL, &errmsg)) {
134
        /* Find out whether there's already another NNTPGrab frontend active */
135
        ngboolean is_running = FALSE;
136
        char *errmsg2 = NULL;
137
        if (nntpgrab_utils_test_is_frontend_already_running(&is_running, &errmsg2)) {
138
            if (is_running) {
139
                /* Another NNTPGrab frontend is already running, close this instance */
140
                return FALSE;
141
            } else {
142
                /* No NNTPGrab was already running, show the error and continue without IPC support */
143
                GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
144
                nntpgrab_gui_base_dialog_show(windowMain, errmsg, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK);
145
            }
146
        } else {
147
            /* The check failed, show the error and continue without IPC support */
148
            GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
149
            nntpgrab_gui_base_dialog_show(windowMain, errmsg2, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK);
150
            g_free(errmsg2);
151
        }
152
    }
153

                
154
    return TRUE;
155
}
156

                
157
static gboolean
158
initialisation_inside_mainloop(gpointer data)
159
{
160
    GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
161
    GtkWidget *windowConnect = nntpgrab_gui_base_get_widget("windowConnect");
162
    char *errmsg = NULL;
163
    GtkWidget *cmbConnectHostname;
164
    GtkWidget *spinConnectPort;
165
    char *hostname;
166
    int port;
167
    char *warnings = NULL;
168
#if GTK_CHECK_VERSION(2,90,0)
169
    GtkTreeIter iter;
170
    GtkTreeModel *model;
171
#endif
172

                
173
#ifdef WIN32
174
    WORD wVersionRequested;
175
    WSADATA wsaData;
176
    int ret;
177

                
178
    // Initialise Winsock
179
    wVersionRequested = MAKEWORD(2, 2);
180

                
181
    ret = WSAStartup(wVersionRequested, &wsaData);
182
    if (ret != 0) {
183
        /* Tell the user that we could not find a usable */
184
        /* WinSock DLL. */
185
        g_error(_("Winsock could not be initialised"));
186
        return -1;
187
    }
188

                
189
    /* Confirm that the WinSock DLL supports 2.2. */
190
    /* Note that if the DLL supports versions greater */
191
    /* than 2.2 in addition to 2.2, it will still return */
192
    /* 2.2 in wVersion since that is the version we */
193
    /* requested. */
194

                
195
    if (LOBYTE( wsaData.wVersion ) != 2 ||
196
        HIBYTE( wsaData.wVersion ) != 2) {
197
        /* Tell the user that we could not find a usable */
198
        /* WinSock DLL. */
199
        WSACleanup();
200

                
201
        g_error(_("Winsock 2.2 or higher is required for this program"));
202

                
203
        return -1;
204
    }
205
#endif
206

                
207
    gtk_widget_show(windowMain);
208

                
209
#if GTK_CHECK_VERSION(3,0,0)
210
    gtk_application_add_window(app, GTK_WINDOW(windowMain));
211
    gtk_application_remove_window(app, GTK_WINDOW(windowConnect));
212
#endif
213

                
214
    cmbConnectHostname = nntpgrab_gui_base_get_widget("cmbConnectHostname");
215
    spinConnectPort = nntpgrab_gui_base_get_widget("spinConnectPort");
216
    hostname = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(cmbConnectHostname)))));
217
    port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinConnectPort));
218

                
219
    glue = nntpgrab_glue_new();
220

                
221
    if (!nntpgrab_glue_init(glue, NNTPGRAB_GLUE_VERSION, &errmsg)) {
222
        nntpgrab_glue_destroy(glue);
223
        glue = NULL;
224
        g_free(hostname);
225
        g_critical(_("NNTPGrab Initialisation FAILED:\n%s\n"), errmsg);
226
        g_free(errmsg);
227
        g_idle_add((GSourceFunc) gtk_main_quit, NULL);
228
        return FALSE;
229
    }
230

                
231
    if (GPOINTER_TO_INT(data) == 0) {       // Standalone mode
232
        GObject *menuitemKillServer = nntpgrab_gui_base_get_object("menuitemKillServer");
233
        GValue val;
234
        memset(&val, 0, sizeof(val));
235
        g_value_init(&val, G_TYPE_BOOLEAN);
236
        g_value_set_boolean (&val, FALSE);
237
        g_object_set_property(G_OBJECT(menuitemKillServer), "sensitive", &val);
238

                
239
        if (hostname) {
240
            g_free(hostname);
241
            hostname = NULL;
242
        }
243
    }
244

                
245
    if (!nntpgrab_glue_connect(glue, hostname, port, NULL, NULL, FALSE, &errmsg, &warnings)) {
246
        if (warnings) {
247
            GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
248
            nntpgrab_gui_base_dialog_show(windowMain, warnings, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK);
249
            g_free(warnings);
250
        }
251

                
252
        g_free(hostname);
253
        g_critical(_("Unable to connect to NNTPGrab server:\n%s"), errmsg);
254
        g_free(errmsg);
255
        g_idle_add((GSourceFunc) gtk_main_quit, NULL);
256
        return FALSE;
257
    }
258

                
259
    if (warnings) {
260
        GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
261
        nntpgrab_gui_base_dialog_show(windowMain, warnings, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK);
262
        g_free(warnings);
263
    }
264

                
265
    g_free(hostname);
266

                
267
    gtk_widget_destroy(windowConnect);
268

                
269
#if !defined(DARWIN)
270
    if (!register_frontend()) {
271
        /* Another NNTPGrab frontend is already running, close this instance */
272
        g_idle_add((GSourceFunc) gtk_main_quit, NULL);
273
        return FALSE;
274
    }
275
#endif
276

                
277
    debug_initialize();
278
    callbacks_initialize();
279
    config_initialize();
280
    config_display_initialize();
281
#ifndef DARWIN
282
    nzb_initialize();
283
#endif
284
    connections_initialize();
285
    queue_initialize();
286
    notify_initialize();
287
    monitor_initialize();
288
    gui_par2_initialize();
289
    nzbcreator_initialize();
290
    auto_import_initialize();
291
    autoshutdown_initialize();
292
    gui_plugins_initialize();
293

                
294
    /* Load any optional plugins which need to be auto-loaded */
295
    load_auto_load_plugins();
296

                
297
    // Did we receive a NZB file on the command line ?
298
    if (nzb_file) {
299
        do_open_nzb_file(nzb_file, NULL);
300
        nzb_file = NULL;
301
    }
302

                
303
    initialized = TRUE;
304

                
305
    return FALSE;
306
}
307

                
308
G_MODULE_EXPORT void
309
on_btnConnectToServer_clicked(GtkWidget *caller, gpointer data)
310
{
311
    GtkWidget *windowConnect = nntpgrab_gui_base_get_widget("windowConnect");
312

                
313
    // Save the hostname into the GUI Configuration
314
    ConfigGUIOpts opts = config_gui_get_opts();
315
    GtkWidget *cmbConnectHostname = nntpgrab_gui_base_get_widget("cmbConnectHostname");
316
    const char *hostname = gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(cmbConnectHostname))));
317

                
318
    // Have we seen this hostname before ?
319
    if (!strcmp(hostname, opts.hostname1)) {
320
        // No need to do anything, item is already at the top of the list
321
    } else if (!strcmp(hostname, opts.hostname2)) {
322
        // Swap positions
323
        strncpy(opts.hostname2, opts.hostname1, sizeof(opts.hostname2));
324
        strncpy(opts.hostname1, hostname, sizeof(opts.hostname1));
325
    } else if (!strcmp(hostname, opts.hostname3)) {
326
        // Push items 1 and 2 one place down and set the first item to the hostname
327
        strncpy(opts.hostname3, opts.hostname2, sizeof(opts.hostname3));
328
        strncpy(opts.hostname2, opts.hostname1, sizeof(opts.hostname2));
329
        strncpy(opts.hostname1, hostname, sizeof(opts.hostname1));
330
    } else if (!strcmp(hostname, opts.hostname4)) {
331
        strncpy(opts.hostname4, opts.hostname3, sizeof(opts.hostname4));
332
        strncpy(opts.hostname3, opts.hostname2, sizeof(opts.hostname3));
333
        strncpy(opts.hostname2, opts.hostname1, sizeof(opts.hostname2));
334
        strncpy(opts.hostname1, hostname, sizeof(opts.hostname1));
335
    } else if (!strcmp(hostname, opts.hostname5)) {
336
        strncpy(opts.hostname5, opts.hostname4, sizeof(opts.hostname5));
337
        strncpy(opts.hostname4, opts.hostname3, sizeof(opts.hostname4));
338
        strncpy(opts.hostname3, opts.hostname2, sizeof(opts.hostname3));
339
        strncpy(opts.hostname2, opts.hostname1, sizeof(opts.hostname2));
340
        strncpy(opts.hostname1, hostname, sizeof(opts.hostname1));
341
    } else {
342
        // Hostname not seen at all, move all the items one place down (forget
343
        // about the last item) and put the hostname in front
344
        strncpy(opts.hostname5, opts.hostname4, sizeof(opts.hostname5));
345
        strncpy(opts.hostname4, opts.hostname3, sizeof(opts.hostname4));
346
        strncpy(opts.hostname3, opts.hostname2, sizeof(opts.hostname3));
347
        strncpy(opts.hostname2, opts.hostname1, sizeof(opts.hostname2));
348
        strncpy(opts.hostname1, hostname, sizeof(opts.hostname1));
349
    }
350

                
351
    config_gui_set_opts(opts);
352

                
353
    gtk_widget_set_sensitive(windowConnect, FALSE);
354
    g_idle_add(initialisation_inside_mainloop, GINT_TO_POINTER(1));
355
}
356

                
357
G_MODULE_EXPORT void
358
on_btnStartStandalone_clicked(GtkWidget *caller, gpointer data)
359
{
360
    GtkWidget *windowConnect = nntpgrab_gui_base_get_widget("windowConnect");
361

                
362
    gtk_widget_set_sensitive(windowConnect, FALSE);
363
    g_idle_add(initialisation_inside_mainloop, GINT_TO_POINTER(0));
364
}
365

                
366
G_MODULE_EXPORT void
367
on_btnConnectQuit_clicked(GtkWidget *caller, gpointer data)
368
{
369
    GtkWidget *windowConnect = nntpgrab_gui_base_get_widget("windowConnect");
370

                
371
    gtk_widget_destroy(windowConnect);
372

                
373
    gtk_main_quit();
374
}
375

                
376
G_MODULE_EXPORT void
377
on_menuitemManagePlugins_activate(GtkWidget *caller, gpointer data)
378
{
379
    GtkWidget *windowPlugins = nntpgrab_gui_base_get_widget("windowPlugins");
380

                
381
    gtk_window_present(GTK_WINDOW(windowPlugins));
382
}
383

                
384
G_MODULE_EXPORT void
385
on_menuitemKillServer_activate(GtkWidget *caller, gpointer data)
386
{
387
    nntpgrab_glue_kill_server(glue);
388
}
389

                
390
#ifdef _MSC_VER
391
void AppInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line,        uintptr_t pReserved ) {
392
        fprintf(
393
                stderr,
394
                "Invalid parameter detected in function %s. File: %s Line: %d\n",
395
                function,
396
                file,
397
                line
398
        );
399
        fprintf(
400
                stderr,
401
                "Expression: %s\n",
402
                expression
403
        );
404
        // Cause a Debug Breakpoint.
405
        DebugBreak();
406
}
407
#endif
408

                
409
gboolean
410
gui_get_is_initialized()
411
{
412
    return initialized;
413
}
414

                
415
static GtkWidget *
416
create_user_interface(void)
417
{
418
    GtkWidget *btnDonate;
419
    GtkWidget *icon;
420
    GdkPixbuf *pixbuf;
421
    GtkWidget *windowMain;
422
    GtkWidget *windowConnect;
423
    GtkWidget *cmbConnectHostname;
424
    GtkListStore *store;
425
    ConfigGUIOpts opts;
426
    GtkTreeIter iter;
427
#ifdef DARWIN
428
    GtkWidget *quit_menu_widget;
429
#endif
430

                
431
    /* Initialize libxml now to prevent possible race conditions */
432
    xmlInitGlobals();
433
    xmlInitParser();
434

                
435
    nntpgrab_gui_base_create_ui("nntpgrab_gui");
436

                
437
    windowMain = nntpgrab_gui_base_get_widget("windowMain");
438
    windowConnect = nntpgrab_gui_base_get_widget("windowConnect");
439

                
440
#ifdef DARWIN
441
    ige_mac_menu_set_global_key_handler_enabled (TRUE);
442
    ige_mac_menu_connect_window_key_handler (GTK_WINDOW(nntpgrab_gui_base_get_widget("windowMain")));
443

                
444
    quit_menu_widget = gtk_ui_manager_get_widget(GTK_UI_MANAGER(nntpgrab_gui_base_get_object("uimanager1")), "ui/menubar1/menuitem1/imagemenuitem5");
445
    g_warn_if_fail(quit_menu_widget != NULL);
446

                
447
    ige_mac_menu_set_quit_menu_item (GTK_MENU_ITEM (quit_menu_widget));
448

                
449
    ige_mac_menu_set_menu_bar(GTK_MENU_SHELL(nntpgrab_gui_base_get_widget("menubar1")));
450
    gtk_widget_hide(nntpgrab_gui_base_get_widget("menubar1"));
451
#endif
452

                
453
    // Set the donate icon of the window
454
    btnDonate = nntpgrab_gui_base_get_widget("btnDonate");
455
    pixbuf = gdk_pixbuf_new_from_xpm_data((const char **) &donate_xpm);
456
    icon = gtk_image_new_from_pixbuf(pixbuf);
457
    gtk_widget_show(icon);
458
    gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(btnDonate), icon);
459
    g_object_unref(pixbuf);
460

                
461
#ifdef DARWIN
462
    /* Due to the way file associations work on Mac OS X, we need to make 
463
     * sure the NZB dialog can be used before the file association is set up */
464
    nzb_initialize();
465

                
466
    /* And the file assocation needs to be set up as soon as possible.. */
467
    if (!register_frontend()) {
468
        return NULL;
469
    }
470
#endif
471

                
472
    // We need to have the GUI configuration loaded at this point because the
473
    // Network GUI requires data from it
474
    config_gui_initialize();
475

                
476
    opts = config_gui_get_opts();
477

                
478
    if (opts.show_connect_dialog || nntpgrab_utils_test_is_server_already_running()) {
479
        // Show the connect dialog so the user can enter where the NNTPGrab server is running
480
        windowConnect = nntpgrab_gui_base_get_widget("windowConnect");
481
        cmbConnectHostname = nntpgrab_gui_base_get_widget("cmbConnectHostname");
482

                
483
        gtk_widget_show(windowConnect);
484

                
485
        store = gtk_list_store_new(1, G_TYPE_STRING);
486
        gtk_combo_box_set_model(GTK_COMBO_BOX(cmbConnectHostname), GTK_TREE_MODEL(store));
487
#if GTK_CHECK_VERSION(3,0,0)
488
        gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(cmbConnectHostname), 0);
489
#else
490
        gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(cmbConnectHostname), 0);
491
#endif
492

                
493
        if (strlen(opts.hostname1) > 0) {
494
            gtk_list_store_append(store, &iter);
495
            gtk_list_store_set(store, &iter, 0, opts.hostname1, -1);
496
        }
497

                
498
        if (strlen(opts.hostname2) > 0) {
499
            gtk_list_store_append(store, &iter);
500
            gtk_list_store_set(store, &iter, 0, opts.hostname2, -1);
501
        }
502

                
503
        if (strlen(opts.hostname3) > 0) {
504
            gtk_list_store_append(store, &iter);
505
            gtk_list_store_set(store, &iter, 0, opts.hostname3, -1);
506
        }
507

                
508
        if (strlen(opts.hostname4) > 0) {
509
            gtk_list_store_append(store, &iter);
510
            gtk_list_store_set(store, &iter, 0, opts.hostname4, -1);
511
        }
512

                
513
        if (strlen(opts.hostname5) > 0) {
514
            gtk_list_store_append(store, &iter);
515
            gtk_list_store_set(store, &iter, 0, opts.hostname5, -1);
516
        }
517

                
518
        gtk_combo_box_set_active(GTK_COMBO_BOX(cmbConnectHostname), 0);
519

                
520
        if (!opts.show_connect_dialog) {
521
            /* If we got here, the user is running the NNTPGrab Server */
522
            GtkWidget *chkAlwaysStandalone = nntpgrab_gui_base_get_widget("chkAlwaysStandalone");
523
            gtk_widget_hide(chkAlwaysStandalone);
524
        }
525

                
526
        // If the NNTPGrab Server is also running on localhost, disable the 'Standalone' button
527
        if (nntpgrab_utils_test_is_server_already_running()) {
528
            GtkWidget *btnStartStandalone = nntpgrab_gui_base_get_widget("btnStartStandalone");
529
            GtkWidget *btnConnectToServer = nntpgrab_gui_base_get_widget("btnConnectToServer");
530
            gtk_widget_set_sensitive(btnStartStandalone, FALSE);
531
            gtk_widget_set_can_default(btnConnectToServer, TRUE);
532
            gtk_widget_grab_default(btnConnectToServer);
533
        }
534
    } else {
535
        g_idle_add(initialisation_inside_mainloop, GINT_TO_POINTER(0));
536
    }
537

                
538
    /* The update information can already be fetched now */
539
    info_initialize();
540

                
541
    if (opts.show_connect_dialog || nntpgrab_utils_test_is_server_already_running()) {
542
        return windowConnect;
543
    } else {
544
        return windowMain;
545
    }
546
}
547

                
548
#if GTK_CHECK_VERSION(3,0,0)
549
static void
550
activate(GtkApplication *app, gpointer data)
551
{
552
    GList *list;
553
    GtkWidget *window;
554

                
555
    list = gtk_application_get_windows(app);
556
    if (list) {
557
        gtk_widget_show(list->data);
558
        gtk_window_present(GTK_WINDOW(list->data));
559
    } else {
560
        window = create_user_interface();
561
        gtk_window_set_application(GTK_WINDOW(window), app);
562
        gtk_widget_show(window);
563
    }
564
}
565

                
566
static int
567
command_line(GtkApplication *app, GApplicationCommandLine *cmdline, gpointer data)
568
{
569
    char **argv;
570
    int argc;
571
    int i;
572

                
573
    argv = g_application_command_line_get_arguments(cmdline, &argc);
574
    for (i = 1; i < argc; i++) {
575
        if (g_file_test(argv[i], G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
576
            if (!initialized) {
577
                /* No windows found yet, assume were starting up for the first time */
578
                if (nzb_file) {
579
                    g_free((char*)nzb_file);
580
                }
581

                
582
                nzb_file = g_strdup(argv[i]);
583
                break;
584
            } else {
585
                do_open_nzb_file(argv[i], NULL);
586
            }
587
        }
588
    }
589

                
590
    if (!initialized) {
591
        activate(app, data);
592
    }
593

                
594
    return 0;
595
}
596
#endif
597

                
598
int
599
main(int argc, char *argv[])
600
{
601
    int status = 0;
602
    char *errmsg = NULL;
603
    gboolean is_running = FALSE;
604
    int i;
605
#ifdef HAVE_LIBPEAS
606
    PeasEngine *engine;
607
    const char *plugin_dir;
608
#endif
609

                
610
#ifdef WIN32
611
#ifdef _MSC_VER
612
    _set_invalid_parameter_handler(AppInvalidParameterHandler);
613
#else
614
    // exchndl.dll is part of Dr. MinGW. By loading this DLL, every time the
615
    // program crashes a .RPT file will be created containing the backtrace
616
    LoadLibraryA("exchndl.dll");
617
#endif
618
#endif
619

                
620
    g_set_application_name("NNTPGrab");
621
    g_set_prgname("NNTPGrab");
622

                
623
    nntpgrab_utils_perform_base_initialization();
624

                
625
#if GTK_CHECK_VERSION(3,0,0)
626
    app = gtk_application_new("org.NNTPGrab.NNTPGrab.GTK3", G_APPLICATION_HANDLES_COMMAND_LINE);
627

                
628
    g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
629
    g_signal_connect (app, "command-line", G_CALLBACK (command_line), NULL);
630
#else
631
    gtk_init(&argc, &argv);
632
#endif
633

                
634
    /* Is there already another NNTPGrab instance running ? */
635
    if (!nntpgrab_utils_test_is_frontend_already_running(&is_running, &errmsg)) {
636
        /* Unable to check whether NNTPGrab is running */
637
        char *errmsg2 = g_strdup_printf(_("Unable to check whether NNTPGrab is already running:\n%s"), errmsg);
638
        nntpgrab_gui_base_dialog_show(NULL, errmsg2, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK);
639
        g_free(errmsg2);
640
        g_free(errmsg);
641

                
642
        return 1;
643
    }
644

                
645
    if (argc > 1) {
646
        /* We have an extra argument! Probably the location of a NZB file 
647
         * Is one our arguments really a filename ? */
648
        for (i = 1; i < argc; i++) {
649
            char *filename;
650

                
651
            if (!strncmp(argv[i], "--debug", 7)) {
652
                g_setenv("NNTPGRAB_DEBUG", "1", TRUE);
653
            }
654

                
655
#ifdef WIN32
656
            filename = g_convert(argv[i], -1, "utf-8", "windows-1252", NULL, NULL, NULL);
657
#else
658
            filename = g_strdup(argv[i]);
659
#endif
660
            if (g_file_test(filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
661
                nzb_file = g_strdup(filename);
662
            }
663
            g_free(filename);
664
        }
665

                
666
        if (nzb_file) {
667
            /* Is there already another NNTPGrab instance running ? */
668
            if (is_running) {
669
                /* Send a message to that other process and commit suicide */
670
                if (!nntpgrab_utils_send_open_nzb_file_request(nzb_file, &errmsg)) {
671
                    nntpgrab_gui_base_dialog_show(NULL, errmsg, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK);
672
                    g_free(errmsg);
673
                }
674

                
675
                if (!nntpgrab_utils_send_bring_to_front_request(&errmsg)) {
676
                    nntpgrab_gui_base_dialog_show(NULL, errmsg, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK);
677
                    g_free(errmsg);
678
                }
679

                
680
                return 2;
681
            }
682

                
683
            /* Nope, open the NZB Import dialog as soon as we're ready to go 
684
             * This will be done automatically due to the fact that nzb_file is a global variable */
685
        }
686
    }
687

                
688
    if (is_running) {
689
        /* There's already another frontend active. Stop execution of this one */
690
        if (!nntpgrab_utils_send_bring_to_front_request(&errmsg)) {
691
            char *errmsg2 = g_strdup_printf(_("Unable to send 'bring to front' request to already running NNTPGrab instance:\n%s"), errmsg);
692
            nntpgrab_gui_base_dialog_show(NULL, errmsg2, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK);
693
            g_free(errmsg2);
694
            g_free(errmsg);
695
        }
696

                
697
        return 3;
698
    }
699

                
700
#ifdef HAVE_LIBPEAS
701
    engine = peas_engine_get_default ();
702
    if (g_getenv("NNTPGRAB_PLUGINS_GTK_DIR")) {
703
        plugin_dir = g_getenv("NNTPGRAB_PLUGINS_GTK_DIR");
704
    } else {
705
        plugin_dir = PLUGIN_GTK_DIR;
706
    }
707
    peas_engine_add_search_path (engine, plugin_dir, plugin_dir);
708

                
709
    peas_engine_enable_loader(engine, "gjs");
710
    peas_engine_enable_loader(engine, "python");
711
    peas_engine_enable_loader(engine, "seed");
712
#endif
713

                
714
#if GTK_CHECK_VERSION(3,0,0)
715
    status = g_application_run(G_APPLICATION(app), argc, argv);
716

                
717
    g_object_unref(app);
718
#else
719
    if (!create_user_interface()) {
720
        return 4;
721
    }
722

                
723
    /* start the event loop */
724
    gtk_main();
725
#endif
726

                
727
    if (nntpgrab_gui_base_tray_icon_get_is_shown()) {
728
        nntpgrab_gui_base_tray_destroy();
729
    }
730

                
731
    /* Unload the GUI plugins before cleaning up the NNTPGrabGlue */
732
    gui_plugins_cleanup();
733

                
734
    if (glue) {
735
        // Always try to disable the auto import even if it isn't in use
736
        if (initialized) {
737
            disable_auto_import();
738
        }
739

                
740
        nntpgrab_glue_destroy(glue);
741
    }
742

                
743
    if (initialized) {
744
        gtk_widget_destroy(nntpgrab_gui_base_get_widget("windowMain"));
745
        gtk_widget_destroy(nntpgrab_gui_base_get_widget("windowConfig"));
746
        gtk_widget_destroy(nntpgrab_gui_base_get_widget("windowNZB"));
747
        gtk_widget_destroy(nntpgrab_gui_base_get_widget("windowDebug"));
748
        gtk_widget_destroy(nntpgrab_gui_base_get_widget("windowSetCollectionName"));
749
        gtk_widget_destroy(nntpgrab_gui_base_get_widget("windowPlugins"));
750

                
751
        nntpgrab_gui_base_destroy_ui();
752
    }
753

                
754
    return status;
755
}
756

                
757
#ifdef WIN32
758
static HINSTANCE instance = NULL;
759

                
760
HINSTANCE
761
get_hinstance(void)
762
{
763
    return instance;
764
}
765

                
766
int _stdcall
767
WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpszCmdLine, int nCmdShow)
768
{
769
    instance = hInstance;
770
    return main(__argc, __argv);
771
}
772

                
773
#endif