From 71a144dacc5dd9a7386b601551f12fd127be60b1 Mon Sep 17 00:00:00 2001 From: Kukuksumusu <stercjak@fit.cvut.cz> Date: Fri, 7 Apr 2017 17:39:23 +0200 Subject: [PATCH] "distribution setup is now working as intended (with all functionality)" - me now --- .../controllers/distribution_setup.py | 71 +++++++++++++------ .../controllers/group_edit_controller.py | 4 +- .../controllers/groups_overview_controller.py | 2 + .../controllers/requirement_dialog.py | 69 ++++++++++++++---- Implementace/model/group.py | 6 +- Implementace/model/requirements.py | 9 +-- .../qtmodels/requirements_table_model.py | 31 +++++--- Implementace/utils/requirements_table.py | 30 +++++++- Implementace/utils/table.py | 12 +--- Implementace/windows/qt/qt.pro.user | 2 +- Implementace/windows/qt/table.ui | 6 -- Implementace/windows/table.py | 4 +- 12 files changed, 176 insertions(+), 70 deletions(-) diff --git a/Implementace/controllers/distribution_setup.py b/Implementace/controllers/distribution_setup.py index d09a7a0..10ed143 100644 --- a/Implementace/controllers/distribution_setup.py +++ b/Implementace/controllers/distribution_setup.py @@ -1,7 +1,10 @@ from math import ceil from PyQt5 import QtWidgets as Qt from PyQt5.QtCore import pyqtSlot -from controllers.requirement_dialog import RequirementDialog +from PyQt5.QtWidgets import QDialog + +from controllers.requirement_dialog import NewRequirementDialog, RequirementEditDialog +from model.requirements import Requirement from utils.groups_table import GroupsTable from utils.requirements_table import RequirementsTable from windows import distributionsetup @@ -17,39 +20,67 @@ class DistributionSetup(Qt.QWidget, distributionsetup.Ui_Form): """ super(DistributionSetup, self).__init__(parent) self.setupUi(self) - self.tableRequirements = RequirementsTable() + self.tableRequirements = RequirementsTable(2, ["edit", "-"]) self.placeTable.insertWidget(1, self.tableRequirements) + self.tableRequirements.btnClicked.connect(self.onTableRequirementsBtnClicked) self.group = group # set up header self.lblGroupName.setText(self.group.name) - self.lblMemberCount.setText('(' + str(self.group.getMemberCount()) + ' ÄŤlenĹŻ)') + self.lblMemberCount.setText('(' + str(self.group.member_count) + ' ÄŤlenĹŻ)') - #set up spinners + # set up spinners self.spinTeamCount.setMinimum(1) - self.spinTeamCount.setMaximum(self.group.getMemberCount()) - self.spinTeamCount.setFocus() - self.spinTeamCount.selectAll() - self.spinTeamCount.valueChanged.connect(self.teamCountSet) + self.spinTeamCount.setMaximum(self.group.member_count) + self.spinMinTeamSize.setMinimum(0) + self.spinMinTeamSize.setMaximum(self.group.member_count) + self.spinMaxTeamSize.setMinimum(1) + self.spinMaxTeamSize.setMaximum(self.group.member_count) + self.spinMaxTeamSize.setValue(self.group.member_count) - self.spinMinTeamSize.valueChanged.connect(self.minSizeSet) + # set up checkboxes + self.cbIgnoreTeamCount.stateChanged.connect(self.spinTeamCount.setDisabled) + self.cbIgnoreMinSize.stateChanged.connect(self.spinMinTeamSize.setDisabled) + self.cbIgnoreMaxSize.stateChanged.connect(self.spinMaxTeamSize.setDisabled) self.btnAddRequirement.clicked.connect(self.showRequirementDialog) + self.btnDistribute.clicked.connect(self.distribute) @pyqtSlot() - def teamCountSet(self): - self.spinMinTeamSize.setMaximum(self.group.getMemberCount() // self.spinTeamCount.value()) - - @pyqtSlot() - def minSizeSet(self): - self.spinMaxTeamSize.setMinimum(ceil(self.group.getMemberCount() / self.spinTeamCount.value())) - self.spinMaxTeamSize.setMaximum(self.group.getMemberCount()) + def showRequirementDialog(self): + dialog = NewRequirementDialog(self.group, self.tableRequirements.model.sourceModel().requirements, parent=self) + dialog.exec_() + if dialog.result() == dialog.Accepted: + if dialog.requirement is not None: + self.tableRequirements.insertRequirement(dialog.requirement) + @pyqtSlot(Requirement, int) + def onTableRequirementsBtnClicked(self, requirement, btn_nr): + if btn_nr == 0: + # it's btn "edit" + self.editRequirement(requirement) + elif btn_nr == 1: + # it's btn "delete" + self.deleteRequirement(requirement) - @pyqtSlot() - def showRequirementDialog(self): - dialog = RequirementDialog(self.group, parent=self) + def editRequirement(self, requirement): + self.tableRequirements.model.sourceModel().removeRequirement(requirement) + dialog = RequirementEditDialog(self.group, requirement) dialog.exec_() if dialog.result() == dialog.Accepted: - requirement = dialog.getRequirement() + if dialog.requirement is not None: + self.tableRequirements.insertRequirement(dialog.requirement) + else: self.tableRequirements.insertRequirement(requirement) + + def deleteRequirement(self, requirement): + msg = Qt.QMessageBox(self) + msg.setIcon(Qt.QMessageBox.Question) + msg.setWindowTitle("Odebrat omezenĂ?") + msg.setText("Chcete odebrat toto omezenĂ?") + msg.setStandardButtons(Qt.QMessageBox.Ok | Qt.QMessageBox.Cancel) + if msg.exec() == Qt.QMessageBox.Ok: + self.tableRequirements.model.sourceModel().removeRequirement(requirement) + + def distribute(self): + ... diff --git a/Implementace/controllers/group_edit_controller.py b/Implementace/controllers/group_edit_controller.py index 5f56969..d91a423 100644 --- a/Implementace/controllers/group_edit_controller.py +++ b/Implementace/controllers/group_edit_controller.py @@ -100,7 +100,7 @@ class GroupEdit(Qt.QWidget, groupedit.Ui_Form): msg.setIcon(Qt.QMessageBox.Question) msg.setWindowTitle("Opravdu?") msg.setText("Opravdu chcete smazat skupinu " + self.group.name + "?") - msg.setStandardButtons(Qt.QMessageBox.Ok|Qt.QMessageBox.Cancel) + msg.setStandardButtons(Qt.QMessageBox.Ok | Qt.QMessageBox.Cancel) if msg.exec() == Qt.QMessageBox.Ok: self.group.delete() self.main_window.dataChanged() @@ -125,7 +125,7 @@ class GroupEdit(Qt.QWidget, groupedit.Ui_Form): """ Updates member count label """ - self.lblMemberCount.setText(str(self.group.getMemberCount())) + self.lblMemberCount.setText(str(self.group.member_count)) @pyqtSlot() def distribute(self): diff --git a/Implementace/controllers/groups_overview_controller.py b/Implementace/controllers/groups_overview_controller.py index 3e5cf3c..15eafb6 100644 --- a/Implementace/controllers/groups_overview_controller.py +++ b/Implementace/controllers/groups_overview_controller.py @@ -32,6 +32,8 @@ class GroupsOverview(QWidget, groupsoverview.Ui_Form): self.layoutTables.addWidget(self.members_table) self.members_table.btnClicked.connect(self.editMember) + self.members_table.table.setAcceptDrops(True) + # reload data, because some other controller changed them def reloadData(self): self.groups_table.changeData(Global.db.getGroups()) diff --git a/Implementace/controllers/requirement_dialog.py b/Implementace/controllers/requirement_dialog.py index 4186a9b..5ef0f22 100644 --- a/Implementace/controllers/requirement_dialog.py +++ b/Implementace/controllers/requirement_dialog.py @@ -1,38 +1,83 @@ from PyQt5 import Qt from PyQt5.QtCore import pyqtSlot, Qt -from PyQt5.QtWidgets import QDialog, QAbstractItemView +from PyQt5.QtWidgets import QDialog, QAbstractItemView, QLabel from model.requirements import RequirementDifferentTeam, RequirementSameTeam from utils.members_table import MembersTable from windows import requirement_dialog -class RequirementDialog(QDialog, requirement_dialog.Ui_Dialog): - def __init__(self, group, requirement=None, parent=None): - super(RequirementDialog, self).__init__(parent) +class NewRequirementDialog(QDialog, requirement_dialog.Ui_Dialog): + def __init__(self, group, all_requirements, parent=None): + super(NewRequirementDialog, self).__init__(parent) self.setupUi(self) self.group = group + self.requirements = all_requirements + self.tableMembers = MembersTable(data=self.group.members, parent=self) self.placeTable.insertWidget(0, self.tableMembers) - self.tableMembers.setSelectionMode(QAbstractItemView.MultiSelection) + self.tableMembers.table.setSelectionMode(QAbstractItemView.MultiSelection) # set up comboWho - for member in sorted(self.group.members, key=lambda member: member.surname, reverse=True): - self.comboWho.insertItem(0, member.surname + " " + member.name, member) + for member in sorted(self.group.members, key=lambda member: member.surname): + if len([req for req in all_requirements if req.person == member]) < 2: + self.comboWho.addItem(member.surname + " " + member.name, member) self.comboWho.setCurrentIndex(0) self.comboWho.currentIndexChanged.connect(self.onComboWhoCurrentChanged) self.onComboWhoCurrentChanged() # to set initial filter - self.comboType.setItemData(0, RequirementDifferentTeam, Qt.UserRole) - self.comboType.setItemData(1, RequirementSameTeam, Qt.UserRole) - @pyqtSlot() def onComboWhoCurrentChanged(self): - self.tableMembers.clearSelection() + self.tableMembers.table.clearSelection() self.tableMembers.model.resetHiddenRows() self.tableMembers.model.hideRowByData(self.comboWho.currentData(Qt.UserRole)) + self.comboType.clear() + + # find what requirement with this person exists (to disable adding the same type) + cur_req = next((requirement for requirement in self.requirements + if requirement.person == self.comboWho.currentData(Qt.UserRole)), None) + if not isinstance(cur_req, RequirementSameTeam): + self.comboType.addItem("musĂ", RequirementSameTeam) + if not isinstance(cur_req, RequirementDifferentTeam): + self.comboType.addItem("nesmĂ", RequirementDifferentTeam) - def getRequirement(self): + @property + def requirement(self): target_members = self.tableMembers.getSelectedItems() + if len(target_members) == 0: + return None who = self.comboWho.currentData(Qt.UserRole) return self.comboType.currentData(Qt.UserRole)(who, target_members) + + +class RequirementEditDialog(QDialog, requirement_dialog.Ui_Dialog): + def __init__(self, group, requirement, parent=None): + super(RequirementEditDialog, self).__init__(parent) + self.setupUi(self) + self.group = group + self._requirement = requirement + self.comboWho.hide() + self.comboType.hide() + + # set up labels + self.horizontalLayout.replaceWidget(self.comboWho, + QLabel(requirement.person.surname + " " + requirement.person.name)) + self.horizontalLayout.replaceWidget(self.comboType, QLabel("<b>" + requirement.keyword + "</b>")) + # set up table + self.tableMembers = MembersTable(data=self.group.members, parent=self) + self.placeTable.insertWidget(0, self.tableMembers) + self.tableMembers.table.setSelectionMode(QAbstractItemView.MultiSelection) + self.tableMembers.model.hideRowByData(self.comboWho.currentData(Qt.UserRole)) + model = self.tableMembers.model + for i in range(model.rowCount()): + if model.data(model.index(i, 0), Qt.UserRole) in requirement.target_members: + self.tableMembers.table.selectRow(i) + self.tableMembers.table.setFocus() + + @property + def requirement(self): + target_people = self.tableMembers.getSelectedItems() + if len(target_people) == 0: + return None + self._requirement.target_members = target_people + return self._requirement diff --git a/Implementace/model/group.py b/Implementace/model/group.py index e6ad428..f85de3b 100644 --- a/Implementace/model/group.py +++ b/Implementace/model/group.py @@ -25,11 +25,13 @@ class Group: self._members = Global.db.getGroupMembers(self.id) return self._members - def getMemberCount(self): + @property + def member_count(self): """ :return: count of members """ - self.members + if self._members is None: + self.members # to force initialization return len(self._members) def delete(self): diff --git a/Implementace/model/requirements.py b/Implementace/model/requirements.py index 6f2d827..df03a68 100644 --- a/Implementace/model/requirements.py +++ b/Implementace/model/requirements.py @@ -1,20 +1,21 @@ class Requirement: - def __init__(self, person, target_members): + def __init__(self, person, target_members, keyword): """ :param person: the one person that's in some "relationship" with each of the target_members :param target_members: see person + :param keyword: the word that represents this requirement ("person -keyword- in the same team as...") """ self.person = person self.target_members = target_members - + self.keyword = keyword class RequirementSameTeam(Requirement): def __init__(self, person, target_members): - super(RequirementSameTeam, self).__init__(person, target_members) + super(RequirementSameTeam, self).__init__(person, target_members, "musĂ") class RequirementDifferentTeam(Requirement): def __init__(self, person, target_members): - super(RequirementDifferentTeam, self).__init__(person, target_members) + super(RequirementDifferentTeam, self).__init__(person, target_members, "nesmĂ") diff --git a/Implementace/utils/qtmodels/requirements_table_model.py b/Implementace/utils/qtmodels/requirements_table_model.py index 99f06a6..732b2e2 100644 --- a/Implementace/utils/qtmodels/requirements_table_model.py +++ b/Implementace/utils/qtmodels/requirements_table_model.py @@ -5,13 +5,13 @@ from model.requirements import RequirementSameTeam, RequirementDifferentTeam class RequirementsTableModel(QtCore.QAbstractTableModel): - def __init__(self, requirements=[], num_columns=3, parent=None): + def __init__(self, requirements=(), num_columns=3, parent=None): super(RequirementsTableModel, self).__init__(parent) - self._requirements = requirements + self.requirements = list(requirements) self._columns = num_columns def rowCount(self, parent=None, *args, **kwargs): - return len(self._requirements) + return len(self.requirements) def columnCount(self, parent=None, *args, **kwargs): return self._columns @@ -27,15 +27,12 @@ class RequirementsTableModel(QtCore.QAbstractTableModel): return 'S kĂ˝m' def data(self, index, role=None): - requirement = self._requirements[index.row()] + requirement = self.requirements[index.row()] if role == QtCore.Qt.DisplayRole: if index.column() == 0: return requirement.person.surname + " " + requirement.person.name if index.column() == 1: - if type(requirement) is RequirementSameTeam: - return 'MusĂ bĂ˝t v tĂ˝mu s' - if type(requirement) is RequirementDifferentTeam: - return 'NesmĂ bĂ˝t v tĂ˝mu s' + return requirement.keyword + ' bĂ˝t v tĂ˝mu s' if index.column() == 2: member = requirement.target_members[0].surname + " " + requirement.target_members[0].name if len(requirement.target_members) > 1: @@ -48,8 +45,20 @@ class RequirementsTableModel(QtCore.QAbstractTableModel): def insertRequirement(self, position, requirement): self.beginInsertRows(QModelIndex(), position, position) - self._requirements.insert(position, requirement) + self.requirements.insert(position, requirement) self.endInsertRows() - def getElementById(self, person_id): - return None + def getRequirement(self, target_person, is_same_team): + if is_same_team: + correct_type = RequirementSameTeam + else: + correct_type = RequirementDifferentTeam + return next((requirement for requirement in self.requirements + if str(requirement.person) == target_person and isinstance(requirement, correct_type)), None) + + def removeRequirement(self, requirement): + position = self.requirements.index(requirement) + self.beginRemoveRows(QModelIndex(), position, position) + self.requirements.remove(requirement) + self.endRemoveRows() + diff --git a/Implementace/utils/requirements_table.py b/Implementace/utils/requirements_table.py index 07bdcec..2e297ad 100644 --- a/Implementace/utils/requirements_table.py +++ b/Implementace/utils/requirements_table.py @@ -1,3 +1,7 @@ +from PyQt5.QtCore import Qt +from PyQt5.QtWidgets import QPushButton + +from model.requirements import RequirementSameTeam from utils.qtmodels.groups_table_model import GroupsTableModel from utils.qtmodels.requirements_table_model import RequirementsTableModel from utils.table import ElemTable @@ -11,4 +15,28 @@ class RequirementsTable(ElemTable): self.setModel(GroupsTableModel(data, self._btn_amount + 3)) def insertRequirement(self, requirement): - self.model.sourceModel().insertRequirement(0, requirement) \ No newline at end of file + self.model.setDynamicSortFilter(False) + self.model.sourceModel().insertRequirement(0, requirement) + + # add buttons to new row + for btn_nr in range(self._btn_amount): + button = QPushButton(self._btn_titles[btn_nr]) + button.clicked.connect(self.onBtnClicked) + requirement = self.model.data(self.model.index(0, 0), Qt.UserRole) + if isinstance(requirement, RequirementSameTeam): + req_type = "same" + else: + req_type = "diff" + button.setObjectName(str(requirement.person) + "_" + req_type + "_" + str(btn_nr)) + self.table.setIndexWidget(self.model.index(0, btn_nr+self._data_columns), button) + + self.model.setDynamicSortFilter(True) + + def onBtnClicked(self): + req_person, req_type, btn_id = str.split(self.sender().objectName(), '_') + if req_type == "same": + is_same_team = True + elif req_type == "diff": + is_same_team = False + requirement = self.model.sourceModel().getRequirement(req_person, is_same_team) + self.btnClicked.emit(requirement, int(btn_id)) diff --git a/Implementace/utils/table.py b/Implementace/utils/table.py index fcf00c8..c56ecc1 100644 --- a/Implementace/utils/table.py +++ b/Implementace/utils/table.py @@ -1,5 +1,3 @@ -from PyQt5.QtCore import QModelIndex - from utils.qtmodels.custom_filter_model import CustomFilterModel from windows import table from PyQt5.QtCore import * @@ -42,8 +40,8 @@ class ElemTable(QWidget, table.Ui_Form): for i in range(self.model.rowCount()): button = QPushButton(self._btn_titles[btn_nr]) button.clicked.connect(self.onBtnClicked) - group = self.model.data(self.model.index(i, 0), Qt.UserRole) - button.setObjectName(str(group.id) + "_" + str(btn_nr)) + item = self.model.data(self.model.index(i, 0), Qt.UserRole) + button.setObjectName(str(item.id) + "_" + str(btn_nr)) self.table.setIndexWidget(self.model.index(i, btn_nr+self._data_columns), button) def onBtnClicked(self): @@ -62,12 +60,6 @@ class ElemTable(QWidget, table.Ui_Form): self.insertButtons() self.table.sortByColumn(0, Qt.AscendingOrder) - def setSelectionMode(self, selection_mode): - self.table.setSelectionMode(selection_mode) - - def clearSelection(self): - self.table.clearSelection() - def getSelectedItems(self): indexes = self.table.selectionModel().selectedRows() res = [] diff --git a/Implementace/windows/qt/qt.pro.user b/Implementace/windows/qt/qt.pro.user index f9adc8d..0304a8a 100644 --- a/Implementace/windows/qt/qt.pro.user +++ b/Implementace/windows/qt/qt.pro.user @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE QtCreatorProject> -<!-- Written by QtCreator 4.2.1, 2017-04-04T17:53:10. --> +<!-- Written by QtCreator 4.2.1, 2017-04-07T01:04:42. --> <qtcreator> <data> <variable>EnvironmentId</variable> diff --git a/Implementace/windows/qt/table.ui b/Implementace/windows/qt/table.ui index 8ef6fe0..434e2e6 100644 --- a/Implementace/windows/qt/table.ui +++ b/Implementace/windows/qt/table.ui @@ -43,12 +43,6 @@ <verstretch>0</verstretch> </sizepolicy> </property> - <property name="dragDropMode"> - <enum>QAbstractItemView::DragDrop</enum> - </property> - <property name="defaultDropAction"> - <enum>Qt::CopyAction</enum> - </property> <property name="selectionMode"> <enum>QAbstractItemView::SingleSelection</enum> </property> diff --git a/Implementace/windows/table.py b/Implementace/windows/table.py index ec8b610..065bdb9 100644 --- a/Implementace/windows/table.py +++ b/Implementace/windows/table.py @@ -27,8 +27,10 @@ class Ui_Form(object): sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.table.sizePolicy().hasHeightForWidth()) self.table.setSizePolicy(sizePolicy) + self.table.setDragEnabled(True) self.table.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop) - self.table.setDefaultDropAction(QtCore.Qt.CopyAction) + self.table.setDefaultDropAction(QtCore.Qt.MoveAction) + self.table.setAlternatingRowColors(False) self.table.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) self.table.setShowGrid(False) -- GitLab