Все изменения накопившиеся с релиза

This commit is contained in:
2025-11-14 21:56:39 +03:00
parent ac2fe4d653
commit 9b8b5ec533
17 changed files with 1008 additions and 699 deletions

View File

@@ -1,109 +1,150 @@
classdef mcuPath
% Класс для работы с путями файлов и папок в маске Simulink
% Обеспечивает преобразование путей, добавление в таблицы и параметры
methods(Static)
%% GET PATH FROM PARAM
%% GET PATH FROM PARAM - получение путей из параметров маски
function path = get(paramName)
% Получение значения пути из параметра маски
% paramName - имя параметра маски содержащего путь
% Возвращает строку с путём (абсолютным или относительным)
blockPath = gcb;
path = get_param(blockPath, paramName);
end
%% ADD PATH TO TABLE
%% ADD PATH TO TABLE - добавление путей в табличные параметры
function addSourceFileTable(targetParamName, message)
% Открываем проводник для выбора файлов
% Добавление исходных файлов в таблицу через диалог выбора
% targetParamName - имя табличного параметра маски
% message - сообщение в диалоге выбора
% Открываем проводник для выбора файлов с фильтрами
[files, pathstr] = uigetfile({ ...
'*.c;*.cpp', 'Исходные файлы (*.c, *.cpp)'; ...
'*.obj;*.lib', 'Библиотеки (*.obj, *.lib)'; ...
'*.*', 'Все файлы (*.*)'}, ...
message, ...
'MultiSelect', 'on');
'MultiSelect', 'on'); % Разрешаем множественный выбор
if isequal(files, 0)
return; % Отмена выбора
return; % Пользователь отменил выбор
end
% Нормализуем входные данные: один файл -> cell array
if ischar(files)
files = {files}; % Один файл в cell
files = {files};
end
% Парсим строку в cell-массив
% Читаем текущее содержимое таблицы
oldTable = customtable.parse(targetParamName);
% Добавляем новые пути, проверяя уникальность
for i = 1:numel(files)
fullpath = fullfile(pathstr, files{i});
% Преобразуем абсолютный путь в относительный
rel = mcuPath.absoluteToRelativePath(fullpath);
% Добавляем только если путь ещё не существует в таблице
if ~any(strcmp(rel, oldTable))
oldTable{end+1, 1} = rel;
end
end
% Парсим строку в cell-массив
% Сохраняем обновленную таблицу обратно в параметр маски
customtable.collect(targetParamName, oldTable);
end
function addPathTable(targetParamName, message)
% Открываем проводник для выбора папок
% Добавление путей к папкам в таблицу через диалог выбора
% targetParamName - имя табличного параметра маски
% message - сообщение в диалоге выбора
% Открываем проводник для выбора папки
pathstr = uigetdir(pwd, message);
if isequal(pathstr, 0)
return; % Отмена выбора
return; % Пользователь отменил выбор
end
% Парсим таблицу
% Читаем текущее содержимое таблицы
oldTable = customtable.parse(targetParamName);
% Преобразуем абсолютный путь в относительный
rel = mcuPath.absoluteToRelativePath(pathstr);
% Проверяем наличие пути
% Проверяем наличие пути в таблице и добавляем если нужно
if ~any(strcmp(rel, oldTable))
oldTable{end+1, 1} = rel;
end
% Собираем таблицу
% Сохраняем обновленную таблицу
customtable.collect(targetParamName, oldTable);
end
%% ADD PATH TO EDIT
%% ADD PATH TO EDIT - добавление путей в текстовые параметры
function addPath(targetParamName, message)
% Добавление пути к папке в текстовый параметр маски
% targetParamName - имя параметра маски для пути
% message - сообщение в диалоге выбора (не используется)
block = gcb;
mask = Simulink.Mask.get(block);
% Открываем окно выбора папки
folderPath = uigetdir('', 'Выберите папку');
% Проверка на отмену
% Проверка на отмену выбора
if isequal(folderPath, 0)
return;
end
% Установка значения параметра маски
% Преобразуем абсолютный путь в относительный
rel = mcuPath.absoluteToRelativePath(folderPath);
% Устанавливаем значение параметра маски
param = mask.getParameter(targetParamName);
param.Value = rel;
end
function addAnyFile(targetParamName, message)
% Добавление пути к файлу в текстовый параметр маски
% targetParamName - имя параметра маски для пути к файлу
% message - сообщение в диалоге выбора (не используется)
block = gcbh;
mask = Simulink.Mask.get(block);
% Открываем проводник для выбора любого файла
[file, path] = uigetfile({'*.*','Все файлы (*.*)'}, 'Выберите файл');
if isequal(file, 0) || isequal(path, 0)
% Отмена выбора ничего не делаем
return;
return; % Пользователь отменил выбор
end
% Формируем полный путь и преобразуем в относительный
fullFilePath = fullfile(path, file);
rel = mcuPath.absoluteToRelativePath(fullFilePath);
% Устанавливаем значение параметра маски
param = mask.getParameter(targetParamName);
param.Value = rel;
end
%% GET PATH STRING
%% GET PATH STRING - утилиты преобразования путей
function absPath = getAbsolutePath(relPath)
% relativeToAbsolutePath преобразует относительный путь в абсолютный.
%
% Если путь уже абсолютный возвращается он же, приведённый к канонической форме.
% Если путь относительный преобразуется относительно текущей директории.
% Преобразование относительного пути в абсолютный
% relPath - относительный или абсолютный путь
% Возвращает абсолютный путь в канонической форме
% Проверка: абсолютный ли путь
% Проверка: абсолютный ли путь уже
if ispc
% Для Windows: путь начинается с буквы диска или \\
isAbsolute = ~isempty(regexp(relPath, '^[a-zA-Z]:[\\/]', 'once')) || startsWith(relPath, '\\');
else
% Для Unix: путь начинается с /
isAbsolute = startsWith(relPath, '/');
end
@@ -111,7 +152,7 @@ classdef mcuPath
% Канонизируем абсолютный путь (убираем ./, ../ и т.п.)
absPath = char(java.io.File(relPath).getCanonicalPath());
else
% Строим абсолютный путь от текущей директории
% Строим абсолютный путь относительно текущей директории
cwd = pwd;
combined = fullfile(cwd, relPath);
absPath = char(java.io.File(combined).getCanonicalPath());
@@ -119,50 +160,52 @@ classdef mcuPath
end
function rel = absoluteToRelativePath(pathstr)
% absoluteToRelativePath преобразует абсолютный путь в относительный от текущей директории.
% Преобразование абсолютного пути в относительный относительно текущей директории
% pathstr - абсолютный путь для преобразования
% Возвращает относительный путь
%
% Если путь находится в текущей директории или вложенной в неё добавляется префикс './'
% Если выше формируются переходы '..'
% Если путь совпадает с текущей директорией возвращается '.'
% Примеры:
% Если путь в текущей директории -> './filename'
% Если путь выше -> '../parent/filename'
% Если путь совпадает с текущей директорией -> '.'
% Получаем текущую рабочую директорию
cwd = pwd;
% Преобразуем пути в канонические абсолютные пути
% Преобразуем оба пути в канонические абсолютные пути
fullpath = char(java.io.File(pathstr).getCanonicalPath());
cwd = char(java.io.File(cwd).getCanonicalPath());
% Разбиваем пути на части
% Разбиваем пути на части по разделителю файловой системы
targetParts = strsplit(fullpath, filesep);
baseParts = strsplit(cwd, filesep);
% Находим длину общего префикса
% Находим длину общего префикса (совпадающих частей пути)
j = 1;
while j <= min(length(targetParts), length(baseParts)) && strcmpi(targetParts{j}, baseParts{j})
j = j + 1;
end
% Формируем количество подъемов ".." из cwd
% Формируем количество подъемов ".." для выхода из базовой директории
numUps = length(baseParts) - (j - 1);
ups = repmat({'..'}, 1, numUps);
% Оставшаяся часть пути после общего префикса
% Оставшаяся часть целевого пути после общего префикса
rest = targetParts(j:end);
% Объединяем для получения относительного пути
% Объединяем части для получения относительного пути
relParts = [ups, rest];
rel = fullfile(relParts{:});
% Если путь пустой это текущая директория
% Если путь пустой - это текущая директория
if isempty(rel)
rel = '.';
end
% Если путь не содержит ".." и начинается внутри текущей директории добавим './'
% Если путь не содержит ".." и начинается внутри текущей директории - добавляем './'
if ~isempty(rest) && isempty(ups)
rel = fullfile('.', rel);
end
end
end
end