/[eiffelstudio]/branches/eth/eve/Src/tools/repository_tool/src/graphical/ctr_logs_tool.e
ViewVC logotype

Contents of /branches/eth/eve/Src/tools/repository_tool/src/graphical/ctr_logs_tool.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 88379 - (show annotations)
Fri Mar 9 09:40:16 2012 UTC (7 years, 7 months ago) by jasonw
File size: 36625 byte(s)
<<Merged from trunk#88377.>>
1 note
2 description: "Summary description for {CTR_LOGS_TOOL}."
3 date: "$Date$"
4 revision: "$Revision$"
5
6 class
7 CTR_LOGS_TOOL
8
9 inherit
10 CTR_TOOL
11 redefine
12 make,
13 focus_widget
14 end
15
16 CTR_SHARED_GUI_PREFERENCES
17
18 EV_SHARED_APPLICATION
19
20 create
21 make
22
23 feature {NONE} -- Initialization
24
25 make (a_name: STRING)
26 do
27 create {ARRAYED_LIST [like current_views.item]} current_views.make (1)
28 Precursor (a_name)
29 end
30
31 build_interface (a_container: EV_CONTAINER)
32 local
33 g: like grid
34 c: like sd_content
35 mtb: SD_TOOL_BAR
36 tbbut: SD_TOOL_BAR_BUTTON
37 tbtoggbut: SD_TOOL_BAR_TOGGLE_BUTTON
38 do
39 create g
40 grid := g
41
42 a_container.extend (g)
43
44 c := sd_content
45 -- g.enable_single_row_selection
46 g.enable_multiple_row_selection
47 g.enable_row_separators
48 g.enable_column_separators
49 g.set_separator_color (grid_separator_color)
50 g.set_column_count_to (4)
51 g.enable_partial_dynamic_content
52 g.set_dynamic_content_function (agent on_logs_compute_grid_item (g, ?,?))
53 g.column (cst_revision_column).set_title ("rev")
54 g.column (cst_author_column).set_title ("author")
55 g.column (cst_log_column).set_title ("message")
56 g.column (cst_date_column).set_title ("date")
57 c.set_short_title ("Logs ...")
58 c.set_long_title ("Logs ...")
59 g.enable_selection_on_single_button_click
60 -- g.disable_selection_on_click
61 g.pointer_button_press_item_actions.extend (agent on_item_pointer_pressed)
62 g.pointer_button_release_item_actions.extend (agent on_item_pointer_released)
63 g.row_select_actions.extend (agent on_log_row_selected)
64 g.pointer_double_press_item_actions.extend (agent on_log_item_double_clicked)
65 create mtb.make
66
67 create tbtoggbut.make
68 tbtoggbut.set_pixmap (icons.new_text_small_toolbar_button_standard_icon ("Filter"))
69 tbtoggbut.select_actions.extend (agent (ai_togg: SD_TOOL_BAR_TOGGLE_BUTTON)
70 do
71 if ai_togg.is_selected then
72 show_search_bar
73 else
74 hide_search_bar
75 end
76 end(tbtoggbut))
77 mtb.extend (tbtoggbut)
78 toggle_search_bar_button := tbtoggbut
79
80 create tbtoggbut.make
81 tbtoggbut.set_pixmap (icons.new_text_small_toolbar_button_standard_icon ("Hide-Read"))
82 tbtoggbut.select_actions.extend (agent (ai_togg: SD_TOOL_BAR_TOGGLE_BUTTON)
83 do
84 if ai_togg.is_selected then
85 add_filter (unread_filter)
86 else
87 remove_filter (unread_filter)
88 end
89 end(tbtoggbut))
90 mtb.extend (tbtoggbut)
91
92 create tbbut.make
93 tbbut.set_pixmap (icons.new_mark_all_read_small_toolbar_button_icon)
94 tbbut.select_actions.extend (agent mark_all_read_logs)
95 mtb.extend (tbbut)
96
97 mtb.extend (create {SD_TOOL_BAR_SEPARATOR}.make)
98
99 create tbbut.make
100 tbbut.set_pixmap (icons.new_check_small_toolbar_button_icon)
101 tbbut.select_actions.extend (agent check_current_repositories)
102 mtb.extend (tbbut)
103
104 mtb.extend (create {SD_TOOL_BAR_SEPARATOR}.make)
105
106 create tbbut.make
107 tbbut.set_pixmap (icons.new_archive_small_toolbar_button_icon)
108 tbbut.select_actions.extend (agent archive_selected_row_logs)
109 mtb.extend (tbbut)
110
111
112 create tbtoggbut.make
113 tbtoggbut.set_pixmap (icons.new_text_small_toolbar_button_standard_icon ("With Archive"))
114 tbtoggbut.select_actions.extend (agent (ai_togg: SD_TOOL_BAR_TOGGLE_BUTTON)
115 do
116 if ai_togg.is_selected then
117 import_archive_logs
118 else
119 reload
120 end
121 end(tbtoggbut))
122 mtb.extend (tbtoggbut)
123
124 -- create tbbut.make
125 -- tbbut.set_pixmap (icons.new_text_small_toolbar_button_standard_icon ("Import archive"))
126 -- tbbut.select_actions.extend (agent import_archive_logs)
127 -- mtb.extend (tbbut)
128
129 create tbbut.make
130 tbbut.set_pixmap (icons.new_remove_small_toolbar_button_icon)
131 tbbut.select_actions.extend (agent delete_selected_row_logs)
132 mtb.extend (tbbut)
133
134 mtb.compute_minimum_size
135 c.set_mini_toolbar (mtb)
136
137 g.key_press_actions.extend (agent on_key_pressed)
138
139 if attached preferences as prefs then
140 if attached prefs.smart_date_kind_pref as p then
141 if attached p.selected_value as p_value then
142 if p_value.same_string ({CTR_DATE_TIME_UTILITY}.smart_date_duration_kind_string) then
143 smart_date_kind := {CTR_DATE_TIME_UTILITY}.smart_date_duration_kind
144 elseif p_value.same_string ({CTR_DATE_TIME_UTILITY}.smart_date_short_kind_string) then
145 smart_date_kind := {CTR_DATE_TIME_UTILITY}.smart_date_short_kind
146 else
147 smart_date_kind := {CTR_DATE_TIME_UTILITY}.smart_date_none_kind
148 end
149 else
150 smart_date_kind := {CTR_DATE_TIME_UTILITY}.smart_date_none_kind
151 end
152 p.change_actions.extend (agent (iap: ARRAY_PREFERENCE)
153 do
154 if attached iap.selected_value as p_value then
155 if p_value.same_string ({CTR_DATE_TIME_UTILITY}.smart_date_duration_kind_string) then
156 smart_date_kind := {CTR_DATE_TIME_UTILITY}.smart_date_duration_kind
157 elseif p_value.same_string ({CTR_DATE_TIME_UTILITY}.smart_date_short_kind_string) then
158 smart_date_kind := {CTR_DATE_TIME_UTILITY}.smart_date_short_kind
159 else
160 smart_date_kind := {CTR_DATE_TIME_UTILITY}.smart_date_none_kind
161 end
162 else
163 smart_date_kind := {CTR_DATE_TIME_UTILITY}.smart_date_none_kind
164 end
165 update
166 end(p))
167 end
168 if attached prefs.date_formatting_pref as p2 then
169 set_date_time_format (p2.value)
170 p2.change_actions.extend (agent (iap: STRING_PREFERENCE)
171 do
172 set_date_time_format (iap.value)
173 end(p2))
174 end
175 if attached prefs.gmt_offset_pref as p3 then
176 set_gmt_offset_with_string (p3.value)
177 p3.change_actions.extend (agent (iap: STRING_PREFERENCE)
178 do
179 set_gmt_offset_with_string (iap.value)
180 end(p3))
181 end
182 end
183 end
184
185 feature -- Access
186
187 focus_widget: detachable EV_WIDGET
188 -- Real widget to focus, when `set_focus' is called
189 do
190 Result := grid
191 end
192
193 current_log: detachable REPOSITORY_LOG
194
195 current_repository: detachable REPOSITORY_DATA
196 do
197 if current_views.count > 0 then
198 Result := current_views.first.repo
199 end
200 end
201
202 current_repositories: LIST [REPOSITORY_DATA]
203 do
204 Result := repositories_from_views (current_views)
205 end
206
207 current_views: LIST [REPOSITORY_DATA_VIEW]
208
209 filter: detachable REPOSITORY_LOG_FILTER
210
211 review_enabled: BOOLEAN
212
213 smart_date_kind: INTEGER
214
215 use_smart_date: BOOLEAN
216 do
217 Result := smart_date_kind /= 0
218 end
219
220 date_time_format: detachable STRING
221
222 gmt_offset: INTEGER
223 gmt_offset_minutes: INTEGER
224
225 grid: ES_GRID
226
227 toggle_search_bar_button: detachable SD_TOOL_BAR_TOGGLE_BUTTON
228
229 feature -- Element change
230
231 set_gmt_offset_with_string (a_offset: STRING)
232 local
233 s: STRING
234 h,m: INTEGER
235 p: INTEGER
236 err: BOOLEAN
237 do
238 a_offset.left_adjust
239 p := a_offset.index_of (':', 1)
240 if p > 0 then
241 s := a_offset.substring (1, p - 1)
242 if s.is_integer then
243 h := s.to_integer
244 else
245 err := True
246 end
247 s := a_offset.substring (p + 1, a_offset.count)
248 if s.is_integer then
249 m := s.to_integer
250 else
251 err := True
252 end
253 if a_offset[1] = '-' then
254 m := -1 * m
255 end
256 else
257 if a_offset.is_integer then
258 h := a_offset.to_integer
259 else
260 err := True
261 end
262 end
263 if err then
264 s := (create {CTR_GMT_OFFSET_UTILITY}).gmt_offset_string
265 console_log_error ("GMT offset value is not valid [" + a_offset + "] => reset to [" + s + "]")
266 if attached (create {CTR_GMT_OFFSET_UTILITY}).gmt_offset as t then
267 h := t.hour
268 m := t.minute
269 if t.negative then
270 h := -1 * h
271 m := -1 * m
272 end
273 else
274 h := 0
275 m := 0
276 end
277 end
278
279 if gmt_offset /= h or gmt_offset_minutes /= m then
280 gmt_offset := h
281 gmt_offset_minutes := m
282 update
283 end
284 end
285
286 set_date_time_format (f: like date_time_format)
287 local
288 s: detachable STRING
289 do
290 if f /= Void then
291 s := f.string
292 s.left_adjust
293 if s.is_empty then
294 s := Void
295 else
296 s := f.string
297 end
298 if s = date_time_format then
299 elseif s /= Void then
300 if attached date_time_format as dtf and then s.same_string (dtf) then
301 -- do nothing
302 else
303 date_time_format := s
304 update
305 end
306 else
307 date_time_format := Void
308 update
309 end
310 end
311 end
312
313 add_filter (f: REPOSITORY_LOG_FILTER)
314 local
315 o_filter: like filter
316 grp: REPOSITORY_LOG_GROUP_FILTER
317 do
318 o_filter := filter
319 if o_filter = Void then
320 filter := f
321 elseif attached {REPOSITORY_LOG_GROUP_FILTER} o_filter as g then
322 g.add_filter (f)
323 else
324 create grp.make (2)
325 grp.add_filter (o_filter)
326 grp.add_filter (f)
327 filter := f
328 end
329 if o_filter /= filter then
330 custom_update (False)
331 end
332 end
333
334 remove_filter (f: REPOSITORY_LOG_FILTER)
335 local
336 o_filter: like filter
337 do
338 o_filter := filter
339 if o_filter = Void then
340 -- do nothing
341 elseif attached {REPOSITORY_LOG_GROUP_FILTER} o_filter as g then
342 g.remove_filter (f)
343 elseif o_filter = f then
344 filter := Void
345 end
346 if o_filter /= filter then
347 custom_update (False)
348 end
349 end
350
351 reload
352 do
353 if attached current_repositories as reps then
354 across
355 reps as c
356 loop
357 c.item.reload_logs
358 end
359 end
360 update
361 end
362
363 update
364 do
365 custom_update (True)
366 end
367
368 custom_update (a_reload: BOOLEAN)
369 local
370 g: like grid
371 l_sorted_logs: ARRAYED_LIST [REPOSITORY_LOG]
372 l_sorter: like log_sorter
373 l_filter: detachable REPOSITORY_LOG_FILTER
374 lst: like current_views
375 n,r: INTEGER
376 rdata: REPOSITORY_DATA
377 plst: ARRAYED_LIST [REPOSITORY_DATA]
378 prev: detachable REPOSITORY_LOG
379 do
380 if review_enabled then
381 show_review_bar
382 else
383 hide_review_bar
384 end
385 g := grid
386 g.set_row_count_to (0)
387 lst := current_views
388 if lst.count > 0 then
389 create plst.make (lst.count)
390 from lst.start until lst.after loop
391 rdata := lst.item.repo
392 if not plst.has (rdata) then
393 plst.force (rdata)
394 if a_reload then
395 rdata.load_logs
396 end
397 n := n + rdata.logs.count
398 end
399 lst.forth
400 end
401 if n > 0 then
402 create l_sorted_logs.make (n)
403 from lst.start until lst.after loop
404 rdata := lst.item.repo
405 if attached rdata.logs as l_logs then
406 l_filter := lst.item.filter
407 -- debug
408 -- create {REPOSITORY_LOG_PATH_FILTER} l_filter.make ("/trunk/Src/C")
409 -- create {REPOSITORY_LOG_AUTHOR_FILTER} l_filter.make ("jfiat")
410 -- end
411
412 across
413 l_logs as c
414 loop
415 n := n - 1
416 if l_filter /= Void then
417 if l_filter.matched (c.item) then
418 l_sorted_logs.force (c.item)
419 end
420 else
421 l_sorted_logs.force (c.item)
422 end
423 end
424 end
425 lst.forth
426 end
427 check n = 0 end
428 if l_sorted_logs.count > 0 then
429 l_sorter := log_sorter
430 l_sorter.reverse_sort (l_sorted_logs)
431 l_filter := filter
432 from l_sorted_logs.start until l_sorted_logs.after loop
433 if attached l_sorted_logs.item as l_log then
434 if l_log = prev then --| remove duplicates
435 l_sorted_logs.remove
436 else
437 if l_filter /= Void then
438 if l_filter.matched (l_log) then
439 l_sorted_logs.forth
440 else
441 l_sorted_logs.remove
442 end
443 else
444 l_sorted_logs.forth
445 end
446 end
447 prev := l_log
448 else
449 l_sorted_logs.remove
450 end
451 end
452 n := l_sorted_logs.count
453 if n > 0 then
454 g.insert_new_rows (n, 1)
455
456 from
457 r := 1
458 l_sorted_logs.start
459 until
460 l_sorted_logs.after
461 loop
462 if attached l_sorted_logs.item as l_log then
463 -- g.insert_new_row (g.row_count + 1)
464 -- l_row := g.row (g.row_count)
465 g.row (r).set_data (l_log)
466 r := r + 1
467 end
468 l_sorted_logs.forth
469 end
470 end
471 end
472 end
473 end
474 sd_content.set_long_title (grid.row_count.out + " logs")
475 end
476
477 reset
478 do
479 current_log := Void
480 if attached repository_colors as h then
481 h.wipe_out
482 end
483 filter := Void
484 hide_search_bar
485 end
486
487 same_views (r1, r2: like current_views): BOOLEAN
488 local
489 bak: like current_views
490 do
491 bak := r1
492 Result := r2.count = bak.count
493 if Result then
494 bak := bak.twin
495 across
496 r2 as c
497 until
498 not bak.has (c.item)
499 loop
500 bak.prune_all (c.item)
501 end
502 Result := bak.count = 0
503 end
504 end
505
506 update_current_repositories (a_data: like current_views)
507 local
508 update_needed: BOOLEAN
509 do
510 if not same_views (current_views, a_data) then
511 update_needed := True
512 current_views.wipe_out
513 if a_data.count > 0 then
514 current_views.fill (a_data)
515 end
516 current_log := Void
517 end
518 if
519 attached repositories_from_views (a_data) as crepos and then
520 crepos.count = 1
521 then
522 review_enabled := crepos.first.review_enabled
523 else
524 review_enabled := False --a_repo /= Void and then a_repo.review_enabled
525 end
526 if update_needed then
527 update
528 end
529 end
530
531 check_current_repositories
532 do
533 if attached ctr_window as w then
534 if attached current_views as rlst and then rlst.count > 0 then
535 across
536 rlst as c
537 loop
538 w.check_repository (c.item.repo)
539 end
540 end
541 end
542 end
543
544 feature -- Search
545
546 search_bar: detachable CTR_LOGS_SEARCH_BOX
547
548 build_search_bar
549 local
550 box: like search_bar
551 do
552 create box.make (Current)
553 search_bar := box
554
555 container.extend (box.widget)
556 container.disable_item_expand (box.widget)
557
558 box.show_hide_actions.extend (agent (b: BOOLEAN)
559 do
560 if attached toggle_search_bar_button as but then
561 but.select_actions.block
562 if b then
563 but.enable_select
564 else
565 but.disable_select
566 end
567 but.select_actions.resume
568 end
569 end
570 )
571 end
572
573 show_search_bar
574 do
575 if search_bar = Void then
576 build_search_bar
577 end
578 if attached search_bar as b then
579 if not b.shown then
580 b.reset
581 end
582 b.show
583 end
584 if attached toggle_search_bar_button as b then
585 b.select_actions.block
586 b.enable_select
587 b.select_actions.resume
588 end
589 end
590
591 hide_search_bar
592 do
593 if attached search_bar as b then
594 b.hide
595 end
596 if attached toggle_search_bar_button as b then
597 b.select_actions.block
598 b.disable_select
599 b.select_actions.resume
600 end
601
602 filter := Void
603 end
604
605 -- toggle_search_bar
606 -- do
607 -- if attached search_bar as b then
608 -- if b.shown then
609 -- hide_search_bar
610 -- else
611 -- show_search_bar
612 -- end
613 -- else
614 -- show_search_bar
615 -- end
616 -- end
617
618 feature -- Review
619
620 review_bar: detachable CTR_LOGS_REVIEW_BOX
621
622 update_review_bar
623 do
624 if attached review_bar as r then
625 r.update_current_log (current_log)
626 end
627 end
628
629 build_review_bar
630 local
631 box: like review_bar
632 do
633 create box.make (Current)
634 review_bar := box
635
636 container.put_front (box.widget)
637 container.disable_item_expand (box.widget)
638 end
639
640 show_review_bar
641 do
642 if review_bar = Void then
643 build_review_bar
644 end
645 if attached review_bar as b then
646 b.reset
647 b.show
648 end
649 end
650
651 hide_review_bar
652 do
653 if attached review_bar as b then
654 b.hide
655 end
656 end
657
658 feature -- Basic operations
659
660 update_log (a_log: REPOSITORY_LOG)
661 local
662 r,n: INTEGER
663 g: like grid
664 l_row: detachable EV_GRID_ROW
665 do
666 g := grid
667 from
668 r := 1
669 n := g.row_count
670 until
671 r > n or l_row /= Void
672 loop
673 l_row := g.row (r)
674 if l_row.data /= a_log then
675 l_row := Void
676 end
677 r := r + 1
678 end
679 if l_row /= Void then
680 compute_row (a_log, l_row)
681 end
682 if a_log = current_log then
683 if attached review_bar as rbar then
684 rbar.update_current_log (a_log)
685 end
686 end
687 end
688
689 feature {CTR_WINDOW} -- Implementation
690
691 repositories_from_views (a_data: like current_views): LIST [REPOSITORY_DATA]
692 do
693 create {ARRAYED_LIST [REPOSITORY_DATA]} Result.make (a_data.count)
694 if a_data.count > 0 then
695 from
696 a_data.start
697 until
698 a_data.after
699 loop
700 if not Result.has (a_data.item.repo) then
701 Result.force (a_data.item.repo)
702 end
703 a_data.forth
704 end
705 end
706 end
707
708 request_update_logs_layout
709 local
710 l_update_logs_layout_action: like update_logs_layout_action
711 do
712 l_update_logs_layout_action := update_logs_layout_action
713 if l_update_logs_layout_action = Void then
714 create l_update_logs_layout_action.make (agent update_logs_layout, 100)
715 update_logs_layout_action := l_update_logs_layout_action
716 end
717 l_update_logs_layout_action.request_call (Void)
718 end
719
720 update_logs_layout_action: detachable EV_DELAYED_ACTION_ARGS [detachable TUPLE]
721
722 update_logs_layout
723 local
724 g: like grid
725 w1, w: INTEGER
726 do
727 if attached update_logs_layout_action as d_act then
728 d_act.cancel_request
729 update_logs_layout_action := Void
730 end
731
732 w1 := 0
733 g := grid
734 if attached g.column (cst_revision_column) as col then
735 col.set_width (col.required_width_of_item_span (1, g.row_count) + 4)
736 w1 := w1 + col.width
737 end
738 if attached g.column (cst_date_column) as col then
739 col.set_width (col.required_width_of_item_span (1, g.row_count) + 4)
740 w1 := w1 + col.width
741 end
742 if attached g.column (cst_author_column) as col then
743 col.set_width (col.required_width_of_item_span (1, g.row_count) + 4)
744 w1 := w1 + col.width
745 end
746 if attached g.column (cst_log_column) as col then
747 w := g.viewable_width
748 col.set_width (w - w1 - g.vertical_scroll_bar.width)
749 end
750 end
751
752 compute_row (a_log: REPOSITORY_LOG; a_row: EV_GRID_ROW)
753 require
754 row_has_log: a_row.data = a_log
755 local
756 glab_buts: EV_GRID_PIXMAPS_ON_RIGHT_LABEL_ITEM
757 gdate_time: EV_GRID_LABEL_ITEM
758 glab: EV_GRID_LABEL_ITEM
759 c: INTEGER
760 stats: like {REPOSITORY_LOG_REVIEW}.stats
761 do
762 if a_log.has_review and then attached a_log.review as l_review then
763 c := 0
764 stats := l_review.stats
765 if stats.approved > 0 then
766 c := c + 1
767 end
768 if stats.refused > 0 then
769 c := c + 1
770 end
771 if stats.question > 0 then
772 c := c + 1
773 end
774 if stats.local_only > 0 then
775 c := c + 1
776 end
777
778 create glab_buts.make_with_text (a_log.id)
779 if stats.approved > stats.refused then
780 glab_buts.set_foreground_color (colors.dark_green)
781 elseif stats.approved < stats.refused then
782 glab_buts.set_foreground_color (colors.dark_red)
783 end
784
785 glab_buts.set_pixmaps_on_right_count (c)
786 if stats.local_only > 0 then
787 glab_buts.put_pixmap_on_right (icons.review_local_only_icon, c)
788 c := c - 1
789 end
790 if stats.approved > 0 then
791 glab_buts.put_pixmap_on_right (icons.review_approved_icon, c)
792 c := c - 1
793 end
794 if stats.refused > 0 then
795 glab_buts.put_pixmap_on_right (icons.review_refused_icon, c)
796 c := c - 1
797 end
798 if stats.question > 0 then
799 glab_buts.put_pixmap_on_right (icons.review_question_icon, c)
800 c := c - 1
801 end
802 a_row.set_item (cst_revision_column, glab_buts)
803 else
804 a_row.set_item (cst_revision_column, create {EV_GRID_LABEL_ITEM}.make_with_text (a_log.id))
805 end
806 if attached smart_token_pixmap (a_log) as p then
807 create glab_buts.make_with_text (a_log.single_line_message)
808 glab := glab_buts
809 glab_buts.set_pixmaps_on_right_count (1)
810 glab_buts.put_pixmap_on_right (p, 1)
811 else
812 create glab.make_with_text (a_log.single_line_message)
813 end
814 a_row.set_item (cst_log_column, glab)
815 a_row.set_item (cst_author_column, create {EV_GRID_LABEL_ITEM}.make_with_text (a_log.author))
816
817 if use_smart_date or date_time_format /= Void then
818 create {CTR_DATE_TIME_GRID_ITEM} gdate_time.make_with_text_and_date (a_log.date, a_log.gmt_date_time, smart_date_kind, date_time_format,
819 gmt_offset, gmt_offset_minutes)
820 else
821 create gdate_time.make_with_text (a_log.date)
822 end
823 a_row.set_item (cst_date_column, gdate_time)
824
825 if current_views.count > 1 then
826 a_row.set_foreground_color (repository_color (a_log.parent))
827 else
828 a_row.set_foreground_color (Void)
829 end
830
831 if a_log.unread then
832 mark_log_unread (a_row)
833 end
834 end
835
836 on_logs_compute_grid_item (g: EV_GRID; c,r: INTEGER): EV_GRID_ITEM
837 local
838 gitem: detachable EV_GRID_ITEM
839 do
840 if attached g.row (r) as l_row then
841 if attached {REPOSITORY_LOG} l_row.data as r_log then
842 compute_row (r_log, l_row)
843 end
844 if l_row.count >= c then
845 gitem := l_row.item (c)
846 end
847 end
848 if gitem /= Void then
849 Result := gitem
850 else
851 create Result
852 g.set_item (c, r, Result)
853 end
854 request_update_logs_layout
855 end
856
857 on_log_row_selected (r: EV_GRID_ROW)
858 local
859 w: like ctr_window
860 do
861 if
862 attached {REPOSITORY_LOG} r.data as rlog
863 then
864 if auto_mark_read then
865 rlog.mark_read
866 mark_log_read (r)
867 end
868 w := ctr_window
869 if w /= Void then
870 w.update_catalog_row_by_data (rlog.parent)
871 end
872 if current_log /= rlog then
873 if grid.selected_rows.count <= 1 then
874 current_log := rlog
875 update_review_bar
876 if w /= Void then
877 w.info_tool.update_current_log (rlog)
878 end
879 else
880 current_log := Void
881 update_review_bar
882 if w /= Void then
883 w.info_tool.update_current_log (Void)
884 end
885 end
886 end
887 end
888 end
889
890 on_key_pressed (a_key: EV_KEY)
891 do
892 inspect a_key.code
893 when {EV_KEY_CONSTANTS}.key_delete then
894 if ev_application.shift_pressed then
895 delete_selected_row_logs
896 end
897 when {EV_KEY_CONSTANTS}.key_a then
898 if ev_application.ctrl_pressed then
899 select_all_rows
900 end
901 when {EV_KEY_CONSTANTS}.key_f then
902 if ev_application.ctrl_pressed then
903 show_search_bar
904 end
905 when {EV_KEY_CONSTANTS}.key_insert then
906 toggle_read_status_on_selected_row_logs (auto_move_to_next_log_direction)
907 when {EV_KEY_CONSTANTS}.key_space then
908 if
909 not ev_application.ctrl_pressed and
910 not ev_application.alt_pressed
911 then
912 set_read_status_on_selected_row_logs (not ev_application.shift_pressed, auto_move_to_next_log_direction)
913 end
914 else
915 end
916 end
917
918 on_item_pointer_released (a_x, a_y, a_but: INTEGER; a_cell: detachable EV_GRID_ITEM)
919 do
920 if a_but = 1 and then a_cell /= Void and then attached a_cell.row as r then
921 on_log_row_selected (r)
922 end
923 end
924
925 on_item_pointer_pressed (a_x, a_y, a_but: INTEGER; a_cell: detachable EV_GRID_ITEM)
926 do
927 if a_cell /= Void and then attached a_cell.row as r and then attached r.parent as g then
928 if a_but = 1 then
929 -- ev_application.add_idle_action_kamikaze (agent on_log_row_selected (r))
930 -- on_log_row_selected (r)
931 else
932 if attached new_row_log_menu (r) as m then
933 m.show_at (g, a_x - g.virtual_x_position, a_y - g.virtual_y_position)
934 end
935 end
936 end
937 end
938
939 new_row_log_menu (r: EV_GRID_ROW): detachable EV_MENU
940 local
941 m: EV_MENU
942 mi: EV_MENU_ITEM
943 mci: EV_CHECK_MENU_ITEM
944 l_username: detachable STRING
945 rev_data: detachable REPOSITORY_LOG_REVIEW
946 user_rev_data: detachable like {REPOSITORY_LOG_REVIEW}.user_review
947 do
948 if attached {REPOSITORY_LOG} r.data as l_log then
949 create m.make_with_text (l_log.id)
950 create mi.make_with_text (l_log.id)
951 mi.disable_sensitive
952 m.extend (mi)
953 m.extend (create {EV_MENU_SEPARATOR})
954 if l_log.parent.review_enabled then
955 if attached l_log.parent.review_username as u then
956 l_username := u
957 end
958
959 create mi.make_with_text ("Review #" + l_log.id)
960 mi.disable_sensitive
961 m.extend (mi)
962
963 if l_log.has_review then
964 rev_data := l_log.review
965 if rev_data /= Void and l_username /= Void then
966 user_rev_data := rev_data.user_review (l_username, Void)
967 end
968 end
969
970 create mci.make_with_text ("Approve")
971 if user_rev_data /= Void and then user_rev_data.is_approved_status then
972 mci.enable_select
973 mci.select_actions.extend (agent (ia_log: REPOSITORY_LOG; ia_rev: detachable REPOSITORY_LOG_REVIEW; ia_usr: detachable STRING)
974 local
975 rev: detachable REPOSITORY_LOG_REVIEW
976 do
977 if ia_usr /= Void then
978 rev := ia_rev
979 if rev = Void then
980 create rev.make
981 end
982 rev.unapprove (ia_usr)
983 ia_log.parent.store_log_review (ia_log, rev)
984 update_log (ia_log)
985 end
986 end(l_log, rev_data, l_username)
987 )
988 else
989 mci.select_actions.extend (agent (ia_log: REPOSITORY_LOG; ia_rev: detachable REPOSITORY_LOG_REVIEW; ia_usr: detachable STRING)
990 local
991 rev: detachable REPOSITORY_LOG_REVIEW
992 do
993 if ia_usr /= Void then
994 rev := ia_rev
995 if rev = Void then
996 create rev.make
997 end
998 rev.approve (ia_usr)
999 ia_log.parent.store_log_review (ia_log, rev)
1000 update_log (ia_log)
1001 end
1002 end(l_log, rev_data, l_username)
1003 )
1004 end
1005 m.extend (mci)
1006 create mci.make_with_text ("Refuse")
1007 if user_rev_data /= Void and then user_rev_data.is_refused_status then
1008 mci.enable_select
1009 mci.select_actions.extend (agent (ia_log: REPOSITORY_LOG; ia_rev: detachable REPOSITORY_LOG_REVIEW; ia_usr: detachable STRING)
1010 local
1011 rev: detachable REPOSITORY_LOG_REVIEW
1012 do
1013 if ia_usr /= Void then
1014 rev := ia_rev
1015 if rev = Void then
1016 create rev.make
1017 end
1018 rev.unrefuse (ia_usr)
1019 ia_log.parent.store_log_review (ia_log, rev)
1020 update_log (ia_log)
1021 end
1022 end(l_log, rev_data, l_username)
1023 )
1024 else
1025 mci.select_actions.extend (agent (ia_log: REPOSITORY_LOG; ia_rev: detachable REPOSITORY_LOG_REVIEW; ia_usr: detachable STRING)
1026 local
1027 rev: detachable REPOSITORY_LOG_REVIEW
1028 do
1029 if ia_usr /= Void then
1030 rev := ia_rev
1031 if rev = Void then
1032 create rev.make
1033 end
1034 rev.refuse (ia_usr)
1035 ia_log.parent.store_log_review (ia_log, rev)
1036 update_log (ia_log)
1037 end
1038 end(l_log, rev_data, l_username)
1039 )
1040 end
1041 m.extend (mci)
1042 create mci.make_with_text ("Comment")
1043 if user_rev_data /= Void and then user_rev_data.is_question_status then
1044 mci.enable_select
1045 end
1046 m.extend (mci)
1047
1048 m.extend (create {EV_MENU_SEPARATOR})
1049 create mi.make_with_text ("Submit Review")
1050 m.extend (mi)
1051 if user_rev_data = Void then
1052 mi.disable_sensitive
1053 elseif not user_rev_data.is_remote then
1054 mi.enable_sensitive
1055 mi.select_actions.extend (agent (ia_log: REPOSITORY_LOG)
1056 do
1057 if
1058 attached ia_log.review as l_review and then
1059 attached ia_log.parent.review_client as l_client
1060 then
1061 l_client.submit (ia_log, l_review)
1062 if l_client.last_error_occurred then
1063 print (l_client.last_error_to_string + "%N")
1064 end
1065 end
1066 end(l_log)
1067 )
1068 end
1069 end
1070
1071 --| Read/delete/...
1072 m.extend (create {EV_MENU_SEPARATOR})
1073 create mci.make_with_text ("Read")
1074 if l_log.unread then
1075 mci.select_actions.extend (agent (ia_r: EV_GRID_ROW; ia_log: REPOSITORY_LOG)
1076 do
1077 mark_log_read (ia_r)
1078 ia_log.mark_read
1079 end(r, l_log))
1080 else
1081 mci.select_actions.extend (agent (ia_r: EV_GRID_ROW; ia_log: REPOSITORY_LOG)
1082 do
1083 mark_log_unread (ia_r)
1084 ia_log.mark_unread
1085 end(r, l_log))
1086 mci.enable_select
1087 end
1088 m.extend (mci)
1089
1090 create mi.make_with_text ("Delete")
1091 mi.select_actions.extend (agent delete_row_log (r, True))
1092 m.extend (mi)
1093
1094 Result := m
1095 end
1096 end
1097
1098 on_log_item_double_clicked (a_x, a_y, a_but: INTEGER; a_cell: detachable EV_GRID_ITEM)
1099 do
1100 if a_cell /= Void and then attached a_cell.row as r then
1101 show_log_diff_from_row (r)
1102 end
1103 end
1104
1105 show_log_diff_from_row (r: EV_GRID_ROW)
1106 do
1107 if attached {REPOSITORY_LOG} r.data as l_log then
1108 if current_log /= l_log then
1109 on_log_row_selected (r)
1110 end
1111 if attached ctr_window as w then
1112 w.show_log_diff (l_log)
1113 else
1114 print (l_log.diff)
1115 end
1116 end
1117 end
1118
1119 select_all_rows
1120 local
1121 g: like grid
1122 r,n: INTEGER
1123 do
1124 g := grid
1125 from
1126 r := 1
1127 n := g.row_count
1128 until
1129 r > n
1130 loop
1131 g.row (r).enable_select
1132 r := r + 1
1133 end
1134 end
1135
1136 import_archive_logs
1137 local
1138 s: STRING
1139 do
1140 s := "Import archives"
1141 if attached current_repositories as reps and then reps.count > 1 then
1142 s.append_string (" for multiple repositories")
1143 elseif attached current_repository as crep then
1144 s.append_string (" for [" + crep.repository_location + "]")
1145 end
1146 console_log (s)
1147 if attached current_repositories as reps and then reps.count > 0 then
1148 from
1149 reps.start
1150 until
1151 reps.after
1152 loop
1153 if attached reps.item as rep then
1154 rep.import_archive_logs
1155 end
1156 reps.forth
1157 end
1158 end
1159 update
1160 update_info_tool
1161 end
1162
1163 archive_selected_row_logs
1164 local
1165 s: STRING
1166 do
1167 if attached grid.selected_rows as l_rows and then l_rows.count > 0 then
1168 s := "Archiving " + l_rows.count.out + " entries"
1169 if attached current_repositories as reps and then reps.count > 1 then
1170 s.append_string (" from multiple repositories")
1171 elseif attached current_repository as crep then
1172 s.append_string (" from [" + crep.repository_location + "]")
1173 end
1174 console_log (s)
1175
1176 across
1177 l_rows as c
1178 loop
1179 if attached {REPOSITORY_LOG} c.item.data as l_log then
1180 c.item.disable_select
1181 l_log.archive
1182 c.item.hide
1183 end
1184 end
1185 current_log := Void
1186 update_info_tool
1187 end
1188 end
1189
1190 mark_all_read_logs
1191 local
1192 g: like grid
1193 r,n: INTEGER
1194 w: like ctr_window
1195 plst: detachable ARRAYED_LIST [REPOSITORY_DATA]
1196 do
1197 g := grid
1198 n := g.row_count
1199 if n > 0 then
1200 w := ctr_window
1201 if w /= Void then
1202 create plst.make (repositories_from_views (current_views).count)
1203 end
1204 from
1205 r := 1
1206 until
1207 r > n
1208 loop
1209 if attached {REPOSITORY_LOG} g.row (r).data as l_log then
1210 if l_log.unread then
1211 l_log.mark_read
1212 mark_log_read (g.row (r))
1213 if plst /= Void and then not plst.has (l_log.parent) then
1214 plst.force (l_log.parent)
1215 end
1216 end
1217 end
1218 r := r + 1
1219 end
1220 if w /= Void and plst /= Void and then plst.count > 0 then
1221 across
1222 plst as c
1223 loop
1224 w.update_catalog_row_by_data (c.item)
1225 end
1226 end
1227 end
1228 end
1229
1230 update_info_tool
1231 do
1232 if attached ctr_window as w then
1233 w.info_tool.update_current_repository (current_repository)
1234 end
1235 end
1236
1237 delete_selected_row_logs
1238 do
1239 if attached grid.selected_rows as l_rows and then l_rows.count > 0 then
1240 across
1241 l_rows as c
1242 loop
1243 delete_row_log (c.item, False)
1244 end
1245 current_log := Void
1246 update_info_tool
1247 end
1248 end
1249
1250 delete_row_log (r: EV_GRID_ROW; update_now: BOOLEAN)
1251 do
1252 if attached {REPOSITORY_LOG} r.data as l_log then
1253 r.disable_select
1254 l_log.delete
1255 r.hide
1256 if update_now and current_log = l_log then
1257 current_log := Void
1258 update_info_tool
1259 end
1260 end
1261 end
1262
1263 toggle_read_status_on_selected_row_logs (a_move_to_next_row: INTEGER)
1264 -- Toggle read status on selected rows
1265 -- if `a_move_to_next_row' is +1 and only one selected row, then select following non selected row
1266 -- if `a_move_to_next_row' is -1 and only one selected row, then select previous non selected row
1267 local
1268 w: like ctr_window
1269 g: like grid
1270 i: INTEGER
1271 do
1272 g := grid
1273 if attached g.selected_rows as l_rows and then l_rows.count > 0 then
1274 w := ctr_window
1275 across
1276 l_rows as c
1277 loop
1278 if attached {REPOSITORY_LOG} c.item.data as l_log then
1279 if l_log.unread then
1280 l_log.mark_read
1281 mark_log_read (c.item)
1282 else
1283 l_log.mark_unread
1284 mark_log_unread (c.item)
1285 end
1286 if w /= Void then
1287 w.update_catalog_row_by_data (l_log.parent)
1288 end
1289 end
1290 end
1291 if a_move_to_next_row /= 0 and l_rows.count = 1 then
1292 i := l_rows.first.index + a_move_to_next_row
1293 if 1 <= i and i <= g.row_count then
1294 g.remove_selection
1295 g.select_row (i)
1296 g.row (i).ensure_visible
1297 end
1298 end
1299 end
1300 end
1301
1302 set_read_status_on_selected_row_logs (a_mark_read: BOOLEAN; a_move_to_next_row: INTEGER)
1303 -- Set read status `a_mark_read' on selected rows
1304 -- if `a_move_to_next_row' is +1 and only one selected row, then select following non selected row
1305 -- if `a_move_to_next_row' is -1 and only one selected row, then select previous non selected row
1306 local
1307 w: like ctr_window
1308 g: like grid
1309 i: INTEGER
1310 do
1311 g := grid
1312 if attached g.selected_rows as l_rows and then l_rows.count > 0 then
1313 w := ctr_window
1314 across
1315 l_rows as c
1316 loop
1317 if attached {REPOSITORY_LOG} c.item.data as l_log then
1318 if a_mark_read and l_log.unread then
1319 l_log.mark_read
1320 mark_log_read (c.item)
1321 elseif not a_mark_read and not l_log.unread then
1322 l_log.mark_unread
1323 mark_log_unread (c.item)
1324 end
1325 if w /= Void then
1326 w.update_catalog_row_by_data (l_log.parent)
1327 end
1328 end
1329 end
1330 if a_move_to_next_row /= 0 and l_rows.count = 1 then
1331 i := l_rows.first.index + a_move_to_next_row
1332 if 1 <= i and i <= g.row_count then
1333 g.remove_selection
1334 g.select_row (i)
1335 g.row (i).ensure_visible
1336 end
1337 end
1338 end
1339 end
1340
1341 mark_log_unread (a_row: EV_GRID_ROW)
1342 local
1343 n,c: INTEGER
1344 ft: EV_FONT
1345 do
1346 n := a_row.count
1347 if n > 0 then
1348 ft := font_unread_log
1349 from
1350 c := 1
1351 until
1352 c > n
1353 loop
1354 if attached {EV_GRID_LABEL_ITEM} a_row.item (c) as l_lab then
1355 l_lab.set_font (ft)
1356 end
1357 c := c + 1
1358 end
1359 end
1360 end
1361
1362 mark_log_read (a_row: EV_GRID_ROW)
1363 local
1364 n,c: INTEGER
1365 ft: EV_FONT
1366 do
1367 n := a_row.count
1368 if n > 0 then
1369 ft := font_read_log
1370 from
1371 c := 1
1372 until
1373 c > n
1374 loop
1375 if attached {EV_GRID_LABEL_ITEM} a_row.item (c) as l_lab then
1376 l_lab.set_font (ft)
1377 end
1378 c := c + 1
1379 end
1380 end
1381 end
1382
1383 repository_color (a_data: REPOSITORY_DATA): detachable EV_COLOR
1384 require
1385 current_views.count > 1
1386 local
1387 h: like repository_colors
1388 do
1389 h := repository_colors
1390 if h = Void then
1391 create h.make (current_views.count)
1392 repository_colors := h
1393 end
1394 if h.has_key (a_data) then
1395 Result := h.found_item
1396 else
1397 inspect
1398 h.count
1399 when 1 then Result := colors.blue
1400 when 2 then Result := colors.red
1401 when 3 then Result := colors.green
1402 when 4 then Result := colors.magenta
1403 when 5 then Result := colors.cyan
1404 else Result := colors.black
1405 end
1406 h.force (Result, a_data)
1407 end
1408 end
1409
1410 repository_colors: detachable HASH_TABLE [EV_COLOR, REPOSITORY_DATA]
1411
1412 feature {NONE} -- Implementation: smart token
1413
1414 smart_token_handler: detachable CTR_SMART_TOKEN_HANDLER
1415 -- Smart token handler
1416
1417 smart_token_pixmap (a_log: REPOSITORY_LOG): detachable EV_PIXMAP
1418 local
1419 hdl: like smart_token_handler
1420 do
1421 hdl := smart_token_handler
1422 if hdl = Void then
1423 create hdl
1424 smart_token_handler := hdl
1425 end
1426 if
1427 attached hdl.smart_token_occurrences (a_log, "bug", a_log.parent.tokens_keys) as ht and then
1428 ht.has_key ("bug") and then attached ht.found_item as l_items
1429 then
1430 if l_items.count = 1 then
1431 Result := token_pixmap ("bug", l_items.first)
1432 elseif l_items.count > 1 then
1433 Result := token_pixmap ("bug", l_items.first + "..")
1434 end
1435 end
1436 end
1437
1438 token_pixmap (k,v: STRING): EV_PIXMAP
1439 local
1440 tcols: like token_pixmap_colors
1441 do
1442 tcols := token_pixmap_colors
1443 Result := icons.new_custom_text_grid_icon (k+"#"+v, tcols.tc, tcols.bc, tcols.fc)
1444 end
1445
1446 token_pixmap_colors: TUPLE [tc,bc,fc: EV_COLOR]
1447 local
1448 tc, bc, fc: EV_COLOR
1449 once
1450 create tc.make_with_8_bit_rgb (0, 90, 0)
1451 create bc.make_with_8_bit_rgb (210, 255, 210)
1452 create fc.make_with_8_bit_rgb (0, 0, 210)
1453 Result := [tc,bc,fc]
1454 end
1455
1456 bug_pixmap: EV_PIXMAP
1457 local
1458 tcols: like token_pixmap_colors
1459 once
1460 tcols := token_pixmap_colors
1461 Result := icons.new_custom_text_grid_icon ("bug", tcols.tc, tcols.bc, tcols.fc)
1462 end
1463
1464 feature {NONE} -- Preferences
1465
1466 auto_mark_read: BOOLEAN
1467 do
1468 if attached preferences as p then
1469 Result := p.auto_mark_read_pref.value
1470 else
1471 Result := True
1472 end
1473 end
1474
1475 auto_move_to_next_log_direction: INTEGER
1476 do
1477 if auto_mark_read then
1478 Result := 0
1479 elseif attached preferences as p then
1480 Result := p.auto_move_to_next_log_direction_pref.value
1481 end
1482 end
1483
1484 feature {NONE} -- Constants
1485
1486 unread_filter: REPOSITORY_LOG_READ_STATUS_FILTER
1487 once
1488 create Result.make_read (False)
1489 end
1490
1491 cst_revision_column: INTEGER = 1
1492 cst_date_column: INTEGER = 2
1493 cst_author_column: INTEGER = 3
1494 cst_log_column: INTEGER = 4
1495
1496
1497 end

Properties

Name Value
svn:eol-style native
svn:keywords Author Date ID Revision

  ViewVC Help
Powered by ViewVC 1.1.23