mirror of https://gitlab.com/pamhyr/pamhyr2
Compare commits
16 Commits
ff9d25412c
...
17a18dde18
| Author | SHA1 | Date |
|---|---|---|
|
|
17a18dde18 | |
|
|
044818072e | |
|
|
d31be61af8 | |
|
|
a8a408b5d5 | |
|
|
879c151524 | |
|
|
7990a60d8b | |
|
|
8aa0e25da2 | |
|
|
1dca9b98df | |
|
|
7640123299 | |
|
|
e6dd983f97 | |
|
|
84486c03ed | |
|
|
68b62a5630 | |
|
|
990d44dd07 | |
|
|
bf95b7f7e6 | |
|
|
861b78b928 | |
|
|
57a80d00aa |
|
|
@ -17,7 +17,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from numpy import sign
|
from numpy import sign, interp
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
||||||
from tools import logger_color_red, logger_color_reset, logger_exception
|
from tools import logger_color_red, logger_color_reset, logger_exception
|
||||||
|
|
@ -273,7 +273,7 @@ class InternalMeshing(AMeshingTool):
|
||||||
sect2.point(start2+len2).name = tag2
|
sect2.point(start2+len2).name = tag2
|
||||||
sect2.modified()
|
sect2.modified()
|
||||||
|
|
||||||
def update_rk(self, reach,
|
def update_rk(self, reach, begin_rk, end_rk,
|
||||||
step: float = 50,
|
step: float = 50,
|
||||||
limites=[-1, -1],
|
limites=[-1, -1],
|
||||||
origin=0,
|
origin=0,
|
||||||
|
|
@ -297,15 +297,25 @@ class InternalMeshing(AMeshingTool):
|
||||||
# 1: up -> downstream
|
# 1: up -> downstream
|
||||||
# 2: down -> upstream
|
# 2: down -> upstream
|
||||||
# else: keep current orientation
|
# else: keep current orientation
|
||||||
|
old_orientation = sign(reach.profiles[-1].rk - reach.profiles[0].rk)
|
||||||
if orientation == 1:
|
if orientation == 1:
|
||||||
sgn = 1.0
|
sgn = 1.0
|
||||||
elif orientation == 2:
|
elif orientation == 2:
|
||||||
sgn = -1.0
|
sgn = -1.0
|
||||||
else:
|
else:
|
||||||
sgn = sign(reach.profiles[-1].rk - reach.profiles[0].rk)
|
sgn = old_orientation
|
||||||
|
|
||||||
rk = [0.0]*nprof
|
new_rk = [0.0]*nprof
|
||||||
rk[origin] = origin_value
|
new_rk[origin] = origin_value
|
||||||
|
|
||||||
|
frictions = reach._parent.frictions
|
||||||
|
|
||||||
|
old_begin_rk = list(map(lambda x: x * old_orientation,
|
||||||
|
begin_rk))
|
||||||
|
old_end_rk = list(map(lambda x: x * old_orientation,
|
||||||
|
end_rk))
|
||||||
|
old_rk = list(map(lambda x: x * old_orientation,
|
||||||
|
reach.get_rk()))
|
||||||
|
|
||||||
if origin < nprof - 1:
|
if origin < nprof - 1:
|
||||||
for i in range(origin+1, nprof):
|
for i in range(origin+1, nprof):
|
||||||
|
|
@ -316,7 +326,7 @@ class InternalMeshing(AMeshingTool):
|
||||||
d2 = reach.profiles[i-1].named_point(
|
d2 = reach.profiles[i-1].named_point(
|
||||||
directrices[1]
|
directrices[1]
|
||||||
).dist_2d(reach.profiles[i].named_point(directrices[1]))
|
).dist_2d(reach.profiles[i].named_point(directrices[1]))
|
||||||
rk[i] = rk[i-1] + (sgn * (d1 + d2) / 2)
|
new_rk[i] = new_rk[i-1] + (sgn * (d1 + d2) / 2)
|
||||||
if origin > 0:
|
if origin > 0:
|
||||||
for i in reversed(range(0, origin)):
|
for i in reversed(range(0, origin)):
|
||||||
# 2D
|
# 2D
|
||||||
|
|
@ -326,6 +336,11 @@ class InternalMeshing(AMeshingTool):
|
||||||
d2 = reach.profiles[i+1].named_point(
|
d2 = reach.profiles[i+1].named_point(
|
||||||
directrices[1]
|
directrices[1]
|
||||||
).dist_2d(reach.profiles[i].named_point(directrices[1]))
|
).dist_2d(reach.profiles[i].named_point(directrices[1]))
|
||||||
rk[i] = rk[i+1] - (sgn * (d1 + d2) / 2)
|
new_rk[i] = new_rk[i+1] - (sgn * (d1 + d2) / 2)
|
||||||
|
|
||||||
return rk
|
new_begin_rk = interp(old_begin_rk, old_rk, new_rk)
|
||||||
|
new_end_rk = interp(old_end_rk, old_rk, new_rk)
|
||||||
|
if abs(sgn - old_orientation) > 0.1: # orientation changed
|
||||||
|
return new_rk, new_end_rk, new_begin_rk
|
||||||
|
else:
|
||||||
|
return new_rk, new_begin_rk, new_end_rk
|
||||||
|
|
|
||||||
|
|
@ -749,8 +749,8 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||||
if zz[i] >= z and zz[i+1] < z:
|
if zz[i] >= z and zz[i+1] < z:
|
||||||
y = np.interp(
|
y = np.interp(
|
||||||
z,
|
z,
|
||||||
[zz[i], zz[i+1]],
|
[zz[i+1], zz[i]],
|
||||||
[station[i], station[i+1]]
|
[station[i+1], station[i]]
|
||||||
)
|
)
|
||||||
line.append([y, z])
|
line.append([y, z])
|
||||||
|
|
||||||
|
|
@ -839,11 +839,8 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||||
|
|
||||||
for i in range(self.number_points-1):
|
for i in range(self.number_points-1):
|
||||||
if zz[i] > z and zz[i+1] <= z:
|
if zz[i] > z and zz[i+1] <= z:
|
||||||
y = np.interp(
|
fact = (z - zz[i]) / (zz[i+1] - zz[i])
|
||||||
z,
|
y = station[i] + fact * (station[i+1] - station[i])
|
||||||
[zz[i], zz[i+1]],
|
|
||||||
[station[i], station[i+1]]
|
|
||||||
)
|
|
||||||
start.append(y)
|
start.append(y)
|
||||||
|
|
||||||
end = []
|
end = []
|
||||||
|
|
@ -852,11 +849,8 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||||
|
|
||||||
for i in reversed(range(self.number_points-1)):
|
for i in reversed(range(self.number_points-1)):
|
||||||
if zz[i] <= z and zz[i+1] > z:
|
if zz[i] <= z and zz[i+1] > z:
|
||||||
y = np.interp(
|
fact = (z - zz[i]) / (zz[i+1] - zz[i])
|
||||||
z,
|
y = station[i] + fact * (station[i+1] - station[i])
|
||||||
[zz[i], zz[i+1]],
|
|
||||||
[station[i], station[i+1]]
|
|
||||||
)
|
|
||||||
end.append(y)
|
end.append(y)
|
||||||
|
|
||||||
if len(start) != len(end):
|
if len(start) != len(end):
|
||||||
|
|
@ -887,33 +881,25 @@ class ProfileXYZ(Profile, SQLSubModel):
|
||||||
|
|
||||||
# Interpolate points at river left side
|
# Interpolate points at river left side
|
||||||
if (i_left > 0):
|
if (i_left > 0):
|
||||||
x = np.interp(
|
fact = (z - self.point(i_left).z) / (self.point(i_left - 1).z
|
||||||
z,
|
- self.point(i_left).z)
|
||||||
[self.point(i_left).z, self.point(i_left - 1).z],
|
x = self.point(i_left).x + fact * (self.point(i_left - 1).x
|
||||||
[self.point(i_left).x, self.point(i_left - 1).x]
|
- self.point(i_left).x)
|
||||||
)
|
y = self.point(i_left).y + fact * (self.point(i_left - 1).y
|
||||||
y = np.interp(
|
- self.point(i_left).y)
|
||||||
z,
|
pt_left = PointXYZ(x=x, y=y, z=z, name="wl_left")
|
||||||
[self.point(i_left).z, self.point(i_left - 1).z],
|
|
||||||
[self.point(i_left).y, self.point(i_left - 1).y]
|
|
||||||
)
|
|
||||||
pt_left = PointXYZ(x, y, z, name="wl_left")
|
|
||||||
else:
|
else:
|
||||||
pt_left = self.point(0)
|
pt_left = self.point(0)
|
||||||
|
|
||||||
# Interpolate points at river right side
|
# Interpolate points at river right side
|
||||||
if (i_right < self.number_points - 1):
|
if (i_right < self.number_points - 1):
|
||||||
x = np.interp(
|
fact = (z - self.point(i_right).z) / (self.point(i_right + 1).z -
|
||||||
z,
|
self.point(i_right).z)
|
||||||
[self.point(i_right).z, self.point(i_right + 1).z],
|
x = self.point(i_right).x + fact * (self.point(i_right + 1).x -
|
||||||
[self.point(i_right).x, self.point(i_right + 1).x]
|
self.point(i_right).x)
|
||||||
)
|
y = self.point(i_right).y + fact * (self.point(i_right + 1).y -
|
||||||
y = np.interp(
|
self.point(i_right).y)
|
||||||
z,
|
pt_right = PointXYZ(x=x, y=y, z=z, name="wl_right")
|
||||||
[self.point(i_right).z, self.point(i_right + 1).z],
|
|
||||||
[self.point(i_right).y, self.point(i_right + 1).y]
|
|
||||||
)
|
|
||||||
pt_right = PointXYZ(x, y, z, name="wl_right")
|
|
||||||
else:
|
else:
|
||||||
pt_right = self.point(self.number_points - 1)
|
pt_right = self.point(self.number_points - 1)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -482,6 +482,8 @@ class Study(SQLModel):
|
||||||
river = self.load_scenario(scenario)
|
river = self.load_scenario(scenario)
|
||||||
self._river = river
|
self._river = river
|
||||||
|
|
||||||
|
self.status.scenario = scenario
|
||||||
|
|
||||||
if reduce(
|
if reduce(
|
||||||
lambda a, s: a or (s.parent is scenario),
|
lambda a, s: a or (s.parent is scenario),
|
||||||
self.scenarios.lst,
|
self.scenarios.lst,
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,8 @@ class Rubar3(CommandLineSolver):
|
||||||
("rubarbe_condav", "3"),
|
("rubarbe_condav", "3"),
|
||||||
("rubarbe_regime", "0"),
|
("rubarbe_regime", "0"),
|
||||||
("rubarbe_iodev", "n"),
|
("rubarbe_iodev", "n"),
|
||||||
# ("rubarbe_iodebord", ""),
|
("rubarbe_iodebord", ""),
|
||||||
# ("rubarbe_iostockage", ""),
|
("rubarbe_iostockage", ""),
|
||||||
("rubarbe_iopdt", "y"),
|
("rubarbe_iopdt", "y"),
|
||||||
("rubarbe_iovis", "n"),
|
("rubarbe_iovis", "n"),
|
||||||
("rubarbe_rep", "n"),
|
("rubarbe_rep", "n"),
|
||||||
|
|
@ -73,36 +73,37 @@ class Rubar3(CommandLineSolver):
|
||||||
("rubarbe_tf_4", "y"),
|
("rubarbe_tf_4", "y"),
|
||||||
("rubarbe_tf_5", "y"),
|
("rubarbe_tf_5", "y"),
|
||||||
("rubarbe_tf_6", "n"),
|
("rubarbe_tf_6", "n"),
|
||||||
("rubarbe_trased", "y"),
|
("rubarbe_trased", "n"),
|
||||||
# ("rubarbe_optfpc", "0"),
|
("rubarbe_optfpc", "0"),
|
||||||
# ("rubarbe_ros", "2650.0"),
|
# trased parameters
|
||||||
# ("rubarbe_dm", "0.1"),
|
("rubarbe_ros", "2650.0"),
|
||||||
# ("rubarbe_segma", "1.0"),
|
("rubarbe_dm", "0.1"),
|
||||||
|
("rubarbe_segma", "1.0"),
|
||||||
# Sediment parameters
|
# Sediment parameters
|
||||||
# ("rubarbe_sediment_ros", "2650.0"),
|
("rubarbe_sediment_ros", "2650.0"),
|
||||||
# ("rubarbe_sediment_por", "0.4"),
|
("rubarbe_sediment_por", "0.4"),
|
||||||
# ("rubarbe_sediment_dcharg", "0.0"),
|
("rubarbe_sediment_dcharg", "0.0"),
|
||||||
# ("rubarbe_sediment_halfa", "1.0"),
|
("rubarbe_sediment_halfa", "1.0"),
|
||||||
# ("rubarbe_sediment_mult_1", "1.0"),
|
("rubarbe_sediment_mult_1", "1.0"),
|
||||||
# ("rubarbe_sediment_mult_2", ""),
|
("rubarbe_sediment_mult_2", ""),
|
||||||
# ("rubarbe_sediment_mult_3", ""),
|
("rubarbe_sediment_mult_3", ""),
|
||||||
# ("rubarbe_sediment_mult_4", ""),
|
("rubarbe_sediment_mult_4", ""),
|
||||||
# ("rubarbe_sediment_mult_5", ""),
|
("rubarbe_sediment_mult_5", ""),
|
||||||
# ("rubarbe_sediment_visc", "0.047"),
|
("rubarbe_sediment_visc", "0.047"),
|
||||||
# ("rubarbe_sediment_opts", "6"),
|
("rubarbe_sediment_opts", "6"),
|
||||||
# ("rubarbe_sediment_odchar", "0"),
|
("rubarbe_sediment_odchar", "0"),
|
||||||
# ("rubarbe_sediment_unisol", "1"),
|
("rubarbe_sediment_unisol", "1"),
|
||||||
# ("rubarbe_sediment_typdef", "3"),
|
("rubarbe_sediment_typdef", "3"),
|
||||||
# ("rubarbe_sediment_depot", "2"),
|
("rubarbe_sediment_depot", "2"),
|
||||||
# ("rubarbe_sediment_choixc", "2"),
|
("rubarbe_sediment_choixc", "2"),
|
||||||
# ("rubarbe_sediment_option", "2"),
|
("rubarbe_sediment_option", "2"),
|
||||||
# ("rubarbe_sediment_capsol", "1"),
|
("rubarbe_sediment_capsol", "1"),
|
||||||
# ("rubarbe_sediment_bmiu", "0.85"),
|
("rubarbe_sediment_bmiu", "0.85"),
|
||||||
# ("rubarbe_sediment_demix", "0"),
|
("rubarbe_sediment_demix", "0"),
|
||||||
# ("rubarbe_sediment_defond", "1"),
|
("rubarbe_sediment_defond", "1"),
|
||||||
# ("rubarbe_sediment_varcons", "1"),
|
("rubarbe_sediment_varcons", "1"),
|
||||||
# ("rubarbe_sediment_dchard", "0.0"),
|
("rubarbe_sediment_dchard", "0.0"),
|
||||||
# ("rubarbe_sediment_dchars", "0.0"),
|
("rubarbe_sediment_dchars", "0.0"),
|
||||||
]
|
]
|
||||||
|
|
||||||
return lst
|
return lst
|
||||||
|
|
@ -169,7 +170,7 @@ class Rubar3(CommandLineSolver):
|
||||||
it = iter(params)
|
it = iter(params)
|
||||||
|
|
||||||
line = 0
|
line = 0
|
||||||
while line < 25:
|
while line < 27:
|
||||||
param = next(it)
|
param = next(it)
|
||||||
name = param.name
|
name = param.name
|
||||||
value = param.value
|
value = param.value
|
||||||
|
|
@ -394,25 +395,59 @@ class Rubar3(CommandLineSolver):
|
||||||
lm = len(reach) + 1
|
lm = len(reach) + 1
|
||||||
f.write(f"{lm:>6}\n")
|
f.write(f"{lm:>6}\n")
|
||||||
|
|
||||||
def get_stricklers_from_rk(rk):
|
lst = list(filter(
|
||||||
return next(
|
lambda f: f.is_full_defined(),
|
||||||
map(
|
edge.frictions.frictions
|
||||||
lambda s: (
|
))
|
||||||
s.begin_strickler.medium if version == "2"
|
|
||||||
else s.begin_strickler.minor
|
rk_min = 9999999.9
|
||||||
),
|
rk_max = -9999999.9
|
||||||
filter(
|
coeff_min = -1.0
|
||||||
lambda f: rk in f,
|
coeff_max = -1.0
|
||||||
edge.frictions.lst
|
for s in lst: # TODO optimise ?
|
||||||
)
|
if s.begin_rk > rk_max:
|
||||||
|
rk_max = s.begin_rk
|
||||||
|
coeff_max = s.begin_strickler
|
||||||
|
if s.begin_rk < rk_min:
|
||||||
|
rk_min = s.begin_rk
|
||||||
|
coeff_min = s.begin_strickler
|
||||||
|
if s.end_rk > rk_max:
|
||||||
|
rk_max = s.end_rk
|
||||||
|
coeff_max = s.end_strickler
|
||||||
|
if s.end_rk < rk_min:
|
||||||
|
rk_min = s.end_rk
|
||||||
|
coeff_min = s.end_strickler
|
||||||
|
|
||||||
|
def get_stricklers_from_rk(rk, lst):
|
||||||
|
|
||||||
|
coeff = None
|
||||||
|
if rk > rk_max:
|
||||||
|
coeff = coeff_max
|
||||||
|
elif rk < rk_min:
|
||||||
|
coeff = coeff_min
|
||||||
|
else:
|
||||||
|
for s in lst:
|
||||||
|
print(s.begin_rk, s.end_rk)
|
||||||
|
if (rk >= s.begin_rk and rk <= s.end_rk or
|
||||||
|
rk <= s.begin_rk and rk >= s.end_rk):
|
||||||
|
coeff = s.begin_strickler # TODO: inerpolate
|
||||||
|
break
|
||||||
|
|
||||||
|
# TODO interpolation if rk is not in frictons
|
||||||
|
|
||||||
|
if coeff is None:
|
||||||
|
logger.error(
|
||||||
|
"Study frictions are not fully defined"
|
||||||
)
|
)
|
||||||
)
|
return None
|
||||||
|
|
||||||
|
return coeff.medium if version == "2" else coeff.minor
|
||||||
|
|
||||||
ind = 1
|
ind = 1
|
||||||
for mail in edge.reach.inter_profiles_rk():
|
for mail in edge.reach.inter_profiles_rk():
|
||||||
coef = get_stricklers_from_rk(mail)
|
coef = get_stricklers_from_rk(mail, lst)
|
||||||
|
if coeff is not None:
|
||||||
f.write(f"{ind:>6} {coef:>12.5f}")
|
f.write(f"{ind:>6} {coef:>12.5f}")
|
||||||
|
|
||||||
ind += 1
|
ind += 1
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
|
@ -583,27 +618,30 @@ class Rubar3(CommandLineSolver):
|
||||||
|
|
||||||
for reach, lm in reachs:
|
for reach, lm in reachs:
|
||||||
# First profile
|
# First profile
|
||||||
e, s, q, z = read_data_line(f)
|
h, s, q, z = read_data_line(f)
|
||||||
set_and_compute_limites(reach, 0, z, q, s)
|
set_and_compute_limites(reach, 0, z+h, q, s)
|
||||||
|
|
||||||
# For each profile
|
# For each profile
|
||||||
ind = 1
|
ind = 1
|
||||||
pe, ps, pq, pz = read_data_line(f)
|
ph, ps, pq, pz = read_data_line(f)
|
||||||
while ind < lm - 2:
|
while ind < lm - 2:
|
||||||
e, s, q, z = read_data_line(f)
|
h, s, q, z = read_data_line(f)
|
||||||
set_and_compute_limites(
|
set_and_compute_limites(
|
||||||
reach, ind,
|
reach, ind,
|
||||||
(pz + z) / 2,
|
(ph + pz + ph + h) / 2,
|
||||||
(pq + q) / 2,
|
(pz + s) / 2,
|
||||||
(ps + s) / 2
|
(pq + q) / 2
|
||||||
)
|
)
|
||||||
|
|
||||||
pe, ps, pq, pz = z, s, q, e
|
ph = h
|
||||||
|
ps = s
|
||||||
|
pq = q
|
||||||
|
pz = z
|
||||||
ind += 1
|
ind += 1
|
||||||
|
|
||||||
# Last profile
|
# Last profile
|
||||||
e, s, q, z = read_data_line(f)
|
h, s, q, z = read_data_line(f)
|
||||||
set_and_compute_limites(reach, ind, z, q, s)
|
set_and_compute_limites(reach, ind, z+h, q, s)
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
def results(self, study, repertory, qlog=None, name="0"):
|
def results(self, study, repertory, qlog=None, name="0"):
|
||||||
|
|
|
||||||
|
|
@ -237,22 +237,40 @@ class UpdateRKCommand(QUndoCommand):
|
||||||
self._data = data
|
self._data = data
|
||||||
self._mesher = mesher
|
self._mesher = mesher
|
||||||
self._rks = reach.get_rk()
|
self._rks = reach.get_rk()
|
||||||
|
self._frictions = [f for f in reach._parent.frictions.frictions
|
||||||
|
if f.is_full_defined()]
|
||||||
|
self._begin_rk = [f.begin_rk for f in self._frictions]
|
||||||
|
self._end_rk = [f.end_rk for f in self._frictions]
|
||||||
|
|
||||||
self._new_rks = None
|
self._new_rks = None
|
||||||
|
self._new_begin_rk = None
|
||||||
|
self._new_end_rk = None
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
for rk, profile in zip(self._rks, self._reach.profiles):
|
for rk, profile in zip(self._rks, self._reach.profiles):
|
||||||
profile.rk = rk
|
profile.rk = rk
|
||||||
|
|
||||||
|
for begin_rk, end_rk, friction in zip(self._begin_rk,
|
||||||
|
self._end_rk,
|
||||||
|
self._frictions):
|
||||||
|
friction.begin_rk = begin_rk
|
||||||
|
friction.end_rk = end_rk
|
||||||
|
|
||||||
def redo(self):
|
def redo(self):
|
||||||
if self._new_rks is None:
|
if self._new_rks is None:
|
||||||
self._new_rks = self._mesher.update_rk(
|
self._new_rks, self._new_begin_rk, self._new_end_rk = \
|
||||||
self._reach,
|
self._mesher.update_rk(
|
||||||
**self._data
|
self._reach, self._begin_rk, self._end_rk,
|
||||||
)
|
**self._data
|
||||||
|
)
|
||||||
|
|
||||||
for rk, profile in zip(self._new_rks, self._reach.profiles):
|
for rk, profile in zip(self._new_rks, self._reach.profiles):
|
||||||
profile.rk = rk
|
profile.rk = rk
|
||||||
|
for begin_rk, end_rk, friction in zip(self._new_begin_rk,
|
||||||
|
self._new_end_rk,
|
||||||
|
self._frictions):
|
||||||
|
friction.begin_rk = begin_rk
|
||||||
|
friction.end_rk = end_rk
|
||||||
|
|
||||||
|
|
||||||
class MeshingCommand(QUndoCommand):
|
class MeshingCommand(QUndoCommand):
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ from View.RunSolver.Window import (
|
||||||
|
|
||||||
from View.Results.Window import ResultsWindow
|
from View.Results.Window import ResultsWindow
|
||||||
from View.Results.CompareDialog import (
|
from View.Results.CompareDialog import (
|
||||||
CompareSolversWindow, CompareScenariosWindow
|
CompareScenariosWindow
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.RunSolver.WindowAdisTS import (
|
from View.RunSolver.WindowAdisTS import (
|
||||||
|
|
@ -153,7 +153,6 @@ define_model_action = [
|
||||||
"action_menu_edit_reach_sediment_layers", "action_menu_edit_reservoirs",
|
"action_menu_edit_reach_sediment_layers", "action_menu_edit_reservoirs",
|
||||||
"action_menu_edit_hydraulic_structures", "action_menu_additional_file",
|
"action_menu_edit_hydraulic_structures", "action_menu_additional_file",
|
||||||
"action_menu_results_last", "action_menu_open_results_from_file",
|
"action_menu_results_last", "action_menu_open_results_from_file",
|
||||||
# "action_menu_compare_results",
|
|
||||||
"action_menu_compare_scenarios_results",
|
"action_menu_compare_scenarios_results",
|
||||||
"action_menu_boundary_conditions_sediment",
|
"action_menu_boundary_conditions_sediment",
|
||||||
"action_menu_rep_additional_lines", "action_menu_output_rk",
|
"action_menu_rep_additional_lines", "action_menu_output_rk",
|
||||||
|
|
@ -301,7 +300,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
"action_menu_close": self.close_model,
|
"action_menu_close": self.close_model,
|
||||||
"action_menu_results_last": self.open_last_results,
|
"action_menu_results_last": self.open_last_results,
|
||||||
"action_menu_open_results_from_file": self.open_results_from_file,
|
"action_menu_open_results_from_file": self.open_results_from_file,
|
||||||
# "action_menu_compare_results": self.compare_results,
|
|
||||||
"action_menu_compare_scenarios_results":
|
"action_menu_compare_scenarios_results":
|
||||||
self.compare_results_scenarios,
|
self.compare_results_scenarios,
|
||||||
"action_menu_open_results_adists": self.open_results_adists,
|
"action_menu_open_results_adists": self.open_results_adists,
|
||||||
|
|
@ -1711,43 +1709,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
results=file_name[0]
|
results=file_name[0]
|
||||||
)
|
)
|
||||||
|
|
||||||
# def compare_results(self):
|
|
||||||
# if self._study is None:
|
|
||||||
# return
|
|
||||||
|
|
||||||
# run = CompareSolversWindow(
|
|
||||||
# study=self._study,
|
|
||||||
# config=self.conf,
|
|
||||||
# parent=self
|
|
||||||
# )
|
|
||||||
# if not run.exec():
|
|
||||||
# return
|
|
||||||
|
|
||||||
# results = self.diff_results(
|
|
||||||
# run.solver1, run.solver2
|
|
||||||
# )
|
|
||||||
|
|
||||||
# # At least one result not available
|
|
||||||
# if results is None:
|
|
||||||
# return
|
|
||||||
|
|
||||||
# # Windows already opened
|
|
||||||
# if self.sub_window_exists(
|
|
||||||
# CompareSolversWindow,
|
|
||||||
# data=[self._study, None] +
|
|
||||||
# [r._solver for r in results] +
|
|
||||||
# [r._repertory for r in results] +
|
|
||||||
# [r._name for r in results]
|
|
||||||
# ):
|
|
||||||
# return
|
|
||||||
|
|
||||||
# res = ResultsWindow(
|
|
||||||
# study=self._study,
|
|
||||||
# results=results,
|
|
||||||
# parent=self
|
|
||||||
# )
|
|
||||||
# res.show()
|
|
||||||
|
|
||||||
def compare_results_scenarios(self):
|
def compare_results_scenarios(self):
|
||||||
if self._study is None:
|
if self._study is None:
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -32,106 +32,14 @@ _translate = QCoreApplication.translate
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
class CompareSolversWindow(PamhyrDialog):
|
|
||||||
_pamhyr_ui = "CompareSolvers"
|
|
||||||
_pamhyr_name = "Compare solvers"
|
|
||||||
|
|
||||||
def __init__(self, study=None, config=None,
|
|
||||||
parent=None):
|
|
||||||
self._solver1 = None
|
|
||||||
self._solver2 = None
|
|
||||||
|
|
||||||
name = _translate("Solver", "Compare solvers")
|
|
||||||
super(CompareSolversWindow, self).__init__(
|
|
||||||
title=name,
|
|
||||||
study=study,
|
|
||||||
config=config,
|
|
||||||
options=[],
|
|
||||||
parent=parent
|
|
||||||
)
|
|
||||||
|
|
||||||
self.setup_solvers()
|
|
||||||
self.setup_connections()
|
|
||||||
self.select_last_solver()
|
|
||||||
|
|
||||||
def setup_solvers(self):
|
|
||||||
solvers = self._config.solvers
|
|
||||||
solvers_name = list(
|
|
||||||
map(
|
|
||||||
self._format_solver_name,
|
|
||||||
solvers
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.combobox_add_items("comboBox1", solvers_name)
|
|
||||||
self.combobox_add_items("comboBox2", solvers_name)
|
|
||||||
|
|
||||||
def setup_connections(self):
|
|
||||||
self.find(QPushButton, "pushButton_ok").clicked.connect(self.accept)
|
|
||||||
self.find(QPushButton, "pushButton_cancel")\
|
|
||||||
.clicked.connect(self.reject)
|
|
||||||
|
|
||||||
def select_last_solver(self):
|
|
||||||
solvers = self._config.solvers
|
|
||||||
last = self._config.last_solver_name
|
|
||||||
|
|
||||||
solver = list(
|
|
||||||
filter(
|
|
||||||
lambda s: s.name == last,
|
|
||||||
solvers
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if len(solver) != 0:
|
|
||||||
self.set_combobox_text(
|
|
||||||
"comboBox1",
|
|
||||||
self._format_solver_name(solver[0])
|
|
||||||
)
|
|
||||||
|
|
||||||
def _format_solver_name(self, solver):
|
|
||||||
return f"{solver.name} - ({solver._type})"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def solver1(self):
|
|
||||||
return self._solver1
|
|
||||||
|
|
||||||
@property
|
|
||||||
def solver2(self):
|
|
||||||
return self._solver2
|
|
||||||
|
|
||||||
def accept(self):
|
|
||||||
solver_name1 = self.get_combobox_text("comboBox1")
|
|
||||||
solver_name1 = solver_name1.rsplit(" - ", 1)[0]
|
|
||||||
|
|
||||||
self._solver1 = next(
|
|
||||||
filter(
|
|
||||||
lambda s: s.name == solver_name1,
|
|
||||||
self._config.solvers
|
|
||||||
)
|
|
||||||
)
|
|
||||||
solver_name2 = self.get_combobox_text("comboBox2")
|
|
||||||
solver_name2 = solver_name2.rsplit(" - ", 1)[0]
|
|
||||||
|
|
||||||
self._solver2 = next(
|
|
||||||
filter(
|
|
||||||
lambda s: s.name == solver_name2,
|
|
||||||
self._config.solvers
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
super(CompareSolversWindow, self).accept()
|
|
||||||
|
|
||||||
|
|
||||||
class CompareScenariosWindow(PamhyrDialog):
|
class CompareScenariosWindow(PamhyrDialog):
|
||||||
_pamhyr_ui = "CompareScenarios"
|
_pamhyr_ui = "CompareScenarios"
|
||||||
_pamhyr_name = "Compare scenarios"
|
_pamhyr_name = "Compare scenarios"
|
||||||
|
|
||||||
def __init__(self, study=None, config=None,
|
def __init__(self, study=None, config=None,
|
||||||
parent=None):
|
parent=None):
|
||||||
self._solver1 = None
|
self._solvers = []
|
||||||
self._solver2 = None
|
self._scenarios = []
|
||||||
self._scenario1 = None
|
|
||||||
self._scenario2 = None
|
|
||||||
|
|
||||||
name = _translate("Solver", "Compare solvers")
|
name = _translate("Solver", "Compare solvers")
|
||||||
super(CompareScenariosWindow, self).__init__(
|
super(CompareScenariosWindow, self).__init__(
|
||||||
|
|
@ -200,53 +108,42 @@ class CompareScenariosWindow(PamhyrDialog):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def solver1(self):
|
def solver1(self):
|
||||||
return self._solver1
|
return self._solvers[0]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def solver2(self):
|
def solver2(self):
|
||||||
return self._solver2
|
return self._solvers[1]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def scenario1(self):
|
def scenario1(self):
|
||||||
return self._scenario1
|
return self._scenarios[0]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def scenario2(self):
|
def scenario2(self):
|
||||||
return self._scenario2
|
return self._scenarios[1]
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
solver_name1 = self.get_combobox_text("comboBoxSolver1")
|
for cb in ["comboBoxSolver1", "comboBoxSolver2"]:
|
||||||
solver_name1 = solver_name1.rsplit(" - ", 1)[0]
|
name = self.get_combobox_text(cb)
|
||||||
self._solver1 = next(
|
name = name.rsplit(" - ", 1)[0]
|
||||||
filter(
|
self._solvers.append(
|
||||||
lambda s: s.name == solver_name1,
|
next(
|
||||||
self._config.solvers
|
filter(
|
||||||
|
lambda s: s.name == name,
|
||||||
|
self._config.solvers
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
solver_name2 = self.get_combobox_text("comboBoxSolver2")
|
for cb in ["comboBoxScenario1", "comboBoxScenario2"]:
|
||||||
solver_name2 = solver_name2.rsplit(" - ", 1)[0]
|
name = self.get_combobox_text(cb)
|
||||||
self._solver2 = next(
|
self._scenarios.append(
|
||||||
filter(
|
next(
|
||||||
lambda s: s.name == solver_name2,
|
filter(
|
||||||
self._config.solvers
|
lambda s: s.name == name,
|
||||||
|
self._study.scenarios.lst
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
scenario_name1 = self.get_combobox_text("comboBoxScenario1")
|
|
||||||
self._scenario1 = next(
|
|
||||||
filter(
|
|
||||||
lambda s: s.name == scenario_name1,
|
|
||||||
self._study.scenarios
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
scenario_name2 = self.get_combobox_text("comboBoxScenario2")
|
|
||||||
self._scenario2 = next(
|
|
||||||
filter(
|
|
||||||
lambda s: s.name == scenario_name2,
|
|
||||||
self._study.scenarios
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
super(CompareScenariosWindow, self).accept()
|
super(CompareScenariosWindow, self).accept()
|
||||||
|
|
|
||||||
|
|
@ -599,13 +599,7 @@ class CustomPlot(PamhyrPlot):
|
||||||
self.lines["wet_area"] = line
|
self.lines["wet_area"] = line
|
||||||
|
|
||||||
# Legend
|
# Legend
|
||||||
lns = reduce(
|
self.update_legend()
|
||||||
lambda acc, line: acc + line,
|
|
||||||
map(lambda line: self.lines[line], self.lines),
|
|
||||||
[]
|
|
||||||
)
|
|
||||||
labs = list(map(lambda line: self._trad[line], self.lines))
|
|
||||||
self.canvas.axes.legend(lns, labs, loc="best")
|
|
||||||
|
|
||||||
def _redraw_rk(self):
|
def _redraw_rk(self):
|
||||||
results = self.data[self._current_res_id]
|
results = self.data[self._current_res_id]
|
||||||
|
|
@ -1103,13 +1097,7 @@ class CustomPlot(PamhyrPlot):
|
||||||
self._customize_x_axes_time(ts)
|
self._customize_x_axes_time(ts)
|
||||||
|
|
||||||
# Legend
|
# Legend
|
||||||
lns = reduce(
|
self.update_legend()
|
||||||
lambda acc, line: acc + line,
|
|
||||||
map(lambda line: self.lines[line], self.lines),
|
|
||||||
[]
|
|
||||||
)
|
|
||||||
labs = list(map(lambda line: self._trad[line], self.lines))
|
|
||||||
self.canvas.axes.legend(lns, labs, loc="best")
|
|
||||||
|
|
||||||
def _redraw_time(self):
|
def _redraw_time(self):
|
||||||
|
|
||||||
|
|
@ -1419,3 +1407,25 @@ class CustomPlot(PamhyrPlot):
|
||||||
x = self._timestamp
|
x = self._timestamp
|
||||||
self._current.set_data([x, x], self.canvas.axes.get_ylim())
|
self._current.set_data([x, x], self.canvas.axes.get_ylim())
|
||||||
self.canvas.draw_idle()
|
self.canvas.draw_idle()
|
||||||
|
|
||||||
|
def update_legend(self):
|
||||||
|
lns = reduce(
|
||||||
|
lambda acc, line: acc + line,
|
||||||
|
map(lambda line: self.lines[line], self.lines),
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
labs = list(map(lambda line: self._trad[line], self.lines))
|
||||||
|
self.canvas.axes.legend(lns, labs, loc="best")
|
||||||
|
|
||||||
|
def add_imported_plot(self, data):
|
||||||
|
if (data["type_x"] == self._x and
|
||||||
|
data["type_y"] in self._y):
|
||||||
|
while data["legend"] in self.lines:
|
||||||
|
data["legend"] += '*'
|
||||||
|
self._trad._dict[data["legend"]] = data["legend"] + data["unit"]
|
||||||
|
self.lines[data["legend"]] = self.canvas.axes.plot(data["x"],
|
||||||
|
data["y"],
|
||||||
|
marker="+",
|
||||||
|
linestyle="--")
|
||||||
|
self.update_legend()
|
||||||
|
self.idle()
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,9 @@ class CustomPlotTranslate(ResultsTranslate):
|
||||||
self._dict['wet_perimeter'] = self._dict["unit_wet_perimeter"]
|
self._dict['wet_perimeter'] = self._dict["unit_wet_perimeter"]
|
||||||
self._dict['hydraulic_radius'] = self._dict["unit_hydraulic_radius"]
|
self._dict['hydraulic_radius'] = self._dict["unit_hydraulic_radius"]
|
||||||
self._dict['froude'] = self._dict["unit_froude"]
|
self._dict['froude'] = self._dict["unit_froude"]
|
||||||
|
self._dict['user_imported'] = _translate(
|
||||||
|
"CustomPlot", "user_imported"
|
||||||
|
)
|
||||||
|
|
||||||
# Unit corresponding long name (plot axes display)
|
# Unit corresponding long name (plot axes display)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -160,8 +160,6 @@ class TableModel(PamhyrTableModel):
|
||||||
self._lst = _river.reachs
|
self._lst = _river.reachs
|
||||||
elif self._opt_data == "profile" or self._opt_data == "raw_data":
|
elif self._opt_data == "profile" or self._opt_data == "raw_data":
|
||||||
self._lst = _river.reach(reach).profiles
|
self._lst = _river.reach(reach).profiles
|
||||||
# self._lst = list(compress(_river.reach(reach).profiles,
|
|
||||||
# _river.reach(reach).profile_mask))
|
|
||||||
elif self._opt_data == "solver":
|
elif self._opt_data == "solver":
|
||||||
self._lst = self._parent._solvers
|
self._lst = self._parent._solvers
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@ except Exception as e:
|
||||||
print(f"Module 'rasterio' is not available: {e}")
|
print(f"Module 'rasterio' is not available: {e}")
|
||||||
_rasterio_loaded = False
|
_rasterio_loaded = False
|
||||||
|
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
from numpy import sqrt
|
from numpy import sqrt
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
@ -54,7 +56,7 @@ from PyQt5.QtWidgets import (
|
||||||
QFileDialog, QTableView, QAbstractItemView,
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
QUndoStack, QShortcut, QAction, QItemDelegate,
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||||
QSlider, QLabel, QWidget, QGridLayout, QTabBar
|
QSlider, QLabel, QWidget, QGridLayout, QTabBar, QInputDialog
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||||
|
|
@ -347,6 +349,7 @@ class ResultsWindow(PamhyrWindow):
|
||||||
"action_add": self._add_custom_plot,
|
"action_add": self._add_custom_plot,
|
||||||
"action_export": self._export,
|
"action_export": self._export,
|
||||||
# "action_export": self.export_current,
|
# "action_export": self.export_current,
|
||||||
|
"action_import_data": self.import_data
|
||||||
}
|
}
|
||||||
if _rasterio_loaded:
|
if _rasterio_loaded:
|
||||||
actions["action_Geo_tiff"] = self.import_geotiff
|
actions["action_Geo_tiff"] = self.import_geotiff
|
||||||
|
|
@ -715,7 +718,7 @@ class ResultsWindow(PamhyrWindow):
|
||||||
select_file="AnyFile",
|
select_file="AnyFile",
|
||||||
callback=lambda f: self.export_to(f[0], x, y, envelop, solver_id),
|
callback=lambda f: self.export_to(f[0], x, y, envelop, solver_id),
|
||||||
default_suffix=".csv",
|
default_suffix=".csv",
|
||||||
file_filter=["CSV (*.csv)"],
|
file_filter=[self._dict["file_csv"]],
|
||||||
)
|
)
|
||||||
|
|
||||||
def export_to(self, filename, x, y, envelop, solver_id):
|
def export_to(self, filename, x, y, envelop, solver_id):
|
||||||
|
|
@ -1225,3 +1228,88 @@ class ResultsWindow(PamhyrWindow):
|
||||||
self.plot_xy.idle()
|
self.plot_xy.idle()
|
||||||
self.canvas.axes.set_xlim(xlim)
|
self.canvas.axes.set_xlim(xlim)
|
||||||
self.canvas.axes.set_ylim(ylim)
|
self.canvas.axes.set_ylim(ylim)
|
||||||
|
return
|
||||||
|
|
||||||
|
def import_data(self):
|
||||||
|
|
||||||
|
file_types = [
|
||||||
|
self._trad["file_csv"],
|
||||||
|
self._trad["file_all"],
|
||||||
|
]
|
||||||
|
|
||||||
|
self.file_dialog(
|
||||||
|
select_file="Existing_file",
|
||||||
|
callback=lambda f: self.read_csv_file(f[0]),
|
||||||
|
default_suffix=".csv",
|
||||||
|
file_filter=file_types,
|
||||||
|
)
|
||||||
|
|
||||||
|
def read_csv_file(self, filename):
|
||||||
|
if filename == "":
|
||||||
|
return
|
||||||
|
|
||||||
|
sep = " "
|
||||||
|
|
||||||
|
def is_float(string):
|
||||||
|
if string.replace(".", "").isnumeric():
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
with open(filename, 'r', newline='') as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
x = []
|
||||||
|
y = []
|
||||||
|
for line in lines:
|
||||||
|
if line[0] != "*" and line[0] != "#" and line[0] != "$":
|
||||||
|
row = line.split(sep)
|
||||||
|
if len(row) >= 2:
|
||||||
|
if is_float(row[0]) and is_float(row[1]):
|
||||||
|
x.append(float(row[0]))
|
||||||
|
y.append(float(row[1]))
|
||||||
|
|
||||||
|
data_type_lst = ['Q(t)', 'Z(t)', 'Z(x)']
|
||||||
|
data_type, ok = QInputDialog.getItem(
|
||||||
|
self, 'Data type', 'Chose the type of data:', data_type_lst)
|
||||||
|
|
||||||
|
if not ok:
|
||||||
|
return
|
||||||
|
|
||||||
|
legend, ok = QInputDialog.getText(self, 'Legend', 'Legend:')
|
||||||
|
|
||||||
|
if not ok:
|
||||||
|
return
|
||||||
|
|
||||||
|
if legend.strip() == '':
|
||||||
|
legend = '*'
|
||||||
|
|
||||||
|
tmp_dict = {'Z': 'water_elevation',
|
||||||
|
'Q': 'discharge',
|
||||||
|
'x': 'rk',
|
||||||
|
't': 'time'}
|
||||||
|
|
||||||
|
tmp_unit = {'Z': ' (m)',
|
||||||
|
'Q': ' (m³/s)'}
|
||||||
|
|
||||||
|
data = {'type_x': tmp_dict[data_type[2]],
|
||||||
|
'type_y': tmp_dict[data_type[0]],
|
||||||
|
'legend': legend,
|
||||||
|
'unit': tmp_unit[data_type[0]],
|
||||||
|
'x': x,
|
||||||
|
'y': y}
|
||||||
|
|
||||||
|
if data_type == 'Z(x)':
|
||||||
|
line = self.canvas_2.axes.plot(x, y, marker="+",
|
||||||
|
label=legend + ' (m)')
|
||||||
|
self.plot_rkc.canvas.draw_idle()
|
||||||
|
self.plot_rkc.update_idle()
|
||||||
|
if data_type == 'Q(t)':
|
||||||
|
line = self.canvas_4.axes.plot(x, y, marker="+",
|
||||||
|
label=legend + ' (m³/s)')
|
||||||
|
self.plot_h._line.append(line)
|
||||||
|
self.plot_h.enable_legend()
|
||||||
|
self.plot_h.canvas.draw_idle()
|
||||||
|
self.plot_h.update_idle
|
||||||
|
|
||||||
|
for p in self._additional_plot:
|
||||||
|
self._additional_plot[p].add_imported_plot(data)
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@ class ResultsTranslate(MainTranslate):
|
||||||
self._dict["file_all"] = _translate("Results", "All files (*)")
|
self._dict["file_all"] = _translate("Results", "All files (*)")
|
||||||
self._dict["file_geotiff"] = _translate(
|
self._dict["file_geotiff"] = _translate(
|
||||||
"Results", "GeoTIFF file (*.tiff *.tif)")
|
"Results", "GeoTIFF file (*.tiff *.tif)")
|
||||||
|
self._dict["file_csv"] = _translate(
|
||||||
|
"Results", "CSV file (*.csv)")
|
||||||
self._dict["ImageCoordinates"] = _translate(
|
self._dict["ImageCoordinates"] = _translate(
|
||||||
"Results", "Image coordinates"
|
"Results", "Image coordinates"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,7 @@
|
||||||
<addaction name="action_export"/>
|
<addaction name="action_export"/>
|
||||||
<addaction name="action_reload"/>
|
<addaction name="action_reload"/>
|
||||||
<addaction name="action_Geo_tiff"/>
|
<addaction name="action_Geo_tiff"/>
|
||||||
|
<addaction name="action_import_data"/>
|
||||||
</widget>
|
</widget>
|
||||||
<action name="action_add">
|
<action name="action_add">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
|
|
@ -288,6 +289,18 @@
|
||||||
<string>Import background image</string>
|
<string>Import background image</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="action_import_data">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/import.png</normaloff>ressources/import.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Import data</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Import data from SCV file</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue