1# -*- coding: utf-8 -*- 2 3# ------------------------------------------------------------------------------- 4 5# This file is part of Code_Saturne, a general-purpose CFD tool. 6# 7# Copyright (C) 1998-2021 EDF S.A. 8# 9# This program is free software; you can redistribute it and/or modify it under 10# the terms of the GNU General Public License as published by the Free Software 11# Foundation; either version 2 of the License, or (at your option) any later 12# version. 13# 14# This program is distributed in the hope that it will be useful, but WITHOUT 15# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 17# details. 18# 19# You should have received a copy of the GNU General Public License along with 20# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin 21# Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 23# ------------------------------------------------------------------------------- 24 25""" 26This module contains the following classes: 27- LabelDelegate 28- LocalizationSelectorDelegate 29- StandardItemModelLocalization 30- LocalizationView 31""" 32 33# ------------------------------------------------------------------------------- 34# Standard modules 35# ------------------------------------------------------------------------------- 36 37import logging 38 39# ------------------------------------------------------------------------------- 40# Third-party modules 41# ------------------------------------------------------------------------------- 42 43from code_saturne.Base.QtCore import * 44from code_saturne.Base.QtGui import * 45from code_saturne.Base.QtWidgets import * 46 47# ------------------------------------------------------------------------------- 48# Application modules import 49# ------------------------------------------------------------------------------- 50 51from code_saturne.model.Common import LABEL_LENGTH_MAX, GuiParam 52from code_saturne.Base.QtPage import IntValidator, RegExpValidator 53from code_saturne.Base.QtPage import from_qvariant, to_text_string 54from code_saturne.Pages.BoundaryNatureForm import Ui_BoundaryNatureForm 55from code_saturne.model.LocalizationModel import LocalizationModel, Zone 56 57# ------------------------------------------------------------------------------- 58# log config 59# ------------------------------------------------------------------------------- 60 61logging.basicConfig() 62log = logging.getLogger("BoundaryNatureView") 63log.setLevel(GuiParam.DEBUG) 64 65 66# ------------------------------------------------------------------------------- 67# QComboBox delegate for the boundary nature 68# ------------------------------------------------------------------------------- 69 70class BoundaryNatureDelegate(QItemDelegate): 71 """ 72 Use of a combo box in the table. 73 """ 74 75 def __init__(self, parent, dicoM2V): 76 super(BoundaryNatureDelegate, self).__init__(parent) 77 self.parent = parent 78 self.dicoM2V = dicoM2V 79 80 self.dicoV2M = {} 81 for k, v in list(self.dicoM2V.items()): 82 self.dicoV2M[v] = k 83 84 def createEditor(self, parent, option, index): 85 editor = QComboBox(parent) 86 for k in list(self.dicoV2M.keys()): 87 editor.addItem(k) 88 editor.installEventFilter(self) 89 editor.setMinimumWidth(120) 90 return editor 91 92 def setEditorData(self, comboBox, index): 93 row = index.row() 94 col = index.column() 95 str_model = index.model().getData(row, col) 96 idx = list(self.dicoM2V.keys()).index(str_model) 97 comboBox.setCurrentIndex(idx) 98 99 def setModelData(self, comboBox, model, index): 100 txt = str(comboBox.currentText()) 101 value = self.dicoV2M[txt] 102 selectionModel = self.parent.selectionModel() 103 for idx in selectionModel.selectedIndexes(): 104 if idx.column() == index.column(): 105 model.setData(idx, value, Qt.DisplayRole) 106 107 108# ------------------------------------------------------------------------------- 109# StandarItemModel class 110# ------------------------------------------------------------------------------- 111 112class StandardItemModelLocalization(QStandardItemModel): 113 def __init__(self, mdl, zoneType, dicoM2V, tree=None, case=None): 114 """ 115 """ 116 QStandardItemModel.__init__(self) 117 self.headers = [self.tr("Label"), 118 self.tr("Nature")] 119 self.setColumnCount(len(self.headers)) 120 121 self.mdl = mdl 122 self.zoneType = zoneType 123 self.dicoM2V = dicoM2V 124 self.browser = tree 125 self.case = case 126 127 self._data = [] 128 self._disable = [] 129 130 def data(self, index, role): 131 if not index.isValid(): 132 return None 133 134 if role == Qt.DisplayRole: 135 row = index.row() 136 col = index.column() 137 138 if col == 0: 139 return self._data[row][col] 140 141 elif col == 1: 142 key = self._data[row][col] 143 return self.dicoM2V[key] 144 145 return None 146 147 def flags(self, index): 148 if not index.isValid(): 149 return Qt.ItemIsEnabled 150 if index.column() == 0: 151 return Qt.ItemIsEnabled 152 return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable 153 154 def headerData(self, section, orientation, role): 155 if orientation == Qt.Horizontal and role == Qt.DisplayRole: 156 return self.headers[section] 157 return None 158 159 def setData(self, index, value, role): 160 col = index.column() 161 162 if col == 1: 163 row = index.row() 164 165 nature = str(from_qvariant(value, to_text_string)) 166 self._data[row][1] = nature 167 168 self.mdl.setNature(self._data[row][0], nature) 169 170 self.dataChanged.emit(index, index) 171 self.browser.configureTree(self.case) 172 return True 173 174 def addItem(self, zone): 175 """ 176 Add an element in the table view. 177 """ 178 line = [zone.getLabel(), 179 zone.getNature()] 180 self._data.append(line) 181 row = self.rowCount() 182 self.setRowCount(row + 1) 183 184 # If row is disabled, it appears in light gray 185 # self._disable.append((row, 0)) 186 self.browser.configureTree(self.case) 187 return zone 188 189 def getItem(self, row): 190 return self._data[row] 191 192 def getData(self, row, column): 193 return self._data[row][column] 194 195 196# ------------------------------------------------------------------------------- 197# Main class 198# ------------------------------------------------------------------------------- 199 200class BoundaryNatureView(QWidget, Ui_BoundaryNatureForm): 201 """ 202 Main class 203 """ 204 205 def __init__(self, parent, case, tree=None): 206 """ 207 Constructor 208 """ 209 QWidget.__init__(self, parent) 210 211 Ui_BoundaryNatureForm.__init__(self) 212 self.setupUi(self) 213 214 self.case = case 215 self.case.undoStopGlobal() 216 217 dicoM2V = Zone("BoundaryZone", case=self.case).getModel2ViewDictionary() 218 zoneType = "BoundaryZone" 219 self.zoneType = "BoundaryZone" 220 221 self.mdl = LocalizationModel("BoundaryZone", case) 222 self.case['dump_python'].append([self.mdl.__module__, "BoundaryZone", ()]) 223 224 self.browser = tree 225 226 # Delegates 227 delegateNature = BoundaryNatureDelegate(self.tableView, dicoM2V) 228 229 # Model for table View 230 self.modelLocalization = StandardItemModelLocalization(self.mdl, 231 zoneType, 232 dicoM2V, 233 tree, 234 case) 235 self.tableView.setModel(self.modelLocalization) 236 self.tableView.setItemDelegateForColumn(1, delegateNature) 237 last_section = 1 238 239 # Populate QTableView model 240 for zone in self.mdl.getZones(): 241 self.modelLocalization.addItem(zone) 242 243 if QT_API == "PYQT4": 244 self.tableView.verticalHeader().setResizeMode(QHeaderView.ResizeToContents) 245 self.tableView.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) 246 self.tableView.horizontalHeader().setResizeMode(last_section, QHeaderView.Stretch) 247 elif QT_API == "PYQT5": 248 self.tableView.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) 249 self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) 250 self.tableView.horizontalHeader().setSectionResizeMode(last_section, QHeaderView.Stretch) 251 252 # Connections 253 self.modelLocalization.dataChanged.connect(self.dataChanged) 254 self.tableView.clicked.connect(self.slotChangeSelection) 255 256 # Context menu 257 self.tableView.setContextMenuPolicy(Qt.CustomContextMenu) 258 self.tableView.customContextMenuRequested[QPoint].connect(self.slotContextMenu) 259 260 self.case.undoStartGlobal() 261 262 def slotChangeSelection(self): 263 """ 264 """ 265 current = self.tableView.currentIndex() 266 267 @pyqtSlot() 268 def slotContextMenu(self): 269 """ 270 Public slot 271 272 Create the popup menu of the Browser 273 """ 274 fileMenu = QMenu(self.tableView) 275 276 self.actionInlet = QAction(self.tr("Select all inlets"), self.tableView) 277 self.actionInlet.triggered.connect(self.slotSelectBoundaries) 278 fileMenu.addAction(self.actionInlet) 279 280 self.actionOutlet = QAction(self.tr("Select all outlets"), self.tableView) 281 self.actionOutlet.triggered.connect(self.slotSelectBoundaries) 282 fileMenu.addAction(self.actionOutlet) 283 284 self.actionWall = QAction(self.tr("Select all walls"), self.tableView) 285 self.actionWall.triggered.connect(self.slotSelectBoundaries) 286 fileMenu.addAction(self.actionWall) 287 288 self.actionSymmetry = QAction(self.tr("Select all symmetries"), self.tableView) 289 self.actionSymmetry.triggered.connect(self.slotSelectBoundaries) 290 fileMenu.addAction(self.actionSymmetry) 291 292 fileMenu.popup(QCursor().pos()) 293 fileMenu.show() 294 295 def dataChanged(self, topLeft, bottomRight): 296 for row in range(topLeft.row(), bottomRight.row() + 1): 297 self.tableView.resizeRowToContents(row) 298 for col in range(topLeft.column(), bottomRight.column() + 1): 299 self.tableView.resizeColumnToContents(col) 300 301 @pyqtSlot() 302 def slotSelectBoundaries(self): 303 """ 304 Public slot. 305 306 Warning: works only if the selection mode of the view is set to MultiSelection. 307 """ 308 previous_selecion_mode = self.tableView.selectionMode() 309 self.tableView.setSelectionMode(QAbstractItemView.MultiSelection) 310 self.tableView.clearSelection() 311 312 if self.sender() == self.actionInlet: 313 select = "inlet" 314 elif self.sender() == self.actionOutlet: 315 select = "outlet" 316 elif self.sender() == self.actionWall: 317 select = "wall" 318 elif self.sender() == self.actionSymmetry: 319 select = "symmetry" 320 321 for row in range(self.modelLocalization.rowCount()): 322 [label, nature] = self.modelLocalization.getItem(row) 323 if nature == select: 324 self.tableView.selectRow(row) 325 326 self.tableView.setSelectionMode(previous_selecion_mode) 327 328 329# ------------------------------------------------------------------------------- 330# End 331# ------------------------------------------------------------------------------- 332