class ExportWindow(BaseWidget): def __init__(self, parent=None): BaseWidget.__init__(self, 'Export data', parent_win=parent) self.set_margin(5) self.setMinimumHeight(600) self.setMinimumWidth(800) self._tree = ControlTree('Data') self._apply = ControlButton('Apply', checkable=True) self._progress = ControlProgress('Progress') self._add = ControlButton('Add') self._remove = ControlButton('Remove') self._export_list = ControlList('Columns to export') self._outdir = ControlDir('Output directory') self._outfile = ControlText('Output file name') self._toggleevts = ControlCheckBox('Split files by events') self._splitevents = ControlCheckBoxList('Events') self._evtsreload = ControlButton('Reload events') self._formset = [[['_add', '_tree'], '||', ['_remove', '_export_list']], '_toggleevts', '_evtsreload', '_splitevents', '_outdir', '_outfile', '_apply', '_progress'] self._add.value = self.__add_column_event self._remove.value = self.__remove_column_event self._apply.value = self.__apply_btn_event self._evtsreload.value = self.__reload_events self._outdir.changed_event = self.__update_outfile_name_event self._outfile.changed_event = self.__update_outfile_name_event self._toggleevts.changed_event = self.__toggleevents_visibility self._splitevents.changed_event = self.__update_outfile_name_event self._splitevents.selection_changed_event = self.__update_outfile_name_event self._tree.show_header = False self._apply.icon = conf.ANNOTATOR_ICON_MOTION self._evtsreload.icon = conf.ANNOTATOR_ICON_REFRESH self._add.icon = conf.ANNOTATOR_ICON_ADD self._remove.icon = conf.ANNOTATOR_ICON_REMOVE self._progress.hide() self._splitevents.hide() self._evtsreload.hide() self._apply.enabled = False self._properties = [] ########################################################################### ### EVENTS ################################################################ ########################################################################### def __toggleevents_visibility(self): if self._toggleevts.value: self._splitevents.show() self._evtsreload.show() else: self._splitevents.hide() self._evtsreload.hide() def __field_full_name(self, tree_item): name = tree_item.text(0) while True: tree_item = tree_item.parent() if tree_item is None: break name = "{0} > {1}".format(tree_item.text(0), name) return name def __add_column_event(self): self.__update_outfile_name_event() item = self._tree.selected_item if item is None: return if hasattr(item, 'data_function'): self._export_list += [self.__field_full_name(item)] self._properties.append((len(item.win), item.data_function)) elif isinstance(item.win, Value): self._export_list += [self.__field_full_name(item)] self._properties.append((len(item.win), item.win.get_value)) def __remove_column_event(self): self.__update_outfile_name_event() if self._export_list.selected_row_index is None: return elif self._export_list.selected_row_index >= 0: self._properties.pop(self._export_list.selected_row_index) self._export_list -= -1 def __update_outfile_name_event(self): """ Update the output filename """ filename = self._outfile.value if len(filename.strip()) == 0: return outfilepath, outfile_extension = os.path.splitext(filename) names = [outfilepath] if len(outfilepath) > 0 else [] if len(list(self._splitevents.value)) > 0: if '{event}' not in outfilepath: names.append('{event}') if '{start}' not in outfilepath: names.append('{start}') if '{end}' not in outfilepath: names.append('{end}') self._outfile.value = ('-'.join(names) + '.csv') self._apply.enabled = True def __apply_btn_event(self): if self._apply.checked: if len(self._properties) == 0: QMessageBox.about( self, "Error", "You need to select at least one value to export.") self._apply.checked = False return if self._outfile.value is None or len( self._outfile.value.strip()) == 0: QMessageBox.about( self, "Error", "You need to select the name of the output file.") self._apply.checked = False return if self._outdir.value is None or len(self._outdir.value) == 0: QMessageBox.about( self, "Error", "You need to select the name of the output directory.") self._apply.checked = False return self.__update_outfile_name_event() self._export_list.enabled = False self._tree.enabled = False self._add.enabled = False self._remove.enabled = False self._outdir.enabled = False self._outfile.enabled = False self._apply.label = 'Cancel' ### calculate the video cuts ############################# timeline = self.parent().timeline selected_events = self._splitevents.value videocuts = [] if len(selected_events): # use the events to cut the video totalframes = 0 for row in timeline.rows: for event in row.events: if event.title not in selected_events: continue b = event.begin e = event.end totalframes += e - b videocuts.append((int(b), int(e), event.title)) videocuts = sorted(videocuts, key=lambda x: x[0]) else: # no events were selected end = max([size for size, func in self._properties]) totalframes = end videocuts = [(0, int(end), None)] ########################################################## self._progress.min = 0 self._progress.max = totalframes self._progress.show() for b, e, eventname in videocuts: filename = self._outfile.value filename = filename.format(event=eventname, start=b, end=e) filename = os.path.join(self._outdir.value, filename) with open(filename, 'w') as out: ## write the csv columns headers out.write('frame;') for values in self._export_list.value: out.write(('{0};'.format(values[0]))) out.write('\n') ## write the values for index in range(b, e): out.write('{0};'.format(index)) for _, func in self._properties: out.write('{0};'.format(func(index))) out.write('\n') self._progress += 1 self._export_list.enabled = True self._tree.enabled = True self._add.enabled = True self._remove.enabled = True self._outdir.enabled = True self._outfile.enabled = True self._apply.label = 'Apply' self._apply.checked = False self._progress.hide() def __copy_tree_node(self, item, new_item): new_item.win = item.win if hasattr(item, 'data_function'): new_item.data_function = item.data_function def __reload_events(self): """ Find all the events available on the timeline """ timeline = self.parent().timeline rows = timeline.rows events = {} for row in rows: for event in row.events: events[event.title] = True events = sorted(events.keys()) loaded_events = dict(self._splitevents.items) self._splitevents.value = [(e, loaded_events.get(e, False)) for e in events] @property def project(self): return self._project @project.setter def project(self, value): self._project = value self._tree.clear() self._tree.clone_tree(value.tree, copy_function=self.__copy_tree_node) self.__reload_events()
class ContoursGUI(DatasetGUI, Contours, BaseWidget): def __init__(self, object2d=None): DatasetGUI.__init__(self) Contours.__init__(self, object2d) BaseWidget.__init__(self, '2D Object', parent_win=object2d) self._sel_pts = [] self._remove_btn = ControlButton('Remove') self._layers = ControlCheckBoxList('Layers') self._sel_pto_btn = ControlButton('Select point') self._switchangle_btn = ControlButton('Switch orientation') self._pickcolor = ControlButton('Pick a color', default=self.__pick_a_color_event) self._formset = [ '_name', '_remove_btn', '_sel_pto_btn', '_switchangle_btn', ' ', '_pickcolor', ' ', '_layers' ] self._switchangle_btn.hide() #### set controls ############################################## self._remove_btn.icon = conf.ANNOTATOR_ICON_REMOVE self._sel_pto_btn.icon = conf.ANNOTATOR_ICON_SELECTPOINT self._switchangle_btn.icon = conf.ANNOTATOR_ICON_REMOVE #### set events ################################################# self._remove_btn.value = self.remove_dataset self._sel_pto_btn.value = self.__sel_pto_btn_event self._switchangle_btn.value = self.__switchangle_btn_event self.create_tree_nodes() self._layers.value = [('contours', True), ('angle', True), ('velocity vector', True), ('bounding rect', False), ('fit ellipse', False), ('extreme points', False), ('convex hull', False), ('rotated rectangle', False), ('minimum enclosing circle', False), ('minimum enclosing triangle', False)] ###################################################################### ### EVENTS ########################################################### ###################################################################### def __sel_pto_btn_event(self): video_index = self.mainwindow._player.video_index - 1 if video_index < 0 and self.get_position(video_index) is not None: return self._sel_pts.append(video_index) self._sel_pts = sorted(self._sel_pts) #store a temporary path for interpolation visualization if len(self._sel_pts) == 2: self._switchangle_btn.show() elif len(self._sel_pts) > 2: self._sel_pts = self._sel_pts[-1:] self._switchangle_btn.hide() else: self._switchangle_btn.hide() self.mainwindow._player.refresh() def __switchangle_btn_event(self): if len(self._sel_pts) == 2: for i in range(self._sel_pts[0], self._sel_pts[1] + 1): head, tail = self.get_extreme_points(i) centroid = self.get_position(i) self._angles[i] = points_angle(centroid, tail) self.mainwindow._player.refresh() def __calc_walked_distance(self): v1 = self.object2d.create_value() v1.name = "Total walked distance" v1._values, _ = self.calc_walked_distance() def __calc_walked_distance_window(self): winsize, ok = QInputDialog.getInt(self, "Calculate the walked distance", "Enter the window size", 30) if ok: v2 = self.object2d.create_value() v2.name = "Walked distance in the previous {0} frames".format( winsize) _, v2._values = self.calc_walked_distance(winsize) def __calc_walked_distance_with_direction(self): v1 = self.object2d.create_value() v1.name = "Total walked distance with direction" v1._values, _ = self.calc_walked_distance_with_direction() def __calc_walked_distance_window_with_direction(self): winsize, ok = QInputDialog.getInt( self, "Calculate the walked distance with direction", "Enter the window size", 30) if ok: v2 = self.object2d.create_value() v2.name = "Walked distance with direction in the previous {0} frames".format( winsize) _, v2._values = self.calc_walked_distance_with_direction(winsize) def __pick_a_color_event(self): color = QColor(self.color[2], self.color[1], self.color[0]) color = QColorDialog.getColor(color, parent=self, title='Pick a color for the path') self.color = color.blue(), color.green(), color.red() self.mainwindow._player.refresh() ###################################################################### ### FUNCTIONS ######################################################## ###################################################################### def create_popupmenu_actions(self): self.tree.add_popup_menu_option(label='Remove', function_action=self.remove_dataset, item=self.treenode, icon=conf.ANNOTATOR_ICON_DELETE) self.tree.add_popup_menu_option('-', item=self.treenode) self.tree.add_popup_menu_option( label='Total walked distance', function_action=self.__calc_walked_distance, item=self.treenode, icon=conf.ANNOTATOR_ICON_POSITION) self.tree.add_popup_menu_option( label='Walked distance in a window', function_action=self.__calc_walked_distance_window, item=self.treenode, icon=conf.ANNOTATOR_ICON_POSITION) self.tree.add_popup_menu_option( label='Total distance with direction', function_action=self.__calc_walked_distance_with_direction, item=self.treenode, icon=conf.ANNOTATOR_ICON_POSITION) self.tree.add_popup_menu_option( label='Walked distance in a window with direction', function_action=self.__calc_walked_distance_window_with_direction, item=self.treenode, icon=conf.ANNOTATOR_ICON_POSITION) def create_tree_nodes(self): self.treenode = self.tree.create_child( self.name, icon=conf.ANNOTATOR_ICON_CONTOUR, parent=self.parent_treenode) self.treenode.win = self self.create_popupmenu_actions() self.create_tracking_tree_nodes() ###################################################################### ### FUNCTIONS ######################################################## ###################################################################### def get_angle_angle_value(self, index): return self.get_angle(index) def get_angle_angularvelocity_value(self, index): return self.get_angular_velocity(index) def get_angle_difftozero_value(self, index): return self.get_angle_diff_to_zero(index) def get_position_x_value(self, index): v = self.get_position(index) return v[0] if v is not None else None def get_position_y_value(self, index): v = self.get_position(index) return v[1] if v is not None else None def get_velocity_x_value(self, index): v = self.get_velocity(index) return v[0] if v is not None else None def get_velocity_y_value(self, index): v = self.get_velocity(index) return v[1] if v is not None else None def get_velocity_absolute_value(self, index): return self.get_absolute_velocity(index) def get_velocity_withdirection_value(self, index): return self.get_velocity_with_direction(index) def get_velocity_angle_value(self, index): return self.get_velocity_angle(index) def get_acceleration_x_value(self, index): v = self.get_acceleration(index) return v[0] if v is not None else None def get_acceleration_y_value(self, index): v = self.get_acceleration(index) return v[1] if v is not None else None def get_acceleration_absolute_value(self, index): v = self.get_acceleration(index) return math.sqrt(v[1]**2 + v[0]**2) if v is not None else None ################# BOUNDING RECT ################################################### def create_tracking_boundingrect_tree_nodes(self): self.create_group_node('bounding rect', icon=conf.ANNOTATOR_ICON_AREA) self.create_data_node('bounding rect > left x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('bounding rect > left y', icon=conf.ANNOTATOR_ICON_Y) self.create_data_node('bounding rect > width', icon=conf.ANNOTATOR_ICON_WIDTH) self.create_data_node('bounding rect > height', icon=conf.ANNOTATOR_ICON_HEIGHT) self.create_data_node('bounding rect > aspect ratio', icon=conf.ANNOTATOR_ICON_ASPECT_RATIO) self.create_data_node('bounding rect > area', icon=conf.ANNOTATOR_ICON_AREA) self.create_data_node('bounding rect > perimeter', icon=conf.ANNOTATOR_ICON_AREA) self.create_data_node('bounding rect > equivalent diameter', icon=conf.ANNOTATOR_ICON_AREA) self.create_data_node('bounding rect > extend', icon=conf.ANNOTATOR_ICON_INFO) def get_boundingrect_leftx_value(self, index): v = self.get_bounding_box(index) return v[0] if v is not None else None def get_boundingrect_lefty_value(self, index): v = self.get_bounding_box(index) return v[1] if v is not None else None def get_boundingrect_width_value(self, index): v = self.get_bounding_box(index) return v[2] if v is not None else None def get_boundingrect_height_value(self, index): v = self.get_bounding_box(index) return v[3] if v is not None else None def get_boundingrect_aspectratio_value(self, index): cnt = self.get_contour(index) if cnt is None: return None x, y, w, h = cv2.boundingRect(cnt) return float(w) / float(h) def get_boundingrect_area_value(self, index): v = self.get_bounding_box(index) return v[0] * v[1] if v is not None else None def get_boundingrect_perimeter_value(self, index): cnt = self.get_contour(index) if cnt is None: return None area = cv2.contourArea(cnt) x, y, w, h = cv2.boundingRect(cnt) return 2 * w + 2 * h def get_boundingrect_equivalentdiameter_value(self, index): area = self.get_boundingrect_area_value(index) if area is None: return None return np.sqrt(4 * area / np.pi) def get_boundingrect_extend_value(self, index): cnt = self.get_contour(index) if cnt is None: return None area = cv2.contourArea(cnt) x, y, w, h = cv2.boundingRect(cnt) rect_area = w * h return float(area) / float(rect_area) ################# BOUNDING RECT ################################################### ################# minimum enclosing triangle ################################################### def create_tracking_minenclosingtriangle_tree_nodes(self): self.create_group_node('minimum enclosing triangle', icon=conf.ANNOTATOR_ICON_AREA) self.create_group_node('minimum enclosing triangle > p1', icon=conf.ANNOTATOR_ICON_POINT) self.create_data_node('minimum enclosing triangle > p1 > x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('minimum enclosing triangle > p1 > y', icon=conf.ANNOTATOR_ICON_Y) self.create_group_node('minimum enclosing triangle > p2', icon=conf.ANNOTATOR_ICON_POINT) self.create_data_node('minimum enclosing triangle > p2 > x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('minimum enclosing triangle > p2 > y', icon=conf.ANNOTATOR_ICON_Y) self.create_group_node('minimum enclosing triangle > p3', icon=conf.ANNOTATOR_ICON_POINT) self.create_data_node('minimum enclosing triangle > p3 > x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('minimum enclosing triangle > p3 > y', icon=conf.ANNOTATOR_ICON_Y) self.create_data_node('minimum enclosing triangle > perimeter', icon=conf.ANNOTATOR_ICON_AREA) self.create_data_node('minimum enclosing triangle > angle', icon=conf.ANNOTATOR_ICON_AREA) def get_minimumenclosingtriangle_p1_x_value(self, index): triangle = self.get_minimumenclosingtriangle(index) if triangle is None: return None return triangle[0][0][0] def get_minimumenclosingtriangle_p1_y_value(self, index): triangle = self.get_minimumenclosingtriangle(index) if triangle is None: return None return triangle[0][0][1] def get_minimumenclosingtriangle_p2_x_value(self, index): triangle = self.get_minimumenclosingtriangle(index) if triangle is None: return None return triangle[0][1][0] def get_minimumenclosingtriangle_p2_y_value(self, index): triangle = self.get_minimumenclosingtriangle(index) if triangle is None: return None return triangle[0][1][1] def get_minimumenclosingtriangle_p3_x_value(self, index): triangle = self.get_minimumenclosingtriangle(index) if triangle is None: return None return triangle[0][2][0] def get_minimumenclosingtriangle_p3_y_value(self, index): triangle = self.get_minimumenclosingtriangle(index) if triangle is None: return None return triangle[0][2][1] def get_minimumenclosingtriangle_perimeter_value(self, index): triangle = self.get_minimumenclosingtriangle(index) if triangle is None: return None p1, p2, p3 = triangle return pts_utils.lin_dist(p1[0], p2[0]) + pts_utils.lin_dist( p2[0], p3[0]) + pts_utils.lin_dist(p3[0], p1[0]) def get_minimumenclosingtriangle_angle_value(self, index): return self.get_minimumenclosingtriangle_angle(index) ################# minimum enclosing triangle ################################################### def create_tracking_minenclosingcircle_tree_nodes(self): self.create_group_node('minimum enclosing circle', icon=conf.ANNOTATOR_ICON_CIRCLE) self.create_data_node('minimum enclosing circle > x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('minimum enclosing circle > y', icon=conf.ANNOTATOR_ICON_Y) self.create_data_node('minimum enclosing circle > radius', icon=conf.ANNOTATOR_ICON_WIDTH) def get_minimumenclosingcircle_x_value(self, index): circle = self.get_minimumenclosingcircle(index) if circle is None: return None center, radius = circle return center[0] def get_minimumenclosingcircle_y_value(self, index): circle = self.get_minimumenclosingcircle(index) if circle is None: return None center, radius = circle return center[1] def get_minimumenclosingcircle_radius_value(self, index): circle = self.get_minimumenclosingcircle(index) if circle is None: return None center, radius = circle return radius ################# EXTREME POINTS #################################################### def create_tracking_extremepoints_tree_nodes(self): self.create_group_node('extreme points', icon=conf.ANNOTATOR_ICON_POINT) self.create_group_node('extreme points > p1', icon=conf.ANNOTATOR_ICON_POINT) self.create_data_node('extreme points > p1 > x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('extreme points > p1 > y', icon=conf.ANNOTATOR_ICON_Y) self.create_group_node('extreme points > p2', icon=conf.ANNOTATOR_ICON_POINT) self.create_data_node('extreme points > p2 > x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('extreme points > p2 > y', icon=conf.ANNOTATOR_ICON_Y) self.create_data_node('extreme points > angle', icon=conf.ANNOTATOR_ICON_ANGLE) def get_extremepoints_p1_x_value(self, index): v = self.get_extreme_points(index) return v[0][0] if v is not None else None def get_extremepoints_p1_y_value(self, index): v = self.get_extreme_points(index) return v[0][1] if v is not None else None def get_extremepoints_p2_x_value(self, index): v = self.get_extreme_points(index) return v[1][0] if v is not None else None def get_extremepoints_p2_y_value(self, index): v = self.get_extreme_points(index) return v[1][1] if v is not None else None def get_extremepoints_angle_value(self, index): v = self.get_extreme_points(index) return math.degrees(pts_utils.points_angle( v[0], v[1])) if v is not None else None ################# FIT ELLISPSE #################################################### ################# FIT ELLIPSE #################################################### def create_tracking_fitellipse_tree_nodes(self): self.create_group_node('fit ellipse', icon=conf.ANNOTATOR_ICON_ELLIPSE) self.create_data_node('fit ellipse > center x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('fit ellipse > center y', icon=conf.ANNOTATOR_ICON_Y) self.create_data_node('fit ellipse > major axis size', icon=conf.ANNOTATOR_ICON_HEIGHT) self.create_data_node('fit ellipse > minor axis size', icon=conf.ANNOTATOR_ICON_WIDTH) self.create_data_node('fit ellipse > angle', icon=conf.ANNOTATOR_ICON_ANGLE) def get_fitellipse_centerx_value(self, index): v = self.get_fit_ellipse(index) return v[0][0] if v is not None else None def get_fitellipse_centery_value(self, index): v = self.get_fit_ellipse(index) return v[0][1] if v is not None else None def get_fitellipse_majoraxissize_value(self, index): v = self.get_fit_ellipse(index) return v[1][1] if v is not None else None def get_fitellipse_minoraxissize_value(self, index): v = self.get_fit_ellipse(index) return v[1][0] if v is not None else None def get_fitellipse_angle_value(self, index): v = self.get_fit_ellipse(index) return v[2] if v is not None else None ################# FIT ELLIPSE #################################################### ################# CONVEX HULL #################################################### def create_tracking_convexhull_tree_nodes(self): self.create_group_node('convex hull', icon=conf.ANNOTATOR_ICON_HULL) self.create_data_node('convex hull > area', icon=conf.ANNOTATOR_ICON_AREA) self.create_data_node('convex hull > perimeter', icon=conf.ANNOTATOR_ICON_AREA) self.create_data_node('convex hull > equivalent diameter', icon=conf.ANNOTATOR_ICON_CIRCLE) self.create_data_node('convex hull > solidity', icon=conf.ANNOTATOR_ICON_BLACK_CIRCLE) def get_convexhull_area_value(self, index): cnt = self.get_contour(index) if cnt is None: return None hull = cv2.convexHull(cnt) return cv2.contourArea(hull) def get_convexhull_perimeter_value(self, index): cnt = self.get_contour(index) if cnt is None: return None hull = cv2.convexHull(cnt) return cv2.arcLength(hull, True) def get_convexhull_equivalentdiameter_value(self, index): cnt = self.get_contour(index) if cnt is None: return None hull = cv2.convexHull(cnt) area = cv2.contourArea(hull) return np.sqrt(4 * area / np.pi) def get_convexhull_solidity_value(self, index): cnt = self.get_contour(index) if cnt is None: return None area = cv2.contourArea(cnt) hull = cv2.convexHull(cnt) hull_area = cv2.contourArea(hull) return float(area) / float(hull_area) ################# CONVEX HULL #################################################### ################# ROTATED RECTANGLE #################################################### def create_tracking_rotatedrectangle_tree_nodes(self): self.create_group_node('rotated rectangle', icon=conf.ANNOTATOR_ICON_AREA) self.create_data_node('rotated rectangle > center x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('rotated rectangle > center y', icon=conf.ANNOTATOR_ICON_Y) self.create_data_node('rotated rectangle > width', icon=conf.ANNOTATOR_ICON_HEIGHT) self.create_data_node('rotated rectangle > height', icon=conf.ANNOTATOR_ICON_WIDTH) self.create_data_node('rotated rectangle > angle', icon=conf.ANNOTATOR_ICON_ANGLE) def get_rotatedrectangle_centerx_value(self, index): v = self.get_rotatedrectangle(index) return v[0][0] if v is not None else None def get_rotatedrectangle_centery_value(self, index): v = self.get_rotatedrectangle(index) return v[0][1] if v is not None else None def get_rotatedrectangle_width_value(self, index): v = self.get_rotatedrectangle(index) return v[1][0] if v is not None else None def get_rotatedrectangle_height_value(self, index): v = self.get_rotatedrectangle(index) return v[1][1] if v is not None else None def get_rotatedrectangle_angle_value(self, index): v = self.get_rotatedrectangle(index) return v[2] if v is not None else None ################# ROTATED RECTANGLE #################################################### ################# MOMENTS #################################################### def create_tracking_moments_tree_nodes(self): self.create_group_node('moments', icon=conf.ANNOTATOR_ICON_HULL) self.create_data_node('moments > m00', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > m10', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > m01', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > m20', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > m11', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > m02', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > m30', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > m21', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > m12', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > m03', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > mu20', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > mu11', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > mu02', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > mu30', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > mu21', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > mu12', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > mu03', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > nu20', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > nu11', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > nu02', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > nu30', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > nu21', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > nu12', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('moments > nu03', icon=conf.ANNOTATOR_ICON_X) ################# MOMENTS #################################################### def get_moments_m00_value(self, index): return self.get_moment(index, 'm00') def get_moments_m10_value(self, index): return self.get_moment(index, 'm10') def get_moments_m01_value(self, index): return self.get_moment(index, 'm01') def get_moments_m20_value(self, index): return self.get_moment(index, 'm20') def get_moments_m11_value(self, index): return self.get_moment(index, 'm11') def get_moments_m02_value(self, index): return self.get_moment(index, 'm02') def get_moments_m30_value(self, index): return self.get_moment(index, 'm30') def get_moments_m21_value(self, index): return self.get_moment(index, 'm21') def get_moments_m12_value(self, index): return self.get_moment(index, 'm12') def get_moments_m03_value(self, index): return self.get_moment(index, 'm03') def get_moments_mu20_value(self, index): return self.get_moment(index, 'mu20') def get_moments_mu11_value(self, index): return self.get_moment(index, 'mu11') def get_moments_mu02_value(self, index): return self.get_moment(index, 'mu02') def get_moments_mu30_value(self, index): return self.get_moment(index, 'mu30') def get_moments_mu21_value(self, index): return self.get_moment(index, 'mu21') def get_moments_mu12_value(self, index): return self.get_moment(index, 'mu12') def get_moments_mu03_value(self, index): return self.get_moment(index, 'mu03') def get_moments_nu20_value(self, index): return self.get_moment(index, 'nu20') def get_moments_nu11_value(self, index): return self.get_moment(index, 'nu11') def get_moments_nu30_value(self, index): return self.get_moment(index, 'nu02') def get_moments_nu02_value(self, index): return self.get_moment(index, 'nu30') def get_moments_nu21_value(self, index): return self.get_moment(index, 'nu21') def get_moments_nu12_value(self, index): return self.get_moment(index, 'nu12') def get_moments_nu03_value(self, index): return self.get_moment(index, 'nu03') ################# HU MOMENTS #################################################### def create_tracking_humoments_tree_nodes(self): self.create_group_node('hu moments', icon=conf.ANNOTATOR_ICON_HULL) self.create_data_node('hu moments > hu0', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('hu moments > hu1', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('hu moments > hu2', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('hu moments > hu3', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('hu moments > hu4', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('hu moments > hu5', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('hu moments > hu6', icon=conf.ANNOTATOR_ICON_X) def get_humoments_hu0_value(self, index): return self.get_humoment(index, 0) def get_humoments_hu1_value(self, index): return self.get_humoment(index, 1) def get_humoments_hu2_value(self, index): return self.get_humoment(index, 2) def get_humoments_hu3_value(self, index): return self.get_humoment(index, 3) def get_humoments_hu4_value(self, index): return self.get_humoment(index, 4) def get_humoments_hu5_value(self, index): return self.get_humoment(index, 5) def get_humoments_hu6_value(self, index): return self.get_humoment(index, 6) ################# HU MOMENTS #################################################### def create_tracking_tree_nodes(self): ################# CONTOUR ######################################################### self.create_data_node('area', icon=conf.ANNOTATOR_ICON_AREA) self.create_data_node('perimeter', icon=conf.ANNOTATOR_ICON_AREA) self.create_data_node('equivalent diameter', icon=conf.ANNOTATOR_ICON_CIRCLE) self.create_group_node('angle', icon=conf.ANNOTATOR_ICON_ANGLE) self.create_data_node('angle > angle', icon=conf.ANNOTATOR_ICON_POSITION) self.create_data_node('angle > angular velocity', icon=conf.ANNOTATOR_ICON_VELOCITY) self.create_data_node('angle > diff to zero', icon=conf.ANNOTATOR_ICON_VELOCITY) self.create_group_node('position', icon=conf.ANNOTATOR_ICON_POSITION) self.create_data_node('position > x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('position > y', icon=conf.ANNOTATOR_ICON_Y) self.create_group_node('velocity', icon=conf.ANNOTATOR_ICON_VELOCITY) self.create_data_node('velocity > x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('velocity > y', icon=conf.ANNOTATOR_ICON_Y) self.create_data_node('velocity > absolute', icon=conf.ANNOTATOR_ICON_INFO) self.create_data_node('velocity > with direction', icon=conf.ANNOTATOR_ICON_INFO) self.create_data_node('velocity > angle', icon=conf.ANNOTATOR_ICON_INFO) self.create_group_node('acceleration', icon=conf.ANNOTATOR_ICON_ACCELERATION) self.create_data_node('acceleration > x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('acceleration > y', icon=conf.ANNOTATOR_ICON_Y) self.create_data_node('acceleration > absolute', icon=conf.ANNOTATOR_ICON_INFO) self.create_tracking_boundingrect_tree_nodes() self.create_tracking_fitellipse_tree_nodes() self.create_tracking_extremepoints_tree_nodes() self.create_tracking_convexhull_tree_nodes() self.create_tracking_rotatedrectangle_tree_nodes() self.create_tracking_minenclosingcircle_tree_nodes() self.create_tracking_minenclosingtriangle_tree_nodes() self.create_tracking_moments_tree_nodes() self.create_tracking_humoments_tree_nodes() ###################################################################### ### FUNCTIONS ######################################################## ###################################################################### def __draw_point(self, frame, p, color=(100, 0, 100)): cv2.circle(frame, p, 5, (255, 255, 255), -1) cv2.circle(frame, p, 3, color, -1) def draw_contour(self, frame, frame_index): cnt = self.get_contour(frame_index) if cnt is not None: cv2.polylines(frame, np.array([cnt]), True, self.color, 2) def draw_angle(self, frame, frame_index): angle = self.get_angle(frame_index) p1 = self.get_position(frame_index) if angle is None or p1 is None: return None p2 = int(round(p1[0] + 40 * math.cos(angle))), int( round(p1[1] + 40 * math.sin(angle))) cv2.line(frame, p1, p2, (255, 100, 0), 2) def draw_boundingrect(self, frame, frame_index): rect = self.get_bounding_box(frame_index) if rect is None: return None x, y, w, h = rect cv2.rectangle(frame, (x, y), (x + w, y + h), self.color, 2) def draw_fitellipse(self, frame, frame_index): ellipse = self.get_fit_ellipse(frame_index) if ellipse is None: return None (x, y), (MA, ma), angle = ellipse cv2.ellipse(frame, (int(round(x)), int(round(y))), (int(round(MA)), int(round(ma))), int(round(angle)), 0, 360, (0, 0, 255), 1) def draw_extremepoints(self, frame, frame_index): head, tail = self.get_extreme_points(frame_index) if head is not None: self.__draw_point(frame, head, color=(100, 0, 100)) if tail is not None: self.__draw_point(frame, tail, color=(100, 100, 0)) def draw_convexhull(self, frame, frame_index): cnt = self.get_contour(frame_index) if cnt is None: return None hull = cv2.convexHull(cnt) cv2.polylines(frame, np.array([hull]), True, self.color, 1) def draw_rotatedrectangle(self, frame, frame_index): rect = self.get_rotatedrectangle(frame_index) box = cv2.boxPoints(rect) box = np.int0(box) cv2.drawContours(frame, [box], 0, self.color, 1) def draw_minimumenclosingcircle(self, frame, frame_index): circle = self.get_minimumenclosingcircle(frame_index) if circle is not None: center, radius = circle center = int(round(center[0])), int(round(center[1])) cv2.circle(frame, center, int(round(radius)), self.color) def draw_minenclosingtriangle(self, frame, frame_index): triangle = self.get_minimumenclosingtriangle(frame_index) if triangle is not None: p1, p2, p3 = triangle p1, p2, p3 = tuple(p1[0]), tuple(p2[0]), tuple(p3[0]) cv2.line(frame, p1, p2, 255) cv2.line(frame, p2, p3, 255) cv2.line(frame, p3, p1, 255) def draw_velocity_vector(self, frame, frame_index): vel = self.get_velocity(frame_index) p0 = self.get_position(frame_index) if vel is not None and p0 is not None: p1 = p0[0] - vel[0], p0[1] - vel[1] cv2.line(frame, p0, p1, (255, 255, 0)) def draw(self, frame, frame_index): for i in self._sel_pts: #store a temporary path for interpolation visualization p = self.get_position(i) cv2.circle(frame, p, 20, (255, 255, 255), 4, lineType=cv2.LINE_AA) # pylint: disable=no-member cv2.circle(frame, p, 20, (50, 50, 255), 1, lineType=cv2.LINE_AA) # pylint: disable=no-member layers = self._layers.value if 'contours' in layers: self.draw_contour(frame, frame_index) if 'angle' in layers: self.draw_angle(frame, frame_index) if 'velocity vector' in layers: self.draw_velocity_vector(frame, frame_index) if 'bounding rect' in layers: self.draw_boundingrect(frame, frame_index) if 'fit ellipse' in layers: self.draw_fitellipse(frame, frame_index) if 'extreme points' in layers: self.draw_extremepoints(frame, frame_index) if 'convex hull' in layers: self.draw_convexhull(frame, frame_index) if 'rotated rectangle' in layers: self.draw_rotatedrectangle(frame, frame_index) if 'minimum enclosing circle' in layers: self.draw_minimumenclosingcircle(frame, frame_index) if 'minimum enclosing triangle' in layers: self.draw_minenclosingtriangle(frame, frame_index) ################# CONTOUR ######################################################### def get_angle_value(self, index): return self.get_angle(index) def get_area_value(self, index): cnt = self.get_contour(index) if cnt is None: return None return cv2.contourArea(cnt) def get_perimeter_value(self, index): cnt = self.get_contour(index) if cnt is None: return None return cv2.arcLength(cnt, True) def get_equivalentdiameter_value(self, index): cnt = self.get_contour(index) if cnt is None: return None area = cv2.contourArea(cnt) return np.sqrt(4 * area / np.pi) @property def mainwindow(self): return self.object2d.mainwindow @property def tree(self): return self.object2d.tree @property def video_capture(self): return self._object2d.video_capture @property def parent_treenode(self): return self.object2d.treenode
class GraphApp(BaseApp): """Application form""" def __init__(self, title='Variables graphs'): super(GraphApp,self).__init__(title) self._graph = ControlVisVis("Graph") self._toggleVars = ControlButton('Show/Hide variables', checkable=True) self._loadGraph = ControlButton('Apply') self._varsList = ControlCheckBoxList('Variables') self._varsList += ('Frames',True) self._varsList += ('X',True) self._varsList += ('Y',True) self._varsList += ('Z',False) self._varsList += ('Velocity',False) self._varsList += ('Acceleration',False) self._modules_tabs.update({ 'Graphs': [ ('_toggleVars',' '), '_varsList', '_loadGraph', '_graph'], }) self._loadGraph.value = self.__calculate_graph self._toggleVars.value = self.__show_hide_variables self._varsList.hide() self._loadGraph.hide() def __show_hide_variables(self): #Show and hide the variables list if self._toggleVars.checked: self._varsList.show() self._loadGraph.show() else: self._varsList.hide() self._loadGraph.hide() def __calculate_graph(self): #Render the graph if self._data==None: self.warning("Please load the data first.", "The data is missing") return lower = 0 if self._boundings.value[0]<0 else self._boundings.value[0] higher = len(self._data) if self._boundings.value[1]>(len(self._data)+1) else self._boundings.value[1] self._progress.min = lower self._progress.max = higher values = [] variables = self._varsList.value if len(variables)>3: self.warning("Please select the maximum of 3 variables.", "Too many variables selected") return for i in range(int(lower), int(higher)-2 ): self._progress.value = i if self._data[i]!=None: val = [] pos = self._data[i].position if 'Frames' in variables: val.append(i) if 'X' in variables: val.append(pos[0]) if 'Y' in variables: val.append(pos[1]) if 'Z' in variables: val.append(pos[2]) if 'Velocity' in variables: val.append(self._velocities[i]) if 'Acceleration' in variables: val.append(self._accelerations[i]) values.append( val ) self._graph.value = [values]
class DatasetsDialog(BaseWidget): def __init__(self, parent_win=None): BaseWidget.__init__(self, 'Datasets', parent_win=parent_win) self._panel = ControlEmptyWidget(default=DatasetsSelectorDialog( parent_win=self)) self._interval = ControlBoundingSlider('Interval', horizontal=True) self._apply_btn = ControlButton('Apply') self.formset = [ '_panel', '_interval', '_apply_btn', ] self._intervals = {} self._panel.value.video_selection_changed_event = self.__video_selection_changed_event self._interval.changed_event = self.__update_intervals_event self._apply_btn.hide() ##################################################################### ### PRIVATE FUNCTIONS ############################################### ##################################################################### def __update_intervals_event(self): self._intervals[self.selected_video] = self._interval.value def __video_selection_changed_event(self): video = self.selected_video if video is not None and video.video_capture is not None: self._interval.max = video.video_capture.get(7) if video not in self._intervals.keys(): self._intervals[video] = 0, self._interval.max self._interval.value = self._intervals[video] self.video_selection_changed_event() ##################################################################### ### EVENTS ########################################################## ##################################################################### def video_selection_changed_event(self): pass def destroy(self, destroyWindow=True, destroySubWindows=True): self._panel.value.destroy(destroyWindow, destroySubWindows) super(DatasetsDialog, self).destroy(destroyWindow, destroySubWindows) ##################################################################### ### FUNCTIONS ####################################################### ##################################################################### def refresh(self): self._panel.value.refresh() def clear(self): self._panel.value.clear() def __add__(self, other): self._panel.value += other return self def __sub__(self, other): self._panel.value -= other return self ##################################################################### ### PROPERTIES ###################################################### ##################################################################### @property def videos(self): return self._panel.value.videos @property def datasets(self): return self._panel.value.datasets @property def datasets_changed_event(self): return self._panel.value.datasets_changed_event @datasets_changed_event.setter def datasets_changed_event(self, value): self._panel.value.datasets_changed_event = value @property def objects_changed_event(self): return self._panel.value.objects_changed_event @objects_changed_event.setter def objects_changed_event(self, value): self._panel.value.objects_changed_event = value @property def selected_video(self): return self._panel.value.selected_video @property def selected_video_range(self): return self._intervals.value @property def selected_data(self): for video, paths in self._panel.value.selected_data: begin, end = self._intervals.get(video, (0, video.video_capture.get(7))) yield video, (begin, end), paths @property def apply_event(self): return self._apply_btn.value @apply_event.setter def apply_event(self, value): if value is not None: self._apply_btn.show() self._apply_btn.value = value @property def interval_visible(self): return self._interval.visible @interval_visible.setter def interval_visible(self, value): if value: self._interval.show() else: self._interval.hide() @property def objects_filter(self): return self._panel.value.objects_filter @objects_filter.setter def objects_filter(self, value): self._panel.value.objects_filter = value @property def datasets_filter(self): return self._panel.value.datasets_filter @datasets_filter.setter def datasets_filter(self, value): self._panel.value.datasets_filter = value
class EditFundingOpportunitiesApp(ModelFormWidget): AUTHORIZED_GROUPS = [settings.PERMISSION_EDIT_FUNDING, 'superuser'] TITLE = "Edit opportunities" MODEL = FundingOpportunity FIELDSETS = [ 'h2:Opportunity details', segment([ ('subject', 'fundingopportunity_published', 'fundingopportunity_rolling'), ('fundingopportunity_name', 'fundingopportunity_end'), ('_loi', 'fundingopportunity_loideadline', 'fundingopportunity_fullproposal'), ('fundingopportunity_link', 'topics'), ]), 'h2:Financing info', segment([ ('financingAgency', 'currency', 'paymentfrequency'), ('fundingtype', 'fundingopportunity_value', 'fundingopportunity_duration'), ]), 'h2:Description', segment([ 'fundingopportunity_eligibility', 'fundingopportunity_scope', 'fundingopportunity_brifdesc', ]) ] def __init__(self, *args, **kwargs): self._loi = ControlCheckBox('LOI', changed_event=self.__loi_changed_event) self._copybtn = ControlButton('Copy', default=self.__copybtn_event, label_visible=False, css='red') super().__init__(*args, **kwargs) self.fundingopportunity_loideadline.hide() self.fundingopportunity_fullproposal.hide() self.__fundingtype_changed_evt() self.__loi_changed_event() self.fundingtype.changed_event = self.__fundingtype_changed_evt def __fundingtype_changed_evt(self): if self.fundingtype.value == None: self.fundingopportunity_value.show() else: self.fundingopportunity_value.hide() self.fundingopportunity_value.value = None def __loi_changed_event(self): if self._loi.value: self.fundingopportunity_loideadline.show() self.fundingopportunity_fullproposal.show() else: self.fundingopportunity_loideadline.value = None self.fundingopportunity_fullproposal.value = None self.fundingopportunity_loideadline.hide() self.fundingopportunity_fullproposal.hide() def delete_event(self): res = super(EditFundingOpportunitiesApp, self).delete_event() self._copybtn.hide() return res def save_event(self, obj, new_object): res = super(EditFundingOpportunitiesApp, self).save_event(obj, new_object) self._copybtn.show() return res def show_create_form(self): super(EditFundingOpportunitiesApp, self).show_create_form() self._copybtn.hide() def show_edit_form(self, pk=None): super(EditFundingOpportunitiesApp, self).show_edit_form(pk) self._copybtn.show() if self.fundingopportunity_loideadline.value is None and self.fundingopportunity_fullproposal.value is None: self.fundingopportunity_loideadline.hide() self.fundingopportunity_fullproposal.hide() self._loi.value = False else: self._loi.value = True def get_buttons_row(self): return [ no_columns('_save_btn', '_create_btn', '_cancel_btn', ' ', '_copybtn', ' ', '_remove_btn') ] def __copybtn_event(self): obj = self.model_object obj.pk = None obj.fundingopportunity_name += ' (copy)' obj.save() for topic in self.model_object.topics.all(): obj.topics.add(topic) app = PyFormsMiddleware.get_instance('opportunities-app') app.populate_list() app.show_edit_form(obj.pk) self.info('Copied')
class Dashboard(BaseWidget): UID = "dashboard-app" TITLE = "New users requests" ######################################################## #### ORQUESTRA CONFIGURATION ########################### ######################################################## LAYOUT_POSITION = conf.ORQUESTRA_HOME ORQUESTRA_MENU = "middle-left" ORQUESTRA_MENU_ICON = "clipboard outline" ORQUESTRA_MENU_ORDER = 10 ######################################################## AUTHORIZED_GROUPS = ["superuser"] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._label = ControlLabel() self._list = ControlQueryList( list_display=["date_joined", "username", "email", "email_confirmed"], headers=["Date joined", "Username", "Email", "Email verified"], ) self._edit_btn_label = '<i class="ui edit icon"></i>Edit' self._approve_btn_label = '<i class="ui check icon"></i>Approve' self._remove_btn_label = '<i class="ui times icon"></i>Remove' self._edit = ControlButton( self._edit_btn_label, label_visible=False, css="fluid secondary", visible=False, default=self.__edit_evt, ) self._approve = ControlButton( self._approve_btn_label, label_visible=False, css="fluid green", visible=False, default=self.__approve_evt, ) self._remove = ControlButton( self._remove_btn_label, label_visible=False, css="fluid red", field_css="", visible=False, default=self.__remove_evt, ) self.formset = [" ", "_label", ("_remove", "_edit", "_approve"), "_list"] self.__enable_actions() self._list.item_selection_changed_event = self.__user_selected_evt self.populate_users_list() def populate_users_list(self): queryset = User.objects.filter(is_active=False) self.__update_label(queryset) if queryset.exists(): self._list.value = queryset.annotate( email_confirmed=F("emailaddress__verified") ) self.__show_actions() self.__disable_actions() else: self._list.hide() self._edit.hide() self._approve.hide() self._remove.hide() def __show_actions(self): self._edit.show() self._approve.show() self._remove.show() def __enable_actions(self, user=None): if user: try: user.full_clean() except ValidationError: user_is_valid = False else: user_is_valid = True self._edit.enabled = True if app_settings.USER_EDIT_FORM else False self._approve.enabled = user_is_valid self._remove.enabled = True else: self.__disable_actions() def __disable_actions(self): self._edit.enabled = False self._approve.enabled = False self._remove.enabled = False def __update_label(self, queryset): if queryset.exists(): icon = '<i class="ui info circle icon"></i>' msg = "Users listed below require approval for accessing the database." css = "info" else: icon = '<i class="ui check icon"></i>' msg = "No users waiting account approval." css = "green" self._label.value = icon + msg self._label.css = css def __user_selected_evt(self): user_id = self._list.selected_row_id user = User.objects.get(pk=user_id) self._edit.label = self._edit_btn_label + f" [{user.username}]" self._approve.label = self._approve_btn_label + f" [{user.username}]" self._remove.label = self._remove_btn_label + f" [{user.username}]" self.__enable_actions(user=user) def __edit_evt(self): app = UserForm(pk=self._list.selected_row_id) app.LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB def __approve_evt(self): user_id = self._list.selected_row_id user = User.objects.get(pk=user_id) user.is_active = True try: user.full_clean() except ValidationError as e: title = "Can not approve user '%s'" % user.username self.alert(e.messages, title=title) return user.save() self.populate_users_list() self.__disable_actions() def __remove_evt(self): user_id = self._list.selected_row_id user = User.objects.get(pk=user_id) user.delete() self.populate_users_list() self.__disable_actions()
class GeometryManualDesigner(BaseWidget): def __init__(self, title, parent=None): super(GeometryManualDesigner, self).__init__(title, parent_win=parent) self._threshold_win = None self._start_point = None self._end_point = None self._selected_poly = None self._selected_point = None self._video = ControlFile("Video file") self._player = ControlPlayer("Video") self._remove = ControlButton("Remove") self._square = ControlButton("Square", checkable=True) self._circle = ControlButton("Circle", checkable=True) self._threshold = ControlButton("Threshold") self._export = ControlButton("Export") self._import = ControlButton("Import") self._polygons = ControlList('Polygons') self._apply = ControlButton('Apply') self._formset = [ '_video', "_player", ("_square", "_circle", "_threshold", " ", "_remove", " ", "_export", "_import"), "=", "_polygons", '_apply' ] self._video.changedchanged_event = self.videoSelected self._square.value = self.square_toggle self._circle.value = self.circle_toggle self._remove.value = self.remove_clicked self._export.value = self.export_clicked self._import.value = self.import_clicked self._threshold.value = self.threshold_btn_click self._player.drag_event = self.on_player_drag_in_video_window self._player.end_drag_event = self.on_player_end_drag_in_video_window self._player.click_event = self.on_player_click_in_video_window self._player.double_click_event = self.on_player_double_click_in_video_window self._player.process_frame_event = self.process_frame self._player.key_release_event = self.on_player_key_release self._apply.hide() def on_player_key_release(self, event): if event.key() == QtCore.Qt.Key_Delete: if self._selected_poly != None and self._selected_point != None: poly = self._polygons.get_value(1, self._selected_poly) try: points = list(eval(poly)) p = points.pop(self._selected_point) self._polygons.set_value(1, self._selected_poly, str(points)[1:-1]) if not self._player.is_playing: self._player.refresh() except: pass def export_clicked(self): filename = str(QFileDialog.getSaveFileName(self, 'Choose a file', '')) if filename != "": output = open(filename, 'w') for values in self._polygons.value: output.write((';'.join(values) + '\n')) output.close() def import_clicked(self): filename = str(QFileDialog.getOpenFileName(self, 'Choose a file', '')) if filename != "": infile = open(filename, 'r') polygons = [] for line in infile: values = line.split(';') name = values[0] poly = values[1] polygons.append((name, poly)) self._polygons.value += polygons def process_frame(self, frame): rows = self._polygons.value for objIndex, obj in enumerate(rows): points = eval(obj[1]) cv2.polylines(frame, [np.array(points, np.int32)], True, (0, 255, 0), 2, lineType=cv2.LINE_AA) for pointIndex, point in enumerate(points): if self._selected_point == pointIndex and objIndex == self._selected_poly: cv2.circle(frame, point, 4, (0, 0, 255), 2) else: cv2.circle(frame, point, 4, (0, 255, 0), 2) if self._start_point and self._end_point: if self._square.checked: cv2.rectangle(frame, self._start_point, self._end_point, (233, 44, 44), 2) elif self._circle.checked and self._end_point[ 0] > self._start_point[0] and self._end_point[ 1] > self._start_point[1]: width = self._end_point[0] - self._start_point[0] height = self._end_point[1] - self._start_point[1] center = (self._start_point[0] + width / 2, self._start_point[1] + height / 2) cv2.ellipse(frame, (center, (width, height), 0), (233, 44, 44), 2) return frame def selectPoint(self, x, y): rows = self._polygons.value for objIndex, obj in enumerate(rows): try: mouseCoord = (x, y) points = eval(obj[1]) for pointIndex, point in enumerate(points): if pointsDistance(mouseCoord, point) <= 5: self._selected_point = pointIndex self._selected_poly = objIndex return self._selected_point = None self._selected_poly = None except: pass def get_intersection_point_distance(self, test_point, point1, point2): p1 = np.float32(point1) p2 = np.float32(point2) p3 = np.float32(test_point) dist = np.linalg.norm(np.cross(p2 - p1, p1 - p3)) / np.linalg.norm(p2 - p1) return dist def on_player_double_click_in_video_window(self, event, x, y): mouse = (int(x), int(y)) rows = self._polygons.value distances = [] for obj_index, obj in enumerate(rows): try: points = list(eval(obj[1])) n_points = len(points) for point_index, point in enumerate(points): next_point = points[(point_index + 1) % n_points] distance = self.get_intersection_point_distance( mouse, point, next_point) if distance <= 5: vector = next_point[0] - point[0], next_point[ 1] - point[1] center = point[0] + vector[0] / 2, point[ 1] + vector[1] / 2 radius = pointsDistance(center, point) mouse_distance = pointsDistance(center, mouse) if mouse_distance < radius: distances.append( (distance, obj_index, point_index)) except: pass if len(distances) > 0: distances = sorted(distances, key=lambda x: x[0]) obj_index = distances[0][1] point_index = distances[0][2] points = list(eval(rows[obj_index][1])) points.insert(point_index + 1, mouse) self._polygons.set_value(1, obj_index, str(points)[1:-1]) self._selected_poly = obj_index self._selected_point = point_index + 1 if not self._player.is_playing: self._player.refresh() def on_player_click_in_video_window(self, event, x, y): self._selected_poly = None self._selected_point = None if not self._square.checked and not self._circle.checked: self.selectPoint(int(x), int(y)) def on_player_drag_in_video_window(self, startPoint, endPoint): self._start_point = (int(startPoint[0]), int(startPoint[1])) self._end_point = (int(endPoint[0]), int(endPoint[1])) if self._selected_poly != None and self._selected_point != None: poly = self._polygons.get_value(1, self._selected_poly) try: points = list(eval(poly)) points[self._selected_point] = self._end_point self._polygons.set_value(1, self._selected_poly, str(points)[1:-1]) except Exception as e: print(e) if not self._player.is_playing: self._player.refresh() def on_player_end_drag_in_video_window(self, startPoint, endPoint): self._start_point = int(startPoint[0]), int(startPoint[1]) self._end_point = int(endPoint[0]), int(endPoint[1]) points = None if self._square.checked: points = createRectanglePoints(self._start_point, self._end_point) elif self._circle.checked and self._end_point[0] > self._start_point[ 0] and self._end_point[1] > self._start_point[1]: points = createEllipsePoints(self._start_point, self._end_point) if points: self._polygons += [ "Poly_%d" % self._polygons.rows_count, str(points)[1:-1] ] self._start_point = None self._end_point = None self._square.checked = False self._circle.checked = False if not self._player.is_playing: self._player.refresh() def __add_contours_from_threshold_win(self, contours): for contour in contours: if contour.any(): points = [tuple(p[0]) for p in contour.tolist()] self._polygons += [ "Poly_%d" % self._polygons.rows_count, str(points)[1:-1] ] def videoSelected(self): self._player.value = self._video.value def square_toggle(self, checked): if checked: self._circle.checked = False def circle_toggle(self, checked): if checked: self._square.checked = False def threshold_btn_click(self): if self._threshold_win is None: self._threshold_win = GeometryFromThreshold(self) self._threshold_win.add_contours = self.__add_contours_from_threshold_win self._threshold_win.show() if len(self._video.value) > 0: self._threshold_win._filename.value = self._video.value def remove_clicked(self): self._polygons -= -1 #Remove the selected row if not self._player.is_playing: self._player.refresh() @property def geometries(self): polys = [] rows = self._polygons.value for objIndex, obj in enumerate(rows): points = eval(obj[1]) polys.append([obj[0], points]) return polys @geometries.setter def geometries(self, value): self._polygons.value = [] for name, poly in value: points = [tuple(p) for p in poly] self._polygons += [name, str(points)[1:-1]] @property def polygons(self): polys = [] rows = self._polygons.value for objIndex, obj in enumerate(rows): points = eval(obj[1]) polys.append(np.array(points, np.int32)) return np.array(polys) @property def apply_event(self): return self._apply.value @apply_event.setter def apply_event(self, value): self._apply.value = value self._show_apply = value is not None def show(self): super(GeometryManualDesigner, self).show() if hasattr(self, '_show_apply') and self._show_apply: self._apply.show() @property def video_filename(self): return None @video_filename.setter def video_filename(self, value): self._video.hide() self._player.value = value @property def video_capture(self): return self.video_capture.value @video_capture.setter def video_capture(self, value): self._video.hide() self._player.value = value @property def total_n_frames(self): if self._player._value is not None and self._player.value != '': return self._player.max else: return 0
class PathGUI(DatasetGUI, Path, BaseWidget): def __init__(self, object2d=None): DatasetGUI.__init__(self) Path.__init__(self, object2d) BaseWidget.__init__(self, '2D Object', parent_win=object2d) self.create_tree_nodes() self._mark_pto_btn = ControlButton('&Mark point', checkable=True, icon=conf.ANNOTATOR_ICON_MARKPLACE ) self._sel_pto_btn = ControlButton('&Select point', default=self.__sel_pto_btn_event, icon=conf.ANNOTATOR_ICON_SELECTPOINT) self._del_path_btn = ControlButton('Delete path', default=self.__del_path_btn_event, icon=conf.ANNOTATOR_ICON_DELETEPATH, visible=False) self._del_point_btn = ControlButton('Delete point', default=self.__del_point_btn_event, icon=conf.ANNOTATOR_ICON_SELECTPOINT, visible=False) self._use_referencial = ControlCheckBox('Apply') self._referencial_pt = ControlText('Referencial', changed_event=self.__referencial_pt_changed_event) self._interpolation_title = ControlLabel('Interpolation', default='INTERPOLATION', visible=False) self._interpolation_mode = ControlCombo('Mode', changed_event=self.__interpolation_mode_changed_event, visible=False) self._interpolate_btn = ControlButton('Apply', default=self.__interpolate_btn_event, icon=conf.ANNOTATOR_ICON_INTERPOLATE, visible=False) self._remove_btn = ControlButton('Remove dataset',default=self.__remove_path_dataset, icon=conf.ANNOTATOR_ICON_REMOVE) self._pickcolor = ControlButton('Pick a color', default=self.__pick_a_color_event) self._show_object_name = ControlCheckBox('Show object name', default=False) self._show_name = ControlCheckBox('Show name', default=False) self._formset = [ '_name', ('_show_name', '_show_object_name'), ('_referencial_pt', '_use_referencial'), '_remove_btn', ' ', '_pickcolor', ' ', ('_mark_pto_btn', '_sel_pto_btn'), '_del_path_btn', '_del_point_btn', '_interpolation_title', ('_interpolation_mode', '_interpolate_btn'), ' ' ] #### set controls ############################################## self._interpolation_mode.add_item("Auto", -1) self._interpolation_mode.add_item("Linear", 'slinear') self._interpolation_mode.add_item("Quadratic", 'quadratic') self._interpolation_mode.add_item("Cubic", 'cubic') ###################################################################### ### FUNCTIONS ######################################################## ###################################################################### def get_velocity(self, index): p1 = self.get_position(index) p2 = self.get_position(index-1) if p1 is None or p2 is None: return None return p2[0]-p1[0], p2[1]-p1[1] def get_acceleration(self, index): v1 = self.get_velocity(index) v2 = self.get_velocity(index-1) if v1 is None or v2 is None: return None return v2[0]-v1[0], v2[1]-v1[1] def get_position_x_value(self, index): v = self.get_position(index) return v[0] if v is not None else None def get_position_y_value(self, index): v = self.get_position(index) return v[1] if v is not None else None def get_velocity_x_value(self, index): v = self.get_velocity(index) return v[0] if v is not None else None def get_velocity_y_value(self, index): v = self.get_velocity(index) return v[1] if v is not None else None def get_velocity_absolute_value(self, index): v = self.get_velocity(index) return math.sqrt(v[1]**2+v[0]**2) if v is not None else None def get_acceleration_x_value(self, index): v = self.get_acceleration(index) return v[0] if v is not None else None def get_acceleration_y_value(self, index): v = self.get_acceleration(index) return v[1] if v is not None else None def get_acceleration_absolute_value(self, index): v = self.get_acceleration(index) return math.sqrt(v[1]**2+v[0]**2) if v is not None else None ###################################################################### ### AUX FUNCTIONS #################################################### ###################################################################### def create_popupmenu_actions(self): self.tree.add_popup_menu_option( label='Duplicate', function_action=self.clone_path, item=self.treenode, icon=conf.ANNOTATOR_ICON_DUPLICATE ) self.tree.add_popup_menu_option( label='Remove', function_action=self.__remove_path_dataset, item=self.treenode, icon=conf.ANNOTATOR_ICON_DELETE ) def create_tree_nodes(self): self.treenode = self.tree.create_child(self.name, icon=conf.ANNOTATOR_ICON_PATH, parent=self.parent_treenode ) self.treenode.win = self self.create_popupmenu_actions() self.create_group_node('position', icon=conf.ANNOTATOR_ICON_POSITION) self.create_data_node('position > x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('position > y', icon=conf.ANNOTATOR_ICON_Y) self.create_group_node('velocity', icon=conf.ANNOTATOR_ICON_VELOCITY) self.create_data_node('velocity > x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('velocity > y', icon=conf.ANNOTATOR_ICON_Y) self.create_data_node('velocity > absolute', icon=conf.ANNOTATOR_ICON_INFO) self.create_group_node('acceleration', icon=conf.ANNOTATOR_ICON_ACCELERATION) self.create_data_node('acceleration > x', icon=conf.ANNOTATOR_ICON_X) self.create_data_node('acceleration > y', icon=conf.ANNOTATOR_ICON_Y) self.create_data_node('acceleration > absolute', icon=conf.ANNOTATOR_ICON_INFO) ###################################################################### ### GUI EVENTS ####################################################### ###################################################################### def __del_point_btn_event(self): video_index = self.mainwindow._player.video_index-1 if video_index<0:return self.set_position(video_index, None, None) try: self._sel_pts.remove(video_index) self._interpolate_btn.hide() self._interpolation_mode.hide() self._interpolation_title.hide() self._del_path_btn.hide() self._tmp_points = [] except ValueError: self.calculate_tmp_interpolation() self.mainwindow._player.refresh() if self.visible: if len(self._sel_pts)==2: self._del_path_btn.show() else: self._del_path_btn.hide() def __sel_pto_btn_event(self): video_index = self.mainwindow._player.video_index-1 if video_index<0:return position = self[video_index] if position is None: return if video_index in self._sel_pts: self._sel_pts.remove(video_index) else: self._sel_pts.append(video_index) self._sel_pts = sorted(self._sel_pts) if self.visible: #store a temporary path for interpolation visualization if len(self._sel_pts) >= 2: ######################################################### #In case 2 frames are selected, draw the temporary path## ######################################################### if self.calculate_tmp_interpolation(): self._interpolate_btn.show() self._interpolation_mode.show() self._interpolation_title.show() if len(self._sel_pts)==2: self._del_path_btn.show() else: self._del_path_btn.hide() ######################################################### else: self._interpolate_btn.hide() self._interpolation_mode.hide() self._interpolation_title.hide() self._del_path_btn.hide() self._tmp_points = [] self.mainwindow._player.refresh() def __remove_path_dataset(self): item = self.tree.selected_item if item is not None: self.object2d -= item.win def __referencial_pt_changed_event(self): try: self._referencial = eval(self._referencial_pt.value) except: self._referencial = None def __pick_a_color_event(self): color = QColor(self.color[2], self.color[1], self.color[0]) color = QColorDialog.getColor(color, parent = self, title = 'Pick a color for the path') self.color = color.blue(), color.green(), color.red() self.mainwindow._player.refresh() #################################################################### def __interpolate_btn_event(self): #store a temporary path for interpolation visualization if len(self._sel_pts) >= 2: mode = None if self._interpolation_mode.value=='Auto' else self._interpolation_mode.value #store a temporary path for interpolation visualization self.interpolate_range( self._sel_pts[0], self._sel_pts[-1], interpolation_mode=mode) self.mainwindow._player.refresh() else: QMessageBox.about(self, "Error", "You need to select 2 frames.") def __interpolation_mode_changed_event(self): #store a temporary path for interpolation visualization if len(self._sel_pts) >= 2: if self.calculate_tmp_interpolation(): self.mainwindow._player.refresh() def __del_path_btn_event(self): #store a temporary path for interpolation visualization if len(self._sel_pts) == 2: reply = QMessageBox.question(self, 'Confirmation', "Are you sure you want to delete this path?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: #store a temporary path for interpolation visualization start, end = self._sel_pts[0], self._sel_pts[1] self.delete_range(start, end) self.calculate_tmp_interpolation() self.mainwindow._player.refresh() else: QMessageBox.about(self, "Error", "You need to select 2 frames.") def __lin_dist(self, p1, p2): return np.linalg.norm( (p1[0]-p2[0], p1[1]-p2[1]) ) ###################################################################### ### VIDEO EVENTS ##################################################### ###################################################################### def on_click(self, event, x, y): if event.button== 1: frame_index = self.mainwindow._player.video_index-1 if self._mark_pto_btn.checked: frame_index = frame_index if frame_index>=0 else 0 self.set_position(frame_index, x, y) self._mark_pto_btn.checked = False else: position = self.get_position(frame_index) if position is not None and self.__lin_dist(position, (x,y))<10: modifier = int(event.event.modifiers()) # If the control button is pressed will add the blob to the previous selections if modifier == QtCore.Qt.ControlModifier: if frame_index not in self._sel_pts: #store a temporary path for interpolation visualization self._sel_pts.append(frame_index) else: # Remove the blob in case it was selected before #store a temporary path for interpolation visualization self._sel_pts.remove(frame_index) else: # The control key was not pressed so will select only one #store a temporary path for interpolation visualization self._sel_pts =[frame_index] else: #store a temporary path for interpolation visualization self._sel_pts =[] # No object selected: remove previous selections #store a temporary path for interpolation visualization self._sel_pts = sorted(self._sel_pts) if self.visible: #store a temporary path for interpolation visualization if len(self._sel_pts) >= 2: ######################################################### #In case 2 frames are selected, draw the temporary path## ######################################################### res = self.calculate_tmp_interpolation() if self.visible & res: self._interpolate_btn.show() self._interpolation_mode.show() self._interpolation_title.show() self._del_path_btn.show() #self._sel_pto_btn.hide() ######################################################### else: if self.visible: self._interpolate_btn.hide() self._interpolation_mode.hide() self._interpolation_title.hide() self._del_path_btn.hide() self._tmp_points = [] self.mainwindow._player.refresh() def draw(self, frame, frame_index): if not self.mainwindow.player.is_playing and self.visible: if self[frame_index] is None: self._del_point_btn.hide() else: self._del_point_btn.show() Path.draw(self, frame, frame_index) ###################################################################### ### PROPERTIES ####################################################### ###################################################################### @property def mainwindow(self): return self._object2d.mainwindow @property def tree(self): return self._object2d.tree @property def video_capture(self): return self._object2d.video_capture @property def parent_treenode(self): return self._object2d.treenode @property def interpolation_mode(self): return None if self._interpolation_mode.value==-1 else self._interpolation_mode.value @property def mark_point_button(self): return self._mark_pto_btn @property def referencial(self): return Path.referencial.fget(self) @referencial.setter def referencial(self, value): self._referencial_pt.value = str(value)[1:-1] if value else '' @property def apply_referencial(self): return self._use_referencial.value @apply_referencial.setter def apply_referencial(self, value): self._use_referencial.value = value @property def show_object_name(self): return self._show_object_name.value @show_object_name.setter def show_object_name(self, value): self._show_object_name.value = value @property def show_name(self): return self._show_name.value @show_name.setter def show_name(self, value): self._show_name.value = value
class UpdatePublication(BaseWidget): TITLE = 'Search publication' LAYOUT_POSITION = conf.ORQUESTRA_NEW_BIGWINDOW def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) authors = kwargs.get('authors') title = kwargs.get('title') journal_name = kwargs.get('journal_name') doi = kwargs.get('doi') pubdate = kwargs.get('pubdate') pubyear = kwargs.get('pubyear') self.pub_hash = str( (authors, title, journal_name, doi, pubdate, pubyear)) text = f""" <table> <tr> <th style='text-align: right' >Title</th> <td style='padding:5px;padding-left:10px;' colspan='3' >{title}</th> <tr/> <tr> <th style='text-align: right' >Authors</th> <td style='padding:5px;padding-left:10px;' colspan='3' >{authors}</th> <tr/> <tr> <th style='text-align: right' >Journal</th> <td style='padding:5px;padding-left:10px;' >{journal_name}</th> <th style='text-align: right' >Pub date</th> <td style='padding:5px;padding-left:10px;' >{pubdate}</th> <tr/> <tr> <th style='text-align: right' >Year</th> <td style='padding:5px;padding-left:10px;' >{pubyear}</th> <th style='text-align: right' >Doi</th> <td style='padding:5px;padding-left:10px;' >{doi}</th> <tr/> </table> """ self._person = ControlAutoComplete( 'Author', queryset=Person.objects.all().order_by('full_name'), visible=False) self._authoralias = ControlText('Author alias', visible=False) self._addalias = ControlButton('Add alias', default=self.__add_author_alias_evt, visible=False) alias = AuthorAlias.objects.all() self._authors = ControlList( 'Unknown authors', default=[[a] for a in authors.split(';') if not alias.filter(name=a).exists()], horizontal_headers=['Authors alias'], item_selection_changed_event=self.__authors_selection_changed_evt) self._ignorebtn = ControlButton('Ignore this publication', css='red', default=self.__ignore_this_pub_evt, label_visible=False) self._info = ControlLabel(text) self._details = ControlEmptyWidget(parent=self, name='_details', default=PubsList(**kwargs)) self.formset = [ '_ignorebtn', '_info', ('_person', '_authoralias', '_addalias'), '_authors', segment('_details', css='secondary') ] if len(self._authors.value) == 0: self._authors.hide() def __authors_selection_changed_evt(self): if self._authors.selected_row_index >= 0: self._addalias.show() self._authoralias.show() self._person.show() self._authoralias.value = self._authors.value[ self._authors.selected_row_index][0] else: self._addalias.hide() self._authoralias.hide() self._person.hide() def __add_author_alias_evt(self): if self._authoralias.value and self._person.value: a = AuthorAlias(name=self._authoralias.value, person=Person.objects.get(pk=self._person.value)) a.save() data = self._authors.value newdata = [] for row in data: if row[0] == self._authoralias.value: continue newdata.append(row) self._authors.value = newdata self._addalias.hide() self._authoralias.hide() self._person.hide() def __ignore_this_pub_evt(self): filepath = os.path.join(settings.MEDIA_ROOT, conf.APP_IMPORT_PUBLICATIONS_BLACKLIST_FILE) with open(filepath, 'a') as out: out.write(str(self.pub_hash) + '\n') self.close() @classmethod def has_permissions(cls, user): if user.is_superuser: return True return user.groups.filter( permissions__codename__in=['app_access_imp_pub']).exists()
class PubsList(PublicationsListWidget): UID = None EDITFORM_CLASS = PubForm LIST_FILTER = [] USE_DETAILS_TO_EDIT = True LIST_ROWS_PER_PAGE = 5 def __init__(self, *args, **kwargs): self.authors = kwargs.get('authors') self.pubtitle = kwargs.get('title') self.doi = kwargs.get('doi') self.pubdate = kwargs.get('pubdate') self.pubyear = kwargs.get('pubyear') self.journal_name = kwargs.get('journal_name') self._addbutton = ControlButton('Add button', label_visible=False, visible=False, default=self.__addbutton_evt) super().__init__(*args, **kwargs) self._list.filter_event = self.__list_changed_evt self.formset = ['_details', '_list', '_addbutton'] def get_toolbar_buttons(self, *args, **kwargs): return [] def get_queryset(self, request, qs): return ModelAdminWidget.get_queryset(self, request, qs) def __addbutton_evt(self): self.show_create_form() form = self._details.value form.publication_title.value = self.pubtitle form.publication_year.value = self.pubyear try: form.publication_publish.value = parse_date(self.pubdate) except: pass journals = Journal.objects.filter( Q(journal_name=self.journal_name) | Q(journalalias__name=self.journal_name)) journal = journals[0] form.journal.value = journal.pk form.publication_doi.value = self.doi form.publication_authors.value = self.authors people = [] authors = AuthorAlias.objects.filter(name__in=self.authors.split(';')) form.authors.value = [a.person.pk for a in authors] self._addbutton.hide() def __list_changed_evt(self): if self._list.value.count() == 0: self._addbutton.show() else: self._addbutton.hide() @classmethod def has_permissions(cls, user): if user.is_superuser: return True return user.groups.filter( permissions__codename__in=['app_access_imp_pub']).exists()
class SimpleExample1(BaseWidget): def __init__(self): super(SimpleExample1, self).__init__(' Thực Tập Cơ Sở ') #main menu self.mainmenu = [{ 'File': [{ 'Open Excel': self.__open, 'icon': 'img/folder_open.png' }, '-', { 'Import': self.__import, 'icon': 'img/import_icon.png' }] }] #tkinler for messagebox root = tk.Tk() root.withdraw() #list self._list = ControlList('Danh sách') self._list.readonly = True #1.open file excel và heap sort self._file = ControlFile('Chọn file Excel') self._butheapsort = ControlButton('Heap Sort') self._butheapsort.icon = 'img/sort_icon.png' self._butheapsort.value = self.__heapsort self._butloadexcel = ControlButton('Load') self._butloadexcel.icon = 'img/load_icon.png' self._butloadexcel.value = self.__load self._butremoveloadexcel = ControlButton('Hủy bỏ') self._butremoveloadexcel.icon = 'img/remove_icon.png' self._butremoveloadexcel.value = self.__removeloadexcel #2.thêm thửa đất self._diachi = ControlText('Địa chỉ') self._dientich = ControlText('Diện tích') self._chusohuuhientai = ControlText('Chủ sở hữu hiện tại') self._loainha = ControlText('Loại nhà') self._mucdichsudung = ControlText('Mục đích Sử dụng') self._giatien = ControlText('Giá tiền') self._but1 = ControlButton('Thêm thửa đất') self._but1.value = self.__add self._but1.icon = 'img/add_icon.png' #3.tìm kiếm thử đất và xóa #tìm kiếm self._butsearch = ControlButton('Tìm kiếm') self._butsearch.icon = 'img/search_icon.png' self._butsearch.value = self.__search self._timkiem = ControlText('Tìm Kiếm') self._checklisttimkiem = ControlCheckBoxList('Chọn tiêu chí tìm kiếm:') self._checklisttimkiem.hide() self._buttonhideshowtimkiem = ControlButton('Hiển thị tiêu chí') self._buttonhideshowtimkiem.value = self._buthideshowtimkiem self._buttonhideshowtimkiem.icon = 'img/show.png' self._buthuybo = ControlButton('Hủy bỏ') self._buthuybo.icon = 'img/remove_icon.png' self._buthuybo.value = self._huybo #xóa self._textxoa = ControlText('Nhập nội dung cần xóa') self._butxoa = ControlButton('Xoá') self._butxoa.icon = 'img/delete_icon.png' self._butxoa.value = self.__xoa self._checklistxoa = ControlCheckBoxList('Chọn tiêu chí xóa:') self._checklistxoa.hide() self._buttonhideshowxoa = ControlButton('Hiển thị tiêu chí') self._buttonhideshowxoa.value = self._buthideshowxoa self._buttonhideshowxoa.icon = 'img/show.png' #4.xuất self._directory = ControlDir('Chọn chỗ xuất file excel') self._tenfilexuat = ControlText('Tên file xuất') self._butxuat = ControlButton('Xuất') self._butxuat.icon = 'img/export_icon.png' self._butxuat.value = self.__xuat #5.merge self._filemerge = ControlFile('Chọn file Excel cần merge') self._butimport = ControlButton('Import') self._butimport.icon = 'img/import2_icon.png' self._butimport.value = self._import self._butmerge = ControlButton('Gộp') self._butmerge.icon = 'img/merge_icon' self._butmerge.value = self._merge self._butmerge.hide() self._listmerge = ControlList('Danh sách import') self._listmerge.readonly = True self._buttonhideshow = ControlButton('Hiển thị tùy chọn') self._buttonhideshow.value = self._buthideshow self._buttonhideshow.hide() self._buttonhideshow.icon = 'img/show.png' self._checklist = ControlCheckBoxList( 'Chọn tiêu chí giữ trong danh sách import:') self._checklist.hide() self._buttonremovemerge = ControlButton('Hủy bỏ') self._buttonremovemerge.value = self._remove self._buttonremovemerge.icon = 'img/remove_icon.png' self._buttonremovemerge.hide() #formset as layout self.formset = [{ '1.Mở File và Heap Sort': [ ' ', '_file', ' ', (' ', '_butloadexcel', '_butremoveloadexcel', '_butheapsort', ' '), ' ' ], '2.Thêm': [ ' ', '_diachi', '_dientich', '_chusohuuhientai', '_loainha', '_mucdichsudung', '_giatien', ' ', (' ', '_but1', ' '), ' ' ], '3.Tìm kiếm và Xóa': [ ' ', '_textxoa', ' ', (' ', '_butxoa', '_buttonhideshowxoa', '_checklistxoa', ' '), ' ', '_timkiem', ' ', (' ', '_butsearch', '_buttonhideshowtimkiem', '_checklisttimkiem', '_buthuybo', ' '), ' ' ], '4.Xuất': [ ' ', '_directory', ' ', '_tenfilexuat', ' ', (' ', '_butxuat', ' '), ' ' ], '5.Merge danh sách': [ '_filemerge', (' ', '_butimport', '_butmerge', '_buttonremovemerge', '_buttonhideshow', '_checklist', ' '), '_listmerge' ], }, '', '', '_list'] #event for mainmenu def __open(self): self._file.click() def __import(self): self._filemerge.click() #event tab 1 #event for _butremoveloadexcel def __removeloadexcel(self): if not values: messagebox.showwarning("Warning", "Không có thông tin cần loại bỏ") else: values.clear() fsqc.clear() self._refresh() #event for _butheapsort def __heapsort(self): if self._list.rows_count <= 1: messagebox.showwarning("Warning", "không có list để sort") else: heap_sort() self._refresh() #event for load button def __load(self): if not self._file.value: tk.messagebox.showwarning("Warning", "Đường dẫn trống") else: try: if self._file.value != '': path = self._file.value read(path) self._list.value = [values_name] n = 0 for i in range(int(len(values) / numberofcols[0])): self._list.__add__(values[n:n + numberofcols[0]]) n = n + numberofcols[0] if self._checklistxoa.count < 1: for s in range(0, len(values_name)): self._checklistxoa.__add__((values_name[s])) if self._checklisttimkiem.count < 1: for s in range(0, len(values_name)): self._checklisttimkiem.__add__((values_name[s])) except: tk.messagebox.showwarning( "Warning", "Không thể đọc file khác excel hoặc đường dẫn không đúng") #event tab 2 #event for thêm button def __add(self): var = str(self._diachi.value).strip().split(',') var2 = var[0].split('/') var3 = var2[0] if self._list.rows_count < 1: messagebox.showwarning("Warning", "Không có list để thêm vào") elif len(var3) == 0 \ or (not var3[0].isdigit() and len(var3) == 1 ) \ or ( not var3[0:(len(var3) -1 )].isdigit() and len(var3) > 1 ) : messagebox.showwarning("Warning", "Địa chỉ không hợp lệ") elif not str(self._dientich.value).strip().isnumeric(): messagebox.showwarning("Warning", "Diện tích không hợp lệ") elif not str(self._chusohuuhientai.value).strip(): messagebox.showwarning("Warning", "Chủ sở hữu trống") elif not str(self._loainha.value).strip(): messagebox.showwarning("Warning", "loại nhà trống") elif not str(self._mucdichsudung.value).strip(): messagebox.showwarning("Warning", "mục đích sử dụng trống") elif not str(self._giatien.value).strip(): messagebox.showwarning("Warning", "giá tiền trống") else: index = self._list.rows_count values.append(index) values.append(str(self._diachi.value)) values.append(str(self._dientich.value)) values.append(str(self._chusohuuhientai.value)) values.append(str(self._loainha.value)) values.append(str(self._mucdichsudung.value)) values.append(str(self._giatien.value)) if var3.isdigit(): fsqc.append(int(var3[0:(len(var3))])) else: fsqc.append(int(var3[0:(len(var3) - 1)])) heap_sort() self._refresh() #event tab 3 #search : def __search(self): if self._list.rows_count <= 1: messagebox.showwarning("Warning", "Danh sách rỗng") elif not self._timkiem.value: messagebox.showwarning("Warning", "Vui lòng nhập nội dung tìm kiếm") elif self._checklisttimkiem.selected_row_index == -1: messagebox.showwarning("Warning", "Vui lòng chọn tiêu chí cần xóa") self._checklisttimkiem.show() self._buttonhideshowtimkiem.icon = 'img/hide_icon.png' self._buttonhideshowtimkiem.label = 'Ẩn tiêu chí' else: self._refresh() s = 1 while s < self._list.rows_count: if not (str(self._timkiem.value).strip()) in str( self._list.get_value( self._checklisttimkiem.selected_row_index, s)): self._list.__sub__(s) s = s - 1 s = s + 1 def _huybo(self): self._refresh() def _buthideshowtimkiem(self): if not values_name: tk.messagebox.showwarning("Warning", "Không có list để chọn tiêu chí") elif str(self._buttonhideshowtimkiem.label) == 'Ẩn tiêu chí': self._checklisttimkiem.hide() self._buttonhideshowtimkiem.icon = 'img/show.png' self._buttonhideshowtimkiem.label = 'Hiển thị tiêu chí' elif str(self._buttonhideshowtimkiem.label) == 'Hiển thị tiêu chí': self._checklisttimkiem.show() self._buttonhideshowtimkiem.icon = 'img/hide_icon.png' self._buttonhideshowtimkiem.label = 'Ẩn tiêu chí' #delete def __xoa(self): if self._list.rows_count <= 1: messagebox.showwarning("Warning", "Danh sách rỗng") elif not self._textxoa.value: messagebox.showwarning("Warning", "Vui lòng nhập nội dung cần xóa") elif self._checklistxoa.selected_row_index == -1: messagebox.showwarning("Warning", "Vui lòng chọn tiêu chí cần xóa") self._checklistxoa.show() self._buttonhideshowxoa.icon = 'img/hide_icon.png' self._buttonhideshowxoa.label = 'Ẩn tiêu chí' else: result = messagebox.askokcancel('Warning', 'Bạn có chắc muốn xóa?') startvaluescount = len(values) if result == 1: s = 1 while s < len(values): if (str(self._textxoa.value).strip()) in str( values[s + self._checklistxoa.selected_row_index - 1]): del fsqc[s // 7] del values[(s - 1):(s + 6)] s = s - 7 s = s + 7 self._refresh() if startvaluescount > len(values): messagebox.showinfo("Sucess!!", "Đã xóa dữ liệu thành công") self._checklistxoa.hide() self._buttonhideshowxoa.icon = 'img/show.png' self._buttonhideshowxoa.label = 'Hiển thị tiêu chí' else: messagebox.showinfo( "Opps", "Nội dung cần xóa không có trong cột tiêu chí trong danh sách" ) def _buthideshowxoa(self): if not values_name: tk.messagebox.showwarning("Warning", "Không có list để chọn tiêu chí") elif str(self._buttonhideshowxoa.label) == 'Ẩn tiêu chí': self._checklistxoa.hide() self._buttonhideshowxoa.icon = 'img/show.png' self._buttonhideshowxoa.label = 'Hiển thị tiêu chí' elif str(self._buttonhideshowxoa.label) == 'Hiển thị tiêu chí': self._checklistxoa.show() self._buttonhideshowxoa.icon = 'img/hide_icon.png' self._buttonhideshowxoa.label = 'Ẩn tiêu chí' #event tab 4 #event _butxuat def __xuat(self): # kiểm tra đường dẫn if not os.path.isdir(self._directory.value): messagebox.showwarning("Warning", "đường dẫn ko có") elif not self._tenfilexuat.value: messagebox.showwarning("Warning", "tên file rỗng") elif not values and not values_name: messagebox.showwarning("Warning", "không có dữ liệu để xuất") else: try: os.makedirs(self._tenfilexuat.value) os.rmdir(self._tenfilexuat.value) if os.path.isfile(self._directory.value + '/' + self._tenfilexuat.value + '.xls'): result = messagebox.askokcancel( 'Warning', 'File đã tồn tại bạn có muốn ghi đè lên ?') if result == 1: write(self._directory.value, self._tenfilexuat.value) myfile = Path(self._directory.value + '/' + self._tenfilexuat.value + '.xls') if myfile.is_file(): messagebox.showinfo("Sucess!!", "Đã xuất file thành công") else: result = messagebox.askokcancel('Warning', 'Bạn có chắc muốn xuất?') if result == 1: write(self._directory.value, self._tenfilexuat.value) myfile = Path(self._directory.value + '/' + self._tenfilexuat.value + '.xls') if myfile.is_file(): messagebox.showinfo("Sucess!!", "Đã xuất file thành công") except OSError: messagebox.showwarning( "Warning", "Tên file không hợp lệ hoặc đang được mở bởi ứng dụng khác" ) #event tab 5 #event _butmerge def _merge(self): if self._list.rows_count < 1: messagebox.showwarning("Warning", "Danh sách rỗng") else: result = messagebox.askokcancel('Warning', 'Bạn có chắc muốn gộp?') if result == 1: for i in range(1, len(valuesimport), 7): n = False for s in range(1, len(values), 7): if valuesimport[i] == values[s]: f = self._checklist.checked_indexes for c in range(0, len(f), 1): values[s + int(f[c]) - 1] = valuesimport[i + int(f[c]) - 1] n = True if not n: fsqc.append(fsqcimport[int(i / 7)]) for s in range(i - 1, i + 6): values.append(valuesimport[s]) self._refresh() for i in range(0, self._listmerge.rows_count): self._listmerge.__sub__(i) for j in range(0, self._listmerge.rows_count): self._listmerge.__sub__(j) self._clearimportdata() self._checklist.hide() self._buttonhideshow.icon = 'img/show.png' self._buttonhideshow.label = 'Hiển thị tùy chọn' self._buttonremovemerge.hide() self._butmerge.hide() self._buttonhideshow.hide() tk.messagebox.showinfo("Success", "Đã merge thành công") #event _buttonremovemerge def _remove(self): if self._listmerge.rows_count < 1: tk.messagebox.showwarning("Warning", "Đã xóa hết!") else: for i in range(0, self._listmerge.rows_count): self._listmerge.__sub__(i) for j in range(0, self._listmerge.rows_count): self._listmerge.__sub__(j) self._clearimportdata() self._checklist.clear() self._buttonremovemerge.hide() self._buttonhideshow.hide() self._checklist.hide() self._butmerge.hide() #event _buttonhideshow def _buthideshow(self): if str(self._buttonhideshow.label) == 'Ẩn tùy chọn': self._checklist.hide() self._buttonhideshow.icon = 'img/show.png' self._buttonhideshow.label = 'Hiển thị tùy chọn' elif str(self._buttonhideshow.label) == 'Hiển thị tùy chọn': self._checklist.show() self._buttonhideshow.icon = 'img/hide_icon.png' self._buttonhideshow.label = 'Ẩn tùy chọn' #event _buttonimport def _import(self): if not self._filemerge.value: tk.messagebox.showwarning("Warning", "Đường dẫn trống") else: path = self._filemerge.value try: importexcel(path) self._listmerge.value = [values_nameimport] n = 0 for i in range(int(len(valuesimport) / numberofcolsimport[0])): self._listmerge.__add__( valuesimport[n:n + numberofcolsimport[0]]) n = n + numberofcolsimport[0] if self._checklist.count < 1: for s in range(0, len(values_nameimport)): self._checklist.__add__((values_nameimport[s], True)) if self._listmerge and not self._buttonhideshow.visible: if str(self._buttonhideshow.label) == 'Ẩn tùy chọn': self._buttonhideshow.icon = 'img/show.png' self._buttonhideshow.label = 'Hiển thị tùy chọn' self._buttonhideshow.show() self._buttonremovemerge.show() self._butmerge.show() except: tk.messagebox.showwarning( "Warning", "Không thể đọc file khác excel hoặc đường dẫn không đúng") #reusable function def _refresh(self): for i in range(1, self._list.rows_count): self._list.__sub__(i) for j in range(1, self._list.rows_count): self._list.__sub__(j) n = 0 for i in range(int(len(values) / numberofcols[0])): self._list.__add__(values[n:n + numberofcols[0]]) n = n + numberofcols[0] # update STT for s in range(1, self._list.rows_count): values[(s - 1) * 7] = s self._list.set_value(0, s, s) def _clearimportdata(self): fsqcimport.clear() valuesimport.clear() sqcimport.clear() numberofcolsimport.clear() values_nameimport.clear() self._checklist.clear()
class RequestReimbursementForm(ModelFormWidget): """ """ TITLE = "Request Reimbursement" MODEL = Reimbursement HAS_CANCEL_BTN_ON_ADD = False HAS_CANCEL_BTN_ON_EDIT = False CLOSE_ON_REMOVE = True READ_ONLY = ["created", "modified", "status_changed", 'status'] INLINES = [ExpenseInline] FIELDSETS = [ no_columns('_previous', '_submit', "_print", '_printed', '_submit2approve','_reject', '_accept', 'bank_transfer_date', '_close', style="float:right"), "h3:Requester Information", segment( ("person", "iban") ), "h3:Expenses", segment("ExpenseInline"), ("created", "modified", "status", "status_changed") ] # Orquestra =============================================================== LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB # ========================================================================= def __init__(self, *args, **kwargs): self._previous = ControlButton( '<i class="ui icon paper plane outline"></i>Previous status', css="basic gray", visible = False, label_visible=False, default = self.__previous_status_evt ) self._submit = ControlButton( '<i class="ui icon paper plane outline"></i>Submit', css="blue", visible=False, label_visible=False, default = self.__submit_2_pending_evt ) self._print = ControlButton( '<i class="ui icon print"></i>Print', visible=False, css="basic blue", label_visible=False ) self._printed = ControlButton( '<i class="ui icon paper plane outline"></i>Set printed', visible=False, css="blue", label_visible=False, default=self.__set_printed_evt ) self._submit2approve = ControlButton( '<i class="ui icon paper plane outline"></i>Submit to approval', visible=False, css="blue", label_visible=False, default=self.__submit_2_approve_evt ) self._accept = ControlButton( '<i class="ui icon thumbs up"></i>Accept', visible=False, css="green", label_visible=False, default = self.__accept_evt ) self._reject = ControlButton( '<i class="ui icon thumbs down"></i>Reject', visible=False, css="red", label_visible=False, default=self.__reject_evt ) self._close = ControlButton( '<i class="ui icon thumbs up"></i>It was paid', visible=False, css="green basic", default=self.__set_closed_evt ) super().__init__(*args, **kwargs) self.person.enabled = False if self.model_object is None: user = PyFormsMiddleware.user() person = user.person_user.first() if person is not None: self.person.value = person.pk self.iban.value = person.privateinfo.iban else: self.warning( 'You need a Person profile associated to your account to be able to create reimbursements.' ) self.update_fields_visibility() def update_fields_visibility(self): obj = self.model_object if obj: self._print.value = 'window.open("{0}", "_blank");'.format( reverse("print-reimbursement-form", args=[obj.pk]) ) self._print.show() else: self._print.hide() # show submit button only when is draft if obj is None or obj.status != 'draft': self._submit.hide() # show print button only when the reimbursement is pending if obj is None: self._print.hide() if obj and self.has_update_permissions(): if obj.status == 'draft': self.bank_transfer_date.hide() self._submit.show() self._previous.hide() self._print.hide() self._printed.hide() self._submit2approve.hide() self._accept.hide() self._reject.hide() self._close.hide() self.iban.enabled = True elif obj.status == 'pending': self.bank_transfer_date.hide() self._previous.show() self._submit.hide() self._print.show() self._printed.show() self._submit2approve.hide() self._accept.hide() self._reject.hide() self._close.hide() self.iban.enabled = False elif obj.status == 'printed': self.bank_transfer_date.hide() self._previous.show() self._submit.hide() self._print.hide() self._printed.hide() self._submit2approve.show() self._accept.hide() self._reject.hide() self._close.hide() self.iban.enabled = False elif obj.status == 'submitted': self.bank_transfer_date.hide() self._previous.show() self._submit.hide() self._print.hide() self._printed.hide() self._submit2approve.hide() self._accept.show() self._reject.show() self._close.hide() self.iban.enabled = False elif obj.status in ['rejected', 'approved']: self._previous.hide() self._submit.hide() self._print.hide() self._printed.hide() self._submit2approve.hide() self._accept.hide() self._reject.hide() self.iban.enabled = False if obj.status == 'approved': self.bank_transfer_date.show() self._close.show() else: self.bank_transfer_date.hide() self._close.hide() elif obj.status == 'closed': self.bank_transfer_date.show() self.bank_transfer_date.readonly = True self._previous.hide() self._submit.hide() self._print.hide() self._printed.hide() self._submit2approve.hide() self._accept.hide() self._reject.hide() self._close.hide() self.iban.enabled = False else: self.bank_transfer_date.hide() self._submit.hide() self._previous.hide() self._print.hide() self._printed.hide() self._submit2approve.hide() self._accept.hide() self._reject.hide() self._close.hide() self.iban.enabled = True if obj.status == 'closed': self.bank_transfer_date.show() self.bank_transfer_date.readonly = True def save_btn_event(self): super().save_btn_event() self.update_fields_visibility() def __previous_status_evt(self): if not self.has_update_permissions(): raise Exception('No permission') obj = self.model_object obj.previous_status() self.show_edit_form(self.object_pk) self.update_fields_visibility() def __set_printed_evt(self): if not self.has_update_permissions(): raise Exception('No permission') obj = self.model_object obj.set_printed() self.show_edit_form(self.object_pk) self.update_fields_visibility() def __submit_2_pending_evt(self): """ Notify the users with approval responsibility about the new reimbursement """ if not self.has_update_permissions(): raise Exception('No permission') obj = self.model_object obj.submit_to_pending() self.show_edit_form(self.object_pk) self.update_fields_visibility() def __submit_2_approve_evt(self): if not self.has_update_permissions(): raise Exception('No permission') obj = self.model_object obj.submit_for_approval() self.show_edit_form(self.object_pk) self.update_fields_visibility() def __accept_evt(self): if not self.has_update_permissions(): raise Exception('No permission') obj = self.model_object obj.accept() self.show_edit_form(self.object_pk) self.update_fields_visibility() def __reject_evt(self): if not self.has_update_permissions(): raise Exception('No permission') obj = self.model_object obj.reject() self.show_edit_form(self.object_pk) self.update_fields_visibility() def __set_closed_evt(self): if not self.has_update_permissions(): raise Exception('No permission') obj = self.model_object obj.bank_transfer_date = self.bank_transfer_date.value obj.set_closed() # this function will save the object self.show_edit_form(self.object_pk) self.update_fields_visibility() def get_readonly(self, default): res = super().get_readonly(default) obj = self.model_object if obj and obj.status in ['rejected', 'approved']: return res + ['status'] if obj and obj.has_approve_permissions(PyFormsMiddleware.user()): return res else: return res + ['status'] def update_object_fields(self, obj): """ Update the created by field. :param Reimbursement obj: :return: Return the updated reimbursement object. """ obj = super().update_object_fields(obj) if obj.pk is None: obj.created_by = PyFormsMiddleware.user() return obj @property def title(self): obj = self.model_object if obj: name = obj.requester_name total = obj.total return f"({obj.pk}) {obj.person} ({obj.total})" else: return super().title
class AccessRequestFormWidget(ModelFormWidget): TITLE = "Access request" MODEL = AccessRequest LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB READ_ONLY = [ 'resource', 'requested_by', 'requested_on', 'reason', 'closed_by', 'closed_on' ] FIELDSETS = [ no_columns('resource', 'requested_by', 'requested_on'), 'reason', 'comment', no_columns('_until', '_acceptbtn', '_rejectbtn', 'closed_by', 'closed_on') ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.resource.field_css = 'eleven wide' self._until = ControlDateTime('Access until', visible=False) self._acceptbtn = ControlButton('Accept', default=self.__accept_evt, css='basic green', visible=False) self._rejectbtn = ControlButton('Reject', default=self.__reject_evt, css='red', visible=False) req = self.model_object if req.is_approved() is None: self._acceptbtn.show() self._rejectbtn.show() self._until.show() self.closed_by.hide() self.closed_on.hide() else: self._until.hide() self.closed_by.show() self.closed_on.show() self.comment.readonly = True def has_remove_permissions(self): return False def has_add_permissions(self): return False def has_update_permissions(self): return False def __open_access_evt(self): pass def __accept_evt(self): req = self.model_object req.comment = self.comment.value req.accept(PyFormsMiddleware.user(), until=self._until.value, comment=self.comment.value) self._acceptbtn.hide() self._rejectbtn.hide() self._until.hide() self.success('The access request was accepted successfully.') self.closed_by.show() self.closed_on.show() self.closed_by.value = str(req.closed_by) self.closed_on.value = req.closed_on self.comment.readonly = True def __reject_evt(self): req = self.model_object req.comment = self.comment.value req.reject(PyFormsMiddleware.user(), comment=self.comment.value) self._acceptbtn.hide() self._rejectbtn.hide() self._until.hide() self.alert('The access request was rejected!') self.closed_by.show() self.closed_on.show() self.closed_by.value = str(req.closed_by) self.closed_on.value = req.closed_on self.comment.readonly = True @property def title(self): obj = self.model_object if obj is None: return ModelFormWidget.title.fget(self) else: return str(obj) @title.setter def title(self, value): ModelFormWidget.title.fset(self, value)