Beispiel #1
0
class Graph2Event(BaseWidget):
    def __init__(self, timeline=None):
        super(Graph2Event, self).__init__('Graph to event',
                                          parent_win=timeline)
        self.setContentsMargins(10, 10, 10, 10)
        self._timeline = timeline

        # Definition of the forms fields
        self._graphs_list = ControlList('Graphs list (try double click)')
        self._equation = ControlTextArea('Equation')
        self._eventname = ControlText('Event name', 'New event')
        self._rownumber = ControlNumber('Row number', 0, 0, 1000)
        self._mindiff = ControlNumber('Minimum of frames', 0, 0, 1000000)
        self._genevts_btn = ControlButton('Generate events')

        self._formset = [
            (['_graphs_list'], '||', [
                ('_eventname', '_rownumber', '_mindiff'),
                '_equation',
                '_genevts_btn',
            ]),
        ]

        self._graphs_list.cell_double_clicked_event = self.__cell_double_clicked_evt
        self._graphs_list.readonly = True
        self._graphs_list.select_entire_row = True
        self._genevts_btn.value = self.__generage_events_evt

    def __add__(self, other):
        self._graphs_list += [other.name]
        return self

    def __sub__(self, other):
        self._graphs_list -= other
        return self

    def rename_graph(self, graph_index, newname):
        self._graphs_list.set_value(graph_index, 0, newname)

    @property
    def graphs(self):
        return self._timeline._charts

    def __cell_double_clicked_evt(self, row, column):
        if len(self._equation.value.strip()) == 0:
            self._equation.value += '[{0}]'.format(
                self._graphs_list.value[row][column])
        else:
            self._equation.value += ' and [{0}]'.format(
                self._graphs_list.value[row][column])

    def __generage_events_evt(self):
        if len(self._eventname.value.strip()) == 0:
            QMessageBox.warning(self, "Attention!",
                                'The event name cannot be empty')
            return

        if len(self._equation.value.strip()) == 0:
            QMessageBox.warning(self, "Attention!",
                                'The equation cannot be empty')
            return

        max_frame = 0
        equation = self._equation.value
        for i, values in enumerate(self._graphs_list.value):
            graphname = '[{0}]'.format(values[0])

            if graphname in equation:
                max_frame = max(max_frame, len(self.graphs[i]))

            equation = equation.replace(graphname, 'graphs[{0}][i]'.format(i))

        graphs = self.graphs

        last_index = None
        last_value = False

        try:
            for i in range(max_frame):
                value = eval(equation)

                if not last_value and bool(value):
                    last_index = i
                    last_value = True

                if last_value and not bool(value):
                    if (i - 1 - last_index) >= self._mindiff.value:
                        self._timeline.addPeriod(
                            [last_index, i - 1, self._eventname.value],
                            int(self._rownumber.value))
                    last_value = False
                    last_index = None

            if last_value and (max_frame - last_index) >= self._mindiff.value:
                self._timeline.addPeriod(
                    [last_index, max_frame, self._eventname.value],
                    int(self._rownumber.value))
        except Exception as e:
            QMessageBox.warning(self, "Error!", str(e))

        self._timeline.repaint()
