Skip to content

Commit 29f7656

Browse files
🎉 Add feature: multiple windows
🎉 Add feature: multiple windows
2 parents c8bb11d + c9ac7f3 commit 29f7656

File tree

8 files changed

+879
-161
lines changed

8 files changed

+879
-161
lines changed

main.py

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -33,37 +33,35 @@
3333
app.setStyle('Fusion')
3434

3535
wnd = OCBWindow()
36-
scene = wnd.ocb_widget.scene
36+
# if hasattr(wnd, 'ocb_widget'):
37+
# scene = wnd.ocb_widget.scene
3738

38-
test_block = OCBBlock(title="Other kind of block")
39-
scene.addItem(test_block)
40-
test_block.setPos(-250, 150)
39+
# test_block = OCBBlock(title="Other kind of block")
40+
# scene.addItem(test_block)
41+
# test_block.setPos(-250, 150)
4142

42-
test_block_2 = OCBCodeBlock(title="Dataset", source=SOURCE_TEST)
43-
for _ in range(2):
44-
test_block_2.add_socket(OCBSocket(test_block_2, socket_type='input'))
45-
for _ in range(1):
46-
test_block_2.add_socket(OCBSocket(test_block_2, socket_type='output'))
47-
test_block_2.setPos(-350, -100)
48-
scene.addItem(test_block_2)
43+
# test_block_2 = OCBCodeBlock(title="Dataset", source=SOURCE_TEST)
44+
# for _ in range(2):
45+
# test_block_2.add_socket(OCBSocket(test_block_2, socket_type='input'))
46+
# for _ in range(1):
47+
# test_block_2.add_socket(OCBSocket(test_block_2, socket_type='output'))
48+
# test_block_2.setPos(-350, -100)
49+
# scene.addItem(test_block_2)
4950

50-
test_block_3 = OCBCodeBlock(title="Mon IA (par blocks ?)", source=SOURCE_TEST_2)
51-
for _ in range(2):
52-
test_block_3.add_socket(OCBSocket(test_block_3, socket_type='input'))
53-
for _ in range(1):
54-
test_block_3.add_socket(OCBSocket(test_block_3, socket_type='output'))
55-
test_block_3.setPos(0, -100)
56-
scene.addItem(test_block_3)
51+
# test_block_3 = OCBCodeBlock(title="Mon IA (par blocks ?)", source=SOURCE_TEST_2)
52+
# for _ in range(2):
53+
# test_block_3.add_socket(OCBSocket(test_block_3, socket_type='input'))
54+
# for _ in range(1):
55+
# test_block_3.add_socket(OCBSocket(test_block_3, socket_type='output'))
56+
# test_block_3.setPos(0, -100)
57+
# scene.addItem(test_block_3)
5758

58-
# for i in range(3):
59-
# edge = OCBEdge(
60-
# source_socket=test_block_3.sockets_out[0],
61-
# destination_socket=test_block_2.sockets_in[i]
62-
# )
63-
# scene.addItem(edge)
64-
65-
scene.save('scene.ipyg')
66-
scene.load('scene.ipyg')
59+
# # for i in range(3):
60+
# # edge = OCBEdge(
61+
# # source_socket=test_block_3.sockets_out[0],
62+
# # destination_socket=test_block_2.sockets_in[i]
63+
# # )
64+
# # scene.addItem(edge)
6765

6866
wnd.show()
6967
sys.exit(app.exec_())
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# OpenCodeBlock an open-source tool for modular visual programing in python
2+
# Copyright (C) 2021 Mathïs FEDERICO <https://www.gnu.org/licenses/>
3+
4+
""" Module for the OCB qss and styles. """
5+
6+
from typing import List
7+
8+
from PyQt5.QtCore import QFile
9+
from PyQt5.QtWidgets import QApplication
10+
11+
from opencodeblocks.graphics.qss import dark_resources
12+
13+
def loadStylesheets(filenames:List[str]):
14+
styles = ''
15+
for filename in filenames:
16+
file = QFile(filename)
17+
file.open(QFile.ReadOnly | QFile.Text)
18+
stylesheet = file.readAll()
19+
styles += "\n" + str(stylesheet, encoding='utf-8')
20+
QApplication.instance().setStyleSheet(styles)

