def __init__(self, task_data): QMainWindow.__init__(self, None, Qt.WindowTitleHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint) self._task_data = task_data self.setWindowTitle("SimpleTaskManager 1.0.0-SNAPSHOT") self._table_dictionary = {} self._current_task = None self._current_row = None self.category_group = CategoryGroup(self._task_data) self.status_group = FilterGroup(self._task_data, self._task_data.STATUSES, "Status") self.priority_group = FilterGroup(self._task_data, self._task_data.PRIORITIES, "Priority") layout = QGridLayout() add_task = QPushButton("Add Task") self.task_table = QTableWidget() self.task_table.setToolTip("Double-click a row to edit the task.") self.task_table.setColumnCount(8) self.task_table.setHorizontalHeaderLabels(["Category", "Priority", "Task", "Status", "Entry Date", "Due Date", "Check List", "Exp. Effort"]) self.task_table.setMinimumWidth(800) self.refresh_table(self._task_data) layout.addWidget(add_task, 0, 4) layout.addWidget(self.task_table, 1, 0, 1, 5) self.task_table.setContextMenuPolicy(Qt.CustomContextMenu) self.task_table.customContextMenuRequested.connect(self.show_context_menu) add_task.clicked.connect(self.display_new_task_dialog) self.task_table.cellDoubleClicked.connect(self.display_edit_task_dialog) self.task_table.cellClicked.connect(self.display_checklist) section_layout = QHBoxLayout() section_layout.addLayout(self._build_leftside_layout()) section_layout.addLayout(layout) self.filter_tasks() self.setMinimumWidth(800) self.setMinimumHeight(600) frame = QFrame() frame.setLayout(section_layout) self.setCentralWidget(frame) self.setFocus()
class TaskWindow(QMainWindow): def __init__(self, task_data): QMainWindow.__init__(self, None, Qt.WindowTitleHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint) self._task_data = task_data self.setWindowTitle("SimpleTaskManager 1.0.0-SNAPSHOT") self._table_dictionary = {} self._current_task = None self._current_row = None self.category_group = CategoryGroup(self._task_data) self.status_group = FilterGroup(self._task_data, self._task_data.STATUSES, "Status") self.priority_group = FilterGroup(self._task_data, self._task_data.PRIORITIES, "Priority") layout = QGridLayout() add_task = QPushButton("Add Task") self.task_table = QTableWidget() self.task_table.setToolTip("Double-click a row to edit the task.") self.task_table.setColumnCount(8) self.task_table.setHorizontalHeaderLabels(["Category", "Priority", "Task", "Status", "Entry Date", "Due Date", "Check List", "Exp. Effort"]) self.task_table.setMinimumWidth(800) self.refresh_table(self._task_data) layout.addWidget(add_task, 0, 4) layout.addWidget(self.task_table, 1, 0, 1, 5) self.task_table.setContextMenuPolicy(Qt.CustomContextMenu) self.task_table.customContextMenuRequested.connect(self.show_context_menu) add_task.clicked.connect(self.display_new_task_dialog) self.task_table.cellDoubleClicked.connect(self.display_edit_task_dialog) self.task_table.cellClicked.connect(self.display_checklist) section_layout = QHBoxLayout() section_layout.addLayout(self._build_leftside_layout()) section_layout.addLayout(layout) self.filter_tasks() self.setMinimumWidth(800) self.setMinimumHeight(600) frame = QFrame() frame.setLayout(section_layout) self.setCentralWidget(frame) self.setFocus() def show_context_menu(self, position): self._current_row = self.task_table.rowAt(position.y()) self._current_task = self._table_dictionary[self._current_row] status = self._current_task.get_status().get_description() menu = QMenu(self) if status == "New": in_progress = QAction("Getting started", self) menu.addAction(in_progress) in_progress.triggered.connect(self.start_task) if status == "In Progress": complete = QAction("Finished !!!", self) menu.addAction(complete) complete.triggered.connect(self.finish_task) menu.addSeparator() cancelled = QAction("Not going to do it.", self) menu.addAction(cancelled) cancelled.triggered.connect(self.cancel_task) menu.popup(self.task_table.mapToGlobal(position)) def start_task(self): status_by_name = self._task_data.get_status_by_name() in_progress = status_by_name["In Progress"] self._current_task.set_status(in_progress) self._task_data.save_task(self._current_task) self._update_row(self._current_task, self._current_row) self.filter_tasks() def finish_task(self): status_by_name = self._task_data.get_status_by_name() complete = status_by_name["Complete"] self._current_task.set_status(complete) self._task_data.save_task(self._current_task) self._update_row(self._current_task, self._current_row) self.filter_tasks() def cancel_task(self): status_by_name = self._task_data.get_status_by_name() cancelled = status_by_name["Cancelled"] self._current_task.set_status(cancelled) self._task_data.save_task(self._current_task) self._update_row(self._current_task, self._current_row) self.filter_tasks() def display_new_task_dialog(self): dialog = TaskEntryDialog(self._task_data, parent=self) if dialog.exec_(): task = dialog.get_task() self._task_data.save_task(task) self.refresh_table(self._task_data) self.filter_tasks() def display_edit_task_dialog(self, row, column): task = self._table_dictionary[row] dialog = TaskEntryDialog(self._task_data, task, parent=self) if dialog.exec_(): updated_task = dialog.get_task() #self._update_row(updated_task, row) self._task_data.save_task(task) self.refresh_table(self._task_data) self.filter_tasks() def _add_new_task(self, task): rows = self.task_table.rowCount() self.task_table.setRowCount(rows + 1) self._update_row(task, rows) def _create_table_item(self, text): item = QTableWidgetItem(text) item.setFlags(Qt.ItemIsEditable) item.setFlags(Qt.ItemIsEnabled) return item def _expected_effort_display(self, hours, minutes): return str(hours) + "h " + str(minutes) + "m"; def _update_row(self, task, row): category_text = "" if task.get_category() is None else task.get_category().get_description() category = self._create_table_item(category_text) priority = self._create_table_item(task.get_priority().get_description()) description = self._create_table_item(task.get_description()) status = self._create_table_item(task.get_status().get_description()) entrydate = self._create_table_item(task.get_entry_date().strftime("%Y-%m-%d")) duedate_text = "" if task.get_due_date() is None else task.get_due_date().strftime("%Y-%m-%d") duedate = self._create_table_item(duedate_text) item_text = " item" if task.get_checklist_count() == 1 else " items" checklist = self._create_table_item(str(task.get_checklist_count()) + item_text) expected_effort = self._create_table_item(self._expected_effort_display( task.get_expected_hours(), task.get_expected_minutes())) font = QFont(checklist.font()) font.setUnderline(True) checklist.setFont(font) color = QColor(0,0,255) checklist.setTextColor(color) self.task_table.setItem(row, 0, category) self.task_table.setItem(row, 1, priority) self.task_table.setItem(row, 2, description) self.task_table.setItem(row, 3, status) self.task_table.setItem(row, 4, entrydate) self.task_table.setItem(row, 5, duedate) self.task_table.setItem(row, 6, checklist) self.task_table.setItem(row, 7, expected_effort) self.task_table.resizeColumnsToContents() if task.get_due_date() is not None: warning_color = self._assign_color(task) #TODO: Need to create a new category for this if task.get_status().get_selected_by_default(): category.setBackgroundColor(warning_color) priority.setBackgroundColor(warning_color) description.setBackgroundColor(warning_color) status.setBackgroundColor(warning_color) entrydate.setBackgroundColor(warning_color) duedate.setBackgroundColor(warning_color) checklist.setBackgroundColor(warning_color) expected_effort.setBackgroundColor(warning_color) self._table_dictionary[row] = task def _assign_color(self, task): day_difference = (task.get_due_date() - datetime.datetime.now().date()).days * 36 alpha = 255 - day_difference if alpha < 0: alpha = 0 if alpha > 255: alpha = 255 yellow = 255 - alpha if task.get_due_date() < datetime.datetime.now().date(): return QColor(255, 0, 0, 100) else: return QColor(75, 255, yellow, alpha) def _build_leftside_layout(self): top_align_layout = QVBoxLayout() control_layout = QGridLayout() self.category_group.filtered.connect(self.filter_tasks) control_layout.addWidget(self.category_group, 0, 0) self.status_group.filtered.connect(self.filter_tasks) control_layout.addWidget(self.status_group, 1, 0) self.priority_group.filtered.connect(self.filter_tasks) control_layout.addWidget(self.priority_group,2, 0) top_align_layout.addLayout(control_layout) top_align_layout.addStretch(1) return top_align_layout def filter_tasks(self): for i in range(self.task_table.rowCount()): task = self._table_dictionary[i] category_dictionary = self.category_group.get_control_dictionary() status_dictionary = self.status_group.get_control_dictionary() priority_dictionary = self.priority_group.get_control_dictionary() if task.get_status().get_id() in status_dictionary: status_display = status_dictionary[task.get_status().get_id()].isChecked() else: status_display = True priority_display = priority_dictionary[task.get_priority().get_id()].isChecked() if task.get_category().get_id() in category_dictionary: category_check = category_dictionary[task.get_category().get_id()] if category_check.isHidden() or not category_check.isChecked() or not status_display or not priority_display: self.task_table.setRowHidden(i, True) else: self.task_table.setRowHidden(i, False) def refresh_table(self, task_data): task_list = self._task_data.get_task_list() self._clear_table() for task in task_list: self._add_new_task(task) def _clear_table(self): while self.task_table.rowCount() > 0: self.task_table.removeRow(0) self._table_dictionary = {} def display_checklist(self, row, column): if column == 6: task = self._table_dictionary[row] checklist = CheckListDialog(self._task_data, task, row, parent=self) checklist.updated.connect(self.update_checklist_count) checklist.show() def update_checklist_count(self, row_id, count): table_item = self.task_table.item(row_id, 6) item_text = " item" if count == 1 else " items" table_item.setText(str(count) + " " + item_text)