Beispiel #2
0
class GraphsProperties(BaseWidget):
    def __init__(self, timelineWidget=None, parent_win=None):
        super(GraphsProperties, self).__init__('Graphs properties',
                                               parent_win=parent_win)
        self.setContentsMargins(10, 10, 10, 10)
        self._mainwindow = parent_win
        self._timeline = timelineWidget

        #self.setMaximumWidth(300)

        # Definition of the forms fields
        self._graphs_list = ControlList('Graphs list')
        self._name = ControlText('Name')
        self._min_value = ControlNumber('Min',
                                        default=0,
                                        minimum=-sys.float_info.max,
                                        maximum=sys.float_info.max)
        self._max_value = ControlNumber('Max',
                                        default=0,
                                        minimum=-sys.float_info.max,
                                        maximum=sys.float_info.max)
        self._values_zoom = ControlSlider('Amplitude',
                                          default=100,
                                          minimum=60,
                                          maximum=400)
        self._values_top = ControlNumber('Bottom',
                                         default=0,
                                         minimum=-1000,
                                         maximum=1000)
        self._remove_graph_btn = ControlButton('Remove graph')
        self._value = ControlLabel()
        self._pickcolor = ControlButton('Pick color',
                                        default=self.__pickcolor_evt)

        self._graphs_list.readonly = True

        self._formset = [
            (['_graphs_list', '_remove_graph_btn'], '||', [
                ' ', '_name', ('_min_value', '_max_value', ' '),
                ('_values_top', '_pickcolor'), '_values_zoom',
                'info:Choose one graph and move the mouse over \nthe timeline to visualize the coordenates.',
                '_value'
            ]),
        ]

        self._graphs_list.select_entire_row = True
        self._graphs_list.item_selection_changed_event = self.__graphs_list_selection_changed

        self._loaded = False
        self._current_selected_graph = None

        self._name.changed_event = self.__save_graphs_changes
        self._min_value.changed_event = self.__save_graphs_changes
        self._max_value.changed_event = self.__save_graphs_changes
        self._values_zoom.changed_event = self.__save_graphs_changes
        self._values_top.changed_event = self.__save_graphs_changes

        self._name.enabled = False
        self._min_value.enabled = False
        self._max_value.enabled = False
        self._values_zoom.enabled = False
        self._values_top.enabled = False
        self._remove_graph_btn.enabled = False
        self._pickcolor.enabled = False

        self._remove_graph_btn.value = self.__remove_chart

    def __add__(self, other):
        self._graphs_list += [other.name]
        return self

    def __sub__(self, other):
        self._graphs_list -= other
        return self

    def rename_graph(self, graph_index, newname):
        self._graphs_list.set_value(graph_index, 0, newname)

    @property
    def selected_graph(self):
        index = self._graphs_list.selected_row_index
        return self._timeline._charts[index] if (index is not None) else None

    @property
    def coordenate_text(self):
        return self._value

    @coordenate_text.setter
    def coordenate_text(self, value):
        self._value.value = str(value) if value else ''

    def show(self):
        super(GraphsProperties, self).show()
        self._loaded = False

    def __pickcolor_evt(self):
        color = QColorDialog.getColor(self._current_selected_graph._color,
                                      self, 'Pick a color for the graph')
        self._current_selected_graph._color = color
        self._timeline.repaint()

    def __remove_chart(self):
        index = self._graphs_list.selected_row_index
        if index is not None:
            self._current_selected_graph = None
            self._timeline._charts.pop(index)
            self._loaded = False
            self._name.enabled = False
            self._min_value.enabled = False
            self._max_value.enabled = False
            self._values_zoom.enabled = False
            self._values_top.enabled = False
            self._remove_graph_btn.enabled = False
            self._pickcolor.enabled = False
            self._timeline.repaint()
            self._mainwindow -= index

    def __graphs_list_selection_changed(self):
        graph = self.selected_graph
        self._updating_properties = True

        if graph is not None:
            graphmin = np.asscalar(graph.graph_min) if isinstance(
                graph.graph_min, np.generic) else graph.graph_min
            graphmax = np.asscalar(graph.graph_max) if isinstance(
                graph.graph_max, np.generic) else graph.graph_max

            exponent_min = abs(decimal.Decimal(graphmin).as_tuple().exponent)
            exponent_max = abs(decimal.Decimal(graphmax).as_tuple().exponent)
            exponent_min = 4 if exponent_min > 4 else exponent_min
            exponent_max = 4 if exponent_min > 4 else exponent_min

            self._name.value = graph.name
            self._min_value.decimals = exponent_min
            self._min_value.value = graph.graph_min
            self._max_value.decimals = exponent_max

            self._max_value.value = graph.graph_max
            self._values_zoom.value = graph._zoom * 100.0
            self._values_top.value = graph._top

            self._loaded = True
            self._name.enabled = True
            self._min_value.enabled = True
            self._max_value.enabled = True
            self._values_zoom.enabled = True
            self._values_top.enabled = True
            self._remove_graph_btn.enabled = True
            self._pickcolor.enabled = True
            self._current_selected_graph = graph

        del self._updating_properties

    def __save_graphs_changes(self):
        if hasattr(self, '_updating_properties'): return

        if self._loaded and self._current_selected_graph is not None:
            graph = self._current_selected_graph

            #logger.debug('Before: Min: {0} | Max: {1} Zoom: {2}'.format(graph.graph_min, graph.graph_max,graph.zoom ) )

            graph.name = self._name.value
            graph.graph_min = self._min_value.value
            graph.graph_max = self._max_value.value

            graph.zoom = self._values_zoom.value / 100.0
            graph.top = self._values_top.value

            logger.debug('Min: {0} | Max: {1} Zoom: {2}'.format(
                graph.graph_min, graph.graph_max, graph.zoom))

            self._timeline.repaint()

    @property
    def graphs(self):
        return self._timeline.graphs

    def mouse_moveover_timeline_event(self, event):
        graph = self.selected_graph
        if graph is not None: graph.mouse_move_evt(event, 0, self.height())
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 GraphsEventsGenerator(BaseWidget):
    def __init__(self, timeline=None):
        super(GraphsEventsGenerator,
              self).__init__('Apply a function to the graph values',
                             parent_win=timeline)
        self.setContentsMargins(10, 10, 10, 10)
        self._timeline = timeline

        # Definition of the forms fields
        self._graphs_list = ControlList('Graphs list (try double click)',
                                        readonly=False,
                                        select_entire_row=True)
        self._equation = ControlTextArea('Equation')
        self._graphname = ControlText('Graph name')
        self._genevts_btn = ControlButton('Generate graph')

        self._formset = [
            (['_graphs_list'], '||', [
                '_graphname',
                '_equation',
                '_genevts_btn',
            ]),
        ]

        self._graphs_list.cell_double_clicked_event = self.__cell_double_clicked_evt
        self._graphs_list.readonly = True
        self._graphs_list.select_entire_row = True
        self._genevts_btn.value = self.__generage_events_evt

    def __add__(self, other):
        self._graphs_list += [other.name]
        return self

    def __sub__(self, other):
        self._graphs_list -= other
        return self

    def rename_graph(self, graph_index, newname):
        self._graphs_list.set_value(graph_index, 0, newname)

    @property
    def graphs(self):
        return self._timeline._charts

    def show(self):
        super(GraphsEventsGenerator, self).show()

        if len(self._graphname.value.strip()) == 0:
            self._graphname.value = "generated-graph-{0}".format(
                len(self._timeline.graphs))

    def __cell_double_clicked_evt(self, row, column):
        if len(self._equation.value.strip()) == 0:
            self._equation.value += '[{0}]'.format(
                self._graphs_list.value[row][column])
        else:
            self._equation.value += ' and [{0}]'.format(
                self._graphs_list.value[row][column])

    def __generage_events_evt(self):
        if len(self._graphname.value.strip()) == 0:
            QMessageBox.warning(self, "Attention!",
                                'The graph name cannot be empty')
            return

        if len(self._equation.value.strip()) == 0:
            QMessageBox.warning(self, "Attention!",
                                'The equation cannot be empty')
            return

        max_frame = 0
        equation = self._equation.value
        for i, values in enumerate(self._graphs_list.value):
            graphname = '[{0}]'.format(values[0])

            if graphname in equation:
                max_frame = max(max_frame, len(self.graphs[i]))

            equation = equation.replace(graphname, 'graphs[{0}][i]'.format(i))

        graphs = self.graphs
        data = []
        try:
            for i in range(max_frame):

                try:
                    value = eval(equation)
                except:
                    value = None

                data.append((i, value))
            self._timeline.add_chart(self._graphname.value, data)

            self._graphname.value = "generated-graph-{0}".format(
                len(self._timeline.graphs))
        except Exception as e:
            traceback.print_exc()
            QMessageBox.warning(self, "Error!", str(e))
class BoardTaskWindow(BoardTask, BaseWidget):
    """
    Define here which fields from the board_task model should appear on the setup configuration window.

    The model fields shall be defined as UI components like text fields, buttons, combo boxes, etc.

    You may also assign actions to these components.

    .. seealso::
        This class heavy relies on the corresponding API module.

        :py:class:`pybpodgui_api.models.setup.board_task.BoardTask`

    **Properties**

        states
            A list of task states associated with this BoardTask. States are defined on the task code.

        events
            A list of task events associated with this BoardTask. Events are defined on the task code.

        variables
            A list of task variables associated with this BoardTask. Variables are defined on the task code.

    **Private attributes**

        _states
            :class:`pyforms.controls.ControlList`

            UI list to show BoardTask states.

        _events
            :class:`pyforms.controls.ControlList`

            UI list to show BoardTask events.

        _vars
            :class:`pyforms.controls.ControlList`

            UI list to show BoardTask variables.

        _sync_btn
            :class:`pyforms.controls.ControlButton`

            Button to sync variables with board. Pressing the button fires the event :meth:`BoardTaskWindow.sync_variables`.

        _load_btn
            :class:`pyforms.controls.ControlButton`

            Button to read task variables from board. Pressing the button fires the event :meth:`BoardTaskWindow._BoardTaskWindow__load_task_details`.

        _formset
            Describe window fields organization to PyForms.

    **Methods**

    """
    def __init__(self, setup):
        BaseWidget.__init__(self,
                            "Variables config for {0}".format(setup.name))

        self._var_is_being_added = False

        self._updvars = ControlCheckBox('Update variables')
        self._vars = ControlList('Variables',
                                 add_function=self.__add_variable,
                                 remove_function=self.__remove_variable)

        BoardTask.__init__(self, setup)

        self._vars.horizontal_headers = ['NAME', 'TYPE', 'VALUE']
        self._vars.data_changed_event = self.__varslist_data_changed_evt

        self._formset = ['_updvars', '_vars']

        self._variable_rule = re.compile('^[A-Z0-9\_]+$')

    @property
    def update_variables(self):
        return self._updvars.value

    @update_variables.setter
    def update_variables(self, value):
        self._updvars.value = value

    def create_variable(self, name=None, value=None, datatype='string'):
        return TaskVariableWindow(self, name, value, datatype)

    def __varslist_data_changed_evt(self, row, col, item):

        # only verify if the list is being edited
        if self._var_is_being_added is True:
            return

        if col == 0 and item is not None:
            if not (self._variable_rule.match(item)
                    and item.startswith('VAR_')):
                self.critical(
                    "The name of the variable should start with VAR_, should be alphanumeric and upper case.",
                    "Error")

                self._vars.set_value(col, row,
                                     'VAR_{0}'.format(self._vars.rows_count))

        elif col == 2:
            datatype_combo = self._vars.get_value(1, row)
            datatype = datatype_combo.value if datatype_combo else None
            if datatype == 'number' and isinstance(
                    item, str) and not item.isnumeric():
                self.message("The value should be numeric.", "Error")
                self._vars.set_value(col, row, '0')

    def __add_variable(self):
        self._var_is_being_added = True
        var = self.create_variable('VAR_{0}'.format(self._vars.rows_count),
                                   '0')
        self._var_is_being_added = False

    def __remove_variable(self):
        if self._vars.selected_row_index is not None:
            var = self.variables[self._vars.selected_row_index]
            self.variables.remove(var)
            self._vars -= -1

    def before_close(self):
        return False
class UserWidget(User, BaseWidget):
    def __init__(self,
                 admin=None,
                 connection=None,
                 flag='',
                 uid='',
                 email='',
                 name='',
                 services={}):
        super(UserWidget, self).__init__(uid, email, name, services)
        BaseWidget.__init__(self, 'User')
        self._admin = admin
        self._connection = connection
        self._flag = flag
        self.changes = []  #0 is name change, 1 is services change
        if flag == 'edit':
            self._editBtn = ControlButton('Edit')
            self._editBtn.value = self._edit
        elif flag == 'new':
            self._editBtn = ControlButton('Save')
            self._editBtn.value = self._save
        else:
            self._closeBtn = ControlButton('Close')
            self._closeBtn.value = self._close

        if uid != '':
            self._uid_field = ControlText('User_Key')
            self._uid_field.value = uid
        self._email_field = ControlText('Email')
        self._email_field.readonly = True
        if email != '':
            self._email_field.value = email

        self._name_field = ControlText('Name')
        self._name_field.readonly = True
        if name != '':
            self._name_field.value = name

        self._services = services
        self._services_field = ControlList('Services')
        self._services_field.readonly = True
        self._services_field.horizontal_headers = ['Service', 'Value']
        #self._services_field.cell_double_clicked_event = None
        if services != {}:
            for i in services:
                self._services_field.__add__([i, services[i]])

    def _edit(self):
        self._editBtn.label = 'Save'
        self._editBtn.value = self._save
        self._email_field.readonly = False
        self._name_field.readonly = False
        self._services_field.readonly = False
        self._services_field.cell_double_clicked_event = self._toggle

    def _save(self):
        if self.parent != None:
            self.name = self._name_field.value
            self.email = self._email_field.value
            self.services = self._services
            self.uid = self._uid_field.value
            if self._flag == 'edit':
                self.parent._update_user(self)
            elif self._flag == 'new':
                self.parent._add_User(self)
        self._close()

    def _toggle(self, row, column):
        val = self._services_field.get_value(column, row)
        if val == True:
            self._services_field.set_value(column, row, False)
            self._services[self._services_field.get_value(0, row)] = False
        else:
            self._services_field.set_value(column, row, True)
            self._services[self._services_field.get_value(0, row)] = True

    def _close(self):
        close_win(self)
Beispiel #7
0
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()