opencodeblocks/graphics/qss/dark_resources.py

Lines changed: 509 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
QDMNodeContentWidget {
2+
background: transparent;
3+
}
4+
QDMNodeContentWidget QFrame {
5+
background: transparent;
6+
}
7+
QDMNodeContentWidget QTextEdit,
8+
QDMNodeContentWidget QLineEdit {
9+
background: #666;
10+
color: #fff;
11+
}
12+
QDMNodeContentWidget QLabel {
13+
color: #e0e0e0;
14+
min-width: 150px;
15+
max-width: 150px;
16+
min-height: 45px;
17+
max-height: 45px;
18+
margin-left: 10px;
19+
margin-top: 5px;
20+
font-size: 28px;
21+
}
22+
QDMNodeContentWidget QLineEdit#calc_node_input {
23+
width: 140px;
24+
height: 36px;
25+
margin-top: 5px;
26+
margin-left: 5px;
27+
font-size: 28px;
28+
}
29+
QGraphicsView {
30+
selection-background-color: #fff;
31+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
QFrame,QDialog,QMainWindow{background:#474747}QSplitter,QMainWindow::separator{background:#474747}QStatusBar{background:#474747;color:#ccc}QTabWidget{border:0}QTabBar{background:#474747;color:#ccc}QMdiArea QTabBar,QMdiArea QTabWidget,QMdiArea QTabWidget::pane,QMdiArea QTabWidget::tab-bar,QMdiArea QTabBar::tab{height:17px}QMdiArea QTabBar::tab:top:!selected,QMdiArea QTabBar::tab:top:selected,QMdiArea QTabBar::tab:top:!selected:hover{border-top-left-radius:4px;border-top-right-radius:4px;padding:2px 8px;padding-top:0;padding-bottom:3px;min-width:8ex;border:1px solid #333;border-bottom:0}QMdiArea QTabBar::tab:top:!selected,QMdiArea QTabBar::tab:top:!selected:hover{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #6d6d6d,stop : .1 #474747,stop : .89 #3f3f3f,stop : 1 #3f3f3f)}QMdiArea QTabBar::tab:top:selected{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #878787,stop : .1 #545454,stop : .89 #474747,stop : 1 #474747)}QMdiArea QTabBar::tab:top:!selected:hover{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #727272,stop : .1 #4c4c4c,stop : .89 #444,stop : 1 #444)}QMdiArea QTabBar QToolButton{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #878787,stop : .1 #616161,stop : .89 #4f4f4f,stop : 1 #4f4f4f);border:1px solid #333;border-radius:0}QMdiArea QTabBar QToolButton::left-arrow{image:url(":icons/small_arrow_left-light.png")}QMdiArea QTabBar QToolButton::right-arrow{image:url(":icons/small_arrow_right-light.png")}QMdiArea QTabBar::close-button:selected{image:url(":icons/tab_close_btn.png");subcontrol-origin:border;subcontrol-position:right bottom}QMdiArea QTabBar::close-button:!selected{image:url(":icons/tab_close_nonselected_btn.png")}QMdiSubWindow{border-style:solid;background:#616161}QTabBar::tab:selected,QTabBar::tab:hover{color:#eee}QDockWidget{color:#ddd;font-weight:bold;titlebar-close-icon:url(":icons/docktitle-close-btn-light.png");titlebar-normal-icon:url(":icons/docktitle-normal-btn-light.png")}QDockWidget::title{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #3b3b3b,stop : 1 #2e2e2e);padding-top:4px;padding-right:22px;font-weight:bold}QDockWidget::close-button,QDockWidget::float-button{subcontrol-position:top right;subcontrol-origin:margin;text-align:center;icon-size:16px;width:14px;position:absolute;top:0;bottom:0;left:0;right:4px}QDockWidget::close-button{right:4px}QDockWidget::float-button{right:18px}QMenuBar{background:#474747}QMenuBar::item{spacing:3px;padding:3px 5px;color:#eee;background:transparent}QMenuBar::item:selected,QMenuBar::item:pressed{background:#4f9eee}QMenu{background:#474747;border:1px solid #2e2e2e}QMenu::item{background:#474747;color:#eee}QMenu::item:selected{background:#616161}QMenu::active{background:#616161;color:#eee}QMenu::separator{height:1px;background:#2e2e2e}QMenu::disabled,QMenu::item:disabled{color:#6e6e6e}QListView{background-color:#555;alternate-background-color:#434343}QListView::item{height:22px;color:#e6e6e6}QListView::item:hover{background:#6e6e6e}QListView::item::active:hover{color:#fff}QListView::item:selected,QListView::item::active:selected{color:#fff;background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #4f9eee,stop : 1 #2084ea);border:0}QPushButton{color:#e6e6e6;background:#555;border-color:#141414}QLabel{color:#e6e6e6}QLineEdit,QTextEdit{color:#e6e6e6;background:#5a5a5a}QLineEdit{border:1px solid #3a3a3a;border-radius:2px;padding:1px 2px}QDMNodeContentWidget{background:transparent;}QDMNodeContentWidget QFrame{background:transparent}QDMNodeContentWidget QTextEdit{background:#666}QDMNodeContentWidget QLabel{color:#e0e0e0}QGraphicsView{selection-background-color:#fff}

opencodeblocks/graphics/scene/scene.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,9 @@ def has_been_modified(self):
5454
return self._has_been_modified
5555
@has_been_modified.setter
5656
def has_been_modified(self, value:bool):
57-
if not self._has_been_modified and value:
58-
self._has_been_modified = value
59-
60-
# Call listeners
61-
for callback in self._has_been_modified_listeners:
62-
callback()
63-
6457
self._has_been_modified = value
58+
for callback in self._has_been_modified_listeners:
59+
callback()
6560

6661
def addHasBeenModifiedListener(self, callback:FunctionType):
6762
""" Add a callback that will trigger when the scene has been modified. """

opencodeblocks/graphics/widget.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33

44
""" Module for the OCB Widget """
55

6+
import os
7+
68
from PyQt5.QtWidgets import QVBoxLayout, QWidget
9+
from PyQt5.QtCore import Qt
710

811
from opencodeblocks.graphics.scene import OCBScene
912
from opencodeblocks.graphics.view import OCBView
@@ -14,14 +17,48 @@ class OCBWidget(QWidget):
1417

1518
def __init__(self, parent=None):
1619
super().__init__(parent)
20+
self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose)
1721

1822
self.layout = QVBoxLayout()
1923
self.layout.setContentsMargins(0, 0, 0, 0)
2024
self.setLayout(self.layout)
2125

2226
# Graphics Scene
2327
self.scene = OCBScene()
28+
self.scene.addHasBeenModifiedListener(self.updateTitle)
2429

2530
# Graphics View
2631
self.view = OCBView(self.scene)
2732
self.layout.addWidget(self.view)
33+
34+
self.savepath = None
35+
36+
def updateTitle(self):
37+
""" Update the window title. """
38+
if self.savepath is None:
39+
title = 'New Graph'
40+
else:
41+
title = os.path.basename(self.savepath)
42+
if self.isModified():
43+
title += "*"
44+
self.setWindowTitle(title)
45+
46+
def isModified(self) -> bool:
47+
""" Return True if the scene has been modified, False otherwise. """
48+
return self.scene.has_been_modified
49+
50+
@property
51+
def savepath(self):
52+
""" Current cached file save path. Update window title when set."""
53+
return self._savepath
54+
@savepath.setter
55+
def savepath(self, value:str):
56+
self._savepath = value
57+
self.updateTitle()
58+
59+
def save(self):
60+
self.scene.save(self.savepath)
61+
62+
def load(self, filepath:str):
63+
self.scene.load(filepath)
64+
self.savepath = filepath

0 commit comments

Comments
 (0)