RCAIDE-GUI 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- common_widgets/__init__.py +6 -0
- common_widgets/animated_toggle.py +141 -0
- common_widgets/color.py +17 -0
- common_widgets/data_entry_widget.py +337 -0
- common_widgets/image_widget.py +21 -0
- common_widgets/unit_picker_widget.py +48 -0
- main.py +168 -0
- rcaide_gui-1.0.0.dist-info/METADATA +96 -0
- rcaide_gui-1.0.0.dist-info/RECORD +170 -0
- rcaide_gui-1.0.0.dist-info/WHEEL +5 -0
- rcaide_gui-1.0.0.dist-info/entry_points.txt +2 -0
- rcaide_gui-1.0.0.dist-info/top_level.txt +5 -0
- rcaide_io.py +818 -0
- tabs/__init__.py +10 -0
- tabs/aircraft_configs/__init__.py +3 -0
- tabs/aircraft_configs/aircraft_configs.py +301 -0
- tabs/analysis/__init__.py +4 -0
- tabs/analysis/analysis.py +92 -0
- tabs/analysis/widgets/__init__.py +13 -0
- tabs/analysis/widgets/aeroacoustics_widget.py +158 -0
- tabs/analysis/widgets/aerodynamics_widget.py +108 -0
- tabs/analysis/widgets/analysis_data_widget.py +29 -0
- tabs/analysis/widgets/atmosphere_widget.py +49 -0
- tabs/analysis/widgets/costs_widget.py +35 -0
- tabs/analysis/widgets/energy_widget.py +32 -0
- tabs/analysis/widgets/geometry_widget.py +55 -0
- tabs/analysis/widgets/planets_widget.py +34 -0
- tabs/analysis/widgets/propulsion_widget.py +53 -0
- tabs/analysis/widgets/stability_widget.py +34 -0
- tabs/analysis/widgets/weights_widget.py +94 -0
- tabs/geometry/__init__.py +6 -0
- tabs/geometry/aircraft_configs.py +232 -0
- tabs/geometry/frames/__init__.py +15 -0
- tabs/geometry/frames/booms/__init__.py +5 -0
- tabs/geometry/frames/booms/boom_frame.py +238 -0
- tabs/geometry/frames/cargo_bays/__init__.py +5 -0
- tabs/geometry/frames/cargo_bays/cargo_bay_frame.py +159 -0
- tabs/geometry/frames/default_frame.py +23 -0
- tabs/geometry/frames/energy_network/__init__.py +2 -0
- tabs/geometry/frames/energy_network/turbofan_network/__init__.py +3 -0
- tabs/geometry/frames/energy_network/turbofan_network/frames/__init__.py +1 -0
- tabs/geometry/frames/energy_network/turbofan_network/widgets/__init__.py +1 -0
- tabs/geometry/frames/fuselages/__init__.py +5 -0
- tabs/geometry/frames/fuselages/fuselage_frame.py +294 -0
- tabs/geometry/frames/geometry_frame.py +91 -0
- tabs/geometry/frames/landing_gears/__init__.py +5 -0
- tabs/geometry/frames/landing_gears/landing_gear_frame.py +189 -0
- tabs/geometry/frames/nacelles/__init__.py +1 -0
- tabs/geometry/frames/powertrain/__init__.py +6 -0
- tabs/geometry/frames/powertrain/converters/__init__.py +5 -0
- tabs/geometry/frames/powertrain/converters/converter_frame.py +137 -0
- tabs/geometry/frames/powertrain/distributors/__init__.py +5 -0
- tabs/geometry/frames/powertrain/distributors/distributor_frame.py +143 -0
- tabs/geometry/frames/powertrain/nacelles/__init__.py +5 -0
- tabs/geometry/frames/powertrain/nacelles/nacelle_frame.py +283 -0
- tabs/geometry/frames/powertrain/powertrain_frame.py +259 -0
- tabs/geometry/frames/powertrain/propulsors/__init__.py +5 -0
- tabs/geometry/frames/powertrain/propulsors/propulsor_frame.py +146 -0
- tabs/geometry/frames/powertrain/sources/__init__.py +6 -0
- tabs/geometry/frames/powertrain/sources/energy_source_frame.py +147 -0
- tabs/geometry/frames/vehicle_frame.py +171 -0
- tabs/geometry/frames/wings/__init__.py +5 -0
- tabs/geometry/frames/wings/wings_frame.py +457 -0
- tabs/geometry/geometry.py +513 -0
- tabs/geometry/widgets/__init__.py +12 -0
- tabs/geometry/widgets/booms/__init__.py +6 -0
- tabs/geometry/widgets/booms/boom_section_widget.py +109 -0
- tabs/geometry/widgets/cargo_bays/__init__.py +1 -0
- tabs/geometry/widgets/fuselages/__init__.py +8 -0
- tabs/geometry/widgets/fuselages/cabin_class_widget.py +188 -0
- tabs/geometry/widgets/fuselages/cabin_widget.py +217 -0
- tabs/geometry/widgets/fuselages/fuselage_section_widget.py +190 -0
- tabs/geometry/widgets/geometry_data_widget.py +25 -0
- tabs/geometry/widgets/landing_gears/__init__.py +6 -0
- tabs/geometry/widgets/nacelles/__init__.py +1 -0
- tabs/geometry/widgets/powertrain/__init__.py +9 -0
- tabs/geometry/widgets/powertrain/converters/__init__.py +5 -0
- tabs/geometry/widgets/powertrain/converters/turboelectric_generator_widget.py +74 -0
- tabs/geometry/widgets/powertrain/distributors/__init__.py +5 -0
- tabs/geometry/widgets/powertrain/distributors/fuel_line_widget.py +81 -0
- tabs/geometry/widgets/powertrain/modulators/__init__.py +5 -0
- tabs/geometry/widgets/powertrain/modulators/esc_widget.py +58 -0
- tabs/geometry/widgets/powertrain/nacelles/__init__.py +5 -0
- tabs/geometry/widgets/powertrain/nacelles/nacelle_section_widget.py +115 -0
- tabs/geometry/widgets/powertrain/powertrain_connector_widget.py +136 -0
- tabs/geometry/widgets/powertrain/powertrain_widget.py +206 -0
- tabs/geometry/widgets/powertrain/propulsors/__init__.py +5 -0
- tabs/geometry/widgets/powertrain/propulsors/turbofan_widget.py +462 -0
- tabs/geometry/widgets/powertrain/sources/__init__.py +6 -0
- tabs/geometry/widgets/powertrain/sources/fuel_tank_widget.py +103 -0
- tabs/geometry/widgets/powertrain/sources/source_selector_widget.py +35 -0
- tabs/geometry/widgets/wings/__init__.py +7 -0
- tabs/geometry/widgets/wings/wing_cs_widget.py +198 -0
- tabs/geometry/widgets/wings/wing_section_widget.py +298 -0
- tabs/home/__init__.py +3 -0
- tabs/home/home.py +585 -0
- tabs/mission/__init__.py +4 -0
- tabs/mission/mission.py +1124 -0
- tabs/mission/widgets/__init__.py +3 -0
- tabs/mission/widgets/flight_controls_widget.py +186 -0
- tabs/mission/widgets/mission_analysis_widget.py +166 -0
- tabs/mission/widgets/mission_segment_helper.py +358 -0
- tabs/mission/widgets/mission_segment_widget.py +358 -0
- tabs/solve/__init__.py +4 -0
- tabs/solve/plots/__init__.py +12 -0
- tabs/solve/plots/aeroacoustics/__init__.py +6 -0
- tabs/solve/plots/aeroacoustics/plot_2D_noise_contour.py +184 -0
- tabs/solve/plots/aeroacoustics/plot_3D_noise_contour.py +219 -0
- tabs/solve/plots/aeroacoustics/plot_noise_certification_contour.py +115 -0
- tabs/solve/plots/aeroacoustics/plot_noise_level.py +118 -0
- tabs/solve/plots/aerodynamics/__init__.py +10 -0
- tabs/solve/plots/aerodynamics/plot_aerodynamic_coefficients.py +156 -0
- tabs/solve/plots/aerodynamics/plot_aerodynamic_forces.py +155 -0
- tabs/solve/plots/aerodynamics/plot_aircraft_aerodynamics.py +136 -0
- tabs/solve/plots/aerodynamics/plot_drag_components.py +157 -0
- tabs/solve/plots/aerodynamics/plot_lift_distribution.py +107 -0
- tabs/solve/plots/aerodynamics/plot_rotor_conditions.py +255 -0
- tabs/solve/plots/aerodynamics/plot_rotor_disc_performance.py +144 -0
- tabs/solve/plots/aerodynamics/plot_rotor_performance.py +124 -0
- tabs/solve/plots/common/__init__.py +4 -0
- tabs/solve/plots/common/plot_style.py +71 -0
- tabs/solve/plots/common/set_axes.py +55 -0
- tabs/solve/plots/create_plot_widgets.py +34 -0
- tabs/solve/plots/emissions/__init__.py +3 -0
- tabs/solve/plots/emissions/plot_emissions.py +167 -0
- tabs/solve/plots/energy/__init__.py +12 -0
- tabs/solve/plots/energy/plot_altitude_sfc_weight.py +134 -0
- tabs/solve/plots/energy/plot_battery_cell_conditions.py +154 -0
- tabs/solve/plots/energy/plot_battery_degradation.py +157 -0
- tabs/solve/plots/energy/plot_battery_module_C_rates.py +139 -0
- tabs/solve/plots/energy/plot_battery_module_conditions.py +157 -0
- tabs/solve/plots/energy/plot_battery_pack_conditions.py +164 -0
- tabs/solve/plots/energy/plot_battery_ragone_diagram.py +97 -0
- tabs/solve/plots/energy/plot_battery_temperature.py +136 -0
- tabs/solve/plots/energy/plot_electric_propulsor_efficiencies.py +136 -0
- tabs/solve/plots/energy/plot_propulsor_throttles.py +119 -0
- tabs/solve/plots/mission/__init__.py +5 -0
- tabs/solve/plots/mission/plot_aircraft_velocities.py +145 -0
- tabs/solve/plots/mission/plot_flight_conditions.py +236 -0
- tabs/solve/plots/mission/plot_flight_trajectory.py +172 -0
- tabs/solve/plots/stability/__init__.py +5 -0
- tabs/solve/plots/stability/plot_flight_forces_and_moments.py +163 -0
- tabs/solve/plots/stability/plot_lateral_stability.py +151 -0
- tabs/solve/plots/stability/plot_longitudinal_stability.py +173 -0
- tabs/solve/plots/thermal_management/__init__.py +7 -0
- tabs/solve/plots/thermal_management/plot_air_cooled_conditions.py +152 -0
- tabs/solve/plots/thermal_management/plot_cross_flow_heat_exchanger_conditions.py +185 -0
- tabs/solve/plots/thermal_management/plot_reservoir_conditions.py +141 -0
- tabs/solve/plots/thermal_management/plot_thermal_management_performance.py +105 -0
- tabs/solve/plots/thermal_management/plot_wavy_channel_conditions.py +161 -0
- tabs/solve/plots/weights/__init__.py +4 -0
- tabs/solve/plots/weights/plot_load_diagram.py +163 -0
- tabs/solve/plots/weights/plot_weight_breakdown.py +164 -0
- tabs/solve/solve.py +1498 -0
- tabs/style_sheet.py +114 -0
- tabs/tab_widget.py +14 -0
- tabs/visualize_geometry/__init__.py +4 -0
- tabs/visualize_geometry/core_3d_viewer.py +253 -0
- tabs/visualize_geometry/features/__init__.py +10 -0
- tabs/visualize_geometry/features/axes_gizmo.py +173 -0
- tabs/visualize_geometry/features/background.py +161 -0
- tabs/visualize_geometry/features/blueprint.py +685 -0
- tabs/visualize_geometry/features/camera.py +364 -0
- tabs/visualize_geometry/features/drag_aircraft.py +219 -0
- tabs/visualize_geometry/features/grid.py +194 -0
- tabs/visualize_geometry/features/measurement.py +367 -0
- tabs/visualize_geometry/features/screenshot.py +91 -0
- tabs/visualize_geometry/geometry_helper_functions.py +3 -0
- tabs/visualize_geometry/visualize_geometry.py +731 -0
- utilities.py +257 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# RCAIDE_GUI/tabs/geometry/frames/powertrain/converters/converter_frame.py
|
|
2
|
+
#
|
|
3
|
+
# Created: Dec 2025, M. Clarke
|
|
4
|
+
|
|
5
|
+
# ----------------------------------------------------------------------------------------------------------------------
|
|
6
|
+
# IMPORT
|
|
7
|
+
# ----------------------------------------------------------------------------------------------------------------------
|
|
8
|
+
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QFrame, \
|
|
9
|
+
QSizePolicy, QSpacerItem
|
|
10
|
+
|
|
11
|
+
from tabs.geometry.widgets.powertrain.converters import TurboelectricGeneratorWidget
|
|
12
|
+
from common_widgets import DataEntryWidget
|
|
13
|
+
|
|
14
|
+
class ConverterFrame(QWidget):
|
|
15
|
+
def __init__(self):
|
|
16
|
+
super(ConverterFrame, self).__init__()
|
|
17
|
+
|
|
18
|
+
self.save_function = None
|
|
19
|
+
self.data_entry_widget: DataEntryWidget | None = None
|
|
20
|
+
|
|
21
|
+
# List to store data values source_ sections
|
|
22
|
+
self.converter_sections_layout = QVBoxLayout()
|
|
23
|
+
|
|
24
|
+
# Create a horizontal layout for the label and buttons
|
|
25
|
+
header_layout = QVBoxLayout()
|
|
26
|
+
# label = QLabel("<u><b>source Frame</b></u>")
|
|
27
|
+
|
|
28
|
+
layout = self.create_scroll_layout()
|
|
29
|
+
|
|
30
|
+
# header_layout.addWidget(label)
|
|
31
|
+
|
|
32
|
+
# Add source_ Section Button
|
|
33
|
+
add_turboelectric_generator_button = QPushButton("Add Turboelectric Generator", self)
|
|
34
|
+
add_turboelectric_generator_button.setStyleSheet("color:#dbe7ff; font-weight:500; margin:0; padding:0;")
|
|
35
|
+
add_turboelectric_generator_button.setMaximumWidth(200)
|
|
36
|
+
add_turboelectric_generator_button.clicked.connect(self.add_turboelectric_generator)
|
|
37
|
+
header_layout.addWidget(add_turboelectric_generator_button)
|
|
38
|
+
|
|
39
|
+
layout.addLayout(header_layout)
|
|
40
|
+
|
|
41
|
+
# Create a horizontal line
|
|
42
|
+
line_bar = QFrame()
|
|
43
|
+
line_bar.setFrameShape(QFrame.Shape.HLine)
|
|
44
|
+
line_bar.setFrameShadow(QFrame.Shadow.Sunken)
|
|
45
|
+
line_bar.setStyleSheet("background-color: light grey;")
|
|
46
|
+
|
|
47
|
+
# Add the line bar to the main layout
|
|
48
|
+
layout.addWidget(line_bar)
|
|
49
|
+
|
|
50
|
+
# Add the layout for additional source_ sections to the main layout
|
|
51
|
+
layout.addLayout(self.converter_sections_layout)
|
|
52
|
+
|
|
53
|
+
# Create a QHBoxLayout to contain the buttons
|
|
54
|
+
button_layout = QHBoxLayout()
|
|
55
|
+
|
|
56
|
+
# Add the button layout to the main layout
|
|
57
|
+
layout.addLayout(button_layout)
|
|
58
|
+
|
|
59
|
+
# Adds scroll function
|
|
60
|
+
layout.addItem(QSpacerItem(
|
|
61
|
+
20, 40, QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Expanding))
|
|
62
|
+
|
|
63
|
+
def get_data_values(self):
|
|
64
|
+
data = []
|
|
65
|
+
sources = []
|
|
66
|
+
for index in range(self.converter_sections_layout.count()):
|
|
67
|
+
item = self.converter_sections_layout.itemAt(index)
|
|
68
|
+
assert item is not None
|
|
69
|
+
widget = item.widget()
|
|
70
|
+
assert widget is not None and isinstance(widget, TurboelectricGeneratorWidget)
|
|
71
|
+
|
|
72
|
+
source_data, fuel_tank = widget.get_data_values()
|
|
73
|
+
data.append(source_data)
|
|
74
|
+
sources.append(fuel_tank)
|
|
75
|
+
|
|
76
|
+
return data, sources
|
|
77
|
+
|
|
78
|
+
def load_data(self, data):
|
|
79
|
+
while self.converter_sections_layout.count():
|
|
80
|
+
widget_item = self.converter_sections_layout.itemAt(0)
|
|
81
|
+
assert widget_item is not None
|
|
82
|
+
widget = widget_item.widget()
|
|
83
|
+
assert widget is not None
|
|
84
|
+
|
|
85
|
+
self.converter_sections_layout.removeWidget(widget)
|
|
86
|
+
widget.deleteLater()
|
|
87
|
+
|
|
88
|
+
for section_data in data:
|
|
89
|
+
self.converter_sections_layout.addWidget(TurboelectricGeneratorWidget(
|
|
90
|
+
self.converter_sections_layout.count(), self.on_delete_button_pressed, section_data))
|
|
91
|
+
|
|
92
|
+
def delete_data(self):
|
|
93
|
+
# TODO Implement proper deletion of data
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
def add_turboelectric_generator(self):
|
|
97
|
+
self.converter_sections_layout.addWidget(
|
|
98
|
+
TurboelectricGeneratorWidget(self.converter_sections_layout.count(), self.on_delete_button_pressed))
|
|
99
|
+
|
|
100
|
+
def on_delete_button_pressed(self, index):
|
|
101
|
+
distributor = self.converter_sections_layout.itemAt(index)
|
|
102
|
+
if distributor is None:
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
widget = distributor.widget()
|
|
106
|
+
if widget is None:
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
widget.deleteLater()
|
|
110
|
+
self.converter_sections_layout.removeWidget(widget)
|
|
111
|
+
self.converter_sections_layout.update()
|
|
112
|
+
|
|
113
|
+
for i in range(index, self.converter_sections_layout.count()):
|
|
114
|
+
distributor = self.converter_sections_layout.itemAt(i)
|
|
115
|
+
if distributor is None:
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
widget = distributor.widget()
|
|
119
|
+
if widget is None or not isinstance(widget, TurboelectricGeneratorWidget):
|
|
120
|
+
continue
|
|
121
|
+
|
|
122
|
+
widget.index = i
|
|
123
|
+
|
|
124
|
+
def set_save_function(self, function):
|
|
125
|
+
self.save_function = function
|
|
126
|
+
|
|
127
|
+
def create_scroll_layout(self):
|
|
128
|
+
# Create a widget to contain the layout
|
|
129
|
+
scroll_content = QWidget()
|
|
130
|
+
|
|
131
|
+
# Set the main layout inside the scroll content
|
|
132
|
+
layout = QVBoxLayout(scroll_content)
|
|
133
|
+
|
|
134
|
+
# Set the main layout of the widget
|
|
135
|
+
self.setLayout(layout)
|
|
136
|
+
|
|
137
|
+
return layout
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# RCAIDE_GUI/tabs/geometry/frames/powertrain/distributors/__init__.py
|
|
2
|
+
# ----------------------------------------------------------------------------------------------------------------------
|
|
3
|
+
# IMPORT
|
|
4
|
+
# ----------------------------------------------------------------------------------------------------------------------
|
|
5
|
+
from tabs.geometry.frames.powertrain.distributors.distributor_frame import DistributorFrame
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# RCAIDE_GUI/tabs/geometry/frames/powertrain/distributor_frame.py
|
|
2
|
+
#
|
|
3
|
+
# Created: Dec 2025, M. Clarke
|
|
4
|
+
|
|
5
|
+
# ----------------------------------------------------------------------------------------------------------------------
|
|
6
|
+
# IMPORT
|
|
7
|
+
# ----------------------------------------------------------------------------------------------------------------------
|
|
8
|
+
# RCAIDE imports
|
|
9
|
+
import RCAIDE
|
|
10
|
+
|
|
11
|
+
# PyQT imports
|
|
12
|
+
from PyQt6.QtCore import Qt
|
|
13
|
+
from PyQt6.QtWidgets import QWidget, QPushButton, QLineEdit, QSizePolicy, QVBoxLayout, \
|
|
14
|
+
QHBoxLayout, QLabel, QFrame, QScrollArea, QSpacerItem, QComboBox
|
|
15
|
+
|
|
16
|
+
from tabs.geometry.widgets.powertrain.distributors import FuelLineWidget
|
|
17
|
+
from utilities import set_data, show_popup, create_line_bar, Units, create_scroll_area, clear_layout
|
|
18
|
+
from common_widgets import DataEntryWidget
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# ----------------------------------------------------------------------------------------------------------------------
|
|
22
|
+
# Distributor Frame
|
|
23
|
+
# ----------------------------------------------------------------------------------------------------------------------
|
|
24
|
+
class DistributorFrame(QWidget):
|
|
25
|
+
def __init__(self):
|
|
26
|
+
super(DistributorFrame, self).__init__()
|
|
27
|
+
|
|
28
|
+
self.save_function = None
|
|
29
|
+
self.data_entry_widget: DataEntryWidget | None = None
|
|
30
|
+
|
|
31
|
+
# List to store data values distributor_ sections
|
|
32
|
+
self.distributor_sections_layout = QVBoxLayout()
|
|
33
|
+
|
|
34
|
+
# Create a horizontal layout for the label and buttons`
|
|
35
|
+
header_layout = QVBoxLayout()
|
|
36
|
+
|
|
37
|
+
layout = self.create_scroll_layout()
|
|
38
|
+
|
|
39
|
+
# Add distributor_ Section Button
|
|
40
|
+
add_fuel_line_button = QPushButton("Add Fuel Line", self)
|
|
41
|
+
add_fuel_line_button.setStyleSheet("color:#dbe7ff; font-weight:500; margin:0; padding:0;")
|
|
42
|
+
add_fuel_line_button.setMaximumWidth(200)
|
|
43
|
+
add_fuel_line_button.clicked.connect(self.add_fuel_line)
|
|
44
|
+
header_layout.addWidget(add_fuel_line_button)
|
|
45
|
+
layout.addLayout(header_layout)
|
|
46
|
+
|
|
47
|
+
# Create a horizontal line
|
|
48
|
+
line_bar = QFrame()
|
|
49
|
+
line_bar.setFrameShape(QFrame.Shape.HLine)
|
|
50
|
+
line_bar.setFrameShadow(QFrame.Shadow.Sunken)
|
|
51
|
+
line_bar.setStyleSheet("background-color: light grey;")
|
|
52
|
+
|
|
53
|
+
# Add the line bar to the main layout
|
|
54
|
+
layout.addWidget(line_bar)
|
|
55
|
+
|
|
56
|
+
# Add the layout for additional distributor_ sections to the main layout
|
|
57
|
+
layout.addLayout(self.distributor_sections_layout)
|
|
58
|
+
|
|
59
|
+
# Create a QHBoxLayout to contain the buttons
|
|
60
|
+
button_layout = QHBoxLayout()
|
|
61
|
+
|
|
62
|
+
# Add the button layout to the main layout
|
|
63
|
+
layout.addLayout(button_layout)
|
|
64
|
+
|
|
65
|
+
# Adds scroll function
|
|
66
|
+
layout.addItem(QSpacerItem(
|
|
67
|
+
20, 40, QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Expanding))
|
|
68
|
+
|
|
69
|
+
def get_data_values(self):
|
|
70
|
+
data = []
|
|
71
|
+
distributors = []
|
|
72
|
+
for index in range(self.distributor_sections_layout.count()):
|
|
73
|
+
item = self.distributor_sections_layout.itemAt(index)
|
|
74
|
+
assert item is not None
|
|
75
|
+
widget = item.widget()
|
|
76
|
+
assert widget is not None and isinstance(widget, FuelLineWidget)
|
|
77
|
+
|
|
78
|
+
distributor_data, distributor = widget.get_data_values()
|
|
79
|
+
data.append(distributor_data)
|
|
80
|
+
distributors.append(distributor)
|
|
81
|
+
|
|
82
|
+
return data, distributors
|
|
83
|
+
|
|
84
|
+
def load_data(self, data):
|
|
85
|
+
while self.distributor_sections_layout.count():
|
|
86
|
+
widget_item = self.distributor_sections_layout.itemAt(0)
|
|
87
|
+
assert widget_item is not None
|
|
88
|
+
widget = widget_item.widget()
|
|
89
|
+
assert widget is not None
|
|
90
|
+
|
|
91
|
+
self.distributor_sections_layout.removeWidget(widget)
|
|
92
|
+
widget.deleteLater()
|
|
93
|
+
|
|
94
|
+
for section_data in data:
|
|
95
|
+
self.distributor_sections_layout.addWidget(FuelLineWidget(
|
|
96
|
+
self.distributor_sections_layout.count(), self.on_delete_button_pressed, section_data))
|
|
97
|
+
|
|
98
|
+
def delete_data(self):
|
|
99
|
+
# TODO Implement proper deletion of data
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
def add_fuel_line(self):
|
|
103
|
+
self.distributor_sections_layout.addWidget(
|
|
104
|
+
FuelLineWidget(self.distributor_sections_layout.count(), self.on_delete_button_pressed))
|
|
105
|
+
|
|
106
|
+
def on_delete_button_pressed(self, index):
|
|
107
|
+
distributor = self.distributor_sections_layout.itemAt(index)
|
|
108
|
+
if distributor is None:
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
widget = distributor.widget()
|
|
112
|
+
if widget is None:
|
|
113
|
+
return
|
|
114
|
+
|
|
115
|
+
widget.deleteLater()
|
|
116
|
+
self.distributor_sections_layout.removeWidget(widget)
|
|
117
|
+
self.distributor_sections_layout.update()
|
|
118
|
+
|
|
119
|
+
for i in range(index, self.distributor_sections_layout.count()):
|
|
120
|
+
distributor = self.distributor_sections_layout.itemAt(i)
|
|
121
|
+
if distributor is None:
|
|
122
|
+
continue
|
|
123
|
+
|
|
124
|
+
widget = distributor.widget()
|
|
125
|
+
if widget is None or not isinstance(widget, FuelLineWidget):
|
|
126
|
+
continue
|
|
127
|
+
|
|
128
|
+
widget.index = i
|
|
129
|
+
|
|
130
|
+
def set_save_function(self, function):
|
|
131
|
+
self.save_function = function
|
|
132
|
+
|
|
133
|
+
def create_scroll_layout(self):
|
|
134
|
+
# Create a widget to contain the layout
|
|
135
|
+
scroll_content = QWidget()
|
|
136
|
+
|
|
137
|
+
# Set the main layout inside the scroll content
|
|
138
|
+
layout = QVBoxLayout(scroll_content)
|
|
139
|
+
|
|
140
|
+
# Set the main layout of the widget
|
|
141
|
+
self.setLayout(layout)
|
|
142
|
+
|
|
143
|
+
return layout
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# RCAIDE_GUI/tabs/geometry/frames/powertrain/nacelles/__init__.py
|
|
2
|
+
# ----------------------------------------------------------------------------------------------------------------------
|
|
3
|
+
# IMPORT
|
|
4
|
+
# ----------------------------------------------------------------------------------------------------------------------
|
|
5
|
+
from tabs.geometry.frames.powertrain.nacelles.nacelle_frame import NacelleFrame
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# RCAIDE_GUI/tabs/geometry/frames/powertrain/nacelles/nacelle_frame.py
|
|
2
|
+
#
|
|
3
|
+
# Created: Dec 2025, M. Clarke
|
|
4
|
+
|
|
5
|
+
# NOTE: This file is no longer used - nacelles are now integrated into the powertrain. See turbofan_widget.py.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# # RCAIDE_GUI/tabs/geometry/frames/nacelles/nacelle_frame.py
|
|
14
|
+
# #
|
|
15
|
+
# # Created: Dec 2025, M. Clarke
|
|
16
|
+
|
|
17
|
+
# # ----------------------------------------------------------------------------------------------------------------------
|
|
18
|
+
# # IMPORT
|
|
19
|
+
# # ----------------------------------------------------------------------------------------------------------------------
|
|
20
|
+
# # RCAIDE imports
|
|
21
|
+
# import RCAIDE
|
|
22
|
+
|
|
23
|
+
# # PyQT imports
|
|
24
|
+
# from PyQt6.QtCore import Qt
|
|
25
|
+
# from PyQt6.QtWidgets import QWidget, QPushButton, QLineEdit, QSizePolicy, QVBoxLayout,\
|
|
26
|
+
# QHBoxLayout, QLabel, QFrame, QScrollArea, QSpacerItem, QComboBox
|
|
27
|
+
|
|
28
|
+
# # RCAIDE GUI imports
|
|
29
|
+
# from tabs.geometry.frames import GeometryFrame
|
|
30
|
+
# from tabs.geometry.widgets.nacelles.nacelle_section_widget import NacelleSectionWidget
|
|
31
|
+
# from utilities import set_data, show_popup, create_line_bar, Units, create_scroll_area, clear_layout
|
|
32
|
+
# from common_widgets import DataEntryWidget
|
|
33
|
+
|
|
34
|
+
# # python imports
|
|
35
|
+
# from turtle import clear
|
|
36
|
+
|
|
37
|
+
# # ----------------------------------------------------------------------------------------------------------------------
|
|
38
|
+
# # Nacelle Frame
|
|
39
|
+
# # ----------------------------------------------------------------------------------------------------------------------
|
|
40
|
+
# class NacelleFrame(GeometryFrame):
|
|
41
|
+
# def __init__(self):
|
|
42
|
+
# """Create a frame for entering nacelle data."""
|
|
43
|
+
# super(NacelleFrame, self).__init__()
|
|
44
|
+
|
|
45
|
+
# create_scroll_area(self)
|
|
46
|
+
# assert self.main_layout is not None and isinstance(
|
|
47
|
+
# self.main_layout, QVBoxLayout)
|
|
48
|
+
# self.main_layout.addWidget(QLabel("<b>Nacelles</b>"))
|
|
49
|
+
# self.main_layout.addWidget(create_line_bar())
|
|
50
|
+
|
|
51
|
+
# self.add_name_layout()
|
|
52
|
+
# self.add_nacelle_type()
|
|
53
|
+
|
|
54
|
+
# # List of data labels
|
|
55
|
+
# self.data_units_labels = [
|
|
56
|
+
# ("Length", Units.Length, "length"),
|
|
57
|
+
# ("Inlet Diameter", Units.Length, "inlet_diameter"),
|
|
58
|
+
# ("Diameter", Units.Length, "diameter"),
|
|
59
|
+
# ("Origin", Units.Position, "origin"),
|
|
60
|
+
# ("Wetted Area", Units.Area, "areas.wetted"),
|
|
61
|
+
# ("Flow Through", Units.Boolean, "flow_through"),
|
|
62
|
+
# ]
|
|
63
|
+
|
|
64
|
+
# # Add the data entry widget to the main layout
|
|
65
|
+
# self.data_entry_widget: DataEntryWidget = DataEntryWidget(
|
|
66
|
+
# self.data_units_labels)
|
|
67
|
+
# self.main_layout.addWidget(self.data_entry_widget)
|
|
68
|
+
# self.main_layout.addWidget(create_line_bar())
|
|
69
|
+
|
|
70
|
+
# # Add the secctions layout to the main layout
|
|
71
|
+
# self.nacelle_sections_layout = QVBoxLayout()
|
|
72
|
+
# self.main_layout.addLayout(self.nacelle_sections_layout)
|
|
73
|
+
|
|
74
|
+
# self.add_buttons_layout()
|
|
75
|
+
|
|
76
|
+
# # Adds scroll function
|
|
77
|
+
# self.main_layout.addItem(QSpacerItem(
|
|
78
|
+
# 20, 40, QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Expanding))
|
|
79
|
+
|
|
80
|
+
# def add_name_layout(self):
|
|
81
|
+
# assert self.main_layout is not None
|
|
82
|
+
# name_layout = QHBoxLayout()
|
|
83
|
+
# spacer_left = QSpacerItem(
|
|
84
|
+
# 50, 5, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum)
|
|
85
|
+
# spacer_right = QSpacerItem(
|
|
86
|
+
# 200, 5, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum)
|
|
87
|
+
# self.name_line_edit: QLineEdit = QLineEdit(self)
|
|
88
|
+
# name_layout.addItem(spacer_left)
|
|
89
|
+
# name_layout.addWidget(QLabel("Name: "))
|
|
90
|
+
# name_layout.addWidget(self.name_line_edit)
|
|
91
|
+
# name_layout.addItem(spacer_right)
|
|
92
|
+
# self.main_layout.addLayout(name_layout)
|
|
93
|
+
|
|
94
|
+
# def add_nacelle_type(self):
|
|
95
|
+
# nacelle_type_label = QLabel("Nacelle Type: ")
|
|
96
|
+
# nacelle_type_layout = QHBoxLayout()
|
|
97
|
+
# spacer_left = QSpacerItem(
|
|
98
|
+
# 50, 5, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum)
|
|
99
|
+
# spacer_right = QSpacerItem(
|
|
100
|
+
# 200, 5, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum)
|
|
101
|
+
# nacelle_type_layout.addItem(spacer_left)
|
|
102
|
+
# nacelle_type_layout.addWidget(nacelle_type_label)
|
|
103
|
+
# self.nacelle_combo = QComboBox()
|
|
104
|
+
# self.nacelle_combo.addItems(["Select Nacelle Type","Generic Nacelle", "Body of Revolution", "Stack Nacelle"])
|
|
105
|
+
# self.nacelle_combo.setFixedWidth(600)
|
|
106
|
+
# nacelle_type_layout.addWidget(self.nacelle_combo, alignment=Qt.AlignmentFlag.AlignCenter)
|
|
107
|
+
# nacelle_type_layout.addItem(spacer_right)
|
|
108
|
+
|
|
109
|
+
# assert self.main_layout is not None
|
|
110
|
+
# self.main_layout.addLayout(nacelle_type_layout)
|
|
111
|
+
|
|
112
|
+
# # noinspection PyUnresolvedReferences
|
|
113
|
+
# def add_buttons_layout(self):
|
|
114
|
+
# """Add the save, delete, and new buttons to the layout."""
|
|
115
|
+
# assert self.main_layout is not None
|
|
116
|
+
|
|
117
|
+
# new_section_button = QPushButton("New Nacelle Section", self)
|
|
118
|
+
# new_section_button.setStyleSheet("color:#dbe7ff; font-weight:500; margin:0; padding:0;")
|
|
119
|
+
# save_button = QPushButton("Save Data", self)
|
|
120
|
+
# save_button.setStyleSheet("color:#dbe7ff; font-weight:500; margin:0; padding:0;")
|
|
121
|
+
# delete_button = QPushButton("Delete Data", self)
|
|
122
|
+
# delete_button.setStyleSheet("color:#dbe7ff; font-weight:500; margin:0; padding:0;")
|
|
123
|
+
# new_button = QPushButton("New Nacelle Structure", self)
|
|
124
|
+
# new_button.setStyleSheet("color:#dbe7ff; font-weight:500; margin:0; padding:0;")
|
|
125
|
+
|
|
126
|
+
# new_section_button.clicked.connect(self.add_nacelle_section)
|
|
127
|
+
# save_button.clicked.connect(self.save_data)
|
|
128
|
+
# delete_button.clicked.connect(self.delete_data)
|
|
129
|
+
# new_button.clicked.connect(self.create_new_structure)
|
|
130
|
+
|
|
131
|
+
# buttons_layout = QHBoxLayout()
|
|
132
|
+
# buttons_layout.addWidget(new_section_button)
|
|
133
|
+
# buttons_layout.addWidget(save_button)
|
|
134
|
+
# buttons_layout.addWidget(delete_button)
|
|
135
|
+
# buttons_layout.addWidget(new_button)
|
|
136
|
+
# self.main_layout.addLayout(buttons_layout)
|
|
137
|
+
|
|
138
|
+
# # noinspection DuplicatedCode
|
|
139
|
+
# def save_data(self):
|
|
140
|
+
# """Call the save function and pass the entered data to it."""
|
|
141
|
+
# entered_data, v_comp = self.get_data_values()
|
|
142
|
+
# if self.save_function:
|
|
143
|
+
# if self.index >= 0:
|
|
144
|
+
# self.index = self.save_function(
|
|
145
|
+
# tab_index=self.tab_index, index=self.index, data=entered_data)
|
|
146
|
+
# return
|
|
147
|
+
# else:
|
|
148
|
+
# self.index = self.save_function(
|
|
149
|
+
# tab_index=self.tab_index, vehicle_component=v_comp, data=entered_data, new=True)
|
|
150
|
+
|
|
151
|
+
# show_popup("Data Saved!", self)
|
|
152
|
+
|
|
153
|
+
# def add_nacelle_section(self):
|
|
154
|
+
# self.nacelle_sections_layout.addWidget(NacelleSectionWidget(
|
|
155
|
+
# self.nacelle_sections_layout.count(), self.delete_nacelle_section))
|
|
156
|
+
|
|
157
|
+
# def delete_nacelle_section(self, index):
|
|
158
|
+
# item = self.nacelle_sections_layout.itemAt(index)
|
|
159
|
+
# if item is None:
|
|
160
|
+
# return
|
|
161
|
+
|
|
162
|
+
# widget = item.widget()
|
|
163
|
+
# if widget is None or not isinstance(widget, NacelleSectionWidget):
|
|
164
|
+
# return
|
|
165
|
+
|
|
166
|
+
# widget.deleteLater()
|
|
167
|
+
# self.nacelle_sections_layout.removeWidget(widget)
|
|
168
|
+
# self.nacelle_sections_layout.update()
|
|
169
|
+
|
|
170
|
+
# for i in range(index, self.nacelle_sections_layout.count()):
|
|
171
|
+
# item = self.nacelle_sections_layout.itemAt(i)
|
|
172
|
+
# if item is None:
|
|
173
|
+
# continue
|
|
174
|
+
|
|
175
|
+
# widget = item.widget()
|
|
176
|
+
# if widget is not None and isinstance(widget, NacelleSectionWidget):
|
|
177
|
+
# widget.index = i
|
|
178
|
+
|
|
179
|
+
# # TODO: Implement proper deletion of data
|
|
180
|
+
# def delete_data(self):
|
|
181
|
+
# pass
|
|
182
|
+
|
|
183
|
+
# def create_new_structure(self):
|
|
184
|
+
# """Create a new nacelle structure."""
|
|
185
|
+
# # Clear the main data values
|
|
186
|
+
# self.data_entry_widget.clear_values()
|
|
187
|
+
# self.name_line_edit.clear()
|
|
188
|
+
|
|
189
|
+
# # Clear the nacelle sections
|
|
190
|
+
# for i in range(self.nacelle_sections_layout.count()):
|
|
191
|
+
# item = self.nacelle_sections_layout.itemAt(i)
|
|
192
|
+
# if item is None:
|
|
193
|
+
# continue
|
|
194
|
+
|
|
195
|
+
# widget = item.widget()
|
|
196
|
+
# if widget is not None and isinstance(widget, NacelleSectionWidget):
|
|
197
|
+
# widget.deleteLater()
|
|
198
|
+
|
|
199
|
+
# self.nacelle_sections_layout.update()
|
|
200
|
+
# self.index = -1
|
|
201
|
+
|
|
202
|
+
# def create_rcaide_structure(self):
|
|
203
|
+
# """Create a nacelle structure from the given data."""
|
|
204
|
+
# data = self.data_entry_widget.get_values_si()
|
|
205
|
+
# data["name"] = self.name_line_edit.text()
|
|
206
|
+
|
|
207
|
+
# # TODO: what is this line
|
|
208
|
+
# # self.nacelle_combo.addItems(["Select Nacelle Type","Generic Nacelle", "Body of Revolution", "Stack Nacelle"])
|
|
209
|
+
# # selected_nacelle_type = self.nacelle_combo.currentText()
|
|
210
|
+
# # nacelle = RCAIDE.Library.Components.Nacelles.Nacelle() #set to default
|
|
211
|
+
# # if selected_nacelle_type == "Generic Nacelle":
|
|
212
|
+
# # nacelle = RCAIDE.Library.Components.Nacelles.Nacelle()
|
|
213
|
+
# # if selected_nacelle_type == "Body of Revolution":
|
|
214
|
+
# nacelle = RCAIDE.Library.Components.Nacelles.Body_of_Revolution_Nacelle()
|
|
215
|
+
# # if selected_nacelle_type == "Stack Nacelle":
|
|
216
|
+
# # nacelle = RCAIDE.Library.Components.Nacelles.Stack_Nacelle()
|
|
217
|
+
|
|
218
|
+
# # assign nacelle name
|
|
219
|
+
# nacelle.tag = data["name"]
|
|
220
|
+
|
|
221
|
+
# # assign nacelle properties
|
|
222
|
+
# for data_unit_label in self.data_units_labels:
|
|
223
|
+
# user_label = data_unit_label[0]
|
|
224
|
+
# rcaide_label = data_unit_label[-1]
|
|
225
|
+
# set_data(nacelle, rcaide_label, data[user_label][0])
|
|
226
|
+
|
|
227
|
+
# nacelle_airfoil = RCAIDE.Library.Components.Airfoils.NACA_4_Series_Airfoil()
|
|
228
|
+
# nacelle_airfoil.NACA_4_Series_code = '2410' # UPDATE
|
|
229
|
+
# nacelle.append_airfoil(nacelle_airfoil)
|
|
230
|
+
|
|
231
|
+
# for i in range(self.nacelle_sections_layout.count()):
|
|
232
|
+
# item = self.nacelle_sections_layout.itemAt(i)
|
|
233
|
+
# if item is None:
|
|
234
|
+
# continue
|
|
235
|
+
|
|
236
|
+
# widget = item.widget()
|
|
237
|
+
# if widget is not None and isinstance(widget, NacelleSectionWidget):
|
|
238
|
+
# _, segment = widget.get_data_values()
|
|
239
|
+
# nacelle.append_segment(segment)
|
|
240
|
+
|
|
241
|
+
# return nacelle
|
|
242
|
+
|
|
243
|
+
# def get_data_values(self):
|
|
244
|
+
# """Retrieve the entered data values from the text fields."""
|
|
245
|
+
# data = self.data_entry_widget.get_values()
|
|
246
|
+
# data_si = self.data_entry_widget.get_values_si()
|
|
247
|
+
# data_si["name"] = self.name_line_edit.text()
|
|
248
|
+
|
|
249
|
+
# nacelle = self.create_rcaide_structure()
|
|
250
|
+
|
|
251
|
+
# data["sections"] = []
|
|
252
|
+
# for i in range(self.nacelle_sections_layout.count()):
|
|
253
|
+
# item = self.nacelle_sections_layout.itemAt(i)
|
|
254
|
+
# if item is None:
|
|
255
|
+
# continue
|
|
256
|
+
|
|
257
|
+
# widget = item.widget()
|
|
258
|
+
# if widget is not None and isinstance(widget, NacelleSectionWidget):
|
|
259
|
+
# segment_data, segment = widget.get_data_values()
|
|
260
|
+
# data["sections"].append(segment_data)
|
|
261
|
+
# nacelle.append_segment(segment)
|
|
262
|
+
|
|
263
|
+
# data["name"] = self.name_line_edit.text()
|
|
264
|
+
# return data, nacelle
|
|
265
|
+
|
|
266
|
+
# def load_data(self, data, index):
|
|
267
|
+
# """Load the data into the widgets.
|
|
268
|
+
|
|
269
|
+
# Args:
|
|
270
|
+
# data: The data to be loaded into the widgets.
|
|
271
|
+
# index: The index of the data in the list.
|
|
272
|
+
# """
|
|
273
|
+
# self.data_entry_widget.load_data(data)
|
|
274
|
+
# while self.nacelle_sections_layout.count():
|
|
275
|
+
# item = self.nacelle_sections_layout.takeAt(0)
|
|
276
|
+
# assert item is not None
|
|
277
|
+
# widget = item.widget()
|
|
278
|
+
# if widget is not None:
|
|
279
|
+
# widget.deleteLater()
|
|
280
|
+
|
|
281
|
+
# clear_layout(self.nacelle_sections_layout)
|
|
282
|
+
# self.name_line_edit.setText(data["name"])
|
|
283
|
+
# self.index = index
|