211 lines
11 KiB
Matlab
211 lines
11 KiB
Matlab
classdef mcuPath
|
||
% Класс для работы с путями файлов и папок в маске Simulink
|
||
% Обеспечивает преобразование путей, добавление в таблицы и параметры
|
||
|
||
methods(Static)
|
||
|
||
%% GET PATH FROM PARAM - получение путей из параметров маски
|
||
function path = get(paramName)
|
||
% Получение значения пути из параметра маски
|
||
% paramName - имя параметра маски содержащего путь
|
||
% Возвращает строку с путём (абсолютным или относительным)
|
||
|
||
blockPath = gcb;
|
||
path = get_param(blockPath, paramName);
|
||
end
|
||
|
||
%% ADD PATH TO TABLE - добавление путей в табличные параметры
|
||
|
||
function addSourceFileTable(targetParamName, message)
|
||
% Добавление исходных файлов в таблицу через диалог выбора
|
||
% targetParamName - имя табличного параметра маски
|
||
% message - сообщение в диалоге выбора
|
||
|
||
% Открываем проводник для выбора файлов с фильтрами
|
||
[files, pathstr] = uigetfile({ ...
|
||
'*.c;*.cpp', 'Исходные файлы (*.c, *.cpp)'; ...
|
||
'*.obj;*.lib', 'Библиотеки (*.obj, *.lib)'; ...
|
||
'*.*', 'Все файлы (*.*)'}, ...
|
||
message, ...
|
||
'MultiSelect', 'on'); % Разрешаем множественный выбор
|
||
|
||
if isequal(files, 0)
|
||
return; % Пользователь отменил выбор
|
||
end
|
||
|
||
% Нормализуем входные данные: один файл -> cell array
|
||
if ischar(files)
|
||
files = {files};
|
||
end
|
||
|
||
% Читаем текущее содержимое таблицы
|
||
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
|
||
|
||
% Сохраняем обновленную таблицу обратно в параметр маски
|
||
customtable.collect(targetParamName, oldTable);
|
||
end
|
||
|
||
function addPathTable(targetParamName, message)
|
||
% Добавление путей к папкам в таблицу через диалог выбора
|
||
% targetParamName - имя табличного параметра маски
|
||
% message - сообщение в диалоге выбора
|
||
|
||
% Открываем проводник для выбора папки
|
||
pathstr = uigetdir(pwd, message);
|
||
if isequal(pathstr, 0)
|
||
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 - добавление путей в текстовые параметры
|
||
|
||
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; % Пользователь отменил выбор
|
||
end
|
||
|
||
% Формируем полный путь и преобразуем в относительный
|
||
fullFilePath = fullfile(path, file);
|
||
rel = mcuPath.absoluteToRelativePath(fullFilePath);
|
||
|
||
% Устанавливаем значение параметра маски
|
||
param = mask.getParameter(targetParamName);
|
||
param.Value = rel;
|
||
end
|
||
|
||
%% GET PATH STRING - утилиты преобразования путей
|
||
|
||
function absPath = getAbsolutePath(relPath)
|
||
% Преобразование относительного пути в абсолютный
|
||
% relPath - относительный или абсолютный путь
|
||
% Возвращает абсолютный путь в канонической форме
|
||
|
||
% Проверка: абсолютный ли путь уже
|
||
if ispc
|
||
% Для Windows: путь начинается с буквы диска или \\
|
||
isAbsolute = ~isempty(regexp(relPath, '^[a-zA-Z]:[\\/]', 'once')) || startsWith(relPath, '\\');
|
||
else
|
||
% Для Unix: путь начинается с /
|
||
isAbsolute = startsWith(relPath, '/');
|
||
end
|
||
|
||
if isAbsolute
|
||
% Канонизируем абсолютный путь (убираем ./, ../ и т.п.)
|
||
absPath = char(java.io.File(relPath).getCanonicalPath());
|
||
else
|
||
% Строим абсолютный путь относительно текущей директории
|
||
cwd = pwd;
|
||
combined = fullfile(cwd, relPath);
|
||
absPath = char(java.io.File(combined).getCanonicalPath());
|
||
end
|
||
end
|
||
|
||
function rel = absoluteToRelativePath(pathstr)
|
||
% Преобразование абсолютного пути в относительный относительно текущей директории
|
||
% 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
|
||
|
||
% Формируем количество подъемов ".." для выхода из базовой директории
|
||
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 |