• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rgerum / saenopy / 30917102817

04 Aug 2026 02:05PM UTC coverage: 61.038% (+0.02%) from 61.015%
30917102817

push

github

rgerum
PROTOTYPE: cell image underlay and the settings you picked

arrow_span 0.085 and arrow_thickness 0.1 as the starting point, and a
maximum projection over the middle third of the stack laid under the left
panel, as in the static figure. Adds a control to toggle it.

Not for merging.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

8176 of 13395 relevant lines covered (61.04%)

0.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.55
/saenopy/gui/code/gui_code.py
1
import os
1✔
2
from qtpy import QtCore, QtWidgets, QtGui
1✔
3
import qtawesome as qta
1✔
4

5
from saenopy.gui.code.syntax import PythonHighlighter
1✔
6
from saenopy.gui.code.code_editor import CodeEditor
1✔
7
from saenopy.gui.code.script_file import OpenScript
1✔
8

9
from saenopy.gui.common import QtShortCuts
1✔
10
from saenopy.gui.common.resources import resource_icon
1✔
11

12

13
class Console(QtWidgets.QTextEdit):
1✔
14
    def __init__(self, parent, editor):
1✔
15
        super().__init__(parent)
1✔
16
        self.editor = editor
1✔
17

18
    def mousePressEvent(self, e):
1✔
19
        self.anchor = self.anchorAt(e.pos())
×
20
        if self.anchor:
×
21
            QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.PointingHandCursor)
×
22

23
    def mouseReleaseEvent(self, e):
1✔
24
        if self.anchor:
×
25
            print(self.anchor)
×
26
            if "#" in self.anchor:
×
27
                file, line = self.anchor.strip('"').split("#")
×
28

29
                print(file, self.editor.filename)
×
30
                if file == self.editor.filename:
×
31

32
                    cursor = QtGui.QTextCursor(self.editor.document().findBlockByLineNumber(int(line)-1))
×
33
                    self.editor.setTextCursor(cursor)
×
34
                    #QtWidgets.QDesktopServices.openUrl(QUrl(self.anchor))
35
                    QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.ArrowCursor)
×
36
            self.anchor = None
×
37

38

39
class MainWindowCode(QtWidgets.QWidget):
1✔
40
    console_update = QtCore.Signal(OpenScript)
1✔
41
    process_finished = QtCore.Signal()
1✔
42

43
    def __init__(self, parent=None):
1✔
44
        super().__init__(parent)
1✔
45

46
        # QSettings
47
        self.settings = QtCore.QSettings("Saenopy", "Saenopy")
1✔
48

49
        with QtShortCuts.QVBoxLayout(self):
1✔
50
            with QtShortCuts.QVBoxLayout():
1✔
51
                with QtShortCuts.QHBoxLayout():
1✔
52
                    self.button = QtShortCuts.QPushButton(None, "Open File", self.load, icon=qta.icon("fa5s.folder-open"))
1✔
53
                    self.tabs = QtWidgets.QTabBar().addToLayout()
1✔
54
                    self.tabs.setTabsClosable(True)
1✔
55
                    self.tabs.setMaximumHeight(32)
1✔
56
                    QtShortCuts.currentLayout().addStretch()
1✔
57
                    QtShortCuts.currentLayout().setSpacing(11)
1✔
58
                QtShortCuts.QHLine().addToLayout()
1✔
59
                QtShortCuts.currentLayout().setSpacing(0)
1✔
60

61
            with QtShortCuts.QHBoxLayout():
1✔
62
                self.input_filename = QtShortCuts.QInputString()
1✔
63
                self.input_filename.setDisabled(True)
1✔
64
                self.button_stop = QtShortCuts.QPushButton(None, "stop", self.stop, icon=qta.icon("fa5s.stop"))
1✔
65
                self.button_run = QtShortCuts.QPushButton(None, "run", self.run, icon=qta.icon("fa5s.play"))
1✔
66
            with QtShortCuts.QHBoxLayout():
1✔
67
                self.editor = CodeEditor()
1✔
68
                self.highlight = PythonHighlighter(self.editor.document())
1✔
69
                font = QtGui.QFont()
1✔
70
                font.setFamily('Courier')
1✔
71
                font.setFixedPitch(True)
1✔
72
                font.setPointSize(10)
1✔
73
                self.editor.setFont(font)
1✔
74

75
                self.console = Console(self, self.editor)#QtWidgets.QTextEdit()
1✔
76
                self.console.setStyleSheet("background-color: #1e1f22; color: #bcbec4")
1✔
77
                self.console.setReadOnly(True)
1✔
78
                self.console.setFont(font)
1✔
79

80
                self.splitter = QtWidgets.QSplitter().addToLayout()
1✔
81
                self.splitter.addWidget(self.editor)
1✔
82
                self.splitter.addWidget(self.console)
1✔
83

84
        self.console_update.connect(self.update_console)
1✔
85

86
        self.open_scripts = []
1✔
87
        self.open_scripts_index = -1
1✔
88

89
        self.editor.textChanged.connect(self.editor_text_changed)
1✔
90
        self.tabs.currentChanged.connect(self.select_tab)
1✔
91
        self.tabs.tabCloseRequested.connect(self.remove_tab)
1✔
92
        self.process_finished.connect(self.script_status_changed)
1✔
93

94
        self.select_tab(-1)
1✔
95

96
    def update_console(self, open_script):
1✔
97
        if len(self.open_scripts) and open_script == self.open_scripts[self.open_scripts_index]:
1✔
98
            self.console.setText(open_script.console)
×
99

100
    def load(self):
1✔
101
        new_path = QtWidgets.QFileDialog.getOpenFileName(None, "Open Script", os.getcwd(), "Python File (*.py)")[0]
1✔
102
        if new_path:
1✔
103
            self.do_load(new_path)
1✔
104

105
    def do_load(self, open_script):
1✔
106
        # open a script
107
        self.open_scripts.append(OpenScript(self, open_script))
1✔
108
        # and add the tab
109
        self.tabs.addTab(self.open_scripts[-1].filename.name)
1✔
110
        # select the new tab
111
        self.tabs.setCurrentIndex(len(self.open_scripts)-1)
1✔
112

113
    def select_tab(self, index=None):
1✔
114
        if index is not None:
1✔
115
            self.open_scripts_index = index
1✔
116
        if index == -1 or len(self.open_scripts) == 0:
1✔
117
            with QtCore.QSignalBlocker(self.editor):
1✔
118
                self.editor.setPlainText("")
1✔
119
                self.editor.setDisabled(True)
1✔
120
            self.console.setText("")
1✔
121
            self.input_filename.setValue("")
1✔
122
            self.button_run.setDisabled(True)
1✔
123
            self.button_stop.setDisabled(True)
1✔
124
            return
1✔
125

126
        self.editor.setDisabled(False)
1✔
127
        open_script = self.open_scripts[self.open_scripts_index]
1✔
128

129
        self.input_filename.setValue(open_script.filename)
1✔
130

131
        with QtCore.QSignalBlocker(self.editor):
1✔
132
            self.editor.setPlainText(open_script.code)
1✔
133
        self.editor.filename = str(open_script.filename)
1✔
134

135
        self.script_status_changed()
1✔
136

137
    def script_status_changed(self):
1✔
138
        if len(self.open_scripts) == 0:
1✔
139
            return
×
140
        open_script = self.open_scripts[self.open_scripts_index]
1✔
141
        if open_script.unsaved:
1✔
142
            self.tabs.setTabText(self.tabs.currentIndex(), open_script.filename.name + " *")
1✔
143
        else:
144
            self.tabs.setTabText(self.tabs.currentIndex(), open_script.filename.name)
1✔
145
        self.console.setHtml(open_script.console)
1✔
146

147
        self.button_run.setEnabled(open_script.can_run())
1✔
148
        self.button_stop.setEnabled(open_script.can_stop())
1✔
149

150
    def remove_tab(self, index):
1✔
151
        open_script = self.open_scripts.pop(index)
1✔
152
        open_script.stop()
1✔
153
        self.tabs.removeTab(index)
1✔
154

155
    def editor_text_changed(self):
1✔
156
        open_script = self.open_scripts[self.open_scripts_index]
1✔
157
        open_script.change_code(self.editor.toPlainText())
1✔
158
        self.script_status_changed()
1✔
159

160
    def stop(self):
1✔
161
        open_script = self.open_scripts[self.open_scripts_index]
1✔
162
        open_script.stop()
1✔
163

164
        self.script_status_changed()
1✔
165

166
    def run(self):
1✔
167
        open_script = self.open_scripts[self.open_scripts_index]
1✔
168
        open_script.run()
1✔
169

170
        self.script_status_changed()
1✔
171

172
    def keyPressEvent(self, a0: QtGui.QKeyEvent) -> None:
1✔
173
        if a0.key() == QtCore.Qt.Key_F5:
1✔
174
            self.run()
1✔
175

176

177
if __name__ == '__main__':  # pragma: no cover
178
    app = QtWidgets.QApplication(sys.argv)
179
    if sys.platform.startswith('win'):
180
        import ctypes
181
        myappid = 'fabrylab.saenopy.master'  # arbitrary string
182
        ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
183
    print(sys.argv)
184
    window = MainWindowCode()
185
    window.setMinimumWidth(1600)
186
    window.setMinimumHeight(900)
187
    window.setWindowTitle("Saenopy Viewer")
188
    window.setWindowIcon(resource_icon("Icon.ico"))
189
    window.show()
190
    sys.exit(app.exec_())
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc