commit
af5c8f8f3c
226
FlatCAMApp.py
226
FlatCAMApp.py
|
@ -255,6 +255,15 @@ class App(QtCore.QObject):
|
|||
json.dump([], f)
|
||||
f.close()
|
||||
|
||||
try:
|
||||
fp = open(self.data_path + '/recent_projects.json')
|
||||
fp.close()
|
||||
except IOError:
|
||||
App.log.debug('Creating empty recent_projects.json')
|
||||
fp = open(self.data_path + '/recent_projects.json', 'w')
|
||||
json.dump([], fp)
|
||||
fp.close()
|
||||
|
||||
# Application directory. CHDIR to it. Otherwise, trying to load
|
||||
# GUI icons will fail as their path is relative.
|
||||
# This will fail under cx_freeze ...
|
||||
|
@ -294,6 +303,8 @@ class App(QtCore.QObject):
|
|||
# ### Data ####
|
||||
# #############
|
||||
self.recent = []
|
||||
self.recent_projects = []
|
||||
|
||||
self.clipboard = QtWidgets.QApplication.clipboard()
|
||||
self.proc_container = FCVisibleProcessContainer(self.ui.activity_view)
|
||||
|
||||
|
@ -1499,6 +1510,7 @@ class App(QtCore.QObject):
|
|||
self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.connect(
|
||||
lambda: self.on_toggle_units(no_pref=False))
|
||||
|
||||
|
||||
# ##############################
|
||||
# ### GUI PREFERENCES SIGNALS ##
|
||||
# ##############################
|
||||
|
@ -1960,6 +1972,9 @@ class App(QtCore.QObject):
|
|||
# Variable to store the GCODE that was edited
|
||||
self.gcode_edited = ""
|
||||
|
||||
# if Preferences are changed in the Edit -> Preferences tab the value will be set to True
|
||||
self.preferences_changed_flag = False
|
||||
|
||||
self.grb_list = ['gbr', 'ger', 'gtl', 'gbl', 'gts', 'gbs', 'gtp', 'gbp', 'gto', 'gbo', 'gm1', 'gm2', 'gm3',
|
||||
'gko', 'cmp', 'sol', 'stc', 'sts', 'plc', 'pls', 'crc', 'crs', 'tsm', 'bsm', 'ly2', 'ly15',
|
||||
'dim', 'mil', 'grb', 'top', 'bot', 'smt', 'smb', 'sst', 'ssb', 'spt', 'spb', 'pho', 'gdo',
|
||||
|
@ -2922,12 +2937,19 @@ class App(QtCore.QObject):
|
|||
record = {'kind': str(kind), 'filename': str(filename)}
|
||||
if record in self.recent:
|
||||
return
|
||||
|
||||
self.recent.insert(0, record)
|
||||
if record in self.recent_projects:
|
||||
return
|
||||
if record['kind'] == 'project':
|
||||
self.recent_projects.insert(0, record)
|
||||
else:
|
||||
self.recent.insert(0, record)
|
||||
|
||||
if len(self.recent) > self.defaults['global_recent_limit']: # Limit reached
|
||||
self.recent.pop()
|
||||
|
||||
if len(self.recent_projects) > self.defaults['global_recent_limit']: # Limit reached
|
||||
self.recent_projects.pop()
|
||||
|
||||
try:
|
||||
f = open(self.data_path + '/recent.json', 'w')
|
||||
except IOError:
|
||||
|
@ -2938,6 +2960,16 @@ class App(QtCore.QObject):
|
|||
json.dump(self.recent, f, default=to_dict, indent=2, sort_keys=True)
|
||||
f.close()
|
||||
|
||||
try:
|
||||
fp = open(self.data_path + '/recent_projects.json', 'w')
|
||||
except IOError:
|
||||
App.log.error("Failed to open recent items file for writing.")
|
||||
self.inform.emit(_('[ERROR_NOTCL] Failed to open recent projects file for writing.'))
|
||||
return
|
||||
|
||||
json.dump(self.recent_projects, fp, default=to_dict, indent=2, sort_keys=True)
|
||||
fp.close()
|
||||
|
||||
# Re-build the recent items menu
|
||||
self.setup_recent_items()
|
||||
|
||||
|
@ -4541,6 +4573,7 @@ class App(QtCore.QObject):
|
|||
|
||||
def on_save_button(self):
|
||||
log.debug("App.on_save_button() --> Saving preferences to file.")
|
||||
self.preferences_changed_flag = False
|
||||
|
||||
self.save_defaults(silent=False)
|
||||
# load the defaults so they are updated into the app
|
||||
|
@ -5133,7 +5166,6 @@ class App(QtCore.QObject):
|
|||
self.draw_selection_shape(curr_sel_obj)
|
||||
|
||||
def on_preferences(self):
|
||||
|
||||
# add the tab if it was closed
|
||||
self.ui.plot_tab_area.addTab(self.ui.preferences_tab, _("Preferences"))
|
||||
|
||||
|
@ -5145,6 +5177,115 @@ class App(QtCore.QObject):
|
|||
self.ui.plot_tab_area.setCurrentWidget(self.ui.preferences_tab)
|
||||
self.ui.show()
|
||||
|
||||
# this disconnect() is done so the slot will be connected only once
|
||||
try:
|
||||
self.ui.plot_tab_area.tab_closed_signal.disconnect(self.on_preferences_closed)
|
||||
except TypeError:
|
||||
pass
|
||||
self.ui.plot_tab_area.tab_closed_signal.connect(self.on_preferences_closed)
|
||||
|
||||
# detect changes in the preferences
|
||||
for idx in range(self.ui.pref_tab_area.count()):
|
||||
for tb in self.ui.pref_tab_area.widget(idx).findChildren(QtCore.QObject):
|
||||
try:
|
||||
try:
|
||||
tb.textEdited.disconnect()
|
||||
except TypeError:
|
||||
pass
|
||||
tb.textEdited.connect(self.on_preferences_edited)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
try:
|
||||
tb.modificationChanged.disconnect()
|
||||
except TypeError:
|
||||
pass
|
||||
tb.modificationChanged.connect(self.on_preferences_edited)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
try:
|
||||
tb.toggled.disconnect()
|
||||
except TypeError:
|
||||
pass
|
||||
tb.toggled.connect(self.on_preferences_edited)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
try:
|
||||
tb.valueChanged.disconnect()
|
||||
except TypeError:
|
||||
pass
|
||||
tb.valueChanged.connect(self.on_preferences_edited)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
try:
|
||||
tb.currentIndexChanged.disconnect()
|
||||
except TypeError:
|
||||
pass
|
||||
tb.currentIndexChanged.connect(self.on_preferences_edited)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def on_preferences_edited(self):
|
||||
self.inform.emit(_("[WARNING_NOTCL] Preferences edited but not saved."))
|
||||
self.preferences_changed_flag = True
|
||||
|
||||
def on_preferences_closed(self):
|
||||
# disconnect
|
||||
for idx in range(self.ui.pref_tab_area.count()):
|
||||
for tb in self.ui.pref_tab_area.widget(idx).findChildren(QtCore.QObject):
|
||||
try:
|
||||
tb.textEdited.disconnect()
|
||||
except (TypeError, AttributeError):
|
||||
pass
|
||||
|
||||
try:
|
||||
tb.modificationChanged.disconnect()
|
||||
except (TypeError, AttributeError):
|
||||
pass
|
||||
|
||||
try:
|
||||
tb.toggled.disconnect()
|
||||
except (TypeError, AttributeError):
|
||||
pass
|
||||
|
||||
try:
|
||||
tb.valueChanged.disconnect()
|
||||
except (TypeError, AttributeError):
|
||||
pass
|
||||
|
||||
try:
|
||||
tb.currentIndexChanged.disconnect()
|
||||
except (TypeError, AttributeError):
|
||||
pass
|
||||
|
||||
if self.preferences_changed_flag is True:
|
||||
msgbox = QtWidgets.QMessageBox()
|
||||
msgbox.setText(_("One or more values are changed.\n"
|
||||
"Do you want to save the Preferences?"))
|
||||
msgbox.setWindowTitle(_("Save Preferences"))
|
||||
msgbox.setWindowIcon(QtGui.QIcon('share/save_as.png'))
|
||||
|
||||
bt_yes = msgbox.addButton(_('Yes'), QtWidgets.QMessageBox.YesRole)
|
||||
bt_no = msgbox.addButton(_('No'), QtWidgets.QMessageBox.NoRole)
|
||||
|
||||
msgbox.setDefaultButton(bt_yes)
|
||||
msgbox.exec_()
|
||||
response = msgbox.clickedButton()
|
||||
|
||||
if response == bt_yes:
|
||||
self.on_save_button()
|
||||
self.inform.emit(_("[success] Defaults saved."))
|
||||
else:
|
||||
self.preferences_changed_flag = False
|
||||
return
|
||||
|
||||
def on_flipy(self):
|
||||
self.report_usage("on_flipy()")
|
||||
|
||||
|
@ -8253,7 +8394,7 @@ class App(QtCore.QObject):
|
|||
'pdf': lambda fname: self.worker_task.emit({'fcn': self.pdf_tool.open_pdf, 'params': [fname]})
|
||||
}
|
||||
|
||||
# Open file
|
||||
# Open recent file for files
|
||||
try:
|
||||
f = open(self.data_path + '/recent.json')
|
||||
except IOError:
|
||||
|
@ -8270,6 +8411,23 @@ class App(QtCore.QObject):
|
|||
return
|
||||
f.close()
|
||||
|
||||
# Open recent file for projects
|
||||
try:
|
||||
fp = open(self.data_path + '/recent_projects.json')
|
||||
except IOError:
|
||||
App.log.error("Failed to load recent project item list.")
|
||||
self.inform.emit(_("[ERROR_NOTCL] Failed to load recent projects item list."))
|
||||
return
|
||||
|
||||
try:
|
||||
self.recent_projects = json.load(fp)
|
||||
except json.scanner.JSONDecodeError:
|
||||
App.log.error("Failed to parse recent project item list.")
|
||||
self.inform.emit(_("[ERROR_NOTCL] Failed to parse recent project item list."))
|
||||
fp.close()
|
||||
return
|
||||
fp.close()
|
||||
|
||||
# Closure needed to create callbacks in a loop.
|
||||
# Otherwise late binding occurs.
|
||||
def make_callback(func, fname):
|
||||
|
@ -8277,7 +8435,7 @@ class App(QtCore.QObject):
|
|||
func(fname)
|
||||
return opener
|
||||
|
||||
def reset_recent():
|
||||
def reset_recent_files():
|
||||
# Reset menu
|
||||
self.ui.recent.clear()
|
||||
self.recent = []
|
||||
|
@ -8289,28 +8447,66 @@ class App(QtCore.QObject):
|
|||
|
||||
json.dump(self.recent, f)
|
||||
|
||||
def reset_recent_projects():
|
||||
# Reset menu
|
||||
self.ui.recent_projects.clear()
|
||||
self.recent_projects = []
|
||||
|
||||
try:
|
||||
fp = open(self.data_path + '/recent_projects.json', 'w')
|
||||
except IOError:
|
||||
App.log.error("Failed to open recent projects items file for writing.")
|
||||
return
|
||||
|
||||
json.dump(self.recent, fp)
|
||||
|
||||
# Reset menu
|
||||
self.ui.recent.clear()
|
||||
self.ui.recent_projects.clear()
|
||||
|
||||
# Create menu items
|
||||
# Create menu items for projects
|
||||
for recent in self.recent_projects:
|
||||
filename = recent['filename'].split('/')[-1].split('\\')[-1]
|
||||
|
||||
if recent['kind'] == 'project':
|
||||
try:
|
||||
action = QtWidgets.QAction(QtGui.QIcon(icons[recent["kind"]]), filename, self)
|
||||
|
||||
# Attach callback
|
||||
o = make_callback(openers[recent["kind"]], recent['filename'])
|
||||
action.triggered.connect(o)
|
||||
|
||||
self.ui.recent_projects.addAction(action)
|
||||
|
||||
except KeyError:
|
||||
App.log.error("Unsupported file type: %s" % recent["kind"])
|
||||
|
||||
# Last action in Recent Files menu is one that Clear the content
|
||||
clear_action_proj = QtWidgets.QAction(QtGui.QIcon('share/trash32.png'), (_("Clear Recent files")), self)
|
||||
clear_action_proj.triggered.connect(reset_recent_projects)
|
||||
self.ui.recent_projects.addSeparator()
|
||||
self.ui.recent_projects.addAction(clear_action_proj)
|
||||
|
||||
# Create menu items for files
|
||||
for recent in self.recent:
|
||||
filename = recent['filename'].split('/')[-1].split('\\')[-1]
|
||||
|
||||
try:
|
||||
action = QtWidgets.QAction(QtGui.QIcon(icons[recent["kind"]]), filename, self)
|
||||
if recent['kind'] != 'project':
|
||||
try:
|
||||
action = QtWidgets.QAction(QtGui.QIcon(icons[recent["kind"]]), filename, self)
|
||||
|
||||
# Attach callback
|
||||
o = make_callback(openers[recent["kind"]], recent['filename'])
|
||||
action.triggered.connect(o)
|
||||
# Attach callback
|
||||
o = make_callback(openers[recent["kind"]], recent['filename'])
|
||||
action.triggered.connect(o)
|
||||
|
||||
self.ui.recent.addAction(action)
|
||||
self.ui.recent.addAction(action)
|
||||
|
||||
except KeyError:
|
||||
App.log.error("Unsupported file type: %s" % recent["kind"])
|
||||
except KeyError:
|
||||
App.log.error("Unsupported file type: %s" % recent["kind"])
|
||||
|
||||
# Last action in Recent Files menu is one that Clear the content
|
||||
clear_action = QtWidgets.QAction(QtGui.QIcon('share/trash32.png'), (_("Clear Recent files")), self)
|
||||
clear_action.triggered.connect(reset_recent)
|
||||
clear_action.triggered.connect(reset_recent_files)
|
||||
self.ui.recent.addSeparator()
|
||||
self.ui.recent.addAction(clear_action)
|
||||
|
||||
|
|
10
README.md
10
README.md
|
@ -9,6 +9,16 @@ CAD program, and create G-Code for Isolation routing.
|
|||
|
||||
=================================================
|
||||
|
||||
31.07.2019
|
||||
|
||||
- changed the order of the menu entries in the FIle -> Open ...
|
||||
- organized the list of recent files so the Project entries are to the top and separated from the other types of file
|
||||
- work on identification of changes in Preferences tab
|
||||
- added categories names for the recent files
|
||||
- added a detection if any values are changed in the Edit -> Preferences window and on close it will ask the user if he wants to save the changes or not
|
||||
- created a new menu entry in the File menu named Recent projects that will hold the recent projects and the previous "Recent files" will hold only the previous loaded files
|
||||
- updated all translations for the new strings
|
||||
|
||||
30.07.2019
|
||||
|
||||
- fixed bug that crashed the software when trying to edit a GUI value in Geometry selected tab without having a tool in the Tools Table
|
||||
|
|
|
@ -79,13 +79,16 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
self.menufile_open = self.menufile.addMenu(QtGui.QIcon('share/folder32_bis.png'), _('Open'))
|
||||
self.menufile_open.setToolTipsVisible(True)
|
||||
|
||||
# Open gerber ...
|
||||
# Open Project ...
|
||||
self.menufileopenproject = QtWidgets.QAction(QtGui.QIcon('share/folder16.png'), _('Open &Project ...'), self)
|
||||
self.menufile_open.addAction(self.menufileopenproject)
|
||||
self.menufile_open.addSeparator()
|
||||
|
||||
# Open Gerber ...
|
||||
self.menufileopengerber = QtWidgets.QAction(QtGui.QIcon('share/flatcam_icon24.png'),
|
||||
_('Open &Gerber ...\tCTRL+G'), self)
|
||||
self.menufile_open.addAction(self.menufileopengerber)
|
||||
|
||||
self.menufile_open.addSeparator()
|
||||
|
||||
# Open Excellon ...
|
||||
self.menufileopenexcellon = QtWidgets.QAction(QtGui.QIcon('share/open_excellon32.png'),
|
||||
_('Open &Excellon ...\tCTRL+E'), self)
|
||||
|
@ -95,10 +98,6 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
self.menufileopengcode = QtWidgets.QAction(QtGui.QIcon('share/code.png'), _('Open G-&Code ...'), self)
|
||||
self.menufile_open.addAction(self.menufileopengcode)
|
||||
|
||||
# Open Project ...
|
||||
self.menufileopenproject = QtWidgets.QAction(QtGui.QIcon('share/folder16.png'), _('Open &Project ...'), self)
|
||||
self.menufile_open.addAction(self.menufileopenproject)
|
||||
|
||||
self.menufile_open.addSeparator()
|
||||
|
||||
# Open Config File...
|
||||
|
@ -106,6 +105,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
self.menufile_open.addAction(self.menufileopenconfig)
|
||||
|
||||
# Recent
|
||||
self.recent_projects = self.menufile.addMenu(QtGui.QIcon('share/recent_files.png'), _("Recent projects"))
|
||||
self.recent = self.menufile.addMenu(QtGui.QIcon('share/recent_files.png'), _("Recent files"))
|
||||
|
||||
# Separator
|
||||
|
@ -757,10 +757,9 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
self.snap_max_dist_entry.setToolTip(_("Max. magnet distance"))
|
||||
self.snap_magnet = self.snap_toolbar.addWidget(self.snap_max_dist_entry)
|
||||
|
||||
|
||||
############## ##
|
||||
# ############# ##
|
||||
# ## Notebook # ##
|
||||
############## ##
|
||||
# ############# ##
|
||||
|
||||
# ## Project # ##
|
||||
# self.project_tab = QtWidgets.QWidget()
|
||||
|
@ -811,7 +810,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
self.right_lay.setContentsMargins(0, 0, 0, 0)
|
||||
self.right_widget.setLayout(self.right_lay)
|
||||
# self.plot_tab_area = FCTab()
|
||||
self.plot_tab_area = FCDetachableTab(protect=False, protect_by_name=[_('Plot Area')])
|
||||
self.plot_tab_area = FCDetachableTab2(protect=False, protect_by_name=[_('Plot Area')])
|
||||
self.plot_tab_area.useOldIndex(True)
|
||||
|
||||
self.right_lay.addWidget(self.plot_tab_area)
|
||||
|
@ -828,9 +827,9 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
# remove the close button from the Plot Area tab (first tab index = 0) as this one will always be ON
|
||||
self.plot_tab_area.protectTab(0)
|
||||
|
||||
###################################### ##
|
||||
# ##################################### ##
|
||||
# ## HERE WE BUILD THE PREF. TAB AREA # ##
|
||||
###################################### ##
|
||||
# ##################################### ##
|
||||
self.preferences_tab = QtWidgets.QWidget()
|
||||
self.pref_tab_layout = QtWidgets.QVBoxLayout(self.preferences_tab)
|
||||
self.pref_tab_layout.setContentsMargins(2, 2, 2, 2)
|
||||
|
@ -843,6 +842,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
self.pref_tab_layout.addWidget(self.pref_tab_area)
|
||||
|
||||
self.general_tab = QtWidgets.QWidget()
|
||||
self.general_tab.setObjectName("general_tab")
|
||||
self.pref_tab_area.addTab(self.general_tab, _("General"))
|
||||
self.general_tab_lay = QtWidgets.QVBoxLayout()
|
||||
self.general_tab_lay.setContentsMargins(2, 2, 2, 2)
|
||||
|
@ -864,6 +864,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
self.general_tab_lay.addWidget(self.general_scroll_area)
|
||||
|
||||
self.gerber_tab = QtWidgets.QWidget()
|
||||
self.gerber_tab.setObjectName("gerber_tab")
|
||||
self.pref_tab_area.addTab(self.gerber_tab, _("GERBER"))
|
||||
self.gerber_tab_lay = QtWidgets.QVBoxLayout()
|
||||
self.gerber_tab_lay.setContentsMargins(2, 2, 2, 2)
|
||||
|
@ -873,6 +874,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
self.gerber_tab_lay.addWidget(self.gerber_scroll_area)
|
||||
|
||||
self.excellon_tab = QtWidgets.QWidget()
|
||||
self.excellon_tab.setObjectName("excellon_tab")
|
||||
self.pref_tab_area.addTab(self.excellon_tab, _("EXCELLON"))
|
||||
self.excellon_tab_lay = QtWidgets.QVBoxLayout()
|
||||
self.excellon_tab_lay.setContentsMargins(2, 2, 2, 2)
|
||||
|
@ -882,6 +884,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
self.excellon_tab_lay.addWidget(self.excellon_scroll_area)
|
||||
|
||||
self.geometry_tab = QtWidgets.QWidget()
|
||||
self.geometry_tab.setObjectName("geometry_tab")
|
||||
self.pref_tab_area.addTab(self.geometry_tab, _("GEOMETRY"))
|
||||
self.geometry_tab_lay = QtWidgets.QVBoxLayout()
|
||||
self.geometry_tab_lay.setContentsMargins(2, 2, 2, 2)
|
||||
|
@ -2484,7 +2487,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
if key == QtCore.Qt.Key_3 or key == '3':
|
||||
self.app.on_select_tab('tool')
|
||||
|
||||
if self.app.geo_editor.active_tool is not None and self.geo_select_btn.isChecked() == False:
|
||||
if self.app.geo_editor.active_tool is not None and self.geo_select_btn.isChecked() is False:
|
||||
response = self.app.geo_editor.active_tool.on_key(key=key)
|
||||
if response is not None:
|
||||
self.app.inform.emit(response)
|
||||
|
|
|
@ -884,6 +884,7 @@ class FCDetachableTab(QtWidgets.QTabWidget):
|
|||
:param currentIndex:
|
||||
:return:
|
||||
"""
|
||||
|
||||
self.removeTab(currentIndex)
|
||||
|
||||
def protectTab(self, currentIndex):
|
||||
|
@ -1348,6 +1349,28 @@ class FCDetachableTab(QtWidgets.QTabWidget):
|
|||
self.detachedTabDropSignal.emit(name, index, dropPos)
|
||||
|
||||
|
||||
class FCDetachableTab2(FCDetachableTab):
|
||||
tab_closed_signal = pyqtSignal()
|
||||
|
||||
def __init__(self, protect=None, protect_by_name=None, parent=None):
|
||||
super(FCDetachableTab2, self).__init__(protect=protect, protect_by_name=protect_by_name, parent=parent)
|
||||
|
||||
def closeTab(self, currentIndex):
|
||||
"""
|
||||
Slot connected to the tabCloseRequested signal
|
||||
|
||||
:param currentIndex:
|
||||
:return:
|
||||
"""
|
||||
idx = self.currentIndex()
|
||||
|
||||
# emit the signal only if the name is the one we want; the name should be a parameter somehow
|
||||
if self.tabText(idx) == _("Preferences"):
|
||||
self.tab_closed_signal.emit()
|
||||
|
||||
self.removeTab(currentIndex)
|
||||
|
||||
|
||||
class VerticalScrollArea(QtWidgets.QScrollArea):
|
||||
"""
|
||||
This widget extends QtGui.QScrollArea to make a vertical-only
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue