Пример #1
0
    def test_time_pair(self):
        json_time = {
            "start": "12:20",
            "end": "14:00"
        }

        t = TimePair()
        t.load(json_time)
        self.assertEqual(str(t.save()),
                         str(json_time),
                         "Time save/Load test failed")
Пример #2
0
 def combo_box_start_changed(self, index) -> None:
     """
     Slot to change the end time of the pair.
     """
     old_index = self.combo_box_end.currentIndex()
     self.combo_box_end.clear()
     self.combo_box_end.addItems(TimePair.time_ends()[index:])
Пример #3
0
    def set_pair(self, pair: StudentPair) -> None:
        """
        Method to set the pair to edit.

        :param pair: Pair
        """
        self._edit_pair = pair
        self.line_edit_title.setText(str(self._edit_pair["title"]))
        self.line_edit_lecturer.setText(str(self._edit_pair["lecturer"]))
        self.combo_box_type.setCurrentText(str(self._edit_pair["type"]))
        self.line_edit_classes.setText(str(self._edit_pair["classroom"]))
        self.combo_box_subgroup.setCurrentText(str(
            self._edit_pair["subgroup"]))

        time: TimePair = self._edit_pair["time"]
        if time is not None:
            number = time.get_number()
            self.combo_box_start.setCurrentIndex(number)
            self.combo_box_end.clear()
            self.combo_box_end.addItems(TimePair.time_ends()[number:])
            self.combo_box_end.setCurrentIndex(time.duration() - 1)

        self._dates = self._edit_pair["dates"]
        self.update_list_widget_date()
Пример #4
0
    def __init__(self, number, parent: QWidget = None):
        super().__init__(parent)

        self._number: int = number
        self._edit_pair: StudentPair = None
        self._dates: DatePair = DatePair()

        # window settings
        self.setWindowFlag(Qt.WindowContextHelpButtonHint, False)
        self.setWindowTitle(self.tr("Creator"))
        self.setMinimumSize(640, 350)
        self.resize(800, 400)

        # general settings window
        self.group_box_general = QGroupBox(self.tr("General"))
        self.layout_general = QFormLayout(self.group_box_general)

        # title
        self.label_title = QLabel(self.tr("Title"))
        self.layout_general.setWidget(0, QFormLayout.LabelRole,
                                      self.label_title)
        self.line_edit_title = QLineEdit("")
        self.layout_general.setWidget(0, QFormLayout.FieldRole,
                                      self.line_edit_title)

        # lecturer
        self.label_lecturer = QLabel(self.tr("Lecturer"))
        self.layout_general.setWidget(1, QFormLayout.LabelRole,
                                      self.label_lecturer)
        self.line_edit_lecturer = QLineEdit("")
        self.layout_general.setWidget(1, QFormLayout.FieldRole,
                                      self.line_edit_lecturer)

        self.completer = QCompleter(LecturerPair.get_lecturers())
        self.completer.setModelSorting(QCompleter.CaseSensitivelySortedModel)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setFilterMode(Qt.MatchContains)
        self.line_edit_lecturer.setCompleter(self.completer)

        # type
        self.label_type = QLabel(self.tr("Type"))
        self.layout_general.setWidget(2, QFormLayout.LabelRole,
                                      self.label_type)
        self.combo_box_type = QComboBox()
        self.layout_general.setWidget(2, QFormLayout.FieldRole,
                                      self.combo_box_type)

        for name, attrib in TypePairAttrib.items():
            self.combo_box_type.addItem(name, attrib)

        # classes
        self.label_classes = QLabel(self.tr("Classes"))
        self.layout_general.setWidget(3, QFormLayout.LabelRole,
                                      self.label_classes)
        self.line_edit_classes = QLineEdit("")
        self.layout_general.setWidget(3, QFormLayout.FieldRole,
                                      self.line_edit_classes)

        # subgroup
        self.label_subgroup = QLabel(self.tr("Subgroup"))
        self.layout_general.setWidget(4, QFormLayout.LabelRole,
                                      self.label_subgroup)
        self.combo_box_subgroup = QComboBox()
        self.layout_general.setWidget(4, QFormLayout.FieldRole,
                                      self.combo_box_subgroup)

        for name, attrib in SubgroupPairAttrib.items():
            self.combo_box_subgroup.addItem(name, attrib)

        # time setting
        self.group_box_time = QGroupBox(self.tr("Time"))
        self.layout_time = QFormLayout(self.group_box_time)

        self.label_start = QLabel(self.tr("Start"))
        self.layout_time.setWidget(0, QFormLayout.LabelRole, self.label_start)
        self.combo_box_start = QComboBox()
        self.layout_time.setWidget(0, QFormLayout.FieldRole,
                                   self.combo_box_start)

        self.label_end = QLabel(self.tr("End"))
        self.layout_time.setWidget(1, QFormLayout.LabelRole, self.label_end)
        self.combo_box_end = QComboBox()
        self.layout_time.setWidget(1, QFormLayout.FieldRole,
                                   self.combo_box_end)

        self.combo_box_start.addItems(TimePair.time_starts())
        self.combo_box_start.setCurrentIndex(self._number)
        self.combo_box_end.addItems(TimePair.time_ends())
        self.combo_box_end.setCurrentIndex(self._number)

        # date setting
        self.group_box_date = QGroupBox(self.tr("Date"))
        self.layout_date_edit = QHBoxLayout(self.group_box_date)

        self.list_widget_date = QListWidget(self.group_box_date)
        self.layout_date_edit.addWidget(self.list_widget_date)

        self.layout_date_edit_navigate = QVBoxLayout()
        self.layout_date_edit.addLayout(self.layout_date_edit_navigate)

        self.push_button_add_date = QPushButton(self.tr("Add"))
        self.layout_date_edit_navigate.addWidget(self.push_button_add_date)

        self.push_button_edit_date = QPushButton(self.tr("Edit"))
        self.layout_date_edit_navigate.addWidget(self.push_button_edit_date)

        self.push_button_remove_date = QPushButton(self.tr("Remove"))
        self.layout_date_edit_navigate.addWidget(self.push_button_remove_date)

        self.layout_date_edit_navigate.addStretch(1)

        # navigate
        self.layout_navigate = QHBoxLayout()

        self.layout_navigate.addStretch(1)

        self.push_button_ok = QPushButton(self.tr("OK"))
        self.layout_navigate.addWidget(self.push_button_ok)

        self.push_button_cancel = QPushButton(self.tr("Cancel"))
        self.layout_navigate.addWidget(self.push_button_cancel)

        # layout settings
        self.layout_general_time = QVBoxLayout()
        self.layout_general_time.addWidget(self.group_box_general)
        self.layout_general_time.addWidget(self.group_box_time)

        self.layout_center = QHBoxLayout()
        self.layout_center.addLayout(self.layout_general_time)
        self.layout_center.addWidget(self.group_box_date)

        self.layout_main = QVBoxLayout()
        self.layout_main.addLayout(self.layout_center)
        self.layout_main.addLayout(self.layout_navigate)

        self.setLayout(self.layout_main)

        # connection
        self.combo_box_start.currentIndexChanged.connect(
            self.combo_box_start_changed)
        self.list_widget_date.itemDoubleClicked.connect(
            self.push_button_edit_date_clicked)
        self.push_button_add_date.clicked.connect(
            self.push_button_add_date_clicked)
        self.push_button_edit_date.clicked.connect(
            self.push_button_edit_date_clicked)
        self.push_button_remove_date.clicked.connect(
            self.push_button_remove_date_clicked)
        self.push_button_ok.clicked.connect(self.push_button_ok_clicked)
        self.push_button_cancel.clicked.connect(
            self.push_button_cancel_clicked)
def export_full_to_pdf(schedule_ref: Schedule,
                       title_text: str,
                       file_path: str,
                       font_name: str,
                       font_path: str,
                       encoding: str,
                       progress=None) -> None:
    """
    Method for exports to PDF file
    """
    file = QFileInfo(file_path)

    # pdf
    pdf = FPDF(orientation="L")

    # encoding
    if encoding == "UTF-8":
        pdf.add_font(font_name, "", font_path, uni=True)
    else:
        pdf.add_font(font_name, "", font_path)
        pdf.set_doc_option("core_fonts_encoding", encoding)

    pdf.set_font(font_name)
    pdf.add_page()

    x, y = float(pdf.get_x()), float(pdf.get_y())
    w = float(pdf.w) - 2 * float(pdf.get_x())
    h = float(pdf.h) - 2 * float(pdf.get_y()) - 6

    pdf.set_auto_page_break(True, margin=y)

    title = 10

    pdf.set_font_size(14)
    pdf.cell(w, title, txt=title_text, align="C", border=0)
    h -= title

    first_column, first_row = 4, 4

    step_column = (w - first_row) / 8
    step_row = (h - first_column) / 6

    indexes = schedule_ref.indexes()
    table_widget = schedule_editor_window.ScheduleTableWidget()
    table_widget.set_schedule(schedule_ref)

    # processing
    week_step = 100 / 7
    count = 0

    i = 0
    while i < 7:
        j = 0
        while j < 9:
            if i == 0 and j == 0:
                # upper-left cell
                pdf.set_xy(x, y + title)
                pdf.cell(first_column, first_row, border=1)
                j += 1
            elif i == 0:
                # top cells with time
                pdf.set_xy(x + first_row + step_column * (j - 1), y + title)
                pdf.set_font_size(8)
                pdf.cell(step_column,
                         first_row,
                         txt=TimePair.time_start_end(j - 1),
                         align="C",
                         border=1)
                j += 1
            elif j == 0:
                # left cells with days of the week
                pdf.set_xy(
                    x,
                    y + title + first_column + step_row * (i - 1) + step_row)
                pdf.rotate(90)
                pdf.set_font_size(8)
                pdf.cell(step_row,
                         first_row,
                         txt=str(DaysOfWeek.value_of(i - 1)),
                         align="C",
                         border=1)
                pdf.rotate(0)
                j += 1
            else:
                # cells inside the table
                pdf.set_xy(x + first_row + step_column * (j - 1),
                           y + title + first_column + step_row * (i - 1))

                simple_row = (step_row / indexes[i - 1])
                prev_x, prev_y = pdf.get_x(), pdf.get_y()

                start_index = sum(indexes[r] for r in range(i - 1))
                number_row = 0
                for m in range(start_index, start_index + indexes[i - 1]):
                    item = table_widget.item(m, j - 1)
                    if item is not None:
                        x_span_count = table_widget.columnSpan(m, j - 1)
                        y_span_count = table_widget.rowSpan(m, j - 1)

                        pdf.set_xy(prev_x, prev_y + number_row * simple_row)

                        pdf.cell(step_column * x_span_count,
                                 simple_row * y_span_count,
                                 border=1)

                        text = item.text()
                        if text != "":
                            draw_text(
                                pdf, x + first_row + step_column * (j - 1),
                                y + title + first_column + step_row * (i - 1) +
                                simple_row * number_row,
                                step_column * x_span_count,
                                simple_row * y_span_count, text)
                    number_row += 1
                    pdf.set_xy(prev_x, prev_y)
                j += 1
        i += 1

        if progress is not None:
            count += 1
            progress.setValue(week_step * count)
            if progress.wasCanceled():
                break

    pdf.output(file.absoluteFilePath())
