Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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.Weather_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, ["Weather 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, ["Download the GRM model manual"]) 

113 QTreeWidgetItem(help_item, ["QGRM user's manual"]) 

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

115 

116 self.grmDialogFlag = False 

117 

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

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

120 

121 def OnDoubleClick(self, select_item: QTreeWidgetItem): 

122 try: 

123 # 프로젝트 파일 오픈 

124 item_text = select_item.text(0) 

125 is_enable = not select_item.isDisabled() 

126 

127 if item_text == "New Project": 

128 self.NewProjectFile() 

129 

130 elif item_text == "Open Project": 

131 self.OpenProjectFile() 

132 

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

134 self.SaveProjectFile() 

135 

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

137 self.SaveASProjectFile() 

138 

139 elif item_text == "Watershed" and is_enable: 

140 if self.grmDialogFlag == True: 

141 self._grmDialogFlag = 1 

142 elif self.grmDialogFlag == False: 

143 self._grmDialogFlag = 0 

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

145 Watershed.exec_() 

146 self._xmltodict = Watershed._xmltodict 

147 self._grmDialogFlag = Watershed._grmDialogFlag 

148 

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

150 if self.grmDialogFlag == True: 

151 self._grmDialogFlag = 1 

152 if self.grmDialogFlag == False: 

153 self._grmDialogFlag = 0 

154 LandCover = LandCoverDialog( 

155 self._xmltodict, 

156 self._LandCoverCount, 

157 self._GreenAmptCount, 

158 self._SoilDepthCount, 

159 self._grmDialogFlag, 

160 ) 

161 LandCover.exec_() 

162 self._xmltodict = LandCover._xmltodict 

163 self._LandCoverCount = LandCover._LandCoverCount 

164 self._GreenAmptCount = LandCover._GreenAmptCount 

165 self._SoilDepthCount = LandCover._SoilDepthCount 

166 self._grmDialogFlag = LandCover._grmDialogFlag 

167 

168 elif item_text == "Weather Data" and is_enable: 

169 ClimateData = ClimateDataDialog(self._xmltodict) 

170 ClimateData.exec_() 

171 

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

173 try: 

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

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

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

177 def closeSignal(): 

178 self.grmDialogFlag = False 

179 

180 if not self.grmDialogFlag: 

181 GRM = GRMDialog( 

182 self._ProjectFile, 

183 self._xmltodict, 

184 self._WatchPointCount, 

185 self._SubWatershedCount, 

186 self._GreenAmptCount, 

187 self._SoilDepthCount, 

188 self._LandCoverCount, 

189 self._FlowControlCount, 

190 self._ChannelSettingsCount, 

191 ) 

192 

193 GRM.closeDialogEvent.connect(closeSignal) 

194 GRM.show() 

195 self.grmDialogFlag = True 

196 

197 self._xmltodict = GRM._xmltodict 

198 except AttributeError: 

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

200 

201 elif item_text == "QGRM user's manual": 

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

203 webbrowser.open_new(docs_url) 

204 

205 elif item_text == "Download the GRM model manual": 

206 docs_url = "https://github.com/floodmodel/GRM/tree/master/DownloadStableVersion" 

207 webbrowser.open_new(docs_url) 

208 

209 except Exception as e: 

210 self.grmDialogFlag = False 

211 MsError(e) 

212 

213 def NewProjectFile(self): 

214 self._SubWatershedCount = 0 

215 self._WatchPointCount = 0 

216 self._FlowControlCount = 0 

217 self._GreenAmptCount = 0 

218 self._SoilDepthCount = 0 

219 self._LandCoverCount = 0 

220 self._RainFallCount = 0 

221 

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

223 self._ChannelSettingsCount = 0 

224 

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

226 filename = QFileDialog.getSaveFileName(self, "New project", "", "*.gmp")[0] 

227 

228 if filename: 

229 self._ProjectFile = filename 

230 _XmlCreat.Make_GMP_File(filename) 

231 if len(filename) > 0: 

232 self.set_enable() 

233 Projectfile = open(filename, "r") 

234 data = Projectfile.read() 

235 Projectfile.close() 

236 time.sleep(1) 

237 if ChFile_Exists(filename): 

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

239 else: 

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

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

242 else: 

243 return 

244 

245 def OpenProjectFile(self): 

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

247 try: 

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

249 self.filename = QFileDialog.getOpenFileName( 

250 self, 

251 "Open project", 

252 "", 

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

254 options=QFileDialog.DontUseNativeDialog, 

255 )[0] 

256 if ChFile_Exists(self.filename): 

257 self._ProjectFile = self.filename 

258 

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

260 

261 _XmlCheck.Check_Gmp_xml(self._ProjectFile) 

262 time.sleep(1) 

263 self._LandCoverCount = _XmlCheck._LandCoverCount 

264 self._GreenAmptCount = _XmlCheck._GreenAmptCount 

265 self._SoilDepthCount = _XmlCheck._SoilDepthCount 

266 self._WatchPointCount = _XmlCheck._WatchPointCount 

267 self._SubWatershedCount = _XmlCheck._SubWatershedCount 

268 self._FlowControlCount = _XmlCheck._FlowControlCount 

269 self._ChannelSettingsCount = _XmlCheck._ChannelSettingsCount 

270 

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

272 if len(self.filename) > 0: 

273 self.set_enable() 

274 

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

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

277 data = Projectfile.read() 

278 Projectfile.close() 

279 

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

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

282 

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

284 if ( 

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

286 is not None 

287 ): 

288 self.AddlayerQGIS( 

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

290 ) 

291 

292 if ( 

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

294 is not None 

295 ): 

296 self.AddlayerQGIS( 

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

298 ) 

299 

300 if ( 

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

302 "FlowDirectionFile" 

303 ] 

304 is not None 

305 ): 

