1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2 
3 /* AbiWord
4  * Copyright (C) 1998 AbiSource, Inc.
5  * Copyright (C) Robert Staudinger <robsta@stereolyzer.net>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  * 02110-1301 USA.
21  */
22 
23 
24 #include <stdlib.h>
25 #include <string.h>
26 #include <gtk/gtk.h>
27 
28 #include "ut_string.h"
29 #include "ut_assert.h"
30 #include "ut_debugmsg.h"
31 #include "xap_UnixDialogHelper.h"
32 #include "xap_GtkSignalBlocker.h"
33 
34 #include "xap_Dialog_Id.h"
35 #include "xap_UnixApp.h"
36 #include "xap_Frame.h"
37 
38 #include "ap_Strings.h"
39 #include "ap_Dialog_Id.h"
40 #include "ap_Dialog_Goto.h"
41 #include "ap_UnixDialog_Goto.h"
42 
43 #include "GTKCommon.h"
44 
45 
AP_UnixDialog_Goto__onSwitchPage(GtkNotebook * notebook,gpointer Page,guint page,gpointer data)46 static void AP_UnixDialog_Goto__onSwitchPage (GtkNotebook *notebook,
47 											  gpointer Page,
48 											  guint page,
49 											  gpointer data)
50 {
51 	UT_UNUSED(notebook);
52 	UT_UNUSED(Page);
53 	UT_DEBUGMSG(("_onSwitchPage() '%d'\n", page));
54 
55 	if (page == 0)
56 	{
57 		AP_UnixDialog_Goto *dlg = static_cast<AP_UnixDialog_Goto *>(data);
58 		dlg->updatePosition();
59 	}
60 }
61 
62 /*!
63 * Event dispatcher for spinbutton "page".
64 */
65 gboolean
AP_UnixDialog_Goto__onFocusPage(GtkWidget *,GdkEventFocus * event,gpointer data)66 AP_UnixDialog_Goto__onFocusPage (GtkWidget 		  * /*widget*/,
67 								 GdkEventFocus    *event,
68 								 gpointer 		  data)
69 {
70 	UT_DEBUGMSG (("ROB: _onFocusPage () '%d', '%d'\n", event->type, event->in));
71 	if (event->type == GDK_FOCUS_CHANGE && event->in) {
72 		AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
73 		dlg->updateCache (AP_JUMPTARGET_PAGE);
74 	}
75 	/* propagate further */
76 	return FALSE;
77 }
78 
79 /*!
80 * Event dispatcher for spinbutton "line".
81 */
82 gboolean
AP_UnixDialog_Goto__onFocusLine(GtkWidget *,GdkEventFocus * event,gpointer data)83 AP_UnixDialog_Goto__onFocusLine (GtkWidget 		  * /*widget*/,
84 								 GdkEventFocus    *event,
85 								 gpointer 		  data)
86 {
87 	UT_DEBUGMSG (("ROB: _onFocusLine () '%d', '%d'\n", event->type, event->in));
88 	if (event->type == GDK_FOCUS_CHANGE && event->in) {
89 		AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
90 		dlg->updateCache (AP_JUMPTARGET_LINE);
91 	}
92 	/* propagate further */
93 	return FALSE;
94 }
95 
96 /*!
97 * Event dispatcher for treeview "bookmarks".
98 */
99 gboolean
AP_UnixDialog_Goto__onFocusBookmarks(GtkWidget *,GdkEventFocus * event,gpointer data)100 AP_UnixDialog_Goto__onFocusBookmarks (GtkWidget 	   * /*widget*/,
101 									  GdkEventFocus    *event,
102 									  gpointer 		   data)
103 {
104 	UT_DEBUGMSG (("ROB: _onFocusBookmarks () '%d', '%d'\n", event->type, event->in));
105 	if (event->type == GDK_FOCUS_CHANGE && event->in) {
106 		AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
107 		dlg->updateCache (AP_JUMPTARGET_BOOKMARK);
108 	}
109 	/* propagate further */
110 	return FALSE;
111 }
112 gboolean
AP_UnixDialog_Goto__onFocusXMLIDs(GtkWidget *,GdkEventFocus * event,gpointer data)113 AP_UnixDialog_Goto__onFocusXMLIDs (GtkWidget 	   * /*widget*/,
114 									  GdkEventFocus    *event,
115 									  gpointer 		   data)
116 {
117 	UT_DEBUGMSG (("MIQ: _onFocusXMLIDs () '%d', '%d'\n", event->type, event->in));
118 	if (event->type == GDK_FOCUS_CHANGE && event->in)
119     {
120 		AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
121 		dlg->updateCache (AP_JUMPTARGET_XMLID);
122 	}
123 	/* propagate further */
124 	return FALSE;
125 }
126 gboolean
AP_UnixDialog_Goto__onFocusAnno(GtkWidget *,GdkEventFocus * event,gpointer data)127 AP_UnixDialog_Goto__onFocusAnno (GtkWidget 	   * /*widget*/,
128                                  GdkEventFocus    *event,
129                                  gpointer 		   data)
130 {
131 	UT_DEBUGMSG (("MIQ: _onFocusAnno () '%d', '%d'\n", event->type, event->in));
132 	if (event->type == GDK_FOCUS_CHANGE && event->in)
133     {
134 		AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
135 		dlg->updateCache (AP_JUMPTARGET_ANNOTATION);
136 	}
137 	/* propagate further */
138 	return FALSE;
139 }
140 
141 /*!
142 * Event dispatcher for spinbutton "page".
143 */
144 void
AP_UnixDialog_Goto__onPageChanged(GtkSpinButton *,gpointer data)145 AP_UnixDialog_Goto__onPageChanged (GtkSpinButton * /*spinbutton*/,
146 								   gpointer 	  data)
147 {
148 	AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
149 	dlg->onPageChanged ();
150 }
151 
152 /*!
153 * Event dispatcher for spinbutton "line".
154 */
155 void
AP_UnixDialog_Goto__onLineChanged(GtkSpinButton *,gpointer data)156 AP_UnixDialog_Goto__onLineChanged (GtkSpinButton * /*spinbutton*/,
157 								   gpointer 	  data)
158 {
159 	AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
160 	dlg->onLineChanged ();
161 }
162 
163 /*!
164 * Event dispatcher for treeview "bookmarks".
165 */
166 void
AP_UnixDialog_Goto__onBookmarkDblClicked(GtkTreeView *,GtkTreePath *,GtkTreeViewColumn *,gpointer data)167 AP_UnixDialog_Goto__onBookmarkDblClicked (GtkTreeView       * /*tree*/,
168 										  GtkTreePath       * /*path*/,
169 										  GtkTreeViewColumn * /*col*/,
170 										  gpointer		    data)
171 {
172 	AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
173 	dlg->onBookmarkDblClicked ();
174 }
175 void
AP_UnixDialog_Goto__onXMLIDDblClicked(GtkTreeView *,GtkTreePath *,GtkTreeViewColumn *,gpointer data)176 AP_UnixDialog_Goto__onXMLIDDblClicked (GtkTreeView       * /*tree*/,
177                                        GtkTreePath       * /*path*/,
178                                        GtkTreeViewColumn * /*col*/,
179                                        gpointer		    data)
180 {
181 	AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
182 	dlg->onXMLIDDblClicked ();
183 }
184 void
AP_UnixDialog_Goto__onAnnoDblClicked(GtkTreeView *,GtkTreePath *,GtkTreeViewColumn *,gpointer data)185 AP_UnixDialog_Goto__onAnnoDblClicked (GtkTreeView       * /*tree*/,
186                                       GtkTreePath       * /*path*/,
187                                       GtkTreeViewColumn * /*col*/,
188                                       gpointer		    data)
189 {
190 	AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
191 	dlg->onAnnoDblClicked ();
192 }
193 
194 /*!
195 * Event dispatcher for button "jump".
196 */
197 void
AP_UnixDialog_Goto__onJumpClicked(GtkButton *,gpointer data)198 AP_UnixDialog_Goto__onJumpClicked (GtkButton * /*button*/,
199 								   gpointer   data)
200 {
201 	AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
202 	dlg->onJumpClicked ();
203 }
204 
205 /*!
206 * Event dispatcher for button "prev".
207 */
208 void
AP_UnixDialog_Goto__onPrevClicked(GtkButton *,gpointer data)209 AP_UnixDialog_Goto__onPrevClicked (GtkButton * /*button*/,
210 								   gpointer   data)
211 {
212 	AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
213 	dlg->onPrevClicked ();
214 }
215 
216 /*!
217 * Event dispatcher for button "next".
218 */
219 void
AP_UnixDialog_Goto__onNextClicked(GtkButton *,gpointer data)220 AP_UnixDialog_Goto__onNextClicked (GtkButton * /*button*/,
221 								   gpointer   data)
222 {
223 	AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
224 	dlg->onNextClicked ();
225 }
226 
227 /*!
228 * Event dispatcher for button "close".
229 */
230 void
AP_UnixDialog_Goto__onDialogResponse(GtkDialog *,gint response,gpointer data)231 AP_UnixDialog_Goto__onDialogResponse (GtkDialog * /*dialog*/,
232 									  gint 		response,
233 									  gpointer  data)
234 {
235 	AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
236 	if (response == GTK_RESPONSE_CLOSE) {
237 		dlg->destroy ();
238 	}
239 }
240 
241 /*!
242 * Event dispatcher for window.
243 */
244 gboolean
AP_UnixDialog_Goto__onDeleteWindow(GtkWidget *,GdkEvent *,gpointer data)245 AP_UnixDialog_Goto__onDeleteWindow (GtkWidget * /*widget*/,
246 									GdkEvent  * /*event*/,
247 									gpointer  data)
248 {
249 	AP_UnixDialog_Goto *dlg = static_cast <AP_UnixDialog_Goto *>(data);
250 	if (dlg->getWindow ()) {
251 		dlg->destroy ();
252 	}
253 	return TRUE;
254 }
255 
256 
257 
258 /*!
259 * Static ctor.
260 */
261 XAP_Dialog *
static_constructor(XAP_DialogFactory * pFactory,XAP_Dialog_Id id)262 AP_UnixDialog_Goto::static_constructor(XAP_DialogFactory *pFactory,
263 									   XAP_Dialog_Id 	 id)
264 {
265 	AP_UnixDialog_Goto *dlg = new AP_UnixDialog_Goto (pFactory, id);
266 	return dlg;
267 }
268 
269 /*!
270 * Ctor.
271 */
AP_UnixDialog_Goto(XAP_DialogFactory * pDlgFactory,XAP_Dialog_Id id)272 AP_UnixDialog_Goto::AP_UnixDialog_Goto(XAP_DialogFactory *pDlgFactory,
273 									   XAP_Dialog_Id 	 id)
274 	: AP_Dialog_Goto   (pDlgFactory, id),
275 	  m_wDialog 	   (NULL),
276 	  m_nbNotebook	   (NULL),
277 	  m_lbPage		   (NULL),
278 	  m_lbLine		   (NULL),
279 	  m_lbBookmarks    (NULL),
280 	  m_lbXMLids	   (NULL),
281 	  m_lbAnnotations  (NULL),
282 	  m_sbPage		   (NULL),
283 	  m_sbLine		   (NULL),
284 	  m_lvBookmarks	   (NULL),
285 	  m_btJump		   (NULL),
286 	  m_btPrev		   (NULL),
287 	  m_btNext		   (NULL),
288       m_lvXMLIDs       (0),
289       m_lvAnno         (0),
290 	  m_btClose 	   (NULL),
291 	  m_iPageConnect (0),
292 	  m_iLineConnect (0),
293 	  m_JumpTarget	   (AP_JUMPTARGET_BOOKMARK)
294 {
295 }
296 
297 /*!
298 * Dtor.
299 */
~AP_UnixDialog_Goto()300 AP_UnixDialog_Goto::~AP_UnixDialog_Goto ()
301 {
302 	UT_DEBUGMSG (("ROB: ~AP_UnixDialog_Goto ()\n"));
303 }
304 
305 
306 
307 /*!
308 * Event handler for spinbutton "page".
309 */
310 void
onPageChanged()311 AP_UnixDialog_Goto::onPageChanged ()
312 {
313 	UT_DEBUGMSG (("ROB: onPageChanged () maxpage='%d'\n", m_DocCount.page));
314 	m_JumpTarget = AP_JUMPTARGET_PAGE;
315 	UT_uint32 page = (UT_uint32)gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_sbPage));
316 	if (page > m_DocCount.page) {
317 		gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbPage), 1);
318 	}
319 	onJumpClicked();
320 }
321 
322 /*!
323 * Event handler for spinbutton "line".
324 */
325 void
onLineChanged()326 AP_UnixDialog_Goto::onLineChanged ()
327 {
328 	UT_DEBUGMSG (("ROB: onLineChanged () maxline='%d'\n", m_DocCount.line));
329 	m_JumpTarget = AP_JUMPTARGET_LINE;
330 	UT_uint32 line = (UT_uint32)gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_sbLine));
331 	if (line > m_DocCount.line) {
332 		gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbLine), 1);
333 	}
334 	if (line == 0) {
335 		gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbLine), m_DocCount.line);
336 	}
337 	onJumpClicked();
338 }
339 
340 /*!
341 * Event handler for treeview "bookmarks".
342 */
343 void
onBookmarkDblClicked()344 AP_UnixDialog_Goto::onBookmarkDblClicked ()
345 {
346 	m_JumpTarget = AP_JUMPTARGET_BOOKMARK;
347 	onJumpClicked();
348 }
349 void
onXMLIDDblClicked()350 AP_UnixDialog_Goto::onXMLIDDblClicked ()
351 {
352 	m_JumpTarget = AP_JUMPTARGET_XMLID;
353 	onJumpClicked();
354 }
355 void
onAnnoDblClicked()356 AP_UnixDialog_Goto::onAnnoDblClicked ()
357 {
358 	m_JumpTarget = AP_JUMPTARGET_ANNOTATION;
359 	onJumpClicked();
360 }
361 
362 /*!
363 * Event handler for button "jump".
364 */
365 void
onJumpClicked()366 AP_UnixDialog_Goto::onJumpClicked ()
367 {
368     std::string text;
369     XAP_GtkSignalBlocker b(G_OBJECT(m_sbLine), m_iLineConnect);
370 
371 	switch (m_JumpTarget) {
372 		case AP_JUMPTARGET_PAGE:
373 			gtk_spin_button_set_value(GTK_SPIN_BUTTON(m_sbLine), 0);
374 			text = tostr(GTK_ENTRY (m_sbPage));
375 			break;
376 		case AP_JUMPTARGET_LINE:
377 			text = tostr(GTK_ENTRY (m_sbLine));
378 			if (text == "0") return;
379 			break;
380 		case AP_JUMPTARGET_BOOKMARK:
381 			text = _getSelectedBookmarkLabel ();
382 			break;
383 		case AP_JUMPTARGET_XMLID:
384 			text = _getSelectedXMLIDLabel();
385 			break;
386 		case AP_JUMPTARGET_ANNOTATION:
387 			text = _getSelectedAnnotationLabel();
388 			break;
389 		default:
390 			UT_DEBUGMSG (("AP_UnixDialog_Goto::onJumpClicked () no jump target\n"));
391 			return;
392 			// UT_ASSERT_NOT_REACHED ();
393 	}
394 
395 	if (text.empty())
396 		return;
397 
398 	performGoto(m_JumpTarget, text.c_str());
399 }
400 
401 /*!
402 * Event handler for button "prev".
403 */
404 void
onPrevClicked()405 AP_UnixDialog_Goto::onPrevClicked ()
406 {
407 	UT_DEBUGMSG (("ROB: onPrevClicked () '%d'\n", m_JumpTarget));
408 
409 	UT_uint32 num = 0;
410 	switch (m_JumpTarget) {
411 		case AP_JUMPTARGET_PAGE:
412 			num = (UT_uint32)gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_sbPage));
413 			if (num == 1)
414 				num = m_DocCount.page;
415 			else
416 				num--;
417 			gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbPage), num);
418 			break;
419 		case AP_JUMPTARGET_LINE:
420 			num = (UT_uint32)gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_sbLine));
421 			if (num == 1)
422 				num = m_DocCount.line;
423 			else
424 				num--;
425 			gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbLine), num);
426 			break;
427 		case AP_JUMPTARGET_BOOKMARK:
428 			_selectPrevBookmark ();
429 			break;
430 		case AP_JUMPTARGET_XMLID:
431             selectPrev(GTK_TREE_VIEW (m_lvXMLIDs));
432 			break;
433 		case AP_JUMPTARGET_ANNOTATION:
434             selectPrev(GTK_TREE_VIEW (m_lvAnno));
435 			break;
436 		default:
437 			UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::onPrevClicked () no jump target\n"));
438 			return;
439 			// UT_ASSERT_NOT_REACHED ();
440 	}
441 
442 	onJumpClicked ();
443 }
444 
445 /*!
446 * Event handler for button "next".
447 */
448 void
onNextClicked()449 AP_UnixDialog_Goto::onNextClicked ()
450 {
451 	UT_DEBUGMSG (("ROB: onNextClicked () '%d'\n", m_JumpTarget));
452 
453 	UT_uint32 num = 0;
454 	switch (m_JumpTarget) {
455 		case AP_JUMPTARGET_PAGE:
456 			num = (UT_uint32)gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_sbPage));
457 			num++;
458 			gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbPage), num);
459 			break;
460 		case AP_JUMPTARGET_LINE:
461 			num = (UT_uint32)gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_sbLine));
462 			num++;
463 			gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbLine), num);
464 			break;
465 		case AP_JUMPTARGET_BOOKMARK:
466 			_selectNextBookmark ();
467 			break;
468 		case AP_JUMPTARGET_XMLID:
469             selectNext(GTK_TREE_VIEW (m_lvXMLIDs));
470 			break;
471 		case AP_JUMPTARGET_ANNOTATION:
472             selectNext(GTK_TREE_VIEW (m_lvAnno));
473 			break;
474 		default:
475 			UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::onNextClicked () no jump target\n"));
476 			return;
477 			// UT_ASSERT_NOT_REACHED ();
478 	}
479 
480 	onJumpClicked ();
481 }
482 
483 /*!
484 * Set jump target and update cached data like number of lines and pages.
485 * @see ap_types.h
486 */
487 void
updateCache(AP_JumpTarget target)488 AP_UnixDialog_Goto::updateCache (AP_JumpTarget target)
489 {
490 	m_JumpTarget = target;
491 	updateDocCount ();
492 }
493 
494 /*!
495 * Update cached data like number of lines and pages.
496 */
497 void
updateDocCount()498 AP_UnixDialog_Goto::updateDocCount ()
499 {
500 	m_DocCount = getView()->countWords(false);
501 	UT_DEBUGMSG (("ROB: updateCache () page='%d' line='%d'\n", m_DocCount.page, m_DocCount.line));
502 }
503 
updatePosition(void)504 void AP_UnixDialog_Goto::updatePosition (void)
505 {
506 	// pages, page increment of 10 is pretty arbitrary (set in the GtkBuilder UI file)
507 	UT_uint32 currentPage = getView()->getCurrentPageNumForStatusBar ();
508 	XAP_GtkSignalBlocker b1(G_OBJECT(m_sbPage), m_iPageConnect);
509 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbPage), currentPage);
510 
511 	// lines, line increment of 10 is pretty arbitrary (set in the GtkBuilder UI file)
512 	UT_uint32 currentLine = 0; /* FIXME get current line */
513 	XAP_GtkSignalBlocker b2(G_OBJECT(m_sbLine), m_iLineConnect);
514 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbLine), currentLine);
515 }
516 
517 void
setupXMLIDList(GtkWidget * w)518 AP_UnixDialog_Goto::setupXMLIDList( GtkWidget* w )
519 {
520 	// Liststore and -view
521 	GtkListStore *store = gtk_list_store_new ( NUM_COLUMNS, G_TYPE_STRING );
522 	gtk_tree_view_set_model (GTK_TREE_VIEW (w), GTK_TREE_MODEL (store));
523 	g_object_unref (G_OBJECT (store));
524 
525 	// Column Bookmark
526 	GtkCellRenderer *renderer = NULL;
527 	renderer = gtk_cell_renderer_text_new ();
528 	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (w),
529 												-1, "Name", renderer,
530 												"text", COLUMN_NAME,
531 												NULL);
532 	GtkTreeViewColumn *column = gtk_tree_view_get_column (GTK_TREE_VIEW (w), 0);
533 	gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
534 
535 	g_signal_connect (GTK_TREE_VIEW (w), "focus-in-event",
536 					  G_CALLBACK (AP_UnixDialog_Goto__onFocusXMLIDs), static_cast <gpointer>(this));
537 	g_signal_connect (GTK_TREE_VIEW (w), "row-activated",
538 					  G_CALLBACK (AP_UnixDialog_Goto__onXMLIDDblClicked), static_cast <gpointer>(this));
539 }
540 
541 
542 void
setupAnnotationList(GtkWidget * w)543 AP_UnixDialog_Goto::setupAnnotationList( GtkWidget* w )
544 {
545 	GtkTreeViewColumn *column = NULL;
546 	GtkCellRenderer *renderer = NULL;
547 	// Liststore and -view
548 	GtkListStore *store = gtk_list_store_new ( NUM_ANNO_COLUMNS,
549                                                G_TYPE_INT,
550                                                G_TYPE_STRING, G_TYPE_STRING );
551 	gtk_tree_view_set_model (GTK_TREE_VIEW (w), GTK_TREE_MODEL (store));
552 	g_object_unref (G_OBJECT (store));
553 
554 	// localization
555 	const XAP_StringSet * pSS = m_pApp->getStringSet ();
556 	std::string id, title, author;
557 	pSS->getValueUTF8(AP_STRING_ID_DLG_Goto_Column_ID, id);
558 	pSS->getValueUTF8(AP_STRING_ID_DLG_Goto_Column_Title, title);
559 	pSS->getValueUTF8(AP_STRING_ID_DLG_Goto_Column_Author, author);
560 
561 	renderer = gtk_cell_renderer_text_new ();
562 	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (w),
563 												-1, id.c_str(), renderer,
564 												"text", COLUMN_ANNO_ID,
565 												NULL);
566 	column = gtk_tree_view_get_column (GTK_TREE_VIEW (w), COLUMN_ANNO_ID );
567 	gtk_tree_view_column_set_sort_column_id (column, COLUMN_ANNO_ID );
568 
569 	renderer = gtk_cell_renderer_text_new ();
570 	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (w),
571 												-1, title.c_str(), renderer,
572 												"text", COLUMN_ANNO_TITLE,
573 												NULL);
574 	column = gtk_tree_view_get_column (GTK_TREE_VIEW (w), COLUMN_ANNO_TITLE );
575 	gtk_tree_view_column_set_sort_column_id (column, COLUMN_ANNO_TITLE );
576 
577 
578 	renderer = gtk_cell_renderer_text_new ();
579 	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (w),
580 												-1, author.c_str(), renderer,
581 												"text", COLUMN_ANNO_AUTHOR,
582 												NULL);
583 	column = gtk_tree_view_get_column (GTK_TREE_VIEW (w), COLUMN_ANNO_AUTHOR );
584 	gtk_tree_view_column_set_sort_column_id (column, COLUMN_ANNO_AUTHOR );
585 
586 
587 
588 	g_signal_connect (GTK_TREE_VIEW (w), "focus-in-event",
589 					  G_CALLBACK (AP_UnixDialog_Goto__onFocusAnno), static_cast <gpointer>(this));
590 	g_signal_connect (GTK_TREE_VIEW (w), "row-activated",
591 					  G_CALLBACK (AP_UnixDialog_Goto__onAnnoDblClicked), static_cast <gpointer>(this));
592 }
593 
594 
595 /*!
596 * Build dialog.
597 */
598 void
_constructWindow(XAP_Frame *)599 AP_UnixDialog_Goto::_constructWindow (XAP_Frame * /*pFrame*/)
600 {
601 	UT_DEBUGMSG (("ROB: _constructWindow ()\n"));
602 
603 	// load the dialog from the UI file
604 #if GTK_CHECK_VERSION(3,0,0)
605 	GtkBuilder* builder = newDialogBuilder("ap_UnixDialog_Goto.ui");
606 #else
607 	GtkBuilder* builder = newDialogBuilder("ap_UnixDialog_Goto-2.ui");
608 #endif
609 
610 	m_wDialog = GTK_WIDGET(gtk_builder_get_object(builder, "ap_UnixDialog_Goto"));
611 	m_nbNotebook = GTK_WIDGET(gtk_builder_get_object(builder, "nbNotebook"));
612 	m_lbPage = GTK_WIDGET(gtk_builder_get_object(builder, "lbPage"));
613 	m_lbLine = GTK_WIDGET(gtk_builder_get_object(builder, "lbLine"));
614 	m_lbBookmarks = GTK_WIDGET(gtk_builder_get_object(builder, "lbBookmarks"));
615 	m_lbXMLids = GTK_WIDGET(gtk_builder_get_object(builder, "lbXMLids"));
616 	m_lbAnnotations = GTK_WIDGET(gtk_builder_get_object(builder, "lbAnnotations"));
617 	m_sbPage = GTK_WIDGET(gtk_builder_get_object(builder, "sbPage"));
618 	m_sbLine = GTK_WIDGET(gtk_builder_get_object(builder, "sbLine"));
619 	m_lvBookmarks = GTK_WIDGET(gtk_builder_get_object(builder, "lvBookmarks"));
620 	m_btJump = GTK_WIDGET(gtk_builder_get_object(builder, "btJump"));
621 	m_btPrev = GTK_WIDGET(gtk_builder_get_object(builder, "btPrev"));
622 	m_btNext = GTK_WIDGET(gtk_builder_get_object(builder, "btNext"));
623 	m_lvXMLIDs = GTK_WIDGET(gtk_builder_get_object(builder, "lvXMLIDs"));
624 	m_lvAnno   = GTK_WIDGET(gtk_builder_get_object(builder, "lvAnno"));
625 	m_btClose = GTK_WIDGET(gtk_builder_get_object(builder, "btClose"));
626 
627 
628 	// localise
629 	const XAP_StringSet * pSS = m_pApp->getStringSet();
630 	localizeLabel(GTK_WIDGET(gtk_builder_get_object(builder, "lbPosition")), pSS, AP_STRING_ID_DLG_Goto_Label_Position);
631 	/* FIXME jump targets localised in xp land, make sure they work for non ascii characters */
632 	const gchar **targets = getJumpTargets ();
633 	const gchar *text = NULL;
634 	if ((text = targets[AP_JUMPTARGET_PAGE]) != NULL)
635 		gtk_label_set_text (GTK_LABEL (m_lbPage), text);
636 	if ((text = targets[AP_JUMPTARGET_LINE]) != NULL)
637 		gtk_label_set_text (GTK_LABEL (m_lbLine), text);
638 	if ((text = targets[AP_JUMPTARGET_BOOKMARK]) != NULL)
639 		gtk_label_set_text (GTK_LABEL (m_lbBookmarks), text);
640 	if ((text = targets[AP_JUMPTARGET_XMLID]) != NULL)
641 		gtk_label_set_text (GTK_LABEL (m_lbXMLids), text);
642 	if ((text = targets[AP_JUMPTARGET_ANNOTATION]) != NULL)
643 		gtk_label_set_text (GTK_LABEL (m_lbAnnotations), text);
644 
645 
646     setupXMLIDList( m_lvXMLIDs );
647     setupAnnotationList( m_lvAnno );
648 
649 	// Liststore and -view
650 	GtkListStore *store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING);
651 	gtk_tree_view_set_model (GTK_TREE_VIEW (m_lvBookmarks), GTK_TREE_MODEL (store));
652 	g_object_unref (G_OBJECT (store));
653 
654 	// Column Bookmark
655 	GtkCellRenderer *renderer = NULL;
656 	renderer = gtk_cell_renderer_text_new ();
657 	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (m_lvBookmarks),
658 												-1, "Name", renderer,
659 												"text", COLUMN_NAME,
660 												NULL);
661 	GtkTreeViewColumn *column = gtk_tree_view_get_column (GTK_TREE_VIEW (m_lvBookmarks), 0);
662 	gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
663 
664 	// Signals
665 	g_signal_connect (GTK_NOTEBOOK (m_nbNotebook), "switch-page",
666 					  G_CALLBACK (AP_UnixDialog_Goto__onSwitchPage), static_cast <gpointer>(this));
667 	g_signal_connect (GTK_SPIN_BUTTON (m_sbPage), "focus-in-event",
668 					  G_CALLBACK (AP_UnixDialog_Goto__onFocusPage), static_cast <gpointer>(this));
669 	m_iPageConnect = g_signal_connect (GTK_SPIN_BUTTON (m_sbPage), "value-changed",
670 					  G_CALLBACK (AP_UnixDialog_Goto__onPageChanged), static_cast <gpointer>(this));
671 
672 	g_signal_connect (GTK_SPIN_BUTTON (m_sbLine), "focus-in-event",
673 					  G_CALLBACK (AP_UnixDialog_Goto__onFocusLine), static_cast <gpointer>(this));
674 	m_iLineConnect = g_signal_connect (GTK_SPIN_BUTTON (m_sbLine), "value-changed",
675 					  G_CALLBACK (AP_UnixDialog_Goto__onLineChanged), static_cast <gpointer>(this));
676 
677 	g_signal_connect (GTK_TREE_VIEW (m_lvBookmarks), "focus-in-event",
678 					  G_CALLBACK (AP_UnixDialog_Goto__onFocusBookmarks), static_cast <gpointer>(this));
679 	g_signal_connect (GTK_TREE_VIEW (m_lvBookmarks), "row-activated",
680 					  G_CALLBACK (AP_UnixDialog_Goto__onBookmarkDblClicked), static_cast <gpointer>(this));
681 
682 	g_signal_connect (GTK_BUTTON (m_btJump), "clicked",
683 					  G_CALLBACK (AP_UnixDialog_Goto__onJumpClicked), static_cast <gpointer>(this));
684 	g_signal_connect (GTK_BUTTON (m_btPrev), "clicked",
685 					  G_CALLBACK (AP_UnixDialog_Goto__onPrevClicked), static_cast <gpointer>(this));
686 	g_signal_connect (GTK_BUTTON (m_btNext), "clicked",
687 					  G_CALLBACK (AP_UnixDialog_Goto__onNextClicked), static_cast <gpointer>(this));
688 
689 	g_signal_connect (GTK_DIALOG (m_wDialog), "response",
690 					  G_CALLBACK (AP_UnixDialog_Goto__onDialogResponse), static_cast <gpointer>(this));
691 	g_signal_connect (m_wDialog, "delete-event",
692 					  G_CALLBACK (AP_UnixDialog_Goto__onDeleteWindow), static_cast <gpointer>(this));
693 
694 	g_object_unref(G_OBJECT(builder));
695 }
696 
697 /*!
698 * Update dialog's data.
699 */
700 void
_updateWindow()701 AP_UnixDialog_Goto::_updateWindow ()
702 {
703 	UT_DEBUGMSG (("ROB: _updateWindow () #bookmarks='%d', mapped='%d'\n", getExistingBookmarksCount(), gtk_widget_get_mapped(m_wDialog)));
704 
705 	ConstructWindowName ();
706 	gtk_window_set_title (GTK_WINDOW (m_wDialog), m_WindowName);
707 
708 	// position: pages and lines
709 	updatePosition();
710 
711 	// bookmarks, detaching model for faster updates
712 	GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (m_lvBookmarks));
713 	g_object_ref (G_OBJECT (model));
714 	gtk_tree_view_set_model (GTK_TREE_VIEW (m_lvBookmarks), NULL);
715 	gtk_list_store_clear (GTK_LIST_STORE (model));
716 
717 	GtkTreeIter iter;
718 	UT_uint32 numBookmarks = getExistingBookmarksCount();
719 	for (UT_uint32 i = 0; i < numBookmarks; i++) {
720 
721 		gtk_list_store_append (GTK_LIST_STORE (model), &iter);
722 		const std::string & name = getNthExistingBookmark(i);
723 		UT_DEBUGMSG (("    ROB: '%s'\n", name.c_str()));
724 		gtk_list_store_set (GTK_LIST_STORE (model), &iter,
725 							COLUMN_NAME, name.c_str(), /*
726 							COLUMN_PAGE, "0",
727 							COLUMN_NUMBER, 0, */
728 							-1);
729 	}
730 	gtk_tree_view_set_model (GTK_TREE_VIEW (m_lvBookmarks), model);
731 	g_object_unref (G_OBJECT (model));
732 
733     updateXMLIDList( m_lvXMLIDs );
734     updateAnnotationList( m_lvAnno );
735 	updateDocCount ();
736 }
737 
738 
739 void
updateXMLIDList(GtkWidget * w)740 AP_UnixDialog_Goto::updateXMLIDList( GtkWidget* w )
741 {
742 	// detaching model for faster updates
743 	GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (w));
744 	g_object_ref (G_OBJECT (model));
745 	gtk_tree_view_set_model (GTK_TREE_VIEW (w), NULL);
746 	gtk_list_store_clear (GTK_LIST_STORE (model));
747 
748     if( PD_DocumentRDFHandle rdf = getRDF() )
749     {
750         GtkTreeIter iter;
751         std::set< std::string > xmlids;
752         rdf->getAllIDs( xmlids );
753         UT_DEBUGMSG (("MIQ: xmlids.sz:%lu\n", (long unsigned)xmlids.size() ));
754 
755         for( std::set< std::string >::iterator xiter = xmlids.begin();
756              xiter != xmlids.end(); ++xiter )
757         {
758             gtk_list_store_append (GTK_LIST_STORE (model), &iter);
759             std::string name = *xiter;
760             UT_DEBUGMSG (("    MIQ: '%s'\n", name.c_str()));
761             gtk_list_store_set (GTK_LIST_STORE (model), &iter,
762                                 COLUMN_NAME, name.c_str(), -1);
763         }
764     }
765 
766 	gtk_tree_view_set_model (GTK_TREE_VIEW (w), model);
767 	g_object_unref (G_OBJECT (model));
768 
769 }
770 
771 
772 void
updateAnnotationList(GtkWidget * w)773 AP_UnixDialog_Goto::updateAnnotationList( GtkWidget* w )
774 {
775 	// detaching model for faster updates
776 	GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (w));
777 	g_object_ref (G_OBJECT (model));
778 	gtk_tree_view_set_model (GTK_TREE_VIEW (w), NULL);
779 	gtk_list_store_clear (GTK_LIST_STORE (model));
780 
781     GtkTreeIter iter;
782     FV_View* pView = getView();
783 	UT_uint32 max = pView->countAnnotations();
784     for( UT_uint32 i=0; i<max; ++i )
785     {
786         gtk_list_store_append (GTK_LIST_STORE (model), &iter);
787         std::string name   = tostr(i);
788         std::string title  = pView->getAnnotationTitle(i);
789         std::string author = pView->getAnnotationAuthor(i);
790 
791         UT_DEBUGMSG (("    MIQ: '%s'\n", name.c_str()));
792         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
793                             COLUMN_ANNO_ID,     i,
794                             COLUMN_ANNO_TITLE,  title.c_str(),
795                             COLUMN_ANNO_AUTHOR, author.c_str(),
796                             -1);
797     }
798 
799 	gtk_tree_view_set_model (GTK_TREE_VIEW (w), model);
800 	g_object_unref (G_OBJECT (model));
801 
802 }
803 
804 
805 
806 void
runModeless(XAP_Frame * pFrame)807 AP_UnixDialog_Goto::runModeless (XAP_Frame * pFrame)
808 {
809 	UT_DEBUGMSG (("ROB: runModeless ()\n"));
810 	_constructWindow (pFrame);
811 	UT_ASSERT (m_wDialog);
812 	_updateWindow ();
813 	abiSetupModelessDialog (GTK_DIALOG (m_wDialog), pFrame, this, GTK_RESPONSE_CLOSE);
814 	gtk_widget_show_all (m_wDialog);
815 	gtk_window_present (GTK_WINDOW (m_wDialog));
816 }
817 
818 void
notifyActiveFrame(XAP_Frame *)819 AP_UnixDialog_Goto::notifyActiveFrame (XAP_Frame * /*pFrame*/)
820 {
821 	UT_DEBUGMSG (("ROB: notifyActiveFrame ()\n"));
822 	UT_ASSERT (m_wDialog);
823 
824 	_updateWindow ();
825 	/* default to page */
826 	m_JumpTarget = AP_JUMPTARGET_PAGE;
827 }
828 
829 void
activate(void)830 AP_UnixDialog_Goto::activate (void)
831 {
832 	UT_ASSERT (m_wDialog);
833 	UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::activate ()\n"));
834 	_updateWindow ();
835 	gtk_window_present (GTK_WINDOW (m_wDialog));
836 }
837 
838 void
destroy()839 AP_UnixDialog_Goto::destroy ()
840 {
841 	UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::destroy ()\n"));
842 	modeless_cleanup ();
843 	if (m_wDialog) {
844 		gtk_widget_destroy (m_wDialog);
845 		m_wDialog = NULL;
846 	}
847 }
848 
849 /**
850 * Try to select the bookmark before the current one.
851 * If none is selected the last in the list is picked.
852 * Wraps around.
853 */
854 void
_selectPrevBookmark()855 AP_UnixDialog_Goto::_selectPrevBookmark ()
856 {
857 	UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::_selectPrevBookmark ()\n"));
858     selectPrev(GTK_TREE_VIEW (m_lvBookmarks));
859 }
860 
861 /**
862 * Try to select the bookmark after the current one.
863 * If none is selected the first in the list is picked.
864 * Wraps around.
865 */
866 void
_selectNextBookmark()867 AP_UnixDialog_Goto::_selectNextBookmark ()
868 {
869 	UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::_selectNextBookmark ()\n"));
870     selectNext(GTK_TREE_VIEW (m_lvBookmarks));
871 }
872 
873 
874 /*!
875 * Get the label of the currently selected bookmark in the list.
876 */
877 std::string
_getSelectedBookmarkLabel()878 AP_UnixDialog_Goto::_getSelectedBookmarkLabel ()
879 {
880 	UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::_getSelectedBookmarkLabel ()\n"));
881     std::string ret = getSelectedText( GTK_TREE_VIEW (m_lvBookmarks), COLUMN_NAME );
882 	return ret;
883 }
884 
885 std::string
_getSelectedXMLIDLabel()886 AP_UnixDialog_Goto::_getSelectedXMLIDLabel()
887 {
888 	UT_DEBUGMSG (("MIQ: AP_UnixDialog_Goto::_getSelectedXMLIDLabel ()\n"));
889     std::string ret = getSelectedText( GTK_TREE_VIEW (m_lvXMLIDs), COLUMN_NAME );
890 	return ret;
891 }
892 
893 std::string
_getSelectedAnnotationLabel()894 AP_UnixDialog_Goto::_getSelectedAnnotationLabel()
895 {
896 	UT_DEBUGMSG (("MIQ: AP_UnixDialog_Goto::_getSelectedAnnotationLabel ()\n"));
897     std::string ret = tostr(getSelectedUInt( GTK_TREE_VIEW (m_lvAnno), COLUMN_ANNO_ID ));
898 	return ret;
899 }
900 
901