def export_weeks_to_pdf(schedule_ref: Schedule,
                        title_text: str,
                        add_date: bool,
                        file_path: str,
                        font_name: str,
                        font_path: str,
                        encoding: str,
                        start: datetime.date,
                        end: datetime.date,
                        color_a: QColor,
                        color_b: QColor,
                        progress=None) -> None:
    """
    Method for exports to PDF file
    """

    file = QFileInfo(file_path)

    # pdf
    pdf = FPDF(orientation="L")

    # encoding
    if encoding == "UTF-8":
        pdf.add_font(font_name, "", font_path, uni=True)
    else:
        pdf.add_font(font_name, "", font_path)
        pdf.set_doc_option("core_fonts_encoding", encoding)

    # processing
    week_step = 100 / (end - start).days / 7
    count = 0

    pdf.set_font(font_name)

    while True:
        pdf.add_page()

        schedule = schedule_ref.create_week_schedule(
            start, start + datetime.timedelta(days=6))

        indexes = schedule.indexes()
        table_widget = schedule_editor_window.ScheduleTableWidget()
        table_widget.set_schedule(schedule)

        start += datetime.timedelta(days=6)

        x, y = float(pdf.get_x()), float(pdf.get_y())
        w = float(pdf.w) - 2 * float(pdf.get_x())
        h = float(pdf.h) - 2 * float(pdf.get_y()) - 6

        pdf.set_auto_page_break(True, margin=y)

        title = 10
        title_page = title_text
        if add_date:
            start_week = (start +
                          datetime.timedelta(days=-6)).strftime("%d.%m.%Y")
            end_week = start.strftime("%d.%m.%Y")
            title_page += f". {start_week} - {end_week}"

        pdf.set_font_size(14)
        pdf.cell(w, title, txt=title_page, align="C", border=0)
        h -= title

        first_column, first_row = 4, 4

        step_column = (w - first_row) / 8
        step_row = (h - first_column) / 6

        i = 0
        while i < 7:
            j = 0
            while j < 9:
                if i == 0 and j == 0:
                    # upper-left cell
                    pdf.set_xy(x, y + title)
                    pdf.cell(first_column, first_row, border=1)
                    j += 1
                elif i == 0:
                    # top cells with time
                    pdf.set_xy(x + first_row + step_column * (j - 1),
                               y + title)
                    pdf.set_font_size(8)
                    pdf.cell(step_column,
                             first_row,
                             txt=TimePair.time_start_end(j - 1),
                             align="C",
                             border=1)
                    j += 1
                elif j == 0:
                    # left cells with days of the week
                    pdf.set_xy(
                        x, y + title + first_column + step_row * (i - 1) +
                        step_row)
                    pdf.rotate(90)
                    pdf.set_font_size(8)
                    pdf.cell(step_row,
                             first_row,
                             txt=str(DaysOfWeek.value_of(i - 1)),
                             align="C",
                             border=1)
                    pdf.rotate(0)
                    j += 1
                else:
                    # cells inside the table
                    pdf.set_xy(x + first_row + step_column * (j - 1),
                               y + title + first_column + step_row * (i - 1))

                    simple_row = (step_row / indexes[i - 1])
                    prev_x, prev_y = pdf.get_x(), pdf.get_y()

                    start_index = sum(indexes[r] for r in range(i - 1))
                    number_row = 0
                    for m in range(start_index, start_index + indexes[i - 1]):
                        item = table_widget.item(m, j - 1)
                        if item is not None:
                            x_span_count = table_widget.columnSpan(m, j - 1)
                            y_span_count = table_widget.rowSpan(m, j - 1)

                            pdf.set_xy(prev_x,
                                       prev_y + number_row * simple_row)

                            # pdf.cell(step_column * x_span_count,
                            #          simple_row * y_span_count,
                            #          border=1)

                            day, number, duration = i - 1, j - 1, x_span_count
                            pairs = schedule.pairs_by_index(
                                day, number, duration, number_row)

                            # select color for cell
                            if all(pair["subgroup"].get_subgroup() ==
                                   SubgroupPairAttrib.Common
                                   for pair in pairs):
                                # common
                                pdf.cell(step_column * x_span_count,
                                         simple_row * y_span_count,
                                         border=1)

                            elif all(pair["subgroup"].get_subgroup() ==
                                     SubgroupPairAttrib.A for pair in pairs):
                                # A subgroup
                                pdf.set_fill_color(color_a.red(),
                                                   color_a.green(),
                                                   color_a.blue())
                                pdf.cell(step_column * x_span_count,
                                         simple_row * y_span_count,
                                         border=1,
                                         fill=1)
                            elif all(pair["subgroup"].get_subgroup() ==
                                     SubgroupPairAttrib.B for pair in pairs):
                                # B subgroup
                                pdf.set_fill_color(color_b.red(),
                                                   color_b.green(),
                                                   color_b.blue())
                                pdf.cell(step_column * x_span_count,
                                         simple_row * y_span_count,
                                         border=1,
                                         fill=1)
                            else:
                                # A and B subgroup
                                prev_x = pdf.get_x()
                                prev_y = pdf.get_y()

                                toggle = True

                                row = 5
                                column = math.ceil(step_column * x_span_count /
                                                   step_row * row)

                                for t in range(column):
                                    for n in range(row):
                                        pdf.set_xy(
                                            prev_x + t * step_column *
                                            x_span_count / column,
                                            prev_y + n * step_row / row)

                                        if toggle:
                                            color = color_a
                                            toggle = False
                                        else:
                                            color = color_b
                                            toggle = True

                                        pdf.set_fill_color(
                                            color.red(), color.green(),
                                            color.blue())
                                        pdf.cell(step_column * x_span_count /
                                                 column,
                                                 simple_row * y_span_count /
                                                 row,
                                                 border=0)

                                pdf.set_xy(prev_x, prev_y)
                                pdf.cell(step_column * x_span_count,
                                         simple_row * y_span_count,
                                         border=1)

                            if len(pairs) != 0:
                                text = "\n".join(str(pair) for pair in pairs)
                                draw_text(
                                    pdf, x + first_row + step_column * (j - 1),
                                    y + title + first_column + step_row *
                                    (i - 1) + simple_row * number_row,
                                    step_column * x_span_count,
                                    simple_row * y_span_count, text)
                        number_row += 1
                        pdf.set_xy(prev_x, prev_y)
                    j += 1

                    # old
                    # pairs = schedule.pairs_by_index(i - 1, j - 1, 1) \
                    #     + schedule.pairs_by_index(i - 1, j - 1, 2)
                    #
                    # max_duration = max([1, *[pair["time"].duration() for pair in pairs]])
                    #
                    # # select color for cell
                    # if all(pair["subgroup"].get_subgroup() == SubgroupPairAttrib.Common
                    #        for pair in pairs):
                    #     # common
                    #     pdf.cell(step_column * max_duration,
                    #              step_row,
                    #              border=1)
                    # elif all(pair["subgroup"].get_subgroup() == SubgroupPairAttrib.A
                    #          for pair in pairs):
                    #     # A subgroup
                    #     pdf.set_fill_color(color_a.red(), color_a.green(), color_a.blue())
                    #     pdf.cell(step_column * max_duration,
                    #              step_row,
                    #              border=1,
                    #              fill=1)
                    # elif all(pair["subgroup"].get_subgroup() == SubgroupPairAttrib.B
                    #          for pair in pairs):
                    #     # B subgroup
                    #     pdf.set_fill_color(color_b.red(), color_b.green(), color_b.blue())
                    #     pdf.cell(step_column * max_duration,
                    #              step_row,
                    #              border=1,
                    #              fill=1)
                    # else:
                    #     # A and B subgroup
                    #     prev_x = pdf.get_x()
                    #     prev_y = pdf.get_y()
                    #
                    #     toggle = True
                    #
                    #     row = 5
                    #     column = math.ceil(step_column * max_duration / step_row * row)
                    #
                    #     for m in range(column):
                    #         for n in range(row):
                    #             pdf.set_xy(prev_x + m * step_column * max_duration / column,
                    #                        prev_y + n * step_row / row)
                    #
                    #             if toggle:
                    #                 color = color_a
                    #                 toggle = False
                    #             else:
                    #                 color = color_b
                    #                 toggle = True
                    #
                    #             pdf.set_fill_color(color.red(), color.green(), color.blue())
                    #             pdf.cell(step_column * max_duration / column,
                    #                      step_row / row,
                    #                      border=0,
                    #                      fill=1)
                    #     pdf.set_xy(prev_x, prev_y)
                    #     pdf.cell(step_column * max_duration,
                    #              step_row,
                    #              border=1)
                    # text = ""
                    # for pair in pairs:
                    #     text += str(pair) + "\n"
                    #
                    # if text != "":
                    #     draw_text(pdf,
                    #               x + first_row + step_column * (j - 1),
                    #               y + title + first_column + step_row
                    #               * (i - 1),
                    #               step_column * max_duration,
                    #               step_row,
                    #               text)
                    # j += max_duration
            i += 1

        if progress is not None:
            count += 1
            progress.setValue(week_step * count)
            if progress.wasCanceled():
                break

        start += datetime.timedelta(days=1)
        if end <= start:
            break

    pdf.output(file.absoluteFilePath())
Пример #7
0
    def __init__(self):
        super().__init__()

        self._schedule = Schedule()
        self._indexes_ref = self._schedule.indexes()
        self._file = None

        # window settings
        self.setWindowTitle(self.tr("Schedule Editor"))
        self.setMinimumSize(800, 600)

        # central widget settings
        self.table_widget = ScheduleTableWidget()
        self.table_widget.set_schedule(self._schedule)
        self.table_widget.setVerticalHeader(
            CustomHeaderView(Qt.Vertical, self._indexes_ref))
        self.table_widget.setHorizontalHeader(CustomHeaderView(Qt.Horizontal))
        self.table_widget.setWordWrap(True)
        self.table_widget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table_widget.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table_widget.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.table_widget.horizontalHeader().setMaximumHeight(25)
        self.table_widget.horizontalHeader().setStretchLastSection(True)
        self.table_widget.verticalHeader().setSectionResizeMode(
            QHeaderView.Fixed)
        self.table_widget.verticalHeader().setMaximumWidth(25)
        self.table_widget.verticalHeader().setStretchLastSection(True)
        self.table_widget.setSizePolicy(QSizePolicy.MinimumExpanding,
                                        QSizePolicy.MinimumExpanding)
        self.table_widget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.table_widget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.table_widget.setColumnCount(self._schedule.columns())
        for i in range(8):
            item = QTableWidgetItem(TimePair.time_start_end(i))
            self.table_widget.setHorizontalHeaderItem(i, item)

        self.table_widget.setRowCount(self._schedule.rows())
        for i, day in enumerate(DaysOfWeek.to_list()):
            item = QTableWidgetItem(day)
            self.table_widget.setVerticalHeaderItem(i, item)

        self.setCentralWidget(self.table_widget)

        # menu bar settings
        self.menu_bar = self.menuBar()
        self.menu_file = self.menu_bar.addMenu(self.tr("&File"))

        self.action_new_file = QAction(QIcon.fromTheme("document-new"),
                                       self.tr("&New file"), self)
        self.action_new_file.setShortcut("Ctrl+N")
        self.menu_file.addAction(self.action_new_file)

        self.action_open = QAction(QIcon.fromTheme("document-open"),
                                   self.tr("&Open"), self)
        self.action_open.setShortcut("Ctrl+O")
        self.menu_file.addAction(self.action_open)

        self.action_save = QAction(QIcon.fromTheme("document-save"),
                                   self.tr("&Save"), self)
        self.action_save.setShortcut("Ctrl+S")
        self.menu_file.addAction(self.action_save)

        self.action_save_as = QAction(QIcon.fromTheme("document-save-as"),
                                      self.tr("Save as..."), self)
        self.action_save_as.setShortcut("Ctrl+S+A")
        self.menu_file.addAction(self.action_save_as)

        self.action_export = QAction(self.tr("Export"), self)
        self.action_export.setShortcut("Ctrl+E")
        self.menu_file.addAction(self.action_export)

        self.action_import = QAction(self.tr("Import"), self)
        self.action_import.setShortcut("Ctrl+I")
        self.menu_file.addAction(self.action_import)

        self.menu_file.addSeparator()

        self.action_settings = QAction(self.tr("Settings"), self)
        self.menu_file.addAction(self.action_settings)

        self.action_about = QAction(self.tr("About"), self)
        self.menu_file.addAction(self.action_about)

        self.action_exit = QAction(self.tr("&Quit"), self)
        self.action_exit.setShortcut("Ctrl+Q")
        self.menu_file.addAction(self.action_exit)

        # status bar settings
        self.statusBar().showMessage(self.tr("Ready!"))

        # connection
        self.action_new_file.triggered.connect(self.action_new_file_clicked)
        self.action_open.triggered.connect(self.action_open_clicked)
        self.action_save.triggered.connect(self.action_save_clicked)
        self.action_save_as.triggered.connect(self.action_save_as_clicked)
        self.action_export.triggered.connect(self.action_export_clicked)
        self.action_import.triggered.connect(self.action_import_clicked)
        self.action_settings.triggered.connect(self.action_settings_clicked)
        self.action_about.triggered.connect(self.action_about_clicked)
        self.action_exit.triggered.connect(self.close)

        # self.table_widget.clicked.connect(self.test)
        self.table_widget.doubleClicked.connect(self.cell_clicked)
        self.table_widget.customContextMenuRequested.connect(
            self.context_menu_requested)
def import_from_pdf(process_id, manager: ImportManager) -> None:
    tesseract = TesseractWrapper(tesseract_path=manager.tesseract_path)
    while not manager.queue.empty():
        try:
            file_path = manager.queue.get(True, 1)
            file = QFileInfo(file_path)

            # convert from pdf to PIL image
            img_pdf = pdf2image.convert_from_path(
                file.absoluteFilePath(),
                dpi=manager.dpi,
                poppler_path=manager.poppler_path)
            img_pdf = img_pdf[0].convert('RGB')

            # convert to NumPy array
            img = np.array(img_pdf)
            img = img[:, :, ::-1].copy()

            # set mask
            grey = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
            thresh = cv.threshold(grey, 127, 255, 0)[1]

            if manager.flags["stop"]:
                break

            # found contours
            contours = cv.findContours(thresh, cv.RETR_TREE,
                                       cv.CHAIN_APPROX_SIMPLE)[0]

            height, width = img.shape[:2]
            # max and min area of rect
            max_area = height * width / 20
            min_area = max_area / 40

            cells = []
            time_cells = dict()

            contours_number = len(contours)
            number = 0

            for k, contour in enumerate(contours, 1):
                rect = cv.minAreaRect(contour)
                area = int(rect[1][0] * rect[1][1])
                if min_area < area < max_area:
                    if manager.flags["stop"]:
                        break

                    x, y, w, h = cv.boundingRect(contour)
                    crop_img = img[int(y):int(y + h), int(x):int(x + w)]

                    txt = tesseract.to_string(crop_img)

                    found = False
                    for i in range(8):
                        if TimePair.time_starts(
                        )[i] in txt and TimePair.time_ends()[i]:
                            time_cells[i] = (x, x + w)
                            found = True
                            break

                    if not found:
                        cells.append((x, x + w, " ".join(txt.split())))

                    # draw debug rect with number
                    if manager.debug_image:
                        box = cv.boxPoints(rect)
                        box = np.int0(box)
                        blue_color = (255, 0, 0)
                        center = (int(rect[0][0]), int(rect[0][1]))

                        cv.drawContours(img, [box], 0, blue_color, 2)
                        cv.putText(img, str(number),
                                   (center[0] - 100, center[1] - 40),
                                   cv.FONT_HERSHEY_SIMPLEX, 3, blue_color, 12)

                    number += 1
                    process = int(k / contours_number * 70)
                    manager.progress_value_list[process_id] = process
                    manager.progress_text_list[process_id] = "{} {}%".format(
                        file.baseName(), process)
            if manager.debug_image:
                cv.imwrite(file_path[0:-4] + "-debug.jpg", img)

            if manager.flags["stop"]:
                break

            schedule = Schedule()
            cells_number = len(cells)

            for k, cell in enumerate(cells):
                if manager.flags["stop"]:
                    break

                start_x, end_x, text = cell
                first_start_time, first_end_time = time_cells[0]

                if not abs(end_x - first_start_time) < abs(start_x -
                                                           first_start_time):
                    text = "\n".join(re.findall(r".*?\]", text))
                    while True:
                        try:
                            pairs = parse_pair(manager, text)
                            break
                        except InvalidDatePair as ex:
                            text = confuse_loop(
                                process_id, manager,
                                ConfuseSituationException(
                                    file.absoluteFilePath(),
                                    text,
                                    confuse=str(ex)))
                        except ConfuseSituationException as ex:
                            ex.filename = file.absoluteFilePath(
                            )[0:-4] + "-debug.jpg"
                            ex.cell = k
                            ex.context = text
                            if ex.maybe_answer == "":
                                ex.maybe_answer = text

                            text = confuse_loop(process_id, manager, ex)

                    if len(pairs) != 0:
                        diff_start = abs(start_x - first_start_time)
                        diff_end = abs(end_x - first_end_time)
                        start, end = 0, 0

                        for number, (start_time,
                                     end_time) in time_cells.items():
                            diff = abs(start_x - start_time)
                            if diff < diff_start:
                                diff_start = diff
                                start = number

                            diff = abs(end_x - end_time)
                            if diff < diff_end:
                                diff_end = diff
                                end = number

                        for pair in pairs:
                            pair["time"].set_time(
                                TimePair.time_starts()[start],
                                TimePair.time_ends()[end])
                            schedule.add_pair(pair)

                    process = int(70 + k / cells_number * 30)
                    manager.progress_value_list[process_id] = process
                    manager.progress_text_list[process_id] = "{} {}%".format(
                        file.baseName(), process)

            schedule.save(file.absoluteFilePath()[0:-4] + ".json")
            print(file.absoluteFilePath()[0:-4] + ".json")

            if manager.flags["stop"]:
                break

            if manager.weekly:
                export_weeks_to_pdf(
                    schedule, file.baseName(), True,
                    file.absoluteFilePath()[0:-4] + "-weekly.pdf",
                    manager.font_name, manager.font_path, manager.encoding,
                    manager.start, manager.end, manager.color_a,
                    manager.color_b)

            if manager.full:
                export_full_to_pdf(schedule, file.baseName(),
                                   file.absoluteFilePath()[0:-4] + "-full.pdf",
                                   manager.font_name, manager.font_path,
                                   manager.encoding)

        except Exception as ex:
            print("Exception, process:", process_id, "is:", ex)
            traceback.print_exc()

    manager.progress_value_list[process_id] = 100
    manager.progress_text_list[process_id] = "Work complete"