change to plugin
15
ReadMe.md
@ -9,4 +9,17 @@ Python3 + PyQt + QGIS?
|
||||
pyqt qgis gdal numpy
|
||||
|
||||
# 打包方式
|
||||
comming soon
|
||||
comming soon
|
||||
|
||||
# 功能
|
||||
|
||||
1. 证书检查与生成
|
||||
1. 基于MAC地址与过期时间进行证书生成,启动时检查证书,过期则退出
|
||||
2. 项目管理
|
||||
1. 以项目为单位进行数据管理与生产
|
||||
2. 提供项目保存与导入功能
|
||||
3. 提供多种格式的栅格数据导入(TIF、PNG、BMP、JPG)等
|
||||
4. 提供矢量数据导入
|
||||
3. 基本工具
|
||||
1. 双视图同步浏览
|
||||
2. 格网展示
|
||||
|
@ -1,341 +0,0 @@
|
||||
import logging
|
||||
import os
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
from PyQt5.QtWidgets import QAction, QActionGroup, QLabel, QFileDialog
|
||||
from gui.about import AboutDialog
|
||||
from gui.project import Create
|
||||
from utils.project import Project
|
||||
|
||||
class ActionManager(QtCore.QObject):
|
||||
|
||||
def __init__(self,
|
||||
double_map,
|
||||
layer_tree,
|
||||
follow_box,
|
||||
result_box,
|
||||
message_box,
|
||||
parent=None):
|
||||
super().__init__(parent)
|
||||
self.w_parent = parent
|
||||
self.actions = {}
|
||||
self.action_groups = {}
|
||||
self.action_group_actions = {}
|
||||
|
||||
self.double_map = double_map
|
||||
self.layer_tree = layer_tree
|
||||
self.follow_box = follow_box
|
||||
self.result_box = result_box
|
||||
self.message_box = message_box
|
||||
|
||||
self.allways_enable = []
|
||||
self.init_enable = []
|
||||
self.dataload_enable = []
|
||||
|
||||
self.toolbar = None
|
||||
self.menubar = None
|
||||
self.status_bar = None
|
||||
|
||||
def set_menus(self, menubar):
|
||||
self.menubar = menubar
|
||||
self.file_menu = menubar.addMenu('&文件')
|
||||
# self.view_menu = menubar.addMenu('&视图')
|
||||
self.basic_menu = menubar.addMenu('&基本工具')
|
||||
self.preop_menu = menubar.addMenu('&预处理')
|
||||
self.change_detection_menu = menubar.addMenu('&变化检测')
|
||||
self.special_chagne_detec_menu = menubar.addMenu('&专题变化检测')
|
||||
self.postop_menu = menubar.addMenu('&后处理')
|
||||
self.eval_menu = menubar.addMenu('&评估')
|
||||
self.help_menu = menubar.addMenu('&帮助')
|
||||
|
||||
def set_toolbar(self, toolbar):
|
||||
self.toolbar = toolbar
|
||||
self.toolbar.setIconSize(QtCore.QSize(24, 24))
|
||||
|
||||
def set_status_bar(self, status_bar):
|
||||
self.status_bar = status_bar
|
||||
|
||||
def set_actions(self):
|
||||
'''
|
||||
File menu
|
||||
'''
|
||||
project_create = self.add_action(QAction('&工程创建', self.w_parent), 'File')
|
||||
project_open = self.add_action(QAction('&打开工程', self.w_parent), 'File')
|
||||
project_save = self.add_action(QAction('&保存工程', self.w_parent), 'File')
|
||||
data_load = self.add_action(QAction('&数据加载', self.w_parent), 'File')
|
||||
view_setting = self.add_action(QAction('&界面定制', self.w_parent), 'File')
|
||||
exit_app = self.add_action(QAction('&退出', self.w_parent), 'File')
|
||||
project_create.triggered.connect(self.project_create)
|
||||
project_open.triggered.connect(self.project_open)
|
||||
project_save.triggered.connect(self.project_save)
|
||||
data_load.triggered.connect(self.data_load)
|
||||
view_setting.triggered.connect(self.view_setting)
|
||||
exit_app.triggered.connect(self.w_parent.close)
|
||||
|
||||
self.allways_enable.append(project_create, project_open, exit_app, view_setting)
|
||||
self.init_enable.append(project_save, data_load)
|
||||
|
||||
self.file_menu.addAction(project_create)
|
||||
self.file_menu.addAction(project_open)
|
||||
self.file_menu.addAction(project_save)
|
||||
self.file_menu.addAction(data_load)
|
||||
self.file_menu.addAction(view_setting)
|
||||
self.file_menu.addAction(exit_app)
|
||||
|
||||
if self.toolbar is not None:
|
||||
self.toolbar.addAction(project_create)
|
||||
self.toolbar.addAction(project_open)
|
||||
self.toolbar.addAction(project_save)
|
||||
|
||||
'''
|
||||
Basic menu
|
||||
'''
|
||||
grid_line = self.add_action(QAction('&网格线', self.w_parent), 'Basic')
|
||||
grid_line.setCheckable(True)
|
||||
grid_line.setChecked(True)
|
||||
|
||||
zomm_in = self.add_action(QAction('&放大', self.w_parent), 'Basic')
|
||||
zomm_out = self.add_action(QAction('&缩小', self.w_parent), 'Basic')
|
||||
pan = self.add_action(QAction('&漫游', self.w_parent), 'Basic')
|
||||
locate = self.add_action(QAction('&定位', self.w_parent), 'Basic')
|
||||
|
||||
|
||||
|
||||
self.basic_menu.addAction(grid_line)
|
||||
self.basic_menu.addAction(zomm_in)
|
||||
self.basic_menu.addAction(zomm_out)
|
||||
self.basic_menu.addAction(pan)
|
||||
self.basic_menu.addAction(locate)
|
||||
|
||||
'''
|
||||
Preop menu
|
||||
'''
|
||||
morphology_filter = self.add_action(QAction('&形态学滤波', self.w_parent), 'filter')
|
||||
lee_filter = self.add_action(QAction('&Lee滤波', self.w_parent), 'filter')
|
||||
auto_filter = self.add_action(QAction('&自适应滤波-自主', self.w_parent), 'filter')
|
||||
auto_filter_no_params = self.add_action(QAction('自动滤波(无参自适应滤波)-自主', self.w_parent), 'filter')
|
||||
double_filter = self.add_action(QAction('&双边滤波', self.w_parent), 'filter')
|
||||
align_action = self.add_action(QAction('&配准', self.w_parent), 'align')
|
||||
filter_action_group = self.get_action_group('filter')
|
||||
|
||||
filter_menu = self.preop_menu.addMenu('&滤波')
|
||||
for action in filter_action_group.actions():
|
||||
filter_menu.addAction(action)
|
||||
|
||||
# self.preop_menu.addActionGroup(filter_action_group)
|
||||
self.preop_menu.addAction(align_action)
|
||||
|
||||
if self.toolbar is not None:
|
||||
self.toolbar.addAction(morphology_filter)
|
||||
self.toolbar.addAction(lee_filter)
|
||||
self.toolbar.addAction(auto_filter)
|
||||
self.toolbar.addAction(auto_filter_no_params)
|
||||
self.toolbar.addAction(double_filter)
|
||||
|
||||
'''
|
||||
Change detection menu
|
||||
'''
|
||||
diff_method = self.add_action(QAction('&差分法', self.w_parent), 'unsuper_change_detection')
|
||||
log_diff = self.add_action(QAction('&对数差分法', self.w_parent), 'unsuper_change_detection')
|
||||
lsts_ = self.add_action(QAction('&LSTS法', self.w_parent), 'unsuper_change_detection')
|
||||
lhba = self.add_action(QAction('&LHBA法', self.w_parent), 'unsuper_change_detection')
|
||||
aht = self.add_action(QAction('&AHT法', self.w_parent), 'unsuper_change_detection')
|
||||
kpvd = self.add_action(QAction('&KPVD法', self.w_parent), 'unsuper_change_detection')
|
||||
mohd = self.add_action(QAction('&MOHD法', self.w_parent), 'unsuper_change_detection')
|
||||
sh = self.add_action(QAction('&SH法', self.w_parent), 'unsuper_change_detection')
|
||||
cva = self.add_action(QAction('&CVA法', self.w_parent), 'unsuper_change_detection')
|
||||
mls = self.add_action(QAction('&MLS法', self.w_parent), 'unsuper_change_detection')
|
||||
pca_kmean = self.add_action(QAction('&PCA-KMean法', self.w_parent), 'unsuper_change_detection')
|
||||
semi_fcm = self.add_action(QAction('&Semi-FCM法', self.w_parent), 'unsuper_change_detection')
|
||||
mls_svm = self.add_action(QAction('&MLS-SVM法', self.w_parent), 'unsuper_change_detection')
|
||||
cva_fcm = self.add_action(QAction('&CVA-FCM法', self.w_parent), 'unsuper_change_detection')
|
||||
cva_emgmm = self.add_action(QAction('&CVA-EMGMM法', self.w_parent), 'unsuper_change_detection')
|
||||
gwdm = self.add_action(QAction('&GWDM法', self.w_parent), 'unsuper_change_detection')
|
||||
|
||||
mrf = self.add_action(QAction('&MRF法', self.w_parent), 'super_change_detection')
|
||||
mad = self.add_action(QAction('&MAD法', self.w_parent), 'super_change_detection')
|
||||
irmad = self.add_action(QAction('&IRMAD法', self.w_parent), 'super_change_detection')
|
||||
|
||||
dcva = self.add_action(QAction('&DCVA法', self.w_parent), 'ai_change_detection')
|
||||
dp_fcn = self.add_action(QAction('&DP-FCN法', self.w_parent), 'ai_change_detection')
|
||||
rcnn = self.add_action(QAction('&RCNN法', self.w_parent), 'ai_change_detection')
|
||||
|
||||
if self.toolbar is not None:
|
||||
self.toolbar.addAction(diff_method)
|
||||
self.toolbar.addAction(log_diff)
|
||||
self.toolbar.addAction(lsts_)
|
||||
self.toolbar.addAction(lhba)
|
||||
|
||||
|
||||
unsuper_change_detection = self.get_action_group('unsuper_change_detection')
|
||||
super_change_detection = self.get_action_group('super_change_detection')
|
||||
ai_change_detection = self.get_action_group('ai_change_detection')
|
||||
unsuper_menu = self.change_detection_menu.addMenu('&非监督')
|
||||
for action in unsuper_change_detection.actions():
|
||||
unsuper_menu.addAction(action)
|
||||
super_menu = self.change_detection_menu.addMenu('&监督')
|
||||
for action in super_change_detection.actions():
|
||||
super_menu.addAction(action)
|
||||
ai_menu = self.change_detection_menu.addMenu('&AI')
|
||||
for action in ai_change_detection.actions():
|
||||
ai_menu.addAction(action)
|
||||
|
||||
# self.change_detection_menu.addActionGroup(super_change_detection)
|
||||
# self.change_detection_menu.addActionGroup(ai_change_detection)
|
||||
|
||||
'''
|
||||
Special change detection menu
|
||||
'''
|
||||
|
||||
water_change = self.add_action(QAction('&水体变化', self.w_parent), 'special_change_detection')
|
||||
vegetation_change = self.add_action(QAction('&植被变化', self.w_parent), 'special_change_detection')
|
||||
build_change = self.add_action(QAction('&房屋变化', self.w_parent), 'special_change_detection')
|
||||
|
||||
self.special_chagne_detec_menu.addAction(water_change)
|
||||
self.special_chagne_detec_menu.addAction(vegetation_change)
|
||||
self.special_chagne_detec_menu.addAction(build_change)
|
||||
|
||||
'''
|
||||
Postop menu
|
||||
'''
|
||||
slide_window = self.add_action(QAction('&滑动窗口法', self.w_parent), 'noise_reduction')
|
||||
density = self.add_action(QAction('&密度法', self.w_parent), 'noise_reduction')
|
||||
|
||||
raster_export = self.add_action(QAction('&二值栅格数据导出', self.w_parent), 'export')
|
||||
txt_pos_export = self.add_action(QAction('&兼容ArcMap的坐标Txt文件', self.w_parent), 'export')
|
||||
render_export = self.add_action(QAction('&渲染图像导出', self.w_parent), 'export')
|
||||
|
||||
noise_reduction = self.get_action_group('noise_reduction')
|
||||
export = self.get_action_group('export')
|
||||
|
||||
noise_reduction_menu = self.postop_menu.addMenu('&噪声抑制')
|
||||
for action in noise_reduction.actions():
|
||||
noise_reduction_menu.addAction(action)
|
||||
export_menu = self.postop_menu.addMenu('&导出')
|
||||
for action in export.actions():
|
||||
export_menu.addAction(action)
|
||||
|
||||
# self.postop_menu.addActionGroup(noise_reduction)
|
||||
# self.postop_menu.addActionGroup(export)
|
||||
|
||||
'''
|
||||
Evaluation menu
|
||||
'''
|
||||
|
||||
evaluation = self.add_action(QAction('&评估', self.w_parent), 'evaluation')
|
||||
self.eval_menu.addAction(evaluation)
|
||||
|
||||
'''
|
||||
Help menu
|
||||
'''
|
||||
about = self.add_action(QAction('&关于', self.w_parent), 'about')
|
||||
about.triggered.connect(lambda : AboutDialog(self.w_parent).show())
|
||||
self.help_menu.addAction(about)
|
||||
|
||||
self.message_box.info('Menu init finished')
|
||||
self.message_box.info(self.actions.keys())
|
||||
for group in self.action_groups.keys():
|
||||
self.message_box.info('%s:' % (group))
|
||||
for action in self.action_groups[group].actions():
|
||||
action.setEnabled(False)
|
||||
self.message_box.info('\t%s' % (action.text()))
|
||||
|
||||
'''
|
||||
Enabled actions
|
||||
'''
|
||||
about.setEnabled(True)
|
||||
project_create.setEnabled(True)
|
||||
project_open.setEnabled(True)
|
||||
|
||||
Project().project_init.connect(self.project_init)
|
||||
|
||||
if self.status_bar is not None:
|
||||
corr_widget = QLabel(self.status_bar)
|
||||
# corr_widget.setLineWidth(200)
|
||||
corr_widget.setFixedWidth(200)
|
||||
self.status_bar.addWidget(corr_widget)
|
||||
scale_widget = QLabel(self.status_bar)
|
||||
scale_widget.setFixedWidth(200)
|
||||
self.status_bar.addWidget(scale_widget)
|
||||
self.double_map.corr_changed.connect(corr_widget.setText)
|
||||
self.double_map.scale_changed.connect(scale_widget.setText)
|
||||
|
||||
def project_create(self):
|
||||
project = Project()
|
||||
if project.is_init:
|
||||
project.save()
|
||||
|
||||
projec_create = Create(self.w_parent)
|
||||
if(projec_create.exec_()):
|
||||
project.setup(os.path.join(projec_create.file, projec_create.name + '.prj'))
|
||||
project.is_init = True
|
||||
project.cell_size = projec_create.cell_size
|
||||
|
||||
def project_init(self, state):
|
||||
self.message_box.info('Project init')
|
||||
for group in self.action_groups.keys():
|
||||
# self.message_box.info('%s:' % (group))
|
||||
for action in self.action_groups[group].actions():
|
||||
action.setEnabled(state)
|
||||
# self.message_box.info('\t%s' % (action.text()))
|
||||
|
||||
self.message_box.info('Project init finished')
|
||||
|
||||
def project_open(self):
|
||||
if Project().is_init:
|
||||
Project().save()
|
||||
|
||||
project_file = QFileDialog.getOpenFileName(self.w_parent, '打开工程', '.', '*.prj')
|
||||
if project_file[0] != '':
|
||||
Project().clear()
|
||||
Project().setup(project_file[0])
|
||||
|
||||
def project_save(self):
|
||||
if Project().is_init:
|
||||
Project().save()
|
||||
|
||||
def data_load(self):
|
||||
if Project().is_init:
|
||||
Project().save()
|
||||
|
||||
def view_setting(self):
|
||||
pass
|
||||
|
||||
|
||||
def add_action(self, action, group=None):
|
||||
if group is None:
|
||||
self.actions[action.text()] = action
|
||||
else:
|
||||
if group not in self.action_groups:
|
||||
self.action_groups[group] = QActionGroup(self.w_parent)
|
||||
self.action_groups[group].setExclusive(True)
|
||||
self.action_groups[group].addAction(action)
|
||||
self.action_group_actions[group] = action
|
||||
return action
|
||||
|
||||
def get_action(self, action_name, group_name=None):
|
||||
if action_name in self.actions:
|
||||
return self.actions[action_name]
|
||||
else:
|
||||
if group_name is None:
|
||||
return None
|
||||
else:
|
||||
if group_name not in self.action_group_actions:
|
||||
return None
|
||||
else:
|
||||
group = self.action_group_actions[group_name]
|
||||
for action in group.actions():
|
||||
if action.text() == action_name:
|
||||
return action
|
||||
return None
|
||||
|
||||
def get_action_group(self, group_name):
|
||||
return self.action_groups[group_name]
|
||||
|
||||
def get_action_group_action(self, group_name):
|
||||
return self.action_group_actions[group_name]
|
||||
|
||||
def get_action_group_actions(self, group_name):
|
||||
return self.action_group_actions[group_name].actions()
|
||||
|
||||
def get_actions(self):
|
||||
return self.actions
|
2
main.py
@ -1,4 +1,4 @@
|
||||
from mul.mulstart import MulStart
|
||||
from rscder import MulStart
|
||||
import logging
|
||||
|
||||
logging.basicConfig(level=logging.INFO, filename='log.txt', filemode='w', format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||
|
@ -1,6 +1,8 @@
|
||||
from PyQt5.QtWidgets import QDialog, QApplication, QLabel, QTextEdit, QVBoxLayout
|
||||
from PyQt5.QtCore import Qt
|
||||
from rscder.plugins.basic import BasicPlugin
|
||||
|
||||
from PyQt5.QtWidgets import QDialog, QAction, QApplication, QLabel, QTextEdit, QVBoxLayout
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QIcon
|
||||
|
||||
class AboutDialog(QDialog):
|
||||
def __init__(self, parent=None):
|
||||
@ -40,3 +42,17 @@ class AboutDialog(QDialog):
|
||||
self.layout.addWidget(self.label4)
|
||||
self.layout.addWidget(self.text)
|
||||
self.setLayout(self.layout)
|
||||
|
||||
|
||||
class AboutPlugin(BasicPlugin):
|
||||
|
||||
def set_action(self):
|
||||
menu = self.ctx['help_menu']
|
||||
action = QAction('&关于', self.ctx['menubar'])
|
||||
action.triggered.connect(self.on_about)
|
||||
|
||||
menu.addAction(action)
|
||||
|
||||
def on_about(self):
|
||||
dialog = AboutDialog(self.ctx['main_window'])
|
||||
dialog.show()
|
8
plugins/basic_change/main.py
Normal file
@ -0,0 +1,8 @@
|
||||
from rscder.plugins.basic import BasicPlugin
|
||||
|
||||
class BasicMethod(BasicPlugin):
|
||||
|
||||
def set_action(self):
|
||||
menubar = self.ctx['menubar']
|
||||
|
||||
|
1
rscder/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .mul.mulstart import MulStart
|
382
rscder/gui/actions.py
Normal file
@ -0,0 +1,382 @@
|
||||
import logging
|
||||
import os
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
from PyQt5.QtWidgets import QAction, QActionGroup, QLabel, QFileDialog
|
||||
from rscder.gui.project import Create
|
||||
from rscder.utils.project import Project
|
||||
from rscder.gui.plugins import PluginDialog
|
||||
class ActionManager(QtCore.QObject):
|
||||
|
||||
def __init__(self,
|
||||
double_map,
|
||||
layer_tree,
|
||||
follow_box,
|
||||
result_box,
|
||||
message_box,
|
||||
parent=None):
|
||||
super().__init__(parent)
|
||||
self.w_parent = parent
|
||||
self.actions = {}
|
||||
self.action_groups = {}
|
||||
self.action_group_actions = {}
|
||||
|
||||
self.double_map = double_map
|
||||
self.layer_tree = layer_tree
|
||||
self.follow_box = follow_box
|
||||
self.result_box = result_box
|
||||
self.message_box = message_box
|
||||
|
||||
self.allways_enable = []
|
||||
self.init_enable = []
|
||||
self.dataload_enable = []
|
||||
|
||||
self.toolbar = None
|
||||
self.menubar = None
|
||||
self.status_bar = None
|
||||
|
||||
def set_menus(self, menubar):
|
||||
self.menubar = menubar
|
||||
self.file_menu = menubar.addMenu('&文件')
|
||||
self.basic_menu = menubar.addMenu('&基本工具')
|
||||
self.change_detection_menu = menubar.addMenu('&通用变化检测')
|
||||
self.special_chagne_detec_menu = menubar.addMenu('&专题变化检测')
|
||||
self.seg_chagne_detec_menu = menubar.addMenu('&分类后变化检测')
|
||||
self.postop_menu = menubar.addMenu('&检测后处理')
|
||||
self.view_menu = menubar.addMenu('&视图')
|
||||
self.plugin_menu = menubar.addMenu('&插件')
|
||||
self.help_menu = menubar.addMenu('&帮助')
|
||||
|
||||
|
||||
def set_toolbar(self, toolbar):
|
||||
self.toolbar = toolbar
|
||||
self.toolbar.setIconSize(QtCore.QSize(24, 24))
|
||||
|
||||
def set_status_bar(self, status_bar):
|
||||
self.status_bar = status_bar
|
||||
|
||||
def set_actions(self):
|
||||
'''
|
||||
File menu
|
||||
'''
|
||||
project_create = self.add_action(QAction('&工程创建', self.w_parent), 'File')
|
||||
project_open = self.add_action(QAction('&打开工程', self.w_parent), 'File')
|
||||
project_save = self.add_action(QAction('&保存工程', self.w_parent), 'File')
|
||||
data_load = self.add_action(QAction('&数据加载', self.w_parent), 'File')
|
||||
view_setting = self.add_action(QAction('&界面定制', self.w_parent), 'File')
|
||||
exit_app = self.add_action(QAction('&退出', self.w_parent), 'File')
|
||||
project_create.triggered.connect(self.project_create)
|
||||
project_open.triggered.connect(self.project_open)
|
||||
project_save.triggered.connect(self.project_save)
|
||||
data_load.triggered.connect(self.data_load)
|
||||
view_setting.triggered.connect(self.view_setting)
|
||||
exit_app.triggered.connect(self.w_parent.close)
|
||||
|
||||
self.allways_enable.extend([project_create, project_open, exit_app, view_setting])
|
||||
self.init_enable.extend([project_save, data_load])
|
||||
|
||||
self.file_menu.addAction(project_create)
|
||||
self.file_menu.addAction(project_open)
|
||||
self.file_menu.addAction(project_save)
|
||||
self.file_menu.addAction(data_load)
|
||||
self.file_menu.addAction(view_setting)
|
||||
self.file_menu.addAction(exit_app)
|
||||
|
||||
if self.toolbar is not None:
|
||||
self.toolbar.addAction(project_create)
|
||||
self.toolbar.addAction(project_open)
|
||||
self.toolbar.addAction(project_save)
|
||||
|
||||
'''
|
||||
Basic menu
|
||||
'''
|
||||
grid_line = self.add_action(QAction('&网格线', self.w_parent), 'Basic Line')
|
||||
grid_line.setCheckable(True)
|
||||
grid_line.setChecked(True)
|
||||
|
||||
zomm_in = self.add_action(QAction('&放大', self.w_parent), 'Basic')
|
||||
zomm_out = self.add_action(QAction('&缩小', self.w_parent), 'Basic')
|
||||
pan = self.add_action(QAction('&漫游', self.w_parent), 'Basic')
|
||||
locate = self.add_action(QAction('&定位', self.w_parent), 'Basic')
|
||||
|
||||
pan.setCheckable(True)
|
||||
pan.setChecked(True)
|
||||
zomm_out.setCheckable(True)
|
||||
zomm_out.setChecked(False)
|
||||
zomm_in.setCheckable(True)
|
||||
zomm_in.setChecked(False)
|
||||
|
||||
self.double_map.connect_map_tool(pan, zomm_in, zomm_out)
|
||||
self.double_map.connect_grid_show(grid_line)
|
||||
|
||||
self.view_menu.addAction(grid_line)
|
||||
self.view_menu.addSeparator()
|
||||
self.view_menu.addAction(pan)
|
||||
self.view_menu.addAction(zomm_in)
|
||||
self.view_menu.addAction(zomm_out)
|
||||
self.view_menu.addAction(locate)
|
||||
|
||||
'''
|
||||
Plugin menu
|
||||
'''
|
||||
plugin_list = self.add_action(QAction('&插件列表', self.w_parent), 'Plugin')
|
||||
plugin_list.triggered.connect(self.plugin_list)
|
||||
|
||||
self.plugin_menu.addAction(plugin_list)
|
||||
# morphology_filter = self.add_action(QAction('&形态学滤波', self.w_parent), 'filter')
|
||||
# lee_filter = self.add_action(QAction('&Lee滤波', self.w_parent), 'filter')
|
||||
# auto_filter = self.add_action(QAction('&自适应滤波-自主', self.w_parent), 'filter')
|
||||
# auto_filter_no_params = self.add_action(QAction('自动滤波(无参自适应滤波)-自主', self.w_parent), 'filter')
|
||||
# double_filter = self.add_action(QAction('&双边滤波', self.w_parent), 'filter')
|
||||
|
||||
# filter_action_group = self.get_action_group('filter')
|
||||
|
||||
# filter_menu = self.basic_menu.addMenu('&滤波处理')
|
||||
# for action in filter_action_group.actions():
|
||||
# filter_menu.addAction(action)
|
||||
|
||||
# rgb2rgb = self.add_action(QAction('&光学-影像', self.w_parent), 'align')
|
||||
# sar2sar = self.add_action(QAction('&SAR-影像', self.w_parent), 'align')
|
||||
# multi_source = self.add_action(QAction('&多源影像', self.w_parent), 'align')
|
||||
|
||||
# align_menu = self.basic_menu.addMenu('&图像配准')
|
||||
# align_menu.addAction(rgb2rgb)
|
||||
# align_menu.addAction(sar2sar)
|
||||
# align_menu.addAction(multi_source)
|
||||
|
||||
# cloud_menu = self.basic_menu.addMenu('&去云处理')
|
||||
# defogging_menu = self.basic_menu.addMenu('&去雾处理')
|
||||
|
||||
# # self.preop_menu.addActionGroup(filter_action_group)
|
||||
# # self.basic_menu.addAction(align_action)
|
||||
|
||||
# if self.toolbar is not None:
|
||||
# self.toolbar.addAction(morphology_filter)
|
||||
# self.toolbar.addAction(lee_filter)
|
||||
# self.toolbar.addAction(auto_filter)
|
||||
# self.toolbar.addAction(auto_filter_no_params)
|
||||
# self.toolbar.addAction(double_filter)
|
||||
|
||||
# '''
|
||||
# Change detection menu
|
||||
# '''
|
||||
# diff_method = self.add_action(QAction('&差分法', self.w_parent), 'unsuper_change_detection')
|
||||
# log_diff = self.add_action(QAction('&对数差分法', self.w_parent), 'unsuper_change_detection')
|
||||
# lsts_ = self.add_action(QAction('&LSTS法', self.w_parent), 'unsuper_change_detection')
|
||||
# lhba = self.add_action(QAction('&LHBA法', self.w_parent), 'unsuper_change_detection')
|
||||
# aht = self.add_action(QAction('&AHT法', self.w_parent), 'unsuper_change_detection')
|
||||
# kpvd = self.add_action(QAction('&KPVD法', self.w_parent), 'unsuper_change_detection')
|
||||
# mohd = self.add_action(QAction('&MOHD法', self.w_parent), 'unsuper_change_detection')
|
||||
# sh = self.add_action(QAction('&SH法', self.w_parent), 'unsuper_change_detection')
|
||||
# cva = self.add_action(QAction('&CVA法', self.w_parent), 'unsuper_change_detection')
|
||||
# mls = self.add_action(QAction('&MLS法', self.w_parent), 'unsuper_change_detection')
|
||||
# pca_kmean = self.add_action(QAction('&PCA-KMean法', self.w_parent), 'unsuper_change_detection')
|
||||
# semi_fcm = self.add_action(QAction('&Semi-FCM法', self.w_parent), 'unsuper_change_detection')
|
||||
# mls_svm = self.add_action(QAction('&MLS-SVM法', self.w_parent), 'unsuper_change_detection')
|
||||
# cva_fcm = self.add_action(QAction('&CVA-FCM法', self.w_parent), 'unsuper_change_detection')
|
||||
# cva_emgmm = self.add_action(QAction('&CVA-EMGMM法', self.w_parent), 'unsuper_change_detection')
|
||||
# gwdm = self.add_action(QAction('&GWDM法', self.w_parent), 'unsuper_change_detection')
|
||||
|
||||
# mrf = self.add_action(QAction('&MRF法', self.w_parent), 'super_change_detection')
|
||||
# mad = self.add_action(QAction('&MAD法', self.w_parent), 'super_change_detection')
|
||||
# irmad = self.add_action(QAction('&IRMAD法', self.w_parent), 'super_change_detection')
|
||||
|
||||
# dcva = self.add_action(QAction('&DCVA法', self.w_parent), 'ai_change_detection')
|
||||
# dp_fcn = self.add_action(QAction('&DP-FCN法', self.w_parent), 'ai_change_detection')
|
||||
# rcnn = self.add_action(QAction('&RCNN法', self.w_parent), 'ai_change_detection')
|
||||
|
||||
# if self.toolbar is not None:
|
||||
# self.toolbar.addAction(diff_method)
|
||||
# self.toolbar.addAction(log_diff)
|
||||
# self.toolbar.addAction(lsts_)
|
||||
# self.toolbar.addAction(lhba)
|
||||
|
||||
|
||||
# unsuper_change_detection = self.get_action_group('unsuper_change_detection')
|
||||
# super_change_detection = self.get_action_group('super_change_detection')
|
||||
# ai_change_detection = self.get_action_group('ai_change_detection')
|
||||
# unsuper_menu = self.change_detection_menu.addMenu('&非监督')
|
||||
# for action in unsuper_change_detection.actions():
|
||||
# unsuper_menu.addAction(action)
|
||||
# super_menu = self.change_detection_menu.addMenu('&监督')
|
||||
# for action in super_change_detection.actions():
|
||||
# super_menu.addAction(action)
|
||||
# ai_menu = self.change_detection_menu.addMenu('&AI')
|
||||
# for action in ai_change_detection.actions():
|
||||
# ai_menu.addAction(action)
|
||||
|
||||
# # self.change_detection_menu.addActionGroup(super_change_detection)
|
||||
# # self.change_detection_menu.addActionGroup(ai_change_detection)
|
||||
|
||||
# '''
|
||||
# Special change detection menu
|
||||
# '''
|
||||
|
||||
# water_change = self.add_action(QAction('&水体变化', self.w_parent), 'special_change_detection')
|
||||
# vegetation_change = self.add_action(QAction('&植被变化', self.w_parent), 'special_change_detection')
|
||||
# build_change = self.add_action(QAction('&房屋变化', self.w_parent), 'special_change_detection')
|
||||
|
||||
# self.special_chagne_detec_menu.addAction(water_change)
|
||||
# self.special_chagne_detec_menu.addAction(vegetation_change)
|
||||
# self.special_chagne_detec_menu.addAction(build_change)
|
||||
|
||||
# '''
|
||||
# Postop menu
|
||||
# '''
|
||||
# slide_window = self.add_action(QAction('&滑动窗口法', self.w_parent), 'noise_reduction')
|
||||
# density = self.add_action(QAction('&密度法', self.w_parent), 'noise_reduction')
|
||||
|
||||
# raster_export = self.add_action(QAction('&二值栅格数据导出', self.w_parent), 'export')
|
||||
# txt_pos_export = self.add_action(QAction('&兼容ArcMap的坐标Txt文件', self.w_parent), 'export')
|
||||
# render_export = self.add_action(QAction('&渲染图像导出', self.w_parent), 'export')
|
||||
|
||||
# noise_reduction = self.get_action_group('noise_reduction')
|
||||
# export = self.get_action_group('export')
|
||||
|
||||
# noise_reduction_menu = self.postop_menu.addMenu('&噪声抑制')
|
||||
# for action in noise_reduction.actions():
|
||||
# noise_reduction_menu.addAction(action)
|
||||
# export_menu = self.postop_menu.addMenu('&导出')
|
||||
# for action in export.actions():
|
||||
# export_menu.addAction(action)
|
||||
|
||||
# # self.postop_menu.addActionGroup(noise_reduction)
|
||||
# # self.postop_menu.addActionGroup(export)
|
||||
|
||||
# '''
|
||||
# Evaluation menu
|
||||
# '''
|
||||
|
||||
# evaluation = self.add_action(QAction('&评估', self.w_parent), 'evaluation')
|
||||
# self.postop_menu.addAction(evaluation)
|
||||
|
||||
'''
|
||||
Help menu
|
||||
'''
|
||||
# about = self.add_action(QAction('&关于', self.w_parent), 'about')
|
||||
# about.triggered.connect(lambda : AboutDialog(self.w_parent).show())
|
||||
# self.help_menu.addAction(about)
|
||||
|
||||
self.message_box.info('Menu init finished')
|
||||
self.message_box.info(self.actions.keys())
|
||||
# for group in self.action_groups.keys():
|
||||
# self.message_box.info('%s:' % (group))
|
||||
# for action in self.action_groups[group].actions():
|
||||
# action.setEnabled(False)
|
||||
# self.message_box.info('\t%s' % (action.text()))
|
||||
|
||||
'''
|
||||
Enabled actions
|
||||
'''
|
||||
# about.setEnabled(True)
|
||||
project_create.setEnabled(True)
|
||||
project_open.setEnabled(True)
|
||||
|
||||
Project().project_init.connect(self.project_init)
|
||||
|
||||
if self.status_bar is not None:
|
||||
corr_widget = QLabel(self.status_bar)
|
||||
# corr_widget.setLineWidth(200)
|
||||
corr_widget.setFixedWidth(200)
|
||||
self.status_bar.addWidget(corr_widget)
|
||||
scale_widget = QLabel(self.status_bar)
|
||||
scale_widget.setFixedWidth(200)
|
||||
self.status_bar.addWidget(scale_widget)
|
||||
self.double_map.corr_changed.connect(corr_widget.setText)
|
||||
self.double_map.scale_changed.connect(scale_widget.setText)
|
||||
|
||||
def plugin_list(self):
|
||||
dialog = PluginDialog(self.w_parent)
|
||||
dialog.show()
|
||||
|
||||
def project_create(self):
|
||||
project = Project()
|
||||
|
||||
projec_create = Create(self.w_parent)
|
||||
if(projec_create.exec_()):
|
||||
if project.is_init:
|
||||
project.save()
|
||||
project.clear()
|
||||
project.setup(os.path.join(projec_create.file, projec_create.name + '.prj'))
|
||||
project.is_init = True
|
||||
project.cell_size = projec_create.cell_size
|
||||
project.max_memory = projec_create.max_memory
|
||||
project.save()
|
||||
self.message_box.info('Project created')
|
||||
|
||||
def project_init(self, state):
|
||||
self.message_box.info('Project init')
|
||||
for group in self.action_groups.keys():
|
||||
# self.message_box.info('%s:' % (group))
|
||||
for action in self.action_groups[group].actions():
|
||||
action.setEnabled(state)
|
||||
# self.message_box.info('\t%s' % (action.text()))
|
||||
|
||||
self.message_box.info('Project init finished')
|
||||
|
||||
def project_open(self):
|
||||
if Project().is_init:
|
||||
Project().save()
|
||||
|
||||
project_file = QFileDialog.getOpenFileName(self.w_parent, '打开工程', '.', '*.prj')
|
||||
if project_file[0] != '':
|
||||
Project().clear()
|
||||
Project().setup(project_file[0])
|
||||
|
||||
def project_save(self):
|
||||
if Project().is_init:
|
||||
Project().save()
|
||||
|
||||
def data_load(self):
|
||||
if Project().is_init:
|
||||
Project().save()
|
||||
|
||||
file_open = QFileDialog.getOpenFileNames(self.w_parent, '打开数据', Project().root, '*.*')
|
||||
if file_open[0] != '':
|
||||
if len(file_open[0]) != 2:
|
||||
self.message_box.warning('请选择两个数据文件')
|
||||
return
|
||||
Project().add_layer(file_open[0][0], file_open[0][1])
|
||||
self.message_box.info('Data loaded')
|
||||
|
||||
def view_setting(self):
|
||||
pass
|
||||
|
||||
|
||||
def add_action(self, action, group=None):
|
||||
if group is None:
|
||||
self.actions[action.text()] = action
|
||||
else:
|
||||
if group not in self.action_groups:
|
||||
self.action_groups[group] = QActionGroup(self.w_parent)
|
||||
self.action_groups[group].setExclusive(True)
|
||||
self.action_groups[group].addAction(action)
|
||||
self.action_group_actions[group] = action
|
||||
return action
|
||||
|
||||
def get_action(self, action_name, group_name=None):
|
||||
if action_name in self.actions:
|
||||
return self.actions[action_name]
|
||||
else:
|
||||
if group_name is None:
|
||||
return None
|
||||
else:
|
||||
if group_name not in self.action_group_actions:
|
||||
return None
|
||||
else:
|
||||
group = self.action_group_actions[group_name]
|
||||
for action in group.actions():
|
||||
if action.text() == action_name:
|
||||
return action
|
||||
return None
|
||||
|
||||
def get_action_group(self, group_name):
|
||||
return self.action_groups[group_name]
|
||||
|
||||
def get_action_group_action(self, group_name):
|
||||
return self.action_group_actions[group_name]
|
||||
|
||||
def get_action_group_actions(self, group_name):
|
||||
return self.action_group_actions[group_name].actions()
|
||||
|
||||
def get_actions(self):
|
||||
return self.actions
|
@ -4,7 +4,7 @@ from PyQt5.QtCore import Qt,QModelIndex
|
||||
from PyQt5.QtGui import QStandardItemModel, QStandardItem
|
||||
from PyQt5.QtWidgets import (QTreeView, QTreeWidgetItem, QAbstractItemView, QHeaderView, QStyleFactory)
|
||||
|
||||
from utils.project import PairLayer
|
||||
from rscder.utils.project import PairLayer, Project
|
||||
|
||||
class LayerTree(QtWidgets.QWidget):
|
||||
|
||||
@ -18,13 +18,13 @@ class LayerTree(QtWidgets.QWidget):
|
||||
self.root=QTreeWidgetItem(self.tree)
|
||||
self.tree.setHeaderHidden(True)
|
||||
# self.tree.setHeaderLabels(['图层'])
|
||||
self.root.setText(0,'Root')
|
||||
self.root.setText(0,'图层')
|
||||
|
||||
child1=QTreeWidgetItem()
|
||||
child1.setText(0,'child1')
|
||||
child1.setCheckState(0,Qt.Checked)
|
||||
# child1=QTreeWidgetItem()
|
||||
# child1.setText(0,'child1')
|
||||
# child1.setCheckState(0,Qt.Checked)
|
||||
|
||||
self.root.addChild(child1)
|
||||
# self.root.addChild(child1)
|
||||
self.tree.expandAll()
|
||||
|
||||
self.tree.addTopLevelItem(self.root)
|
||||
@ -39,9 +39,25 @@ class LayerTree(QtWidgets.QWidget):
|
||||
def onClicked(self,index):
|
||||
print(index.row())
|
||||
|
||||
def add_layer(self, layer:PairLayer):
|
||||
pass
|
||||
|
||||
def add_layer(self, layer:str):
|
||||
layer:PairLayer = Project().layers[layer]
|
||||
item1 = QtWidgets.QTreeWidgetItem(self.root)
|
||||
item1.setText(0, layer.l1_name)
|
||||
item1.setCheckState(0, Qt.Checked)
|
||||
item2 = QtWidgets.QTreeWidgetItem(self.root)
|
||||
item2.setText(0, layer.l2_name)
|
||||
item2.setCheckState(0, Qt.Checked)
|
||||
|
||||
item1.setData(0, Qt.UserRole, layer.id)
|
||||
item2.setData(0, Qt.UserRole, layer.id)
|
||||
self.tree.expandAll()
|
||||
|
||||
def clear(self):
|
||||
self.tree.clear()
|
||||
self.root = QTreeWidgetItem(self.tree)
|
||||
self.root.setText(0,'图层')
|
||||
self.tree.addTopLevelItem(self.root)
|
||||
|
||||
def right_menu_show(self, position):
|
||||
rightMenu = QtWidgets.QMenu(self)
|
||||
# QAction = QtWidgets.QAction(self.menuBar1)
|
@ -4,7 +4,7 @@ from PyQt5 import QtCore
|
||||
from PyQt5.QtGui import QIcon
|
||||
import os
|
||||
|
||||
from utils.license import LicenseHelper
|
||||
from rscder.utils.license import LicenseHelper
|
||||
|
||||
class License(QtWidgets.QDialog):
|
||||
|
@ -4,13 +4,13 @@ from PyQt5.QtCore import Qt, QSize
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5 import QtGui
|
||||
from PyQtAds import QtAds
|
||||
from actions.actions import ActionManager
|
||||
from gui.layertree import LayerTree
|
||||
from gui.mapcanvas import DoubleCanvas
|
||||
from gui.messagebox import MessageBox
|
||||
from gui.result import ResultTable
|
||||
from utils import Settings
|
||||
from utils.project import Project
|
||||
from rscder.gui.actions import ActionManager
|
||||
from rscder.gui.layertree import LayerTree
|
||||
from rscder.gui.mapcanvas import DoubleCanvas
|
||||
from rscder.gui.messagebox import MessageBox
|
||||
from rscder.gui.result import ResultTable
|
||||
from rscder.utils import Settings
|
||||
from rscder.utils.project import Project
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
|
||||
@ -41,7 +41,6 @@ class MainWindow(QMainWindow):
|
||||
self.action_manager.set_menus(self.menuBar())
|
||||
self.action_manager.set_toolbar(self.toolbar)
|
||||
self.action_manager.set_status_bar(self.statusBar())
|
||||
|
||||
self.action_manager.set_actions()
|
||||
|
||||
self.resize(*Settings.General().size)
|
@ -12,13 +12,15 @@ from PyQt5.QtWidgets import QMessageBox, QWidget, QHBoxLayout
|
||||
from PyQt5.QtGui import QColor, QDragEnterEvent, QDropEvent
|
||||
|
||||
from qgis.core import QgsPointXY, QgsRasterLayer, QgsVectorLayer, QgsFeature, QgsGeometry, QgsCategorizedSymbolRenderer, QgsRendererCategory, QgsFillSymbol, QgsPalLayerSettings, QgsRuleBasedLabeling, QgsTextFormat
|
||||
from qgis.gui import QgsMapCanvas
|
||||
from qgis.core import QgsVectorLayerExporter, QgsVectorFileWriter, QgsProject, QgsField, QgsRasterFileWriter, QgsRasterPipe
|
||||
from qgis.gui import QgsMapCanvas, QgsMapToolPan, QgsMapToolZoom
|
||||
from qgis.core import QgsRectangle, QgsVectorFileWriter, QgsProject, QgsField, QgsRasterFileWriter, QgsRasterPipe
|
||||
import threading
|
||||
import tempfile
|
||||
import cv2
|
||||
import os
|
||||
|
||||
from rscder.utils.project import PairLayer, Project
|
||||
|
||||
class DoubleCanvas(QWidget):
|
||||
corr_changed = pyqtSignal(str)
|
||||
scale_changed = pyqtSignal(str)
|
||||
@ -35,6 +37,16 @@ class DoubleCanvas(QWidget):
|
||||
self.mapcanva1.update_coordinates_text.connect(self.corr_changed)
|
||||
self.mapcanva2.update_coordinates_text.connect(self.corr_changed)
|
||||
|
||||
def set_map1_extent():
|
||||
self.mapcanva1.set_extent(self.mapcanva2.extent())
|
||||
def set_map2_extent():
|
||||
self.mapcanva2.set_extent(self.mapcanva1.extent())
|
||||
|
||||
self.mapcanva1.extentsChanged.connect(set_map2_extent)
|
||||
self.mapcanva2.extentsChanged.connect(set_map1_extent)
|
||||
|
||||
self.set_pan_tool(True)
|
||||
|
||||
self.mapcanva1.update_scale_text.connect(self.scale_changed)
|
||||
self.mapcanva2.update_scale_text.connect(self.scale_changed)
|
||||
|
||||
@ -43,16 +55,117 @@ class DoubleCanvas(QWidget):
|
||||
layout.addWidget(self.mapcanva2)
|
||||
|
||||
self.setLayout(layout)
|
||||
self.grid_show = True
|
||||
|
||||
def connect_grid_show(self, action):
|
||||
def show_grid(_):
|
||||
|
||||
self.grid_show = not self.grid_show
|
||||
action.setChecked(self.grid_show)
|
||||
if self.grid_show:
|
||||
for layer in Project().layers.values():
|
||||
self.mapcanva1.add_grid_layer(layer.grid_layer.grid_layer)
|
||||
self.mapcanva2.add_grid_layer(layer.grid_layer.grid_layer)
|
||||
else:
|
||||
self.mapcanva1.remove_grid_layer()
|
||||
self.mapcanva2.remove_grid_layer()
|
||||
|
||||
action.triggered.connect(show_grid)
|
||||
|
||||
|
||||
def connect_map_tool(self, pan, zoom_in, zoom_out):
|
||||
pan.triggered.connect(self.set_pan_tool)
|
||||
zoom_in.triggered.connect(self.set_zoom_in)
|
||||
zoom_out.triggered.connect( self.set_zoom_out)
|
||||
|
||||
def set_pan_tool(self, s):
|
||||
print('set pan tool')
|
||||
if s:
|
||||
self.mapcanva1.setMapTool(QgsMapToolPan(self.mapcanva1))
|
||||
self.mapcanva2.setMapTool(QgsMapToolPan(self.mapcanva2))
|
||||
|
||||
def set_zoom_in(self, s):
|
||||
print('set zoom in')
|
||||
if s:
|
||||
self.mapcanva1.setMapTool(QgsMapToolZoom(self.mapcanva1, False))
|
||||
self.mapcanva2.setMapTool(QgsMapToolZoom(self.mapcanva2, False))
|
||||
|
||||
def set_zoom_out(self, s):
|
||||
print('set zoom out')
|
||||
if s:
|
||||
self.mapcanva1.setMapTool(QgsMapToolZoom(self.mapcanva1, True))
|
||||
self.mapcanva2.setMapTool(QgsMapToolZoom(self.mapcanva2, True))
|
||||
|
||||
def add_layer(self, layer:str):
|
||||
layer = Project().layers[layer]
|
||||
if not self.mapcanva1.is_main and not self.mapcanva2.is_main:
|
||||
self.mapcanva1.is_main = True
|
||||
self.mapcanva1.add_layer(layer.l1)
|
||||
self.mapcanva2.add_layer(layer.l2)
|
||||
if self.grid_show:
|
||||
self.mapcanva1.add_grid_layer(layer.grid_layer.grid_layer)
|
||||
self.mapcanva2.add_grid_layer(layer.grid_layer.grid_layer)
|
||||
|
||||
|
||||
def clear(self):
|
||||
self.mapcanva1.clear()
|
||||
self.mapcanva2.clear()
|
||||
|
||||
class CanvasWidget(QgsMapCanvas):
|
||||
update_coordinates_text = pyqtSignal(str)
|
||||
update_scale_text = pyqtSignal(str)
|
||||
|
||||
def add_layer(self, layer) -> None:
|
||||
self.layers.insert(0, layer)
|
||||
self.setLayers(self.layers)
|
||||
self.zoomToFeatureExtent(layer.extent())
|
||||
|
||||
def add_grid_layer(self, layer):
|
||||
self.grid_layers.append(layer)
|
||||
self.layers.insert(0, layer)
|
||||
self.setLayers(self.layers)
|
||||
|
||||
def remove_grid_layer(self):
|
||||
layers = []
|
||||
for layer in self.layers:
|
||||
if layer in self.grid_layers:
|
||||
continue
|
||||
layers.append(layer)
|
||||
self.layers = layers
|
||||
self.setLayers(self.layers)
|
||||
|
||||
def enterEvent(self,e):
|
||||
self.is_main = True
|
||||
# print(e)
|
||||
pass
|
||||
|
||||
def leaveEvent(self, e):
|
||||
self.is_main = False
|
||||
pass
|
||||
|
||||
def set_extent(self, extent:QgsRectangle):
|
||||
'''
|
||||
Zoom to extent
|
||||
'''
|
||||
# print(extent)
|
||||
if self.is_main:
|
||||
return
|
||||
else:
|
||||
self.zoomToFeatureExtent(extent)
|
||||
|
||||
def clear(self) -> None:
|
||||
self.setTheme('')
|
||||
self.layers = []
|
||||
self.is_main = False
|
||||
self.setLayers([])
|
||||
self.clearCache()
|
||||
self.refresh()
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
self.current_raster_layer = None
|
||||
self.current_vector_layer = None
|
||||
|
||||
self.layers = []
|
||||
self.grid_layers = []
|
||||
self.is_main = False
|
||||
self.setCanvasColor(Qt.white)
|
||||
self.enableAntiAliasing(True)
|
||||
self.setAcceptDrops(False)
|
97
rscder/gui/plugins.py
Normal file
@ -0,0 +1,97 @@
|
||||
from PyQt5.QtWidgets import *
|
||||
from PyQt5.QtGui import QIcon, Qt
|
||||
from rscder.utils.setting import Settings
|
||||
|
||||
class PluginDialog(QDialog):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle('Plugins')
|
||||
self.setWindowIcon(QIcon(":/icons/logo.svg"))
|
||||
self.setMinimumWidth(800)
|
||||
self.setMinimumHeight(600)
|
||||
self.plugins = Settings.Plugin().plugins
|
||||
|
||||
self.plugin_table = QTableWidget(len(self.plugins), 2, self)
|
||||
self.plugin_table.setSelectionMode(QAbstractItemView.ExtendedSelection)
|
||||
self.plugin_table.setColumnWidth(0, 200)
|
||||
self.plugin_table.setColumnWidth(1, 500)
|
||||
self.plugin_table.setHorizontalHeaderLabels(['Name', 'Path', 'Enabled'])
|
||||
self.plugin_table.setEditTriggers(QAbstractItemView.DoubleClicked)
|
||||
self.plugin_table.cellDoubleClicked.connect(self.edit_plugin)
|
||||
for idx, plugin in enumerate(self.plugins):
|
||||
name_item = QTableWidgetItem(plugin['name'])
|
||||
path_item = QTableWidgetItem(plugin['path'])
|
||||
enabled_item = QTableWidgetItem()
|
||||
enabled_item.setCheckState(Qt.Checked if plugin['enabled'] else Qt.Unchecked)
|
||||
|
||||
self.plugin_table.setItem(idx, 0, name_item)
|
||||
self.plugin_table.setItem(idx, 1, path_item)
|
||||
self.plugin_table.setItem(idx, 2, enabled_item)
|
||||
|
||||
self.add_button = QPushButton('Add', self)
|
||||
self.add_button.clicked.connect(self.add_plugin)
|
||||
self.remove_button = QPushButton('Remove', self)
|
||||
self.remove_button.clicked.connect(self.remove_plugin)
|
||||
self.save_button = QPushButton('Save', self)
|
||||
self.save_button.clicked.connect(self.save_plugin)
|
||||
self.cancel_button = QPushButton('Cancel', self)
|
||||
self.cancel_button.clicked.connect(self.close)
|
||||
|
||||
layout = QVBoxLayout(self)
|
||||
layout.addWidget(self.plugin_table)
|
||||
hlayout = QHBoxLayout()
|
||||
hlayout.addWidget(self.add_button)
|
||||
hlayout.addWidget(self.remove_button)
|
||||
hlayout.addWidget(self.save_button)
|
||||
hlayout.addWidget(self.cancel_button)
|
||||
layout.addLayout(hlayout)
|
||||
self.setLayout(layout)
|
||||
self.has_change = False
|
||||
|
||||
def add_plugin(self):
|
||||
self.has_change = True
|
||||
self.plugin_table.insertRow(self.plugin_table.rowCount())
|
||||
|
||||
def remove_plugin(self):
|
||||
self.has_change = True
|
||||
for row in self.plugin_table.selectedItems():
|
||||
self.plugin_table.removeRow(row.row())
|
||||
|
||||
# for idx in self.plugins
|
||||
|
||||
def edit_plugin(self, row, column):
|
||||
self.has_change = True
|
||||
if column == 0:
|
||||
self.plugin_table.item(row, column).setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
|
||||
elif column == 1:
|
||||
open_file = QFileDialog.getOpenFileName(self, 'Open File', '', 'Python Files (*.py)')
|
||||
if open_file[0]:
|
||||
self.plugin_table.item(row, column).setText(open_file[0])
|
||||
else:
|
||||
pass
|
||||
elif column == 2:
|
||||
self.plugin_table.item(row, column).setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
|
||||
# self.plugin_list.setFixedWidth(200)
|
||||
|
||||
def save_plugin(self):
|
||||
|
||||
plugins = []
|
||||
for idx in range(self.plugin_table.rowCount()):
|
||||
name = self.plugin_table.item(idx, 0).text()
|
||||
path = self.plugin_table.item(idx, 1).text()
|
||||
enabled = self.plugin_table.item(idx, 2).checkState() == Qt.Checked
|
||||
plugins.append({'name': name, 'path': path, 'enabled': enabled})
|
||||
Settings.Plugin().plugins = plugins
|
||||
self.close()
|
||||
|
||||
def closeEvent(self, event):
|
||||
if self.has_change:
|
||||
reply = QMessageBox.question(self, 'Message', "Do you want to save the changes?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
|
||||
if reply == QMessageBox.Yes:
|
||||
self.save_plugin()
|
||||
event.accept()
|
||||
else:
|
||||
event.accept()
|
||||
else:
|
||||
event.accept()
|
@ -1,7 +1,7 @@
|
||||
from PyQt5.QtWidgets import QDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QMessageBox
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5.QtWidgets import QDialog, QFileDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QMessageBox
|
||||
from PyQt5.QtGui import QIcon, QIntValidator
|
||||
from PyQt5.QtCore import Qt
|
||||
from utils.setting import Settings
|
||||
from rscder.utils.setting import Settings
|
||||
class Create(QDialog):
|
||||
|
||||
def __init__(self, parent=None) -> None:
|
||||
@ -21,12 +21,21 @@ class Create(QDialog):
|
||||
file_input.setToolTip('Project Dir')
|
||||
file_input.setReadOnly(True)
|
||||
file_input.setText(self.file)
|
||||
self.file_input = file_input
|
||||
|
||||
file_open = QPushButton('...', self)
|
||||
file_open.setFixedWidth(30)
|
||||
file_open.clicked.connect(self.open_file)
|
||||
|
||||
|
||||
name_label = QLabel('Project Name:')
|
||||
name_label.setFixedWidth(100)
|
||||
name_input = QLineEdit()
|
||||
name_input.setPlaceholderText('Project Name')
|
||||
name_input.setToolTip('Project Name')
|
||||
name_input.setText(self.name)
|
||||
self.name_input = name_input
|
||||
|
||||
|
||||
name_input_layout = QHBoxLayout()
|
||||
name_input_layout.addWidget(name_label)
|
||||
@ -35,6 +44,7 @@ class Create(QDialog):
|
||||
file_input_layout = QHBoxLayout()
|
||||
file_input_layout.addWidget(file_label)
|
||||
file_input_layout.addWidget(file_input)
|
||||
file_input_layout.addWidget(file_open)
|
||||
|
||||
cell_size_label = QLabel('Cell Size:')
|
||||
cell_size_label.setFixedWidth(100)
|
||||
@ -43,9 +53,16 @@ class Create(QDialog):
|
||||
cell_size_x_input = QLineEdit()
|
||||
cell_size_y_input = QLineEdit()
|
||||
cell_size_x_input.setPlaceholderText('Cell Size X')
|
||||
cell_size_x_input.setValidator(QIntValidator())
|
||||
cell_size_y_input.setPlaceholderText('Cell Size Y')
|
||||
cell_size_y_input.setValidator(QIntValidator())
|
||||
cell_size_x_input.setToolTip('Cell Size X')
|
||||
cell_size_y_input.setToolTip('Cell Size Y')
|
||||
cell_size_x_input.setText(str(self.cell_size[0]))
|
||||
cell_size_y_input.setText(str(self.cell_size[1]))
|
||||
|
||||
self.cell_size_x_input = cell_size_x_input
|
||||
self.cell_size_y_input = cell_size_y_input
|
||||
|
||||
cell_input_layout = QHBoxLayout()
|
||||
cell_input_layout.addWidget(cell_size_label)
|
||||
@ -54,8 +71,20 @@ class Create(QDialog):
|
||||
cell_input_layout.addWidget(cell_size_y_label)
|
||||
cell_input_layout.addWidget(cell_size_y_input)
|
||||
|
||||
max_memory_label = QLabel('Max Memory (MB):')
|
||||
max_memory_label.setFixedWidth(100)
|
||||
max_memory_input = QLineEdit()
|
||||
max_memory_input.setPlaceholderText('Max Memory')
|
||||
max_memory_input.setToolTip('Max Memory')
|
||||
max_memory_input.setText(str(self.max_memory))
|
||||
max_memory_input.setValidator(QIntValidator())
|
||||
self.max_memory_input = max_memory_input
|
||||
|
||||
ok_button = QPushButton('OK')
|
||||
cancel_button = QPushButton('Cancel')
|
||||
|
||||
ok_button.clicked.connect(self.ok)
|
||||
cancel_button.clicked.connect(self.cancel)
|
||||
|
||||
button_layout = QHBoxLayout()
|
||||
button_layout.setDirection(QHBoxLayout.RightToLeft)
|
||||
@ -70,3 +99,29 @@ class Create(QDialog):
|
||||
|
||||
self.setLayout(main_layout)
|
||||
|
||||
|
||||
def open_file(self):
|
||||
file = QFileDialog.getExistingDirectory(self, 'Open Directory', self.file)
|
||||
if file:
|
||||
self.file = file
|
||||
self.file_input.setText(self.file)
|
||||
|
||||
def ok(self):
|
||||
self.name = self.name_input.text()
|
||||
self.max_memory = self.max_memory_input.text()
|
||||
self.cell_size = (self.cell_size_x_input.text(), self.cell_size_y_input.text())
|
||||
if self.name == '':
|
||||
QMessageBox.warning(self, 'Warning', 'Please input project name!')
|
||||
return
|
||||
if self.max_memory == '':
|
||||
QMessageBox.warning(self, 'Warning', 'Please input max memory!')
|
||||
return
|
||||
if self.cell_size == ('', ''):
|
||||
QMessageBox.warning(self, 'Warning', 'Please input cell size!')
|
||||
return
|
||||
self.max_memory = int(self.max_memory)
|
||||
self.cell_size = (int(self.cell_size[0]), int(self.cell_size[1]))
|
||||
self.accept()
|
||||
|
||||
def cancel(self):
|
||||
self.reject()
|
@ -4,7 +4,7 @@ from PyQt5.QtCore import Qt,QModelIndex
|
||||
from PyQt5.QtGui import QStandardItemModel, QStandardItem
|
||||
from PyQt5.QtWidgets import (QTreeView, QTreeWidgetItem, QAbstractItemView, QHeaderView, QStyleFactory)
|
||||
|
||||
from utils.project import PairLayer
|
||||
from rscder.utils.project import PairLayer
|
||||
|
||||
class ResultTable(QtWidgets.QWidget):
|
||||
|
||||
@ -34,6 +34,9 @@ class ResultTable(QtWidgets.QWidget):
|
||||
layout.addWidget(self.tree)
|
||||
self.setLayout(layout)
|
||||
|
||||
def clear(self):
|
||||
pass
|
||||
|
||||
def onClicked(self,index):
|
||||
print(index.row())
|
||||
|
Before Width: | Height: | Size: 638 B After Width: | Height: | Size: 638 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 622 B After Width: | Height: | Size: 622 B |
Before Width: | Height: | Size: 606 B After Width: | Height: | Size: 606 B |
Before Width: | Height: | Size: 508 B After Width: | Height: | Size: 508 B |
Before Width: | Height: | Size: 632 B After Width: | Height: | Size: 632 B |
Before Width: | Height: | Size: 689 B After Width: | Height: | Size: 689 B |
Before Width: | Height: | Size: 642 B After Width: | Height: | Size: 642 B |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 699 B After Width: | Height: | Size: 699 B |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 593 B After Width: | Height: | Size: 593 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 514 B After Width: | Height: | Size: 514 B |
Before Width: | Height: | Size: 654 B After Width: | Height: | Size: 654 B |
Before Width: | Height: | Size: 756 B After Width: | Height: | Size: 756 B |
Before Width: | Height: | Size: 730 B After Width: | Height: | Size: 730 B |
54
rscder/plugins/basic.py
Normal file
@ -0,0 +1,54 @@
|
||||
from PyQt5.QtCore import QObject, pyqtSignal
|
||||
from rscder.utils.project import PairLayer
|
||||
|
||||
class BasicPlugin(QObject):
|
||||
'''
|
||||
插件基类
|
||||
ctx:
|
||||
layer_tree: layer tree
|
||||
pair_canvas: pair canvas
|
||||
message_box: message box
|
||||
result_table: result table
|
||||
project: project instance
|
||||
mainwindow: mainwindow
|
||||
toolbar: toolbar
|
||||
statusbar: statusbar
|
||||
menu: menu
|
||||
file_menu: file menu
|
||||
|
||||
|
||||
'''
|
||||
def __init__(self, ctx:dict) -> None:
|
||||
super().__init__()
|
||||
self.ctx = ctx
|
||||
self.layer_tree = ctx['layer_tree']
|
||||
self.pair_canvas = ctx['pair_canvas']
|
||||
self.message_box = ctx['message_box']
|
||||
self.result_table = ctx['result_table']
|
||||
self.project = ctx['project']
|
||||
self.mainwindow = ctx['mainwindow']
|
||||
self.set_action()
|
||||
self.project.layer_load.connect(self.on_data_load)
|
||||
self.project.project_created.connect(self.setup)
|
||||
|
||||
|
||||
def set_action(self):
|
||||
'''
|
||||
When App start
|
||||
'''
|
||||
pass
|
||||
|
||||
def setup(self):
|
||||
'''
|
||||
When project create
|
||||
'''
|
||||
pass
|
||||
|
||||
def get_layer(self, layer_id)-> PairLayer:
|
||||
return self.project.layers[layer_id]
|
||||
|
||||
def on_data_load(self, layer_id):
|
||||
'''
|
||||
When data load
|
||||
'''
|
||||
pass
|
30
rscder/plugins/loader.py
Normal file
@ -0,0 +1,30 @@
|
||||
from rscder.utils.setting import Settings
|
||||
from PyQt5.QtCore import QObject, pyqtSignal
|
||||
from rscder.plugins.basic import BasicPlugin
|
||||
import importlib
|
||||
import os
|
||||
import sys
|
||||
import inspect
|
||||
|
||||
class PluginLoader(QObject):
|
||||
|
||||
plugin_loaded = pyqtSignal()
|
||||
|
||||
def __init__(self, ctx):
|
||||
self.ctx = ctx
|
||||
|
||||
def load_plugin(self):
|
||||
plugins = Settings.Plugin().plugins
|
||||
for plugin in plugins:
|
||||
name = plugin['name']
|
||||
path = plugin['path']
|
||||
try:
|
||||
module = importlib.import_module(path)
|
||||
for oname, obj in inspect.getmembers(module):
|
||||
if inspect.isclass(obj) and issubclass(obj, BasicPlugin) and obj != BasicPlugin and obj != PluginLoader and oname == name:
|
||||
obj(self.ctx)
|
||||
except Exception as e:
|
||||
self.ctx['message_box'].error(f'{name} load error: {e}')
|
||||
# print(e)
|
||||
|
||||
self.plugin_loaded.emit()
|
262
rscder/utils/project.py
Normal file
@ -0,0 +1,262 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
import uuid
|
||||
from osgeo import gdal, gdal_array
|
||||
from utils.setting import Settings
|
||||
from qgis.core import QgsRasterLayer, QgsLineSymbol, QgsSingleSymbolRenderer, QgsSimpleLineSymbolLayer, QgsVectorLayer, QgsCoordinateReferenceSystem, QgsFeature, QgsGeometry, QgsPointXY
|
||||
from PyQt5.QtCore import QObject, pyqtSignal
|
||||
from PyQt5.QtGui import QColor
|
||||
import yaml
|
||||
def singleton(cls):
|
||||
_instance = {}
|
||||
|
||||
def inner(*args, **kargs):
|
||||
if cls not in _instance:
|
||||
_instance[cls] = cls(*args, **kargs)
|
||||
return _instance[cls]
|
||||
return inner
|
||||
|
||||
@singleton
|
||||
class Project(QObject):
|
||||
|
||||
project_init = pyqtSignal(bool)
|
||||
|
||||
layer_load = pyqtSignal(str)
|
||||
|
||||
def __init__(self,
|
||||
parent=None):
|
||||
super().__init__(parent)
|
||||
self.is_init = False
|
||||
self.cell_size = Settings.Project().cell_size
|
||||
self.max_memory = Settings.Project().max_memory
|
||||
self.max_threads = Settings.Project().max_threads
|
||||
self.root = Settings.General().root
|
||||
self.layers:Dict = dict()
|
||||
# self.layers:List[PairLayer] = []
|
||||
|
||||
def connect(self, pair_canvas,
|
||||
layer_tree,
|
||||
message_box,
|
||||
result_table):
|
||||
self.pair_canvas = pair_canvas
|
||||
self.layer_tree = layer_tree
|
||||
self.message_box = message_box
|
||||
self.result_table = result_table
|
||||
|
||||
self.layer_load.connect(layer_tree.add_layer)
|
||||
self.layer_load.connect(pair_canvas.add_layer)
|
||||
# self.layer_load.connect(message_box.add_layer)
|
||||
|
||||
|
||||
def setup(self, file=None):
|
||||
self.is_init = True
|
||||
self.file = file
|
||||
if file is None:
|
||||
self.file = Path(self.root)/'project'/'untitled.prj'
|
||||
self.root = str(Path(self.file).parent)
|
||||
dir_name = os.path.dirname(self.file)
|
||||
if not os.path.exists(dir_name):
|
||||
os.makedirs(dir_name, exist_ok=True)
|
||||
if not os.path.exists(self.file):
|
||||
with open(self.file, 'w') as f:
|
||||
pass
|
||||
else:
|
||||
self.load()
|
||||
# self.project_created.emit()
|
||||
self.project_init.emit(True)
|
||||
|
||||
def save(self):
|
||||
data_dict = {
|
||||
'cell_size': self.cell_size,
|
||||
'max_memory': self.max_memory,
|
||||
'max_threads': self.max_threads,
|
||||
'root': self.root,
|
||||
'layers': [ layer.to_dict() for layer in self.layers.values() ],
|
||||
'results': []
|
||||
}
|
||||
with open(self.file, 'w') as f:
|
||||
yaml.safe_dump(data_dict, f)
|
||||
# yaml.safe_dump(data_dict, open(self.file, 'w'))
|
||||
|
||||
|
||||
def clear(self):
|
||||
'''
|
||||
clear all layers
|
||||
'''
|
||||
self.layers = dict()
|
||||
self.layer_tree.clear()
|
||||
self.pair_canvas.clear()
|
||||
self.message_box.clear()
|
||||
self.result_table.clear()
|
||||
|
||||
def load(self):
|
||||
with open(self.file, 'r') as f:
|
||||
data = yaml.safe_load(f)
|
||||
if data is None:
|
||||
return
|
||||
# data = yaml.safe_load(open(self.file, 'r'))
|
||||
self.cell_size = data['cell_size']
|
||||
self.max_memory = data['max_memory']
|
||||
self.max_threads = data['max_threads']
|
||||
self.root = data['root']
|
||||
self.layers = dict()
|
||||
for layer in data['layers']:
|
||||
player = PairLayer.from_dict(layer)
|
||||
if player.check():
|
||||
self.layers[player.id] = player
|
||||
self.layer_load.emit(player.id)
|
||||
|
||||
def add_layer(self, pth1, pth2):
|
||||
self.root = str(Path(pth1).parent)
|
||||
player = PairLayer(pth1, pth2, self.cell_size)
|
||||
if player.check():
|
||||
# self.layers.append(player)
|
||||
self.layers[player.id] = player
|
||||
self.layer_load.emit(player.id)
|
||||
else:
|
||||
self.message_box.error(player.msg)
|
||||
|
||||
class VectorLayer:
|
||||
pass
|
||||
|
||||
class GridLayer:
|
||||
|
||||
def set_render(self):
|
||||
symbol_layer = QgsSimpleLineSymbolLayer()
|
||||
symbol_layer.setWidth(1)
|
||||
symbol_layer.setColor(QColor.fromRgb(255,255,255, 100))
|
||||
|
||||
symbol = QgsLineSymbol()
|
||||
symbol.changeSymbolLayer(0, symbol_layer)
|
||||
|
||||
render = QgsSingleSymbolRenderer(symbol)
|
||||
self.lines_layer.setRenderer(render)
|
||||
|
||||
|
||||
def __init__(self, cell_size, ds):
|
||||
self.cell_size = cell_size
|
||||
self.ds = ds
|
||||
|
||||
proj = ds.GetProjection()
|
||||
geo = ds.GetGeoTransform()
|
||||
self.proj = proj
|
||||
self.geo = geo
|
||||
self.x_size = ds.RasterXSize
|
||||
self.y_size = ds.RasterYSize
|
||||
|
||||
self.x_min = geo[0]
|
||||
self.y_min = geo[3]
|
||||
self.x_res = geo[1]
|
||||
self.y_res = geo[5]
|
||||
self.x_max = self.x_min + self.x_res * self.x_size
|
||||
self.y_max = self.y_min + self.y_res * self.y_size
|
||||
self.x_lines = []
|
||||
for xi in range(self.x_size // self.cell_size[0]):
|
||||
self.x_lines.append(self.x_min + self.x_res * xi * self.cell_size[0])
|
||||
if self.x_lines[-1] == self.x_max:
|
||||
self.x_lines.pop()
|
||||
self.x_lines.append(self.x_max)
|
||||
self.y_lines = []
|
||||
for yi in range(self.y_size // self.cell_size[1]):
|
||||
self.y_lines.append(self.y_min + self.y_res * yi * self.cell_size[1])
|
||||
if self.y_lines[-1] == self.y_max:
|
||||
self.y_lines.pop()
|
||||
self.y_lines.append(self.y_max)
|
||||
crs = QgsCoordinateReferenceSystem()
|
||||
crs.createFromString('WKT:{}'.format(ds.GetProjection()))
|
||||
# print(crs)
|
||||
lines_layer = QgsVectorLayer('LineString?crs={}'.format(crs.toProj()), 'temp-grid-outline', "memory")
|
||||
if not lines_layer.isValid():
|
||||
Project().message_box.error('Failed to create grid outline layer')
|
||||
return
|
||||
lines_layer.setLabelsEnabled(False)
|
||||
lines_layer.startEditing()
|
||||
features = []
|
||||
for x in self.x_lines:
|
||||
line = QgsFeature()
|
||||
line.setGeometry(QgsGeometry.fromPolylineXY([QgsPointXY(x, self.y_min), QgsPointXY(x, self.y_max)]))
|
||||
features.append(line)
|
||||
for y in self.y_lines:
|
||||
line = QgsFeature()
|
||||
line.setGeometry(QgsGeometry.fromPolylineXY([QgsPointXY(self.x_min, y), QgsPointXY(self.x_max, y)]))
|
||||
features.append(line)
|
||||
lines_layer.addFeatures(features)
|
||||
lines_layer.commitChanges()
|
||||
self.lines_layer = lines_layer
|
||||
|
||||
self.set_render()
|
||||
# self.x_lines = [ self.x_min + i * self.x_res for i in range(self.x_size) ]
|
||||
|
||||
@property
|
||||
def grid_layer(self):
|
||||
return self.lines_layer
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'cell_size': self.cell_size
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def from_dict(data):
|
||||
return GridLayer()
|
||||
|
||||
class PairLayer:
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'pth1': self.pth1,
|
||||
'pth2': self.pth2,
|
||||
'l1_name': self.l1_name,
|
||||
'l2_name': self.l2_name,
|
||||
'cell_size': self.cell_size,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def from_dict(data):
|
||||
layer = PairLayer(data['pth1'], data['pth2'], data['cell_size'])
|
||||
layer.l1_name = data['l1_name']
|
||||
layer.l2_name = data['l2_name']
|
||||
# layer.grid_layer = GridLayer.from_dict(data['grid_layer'])
|
||||
return layer
|
||||
def __init__(self, pth1, pth2, cell_size) -> None:
|
||||
self.pth1 = pth1
|
||||
self.pth2 = pth2
|
||||
self.id = str(uuid.uuid1())
|
||||
|
||||
self.l1_name = os.path.basename(pth1)
|
||||
self.l2_name = os.path.basename(pth2)
|
||||
|
||||
self.cell_size = cell_size
|
||||
|
||||
# self.grid_layer = GridLayer(cell_size)
|
||||
|
||||
self.msg = ''
|
||||
|
||||
def check(self):
|
||||
if not os.path.exists(self.pth1):
|
||||
self.msg = '图层1不存在'
|
||||
return False
|
||||
if not os.path.exists(self.pth2):
|
||||
self.msg = '图层2不存在'
|
||||
return False
|
||||
|
||||
ds1 = gdal.Open(self.pth1)
|
||||
ds2 = gdal.Open(self.pth2)
|
||||
if ds1 is None or ds2 is None:
|
||||
self.msg = '图层打开失败'
|
||||
return False
|
||||
|
||||
if ds1.RasterXSize != ds2.RasterXSize or ds1.RasterYSize != ds2.RasterYSize:
|
||||
self.msg = '图层尺寸不一致'
|
||||
return False
|
||||
|
||||
self.grid_layer = GridLayer(self.cell_size, ds1)
|
||||
|
||||
del ds1
|
||||
del ds2
|
||||
|
||||
self.l1 = QgsRasterLayer(self.pth1, self.l1_name)
|
||||
self.l2 = QgsRasterLayer(self.pth2, self.l2_name)
|
||||
|
||||
return True
|
@ -2,7 +2,7 @@ from datetime import datetime
|
||||
import os
|
||||
from typing import Tuple
|
||||
from PyQt5.QtCore import QSettings
|
||||
from utils.license import LicenseHelper
|
||||
from rscder.utils.license import LicenseHelper
|
||||
|
||||
class Settings(QSettings):
|
||||
|
||||
@ -16,6 +16,25 @@ class Settings(QSettings):
|
||||
def __exit__(self, *args, **kargs):
|
||||
self.endGroup()
|
||||
|
||||
class Plugin:
|
||||
|
||||
PRE='plugin'
|
||||
|
||||
@property
|
||||
def root(self):
|
||||
return './3rd'
|
||||
|
||||
@property
|
||||
def plugins(self):
|
||||
with Settings(Settings.Plugin.PRE) as s:
|
||||
return s.value('plugins', [])
|
||||
|
||||
@plugins.setter
|
||||
def plugins(self, value):
|
||||
with Settings(Settings.Plugin.PRE) as s:
|
||||
s.setValue('plugins', value)
|
||||
|
||||
|
||||
class Project:
|
||||
|
||||
PRE= 'project'
|
@ -1,11 +0,0 @@
|
||||
from functools import wraps
|
||||
|
||||
def as_menu(D, name, icon=None, shortcut=None, tip=None, checkable=False, signal=None, callback=None, enabled=True):
|
||||
|
||||
def func(f):
|
||||
@wraps(f)
|
||||
def wrapper(*args, **kwargs):
|
||||
return f(*args, **kwargs)
|
||||
D.addMenu(name, icon, shortcut, tip, checkable, signal, callback, enabled, wrapper)
|
||||
return f
|
||||
return func
|
121
utils/project.py
@ -1,121 +0,0 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from osgeo import gdal, gdal_array
|
||||
from utils.setting import Settings
|
||||
from qgis.core import QgsRasterLayer
|
||||
from PyQt5.QtCore import QObject, pyqtSignal
|
||||
|
||||
def singleton(cls):
|
||||
_instance = {}
|
||||
|
||||
def inner(*args, **kargs):
|
||||
if cls not in _instance:
|
||||
_instance[cls] = cls(*args, **kargs)
|
||||
return _instance[cls]
|
||||
return inner
|
||||
|
||||
@singleton
|
||||
class Project(QObject):
|
||||
|
||||
project_init = pyqtSignal(bool)
|
||||
|
||||
def __init__(self,
|
||||
parent=None):
|
||||
super().__init__(parent)
|
||||
self.is_init = False
|
||||
self.cell_size = Settings.Project().cell_size
|
||||
self.max_memory = Settings.Project().max_memory
|
||||
self.max_threads = Settings.Project().max_threads
|
||||
self.root = Settings.General().root
|
||||
|
||||
def connect(self, pair_canvas,
|
||||
layer_tree,
|
||||
message_box,
|
||||
result_table):
|
||||
self.pair_canvas = pair_canvas
|
||||
self.layer_tree = layer_tree
|
||||
self.message_box = message_box
|
||||
self.result_table = result_table
|
||||
|
||||
def setup(self, file=None):
|
||||
self.is_init = True
|
||||
|
||||
if file is None:
|
||||
self.file = Path(self.root)/'project'/'untitled.cdp'
|
||||
dir_name = os.path.dirname(self.file)
|
||||
if not os.path.exists(dir_name):
|
||||
os.makedirs(dir_name, exist_ok=True)
|
||||
if not self.file.exists():
|
||||
f = self.file.open('w')
|
||||
f.close()
|
||||
else:
|
||||
self.load()
|
||||
# self.project_created.emit()
|
||||
self.project_init.emit(True)
|
||||
|
||||
def save(self):
|
||||
pass
|
||||
|
||||
def clear(self):
|
||||
'''
|
||||
clear all layers
|
||||
'''
|
||||
self.layer_tree.clear()
|
||||
self.pair_canvas.clear()
|
||||
self.message_box.clear()
|
||||
self.result_table.clear()
|
||||
|
||||
def load(self):
|
||||
pass
|
||||
|
||||
def add_layer(self, pth1, pth2):
|
||||
player = PairLayer(pth1, pth2)
|
||||
if player.check():
|
||||
self.layer_tree.add_layer(player)
|
||||
else:
|
||||
self.message_box.show_message(player.msg)
|
||||
|
||||
class VectorLayer:
|
||||
pass
|
||||
|
||||
class GridLayer:
|
||||
pass
|
||||
|
||||
class PairLayer:
|
||||
|
||||
def __init__(self, pth1, pth2) -> None:
|
||||
self.pth1 = pth1
|
||||
self.pth2 = pth2
|
||||
|
||||
self.l1_name = os.path.basename(pth1)
|
||||
self.l2_name = os.path.basename(pth2)
|
||||
|
||||
self.grid_layer = GridLayer()
|
||||
|
||||
self.msg = ''
|
||||
|
||||
def check(self):
|
||||
if not os.path.exists(self.pth1):
|
||||
self.msg = '图层1不存在'
|
||||
return False
|
||||
if not os.path.exists(self.pth2):
|
||||
self.msg = '图层2不存在'
|
||||
return False
|
||||
|
||||
ds1 = gdal.Open(self.pth1)
|
||||
ds2 = gdal.Open(self.pth2)
|
||||
if ds1 is None or ds2 is None:
|
||||
self.msg = '图层打开失败'
|
||||
return False
|
||||
|
||||
if ds1.RasterXSize != ds2.RasterXSize or ds1.RasterYSize != ds2.RasterYSize:
|
||||
self.msg = '图层尺寸不一致'
|
||||
return False
|
||||
|
||||
del ds1
|
||||
del ds2
|
||||
|
||||
self.l1 = QgsRasterLayer(self.pth1, self.l1_name)
|
||||
self.l2 = QgsRasterLayer(self.pth2, self.l2_name)
|
||||
|
||||
return True
|
13
未命名.prj
Normal file
@ -0,0 +1,13 @@
|
||||
cell_size: &id001
|
||||
- 100
|
||||
- 100
|
||||
layers:
|
||||
- cell_size: *id001
|
||||
l1_name: p122_r032_l5_20090915.tif
|
||||
l2_name: p122_r032_l8_20170804.tif
|
||||
pth1: F:/LZY_DATA/p122r032/p122_r032_l5_20090915.tif
|
||||
pth2: F:/LZY_DATA/p122r032/p122_r032_l8_20170804.tif
|
||||
max_memory: 100
|
||||
max_threads: 4
|
||||
results: []
|
||||
root: F:\LZY_DATA\p122r032
|