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