1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2020 Joël Krähemann
3 *
4 * This file is part of GSequencer.
5 *
6 * GSequencer is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GSequencer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GSequencer. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <ags/X/ags_online_help_window.h>
21 #include <ags/X/ags_online_help_window_callbacks.h>
22
23 #include <ags/X/ags_ui_provider.h>
24 #include <ags/X/ags_window.h>
25
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include <ags/i18n.h>
30
31 void ags_online_help_window_class_init(AgsOnlineHelpWindowClass *online_help_window);
32 void ags_online_help_window_connectable_interface_init(AgsConnectableInterface *connectable);
33 void ags_online_help_window_init(AgsOnlineHelpWindow *online_help_window);
34
35 void ags_online_help_window_connect(AgsConnectable *connectable);
36 void ags_online_help_window_disconnect(AgsConnectable *connectable);
37
38 gboolean ags_online_help_window_delete_event(GtkWidget *widget, GdkEventAny *event);
39
40 static gpointer ags_online_help_window_parent_class = NULL;
41
42 GType
ags_online_help_window_get_type()43 ags_online_help_window_get_type()
44 {
45 static volatile gsize g_define_type_id__volatile = 0;
46
47 if(g_once_init_enter (&g_define_type_id__volatile)){
48 GType ags_type_online_help_window = 0;
49
50 static const GTypeInfo ags_online_help_window_info = {
51 sizeof (AgsOnlineHelpWindowClass),
52 NULL, /* base_init */
53 NULL, /* base_finalize */
54 (GClassInitFunc) ags_online_help_window_class_init,
55 NULL, /* class_finalize */
56 NULL, /* class_data */
57 sizeof (AgsOnlineHelpWindow),
58 0, /* n_preallocs */
59 (GInstanceInitFunc) ags_online_help_window_init,
60 };
61
62 static const GInterfaceInfo ags_connectable_interface_info = {
63 (GInterfaceInitFunc) ags_online_help_window_connectable_interface_init,
64 NULL, /* interface_finalize */
65 NULL, /* interface_data */
66 };
67
68 ags_type_online_help_window = g_type_register_static(GTK_TYPE_WINDOW,
69 "AgsOnlineHelpWindow", &ags_online_help_window_info,
70 0);
71
72 g_type_add_interface_static(ags_type_online_help_window,
73 AGS_TYPE_CONNECTABLE,
74 &ags_connectable_interface_info);
75
76 g_once_init_leave(&g_define_type_id__volatile, ags_type_online_help_window);
77 }
78
79 return g_define_type_id__volatile;
80 }
81
82 void
ags_online_help_window_class_init(AgsOnlineHelpWindowClass * online_help_window)83 ags_online_help_window_class_init(AgsOnlineHelpWindowClass *online_help_window)
84 {
85 GtkWidgetClass *widget;
86
87 ags_online_help_window_parent_class = g_type_class_peek_parent(online_help_window);
88
89 /* GtkWidgetClass */
90 widget = (GtkWidgetClass *) online_help_window;
91
92 widget->delete_event = ags_online_help_window_delete_event;
93 }
94
95 void
ags_online_help_window_connectable_interface_init(AgsConnectableInterface * connectable)96 ags_online_help_window_connectable_interface_init(AgsConnectableInterface *connectable)
97 {
98 connectable->get_uuid = NULL;
99 connectable->has_resource = NULL;
100
101 connectable->is_ready = NULL;
102 connectable->add_to_registry = NULL;
103 connectable->remove_from_registry = NULL;
104
105 connectable->list_resource = NULL;
106
107 connectable->xml_compose = NULL;
108 connectable->xml_parse = NULL;
109
110 connectable->is_connected = NULL;
111 connectable->connect = ags_online_help_window_connect;
112 connectable->disconnect = ags_online_help_window_disconnect;
113
114 connectable->connect_connection = NULL;
115 connectable->disconnect_connection = NULL;
116 }
117
118 void
ags_online_help_window_init(AgsOnlineHelpWindow * online_help_window)119 ags_online_help_window_init(AgsOnlineHelpWindow *online_help_window)
120 {
121 #if defined(AGS_WITH_WEBKIT)
122 GtkBox *vbox;
123 GtkBox *navigation_hbox;
124 GtkLabel *label;
125
126 gchar *start_filename;
127
128 g_object_set(online_help_window,
129 "title", i18n("online help"),
130 NULL);
131
132 g_object_set(online_help_window,
133 "default-width", 800,
134 "default-height", 600,
135 NULL);
136
137 vbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_VERTICAL,
138 0);
139 gtk_container_add((GtkContainer *) online_help_window,
140 (GtkWidget *) vbox);
141
142 /* navigation */
143 navigation_hbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
144 0);
145 gtk_box_pack_start((GtkBox *) vbox,
146 (GtkWidget *) navigation_hbox,
147 FALSE, FALSE,
148 0);
149
150 online_help_window->home = (GtkButton *) gtk_button_new_from_icon_name("go-home",
151 GTK_ICON_SIZE_BUTTON);
152 gtk_box_pack_start((GtkBox *) navigation_hbox,
153 (GtkWidget *) online_help_window->home,
154 FALSE, FALSE,
155 0);
156
157 online_help_window->prev = (GtkButton *) gtk_button_new_from_icon_name("go-previous",
158 GTK_ICON_SIZE_BUTTON);
159 gtk_box_pack_start((GtkBox *) navigation_hbox,
160 (GtkWidget *) online_help_window->prev,
161 FALSE, FALSE,
162 0);
163
164 online_help_window->next = (GtkButton *) gtk_button_new_from_icon_name("go-next",
165 GTK_ICON_SIZE_BUTTON);
166 gtk_box_pack_start((GtkBox *) navigation_hbox,
167 (GtkWidget *) online_help_window->next,
168 FALSE, FALSE,
169 0);
170
171 label = (GtkLabel *) gtk_label_new(i18n("Place"));
172 gtk_box_pack_start((GtkBox *) navigation_hbox,
173 (GtkWidget *) label,
174 FALSE, FALSE,
175 0);
176
177 online_help_window->location = (GtkEntry *) gtk_entry_new();
178 gtk_box_pack_start((GtkBox *) navigation_hbox,
179 (GtkWidget *) online_help_window->location,
180 FALSE, FALSE,
181 0);
182
183 /* webkit */
184 start_filename = NULL;
185
186 #if defined(AGS_ONLINE_HELP_START_FILENAME)
187 start_filename = g_strdup(AGS_ONLINE_HELP_START_FILENAME);
188 #else
189 if((start_filename = getenv("AGS_ONLINE_HELP_START_FILENAME")) != NULL){
190 start_filename = g_strdup(start_filename);
191 }else{
192 #if defined (AGS_W32API)
193 AgsApplicationContext *application_context;
194
195 gchar *app_dir;
196
197 application_context = ags_application_context_get_instance();
198
199 app_dir = NULL;
200
201 if(strlen(application_context->argv[0]) > strlen("\\gsequencer.exe")){
202 app_dir = g_strndup(application_context->argv[0],
203 strlen(application_context->argv[0]) - strlen("\\gsequencer.exe"));
204 }
205
206 start_filename = g_strdup_printf("%s\\share\\doc\\gsequencer-doc\\html\\index.html",
207 g_get_current_dir());
208
209 if(!g_file_test(start_filename,
210 G_FILE_TEST_IS_REGULAR)){
211 g_free(start_filename);
212
213 if(g_path_is_absolute(app_dir)){
214 start_filename = g_strdup_printf("%s\\%s",
215 app_dir,
216 "\\share\\doc\\gsequencer-doc\\html\\index.html");
217 }else{
218 start_filename = g_strdup_printf("%s\\%s\\%s",
219 g_get_current_dir(),
220 app_dir,
221 "\\share\\doc\\gsequencer-doc\\html\\index.html");
222 }
223 }
224
225 g_free(app_dir);
226 #else
227 #if defined(AGS_WITH_SINGLE_DOCDIR)
228 start_filename = g_strdup_printf("file://%s/user-manual/index.html",
229 DOCDIR);
230 #else
231 start_filename = g_strdup_printf("file://%s/doc/gsequencer-doc/html/index.html",
232 DESTDIR);
233 #endif
234 #endif
235 }
236 #endif /* defined(AGS_ONLINE_HELP_START_FILENAME) */
237
238 online_help_window->web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
239 gtk_box_pack_start((GtkBox *) vbox,
240 GTK_WIDGET(online_help_window->web_view),
241 TRUE, TRUE,
242 0);
243
244 g_signal_connect(GTK_WIDGET(online_help_window->web_view), "load-changed",
245 G_CALLBACK(ags_online_help_window_load_changed), online_help_window);
246
247 online_help_window->start_filename = start_filename;
248
249 webkit_web_view_load_uri(online_help_window->web_view,
250 start_filename);
251 #else
252 #if defined(AGS_WITH_POPPLER)
253 GtkVBox *vbox;
254 GtkGrid *grid;
255
256 GtkAdjustment *vadjustment, *hadjustment;
257 GtkAllocation allocation;
258
259 cairo_t *cr;
260
261 gchar *data;
262 gchar *pdf_filename;
263
264 gsize length;
265 gint num_pages, i;
266 gdouble width, height;
267 gint max_width, max_height;
268
269 GError *error;
270
271 g_object_set(online_help_window,
272 "title", i18n("online help"),
273 NULL);
274
275 width = 800.0;
276 height = 600.0;
277
278 g_object_set(online_help_window,
279 "default-width", (gint) width,
280 "default-height", (gint) height,
281 NULL);
282
283 vbox = (GtkVBox *) gtk_vbox_new(FALSE,
284 0);
285 gtk_container_add((GtkContainer *) online_help_window,
286 (GtkWidget *) vbox);
287
288 grid = gtk_grid_new();
289 gtk_box_pack_start((GtkBox *) vbox,
290 (GtkWidget *) grid,
291 TRUE, TRUE,
292 0);
293
294 online_help_window->pdf_drawing_area = (GtkDrawingArea *) gtk_drawing_area_new();
295 gtk_widget_set_vexpand(online_help_window->pdf_drawing_area,
296 TRUE);
297 gtk_widget_set_hexpand(online_help_window->pdf_drawing_area,
298 TRUE);
299
300 gtk_grid_attach(grid,
301 (GtkWidget *) online_help_window->pdf_drawing_area,
302 0, 0,
303 1, 1);
304
305 vadjustment = gtk_adjustment_new(0.0, 0.0, 1.0, 0.1, 0.2, 1.0);
306
307 online_help_window->pdf_vscrollbar = gtk_vscrollbar_new(vadjustment);
308 gtk_grid_attach(grid,
309 (GtkWidget *) online_help_window->pdf_vscrollbar,
310 1, 0,
311 1, 1);
312
313 hadjustment = gtk_adjustment_new(0.0, 0.0, 1.0, 0.1, 0.2, 1.0);
314
315 online_help_window->pdf_hscrollbar = gtk_hscrollbar_new(hadjustment);
316 gtk_grid_attach(grid,
317 (GtkWidget *) online_help_window->pdf_hscrollbar,
318 0, 1,
319 1, 1);
320
321 #ifdef AGS_ONLINE_HELP_PDF_FILENAME
322 pdf_filename = g_strdup(AGS_ONLINE_HELP_PDF_FILENAME);
323 #else
324 if((pdf_filename = getenv("AGS_ONLINE_HELP_PDF_FILENAME")) != NULL){
325 pdf_filename = g_strdup(pdf_filename);
326 }else{
327 #if defined (AGS_W32API)
328 AgsApplicationContext *application_context;
329
330 gchar *app_dir;
331
332 application_context = ags_application_context_get_instance();
333
334 app_dir = NULL;
335
336 if(strlen(application_context->argv[0]) > strlen("\\gsequencer.exe")){
337 app_dir = g_strndup(application_context->argv[0],
338 strlen(application_context->argv[0]) - strlen("\\gsequencer.exe"));
339 }
340
341 pdf_filename = g_strdup_printf("%s\\share\\doc\\gsequencer-doc\\pdf\\ags-user-manual.pdf",
342 g_get_current_dir());
343
344 if(!g_file_test(pdf_filename,
345 G_FILE_TEST_IS_REGULAR)){
346 g_free(pdf_filename);
347
348 if(g_path_is_absolute(app_dir)){
349 pdf_filename = g_strdup_printf("%s\\%s",
350 app_dir,
351 "\\share\\doc\\gsequencer-doc\\pdf\\ags-user-manual.pdf");
352 }else{
353 pdf_filename = g_strdup_printf("%s\\%s\\%s",
354 g_get_current_dir(),
355 app_dir,
356 "\\share\\doc\\gsequencer-doc\\pdf\\ags-user-manual.pdf");
357 }
358 }
359
360 g_free(app_dir);
361 #else
362 pdf_filename = g_strdup_printf("%s%s", DOCDIR, "/pdf/user-manual.pdf");
363 #endif
364 }
365 #endif
366
367 error = NULL;
368 g_file_get_contents(pdf_filename,
369 &data,
370 &length,
371 &error);
372
373 error = NULL;
374 online_help_window->pdf_document = poppler_document_new_from_data(data,
375 length,
376 NULL,
377 &error);
378
379 num_pages = poppler_document_get_n_pages(online_help_window->pdf_document);
380
381 max_width = 0;
382 max_height = 0;
383
384 for(i = 0; i < num_pages; i++){
385 PopplerPage *page;
386
387 page = poppler_document_get_page(online_help_window->pdf_document,
388 i);
389
390 if(page == NULL) {
391 g_warning("poppler fail: page not found");
392
393 break;
394 }
395
396 poppler_page_get_size(page,
397 &width, &height);
398
399 if(max_width < width){
400 max_width = width;
401 }
402
403 max_height += height;
404
405 g_object_unref(page);
406 }
407
408 online_help_window->max_height = max_height;
409 online_help_window->max_width = max_width;
410
411 gtk_widget_get_allocation(online_help_window->pdf_drawing_area,
412 &allocation);
413
414 gtk_adjustment_configure(vadjustment,
415 0.0,
416 0.0,
417 (double) online_help_window->max_height - (double) allocation.height,
418 5.0,
419 15.0,
420 (double) 10.0);
421
422 gtk_adjustment_configure(hadjustment,
423 0.0,
424 0.0,
425 (double) online_help_window->max_width - (double) allocation.width,
426 5.0,
427 15.0,
428 (double) 100.0);
429 #endif
430 #endif
431 }
432
433 void
ags_online_help_window_connect(AgsConnectable * connectable)434 ags_online_help_window_connect(AgsConnectable *connectable)
435 {
436 AgsOnlineHelpWindow *online_help_window;
437
438 online_help_window = AGS_ONLINE_HELP_WINDOW(connectable);
439
440 if((AGS_ONLINE_HELP_WINDOW_CONNECTED & (online_help_window->flags)) != 0){
441 return;
442 }
443
444 online_help_window->flags |= AGS_ONLINE_HELP_WINDOW_CONNECTED;
445
446 #if defined(AGS_WITH_WEBKIT)
447 g_signal_connect(G_OBJECT(online_help_window->home), "clicked",
448 G_CALLBACK(ags_online_help_window_home_callback), online_help_window);
449
450 g_signal_connect(G_OBJECT(online_help_window->next), "clicked",
451 G_CALLBACK(ags_online_help_window_next_callback), online_help_window);
452
453 g_signal_connect(G_OBJECT(online_help_window->prev), "clicked",
454 G_CALLBACK(ags_online_help_window_prev_callback), online_help_window);
455 #else
456 #if defined(AGS_WITH_POPPLER)
457 g_signal_connect_after(G_OBJECT(online_help_window->pdf_drawing_area), "draw",
458 G_CALLBACK(ags_online_help_window_pdf_drawing_area_draw_callback), online_help_window);
459
460 g_signal_connect_after(G_OBJECT(online_help_window->pdf_drawing_area), "configure-event",
461 G_CALLBACK(ags_online_help_window_pdf_drawing_area_configure_callback), online_help_window);
462
463 g_signal_connect_after(G_OBJECT(online_help_window->pdf_vscrollbar), "value-changed",
464 G_CALLBACK(ags_online_help_window_pdf_vscrollbar_value_changed_callback), online_help_window);
465
466 g_signal_connect_after(G_OBJECT(online_help_window->pdf_hscrollbar), "value-changed",
467 G_CALLBACK(ags_online_help_window_pdf_hscrollbar_value_changed_callback), online_help_window);
468 #endif
469 #endif
470 }
471
472 void
ags_online_help_window_disconnect(AgsConnectable * connectable)473 ags_online_help_window_disconnect(AgsConnectable *connectable)
474 {
475 AgsOnlineHelpWindow *online_help_window;
476
477 online_help_window = AGS_ONLINE_HELP_WINDOW(connectable);
478
479 if((AGS_ONLINE_HELP_WINDOW_CONNECTED & (online_help_window->flags)) == 0){
480 return;
481 }
482
483 online_help_window->flags &= (~AGS_ONLINE_HELP_WINDOW_CONNECTED);
484
485 #if defined(AGS_WITH_WEBKIT)
486 g_object_disconnect(G_OBJECT(online_help_window->home),
487 "any_signal::clicked",
488 G_CALLBACK(ags_online_help_window_home_callback),
489 online_help_window,
490 NULL);
491
492 g_object_disconnect(G_OBJECT(online_help_window->next),
493 "any_signal::clicked",
494 G_CALLBACK(ags_online_help_window_next_callback),
495 online_help_window,
496 NULL);
497
498 g_object_disconnect(G_OBJECT(online_help_window->prev),
499 "any_signal::clicked",
500 G_CALLBACK(ags_online_help_window_prev_callback),
501 online_help_window,
502 NULL);
503 #else
504 #if defined(AGS_WITH_POPPLER)
505 g_object_disconnect(G_OBJECT(online_help_window->pdf_drawing_area),
506 "any_signal::draw",
507 G_CALLBACK(ags_online_help_window_pdf_drawing_area_draw_callback),
508 online_help_window,
509 "any_signal::configure-event",
510 G_CALLBACK(ags_online_help_window_pdf_drawing_area_configure_callback),
511 online_help_window,
512 NULL);
513
514 g_object_disconnect(G_OBJECT(online_help_window->pdf_vscrollbar),
515 "value-changed",
516 G_CALLBACK(ags_online_help_window_pdf_vscrollbar_value_changed_callback),
517 online_help_window,
518 NULL);
519
520 g_object_disconnect(G_OBJECT(online_help_window->pdf_hscrollbar),
521 "value-changed",
522 G_CALLBACK(ags_online_help_window_pdf_hscrollbar_value_changed_callback),
523 online_help_window,
524 NULL);
525 #endif
526 #endif
527 }
528
529 gboolean
ags_online_help_window_delete_event(GtkWidget * widget,GdkEventAny * event)530 ags_online_help_window_delete_event(GtkWidget *widget, GdkEventAny *event)
531 {
532 gtk_widget_hide(widget);
533
534 return(TRUE);
535 }
536
537 /**
538 * ags_online_help_window_new:
539 *
540 * Creates an #AgsOnlineHelpWindow
541 *
542 * Returns: a new #AgsOnlineHelpWindow
543 *
544 * Since: 3.5.0
545 */
546 AgsOnlineHelpWindow*
ags_online_help_window_new()547 ags_online_help_window_new()
548 {
549 AgsOnlineHelpWindow *online_help_window;
550
551 online_help_window = (AgsOnlineHelpWindow *) g_object_new(AGS_TYPE_ONLINE_HELP_WINDOW,
552 NULL);
553
554 return(online_help_window);
555 }
556