1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 from contextlib import contextmanager
24 import cairo
25 import gobject
26 import gtk
27 import math
28 import os
29 import pango
30 import pangocairo
31 import socket
32 import subprocess
33 import time
34 from constant import (WIDGET_POS_TOP_LEFT, WIDGET_POS_TOP_RIGHT,
35 WIDGET_POS_TOP_CENTER, WIDGET_POS_BOTTOM_LEFT,
36 WIDGET_POS_BOTTOM_CENTER, WIDGET_POS_BOTTOM_RIGHT,
37 WIDGET_POS_LEFT_CENTER, WIDGET_POS_RIGHT_CENTER,
38 WIDGET_POS_CENTER, DEFAULT_FONT, COLOR_NAME_DICT,
39 BLACK_COLOR_MAPPED, WHITE_COLOR_MAPPED, SIMILAR_COLOR_SEQUENCE,
40 DEFAULT_FONT_SIZE)
43 '''
44 Get node count number of TreeView.
45
46 @param treeview: Gtk.TreeView instance.
47 @return: Return number of node.
48
49 Return 0 if treeview haven't model.
50 '''
51 model = treeview.get_model()
52 if model != None:
53 return model.iter_n_children(None)
54 else:
55 return 0
56
58 '''
59 Get selected path of TreeView.
60
61 @param treeview: Gtk.TreeView instance.
62 @return: Return selected path of treeview.
63
64 Return None if haven't any path selected.
65 '''
66 selection = treeview.get_selection()
67 (_, tree_paths) = selection.get_selected_rows()
68 if len(tree_paths) != 0:
69 return (tree_paths[0])[0]
70 else:
71 return None
72
74 '''
75 Focus first toplevel node of TreeView.
76
77 @param treeview: Gtk.TreeView instance.
78 '''
79 treeview.set_cursor((0))
80
93
121
133
135 '''
136 Focus previous toplevel node of TreeView.
137
138 @param treeview: Gtk.TreeView instance.
139 '''
140 selected_path = tree_view_get_selected_path(treeview)
141 if selected_path != None:
142 if selected_path > 0:
143 treeview.set_cursor((selected_path - 1))
144
145 -def get_entry_text(entry):
146 '''
147 Get text of entry.
148
149 @param entry: Gtk.Entry instance.
150 @return: Return text of entry.
151 '''
152 return entry.get_text().split(" ")[0]
153
155 '''
156 Set cursor type with given widget.
157
158 @param cursor_widget: Gtk.Widget or Gdk.Window instance.
159 @param cursor_type: The cursor type of gtk.gdk.Cursor, please set with None if you want reset widget's cursor as default.
160 @return: Always return False
161 '''
162 if isinstance(cursor_widget, gtk.Widget):
163 cursor_window = cursor_widget.window
164 elif isinstance(cursor_widget, gtk.gdk.Window):
165 cursor_window = cursor_widget
166 else:
167 print "set_cursor: impossible!"
168
169 if cursor_type == None:
170 cursor_window.set_cursor(None)
171 else:
172 cursor_window.set_cursor(gtk.gdk.Cursor(cursor_type))
173
174 return False
175
177 '''
178 Show gtk.gdk.HAND2 cursor when mouse hover widget.
179
180 @param widget: Gtk.Widget instance.
181 '''
182 set_hover_cursor(widget, gtk.gdk.HAND2)
183
185 '''
186 Set cursor type when mouse hover widget.
187
188 @param widget: Gtk.Widget instance.
189 @param cursor_type: The cursor type of gtk.gdk.Cursor.
190 '''
191 widget.connect("enter-notify-event", lambda w, e: set_cursor(w, cursor_type))
192 widget.connect("leave-notify-event", lambda w, e: set_cursor(w))
193
250
252 '''
253 Get root coordinate with given event.
254
255 @param event: Gdk.Event instance, general, we get event instance from gtk signal callback.
256 @return: Return (x, y) as event's root coordination.
257 '''
258 (rx, ry) = event.get_root_coords()
259 return (int(rx), int(ry))
260
262 '''
263 Get coordinate with given event.
264
265 @param event: Gdk.Event instance, general, we get event instance from gtk signal callback.
266 @return: Return (x, y) as event's coordination.
267 '''
268 (rx, ry) = event.get_coords()
269 return (int(rx), int(ry))
270
272 '''
273 Propagate expose to children.
274
275 General, this function use at last position of `expose_event` callback to make child redraw after parent widget.
276
277 And you must put \"return True\" after \"propagate_expose(widget, event)\".
278
279 Example:
280
281 >>> def expose_event_callback(widget, event):
282 >>> # Do something.
283 >>>
284 >>> propagate_expose(widget, event)
285 >>> return True
286
287 @param widget: Gtk.Container instance.
288
289 This function do nothing if widget is not Gtk.Container instance or haven't any child widget.
290
291 @param event: Gdk.Event instance.
292 '''
293 if "get_child" in dir(widget) and widget.get_child() != None:
294 widget.propagate_expose(widget.get_child(), event)
295
297 '''
298 Move window with given widget and event.
299
300 This function generic use for move window when mouse drag on target widget.
301
302 @param widget: Gtk.Widget instance to drag.
303 @param event: Gdk.Event instance, generic, event come from gtk signal callback.
304 @param window: Gtk.Window instance.
305 '''
306 if is_left_button(event):
307 window.begin_move_drag(
308 event.button,
309 int(event.x_root),
310 int(event.y_root),
311 event.time)
312
313 return False
314
316 '''
317 Resize window with given widget and event.
318
319 This function generic use for resize window when mouse drag on target widget.
320
321 @param widget: Gtk.Widget instance to drag.
322 @param event: Gdk.Event instance, generic, event come from gtk signal callback.
323 @param window: Gtk.Window instance.
324 '''
325 if is_left_button(event):
326 window.begin_resize_drag(
327 edge,
328 event.button,
329 int(event.x_root),
330 int(event.y_root),
331 event.time)
332
333 return False
334
351
353 '''
354 Whether an event is single click event.
355
356 @param event: gtk.gdk.BUTTON_PRESS event.
357 @return: Return True if event is single click event.
358 '''
359 return event.button == 1 and event.type == gtk.gdk.BUTTON_PRESS
360
362 '''
363 Whether an event is double click event.
364
365 @param event: gtk.gdk.BUTTON_PRESS event.
366 @return: Return True if event is double click event.
367 '''
368 return event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS
369
378
387
396
398 '''
399 Make callback call for all children of widget.
400
401 @param widget: Gtk.Container instance.
402 @param callback: Callback.
403 '''
404 callback(widget)
405
406 if isinstance(widget, gtk.Container):
407 foreach_recursive(widget, callback)
408
410 '''
411 Helper function for L{ I{foreach_container} <foreach_container>}.
412
413 @param container: Gtk.Container instance.
414 @param callback: Callback.
415 '''
416 container.foreach(lambda w: foreach_container(w, callback))
417
419 '''
420 Handy function to remove all children widget from container.
421
422 @param container: Gtk.Container instance.
423 '''
424 container.foreach(lambda widget: container.remove(widget))
425
427 '''
428 Get screen size from the toplevel window associated with widget.
429
430 @param widget: Gtk.Widget instance.
431 @return: Return screen size as (screen_width, screen_height)
432
433 '''
434 screen = widget.get_screen()
435 width = screen.get_width()
436 height = screen.get_height()
437 return (width, height)
438
440 '''
441 Whether target coordinate in given rectangle.
442
443 @param tx: Target x coordinate.
444 @param ty: Target y coordinate.
445 @param x: X coordinate of rectangle area.
446 @param y: X coordinate of rectangle area.
447 @param w: Width of rectangle area.
448 @param h: Height of rectangle area.
449 @return: Return True if target coordinate in given rectangle.
450 '''
451 return (tx >= x and tx <= x + w and ty >= y and ty <= y + h)
452
460
469
470 -def get_content_size(text, text_size=DEFAULT_FONT_SIZE, text_font=DEFAULT_FONT, wrap_width=None):
471 '''
472 Get text size, in pixel.
473
474 @param text: String or markup string.
475 @param text_size: Text size, in pixel.
476 @param text_font: Text font.
477 @param wrap_width: The width of wrap rule, default don't wrap.
478 @return: Return text size as (text_width, text_height), return (0, 0) if occur error.
479 '''
480 if text:
481 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 0, 0)
482 cr = cairo.Context(surface)
483 context = pangocairo.CairoContext(cr)
484 layout = context.create_layout()
485 layout.set_font_description(pango.FontDescription("%s %s" % (text_font, text_size)))
486 layout_set_markup(layout, text)
487 if wrap_width == None:
488 layout.set_single_paragraph_mode(True)
489 else:
490 layout.set_width(wrap_width * pango.SCALE)
491 layout.set_single_paragraph_mode(False)
492 layout.set_wrap(pango.WRAP_WORD)
493
494 return layout.get_pixel_size()
495 else:
496 return (0, 0)
497
499 '''
500 Create directory.
501
502 @param directory: Target directory to create.
503 @param remove_first: If you want remove directory when directory has exist, set it as True.
504 '''
505 if remove_first and os.path.exists(directory):
506 remove_directory(directory)
507
508 if not os.path.exists(directory):
509 os.makedirs(directory)
510
512 '''
513 Remove file if file exist.
514
515 @param path: Target path to remove.
516 '''
517 if os.path.exists(path):
518 os.remove(path)
519
521 """
522 Remove directory recursively, equivalent to command `rm -rf path`.
523
524 @param path: Target directory to remove.
525 """
526 if os.path.exists(path):
527 for i in os.listdir(path):
528 full_path = os.path.join(path, i)
529 if os.path.isdir(full_path):
530 remove_directory(full_path)
531 else:
532 os.remove(full_path)
533 os.rmdir(path)
534
536 '''
537 Touch file, equivalent to command `touch filepath`.
538
539 If filepath's parent directory is not exist, this function will create parent directory first.
540
541 @param filepath: Target path to touch.
542 '''
543
544 dir = os.path.dirname(filepath)
545 if not os.path.exists(dir):
546 os.makedirs(dir)
547
548
549 open(filepath, "w").close()
550
552 '''
553 Read file content.
554
555 @param filepath: Target filepath.
556 @param check_exists: Whether check file is exist, default is False.
557
558 @return: Return \"\" if check_exists is True and filepath not exist.
559
560 Otherwise return file's content.
561 '''
562 if check_exists and not os.path.exists(filepath):
563 return ""
564 else:
565 r_file = open(filepath, "r")
566 content = r_file.read()
567 r_file.close()
568
569 return content
570
572 '''
573 Read first line of file.
574
575 @param filepath: Target filepath.
576 @param check_exists: Whether check file is exist, default is False.
577 @return: Return \"\" if check_exists is True and filepath not exist.
578
579 Otherwise return file's first line.
580 '''
581 if check_exists and not os.path.exists(filepath):
582 return ""
583 else:
584 r_file = open(filepath, "r")
585 content = r_file.readline().split("\n")[0]
586 r_file.close()
587
588 return content
589
591 '''
592 Eval file content.
593
594 @param filepath: Target filepath.
595 @param check_exists: Whether check file is exist, default is False.
596 @return: Return None if check_exists is True and file not exist.
597
598 Return None if occur error when eval file.
599
600 Otherwise return file content as python structure.
601 '''
602 if check_exists and not os.path.exists(filepath):
603 return None
604 else:
605 try:
606 read_file = open(filepath, "r")
607 content = eval(read_file.read())
608 read_file.close()
609
610 return content
611 except Exception, e:
612 print e
613
614 return None
615
617 '''
618 Write file with given content.
619
620 @param filepath: Target filepath to write.
621 @param content: File content to write.
622 '''
623 f = open(filepath, "w")
624 f.write(content)
625 f.close()
626
628 '''
629 Kill process.
630
631 @param proc: Subprocess instance.
632 '''
633 try:
634 if proc != None:
635 proc.kill()
636 except Exception, e:
637 print "kill_process got error: %s" % (e)
638
640 '''
641 Run command and return first line of output.
642
643 @param commands: Input commands.
644 @return: Return first line of command output.
645 '''
646 process = subprocess.Popen(commands, stdout=subprocess.PIPE)
647 process.wait()
648 return process.stdout.readline()
649
651 '''
652 Run command and return output.
653
654 @param commands: Input commands.
655 @return: Return command output.
656 '''
657 process = subprocess.Popen(commands, stdout=subprocess.PIPE)
658 process.wait()
659 return process.stdout.readlines()
660
662 '''
663 Run command silencely.
664
665 @param command: Input command.
666 '''
667 subprocess.Popen("nohup %s > /dev/null 2>&1" % (command), shell=True)
668
670 '''
671 Get OS version with command `lsb_release -i`.
672
673 @return: Return OS version string.
674 '''
675 version_infos = get_command_output_first_line(["lsb_release", "-i"]).split()
676
677 if len(version_infos) > 0:
678 return version_infos[-1]
679 else:
680 return ""
681
683 '''
684 Get current time with given time format.
685
686 @param time_format: Time format, default is %Y-%m-%d %H:%M:%S
687 @return: Return current time with given time format.
688 '''
689 return time.strftime(time_format, time.localtime())
690
692 '''
693 Add element in list, don't add if element has in list.
694
695 @param e_list: List to insert.
696 @param element: Element will insert to list.
697 '''
698 if not element in e_list:
699 e_list.append(element)
700
702 '''
703 Try remove element from list, do nothing if element not in list.
704
705 @param e_list: List to remove.
706 @param element: Element try to remove from list.
707 '''
708 if element in e_list:
709 e_list.remove(element)
710
712 '''
713 Sort list with alpha order.
714
715 @param e_list: List to sort.
716 '''
717 return sorted(e_list, key=lambda e: e)
718
720 '''
721 Get size of given directory.
722
723 @param dirname: Directory path.
724 @return: Return total size of directory.
725 '''
726 total_size = 0
727 for root, dirs, files in os.walk(dirname):
728 for filepath in files:
729 total_size += os.path.getsize(os.path.join(root, filepath))
730
731 return total_size
732
734 '''
735 Print environment variable.
736 '''
737 for param in os.environ.keys():
738 print "*** %20s %s" % (param,os.environ[param])
739
741 '''
742 Print execute time of function.
743
744 @param func: Fucntion name.
745
746 Usage:
747
748 >>> @print_exec_time
749 >>> def function_to_test():
750 >>> ...
751 '''
752 def wrap(*a, **kw):
753 start_time = time.time()
754 ret = func(*a, **kw)
755 print "%s time: %s" % (str(func), time.time() - start_time)
756 return ret
757 return wrap
758
760 '''
761 Get all font families in system.
762
763 @return: Return font families list in current system.
764 '''
765 fontmap = pangocairo.cairo_font_map_get_default()
766 return map (lambda f: f.get_name(), fontmap.list_families())
767
792
794 '''
795 Add color stop as rgba format.
796
797 @param pat: Pattern.
798 @param pos: Stop position.
799 @param color_info: (color, alpha), color is hex value, alpha value range: [0, 1]
800 '''
801
802 (color, alpha) = color_info
803 (r, g, b) = color_hex_to_cairo(color)
804
805 pat.add_color_stop_rgba(pos, r, g, b, alpha)
806
808 '''
809 Convert alpha color (color, alpha) to cairo color (r, g, b, alpha).
810
811 @param color: Hex color.
812 @param alpha: Alpha value.
813 @return: Return cairo value (red, green, blue, alpha).
814 '''
815 (r, g, b) = color_hex_to_cairo(color)
816 return (r, g, b, alpha)
817
819 '''
820 Convert hex color to cairo color (r, g, b).
821
822 @param color: Hex color value.
823 @return: Return cairo value, (red, green, blue)
824 '''
825 if color[0] == '#':
826 color = color[1:]
827 return (int(color[:2], 16), int(color[2:4], 16), int(color[4:], 16))
828
830 """
831 Convert a html (hex) RGB value to cairo color.
832
833 @param color: The color to convert.
834 @return: A color in cairo format, (red, green, blue).
835 """
836 gdk_color = gtk.gdk.color_parse(color)
837 return (gdk_color.red / 65535.0, gdk_color.green / 65535.0, gdk_color.blue / 65535.0)
838
840 '''
841 Convert cairo color to hex color.
842
843 @param rgb_color: (red, green, blue)
844 @return: Return hex color.
845 '''
846 return "#%02X%02X%02X" % rgb_color
847
849 """
850 Convert a 8 bit RGB value to cairo color.
851
852 @type color: a triple of integers between 0 and 255
853 @param color: The color to convert.
854 @return: A color in cairo format.
855 """
856 return (color[0] / 255.0, color[1] / 255.0, color[2] / 255.0)
857
859 '''
860 Get parent widget match given type.
861
862 @param widget: Gtk.Widget instance.
863 @param match_types: A list gtk widget types.
864 @return: Return first parent widget match with given types.
865
866 Return None if nothing match.
867 '''
868 parent = widget.get_parent()
869 if parent == None:
870 return None
871 elif type(parent).__name__ in match_types:
872 return parent
873 else:
874 return get_match_parent(parent, match_types)
875
893
894 -def map_value(value_list, get_value_callback):
895 '''
896 Return value with map list.
897
898 @param value_list: A list to loop.
899 @param get_value_callback: Callback for element in list.
900 @return: Return a new list that every element is result of get_value_callback.
901 '''
902 if value_list == None:
903 return []
904 else:
905 return map(get_value_callback, value_list)
906
919
921 '''
922 Return new list that element is max value between list_a and list_b.
923
924 @param list_a: List a.
925 @param list_b: List b.
926 @return: Return new list that element is max value between two list.
927
928 Return empty list if any input list is empty or two list's length is not same.
929 '''
930 if list_a == []:
931 return list_b
932 elif list_b == []:
933 return list_a
934 elif len(list_a) == len(list_b):
935 result = []
936 for (index, item_a) in enumerate(list_a):
937 if item_a > list_b[index]:
938 result.append(item_a)
939 else:
940 result.append(list_b[index])
941
942 return result
943 else:
944 print "mix_list_max: two list's length not same."
945 return []
946
948 '''
949 Unzip [(1, 'a'), (2, 'b'), (3, 'c')] to ([1, 2, 3], ['a', 'b', 'c']).
950
951 @param unzip_list: List to unzip.
952 @return: Return new unzip list.
953 '''
954 first_list, second_list = zip(*unzip_list)
955 return (list(first_list), list(second_list))
956
958 '''
959 Whether is seriate list.
960
961 @param test_list: Test list.
962 @return: Return True is test list is seriate list.
963 '''
964 for (index, item) in enumerate(test_list):
965 if item != test_list[0] + index:
966 return False
967
968 return True
969
971 '''
972 Get index in disperse list.
973
974 @param disperse_list: Disperse list.
975 @param value: Match value.
976 @return: Return index in disperse list.
977 '''
978 for (index, _) in enumerate(disperse_list):
979 start_value = sum(disperse_list[0:index])
980 end_value = sum(disperse_list[0:index + 1])
981 if start_value <= value < end_value:
982 return (index, value - start_value)
983
984
985 return (last_index(disperse_list), disperse_list[-1])
986
988 '''
989 Whether window is maximized.
990
991 @param widget: Gtk.Widget instance.
992 @return: Return True if widget's toplevel window is maximized.
993 '''
994 toplevel_window = widget.get_toplevel()
995 if toplevel_window.window.get_state() == gtk.gdk.WINDOW_STATE_MAXIMIZED:
996 return True
997 else:
998 return False
999
1001 '''
1002 Return last index of list.
1003
1004 @param test_list: Test list.
1005 @return: Return last index of list.
1006 '''
1007 return len(test_list) - 1
1008
1011 '''
1012 Protected cairo context state for operate cairo safety.
1013
1014 @param cr: Cairo context.
1015 '''
1016 cr.save()
1017 try:
1018 yield
1019 except Exception, e:
1020 print 'with an cairo error %s' % e
1021 else:
1022 cr.restore()
1023
1026 '''
1027 Disable cairo antialias temporary.
1028
1029 @param cr: Cairo context.
1030 '''
1031
1032 antialias = cr.get_antialias()
1033
1034 cr.set_antialias(cairo.ANTIALIAS_NONE)
1035 try:
1036 yield
1037 except Exception, e:
1038 print 'with an cairo error %s' % e
1039 else:
1040
1041 cr.set_antialias(antialias)
1042
1045 '''
1046 Print execute time with given code block.
1047
1048 Usage:
1049
1050 >>> with exec_time():
1051 >>> # Write any code at here.
1052 >>> # ...
1053 '''
1054 start_time = time.time()
1055 try:
1056 yield
1057 except Exception, e:
1058 print 'exec_time error %s' % e
1059 else:
1060 print "time: %f" % (time.time() - start_time)
1061
1063 '''
1064 Remove callback id.
1065
1066 @param callback_id: Callback id.
1067 '''
1068 if callback_id:
1069 gobject.source_remove(callback_id)
1070 callback_id = None
1071
1073 '''
1074 Remove signal id.
1075
1076 @param signal_id: Signal id that return by function gobject.connect.
1077 '''
1078 if signal_id:
1079 (signal_object, signal_handler_id) = signal_id
1080 if signal_object.handler_is_connected(signal_handler_id):
1081 signal_object.disconnect(signal_handler_id)
1082 signal_id = None
1083
1085 '''
1086 Print callback arguments.
1087
1088 Usage:
1089
1090 >>> some_widget.connect(\"signal\", print_callback_args)
1091 '''
1092 print "Print callback argument: %s" % (args)
1093
1095 '''
1096 Whether widget is support composited.
1097
1098 @param widget: Gtk.Widget instance.
1099 @return: Return True if widget is support composited.
1100 '''
1101 return widget.is_composited()
1102
1103 -def rgb2hsb(r_value, g_value, b_value):
1104 '''
1105 Convert color from RGB to HSB format.
1106
1107 @param r_value: Red.
1108 @param g_value: Green.
1109 @param b_value: Blue.
1110 @return: Return color with HSB (h, s, b) format.
1111 '''
1112 r = r_value
1113 g = g_value
1114 b = b_value
1115
1116 max_v = max(r, g, b)
1117 min_v = min(r, g, b)
1118
1119 h = 0.0
1120
1121 if max_v == min_v:
1122 h = 0
1123 elif max_v == r and g >= b:
1124 h = 60 * (g - b) / (max_v - min_v)
1125 elif max_v == r and g < b:
1126 h = 60 * (g - b) / (max_v - min_v) + 360
1127 elif max_v == g:
1128 h = 60 * (b - r) / (max_v - min_v) + 120
1129 elif max_v == b:
1130 h = 60 * (r - g) / (max_v - min_v) + 240
1131
1132 if max_v == 0:
1133 s = 0.0
1134 else:
1135 s = 1.0 - min_v / max_v
1136
1137 b = max_v
1138
1139 return (h, s, b)
1140
1142 '''
1143 Find simliar color match search_color.
1144
1145 @param search_color: Color to search.
1146 @return: Return similar color name and value, (color_name, color_value).
1147 '''
1148 (search_h, search_s, search_b) = rgb2hsb(*color_hex_to_cairo(search_color))
1149 hsb_colors = map(lambda name: (name, rgb2hsb(*color_hex_to_cairo(COLOR_NAME_DICT[name]))), SIMILAR_COLOR_SEQUENCE)
1150
1151
1152
1153
1154 similar_color_name = None
1155 similar_color_value = None
1156
1157 if search_b < 0.35:
1158 similar_color_name = BLACK_COLOR_MAPPED
1159
1160 elif search_s < 0.05:
1161 similar_color_name = WHITE_COLOR_MAPPED
1162
1163 else:
1164 min_color_distance = None
1165 for (color_name, (h, s, b)) in hsb_colors:
1166 color_distance = abs(h - search_h)
1167 if min_color_distance == None or color_distance < min_color_distance:
1168 min_color_distance = color_distance
1169 similar_color_name = color_name
1170
1171 similar_color_value = COLOR_NAME_DICT[similar_color_name]
1172 return (similar_color_name, similar_color_value)
1173
1175 '''
1176 Whether file endswith given suffixs.
1177
1178 @param filepath: Filepath to test.
1179 @param suffixs: A list suffix to match.
1180 @return: Return True if filepath endswith with given suffixs.
1181 '''
1182 for suffix in suffixs:
1183 if filepath.endswith(suffix):
1184 return True
1185
1186 return False
1187
1189 '''
1190 Place place_window in center of refer_window.
1191
1192 @param refer_window: Reference window.
1193 @param place_window: Place window.
1194 '''
1195 (center_x, center_y) = get_widget_root_coordinate(refer_window, WIDGET_POS_CENTER)
1196 place_window.move(
1197 center_x - place_window.allocation.width / 2,
1198 center_y - place_window.allocation.height / 2
1199 )
1200
1202 '''
1203 Get formats that support by pixbuf.
1204
1205 @return: Return formats that support by pixbuf.
1206 '''
1207 support_formats = []
1208 for support_format in gtk.gdk.pixbuf_get_formats():
1209 support_formats += support_format.get("extensions")
1210
1211 return support_formats
1212
1214 '''
1215 Get parent directory with given return level.
1216
1217 @param filepath: Filepath.
1218 @param level: Return level, default is 1
1219 @return: Return parent directory with given return level.
1220 '''
1221 parent_dir = os.path.realpath(filepath)
1222
1223 while(level > 0):
1224 parent_dir = os.path.dirname(parent_dir)
1225 level -= 1
1226
1227 return parent_dir
1228
1230 '''
1231 Gdk color to string.
1232
1233 @param gdkcolor: Gdk.Color
1234 @return: Return string of gdk color.
1235 '''
1236 return "#%0.2X%0.2X%0.2X" % (gdkcolor.red / 256, gdkcolor.green / 256, gdkcolor.blue / 256)
1237
1239 '''
1240 Is string can convert to long type.
1241
1242 @param string: Test string.
1243 @return: Return True if string can convert to long type.
1244 '''
1245 if string == "":
1246 return True
1247
1248 try:
1249 long(string)
1250 return True
1251 except ValueError:
1252 return False
1253
1255 '''
1256 Is string can convert to int type.
1257
1258 @param string: Test string.
1259 @return: Return True if string can convert to int type.
1260 '''
1261 if string == "":
1262 return True
1263
1264 try:
1265 int(string)
1266 return True
1267 except ValueError:
1268 return False
1269
1271 '''
1272 Is string can convert to float type.
1273
1274 @param string: Test string.
1275 @return: Return True if string can convert to float type.
1276 '''
1277 if string == "":
1278 return True
1279
1280 try:
1281 float(string)
1282 return True
1283 except ValueError:
1284 return False
1285
1287 '''
1288 Is string can convert to hex color type.
1289
1290 @param string: Test string.
1291 @return: Return True if string can convert to hex color type.
1292 '''
1293 HEX_CHAR = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
1294 "a", "b", "c", "d", "e", "f",
1295 "A", "B", "C", "D", "E", "F",
1296 "#"
1297 ]
1298
1299 if string == "":
1300 return True
1301 else:
1302 for c in string:
1303 if not c in HEX_CHAR:
1304 return False
1305
1306 if string.startswith("#"):
1307 if len(string) > 7:
1308 return False
1309 else:
1310 return True
1311 else:
1312 if len(string) > 6:
1313 return False
1314 else:
1315 return True
1316
1318 '''
1319 Get window shadow size.
1320
1321 @param window: Test window.
1322 @return: Return shadow size as (width, height), or return (0, 0) if window haven't shadow.
1323 '''
1324 if "get_shadow_size" in dir(window):
1325 return window.get_shadow_size()
1326 else:
1327 return (0, 0)
1328
1330 '''
1331 Set layout markup.
1332
1333 @param layout: Pango layout.
1334 @param markup: Markup string.
1335 '''
1336 if "&" in markup or "<" in markup or ">" in markup:
1337 layout.set_markup(markup.replace("&", "&").replace("<", "<").replace(">", ">"))
1338 else:
1339 layout.set_markup(markup)
1340
1342 '''
1343 Get optimum size pixbuf from file.
1344
1345 @param filepath: Filepath to contain image.
1346 @param expect_width: Expect width.
1347 @param expect_height: Expect height.
1348 @param cut_middle_area: Default cut image with middle area.
1349 @return: Return optimum size pixbuf with expect size.
1350 '''
1351 pixbuf = gtk.gdk.pixbuf_new_from_file(filepath)
1352 pixbuf_width, pixbuf_height = pixbuf.get_width(), pixbuf.get_height()
1353 if pixbuf_width >= expect_width and pixbuf_height >= expect_height:
1354 if float(pixbuf_width) / pixbuf_height == float(expect_width) / expect_height:
1355 scale_width, scale_height = expect_width, expect_height
1356 elif float(pixbuf_width) / pixbuf_height > float(expect_width) / expect_height:
1357 scale_height = expect_height
1358 scale_width = int(float(pixbuf_width) * expect_height / pixbuf_height)
1359 else:
1360 scale_width = expect_width
1361 scale_height = int(float(pixbuf_height) * expect_width / pixbuf_width)
1362
1363 if cut_middle_area:
1364 subpixbuf_x = (scale_width - expect_width) / 2
1365 subpixbuf_y = (scale_height - expect_height) / 2
1366 else:
1367 subpixbuf_x = 0
1368 subpixbuf_y = 0
1369
1370 return pixbuf.scale_simple(
1371 scale_width,
1372 scale_height,
1373 gtk.gdk.INTERP_BILINEAR).subpixbuf(subpixbuf_x,
1374 subpixbuf_y,
1375 expect_width,
1376 expect_height)
1377 elif pixbuf_width >= expect_width:
1378 scale_width = expect_width
1379 scale_height = int(float(expect_width) * pixbuf_height / pixbuf_width)
1380
1381 if cut_middle_area:
1382 subpixbuf_x = (scale_width - expect_width) / 2
1383 subpixbuf_y = max((scale_height - expect_height) / 2, 0)
1384 else:
1385 subpixbuf_x = 0
1386 subpixbuf_y = 0
1387
1388 return pixbuf.scale_simple(
1389 scale_width,
1390 scale_height,
1391 gtk.gdk.INTERP_BILINEAR).subpixbuf(subpixbuf_x,
1392 subpixbuf_y,
1393 expect_width,
1394 min(expect_height, scale_height))
1395 elif pixbuf_height >= expect_height:
1396 scale_width = int(float(expect_height) * pixbuf_width / pixbuf_height)
1397 scale_height = expect_height
1398
1399 if cut_middle_area:
1400 subpixbuf_x = max((scale_width - expect_width) / 2, 0)
1401 subpixbuf_y = (scale_height - expect_height) / 2
1402 else:
1403 subpixbuf_x = 0
1404 subpixbuf_y = 0
1405
1406 return pixbuf.scale_simple(
1407 scale_width,
1408 scale_height,
1409 gtk.gdk.INTERP_BILINEAR).subpixbuf(subpixbuf_x,
1410 subpixbuf_y,
1411 min(expect_width, scale_width),
1412 expect_height)
1413 else:
1414 return pixbuf
1415
1417 '''
1418 Unique print, generic for test code.
1419
1420 @param text: Test text.
1421 '''
1422 print "%s: %s" % (time.time(), text)
1423
1425 """
1426 Check connect has active with given port.
1427
1428 @param port: Test port.
1429 @param retry_times: Retry times.
1430 @param sleep_time: Sleep time between retry, in seconds.
1431 @return: Return True if given port is active.
1432 """
1433 ret_val = False
1434 test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1435 retry_time = 0
1436 while (True):
1437 try:
1438 test_socket.connect(("localhost", port))
1439 ret_val = True
1440 break
1441 except socket.error:
1442 time.sleep(sleep_time)
1443 retry_time += 1
1444 if retry_time >= retry_times:
1445 break
1446 else:
1447 continue
1448 return ret_val
1449
1451 '''
1452 Is network connected, if nothing in file `/proc/net/arp`, network is disconnected.
1453
1454 @return: Return True if network is connected.
1455 '''
1456 return len(filter(lambda line: line != '', open("/proc/net/arp", "r").read().split("\n")) )> 1
1457