Skip to content

Instantly share code, notes, and snippets.

@f4exb
Last active March 31, 2022 16:43
Show Gist options
  • Save f4exb/dfbfa0aa4397240d1d55110241e5c6c9 to your computer and use it in GitHub Desktop.
Save f4exb/dfbfa0aa4397240d1d55110241e5c6c9 to your computer and use it in GitHub Desktop.
SDRangel v7 main window PyQt5 mock up
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_())
@f4exb
Copy link
Author

f4exb commented Mar 30, 2022

This is a small mock up in Python (PyQt5) showing the top level items and their arrangement

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment