Last active
March 31, 2022 16:43
-
-
Save f4exb/dfbfa0aa4397240d1d55110241e5c6c9 to your computer and use it in GitHub Desktop.
SDRangel v7 main window PyQt5 mock up
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PyQt5.QtCore import * | |
from PyQt5.QtWidgets import QApplication | |
from PyQt5.QtWidgets import QMainWindow | |
from PyQt5.QtWidgets import QMdiArea | |
from PyQt5.QtWidgets import QWidget | |
from PyQt5.QtWidgets import QDockWidget | |
from PyQt5.QtWidgets import QAction | |
from PyQt5.QtWidgets import QHBoxLayout | |
from PyQt5.QtWidgets import QVBoxLayout | |
from PyQt5.QtWidgets import QMdiSubWindow | |
from PyQt5.QtWidgets import QPushButton | |
from PyQt5.QtWidgets import QLabel | |
from PyQt5.QtWidgets import QSpacerItem | |
from PyQt5.QtWidgets import QSizePolicy | |
from PyQt5.QtWidgets import QTextEdit | |
from PyQt5.QtWidgets import QSizeGrip | |
from PyQt5.QtWidgets import QStyle | |
from PyQt5.QtGui import QPalette | |
from PyQt5.QtGui import QColor | |
from PyQt5.QtGui import QIcon | |
import sys | |
def make_palette(): | |
""" Make theme like SDRangel's | |
""" | |
palette = QPalette() | |
palette.setColor(QPalette.Window, QColor(53,53,53)) | |
palette.setColor(QPalette.WindowText, Qt.white) | |
palette.setColor(QPalette.Base, QColor(25,25,25)) | |
palette.setColor(QPalette.AlternateBase, QColor(53,53,53)) | |
palette.setColor(QPalette.ToolTipBase, Qt.white) | |
palette.setColor(QPalette.ToolTipText, Qt.black) | |
palette.setColor(QPalette.Text, Qt.white) | |
palette.setColor(QPalette.Button, QColor(0x40, 0x40, 0x40)) | |
palette.setColor(QPalette.ButtonText, Qt.black) | |
palette.setColor(QPalette.BrightText, Qt.red) | |
palette.setColor(QPalette.Light, QColor(53,53,53).lighter(125).lighter()) | |
palette.setColor(QPalette.Midlight, QColor(53,53,53).lighter(125).lighter()) | |
palette.setColor(QPalette.Mid, QColor(53,53,53).lighter(125)) | |
palette.setColor(QPalette.Dark, QColor(53,53,53).lighter(125).darker()) | |
palette.setColor(QPalette.Link, QColor(0,0xa0,0xa0)) | |
palette.setColor(QPalette.LinkVisited, QColor(0,0xa0,0xa0).lighter()) | |
palette.setColor(QPalette.Highlight, QColor(0xff, 0x8c, 0x00)) | |
palette.setColor(QPalette.HighlightedText, Qt.black) | |
return palette | |
class AppWindow(QMainWindow): | |
def __init__(self): | |
super().__init__() | |
self.title = 'MDI inside docks' | |
self.left = 0 | |
self.top = 0 | |
self.width = 900 | |
self.height = 600 | |
self.setWindowTitle(self.title) | |
self.setGeometry(self.left, self.top, self.width, self.height) | |
self.workspaces = [] | |
bar = self.menuBar() | |
file_menu = bar.addMenu("File") | |
file_menu.addAction("Exit") | |
file_menu.triggered[QAction].connect(self.file_menu_trig) | |
workspace_menu = bar.addMenu("Workspaces") | |
workspace_menu.addAction("New") | |
workspace_menu.addAction("View all") | |
workspace_menu.triggered[QAction].connect(self.workspace_menu_trig) | |
def file_menu_trig(self, p): | |
if p.text() == "Exit": | |
self.close() | |
def workspace_menu_trig(self, p): | |
if p.text() == "New": | |
workspace_id = len(self.workspaces) | |
workspace = Workspace(self, workspace_id) | |
self.workspaces.append(workspace) | |
self.addDockWidget(Qt.RightDockWidgetArea, workspace) | |
# tabify and set focus on the workspace that was just added | |
if len(self.workspaces) > 1: | |
for i in range(1, len(self.workspaces)): | |
self.tabifyDockWidget(self.workspaces[0], self.workspaces[i]) | |
workspace.show() | |
workspace.raise_() | |
elif p.text() == "View all": | |
for workspace in self.workspaces: | |
if workspace.isHidden(): | |
workspace.show() | |
class SubUI(QMdiSubWindow): | |
def __init__(self, parent, id, sub_id): | |
super(QMdiSubWindow, self).__init__(parent) | |
self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint) | |
self.resize(600, 400) | |
# self.contentFrame = QFrame(self) | |
# There are two Buttons and using them custom title bar. | |
# We could give them string or pictures. | |
self.indexLabel = QLabel() | |
self.indexLabel.setFixedSize(16, 16) | |
self.indexLabel.setStyleSheet("QLabel { background-color: rgb(0, 255, 255); color: black; qproperty-alignment: AlignCenter; }") | |
self.indexLabel.setText(f"R{id}:{sub_id}") | |
self.indexLabel.setFixedSize(40, 16) | |
self.titleLabel = QLabel() | |
self.titleLabel.setText("DSD Demodulator") | |
self.closeButton = QPushButton() | |
self.closeButton.setFixedSize(16, 16) | |
self.closeButton.setIcon(self.style().standardIcon(QStyle.SP_TitleBarCloseButton)) | |
self.closeButton.clicked.connect(self.closeClicked) | |
self.statusLabel = QLabel() | |
self.statusLabel.setText("OK") | |
self.statusLabel.setFixedSize(16, 100) | |
self.statusLabel.setFixedHeight(16) | |
# And some layouts. | |
# This is the global layout (vertical). | |
self.layouts = QVBoxLayout() | |
self.layouts.setContentsMargins(2, 4, 0, 4) | |
self.layouts.setSpacing(2) | |
# This is the top layout (horizontal). | |
self.topLayout = QHBoxLayout() | |
self.topLayout.setContentsMargins(0, 0, 0, 0) | |
self.topLayout.addWidget(self.indexLabel) | |
self.topLayout.addWidget(self.titleLabel) | |
self.topLayout.addStretch(1) | |
self.topLayout.addWidget(self.closeButton) | |
self.sizegripTop = QSizeGrip(self) | |
self.topLayout.addWidget(self.sizegripTop, 0, Qt.AlignTop | Qt.AlignRight) | |
self.centerLayout = QHBoxLayout() | |
self.spacer = QSpacerItem(40, 40, QSizePolicy.Expanding, QSizePolicy.Expanding) | |
self.botLayout = QHBoxLayout() | |
self.botLayout.setContentsMargins(0, 0, 0, 0) | |
self.botLayout.addWidget(self.statusLabel) | |
self.sizegripBot = QSizeGrip(self) | |
self.botLayout.addWidget(self.sizegripBot, 0, Qt.AlignBottom | Qt.AlignRight) | |
self.layouts.addLayout(self.topLayout) | |
self.layouts.addLayout(self.centerLayout) | |
self.layouts.addLayout(self.botLayout) | |
# Replace layout | |
QObjectCleanupHandler().add(self.layout()) | |
self.setLayout(self.layouts) | |
def addContent(self, widget): | |
self.centerLayout.addWidget(widget) | |
def closeClicked(self): | |
self.close() | |
def mousePressEvent(self, event): | |
if event.buttons() == Qt.LeftButton: | |
self.m_drag = True | |
self.m_DragPosition = event.globalPos()-self.pos() | |
event.accept() | |
def mouseMoveEvent(self, event): | |
try: | |
if event.buttons() and Qt.LeftButton: | |
self.move(event.globalPos()-self.m_DragPosition) | |
event.accept() | |
except AttributeError: | |
pass | |
def mouseReleaseEvent(self, event): | |
self.m_drag = False | |
class Workspace(QDockWidget): | |
def __init__(self, parent, id): | |
super(QDockWidget, self).__init__(parent) | |
self.id = id | |
self.setWindowTitle(f"W{id}") | |
self.mdi = QMdiArea() | |
self.mdi.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) | |
self.mdi.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) | |
self.setWidget(self.mdi) | |
self.submdi_count = 0 | |
self.title_bar = QWidget() | |
self.title_bar_layout = QHBoxLayout() | |
self.title_bar_layout.setContentsMargins(1, 1, 1, 1) | |
self.title_bar.setLayout(self.title_bar_layout) | |
self.title_label = QLabel() | |
self.title_label.setText(f"W{id}") | |
self.add_ui_button = QPushButton() | |
self.add_ui_button.setText("Add") | |
self.add_ui_button.setToolTip("Add a new window") | |
self.add_ui_button.setFixedSize(32, 20) | |
self.add_ui_button.clicked.connect(self.add_window) | |
self.cascade_ui_button = QPushButton() | |
self.cascade_ui_button.setText("Cas") | |
self.cascade_ui_button.setToolTip("Cascade windows") | |
self.cascade_ui_button.setFixedSize(32, 20) | |
self.cascade_ui_button.clicked.connect(self.cascade_windows) | |
self.tile_ui_button = QPushButton() | |
self.tile_ui_button.setText("Til") | |
self.tile_ui_button.setToolTip("Tile windows") | |
self.tile_ui_button.setFixedSize(32, 20) | |
self.tile_ui_button.clicked.connect(self.tile_windows) | |
self.normalButton = QPushButton() | |
self.normalButton.setFixedSize(16, 16) | |
self.normalButton.setIcon(self.style().standardIcon(QStyle.SP_TitleBarNormalButton)) | |
self.normalButton.clicked.connect(self.toggle_floating) | |
self.closeButton = QPushButton() | |
self.closeButton.setFixedSize(16, 16) | |
self.closeButton.setIcon(self.style().standardIcon(QStyle.SP_TitleBarCloseButton)) | |
self.closeButton.clicked.connect(self.make_hiding) | |
self.title_bar_layout.addWidget(self.title_label) | |
self.title_bar_layout.addWidget(self.add_ui_button) | |
self.title_bar_layout.addWidget(self.cascade_ui_button) | |
self.title_bar_layout.addWidget(self.tile_ui_button) | |
self.title_bar_layout.addStretch(1) | |
self.title_bar_layout.addWidget(self.normalButton) | |
self.title_bar_layout.addWidget(self.closeButton) | |
self.setTitleBarWidget(self.title_bar) | |
def add_window(self): | |
sub = SubUI(self, self.id, self.submdi_count) | |
self.submdi_count += 1 | |
sub.addContent(QTextEdit()) | |
#sub.setWindowTitle("Sub Window" + str(self.submdi_count)) | |
self.mdi.addSubWindow(sub) | |
sub.show() | |
def cascade_windows(self): | |
self.mdi.cascadeSubWindows() | |
def tile_windows(self): | |
self.mdi.tileSubWindows() | |
def toggle_floating(self): | |
self.setFloating(not self.isFloating()) | |
def make_hiding(self): | |
self.hide() | |
if __name__ == '__main__': | |
app = QApplication(sys.argv) | |
app.setPalette(make_palette()) | |
ex = AppWindow() | |
ex.show() | |
sys.exit(app.exec_()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a small mock up in Python (PyQt5) showing the top level items and their arrangement