306 self.AddlayerQGIS( 

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

308 "FlowDirectionFile" 

309 ] 

310 ) 

311 

312 if ( 

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

314 is not None 

315 ): 

316 self.AddlayerQGIS( 

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

318 "FlowAccumFile" 

319 ] 

320 ) 

321 

322 if ( 

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

324 is not None 

325 ): 

326 self.AddlayerQGIS( 

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

328 ) 

329 

330 if ( 

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

332 is not None 

333 ): 

334 self.AddlayerQGIS( 

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

336 "LandCoverFile" 

337 ] 

338 ) 

339 

340 if ( 

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

342 is not None 

343 ): 

344 self.AddlayerQGIS( 

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

346 "SoilDepthFile" 

347 ] 

348 ) 

349 

350 if ( 

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

352 is not None 

353 ): 

354 self.AddlayerQGIS( 

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

356 "SoilTextureFile" 

357 ] 

358 ) 

359 

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

361 except Exception as wa: 

362 MsError(wa) 

363 

364 def SaveProjectFile(self): 

365 DictoXml = unparse(self._xmltodict) 

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

367 fw.write(DictoXml) 

368 fw.close() 

369 

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

371 _XmlCheck.Check_Gmp_xml(self._ProjectFile) 

372 time.sleep(1) 

373 self._LandCoverCount = _XmlCheck._LandCoverCount 

374 self._GreenAmptCount = _XmlCheck._GreenAmptCount 

375 self._SoilDepthCount = _XmlCheck._SoilDepthCount 

376 self._WatchPointCount = _XmlCheck._WatchPointCount 

377 self._SubWatershedCount = _XmlCheck._SubWatershedCount 

378 self._FlowControlCount = _XmlCheck._FlowControlCount 

379 self._ChannelSettingsCount = _XmlCheck._ChannelSettingsCount 

380 

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

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

383 data = Projectfile.read() 

384 Projectfile.close() 

385 

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

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

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

389 

390 def SaveASProjectFile(self): 

391 SaveAsPath = QFileDialog.getSaveFileName(self, "Save as project", "", "*.gmp")[ 

392 0 

393 ] 

394 if SaveAsPath == "": 

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

396 return 

397 else: 

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_())