boris-behav-obs 8.16.5__py3-none-any.whl → 9.7.12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- boris/__init__.py +1 -1
- boris/__main__.py +1 -1
- boris/about.py +28 -40
- boris/add_modifier.py +88 -80
- boris/add_modifier_ui.py +266 -144
- boris/advanced_event_filtering.py +23 -29
- boris/analysis_plugins/__init__.py +0 -0
- boris/analysis_plugins/_export_to_feral.py +225 -0
- boris/analysis_plugins/_latency.py +59 -0
- boris/analysis_plugins/irr_cohen_kappa.py +109 -0
- boris/analysis_plugins/irr_cohen_kappa_with_modifiers.py +112 -0
- boris/analysis_plugins/irr_weighted_cohen_kappa.py +157 -0
- boris/analysis_plugins/irr_weighted_cohen_kappa_with_modifiers.py +162 -0
- boris/analysis_plugins/list_of_dataframe_columns.py +22 -0
- boris/analysis_plugins/number_of_occurences.py +22 -0
- boris/analysis_plugins/number_of_occurences_by_independent_variable.py +54 -0
- boris/analysis_plugins/time_budget.py +61 -0
- boris/behav_coding_map_creator.py +235 -236
- boris/behavior_binary_table.py +33 -50
- boris/behaviors_coding_map.py +17 -18
- boris/boris_cli.py +6 -25
- boris/cmd_arguments.py +12 -1
- boris/coding_pad.py +19 -36
- boris/config.py +109 -50
- boris/config_file.py +58 -67
- boris/connections.py +105 -58
- boris/converters.py +13 -37
- boris/converters_ui.py +187 -110
- boris/cooccurence.py +250 -0
- boris/core.py +2174 -1303
- boris/core_qrc.py +15892 -10829
- boris/core_ui.py +941 -806
- boris/db_functions.py +17 -42
- boris/dev.py +27 -7
- boris/dialog.py +461 -242
- boris/duration_widget.py +9 -14
- boris/edit_event.py +61 -31
- boris/edit_event_ui.py +208 -97
- boris/event_operations.py +405 -281
- boris/events_cursor.py +25 -17
- boris/events_snapshots.py +36 -82
- boris/exclusion_matrix.py +4 -9
- boris/export_events.py +180 -203
- boris/export_observation.py +60 -73
- boris/external_processes.py +123 -98
- boris/geometric_measurement.py +427 -218
- boris/gui_utilities.py +91 -14
- boris/image_overlay.py +4 -4
- boris/import_observations.py +190 -98
- boris/ipc_mpv.py +325 -0
- boris/irr.py +20 -57
- boris/latency.py +31 -24
- boris/measurement_widget.py +14 -18
- boris/media_file.py +17 -19
- boris/menu_options.py +16 -6
- boris/modifier_coding_map_creator.py +1013 -0
- boris/modifiers_coding_map.py +7 -9
- boris/mpv2.py +128 -35
- boris/observation.py +501 -211
- boris/observation_operations.py +1037 -393
- boris/observation_ui.py +573 -363
- boris/observations_list.py +51 -58
- boris/otx_parser.py +74 -68
- boris/param_panel.py +45 -59
- boris/param_panel_ui.py +254 -138
- boris/player_dock_widget.py +91 -56
- boris/plot_data_module.py +20 -53
- boris/plot_events.py +56 -153
- boris/plot_events_rt.py +16 -30
- boris/plot_spectrogram_rt.py +83 -56
- boris/plot_waveform_rt.py +27 -49
- boris/plugins.py +468 -0
- boris/portion/__init__.py +18 -8
- boris/portion/const.py +35 -18
- boris/portion/dict.py +5 -5
- boris/portion/func.py +2 -2
- boris/portion/interval.py +21 -41
- boris/portion/io.py +41 -32
- boris/preferences.py +307 -123
- boris/preferences_ui.py +686 -227
- boris/project.py +294 -271
- boris/project_functions.py +626 -537
- boris/project_import_export.py +204 -213
- boris/project_ui.py +673 -441
- boris/qrc_boris.py +6 -3
- boris/qrc_boris5.py +6 -3
- boris/select_modifiers.py +62 -90
- boris/select_observations.py +19 -197
- boris/select_subj_behav.py +67 -39
- boris/state_events.py +51 -33
- boris/subjects_pad.py +7 -9
- boris/synthetic_time_budget.py +42 -26
- boris/time_budget_functions.py +169 -169
- boris/time_budget_widget.py +77 -89
- boris/transitions.py +41 -41
- boris/utilities.py +594 -226
- boris/version.py +3 -3
- boris/video_equalizer.py +16 -14
- boris/video_equalizer_ui.py +199 -130
- boris/video_operations.py +86 -28
- boris/view_df.py +104 -0
- boris/view_df_ui.py +75 -0
- boris/write_event.py +240 -136
- boris_behav_obs-9.7.12.dist-info/METADATA +139 -0
- boris_behav_obs-9.7.12.dist-info/RECORD +110 -0
- {boris_behav_obs-8.16.5.dist-info → boris_behav_obs-9.7.12.dist-info}/WHEEL +1 -1
- boris_behav_obs-9.7.12.dist-info/entry_points.txt +2 -0
- boris/README.TXT +0 -22
- boris/add_modifier.ui +0 -323
- boris/converters.ui +0 -289
- boris/core.qrc +0 -37
- boris/core.ui +0 -1571
- boris/edit_event.ui +0 -233
- boris/icons/logo_eye.ico +0 -0
- boris/map_creator.py +0 -982
- boris/observation.ui +0 -814
- boris/param_panel.ui +0 -379
- boris/preferences.ui +0 -537
- boris/project.ui +0 -1074
- boris/vlc_local.py +0 -90
- boris_behav_obs-8.16.5.dist-info/LICENSE.TXT +0 -674
- boris_behav_obs-8.16.5.dist-info/METADATA +0 -134
- boris_behav_obs-8.16.5.dist-info/RECORD +0 -107
- boris_behav_obs-8.16.5.dist-info/entry_points.txt +0 -2
- {boris → boris_behav_obs-9.7.12.dist-info/licenses}/LICENSE.TXT +0 -0
- {boris_behav_obs-8.16.5.dist-info → boris_behav_obs-9.7.12.dist-info}/top_level.txt +0 -0
boris/map_creator.py
DELETED
|
@@ -1,982 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
BORIS
|
|
3
|
-
Behavioral Observation Research Interactive Software
|
|
4
|
-
Copyright 2012-2023 Olivier Friard
|
|
5
|
-
|
|
6
|
-
This file is part of BORIS.
|
|
7
|
-
|
|
8
|
-
BORIS is free software; you can redistribute it and/or modify
|
|
9
|
-
it under the terms of the GNU General Public License as published by
|
|
10
|
-
the Free Software Foundation; either version 3 of the License, or
|
|
11
|
-
any later version.
|
|
12
|
-
|
|
13
|
-
BORIS is distributed in the hope that it will be useful,
|
|
14
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
-
GNU General Public License for more details.
|
|
17
|
-
|
|
18
|
-
You should have received a copy of the GNU General Public License
|
|
19
|
-
along with this program; if not see <http://www.gnu.org/licenses/>.
|
|
20
|
-
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
import binascii
|
|
24
|
-
import json
|
|
25
|
-
import os
|
|
26
|
-
|
|
27
|
-
from PyQt5.QtCore import (
|
|
28
|
-
Qt,
|
|
29
|
-
pyqtSignal,
|
|
30
|
-
QPoint,
|
|
31
|
-
QByteArray,
|
|
32
|
-
QBuffer,
|
|
33
|
-
QIODevice,
|
|
34
|
-
QLineF,
|
|
35
|
-
)
|
|
36
|
-
from PyQt5.QtGui import (
|
|
37
|
-
QColor,
|
|
38
|
-
QBrush,
|
|
39
|
-
QMouseEvent,
|
|
40
|
-
QPixmap,
|
|
41
|
-
QIcon,
|
|
42
|
-
QPen,
|
|
43
|
-
QPolygon,
|
|
44
|
-
QPolygonF,
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
from PyQt5.QtWidgets import (
|
|
48
|
-
QGraphicsPolygonItem,
|
|
49
|
-
QGraphicsEllipseItem,
|
|
50
|
-
QGraphicsPixmapItem,
|
|
51
|
-
QGraphicsLineItem,
|
|
52
|
-
QAction,
|
|
53
|
-
QMainWindow,
|
|
54
|
-
QGraphicsView,
|
|
55
|
-
QPushButton,
|
|
56
|
-
QLabel,
|
|
57
|
-
QHBoxLayout,
|
|
58
|
-
QLineEdit,
|
|
59
|
-
QSlider,
|
|
60
|
-
QGraphicsScene,
|
|
61
|
-
QWidget,
|
|
62
|
-
QColorDialog,
|
|
63
|
-
QVBoxLayout,
|
|
64
|
-
QMessageBox,
|
|
65
|
-
QInputDialog,
|
|
66
|
-
QFileDialog,
|
|
67
|
-
QApplication,
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
from . import config as cfg
|
|
71
|
-
from . import dialog
|
|
72
|
-
from . import utilities as util
|
|
73
|
-
|
|
74
|
-
designColor = QColor(255, 0, 0, 128) # red opacity: 50%
|
|
75
|
-
penWidth = 0
|
|
76
|
-
penStyle = Qt.NoPen
|
|
77
|
-
selectedBrush = QBrush()
|
|
78
|
-
selectedBrush.setStyle(Qt.SolidPattern)
|
|
79
|
-
selectedBrush.setColor(QColor(255, 255, 0, 255))
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
class ModifiersMapCreatorWindow(QMainWindow):
|
|
83
|
-
|
|
84
|
-
closed = pyqtSignal()
|
|
85
|
-
|
|
86
|
-
class View(QGraphicsView):
|
|
87
|
-
"""
|
|
88
|
-
class for handling mousepress event in QGraphicsView
|
|
89
|
-
"""
|
|
90
|
-
|
|
91
|
-
mousePress = pyqtSignal(QMouseEvent)
|
|
92
|
-
|
|
93
|
-
def mousePressEvent(self, event):
|
|
94
|
-
self.mousePress.emit(event)
|
|
95
|
-
|
|
96
|
-
_start = 0
|
|
97
|
-
elList, points = [], []
|
|
98
|
-
|
|
99
|
-
def __init__(self, parent):
|
|
100
|
-
QGraphicsView.__init__(self, parent)
|
|
101
|
-
self.setBackgroundBrush(QColor(128, 128, 128))
|
|
102
|
-
self.setScene(QGraphicsScene(self))
|
|
103
|
-
self.scene().update()
|
|
104
|
-
|
|
105
|
-
bitmapFileName, mapName, fileName = "", "", ""
|
|
106
|
-
flagNewArea, flagMapChanged = False, False
|
|
107
|
-
areasList, polygonsList2 = {}, {}
|
|
108
|
-
areaColor = QColor("lime")
|
|
109
|
-
|
|
110
|
-
def __init__(self):
|
|
111
|
-
|
|
112
|
-
super(ModifiersMapCreatorWindow, self).__init__()
|
|
113
|
-
|
|
114
|
-
self.pixmap = QPixmap()
|
|
115
|
-
self.closedPolygon = None
|
|
116
|
-
self.selectedPolygon = None
|
|
117
|
-
|
|
118
|
-
self.setWindowTitle("BORIS - Modifiers map creator")
|
|
119
|
-
|
|
120
|
-
self.newMapAction = QAction(QIcon(), "&New modifiers map", self)
|
|
121
|
-
self.newMapAction.setShortcut("Ctrl+N")
|
|
122
|
-
self.newMapAction.setStatusTip("Create a new modifiers map")
|
|
123
|
-
self.newMapAction.triggered.connect(self.newMap)
|
|
124
|
-
|
|
125
|
-
self.openMapAction = QAction(QIcon(), "&Open modifiers map", self)
|
|
126
|
-
self.openMapAction.setShortcut("Ctrl+O")
|
|
127
|
-
self.openMapAction.setStatusTip("Open a modifiers map")
|
|
128
|
-
self.openMapAction.triggered.connect(self.openMap)
|
|
129
|
-
|
|
130
|
-
self.saveMapAction = QAction(QIcon(), "&Save modifiers map", self)
|
|
131
|
-
self.saveMapAction.setShortcut("Ctrl+S")
|
|
132
|
-
self.saveMapAction.setStatusTip("Save modifiers map")
|
|
133
|
-
self.saveMapAction.setEnabled(False)
|
|
134
|
-
self.saveMapAction.triggered.connect(self.saveMap_clicked)
|
|
135
|
-
|
|
136
|
-
self.saveAsMapAction = QAction(QIcon(), "Save modifiers map as", self)
|
|
137
|
-
self.saveAsMapAction.setStatusTip("Save modifiers map as")
|
|
138
|
-
self.saveAsMapAction.setEnabled(False)
|
|
139
|
-
self.saveAsMapAction.triggered.connect(self.saveAsMap_clicked)
|
|
140
|
-
|
|
141
|
-
self.mapNameAction = QAction(QIcon(), "&Modifiers map name", self)
|
|
142
|
-
self.mapNameAction.setShortcut("Ctrl+M")
|
|
143
|
-
self.mapNameAction.setStatusTip("Change modifiers map name")
|
|
144
|
-
self.mapNameAction.setEnabled(False)
|
|
145
|
-
self.mapNameAction.triggered.connect(self.mapName_clicked)
|
|
146
|
-
|
|
147
|
-
self.exitAction = QAction(QIcon(), "&Close", self)
|
|
148
|
-
self.exitAction.setStatusTip("Close modifiers map creator")
|
|
149
|
-
self.exitAction.triggered.connect(self.close)
|
|
150
|
-
|
|
151
|
-
menubar = self.menuBar()
|
|
152
|
-
fileMenu = menubar.addMenu("&Modifiers Map creator")
|
|
153
|
-
fileMenu.addAction(self.newMapAction)
|
|
154
|
-
fileMenu.addAction(self.openMapAction)
|
|
155
|
-
fileMenu.addAction(self.saveMapAction)
|
|
156
|
-
fileMenu.addAction(self.saveAsMapAction)
|
|
157
|
-
fileMenu.addSeparator()
|
|
158
|
-
fileMenu.addAction(self.mapNameAction)
|
|
159
|
-
fileMenu.addSeparator()
|
|
160
|
-
fileMenu.addAction(self.exitAction)
|
|
161
|
-
|
|
162
|
-
self.view = self.View(self)
|
|
163
|
-
self.view.mousePress.connect(self.viewMousePressEvent)
|
|
164
|
-
|
|
165
|
-
self.btLoad = QPushButton("Load bitmap", self)
|
|
166
|
-
self.btLoad.clicked.connect(self.loadBitmap)
|
|
167
|
-
self.btLoad.setVisible(False)
|
|
168
|
-
|
|
169
|
-
self.btNewArea = QPushButton("New modifier", self)
|
|
170
|
-
self.btNewArea.clicked.connect(self.newArea)
|
|
171
|
-
self.btNewArea.setVisible(False)
|
|
172
|
-
|
|
173
|
-
self.hlayout = QHBoxLayout()
|
|
174
|
-
|
|
175
|
-
self.lb = QLabel("Modifier")
|
|
176
|
-
self.lb.setVisible(False)
|
|
177
|
-
self.hlayout.addWidget(self.lb)
|
|
178
|
-
|
|
179
|
-
self.leAreaCode = QLineEdit(self)
|
|
180
|
-
self.leAreaCode.setVisible(False)
|
|
181
|
-
self.hlayout.addWidget(self.leAreaCode)
|
|
182
|
-
|
|
183
|
-
self.btColor = QPushButton()
|
|
184
|
-
self.btColor.clicked.connect(self.chooseColor)
|
|
185
|
-
self.btColor.setVisible(False)
|
|
186
|
-
self.btColor.setStyleSheet(
|
|
187
|
-
"QWidget {{background-color:{}}}".format(self.areaColor.name())
|
|
188
|
-
)
|
|
189
|
-
self.hlayout.addWidget(self.btColor)
|
|
190
|
-
|
|
191
|
-
self.slAlpha = QSlider(Qt.Horizontal)
|
|
192
|
-
self.slAlpha.setRange(20, 100)
|
|
193
|
-
self.slAlpha.setValue(50)
|
|
194
|
-
self.slAlpha.valueChanged.connect(self.slAlpha_changed)
|
|
195
|
-
self.slAlpha.setVisible(False)
|
|
196
|
-
self.hlayout.addWidget(self.slAlpha)
|
|
197
|
-
|
|
198
|
-
self.slAlpha_changed(50)
|
|
199
|
-
"""
|
|
200
|
-
self.btCancelMap = QPushButton("Cancel modifiers map", self)
|
|
201
|
-
self.btCancelMap.clicked.connect(self.cancelMap)
|
|
202
|
-
self.btCancelMap.setVisible(False)
|
|
203
|
-
"""
|
|
204
|
-
|
|
205
|
-
layout = QVBoxLayout()
|
|
206
|
-
layout.addWidget(self.view)
|
|
207
|
-
layout.addWidget(self.btLoad)
|
|
208
|
-
|
|
209
|
-
hlayout2 = QHBoxLayout()
|
|
210
|
-
hlayout2.addWidget(self.btNewArea)
|
|
211
|
-
|
|
212
|
-
self.btSaveArea = QPushButton("Save modifier", self)
|
|
213
|
-
self.btSaveArea.clicked.connect(self.saveArea)
|
|
214
|
-
self.btSaveArea.setVisible(False)
|
|
215
|
-
hlayout2.addWidget(self.btSaveArea)
|
|
216
|
-
|
|
217
|
-
self.btCancelAreaCreation = QPushButton("Cancel new modifier", self)
|
|
218
|
-
self.btCancelAreaCreation.clicked.connect(self.cancelAreaCreation)
|
|
219
|
-
self.btCancelAreaCreation.setVisible(False)
|
|
220
|
-
hlayout2.addWidget(self.btCancelAreaCreation)
|
|
221
|
-
|
|
222
|
-
self.btDeleteArea = QPushButton("Delete selected modifier", self)
|
|
223
|
-
self.btDeleteArea.clicked.connect(self.deleteArea)
|
|
224
|
-
self.btDeleteArea.setVisible(True)
|
|
225
|
-
self.btDeleteArea.setEnabled(False)
|
|
226
|
-
hlayout2.addWidget(self.btDeleteArea)
|
|
227
|
-
|
|
228
|
-
layout.addLayout(hlayout2)
|
|
229
|
-
layout.addLayout(self.hlayout)
|
|
230
|
-
"""layout.addWidget(self.btCancelMap)"""
|
|
231
|
-
|
|
232
|
-
main_widget = QWidget(self)
|
|
233
|
-
main_widget.setLayout(layout)
|
|
234
|
-
self.setCentralWidget(main_widget)
|
|
235
|
-
|
|
236
|
-
self.statusBar().showMessage("")
|
|
237
|
-
|
|
238
|
-
def slAlpha_changed(self, val):
|
|
239
|
-
"""
|
|
240
|
-
opacity slider value changed
|
|
241
|
-
"""
|
|
242
|
-
|
|
243
|
-
self.btColor.setText("Opacity: {} %".format(val))
|
|
244
|
-
self.areaColor.setAlpha(int(val / 100 * 255))
|
|
245
|
-
|
|
246
|
-
if self.selectedPolygon:
|
|
247
|
-
self.selectedPolygon.setBrush(self.areaColor)
|
|
248
|
-
self.areasList[self.leAreaCode.text()]["color"] = self.areaColor.rgba()
|
|
249
|
-
|
|
250
|
-
if self.closedPolygon:
|
|
251
|
-
self.closedPolygon.setBrush(self.areaColor)
|
|
252
|
-
|
|
253
|
-
def chooseColor(self):
|
|
254
|
-
"""
|
|
255
|
-
area color button clicked
|
|
256
|
-
"""
|
|
257
|
-
cd = QColorDialog()
|
|
258
|
-
cd.setWindowFlags(Qt.WindowStaysOnTopHint)
|
|
259
|
-
cd.setOptions(QColorDialog.ShowAlphaChannel | QColorDialog.DontUseNativeDialog)
|
|
260
|
-
|
|
261
|
-
if cd.exec_():
|
|
262
|
-
self.areaColor = cd.currentColor()
|
|
263
|
-
self.btColor.setStyleSheet(
|
|
264
|
-
f"QWidget {{background-color:{self.areaColor.name()}}}"
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
if self.selectedPolygon:
|
|
268
|
-
self.selectedPolygon.setBrush(self.areaColor)
|
|
269
|
-
self.areasList[self.leAreaCode.text()]["color"] = self.areaColor.rgba()
|
|
270
|
-
|
|
271
|
-
if self.closedPolygon:
|
|
272
|
-
self.closedPolygon.setBrush(self.areaColor)
|
|
273
|
-
|
|
274
|
-
def closeEvent(self, event):
|
|
275
|
-
|
|
276
|
-
if self.flagMapChanged:
|
|
277
|
-
|
|
278
|
-
response = dialog.MessageDialog(
|
|
279
|
-
"BORIS - Modifiers map creator",
|
|
280
|
-
"What to do about the current unsaved modifiers coding map?",
|
|
281
|
-
["Save", "Discard", "Cancel"],
|
|
282
|
-
)
|
|
283
|
-
|
|
284
|
-
if response == "Save":
|
|
285
|
-
if not self.saveMap_clicked():
|
|
286
|
-
event.ignore()
|
|
287
|
-
|
|
288
|
-
if response == "Cancel":
|
|
289
|
-
event.ignore()
|
|
290
|
-
return
|
|
291
|
-
|
|
292
|
-
self.closed.emit()
|
|
293
|
-
event.accept()
|
|
294
|
-
|
|
295
|
-
def viewMousePressEvent(self, event):
|
|
296
|
-
"""
|
|
297
|
-
check if area selected with mouse
|
|
298
|
-
"""
|
|
299
|
-
|
|
300
|
-
if not self.bitmapFileName:
|
|
301
|
-
return
|
|
302
|
-
|
|
303
|
-
self.btDeleteArea.setEnabled(False)
|
|
304
|
-
|
|
305
|
-
test = self.view.mapToScene(event.pos()).toPoint()
|
|
306
|
-
|
|
307
|
-
if (
|
|
308
|
-
test.x() < 0
|
|
309
|
-
or test.y() < 0
|
|
310
|
-
or test.x() > self.pixmap.size().width()
|
|
311
|
-
or test.y() > self.pixmap.size().height()
|
|
312
|
-
):
|
|
313
|
-
return
|
|
314
|
-
|
|
315
|
-
if not self.flagNewArea: # test clicked point for areas
|
|
316
|
-
txt = ""
|
|
317
|
-
|
|
318
|
-
# reset selected polygon to default pen
|
|
319
|
-
if self.selectedPolygon:
|
|
320
|
-
self.selectedPolygon.setPen(
|
|
321
|
-
QPen(designColor, penWidth, penStyle, Qt.RoundCap, Qt.RoundJoin)
|
|
322
|
-
)
|
|
323
|
-
self.selectedPolygon = None
|
|
324
|
-
self.selectedPolygonMemBrush = None
|
|
325
|
-
|
|
326
|
-
for areaCode in self.polygonsList2:
|
|
327
|
-
|
|
328
|
-
if self.polygonsList2[areaCode].contains(test):
|
|
329
|
-
|
|
330
|
-
if txt:
|
|
331
|
-
txt += ","
|
|
332
|
-
|
|
333
|
-
txt += areaCode
|
|
334
|
-
self.selectedPolygon = self.polygonsList2[areaCode]
|
|
335
|
-
self.selectedPolygonAreaCode = areaCode
|
|
336
|
-
|
|
337
|
-
self.selectedPolygonMemBrush = self.selectedPolygon.brush()
|
|
338
|
-
|
|
339
|
-
self.selectedPolygon.setPen(
|
|
340
|
-
QPen(
|
|
341
|
-
QColor(255, 0, 0, 255),
|
|
342
|
-
2,
|
|
343
|
-
Qt.SolidLine,
|
|
344
|
-
Qt.RoundCap,
|
|
345
|
-
Qt.RoundJoin,
|
|
346
|
-
)
|
|
347
|
-
)
|
|
348
|
-
|
|
349
|
-
self.leAreaCode.setText(areaCode)
|
|
350
|
-
self.leAreaCode.setVisible(True)
|
|
351
|
-
self.btDeleteArea.setEnabled(True)
|
|
352
|
-
|
|
353
|
-
self.areaColor = self.selectedPolygon.brush().color()
|
|
354
|
-
self.btColor.setStyleSheet(
|
|
355
|
-
"QWidget {{background-color:{}}}".format(
|
|
356
|
-
self.selectedPolygon.brush().color().name()
|
|
357
|
-
)
|
|
358
|
-
)
|
|
359
|
-
self.btColor.setVisible(True)
|
|
360
|
-
|
|
361
|
-
self.slAlpha.setValue(
|
|
362
|
-
int(self.selectedPolygon.brush().color().alpha() / 255 * 100)
|
|
363
|
-
)
|
|
364
|
-
self.slAlpha.setVisible(True)
|
|
365
|
-
|
|
366
|
-
break
|
|
367
|
-
|
|
368
|
-
if txt:
|
|
369
|
-
self.statusBar().showMessage(
|
|
370
|
-
"Modifier{}: {}".format("s" if "," in txt else "", txt)
|
|
371
|
-
)
|
|
372
|
-
else:
|
|
373
|
-
self.statusBar().showMessage("")
|
|
374
|
-
|
|
375
|
-
if not self.selectedPolygon:
|
|
376
|
-
self.leAreaCode.setVisible(False)
|
|
377
|
-
self.btColor.setVisible(False)
|
|
378
|
-
self.slAlpha.setVisible(False)
|
|
379
|
-
return
|
|
380
|
-
|
|
381
|
-
# delete last line item
|
|
382
|
-
if (event.buttons() & Qt.RightButton) and not self.closedPolygon:
|
|
383
|
-
|
|
384
|
-
if self.view.points:
|
|
385
|
-
self.view.points = self.view.points[0:-1]
|
|
386
|
-
|
|
387
|
-
if self.view.points:
|
|
388
|
-
self.view._start = QPoint(
|
|
389
|
-
self.view.points[-1][0], self.view.points[-1][1]
|
|
390
|
-
)
|
|
391
|
-
else:
|
|
392
|
-
self.view._start = None
|
|
393
|
-
|
|
394
|
-
# remove graphical elements
|
|
395
|
-
if self.view.elList:
|
|
396
|
-
self.view.scene().removeItem(self.view.elList[-1])
|
|
397
|
-
self.view.elList = self.view.elList[0:-1]
|
|
398
|
-
|
|
399
|
-
# add line item
|
|
400
|
-
if event.buttons() == Qt.LeftButton and not self.closedPolygon:
|
|
401
|
-
|
|
402
|
-
if self.view._start:
|
|
403
|
-
|
|
404
|
-
end = test
|
|
405
|
-
|
|
406
|
-
# test is polygon is crossed
|
|
407
|
-
if len(self.view.points) >= 3:
|
|
408
|
-
|
|
409
|
-
for idx, point in enumerate(self.view.points[:-2]):
|
|
410
|
-
|
|
411
|
-
if util.intersection(
|
|
412
|
-
self.view.points[idx],
|
|
413
|
-
self.view.points[idx + 1],
|
|
414
|
-
self.view.points[-1],
|
|
415
|
-
(int(end.x()), int(end.y())),
|
|
416
|
-
):
|
|
417
|
-
QMessageBox.critical(
|
|
418
|
-
self, "", "The polygon edges can not be intersected"
|
|
419
|
-
)
|
|
420
|
-
return
|
|
421
|
-
|
|
422
|
-
# test if polygon closed (dist min 10 px)
|
|
423
|
-
if (
|
|
424
|
-
abs(end.x() - self.view.points[0][0]) < 10
|
|
425
|
-
and abs(end.y() - self.view.points[0][1]) < 10
|
|
426
|
-
):
|
|
427
|
-
|
|
428
|
-
line = QGraphicsLineItem(
|
|
429
|
-
QLineF(
|
|
430
|
-
self.view._start,
|
|
431
|
-
QPoint(self.view.points[0][0], self.view.points[0][1]),
|
|
432
|
-
)
|
|
433
|
-
)
|
|
434
|
-
line.setPen(
|
|
435
|
-
QPen(
|
|
436
|
-
designColor,
|
|
437
|
-
penWidth,
|
|
438
|
-
Qt.SolidLine,
|
|
439
|
-
Qt.RoundCap,
|
|
440
|
-
Qt.RoundJoin,
|
|
441
|
-
)
|
|
442
|
-
)
|
|
443
|
-
|
|
444
|
-
self.view.scene().addItem(line)
|
|
445
|
-
self.view.elList.append(line)
|
|
446
|
-
|
|
447
|
-
self.statusBar().showMessage("Area completed")
|
|
448
|
-
|
|
449
|
-
# create polygon
|
|
450
|
-
newPolygon = QPolygonF()
|
|
451
|
-
for p in self.view.points:
|
|
452
|
-
newPolygon.append(QPoint(p[0], p[1]))
|
|
453
|
-
|
|
454
|
-
# draw polygon a red polygon
|
|
455
|
-
self.closedPolygon = QGraphicsPolygonItem(newPolygon)
|
|
456
|
-
|
|
457
|
-
self.closedPolygon.setPen(
|
|
458
|
-
QPen(designColor, penWidth, penStyle, Qt.RoundCap, Qt.RoundJoin)
|
|
459
|
-
)
|
|
460
|
-
|
|
461
|
-
self.closedPolygon.setBrush(self.areaColor)
|
|
462
|
-
|
|
463
|
-
self.view.scene().addItem(self.closedPolygon)
|
|
464
|
-
|
|
465
|
-
return
|
|
466
|
-
|
|
467
|
-
self.view.points.append((int(end.x()), int(end.y())))
|
|
468
|
-
|
|
469
|
-
line = QGraphicsLineItem(QLineF(self.view._start, end))
|
|
470
|
-
|
|
471
|
-
line.setPen(
|
|
472
|
-
QPen(designColor, 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
|
|
473
|
-
)
|
|
474
|
-
|
|
475
|
-
self.view.scene().addItem(line)
|
|
476
|
-
self.view.elList.append(line)
|
|
477
|
-
|
|
478
|
-
self.view._start = test
|
|
479
|
-
|
|
480
|
-
else: # first point
|
|
481
|
-
|
|
482
|
-
self.view._start = test
|
|
483
|
-
|
|
484
|
-
ellipse = QGraphicsEllipseItem(
|
|
485
|
-
self.view._start.x(), self.view._start.y(), 3, 3
|
|
486
|
-
)
|
|
487
|
-
ellipse.setPen(
|
|
488
|
-
QPen(designColor, 1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
|
|
489
|
-
)
|
|
490
|
-
|
|
491
|
-
brush = QBrush()
|
|
492
|
-
brush.setStyle(Qt.SolidPattern)
|
|
493
|
-
brush.setColor(designColor)
|
|
494
|
-
ellipse.setBrush(brush)
|
|
495
|
-
|
|
496
|
-
self.view.scene().addItem(ellipse)
|
|
497
|
-
self.view.elList.append(ellipse)
|
|
498
|
-
|
|
499
|
-
self.view.points.append((self.view._start.x(), self.view._start.y()))
|
|
500
|
-
|
|
501
|
-
def mapName_clicked(self):
|
|
502
|
-
"""
|
|
503
|
-
change map name
|
|
504
|
-
"""
|
|
505
|
-
text, ok = QInputDialog.getText(
|
|
506
|
-
self,
|
|
507
|
-
"Modifiers map name",
|
|
508
|
-
"Enter a name for the modifiers map",
|
|
509
|
-
QLineEdit.Normal,
|
|
510
|
-
self.mapName,
|
|
511
|
-
)
|
|
512
|
-
if ok:
|
|
513
|
-
self.mapName = text
|
|
514
|
-
self.setWindowTitle(
|
|
515
|
-
"{} - Modifiers map creator tool - {}".format(
|
|
516
|
-
cfg.programName, self.mapName
|
|
517
|
-
)
|
|
518
|
-
)
|
|
519
|
-
|
|
520
|
-
def newMap(self):
|
|
521
|
-
"""
|
|
522
|
-
create a new map
|
|
523
|
-
"""
|
|
524
|
-
|
|
525
|
-
if self.flagMapChanged:
|
|
526
|
-
|
|
527
|
-
response = dialog.MessageDialog(
|
|
528
|
-
cfg.programName + " - Modifiers map creator",
|
|
529
|
-
"What to do about the current unsaved coding map?",
|
|
530
|
-
["Save", "Discard", "Cancel"],
|
|
531
|
-
)
|
|
532
|
-
|
|
533
|
-
if response == "Save":
|
|
534
|
-
if not self.saveMap_clicked():
|
|
535
|
-
return
|
|
536
|
-
|
|
537
|
-
if response == "Cancel":
|
|
538
|
-
return
|
|
539
|
-
|
|
540
|
-
self.cancelMap()
|
|
541
|
-
|
|
542
|
-
text, ok = QInputDialog.getText(
|
|
543
|
-
self, "Map name", "Enter a name for the new map"
|
|
544
|
-
)
|
|
545
|
-
if ok:
|
|
546
|
-
self.mapName = text
|
|
547
|
-
else:
|
|
548
|
-
return
|
|
549
|
-
|
|
550
|
-
if self.mapName == "":
|
|
551
|
-
QMessageBox.critical(self, "", "You must define a name for the new map")
|
|
552
|
-
return
|
|
553
|
-
|
|
554
|
-
if self.mapName in ["areas", "bitmap"]:
|
|
555
|
-
QMessageBox.critical(self, "", "This name is not allowed")
|
|
556
|
-
return
|
|
557
|
-
|
|
558
|
-
self.setWindowTitle(cfg.programName + " - Map creator tool - " + self.mapName)
|
|
559
|
-
|
|
560
|
-
self.btLoad.setVisible(True)
|
|
561
|
-
"""self.btCancelMap.setVisible(True)"""
|
|
562
|
-
|
|
563
|
-
self.statusBar().showMessage(
|
|
564
|
-
'Click "Load bitmap" button to select and load a bitmap into the viewer'
|
|
565
|
-
)
|
|
566
|
-
|
|
567
|
-
def openMap(self):
|
|
568
|
-
"""
|
|
569
|
-
load bitmap from data
|
|
570
|
-
show it in view scene
|
|
571
|
-
"""
|
|
572
|
-
if self.flagMapChanged:
|
|
573
|
-
|
|
574
|
-
response = dialog.MessageDialog(
|
|
575
|
-
cfg.programName + " - Map creator",
|
|
576
|
-
"What to do about the current unsaved coding map?",
|
|
577
|
-
["Save", "Discard", "Cancel"],
|
|
578
|
-
)
|
|
579
|
-
|
|
580
|
-
if response == "Save":
|
|
581
|
-
if not self.saveMap_clicked():
|
|
582
|
-
return
|
|
583
|
-
|
|
584
|
-
if response == "Cancel":
|
|
585
|
-
return
|
|
586
|
-
|
|
587
|
-
fn = QFileDialog().getOpenFileName(
|
|
588
|
-
self,
|
|
589
|
-
"Open a coding map",
|
|
590
|
-
"",
|
|
591
|
-
"BORIS coding map (*.boris_map);;All files (*)",
|
|
592
|
-
)
|
|
593
|
-
fileName = fn[0] if type(fn) is tuple else fn
|
|
594
|
-
|
|
595
|
-
if fileName:
|
|
596
|
-
|
|
597
|
-
try:
|
|
598
|
-
self.codingMap = json.loads(open(fileName, "r").read())
|
|
599
|
-
except Exception:
|
|
600
|
-
QMessageBox.critical(
|
|
601
|
-
self,
|
|
602
|
-
cfg.programName,
|
|
603
|
-
"The file {} seems not a behaviors coding map...".format(fileName),
|
|
604
|
-
)
|
|
605
|
-
return
|
|
606
|
-
|
|
607
|
-
self.cancelMap()
|
|
608
|
-
|
|
609
|
-
self.mapName = self.codingMap["name"]
|
|
610
|
-
|
|
611
|
-
self.setWindowTitle(
|
|
612
|
-
cfg.programName + " - Map creator tool - " + self.mapName
|
|
613
|
-
)
|
|
614
|
-
|
|
615
|
-
self.bitmapFileName = True
|
|
616
|
-
|
|
617
|
-
self.fileName = fileName
|
|
618
|
-
|
|
619
|
-
self.areasList = self.codingMap["areas"] # dictionary of dictionaries
|
|
620
|
-
bitmapContent = binascii.a2b_base64(self.codingMap["bitmap"])
|
|
621
|
-
|
|
622
|
-
self.pixmap.loadFromData(bitmapContent)
|
|
623
|
-
|
|
624
|
-
self.btDeleteArea.setEnabled(False)
|
|
625
|
-
|
|
626
|
-
self.view.setSceneRect(
|
|
627
|
-
0, 0, self.pixmap.size().width(), self.pixmap.size().height()
|
|
628
|
-
)
|
|
629
|
-
pixItem = QGraphicsPixmapItem(self.pixmap)
|
|
630
|
-
pixItem.setPos(0, 0)
|
|
631
|
-
self.view.scene().addItem(pixItem)
|
|
632
|
-
|
|
633
|
-
for areaCode in self.areasList:
|
|
634
|
-
points = self.areasList[areaCode]["geometry"]
|
|
635
|
-
|
|
636
|
-
newPolygon = QPolygonF()
|
|
637
|
-
for p in points:
|
|
638
|
-
newPolygon.append(QPoint(p[0], p[1]))
|
|
639
|
-
|
|
640
|
-
clr = QColor()
|
|
641
|
-
clr.setRgba(self.areasList[areaCode]["color"])
|
|
642
|
-
|
|
643
|
-
# draw polygon
|
|
644
|
-
polygon = QGraphicsPolygonItem()
|
|
645
|
-
|
|
646
|
-
polygon.setPolygon(newPolygon)
|
|
647
|
-
|
|
648
|
-
polygon.setPen(QPen(clr, penWidth, penStyle, Qt.RoundCap, Qt.RoundJoin))
|
|
649
|
-
|
|
650
|
-
polygon.setBrush(QBrush(clr, Qt.SolidPattern))
|
|
651
|
-
|
|
652
|
-
self.view.scene().addItem(polygon)
|
|
653
|
-
self.polygonsList2[areaCode] = polygon
|
|
654
|
-
|
|
655
|
-
self.btNewArea.setVisible(True)
|
|
656
|
-
|
|
657
|
-
self.btLoad.setVisible(False)
|
|
658
|
-
|
|
659
|
-
self.saveMapAction.setEnabled(True)
|
|
660
|
-
self.saveAsMapAction.setEnabled(True)
|
|
661
|
-
self.mapNameAction.setEnabled(True)
|
|
662
|
-
self.statusBar().showMessage('Click "New area" to create a new area')
|
|
663
|
-
else:
|
|
664
|
-
self.statusBar().showMessage("No file", 5000)
|
|
665
|
-
|
|
666
|
-
def saveMap(self):
|
|
667
|
-
|
|
668
|
-
if self.fileName:
|
|
669
|
-
|
|
670
|
-
# create dict with map name key
|
|
671
|
-
mapDict = {"name": self.mapName}
|
|
672
|
-
|
|
673
|
-
# add areas
|
|
674
|
-
mapDict["areas"] = self.areasList
|
|
675
|
-
|
|
676
|
-
import io
|
|
677
|
-
|
|
678
|
-
# Save QPixmap to QByteArray via QBuffer.
|
|
679
|
-
byte_array = QByteArray()
|
|
680
|
-
buffer = QBuffer(byte_array)
|
|
681
|
-
buffer.open(QIODevice.WriteOnly)
|
|
682
|
-
self.pixmap.save(buffer, "PNG")
|
|
683
|
-
|
|
684
|
-
string_io = io.BytesIO(byte_array)
|
|
685
|
-
|
|
686
|
-
string_io.seek(0)
|
|
687
|
-
|
|
688
|
-
# add bitmap
|
|
689
|
-
mapDict["bitmap"] = binascii.b2a_base64(string_io.read()).decode("utf-8")
|
|
690
|
-
|
|
691
|
-
with open(self.fileName, "w") as outfile:
|
|
692
|
-
outfile.write(json.dumps(mapDict))
|
|
693
|
-
|
|
694
|
-
self.flagMapChanged = False
|
|
695
|
-
|
|
696
|
-
return True
|
|
697
|
-
else:
|
|
698
|
-
return False
|
|
699
|
-
|
|
700
|
-
def saveAsMap_clicked(self):
|
|
701
|
-
|
|
702
|
-
filters = "Modifiers map (*.boris_map);;All files (*)"
|
|
703
|
-
|
|
704
|
-
fn = QFileDialog(self).getSaveFileName(
|
|
705
|
-
self, "Save modifiers map as", "", filters
|
|
706
|
-
)
|
|
707
|
-
if type(fn) is tuple:
|
|
708
|
-
self.fileName, _ = fn
|
|
709
|
-
else:
|
|
710
|
-
self.fileName = fn
|
|
711
|
-
|
|
712
|
-
if self.fileName:
|
|
713
|
-
if os.path.splitext(self.fileName)[1] != ".boris_map":
|
|
714
|
-
self.fileName += ".boris_map"
|
|
715
|
-
self.saveMap()
|
|
716
|
-
|
|
717
|
-
def saveMap_clicked(self):
|
|
718
|
-
|
|
719
|
-
if not self.fileName:
|
|
720
|
-
|
|
721
|
-
fn = QFileDialog(self).getSaveFileName(
|
|
722
|
-
self,
|
|
723
|
-
"Save modifiers map",
|
|
724
|
-
self.mapName + ".boris_map",
|
|
725
|
-
"BORIS MAP (*.boris_map);;All files (*)",
|
|
726
|
-
)
|
|
727
|
-
if type(fn) is tuple:
|
|
728
|
-
self.fileName, _ = fn
|
|
729
|
-
else:
|
|
730
|
-
self.fileName = fn
|
|
731
|
-
|
|
732
|
-
if self.fileName and os.path.splitext(self.fileName)[1] != ".boris_map":
|
|
733
|
-
self.fileName += ".boris_map"
|
|
734
|
-
|
|
735
|
-
if self.fileName:
|
|
736
|
-
return self.saveMap()
|
|
737
|
-
|
|
738
|
-
return False
|
|
739
|
-
|
|
740
|
-
def newArea(self):
|
|
741
|
-
|
|
742
|
-
if not self.bitmapFileName:
|
|
743
|
-
QMessageBox.critical(
|
|
744
|
-
self, cfg.programName, "A bitmap must be loaded before to define areas"
|
|
745
|
-
)
|
|
746
|
-
return
|
|
747
|
-
|
|
748
|
-
if self.selectedPolygon:
|
|
749
|
-
self.selectedPolygon.setPen(
|
|
750
|
-
QPen(designColor, penWidth, penStyle, Qt.RoundCap, Qt.RoundJoin)
|
|
751
|
-
)
|
|
752
|
-
self.selectedPolygon = None
|
|
753
|
-
|
|
754
|
-
self.flagNewArea = True
|
|
755
|
-
self.btSaveArea.setVisible(True)
|
|
756
|
-
self.btCancelAreaCreation.setVisible(True)
|
|
757
|
-
self.btNewArea.setVisible(False)
|
|
758
|
-
self.lb.setVisible(True)
|
|
759
|
-
self.leAreaCode.clear()
|
|
760
|
-
self.leAreaCode.setVisible(True)
|
|
761
|
-
self.btColor.setVisible(True)
|
|
762
|
-
self.slAlpha.setVisible(True)
|
|
763
|
-
self.btDeleteArea.setVisible(False)
|
|
764
|
-
|
|
765
|
-
self.statusBar().showMessage(
|
|
766
|
-
"Select the vertices of the area for this modifier with the mouse (right click will cancel the last point)"
|
|
767
|
-
)
|
|
768
|
-
|
|
769
|
-
def saveArea(self):
|
|
770
|
-
|
|
771
|
-
if not self.closedPolygon:
|
|
772
|
-
QMessageBox.critical(
|
|
773
|
-
self,
|
|
774
|
-
cfg.programName,
|
|
775
|
-
"You must close your area before saving it.\nThe last vertex must correspond to the first one.",
|
|
776
|
-
)
|
|
777
|
-
|
|
778
|
-
if len(self.view.points) < 3:
|
|
779
|
-
QMessageBox.critical(self, cfg.programName, "You must define a closed area")
|
|
780
|
-
return
|
|
781
|
-
|
|
782
|
-
# check if no area code
|
|
783
|
-
if not self.leAreaCode.text():
|
|
784
|
-
QMessageBox.critical(
|
|
785
|
-
self, cfg.programName, "You must define a code for the new modifier"
|
|
786
|
-
)
|
|
787
|
-
return
|
|
788
|
-
|
|
789
|
-
# check if not allowed character
|
|
790
|
-
for c in "|,()":
|
|
791
|
-
if c in self.leAreaCode.text():
|
|
792
|
-
QMessageBox.critical(
|
|
793
|
-
self,
|
|
794
|
-
cfg.programName,
|
|
795
|
-
"The modifier contains a character that is not allowed <b>()|,</b>.",
|
|
796
|
-
)
|
|
797
|
-
return
|
|
798
|
-
|
|
799
|
-
# check if area code already used
|
|
800
|
-
|
|
801
|
-
if self.leAreaCode.text() in self.areasList:
|
|
802
|
-
QMessageBox.critical(
|
|
803
|
-
self, cfg.programName, "The modifier is already in use"
|
|
804
|
-
)
|
|
805
|
-
return
|
|
806
|
-
|
|
807
|
-
# create polygon
|
|
808
|
-
newPolygon = QPolygon()
|
|
809
|
-
for p in self.view.points:
|
|
810
|
-
newPolygon.append(QPoint(p[0], p[1]))
|
|
811
|
-
|
|
812
|
-
self.areasList[self.leAreaCode.text()] = {
|
|
813
|
-
"geometry": self.view.points,
|
|
814
|
-
"color": self.areaColor.rgba(),
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
# remove all lines
|
|
818
|
-
for line in self.view.elList:
|
|
819
|
-
self.view.scene().removeItem(line)
|
|
820
|
-
|
|
821
|
-
# draw polygon
|
|
822
|
-
self.closedPolygon.setBrush(QBrush(self.areaColor, Qt.SolidPattern))
|
|
823
|
-
self.polygonsList2[self.leAreaCode.text()] = self.closedPolygon
|
|
824
|
-
self.closedPolygon = None
|
|
825
|
-
self.view._start = 0
|
|
826
|
-
self.view.points = []
|
|
827
|
-
self.view.elList = []
|
|
828
|
-
self.flagNewArea = False
|
|
829
|
-
self.closedPolygon = None
|
|
830
|
-
|
|
831
|
-
self.btSaveArea.setVisible(False)
|
|
832
|
-
self.btCancelAreaCreation.setVisible(False)
|
|
833
|
-
self.lb.setVisible(False)
|
|
834
|
-
self.leAreaCode.setVisible(False)
|
|
835
|
-
self.btColor.setVisible(False)
|
|
836
|
-
self.slAlpha.setVisible(False)
|
|
837
|
-
self.btDeleteArea.setVisible(True)
|
|
838
|
-
self.btNewArea.setVisible(True)
|
|
839
|
-
|
|
840
|
-
self.leAreaCode.setText("")
|
|
841
|
-
|
|
842
|
-
self.flagMapChanged = True
|
|
843
|
-
self.statusBar().showMessage("New modifier saved", 5000)
|
|
844
|
-
|
|
845
|
-
def cancelAreaCreation(self):
|
|
846
|
-
|
|
847
|
-
if self.closedPolygon:
|
|
848
|
-
self.view.scene().removeItem(self.closedPolygon)
|
|
849
|
-
self.closedPolygon = None
|
|
850
|
-
|
|
851
|
-
# remove all lines
|
|
852
|
-
for line in self.view.elList:
|
|
853
|
-
self.view.scene().removeItem(line)
|
|
854
|
-
|
|
855
|
-
self.view.elList = []
|
|
856
|
-
|
|
857
|
-
self.view._start = 0
|
|
858
|
-
self.view.points = []
|
|
859
|
-
self.flagNewArea = False
|
|
860
|
-
self.btCancelAreaCreation.setVisible(False)
|
|
861
|
-
self.btDeleteArea.setVisible(True)
|
|
862
|
-
self.btSaveArea.setVisible(False)
|
|
863
|
-
self.lb.setVisible(False)
|
|
864
|
-
|
|
865
|
-
self.btColor.setVisible(False)
|
|
866
|
-
self.slAlpha.setVisible(False)
|
|
867
|
-
self.btNewArea.setVisible(True)
|
|
868
|
-
|
|
869
|
-
self.leAreaCode.setVisible(False)
|
|
870
|
-
self.leAreaCode.setText("")
|
|
871
|
-
|
|
872
|
-
def deleteArea(self):
|
|
873
|
-
"""
|
|
874
|
-
remove selected area from map
|
|
875
|
-
"""
|
|
876
|
-
|
|
877
|
-
if self.selectedPolygon:
|
|
878
|
-
self.view.scene().removeItem(self.selectedPolygon)
|
|
879
|
-
self.view.scene().removeItem(
|
|
880
|
-
self.polygonsList2[self.selectedPolygonAreaCode]
|
|
881
|
-
)
|
|
882
|
-
|
|
883
|
-
del self.polygonsList2[self.selectedPolygonAreaCode]
|
|
884
|
-
del self.areasList[self.selectedPolygonAreaCode]
|
|
885
|
-
|
|
886
|
-
self.flagMapChanged = True
|
|
887
|
-
|
|
888
|
-
self.view.elList = []
|
|
889
|
-
|
|
890
|
-
self.view._start = 0
|
|
891
|
-
self.view.points = []
|
|
892
|
-
self.flagNewArea = False
|
|
893
|
-
self.btSaveArea.setVisible(False)
|
|
894
|
-
self.lb.setVisible(False)
|
|
895
|
-
|
|
896
|
-
self.btColor.setVisible(False)
|
|
897
|
-
self.slAlpha.setVisible(False)
|
|
898
|
-
self.btNewArea.setVisible(True)
|
|
899
|
-
|
|
900
|
-
self.leAreaCode.setVisible(False)
|
|
901
|
-
self.leAreaCode.setText("")
|
|
902
|
-
|
|
903
|
-
def cancelMap(self):
|
|
904
|
-
"""
|
|
905
|
-
remove current map
|
|
906
|
-
"""
|
|
907
|
-
self.flagNewArea = False
|
|
908
|
-
self.areasList = {}
|
|
909
|
-
self.polygonsList2 = {}
|
|
910
|
-
self.view.scene().clear()
|
|
911
|
-
self.btLoad.setVisible(False)
|
|
912
|
-
self.btDeleteArea.setVisible(False)
|
|
913
|
-
self.btNewArea.setVisible(False)
|
|
914
|
-
self.saveMapAction.setEnabled(False)
|
|
915
|
-
self.saveAsMapAction.setEnabled(False)
|
|
916
|
-
self.mapNameAction.setEnabled(False)
|
|
917
|
-
self.statusBar().showMessage("")
|
|
918
|
-
self.flagMapChanged = False
|
|
919
|
-
|
|
920
|
-
def loadBitmap(self):
|
|
921
|
-
"""
|
|
922
|
-
load bitmap as background for coding map
|
|
923
|
-
resize bitmap to 512 px if bigger
|
|
924
|
-
"""
|
|
925
|
-
|
|
926
|
-
maxSize = 512
|
|
927
|
-
|
|
928
|
-
fn = QFileDialog().getOpenFileName(
|
|
929
|
-
self, "Load bitmap", "", "bitmap files (*.png *.jpg);;All files (*)"
|
|
930
|
-
)
|
|
931
|
-
fileName = fn[0] if type(fn) is tuple else fn
|
|
932
|
-
|
|
933
|
-
if fileName:
|
|
934
|
-
self.bitmapFileName = fileName
|
|
935
|
-
|
|
936
|
-
self.pixmap.load(self.bitmapFileName)
|
|
937
|
-
|
|
938
|
-
if (
|
|
939
|
-
self.pixmap.size().width() > maxSize
|
|
940
|
-
or self.pixmap.size().height() > maxSize
|
|
941
|
-
):
|
|
942
|
-
self.pixmap = self.pixmap.scaled(maxSize, maxSize, Qt.KeepAspectRatio)
|
|
943
|
-
QMessageBox.information(
|
|
944
|
-
self,
|
|
945
|
-
cfg.programName,
|
|
946
|
-
"The bitmap was resized to %d x %d pixels\nThe original file was not modified"
|
|
947
|
-
% (self.pixmap.size().width(), self.pixmap.size().height()),
|
|
948
|
-
)
|
|
949
|
-
|
|
950
|
-
# scale image
|
|
951
|
-
# pixmap = pixmap.scaled (256, 256, Qt.KeepAspectRatio)
|
|
952
|
-
|
|
953
|
-
self.view.setSceneRect(
|
|
954
|
-
0, 0, self.pixmap.size().width(), self.pixmap.size().height()
|
|
955
|
-
)
|
|
956
|
-
pixitem = QGraphicsPixmapItem(self.pixmap)
|
|
957
|
-
pixitem.setPos(0, 0)
|
|
958
|
-
self.view.scene().addItem(pixitem)
|
|
959
|
-
|
|
960
|
-
self.btNewArea.setVisible(True)
|
|
961
|
-
|
|
962
|
-
self.btLoad.setVisible(False)
|
|
963
|
-
self.saveMapAction.setEnabled(True)
|
|
964
|
-
self.saveAsMapAction.setEnabled(True)
|
|
965
|
-
self.mapNameAction.setEnabled(True)
|
|
966
|
-
|
|
967
|
-
self.statusBar().showMessage(
|
|
968
|
-
"""Click "New modifier" to create a new modifier"""
|
|
969
|
-
)
|
|
970
|
-
|
|
971
|
-
self.flagMapChanged = True
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
if __name__ == "__main__":
|
|
975
|
-
|
|
976
|
-
import sys
|
|
977
|
-
|
|
978
|
-
app = QApplication(sys.argv)
|
|
979
|
-
window = ModifiersMapCreatorWindow()
|
|
980
|
-
window.resize(640, 640)
|
|
981
|
-
window.show()
|
|
982
|
-
sys.exit(app.exec_())
|