Skip to content
Snippets Groups Projects
Commit 787ad8c3 authored by Thomas Holene Løkkeborg's avatar Thomas Holene Løkkeborg
Browse files

#18 merget fra master & fikset sidebar vidde

parents 2d33ab50 1f7884f2
No related branches found
No related tags found
1 merge request!3#18 MVP brukergrensesnitt - inline edit view
Pipeline #71082 failed
......@@ -141,7 +141,8 @@ disable=print-statement,
comprehension-escape,
E0611,
I1101,
E1101
E1101,
R0901
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
......
"""Hovedvinduet."""
"""MainWindow.
During initial development this module will include most of the code necessary
to get our project up-and-running. When our project matures we will move code
out to separate modules.
"""
import sys
import os
from PySide2.QtCore import QRectF, QPoint, QTimer, Qt
from PySide2.QtWidgets import QTabWidget, QWidget, QMainWindow, QApplication, \
QHBoxLayout, QVBoxLayout, QPushButton, QTreeWidget, QGraphicsScene, \
QGraphicsView, QAction, QScrollArea, QGraphicsRectItem
from PySide2.QtWidgets import QTabWidget, QWidget, QMainWindow, \
QApplication, QHBoxLayout, QVBoxLayout, QPushButton, QLabel, \
QAbstractItemView, QListWidget, QListWidgetItem, QAction, QGraphicsScene, \
QGraphicsView, QScrollArea, QGraphicsRectItem
from PySide2.QtGui import QBrush, QIcon, QPalette
......@@ -83,7 +89,7 @@ class MainWindow(QMainWindow):
# Legger til MainWidget som en tab, kanskje flytt ut til egen funksjon
tabs = QTabWidget()
tab = MainWidget()
tab = SOIWorkspaceWidget()
tabs.addTab(tab, "MainTab")
self.setCentralWidget(tabs)
......@@ -95,30 +101,74 @@ class MainWindow(QMainWindow):
self.setWindowIcon(QIcon(filepath))
class MainWidget(QWidget):
"""Hovedwidget til applikasjonen, dette er det som blir tabs."""
class SOIWorkspaceWidget(QWidget):
"""Contains the working area for a single SOI.
The widget is used inside tabs in our application, and contains a sidebar
with a module list along with a view of the SOI.
"""
def __init__(self):
super().__init__()
layout1 = QHBoxLayout()
layout2 = QVBoxLayout()
# New module button
new_module = QPushButton("Ny modul")
new_module.setShortcut("Ctrl+m")
new_module.setStatusTip("Legg til en ny modul")
self.layout_wrapper = QHBoxLayout()
self.layout_sidebar = QVBoxLayout()
# all widgets
self.button_new_module = QPushButton("Ny modul")
self.button_new_module.setShortcut("Ctrl+m")
self.button_new_module.setStatusTip("Legg til en ny modul")
self.button_setup = QPushButton("Oppsett")
self.list_modules = QListWidget()
self.view = ViewArea()
self.widget_sidebar = QWidget()
self.widget_sidebar.setFixedWidth(200)
# prepare module list
self.setup_list_modules()
self.fill_list_modules()
# build layouts
self.layout_sidebar.addWidget(QLabel("Moduler:"))
self.layout_sidebar.addWidget(self.list_modules, 5)
self.layout_sidebar.addWidget(QLabel("Vedlegg:"))
self.layout_sidebar.addWidget(QListWidget(), 1)
self.layout_sidebar.addWidget(self.button_new_module)
self.layout_sidebar.addWidget(self.button_setup)
self.widget_sidebar.setLayout(self.layout_sidebar)
self.layout_wrapper.addWidget(self.widget_sidebar)
self.layout_wrapper.addWidget(self.view)
self.setLayout(self.layout_wrapper)
def setup_list_modules(self):
"""Prepare module list.
The list contains modules that are drag-and-droppable.
"""
# enable drag-and-drop
self.list_modules.setDragEnabled(True)
self.list_modules.viewport().setAcceptDrops(True)
self.list_modules.viewport().setAcceptDrops(True)
self.list_modules.setDragDropMode(QAbstractItemView.InternalMove)
tree_view = QTreeWidget()
setup = QPushButton("Oppsett")
layout2.addWidget(tree_view)
layout2.addWidget(new_module)
layout2.addWidget(setup)
# source: https://www.qtcentre.org/threads/32500-Horizontal-Scrolling-QListWidget
self.list_modules.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
view = ViewArea()
layout1.addLayout(layout2, 2)
layout1.addWidget(view, 8)
def fill_list_modules(self):
"""Fill module list with some items to manually test with.
self.setLayout(layout1)
This function will be removed when we can fill the list properly.
"""
# hardcode some items
items = [
QListWidgetItem("Frekvenstabell"),
QListWidgetItem("Sambandsdiagram"),
QListWidgetItem("Autentifiseringstavle"),
QListWidgetItem("Subtraktorkoder"),
]
for i, item in enumerate(items):
self.list_modules.insertItem(i, item)
class ViewArea(QWidget):
......
"""Base/interface of each module."""
from abc import ABC
class ModuleBase(ABC):
"""Interface for SOI-modules."""
def get_size(self):
"""Abstract method, should be implemented by derived class."""
raise NotImplementedError
def render_onto_pdf(self):
"""Abstract method, should be implemented by derived class."""
raise NotImplementedError
"""Module containing subclassed SOIModule (QTableWidget, ModuleBase)."""
from PySide2.QtWidgets import QTableWidget, QTableWidgetItem, QShortcut
from PySide2 import QtGui
from module_base import ModuleBase
HEADER_FONT = QtGui.QFont()
HEADER_FONT.setFamily('Arial')
HEADER_FONT.setPointSize(12)
HEADER_FONT.setWeight(100)
class Meta(type(ModuleBase), type(QTableWidget)):
"""Used as a metaclass to enable multiple inheritance."""
class TableModule(ModuleBase, QTableWidget, metaclass=Meta):
"""Modified QTableWidget.
Has shortcuts for adding and removing rows and columns.
Also inherits functions from ModuleBase, which is implemented by this class.
"""
def __init__(self):
"""Initialize QTableWidget."""
QTableWidget.__init__(self)
super(QTableWidget)
self.horizontalHeader().hide()
self.verticalHeader().hide()
self.setColumnCount(2)
self.setRowCount(2)
self.set_header_item(0, "")
self.set_header_item(1, "")
self.resizeRowsToContents()
self.resizeColumnsToContents()
self.cellChanged.connect(self.cell_changed)
self.set_shortcuts()
def set_header_item(self, column, text):
"""Insert item with header-style.
Item will always be set on header row (top row).
Parameters
----------
column : int
What column index for inserting item.
text : String
What text the item should contain.
"""
item = QTableWidgetItem(text)
item.setBackground(QtGui.QBrush(QtGui.QColor(220, 220, 220)))
item.setFont(HEADER_FONT)
self.setItem(0, column, item)
def set_shortcuts(self):
"""Set shortcuts for adding and removing rows and columns."""
shortcut_add_col = QShortcut(QtGui.QKeySequence("Shift++"), self)
shortcut_rem_col = QShortcut(QtGui.QKeySequence("Shift+-"), self)
shortcut_add_row = QShortcut(QtGui.QKeySequence("Ctrl++"), self)
shortcut_rem_row = QShortcut(QtGui.QKeySequence("Ctrl+-"), self)
shortcut_add_col.activated.connect(self.add_column)
shortcut_rem_col.activated.connect(self.remove_column)
shortcut_add_row.activated.connect(self.add_row)
shortcut_rem_row.activated.connect(self.remove_row)
def add_column(self):
"""Add column to the right of selected column."""
self.insertColumn(self.columnCount())
# From selected column, move all columns one step to the right
to_pos = self.columnCount() - 2 # to_pos is target index for columns
while to_pos > self.currentColumn():
# Loop through all rows
for j in range(self.rowCount()):
item = self.takeItem(j, to_pos)
self.setItem(j, to_pos + 1, item)
to_pos -= 1
self.set_header_item(self.currentColumn() + 1, "")
self.resizeColumnsToContents()
def remove_column(self):
"""Remove selected column if two or more columns exist."""
if self.columnCount() > 1:
self.removeColumn(self.currentColumn())
def add_row(self):
"""Add row below selected row."""
self.insertRow(self.currentRow() + 1)
self.resizeRowsToContents()
def remove_row(self):
"""Remove selected row if two or more rows exist (including header)."""
if self.rowCount() > 2:
self.removeRow(self.currentRow())
def cell_changed(self):
"""Resize rows and columns to contents when a cell changes."""
self.resizeColumnsToContents()
self.resizeRowsToContents()
def get_size(self):
"""Get size of widget.
Returns
-------
Tuple
(width, height) (total)
"""
width = 0
for i in range(self.columnCount()):
width += self.columnWidth(i)
height = 0
for i in range(self.columnCount()):
height += self.rowHeight(i)
return width, height
def render_onto_pdf(self):
"""Render onto pdf."""
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment