from timeit import default_timer as timer from PyQt5 import QtWidgets as Qtw from PyQt5.QtCore import pyqtSlot, Qt from PyQt5.QtGui import QPainter from PyQt5.QtPrintSupport import QPrinter, QPrintDialog from PyQt5.QtWidgets import QDialog, QMenu from model.distribution import Distribution from model.team import Team from utils.editable_title_widget import EditableTitle from utils.members_drag_drop_table import MembersDragDropTable from utils.print_widget import PrintWidget from windows import distribution_overview class DistributionOverview(Qtw.QWidget, distribution_overview.Ui_Form): def __init__(self, main_window, teams, group, parent=None): super(DistributionOverview, self).__init__(parent) self.setupUi(self) self.main_window = main_window self.group = group self.teamTables = [] for i, team_name in enumerate(teams): table = MembersDragDropTable(i, teams[team_name], team_name, self) table.model.sourceModel().droppedMemberFrom.connect(self.removeMember) table.deleteClicked.connect(self.removeTeam) # connecting the signal of the actual table, not the whole widget (I don't think it's worth it to wrap this) table.contextMenuRequested.connect(self.onContextMenuRequested) self.teamTables.append(table) self.gridTeams.addWidget(table, i // 2, i % 2) self.tableOthers = MembersDragDropTable( -1, self.getUnassigned(teams), self.tr("nezařazeni"), self ) self.tableOthers.model.sourceModel().droppedMemberFrom.connect(self.removeMember) self.tableOthers.contextMenuRequested.connect(self.onContextMenuRequested) self.gridTeams.addWidget(self.tableOthers, len(self.teamTables) // 2, len(self.teamTables) % 2) self.distribution_name = self.tr("Nepojmenované rozdělení") title = EditableTitle(self.distribution_name) self.layoutName.replaceWidget(self.titleWidget, title) self.titleWidget = title # signals self.btnAddTeam.clicked.connect(self.addTeam) self.btnSave.clicked.connect(self.save) self.btnPrint.clicked.connect(self.printDistribution) self.titleWidget.textConfirmed.connect(self.changeDistName) def getUnassigned(self, teams): """ :param teams: teams in distribution (dict) :return: list of unassigned members from group """ res = [] for member in self.group.members: for team in teams.values(): if member in team: break else: res.append(member) return res @pyqtSlot(str) def changeDistName(self, name): self.distribution_name = name @pyqtSlot() def addTeam(self): table_id = len(self.teamTables) table = MembersDragDropTable(table_id, [], "Tým " + str(table_id + 1), self) table.model.sourceModel().droppedMemberFrom.connect(self.removeMember) table.deleteClicked.connect(self.removeTeam) self.teamTables.append(table) self.gridTeams.replaceWidget(self.tableOthers, table) self.gridTeams.addWidget(self.tableOthers, len(self.teamTables) // 2, len(self.teamTables) % 2 ) @pyqtSlot(int, int) def removeMember(self, member_id, table_id): if table_id == -1: self.tableOthers.removeMember(member_id) else: self.teamTables[table_id].removeMember(member_id) @pyqtSlot(int) def removeTeam(self, table_id): if self.teamTables[table_id].isEmpty(): self.teamTables[table_id].hide() self.gridTeams.replaceWidget(self.teamTables[len(self.teamTables) - 1],self.tableOthers) for i in range(len(self.teamTables) - 1, table_id, -1): self.gridTeams.replaceWidget(self.teamTables[i-1], self.teamTables[i]) self.teamTables[i].id_ -= 1 self.teamTables.pop(table_id) else: msg = Qt.QMessageBox(self) msg.setIcon(Qt.QMessageBox.Critical) msg.setWindowTitle("Chyba") msg.setText("Nelze smazat neprázdný tým!") msg.setStandardButtons(Qt.QMessageBox.Ok) msg.exec_() @pyqtSlot() def save(self): teams = [] for table in self.teamTables: team = Team(table.id_, table.name, table.getAllData()) teams.append(team) distribution = Distribution(self.distribution_name, teams, self.group.id_) start = timer() distribution.saveToDb() print('total time:', timer() - start) self.main_window.reset() @pyqtSlot() def printDistribution(self): printer = QPrinter(QPrinter.HighResolution) dialog = QPrintDialog() if dialog.exec_() != QDialog.Accepted: return painter = QPainter() widget = PrintWidget(self.distribution_name, self.teamTables) widget_height = widget.sizeHint().height() widget_width = widget.width() painter.begin(printer) x_scale = printer.pageRect().width() / widget_width y_scale = printer.pageRect().height() / widget_height scale = min([x_scale, y_scale]) painter.translate(printer.paperRect().x() + printer.pageRect().width() / 2, printer.paperRect().y() + printer.pageRect().height() / 2) painter.scale(scale, scale) painter.translate(-widget_width / 2, -widget_height / 2) widget.render(painter) painter.end() def onContextMenuRequested(self, member, from_table_id, point): """ construct and display context menu allowing to move members from a team to different one :param member: :param from_table_id: :param point: """ menu = QMenu(self.sender()) submenu = menu.addMenu(self.tr("Přesunout do týmu:")) for table in self.teamTables: if table.id_ != from_table_id: submenu.addAction(table.name, lambda i=table.id_: self.moveMember(member, from_table_id, i)) if from_table_id != -1: menu.addSeparator() menu.addAction(self.tr("Vyřadit z rozdělení"), lambda: self.moveMember(member, from_table_id, -1)) menu.exec_(point) def moveMember(self, member, from_table_id, to_table_id): self.removeMember(member.id_, from_table_id) if to_table_id == -1: self.tableOthers.insertMember(member) else: self.teamTables[to_table_id].insertMember(member)