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

rgerum / saenopy / 28380254720

29 Jun 2026 02:40PM UTC coverage: 61.061% (-0.07%) from 61.132%
28380254720

Pull #86

github

web-flow
Merge 22d9cb2d4 into 2b49ac9f7
Pull Request #86: [codex] Add macOS DMG installer artifact

15 of 76 new or added lines in 1 file covered. (19.74%)

23 existing lines in 2 files now uncovered.

8192 of 13416 relevant lines covered (61.06%)

0.61 hits per line

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

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

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

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

13

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

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

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

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

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

39

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

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

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

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

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

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

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

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

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

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

95
        self.select_tab(-1)
1✔
96

97
        for arg in sys.argv[1:]:
1✔
UNCOV
98
            if arg.endswith(".py"):
×
UNCOV
99
                self.do_load(arg)
×
100

101
    def update_console(self, open_script):
1✔
102
        if len(self.open_scripts) and open_script == self.open_scripts[self.open_scripts_index]:
1✔
103
            self.console.setText(open_script.console)
1✔
104

105
    def load(self):
1✔
106
        new_path = QtWidgets.QFileDialog.getOpenFileName(None, "Open Script", os.getcwd(), "Python File (*.py)")[0]
1✔
107
        if new_path:
1✔
108
            self.do_load(new_path)
1✔
109

110
    def do_load(self, open_script):
1✔
111
        # open a script
112
        self.open_scripts.append(OpenScript(self, open_script))
1✔
113
        # and add the tab
114
        self.tabs.addTab(self.open_scripts[-1].filename.name)
1✔
115
        # select the new tab
116
        self.tabs.setCurrentIndex(len(self.open_scripts)-1)
1✔
117

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

131
        self.editor.setDisabled(False)
1✔
132
        open_script = self.open_scripts[self.open_scripts_index]
1✔
133

134
        self.input_filename.setValue(open_script.filename)
1✔
135

136
        with QtCore.QSignalBlocker(self.editor):
1✔
137
            self.editor.setPlainText(open_script.code)
1✔
138
        self.editor.filename = str(open_script.filename)
1✔
139

140
        self.script_status_changed()
1✔
141

142
    def script_status_changed(self):
1✔
143
        if len(self.open_scripts) == 0:
1✔
UNCOV
144
            return
×
145
        open_script = self.open_scripts[self.open_scripts_index]
1✔
146
        if open_script.unsaved:
1✔
147
            self.tabs.setTabText(self.tabs.currentIndex(), open_script.filename.name + " *")
1✔
148
        else:
149
            self.tabs.setTabText(self.tabs.currentIndex(), open_script.filename.name)
1✔
150
        self.console.setHtml(open_script.console)
1✔
151

152
        self.button_run.setEnabled(open_script.can_run())
1✔
153
        self.button_stop.setEnabled(open_script.can_stop())
1✔
154

155
    def remove_tab(self, index):
1✔
156
        open_script = self.open_scripts.pop(index)
1✔
157
        open_script.stop()
1✔
158
        self.tabs.removeTab(index)
1✔
159

160
    def editor_text_changed(self):
1✔
161
        open_script = self.open_scripts[self.open_scripts_index]
1✔
162
        open_script.change_code(self.editor.toPlainText())
1✔
163
        self.script_status_changed()
1✔
164

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

169
        self.script_status_changed()
1✔
170

171
    def run(self):
1✔
172
        open_script = self.open_scripts[self.open_scripts_index]
1✔
173
        open_script.run()
1✔
174

175
        self.script_status_changed()
1✔
176

177
    def keyPressEvent(self, a0: QtGui.QKeyEvent) -> None:
1✔
178
        if a0.key() == QtCore.Qt.Key_F5:
1✔
179
            self.run()
1✔
180

181

182
if __name__ == '__main__':  # pragma: no cover
183
    app = QtWidgets.QApplication(sys.argv)
184
    if sys.platform.startswith('win'):
185
        import ctypes
186
        myappid = 'fabrylab.saenopy.master'  # arbitrary string
187
        ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
188
    print(sys.argv)
189
    window = MainWindowCode()
190
    window.setMinimumWidth(1600)
191
    window.setMinimumHeight(900)
192
    window.setWindowTitle("Saenopy Viewer")
193
    window.setWindowIcon(resource_icon("Icon.ico"))
194
    window.show()
195
    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