From 65a11ff8d6651668c045565a9a76936d032f1276 Mon Sep 17 00:00:00 2001
From: Kukuksumusu <stercjak@fit.cvut.cz>
Date: Mon, 20 Mar 2017 11:07:52 +0100
Subject: [PATCH] tables separated to classes just handling them

---
 .../controllers/group_edit_controller.py      | 15 ++-
 .../controllers/groups_overview_controller.py | 97 ++++++-------------
 .../controllers/mainwindow_controller.py      | 40 ++++----
 Implementace/database.py                      |  1 +
 Implementace/model/group.py                   |  7 +-
 .../model/qtmodels/person_table_model.py      |  7 +-
 Implementace/utils/group_table.py             | 63 ++++++++++++
 Implementace/utils/person_table.py            | 57 +++++++++++
 Implementace/windows/groupedit.py             | 26 ++---
 Implementace/windows/groupsoverview.py        | 28 +-----
 Implementace/windows/grouptable.py            | 37 +++++++
 Implementace/windows/qt/groupoverview.ui      | 59 +----------
 Implementace/windows/qt/qt.pro                |  4 +-
 Implementace/windows/qt/qt.pro.user           |  2 +-
 14 files changed, 247 insertions(+), 196 deletions(-)
 create mode 100644 Implementace/utils/group_table.py
 create mode 100644 Implementace/utils/person_table.py
 create mode 100644 Implementace/windows/grouptable.py

diff --git a/Implementace/controllers/group_edit_controller.py b/Implementace/controllers/group_edit_controller.py
index 46e0dfd..323d1cb 100644
--- a/Implementace/controllers/group_edit_controller.py
+++ b/Implementace/controllers/group_edit_controller.py
@@ -1,26 +1,34 @@
 from PyQt5.QtWidgets import QLineEdit
 from model.qtmodels.person_table_model import PersonTableModel
+from utils.person_table import PersonTable
 from windows import groupedit
 from PyQt5 import QtWidgets as Qt
 from model.group import Group
 
+
 class GroupEdit(Qt.QWidget, groupedit.Ui_Form):
     NEW_GROUP = 0
     def __init__(self, main_window, group, parent=None):
         super(GroupEdit, self).__init__(parent)
         self.setupUi(self)
+        self.main_window = main_window
         if group == self.NEW_GROUP:
             self.setGroup(Group(Group.NEW_GROUP))
         else:
             self.setGroup(group)
         self._editName = QLineEdit()
 
+        # insert others table
+        self.othersTable = PersonTable()
+        self.layoutOthers.insertWidget(1, self.othersTable)
+
         self.btnDelete.clicked.connect(self.deleteGroup)
         self.btnChangeName.clicked.connect(self.editName)
 
     def setGroup(self, group):
         self.group = group
-        self.tableMembers.setModel(PersonTableModel(group.getMembers(), 2))
+        self.personTable = PersonTable(group.getMembers())
+        self.layoutMembers.insertWidget(1, self.personTable)
         self.lblName.setText(group.name)
 
     def editName(self):
@@ -41,6 +49,7 @@ class GroupEdit(Qt.QWidget, groupedit.Ui_Form):
         self.btnChangeName.clicked.disconnect(self.editName)
         self.btnChangeName.clicked.connect(self.changeName)
 
+    #TODO database
     def changeName(self):
         self._checkName()
         self.btnChangeName.setText("Edit")
@@ -55,8 +64,12 @@ class GroupEdit(Qt.QWidget, groupedit.Ui_Form):
         self.btnChangeName.clicked.disconnect(self.changeName)
         self.btnChangeName.clicked.connect(self.editName)
 
+    # TODO check name (long enough (but not too much :)), unique ...
     def _checkName(self):
         ...
 
+    # TODO confirmation (QMessage)
     def deleteGroup(self):
         self.group.delete()
+        self.main_window.dataChanged()
+        self.main_window.goBack()
diff --git a/Implementace/controllers/groups_overview_controller.py b/Implementace/controllers/groups_overview_controller.py
index 854095f..a7abe8b 100644
--- a/Implementace/controllers/groups_overview_controller.py
+++ b/Implementace/controllers/groups_overview_controller.py
@@ -1,9 +1,12 @@
 from PyQt5.QtCore import *
 from PyQt5.QtWidgets import *
-from globals import Global
-from model.qtmodels.group_table_model import GroupTableModel
-from model.qtmodels.person_table_model import PersonTableModel
+
+from model.person import Person
+from utils.person_table import PersonTable
 from windows import groupsoverview
+from globals import Global
+from utils.group_table import GroupTable
+from model.group import Group
 
 
 class GroupsOverview(QWidget, groupsoverview.Ui_Form):
@@ -17,78 +20,32 @@ class GroupsOverview(QWidget, groupsoverview.Ui_Form):
         self.main_window = main_window
         self.setupUi(self)
         self.btnCreateGroup.clicked.connect(main_window.goToGroupEdit)
-        self._initializeGroupsTable()
-        self._initializeMembersTable()
-
-    # initializes groups table (sets column widths, signals, etc.)
-    def _initializeGroupsTable(self):
-
-        # initialize content
-        self._model_groups = GroupTableModel(Global.db.getGroups(), 2)
-        self.tableGroups.setModel(self._model_groups)
-        for i in range(self._model_groups.rowCount()):
-            edit_button = QPushButton("edit")
-            self._edit_buttons_groups.append(edit_button)
-            edit_button.clicked.connect(self.editGroup)
-            self.tableGroups.setIndexWidget(self._model_groups.index(i, 1), edit_button)
-        self._model_groups.dataChanged.connect(self.nameButtonsGroup)
-
-        # initialize table settings (and signals)
-        header_view = self.tableGroups.horizontalHeader()
-        header_view.setSectionResizeMode(0, QHeaderView.Stretch)
-        header_view.resizeSection(1, self._BUTTON_WIDTH)
-        self.tableGroups.clicked.connect(self.showMembers)
-        self.tableGroups.activated.connect(self.showMembers)
-
-        # this also calls nameButtonsGroup() (so the buttons will be correctly named)
-        # if for some reason you want to remove this, call self.nameButtonsGroup()
-        self.tableGroups.sortByColumn(0, Qt.AscendingOrder)
 
-    # sets object name of every button to id of group on given row
-    # also slot for signal 'dataChanged', because buttons do not move when sorting table (we just change their names)
-    def nameButtonsGroup(self):
-        for i, button in enumerate(self._edit_buttons_groups):
-            group = self._model_groups.data(self._model_groups.index(i, 0), self._model_groups.MODEL_ROLE)
-            button.setObjectName(str(group.id))
+        # add groups table
+        self.groups_table = GroupTable(Global.db.getGroups())
+        self.layoutTables.addWidget(self.groups_table)
+        self.groups_table.editClicked.connect(self.editGroup)
+        self.groups_table.groupSelected.connect(self.showMembers)
 
-    # initializes members table (sets column widths, signals, etc.)
-    def _initializeMembersTable(self):
-        model = PersonTableModel(num_columns=3)
-        self.tableMembers.setModel(model)
-        header_view = self.tableMembers.horizontalHeader()
-        header_view.setSectionResizeMode(0, QHeaderView.Stretch)
-        header_view.setSectionResizeMode(1, QHeaderView.Stretch)
-        header_view.resizeSection(2, self._BUTTON_WIDTH)
+        # add members table
+        self.members_table = PersonTable([])
+        self.layoutTables.addWidget(self.members_table)
+        self.members_table.editClicked.connect(self.editMember)
 
-    # sets object name of every button to id of user on given row
-    # also slot for signal 'dataChanged', because buttons do not move when sorting table (we just change their names)
-    def nameButtonsMembers(self):
-        model = self.tableMembers.model()
-        for i, button in enumerate(self._edit_buttons_members):
-            member = model.data(model.index(i, 0), model.MODEL_ROLE)
-            button.setObjectName(str(member.id))
+    # reload data, because some other controller changed them
+    def reloadData(self):
+        self.groups_table.changeData(Global.db.getGroups())
+        self.members_table.changeData([])
 
     # changes content of members table to correspond with groups table selection
-    def showMembers(self):
-        index = self.tableGroups.currentIndex()
-        group = self._model_groups.data(index, GroupTableModel.MODEL_ROLE)
-        members = group.getMembers()
-        self._model_members = PersonTableModel(members, 3)
-        self.tableMembers.setModel(self._model_members)
-        self._edit_buttons_members = []
-        for i in range(self._model_members.rowCount()):
-            edit_button = QPushButton("edit")
-            self._edit_buttons_members.append(edit_button)
-            edit_button.clicked.connect(self.editMember)
-            self.tableMembers.setIndexWidget(self._model_members.index(i, 2), edit_button)
-        self._model_members.dataChanged.connect(self.nameButtonsMembers)
-        # this also calls nameButtonsMembers() (so the buttons will be correctly named)
-        # if for some reason you want to remove this, call self.nameButtonsMembers()
-        self.tableMembers.sortByColumn(0, Qt.AscendingOrder)
+    @pyqtSlot(Group)
+    def showMembers(self, group):
+        self.members_table.changeData(group.getMembers())
 
-    def editGroup(self):
-        group = self._model_groups.getGroupById(self.sender().objectName())
+    @pyqtSlot(Group)
+    def editGroup(self, group):
         self.main_window.goToGroupEdit(group)
 
-    def editMember(self):
-        print(self.sender().objectName())
\ No newline at end of file
+    @pyqtSlot(Person)
+    def editMember(self, person):
+        print(person.id)
\ No newline at end of file
diff --git a/Implementace/controllers/mainwindow_controller.py b/Implementace/controllers/mainwindow_controller.py
index 3e5eda2..b470eeb 100644
--- a/Implementace/controllers/mainwindow_controller.py
+++ b/Implementace/controllers/mainwindow_controller.py
@@ -1,5 +1,4 @@
 from PyQt5 import QtWidgets as Qt
-
 from controllers.group_edit_controller import GroupEdit
 from controllers.groups_overview_controller import GroupsOverview
 from model.qtmodels.group_table_model import GroupTableModel
@@ -10,34 +9,39 @@ from globals import Global
 
 class MainWindow(Qt.QMainWindow, mainwindow.Ui_MainWindow):
 
-    def _init_screens(self):
-        self._screens = [
-            GroupsOverview(self),
-        ]
-        self._cur_screen = 0
-
     def __init__(self, parent=None):
         super(MainWindow, self).__init__(parent)
         self.setupUi(self)
-        self._init_screens()
         self.btnBack.clicked.connect(self.goBack)
-        for controller in self._screens:
-            self.stackedWidget.addWidget(controller)
-        self.goToGroupOverview()
+        self.goToGroupsOverview()
+        self._last_changed = 0
+
+    # all controllers have to call this when they change data in db
+    # it prompts every controller before current widget in stack to reload data
+    def dataChanged(self):
+        self._last_changed = self.stackedWidget.currentIndex()
 
-    def goToGroupOverview(self):
-        self.stackedWidget.setCurrentWidget(self._screens[0])
+    def goToGroupsOverview(self):
+        groups_overview = GroupsOverview(self)
+        self.stackedWidget.addWidget(groups_overview)
+        self.stackedWidget.setCurrentWidget(groups_overview)
 
     # if group_id unfilled - create new group
     def goToGroupEdit(self, group=GroupEdit.NEW_GROUP):
+        if group == GroupEdit.NEW_GROUP:
+            self._last_changed = self.stackedWidget.currentIndex() + 1
         group_edit = GroupEdit(self, group)
-        self._screens.append(group_edit)
-        self._cur_screen += 1
         self.stackedWidget.addWidget(group_edit)
         self.stackedWidget.setCurrentWidget(group_edit)
 
     def goBack(self):
-        if self._cur_screen <= 0:
+        current_index = self.stackedWidget.currentIndex()
+        if current_index <= 0:
+            # we're on groups overview (do nothing)
+            print('nope')
             return
-        self._cur_screen -= 1
-        self.stackedWidget.setCurrentIndex(self._cur_screen)
+        if current_index <= self._last_changed:
+            self.stackedWidget.widget(current_index - 1).reloadData()
+            self._last_changed -= 1
+        self.stackedWidget.removeWidget(self.stackedWidget.currentWidget())
+        self.stackedWidget.setCurrentIndex(current_index - 1)
diff --git a/Implementace/database.py b/Implementace/database.py
index e9e5b8c..0a99a3a 100644
--- a/Implementace/database.py
+++ b/Implementace/database.py
@@ -32,6 +32,7 @@ class Database:
         return res
 
     # creates new group, returns (id, name)
+    # TODO can still conflict (e.g. you deleted 'Nová skupina' and still have 'Nová skupina 2')
     def createNewGroup(self):
         curs = self.connection.execute('''SELECT name FROM groups WHERE name LIKE 'Nová skupina%' ''')
         name = "Nová skupina"
diff --git a/Implementace/model/group.py b/Implementace/model/group.py
index a1441b1..1086da3 100644
--- a/Implementace/model/group.py
+++ b/Implementace/model/group.py
@@ -9,9 +9,12 @@ class Group:
         else:
             self.id = db_row[0]
             self.name = db_row[1]
+        self._members = None
 
     def getMembers(self):
-        return Global.db.getGroupMembers(self.id)
+        if self._members is None:
+            self._members = Global.db.getGroupMembers(self.id)
+        return self._members
 
     def delete(self):
-        Global.db.deleteGroup(self.id)
\ No newline at end of file
+        Global.db.deleteGroup(self.id)
diff --git a/Implementace/model/qtmodels/person_table_model.py b/Implementace/model/qtmodels/person_table_model.py
index 32a2f8a..7642f45 100644
--- a/Implementace/model/qtmodels/person_table_model.py
+++ b/Implementace/model/qtmodels/person_table_model.py
@@ -22,7 +22,6 @@ class PersonTableModel(QtCore.QAbstractTableModel):
             if p_int == 1:
                 return 'Jméno'
 
-
     def data(self, index, role=None):
         person = self._people[index.row()]
         if role == QtCore.Qt.DisplayRole:
@@ -46,7 +45,7 @@ class PersonTableModel(QtCore.QAbstractTableModel):
                 self._people.sort(key=lambda person: person.surname, reverse=True)
 
         #sorting by name
-        if p_int == 0:
+        if p_int == 1:
             if order == QtCore.Qt.AscendingOrder:
                 self._people.sort(key=lambda person: person.name)
             if order == QtCore.Qt.DescendingOrder:
@@ -56,5 +55,5 @@ class PersonTableModel(QtCore.QAbstractTableModel):
                          self.index(self.rowCount(), 0),
                          [])
 
-        def getPersonById(self, person_id):
-            return next(person for person in self._people if person.id == person_id)
+    def getPersonById(self, person_id):
+        return next((person for person in self._people if person.id == int(person_id)), None)
diff --git a/Implementace/utils/group_table.py b/Implementace/utils/group_table.py
new file mode 100644
index 0000000..d19060e
--- /dev/null
+++ b/Implementace/utils/group_table.py
@@ -0,0 +1,63 @@
+from windows import grouptable
+from model.qtmodels.group_table_model import GroupTableModel
+from PyQt5.QtCore import *
+from PyQt5.QtWidgets import *
+from model.group import Group
+
+
+class GroupTable(QTableView, grouptable.Ui_Form):
+    _BUTTON_WIDTH = 50
+
+    editClicked = pyqtSignal(Group)
+    groupSelected = pyqtSignal(Group)
+
+    def __init__(self, data=[], parent=None):
+        super(GroupTable, self).__init__(parent)
+        self.setupUi(self)
+
+        self._model = GroupTableModel(data, 2)
+        self.tableGroups.setModel(self._model)
+        self.insertButtons()
+        self._model.dataChanged.connect(self.nameButtons)
+
+        # initialize table settings (and signals)
+        header_view = self.tableGroups.horizontalHeader()
+        header_view.setSectionResizeMode(0, QHeaderView.Stretch)
+        header_view.setSectionResizeMode(1, QHeaderView.Fixed)
+        header_view.resizeSection(1, self._BUTTON_WIDTH)
+        self.tableGroups.clicked.connect(self.onGroupSelected)
+        self.tableGroups.activated.connect(self.onGroupSelected)
+
+        # this also calls nameButtonsG() (so the buttons will be correctly named)
+        # if for some reason you want to remove this, call self.nameButtons()
+        self.tableGroups.sortByColumn(0, Qt.AscendingOrder)
+
+    def insertButtons(self):
+        self._edit_buttons = []  # if we're reloading data
+        for i in range(self._model.rowCount()):
+            edit_button = QPushButton("edit")
+            self._edit_buttons.append(edit_button)
+            edit_button.clicked.connect(self.onEditClicked)
+            self.tableGroups.setIndexWidget(self._model.index(i, 1), edit_button)
+
+    # sets object name of every button to id of group on given row
+    # also slot for signal 'dataChanged', because buttons do not move when sorting table (we just change their names)
+    def nameButtons(self):
+        for i, button in enumerate(self._edit_buttons):
+            group = self._model.data(self._model.index(i, 0), self._model.MODEL_ROLE)
+            button.setObjectName(str(group.id))
+
+    def onEditClicked(self):
+        group = self._model.getGroupById(self.sender().objectName())
+        self.editClicked.emit(group)
+
+    def onGroupSelected(self):
+        group = self._model.data(self.tableGroups.currentIndex(), GroupTableModel.MODEL_ROLE)
+        self.groupSelected.emit(group)
+
+    def changeData(self, data):
+        self._model = GroupTableModel(data, 2)
+        self.tableGroups.setModel(self._model)
+        self.insertButtons()
+        self._model.dataChanged.connect(self.nameButtons)
+        self.tableGroups.sortByColumn(0, Qt.AscendingOrder)
diff --git a/Implementace/utils/person_table.py b/Implementace/utils/person_table.py
new file mode 100644
index 0000000..bcd9beb
--- /dev/null
+++ b/Implementace/utils/person_table.py
@@ -0,0 +1,57 @@
+from windows import persontable
+from model.qtmodels.person_table_model import PersonTableModel
+from PyQt5.QtCore import *
+from PyQt5.QtWidgets import *
+from model.person import Person
+
+
+class PersonTable(QTableView, persontable.Ui_Form):
+    _BUTTON_WIDTH = 50
+
+    editClicked = pyqtSignal(Person)
+
+    def __init__(self, data=[], parent=None):
+        super(PersonTable, self).__init__(parent)
+        self.setupUi(self)
+
+        self._model = PersonTableModel(data, 3)
+        self.tablePeople.setModel(self._model)
+        self.insertButtons()
+        self._model.dataChanged.connect(self.nameButtons)
+
+        # initialize table settings (and signals)
+        header_view = self.tablePeople.horizontalHeader()
+        header_view.setSectionResizeMode(0, QHeaderView.Stretch)
+        header_view.setSectionResizeMode(1, QHeaderView.Stretch)
+        header_view.setSectionResizeMode(2, QHeaderView.Fixed)
+        header_view.resizeSection(2, self._BUTTON_WIDTH)
+
+        # this also calls nameButtons() (so the buttons will be correctly named)
+        # if for some reason you want to remove this, call self.nameButtons()
+        self.tablePeople.sortByColumn(0, Qt.AscendingOrder)
+
+    def insertButtons(self):
+        self._edit_buttons = []  # if we're reloading data
+        for i in range(self._model.rowCount()):
+            edit_button = QPushButton("edit")
+            self._edit_buttons.append(edit_button)
+            edit_button.clicked.connect(self.onEditClicked)
+            self.tablePeople.setIndexWidget(self._model.index(i, 2), edit_button)
+
+    # sets object name of every button to id of group on given row
+    # also slot for signal 'dataChanged', because buttons do not move when sorting table (we just change their names)
+    def nameButtons(self):
+        for i, button in enumerate(self._edit_buttons):
+            person = self._model.data(self._model.index(i, 0), self._model.MODEL_ROLE)
+            button.setObjectName(str(person.id))
+
+    def onEditClicked(self):
+        person = self._model.getPersonById(self.sender().objectName())
+        self.editClicked.emit(person)
+
+    def changeData(self, data):
+        self._model = PersonTableModel(data, 3)
+        self.tablePeople.setModel(self._model)
+        self.insertButtons()
+        self._model.dataChanged.connect(self.nameButtons)
+        self.tablePeople.sortByColumn(0, Qt.AscendingOrder)
diff --git a/Implementace/windows/groupedit.py b/Implementace/windows/groupedit.py
index 770e657..b1e5ca4 100644
--- a/Implementace/windows/groupedit.py
+++ b/Implementace/windows/groupedit.py
@@ -46,8 +46,8 @@ class Ui_Form(object):
         self.verticalLayout_3 = QtWidgets.QVBoxLayout()
         self.verticalLayout_3.setSpacing(0)
         self.verticalLayout_3.setObjectName("verticalLayout_3")
-        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
-        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+        self.layoutMembers = QtWidgets.QHBoxLayout()
+        self.layoutMembers.setObjectName("layoutMembers")
         self.label_2 = QtWidgets.QLabel(Form)
         self.label_2.setMinimumSize(QtCore.QSize(80, 0))
         self.label_2.setMaximumSize(QtCore.QSize(80, 16777215))
@@ -58,15 +58,12 @@ class Ui_Form(object):
         self.label_2.setFont(font)
         self.label_2.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop)
         self.label_2.setObjectName("label_2")
-        self.horizontalLayout_2.addWidget(self.label_2)
-        self.tableMembers = QtWidgets.QTableView(Form)
-        self.tableMembers.setObjectName("tableMembers")
-        self.horizontalLayout_2.addWidget(self.tableMembers)
+        self.layoutMembers.addWidget(self.label_2)
         spacerItem2 = QtWidgets.QSpacerItem(80, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)
-        self.horizontalLayout_2.addItem(spacerItem2)
-        self.verticalLayout_3.addLayout(self.horizontalLayout_2)
-        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
-        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
+        self.layoutMembers.addItem(spacerItem2)
+        self.verticalLayout_3.addLayout(self.layoutMembers)
+        self.layoutOthers = QtWidgets.QHBoxLayout()
+        self.layoutOthers.setObjectName("layoutOthers")
         self.label_3 = QtWidgets.QLabel(Form)
         self.label_3.setMinimumSize(QtCore.QSize(80, 0))
         self.label_3.setMaximumSize(QtCore.QSize(80, 16777215))
@@ -77,13 +74,10 @@ class Ui_Form(object):
         self.label_3.setFont(font)
         self.label_3.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop)
         self.label_3.setObjectName("label_3")
-        self.horizontalLayout_3.addWidget(self.label_3)
-        self.treeOthers = QtWidgets.QTreeView(Form)
-        self.treeOthers.setObjectName("treeOthers")
-        self.horizontalLayout_3.addWidget(self.treeOthers)
+        self.layoutOthers.addWidget(self.label_3)
         spacerItem3 = QtWidgets.QSpacerItem(80, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)
-        self.horizontalLayout_3.addItem(spacerItem3)
-        self.verticalLayout_3.addLayout(self.horizontalLayout_3)
+        self.layoutOthers.addItem(spacerItem3)
+        self.verticalLayout_3.addLayout(self.layoutOthers)
         self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
         self.horizontalLayout_4.setObjectName("horizontalLayout_4")
         spacerItem4 = QtWidgets.QSpacerItem(80, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
diff --git a/Implementace/windows/groupsoverview.py b/Implementace/windows/groupsoverview.py
index b297fc4..792f0d9 100644
--- a/Implementace/windows/groupsoverview.py
+++ b/Implementace/windows/groupsoverview.py
@@ -22,31 +22,9 @@ class Ui_Form(object):
         spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
         self.horizontalLayout.addItem(spacerItem)
         self.verticalLayout.addLayout(self.horizontalLayout)
-        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
-        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
-        self.tableGroups = QtWidgets.QTableView(Form)
-        self.tableGroups.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
-        self.tableGroups.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
-        self.tableGroups.setShowGrid(False)
-        self.tableGroups.setSortingEnabled(True)
-        self.tableGroups.setCornerButtonEnabled(False)
-        self.tableGroups.setObjectName("tableGroups")
-        self.tableGroups.horizontalHeader().setHighlightSections(False)
-        self.tableGroups.verticalHeader().setVisible(False)
-        self.tableGroups.verticalHeader().setCascadingSectionResizes(True)
-        self.horizontalLayout_2.addWidget(self.tableGroups)
-        self.tableMembers = QtWidgets.QTableView(Form)
-        self.tableMembers.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
-        self.tableMembers.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
-        self.tableMembers.setShowGrid(False)
-        self.tableMembers.setSortingEnabled(True)
-        self.tableMembers.setCornerButtonEnabled(False)
-        self.tableMembers.setObjectName("tableMembers")
-        self.tableMembers.horizontalHeader().setHighlightSections(False)
-        self.tableMembers.verticalHeader().setVisible(False)
-        self.tableMembers.verticalHeader().setCascadingSectionResizes(True)
-        self.horizontalLayout_2.addWidget(self.tableMembers)
-        self.verticalLayout.addLayout(self.horizontalLayout_2)
+        self.layoutTables = QtWidgets.QHBoxLayout()
+        self.layoutTables.setObjectName("layoutTables")
+        self.verticalLayout.addLayout(self.layoutTables)
 
         self.retranslateUi(Form)
         QtCore.QMetaObject.connectSlotsByName(Form)
diff --git a/Implementace/windows/grouptable.py b/Implementace/windows/grouptable.py
new file mode 100644
index 0000000..513a807
--- /dev/null
+++ b/Implementace/windows/grouptable.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'grouptable.ui'
+#
+# Created by: PyQt5 UI code generator 5.8.1
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Form(object):
+    def setupUi(self, Form):
+        Form.setObjectName("Form")
+        Form.resize(400, 300)
+        self.verticalLayout = QtWidgets.QVBoxLayout(Form)
+        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
+        self.verticalLayout.setSpacing(0)
+        self.verticalLayout.setObjectName("verticalLayout")
+        self.tableGroups = QtWidgets.QTableView(Form)
+        self.tableGroups.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
+        self.tableGroups.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
+        self.tableGroups.setShowGrid(False)
+        self.tableGroups.setSortingEnabled(True)
+        self.tableGroups.setCornerButtonEnabled(False)
+        self.tableGroups.setObjectName("tableGroups")
+        self.tableGroups.horizontalHeader().setHighlightSections(False)
+        self.tableGroups.verticalHeader().setVisible(False)
+        self.tableGroups.verticalHeader().setCascadingSectionResizes(True)
+        self.verticalLayout.addWidget(self.tableGroups)
+
+        self.retranslateUi(Form)
+        QtCore.QMetaObject.connectSlotsByName(Form)
+
+    def retranslateUi(self, Form):
+        _translate = QtCore.QCoreApplication.translate
+        Form.setWindowTitle(_translate("Form", "Form"))
+
diff --git a/Implementace/windows/qt/groupoverview.ui b/Implementace/windows/qt/groupoverview.ui
index e1e5b12..e40cfd7 100644
--- a/Implementace/windows/qt/groupoverview.ui
+++ b/Implementace/windows/qt/groupoverview.ui
@@ -39,64 +39,7 @@
     </layout>
    </item>
    <item>
-    <layout class="QHBoxLayout" name="horizontalLayout_2">
-     <item>
-      <widget class="QTableView" name="tableGroups">
-       <property name="selectionMode">
-        <enum>QAbstractItemView::SingleSelection</enum>
-       </property>
-       <property name="selectionBehavior">
-        <enum>QAbstractItemView::SelectRows</enum>
-       </property>
-       <property name="showGrid">
-        <bool>false</bool>
-       </property>
-       <property name="sortingEnabled">
-        <bool>true</bool>
-       </property>
-       <property name="cornerButtonEnabled">
-        <bool>false</bool>
-       </property>
-       <attribute name="horizontalHeaderHighlightSections">
-        <bool>false</bool>
-       </attribute>
-       <attribute name="verticalHeaderVisible">
-        <bool>false</bool>
-       </attribute>
-       <attribute name="verticalHeaderCascadingSectionResizes">
-        <bool>true</bool>
-       </attribute>
-      </widget>
-     </item>
-     <item>
-      <widget class="QTableView" name="tableMembers">
-       <property name="selectionMode">
-        <enum>QAbstractItemView::SingleSelection</enum>
-       </property>
-       <property name="selectionBehavior">
-        <enum>QAbstractItemView::SelectRows</enum>
-       </property>
-       <property name="showGrid">
-        <bool>false</bool>
-       </property>
-       <property name="sortingEnabled">
-        <bool>true</bool>
-       </property>
-       <property name="cornerButtonEnabled">
-        <bool>false</bool>
-       </property>
-       <attribute name="horizontalHeaderHighlightSections">
-        <bool>false</bool>
-       </attribute>
-       <attribute name="verticalHeaderVisible">
-        <bool>false</bool>
-       </attribute>
-       <attribute name="verticalHeaderCascadingSectionResizes">
-        <bool>true</bool>
-       </attribute>
-      </widget>
-     </item>
-    </layout>
+    <layout class="QHBoxLayout" name="layoutTables"/>
    </item>
   </layout>
  </widget>
diff --git a/Implementace/windows/qt/qt.pro b/Implementace/windows/qt/qt.pro
index efe16be..263e67c 100644
--- a/Implementace/windows/qt/qt.pro
+++ b/Implementace/windows/qt/qt.pro
@@ -30,4 +30,6 @@ HEADERS  += mainwindow.h
 
 FORMS    += mainwindow.ui \
     groupoverview.ui \
-    groupedit.ui
+    groupedit.ui \
+    grouptable.ui \
+    persontable.ui
diff --git a/Implementace/windows/qt/qt.pro.user b/Implementace/windows/qt/qt.pro.user
index 782ad29..de6987c 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-03-17T22:12:48. -->
+<!-- Written by QtCreator 4.2.1, 2017-03-19T20:14:30. -->
 <qtcreator>
  <data>
   <variable>EnvironmentId</variable>
-- 
GitLab