Coverage for grm\GRM_dockwidget.py: 0%

258 statements  

« prev     ^ index     » next       coverage.py v7.2.3, created at 2023-04-12 14:21 +0900

1# -*- coding: utf-8 -*- 

2""" 

3/*************************************************************************** 

4 GRMDockWidget 

5 A QGIS plugin 

6 GRM 

7 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/ 

8 ------------------- 

9 begin : 2020-01-08 

10 git sha : $Format:%H$ 

11 copyright : (C) 2020 by Hermesys 

12 email : shpark@hermesys.co.kr 

13 ***************************************************************************/ 

14 

15/*************************************************************************** 

16 * * 

17 * This program is free software; you can redistribute it and/or modify * 

18 * it under the terms of the GNU General Public License as published by * 

19 * the Free Software Foundation; either version 2 of the License, or * 

20 * (at your option) any later version. * 

21 * * 

22 ***************************************************************************/ 

23""" 

24 

25import os 

26import time 

27import webbrowser 

28from typing import Dict, Union 

29 

30from qgis.core import QgsProject, QgsRasterLayer 

31from qgis.PyQt import QtGui, QtWidgets 

32from qgis.PyQt.QtCore import QFileInfo, pyqtSignal 

33from qgis.PyQt.QtWidgets import QFileDialog, QTreeWidgetItem 

34 

35from grm.dialogs.Climate_data import ClimateDataDialog 

36from grm.dialogs.LandCover_dialog import LandCoverDialog 

37from grm.GRM_dialog import GRMDialog 

38from grm.lib.File_Class import ChFile_Exists 

39from grm.lib.Util import MsError, MsInfo, MsTitle 

40from grm.lib.xmltodict import parse, unparse 

41from grm.ui.GRM_dockwidget_base import Ui_GRMDockWidgetBase 

42 

43# from .lib.File_Class import * 

44# from .lib.Util import * 

45# from .lib.xmltodict import * 

46from grm.Watershed_dialog import WatershedDialog 

47from grm.XMLCheck import xmls 

48from grm.XMLMake import make 

49 

50path = os.path.dirname(os.path.realpath(__file__)) 

51project_icon_path = path + "\image\Folder_3.png" 

52input_data_icon_path = path + "\image\database.png" 

53run_GRM_icon_path = path + "\image\settings.png" 

54GRMTools = path + "\image\Tool.png" 

55help_icon_path = path + "\image\information.png" 

56Analysis = path + "\image\Analysis.png" 

57Flask = path + "\image\Flask.png" 

58 

59_XmlCheck = xmls() 

60_XmlCreat = make() 

61# 트리 위제 목록이 비활성화 중에도 클릭 이벤트가 처리 되는 현상으로 

62# 구분 하기위해서 넣음 

63_ProjectFlage = False 

64 

65 

66class GRMDockWidget(QtWidgets.QDockWidget, Ui_GRMDockWidgetBase): 

67 closingPlugin = pyqtSignal() 

68 

69 def __init__(self, parent=None): 

70 super(GRMDockWidget, self).__init__(parent) 

71 self.setupUi(self) 

72 

73 # 변수 초기화 

74 self._xmltodict: Union[Dict, None] = None 

75 

76 # 화면 초기화 

77 self.initUI() 

78 

79 def initUI(self): 

80 MsTitle("GRM") 

81 self.setWindowTitle("GRM") 

82 self.treeWidget.setItemsExpandable(True) 

83 self.treeWidget.setAnimated(True) 

84 self.treeWidget.setColumnCount(1) 

85 self.treeWidget.setHeaderHidden(True) 

86 

87 # Project 메뉴 설정 

88 project_item = QTreeWidgetItem(self.treeWidget, ["Project"]) 

89 project_item.setIcon(0, QtGui.QIcon(project_icon_path)) 

90 QTreeWidgetItem(project_item, ["New Project"]) 

91 QTreeWidgetItem(project_item, ["Open Project"]) 

92 save_project_item = QTreeWidgetItem(project_item, ["Save Project"]) 

93 save_project_item.setDisabled(True) 

94 save_as_project_item = QTreeWidgetItem(project_item, ["Save as Project"]) 

95 save_as_project_item.setDisabled(True) 

96 

97 # Input Data 메뉴 설정 

98 input_data_item = QTreeWidgetItem(self.treeWidget, ["Setup input data"]) 

99 input_data_item.setIcon(0, QtGui.QIcon(input_data_icon_path)) 

100 input_data_item.setDisabled(True) 

101 QTreeWidgetItem(input_data_item, ["Watershed"]) 

102 QTreeWidgetItem(input_data_item, ["Land Cover / Soil"]) 

103 QTreeWidgetItem(input_data_item, ["Climate Data"]) 

104 

105 # Setup / Run GRM 메뉴 설정 

106 setup_and_run_grm_item = QTreeWidgetItem(self.treeWidget, ["Setup / Run GRM"]) 

107 setup_and_run_grm_item.setIcon(0, QtGui.QIcon(run_GRM_icon_path)) 

108 setup_and_run_grm_item.setDisabled(True) 

109 

110 # 도움말 메뉴 설정 

111 help_item = QTreeWidgetItem(self.treeWidget, ["Help"]) 

112 QTreeWidgetItem(help_item, ["Helps"]) 

113 help_item.setIcon(0, QtGui.QIcon(help_icon_path)) 

114 

115 self.grmDialogFlag = False 

116 

117 # 더블 클릭 했을대 메뉴 명칭 확인 

118 self.treeWidget.itemDoubleClicked.connect(self.OnDoubleClick) 

119 

120 def OnDoubleClick(self, select_item: QTreeWidgetItem): 

121 try: 

122 # 프로젝트 파일 오픈 

123 item_text = select_item.text(0) 

124 is_enable = not select_item.isDisabled() 

125 

126 if item_text == "New Project": 

127 self.NewProjectFile() 

128 

129 elif item_text == "Open Project": 

130 self.OpenProjectFile() 

131 

132 elif item_text == "Save Project" and is_enable: 

133 self.SaveProjectFile() 

134 

135 elif item_text == "Save as Project" and is_enable: 

136 self.SaveASProjectFile() 

137 

138 elif item_text == "Watershed" and is_enable: 

139 if self.grmDialogFlag == True: 

140 self._grmDialogFlag = 1 

141 elif self.grmDialogFlag == False: 

142 self._grmDialogFlag = 0 

143 Watershed = WatershedDialog(self._xmltodict, self._grmDialogFlag) 

144 Watershed.exec_() 

145 self._xmltodict = Watershed._xmltodict 

146 self._grmDialogFlag = Watershed._grmDialogFlag 

147 

148 elif item_text == "Land Cover / Soil" and is_enable: 

149 if self.grmDialogFlag == True: 

150 self._grmDialogFlag = 1 

151 if self.grmDialogFlag == False: 

152 self._grmDialogFlag = 0 

153 LandCover = LandCoverDialog( 

154 self._xmltodict, 

155 self._LandCoverCount, 

156 self._GreenAmptCount, 

157 self._SoilDepthCount, 

158 self._grmDialogFlag, 

159 ) 

160 LandCover.exec_() 

161 self._xmltodict = LandCover._xmltodict 

162 self._LandCoverCount = LandCover._LandCoverCount 

163 self._GreenAmptCount = LandCover._GreenAmptCount 

164 self._SoilDepthCount = LandCover._SoilDepthCount 

165 self._grmDialogFlag = LandCover._grmDialogFlag 

166 

167 elif item_text == "Climate Data" and is_enable: 

168 ClimateData = ClimateDataDialog(self._xmltodict) 

169 ClimateData.exec_() 

170 

171 elif item_text == "Setup / Run GRM" and is_enable: 

172 try: 

173 # 2022.01.05 동 : flag를 사용하지 않으면 GRMDialog 창이 클릭한 개수만큼 뜨게 됨. 

174 # 창이 여러개 뜨면 grid line, flow direction을 캔버스에 표시할때 오류가 발생해서 1개의 창만 킬 수 있도록 변경 

175 # 그 외, 개발할때 reload plugin 하기 전에 dialog 창이 켜진 상태로 reload를 진행하면 기존 레이어가 지워지지 않아서 오류가 발생할 수 있음. 

176 def closeSignal(): 

177 self.grmDialogFlag = False 

178 

179 if not self.grmDialogFlag: 

180 GRM = GRMDialog( 

181 self._xmltodict, 

182 self._WatchPointCount, 

183 self._SubWatershedCount, 

184 self._GreenAmptCount, 

185 self._SoilDepthCount, 

186 self._LandCoverCount, 

187 self._FlowControlCount, 

188 self._ChannelSettingsCount, 

189 ) 

190 

191 GRM.closeDialogEvent.connect(closeSignal) 

192 GRM.show() 

193 self.grmDialogFlag = True 

194 

195 self._xmltodict = GRM._xmltodict 

196 except AttributeError: 

197 MsError("All input data is not set.") 

198 

199 elif item_text == "Helps": 

200 docs_url = "https://docs.google.com/document/d/15vySQ7c6e2fnKsJtovMoA7n9PoY7gnfdoUKRowD_vYY/edit" 

201 webbrowser.open_new(docs_url) 

202 

203 except Exception as e: 

204 self.grmDialogFlag = False 

205 MsError(e) 

206 

207 def NewProjectFile(self): 

208 self._SubWatershedCount = 0 

209 self._WatchPointCount = 0 

210 self._FlowControlCount = 0 

211 self._GreenAmptCount = 0 

212 self._SoilDepthCount = 0 

213 self._LandCoverCount = 0 

214 self._RainFallCount = 0 

215 

216 # 2020-04-21 박: 추가 항목 

217 self._ChannelSettingsCount = 0 

218 

219 # New Project 시에 GMP 파일 새로 생성 

220 filename = QFileDialog.getSaveFileName( 

221 self, "select output file ", "", "*.gmp" 

222 )[0] 

223 

224 if filename: 

225 self._ProjectFile = filename 

226 _XmlCreat.Make_GMP_File(filename) 

227 if len(filename) > 0: 

228 self.set_enable() 

229 Projectfile = open(filename, "r") 

230 data = Projectfile.read() 

231 Projectfile.close() 

232 time.sleep(1) 

233 if ChFile_Exists(filename): 

234 MsInfo("[" + str(self._ProjectFile) + "]" + " GMP file created. ") 

235 else: 

236 MsError("The GMP file creation failed.") 

237 self._xmltodict = dict(parse(data)) 

238 else: 

239 return 

240 

241 def OpenProjectFile(self): 

242 # 프로젝트 파일 찾을 다이얼 로그 

243 try: 

244 # 프로젝트 파일 불러오기 

245 self.filename = QFileDialog.getOpenFileName( 

246 self, 

247 "select output file", 

248 "", 

249 "GRM Project xml files (*.gmp)", 

250 options=QFileDialog.DontUseNativeDialog, 

251 )[0] 

252 if ChFile_Exists(self.filename): 

253 self._ProjectFile = self.filename 

254 

255 # 2020-02-10 박: XML 체크할때 Landcover 데이터를 배열에 받아서 반환 함 

256 

257 _XmlCheck.Check_Gmp_xml(self._ProjectFile) 

258 time.sleep(1) 

259 self._LandCoverCount = _XmlCheck._LandCoverCount 

260 self._GreenAmptCount = _XmlCheck._GreenAmptCount 

261 self._SoilDepthCount = _XmlCheck._SoilDepthCount 

262 self._WatchPointCount = _XmlCheck._WatchPointCount 

263 self._SubWatershedCount = _XmlCheck._SubWatershedCount 

264 self._FlowControlCount = _XmlCheck._FlowControlCount 

265 self._ChannelSettingsCount = _XmlCheck._ChannelSettingsCount 

266 

267 # 프로젝트 파일 확인 후에 QtreeWidget 재설정(비활성화 메뉴 활성화) 

268 if len(self.filename) > 0: 

269 self.set_enable() 

270 

271 # 2017/09/17 프로젝트 파일(XML)을 그냥 일반 문서 처럼 읽어옴 

272 Projectfile = open(self.filename, "r") 

273 data = Projectfile.read() 

274 Projectfile.close() 

275 

276 # 읽어온 파일 내용(XML)을 dictionary 로 변경 

277 self._xmltodict = dict(parse(data)) 

278 

279 # dictionary 값을 받아서 레이어 목록을 Qgis 에 올림 

280 if ( 

281 self._xmltodict["GRMProject"]["ProjectSettings"]["DomainFile"] 

282 is not None 

283 ): 

284 self.AddlayerQGIS( 

285 self._xmltodict["GRMProject"]["ProjectSettings"]["DomainFile"] 

286 ) 

287 

288 if ( 

289 self._xmltodict["GRMProject"]["ProjectSettings"]["SlopeFile"] 

290 is not None 

291 ): 

292 self.AddlayerQGIS( 

293 self._xmltodict["GRMProject"]["ProjectSettings"]["SlopeFile"] 

294 ) 

295 

296 if ( 

297 self._xmltodict["GRMProject"]["ProjectSettings"][ 

298 "FlowDirectionFile" 

299 ] 

300 is not None 

301 ): 

302 self.AddlayerQGIS( 

303 self._xmltodict["GRMProject"]["ProjectSettings"][ 

304 "FlowDirectionFile" 

305 ] 

306 ) 

307 

308 if ( 

309 self._xmltodict["GRMProject"]["ProjectSettings"]["FlowAccumFile"] 

310 is not None 

311 ): 

312 self.AddlayerQGIS( 

313 self._xmltodict["GRMProject"]["ProjectSettings"][ 

314 "FlowAccumFile" 

315 ] 

316 ) 

317 

318 if ( 

319 self._xmltodict["GRMProject"]["ProjectSettings"]["StreamFile"] 

320 is not None 

321 ): 

322 self.AddlayerQGIS( 

323 self._xmltodict["GRMProject"]["ProjectSettings"]["StreamFile"] 

324 ) 

325 

326 if ( 

327 self._xmltodict["GRMProject"]["ProjectSettings"]["LandCoverFile"] 

328 is not None 

329 ): 

330 self.AddlayerQGIS( 

331 self._xmltodict["GRMProject"]["ProjectSettings"][ 

332 "LandCoverFile" 

333 ] 

334 ) 

335 

336 if ( 

337 self._xmltodict["GRMProject"]["ProjectSettings"]["SoilDepthFile"] 

338 is not None 

339 ): 

340 self.AddlayerQGIS( 

341 self._xmltodict["GRMProject"]["ProjectSettings"][ 

342 "SoilDepthFile" 

343 ] 

344 ) 

345 

346 if ( 

347 self._xmltodict["GRMProject"]["ProjectSettings"]["SoilTextureFile"] 

348 is not None 

349 ): 

350 self.AddlayerQGIS( 

351 self._xmltodict["GRMProject"]["ProjectSettings"][ 

352 "SoilTextureFile" 

353 ] 

354 ) 

355 

356 # 현재 열은 프로젝트 파일 경로와 GMP 내부 프로젝트 파일 경로 동기화 

357 self._xmltodict["GRMProject"]["ProjectSettings"][ 

358 "ProjectFile" 

359 ] = self._ProjectFile 

360 except Exception as wa: 

361 MsError(wa) 

362 

363 def SaveProjectFile(self): 

364 DictoXml = unparse(self._xmltodict) 

365 fw = open(self._ProjectFile, "w+") 

366 fw.write(DictoXml) 

367 fw.close() 

368 

369 # 2020-02-10 박: XML 체크할때 Landcover 데이터를 배열에 받아서 반환 함 

370 _XmlCheck.Check_Gmp_xml(self._ProjectFile) 

371 time.sleep(1) 

372 self._LandCoverCount = _XmlCheck._LandCoverCount 

373 self._GreenAmptCount = _XmlCheck._GreenAmptCount 

374 self._SoilDepthCount = _XmlCheck._SoilDepthCount 

375 self._WatchPointCount = _XmlCheck._WatchPointCount 

376 self._SubWatershedCount = _XmlCheck._SubWatershedCount 

377 self._FlowControlCount = _XmlCheck._FlowControlCount 

378 self._ChannelSettingsCount = _XmlCheck._ChannelSettingsCount 

379 

380 ## 2017/09/17 프로젝트 파일(XML)을 그냥 일반 문서 처럼 읽어옴 

381 Projectfile = open(self._ProjectFile, "r") 

382 data = Projectfile.read() 

383 Projectfile.close() 

384 

385 # 읽어온 파일 내용(XML)을 dictionary 로 변경 

386 self._xmltodict = dict(parse(data)) 

387 MsInfo("[" + self._ProjectFile + "] " + "was saved. ") 

388 

389 def SaveASProjectFile(self): 

390 SaveAsPath = QFileDialog.getSaveFileName( 

391 self, "select output file ", "", "*.gmp" 

392 )[0] 

393 if SaveAsPath == "": 

394 MsInfo("[" + str(self._ProjectFile) + "]" + " Save was cancelled. ") 

395 return 

396 else: 

397 self._xmltodict["GRMProject"]["ProjectSettings"]["ProjectFile"] = SaveAsPath 

398 self._ProjectFile = SaveAsPath 

399 DictoXml = unparse(self._xmltodict) 

400 fw = open(self._ProjectFile, "w+") 

401 fw.write(DictoXml) 

402 fw.close() 

403 # self.indent(self._ProjectFile) 

404 time.sleep(1) 

405 # 2020-02-10 박: XML 체크할때 Landcover 데이터를 배열에 받아서 반환 함 

406 _XmlCheck.Check_Gmp_xml(self._ProjectFile) 

407 

408 self._LandCoverCount = _XmlCheck._LandCoverCount 

409 self._GreenAmptCount = _XmlCheck._GreenAmptCount 

410 self._SoilDepthCount = _XmlCheck._SoilDepthCount 

411 self._WatchPointCount = _XmlCheck._WatchPointCount 

412 self._SubWatershedCount = _XmlCheck._SubWatershedCount 

413 self._GreenAmptCount = _XmlCheck._GreenAmptCount 

414 self._SoilDepthCount = _XmlCheck._SoilDepthCount 

415 self._LandCoverCount = _XmlCheck._LandCoverCount 

416 self._FlowControlCount = _XmlCheck._FlowControlCount 

417 self._ChannelSettingsCount = _XmlCheck._ChannelSettingsCount 

418 

419 ## 2017/09/17 프로젝트 파일(XML)을 그냥 일반 문서 처럼 읽어옴 

420 Projectfile = open(self._ProjectFile, "r") 

421 data = Projectfile.read() 

422 Projectfile.close() 

423 # 읽어온 파일 내용(XML)을 dictionary 로 변경 

424 self._xmltodict = dict(parse(data)) 

425 

426 MsInfo("[" + self._ProjectFile + "]" + " was saved. ") 

427 

428 # gis에 올리기 

429 def AddlayerQGIS(self, path): 

430 if (os.path.isfile(path)) and (self.CheckLayer(path)): 

431 fileInfo = QFileInfo(path) 

432 baseName = fileInfo.baseName() 

433 layer = QgsRasterLayer(path, baseName, "gdal") 

434 QgsProject.instance().addMapLayer(layer) 

435 

436 # 레이어가 Qgis에 올라와 있는지 확인 (현재 QGIS에 올라온 레이어면 올리지 않음) 

437 def CheckLayer(self, layerpath): 

438 for lyr in QgsProject.instance().mapLayers().values(): 

439 if lyr.dataProvider().dataSourceUri().upper() == layerpath.upper(): 

440 return False 

441 return True 

442 

443 # tree widget 초기화 시키고 다시 메뉴 셋팅(프로젝트 파일 로드후 비활성화 메뉴 활성화로 변경) 

444 def set_enable(self): 

445 self.__set_enable_widget(self.treeWidget.invisibleRootItem()) 

446 

447 def __set_enable_widget(self, item: QTreeWidgetItem): 

448 item.setDisabled(False) 

449 for i in range(item.childCount()): 

450 self.__set_enable_widget(item.child(i)) 

451 

452 

453if __name__ == "__main__": 

454 import os 

455 

456 os.environ[ 

457 "QT_QPA_PLATFORM_PLUGIN_PATH" 

458 ] = r"C:\Program Files\QGIS 3.10\apps\Qt5\plugins" 

459 

460 import sys 

461 

462 from qgis.PyQt.QtWidgets import QApplication 

463 

464 from grm.lib.Util import MsTitle 

465 

466 MsTitle("GRM Dock Widget") 

467 

468 app = QApplication(sys.argv) 

469 w = GRMDockWidget() 

470 w.show() 

471 sys.exit(app.exec_())