Страница 1 из 3

Поиск правильного решения

СообщениеДобавлено: 31.01.2017 13:16:42
igordz
Здравствуйте, помогите найти правильный путь для решения следующующей задачи.
Просканировать все файлы в заданном каталоге (получить полный путь к файлу и дату последнего изменения) и на основе этих данных заполнить двухуровневый TreeView:
1 уровень - дата последнего изменения файла, 2 уровень - пуь и имя файла.
Сделал следующим способом: с помощью FindAllFiles получаю StringList с именами файлов и на его основе заполняю TreeView (получаю дату последнего изменения файла, ищу в TreeView узел первого уровня соответствующий дате, если есть добавляю дочерний - путь к файлу если нет, создаю узел с датой и добавляю дочерний с именем файла).
Все работает, но проблемой оказалось реализовать сортировку по дате последнего доступа. После безрезультатных попыток сортировки TreeView было принято решение построения TreeView на основе уже отсортированных данных но и тут зашел в тупик.
Есть идея на основе StringList полученого с помощью FindAllFiles построить еще один StringList методом AddObject с данными путь и имя файла и датой последнего доступа и потом его отсортировать, но признаюсь что в работе со списками "плаваю совсем мелко" поэтому и прошу помощи.

Re: Поиск правильного решения

СообщениеДобавлено: 31.01.2017 14:07:16
vitaly_l
igordz писал(а):Есть идея на основе StringList полученого с помощью FindAllFiles построить еще один StringList методом AddObject с данными путь и имя файла и датой последнего доступа и потом его отсортировать

Вначале все Ваши "aDate" положите в tmpList:TStringList; затем запустите tmpList.Sort;, и только потом загружайте отсортированный список в TreeView1. И ещё сам TreeView1 даёт возможность сортировать TreeView1.Items.SortTopLevelNodes();, если ему задать алгоритм.

Re: Поиск правильного решения

СообщениеДобавлено: 31.01.2017 17:26:43
igordz
vitaly_l писал(а):Вначале все Ваши "aDate" положите в tmpList:TStringList; затем запустите tmpList.Sort;, и только потом загружайте отсортированный список в TreeView1


Спасибо vitaly_l, сделал на основе Вашей подсказки
Код: Выделить всё
aFiles:= TStringList.Create;
aFiles:= FindAllFiles(DirectoryEdit1.Directory, '*.*', true);
tmpList:= TStringList.Create;
for I:= 0 to aFiles.Count-1 do tmpList.AddObject(GetChangeDate(aFiles.Strings[i]), TObject(aFiles.Strings[i]));
tmpList.Sort;


Все работает, кроме сортировки, думаю что с помощью TStringList.Sort правильно отсортировать данные типа 01.12.2016, 25.08.2008 (даты) не получится, сортировка производится только по дням (по первым двум цыфрам).Результат сортировки данным способом на рисунке.

Что посоветуете насчет сортировки?

Re: Поиск правильного решения

СообщениеДобавлено: 31.01.2017 17:43:23
vitaly_l
igordz писал(а):с помощью TStringList.Sort правильно отсортировать данные типа 01.12.2016, 25.08.2008 (даты) не получится

Надо даты повернуть обратно: Вначале ГОД, затем МЕСЯЦ, потом ЧИСЛО - иначе любой сортировщик собьётся.
вот этот код:
Код: Выделить всё
Result:=FormatDateTime('dd.mm.yyyy', FileDateToDateTime(FileAge(aFile))); 

замените на
Код: Выделить всё
Result:=FormatDateTime('yyyy.mm.dd', FileDateToDateTime(FileAge(aFile))); 

Re: Поиск правильного решения

СообщениеДобавлено: 31.01.2017 18:11:12
igordz
Огромное спасибо, все получилось !

Re: Поиск правильного решения

СообщениеДобавлено: 31.01.2017 21:54:32
Снег Север
кстати, у всех наследников TStrings можно добавить собственную функцию сортировки

Re: Поиск правильного решения

СообщениеДобавлено: 06.02.2017 20:01:42
vitaly_l
Снег Север писал(а):кстати, у всех наследников TStrings можно добавить собственную функцию сортировки

у TreeView оказывается, есть родная сортировка.
igordz писал(а):Огромное спасибо, все получилось !

не за что.

Я тут наткнулся, на факт, что у TreeView есть своя сортировка, если кому понадобится, она при желании позволяет сортировать как по датам так и по названиям:
Код: Выделить всё
  TreeView1.SortType:=stText;
  TreeView1.AlphaSort; 

Re: Поиск правильного решения

СообщениеДобавлено: 06.02.2017 20:58:53
zub
чето какието сплошь неправильные решения - и даты "развернуть" и сортировать данные а не их представления в дереве.

Re: Поиск правильного решения

СообщениеДобавлено: 06.02.2017 21:20:25
vitaly_l
zub писал(а):даты "развернуть" и сортировать данные а не их представления в дереве

Что в этом плохого? Разворот дат, наименее затратное решение. И сортировка происходит, на самом деле: представления, а не данных, т.к. сами данные вообще даже не подключаются в коде, а лишь выводятся для обозрения.

Re: Поиск правильного решения

СообщениеДобавлено: 06.02.2017 21:33:05
zub
>>Что в этом плохого?
>>наименее затратное решение
Наименее затратное - если только по количеству серого вещества потраченого на обдумывание)) следующей хотелкой будет настройка сортировки. будем вертеть и перегружать?

>>И сортировка происходит, на самом деле: представления, а не данных
Сортируются данные перед загрузкой в контрол.

ТС, не слушай художников, художникам самим еще слушать не переслушать

Re: Поиск правильного решения

СообщениеДобавлено: 06.02.2017 21:38:32
vitaly_l
zub писал(а):Сортируются данные

Данные лежат в виде списка файлов на диске и им пофигу сортировка, соответственно - в дереве их представление.
zub писал(а):чудожникам самим еще слушать не переслушать

Это мы любим, излагайте, мы всё внимательно выслушаем и впитаем как губка, если наше серое вещество решит что информация будет полезна для нашего белого вещества.

Re: Поиск правильного решения

СообщениеДобавлено: 06.02.2017 22:25:40
zub
>>Данные лежат в виде списка файлов на диске и им пофигу сортировка, соответственно - в дереве их представление.
ну это ты загнул. У ТС данные это StringList который на выходе FindAllFiles.


ИМХО:
Я бы делал так:
1 - Нафиг FindAllFiles и StringList. определяем данные которые нам понадобятся и рожаем тип в котором будет полностью описывать файл, чтото типа:
Код: Выделить всё
TMyFileInfo=record
  Path,Name:String;
  CreateTime,ModifyTime:TDateTime;
  Attr:TMyFileAttr;
end;

2 - определяемся как будем организовывать массив TMyFileInfo:
2.1 - статический. сначала посчитать сколько нам понадобится элементов, потом выделить в памяти нужный объем данных и заполнять
2.2 - динамический. тут главное будет организовать обертку над динмассивом, чтоб добавлять элементы не по одному а "небольшими пачками"
2.3 - использовать готовую обертку над 2.2, например GVector из fcl-stl
Мне ближе вариант 2.3

3 - на основе FindFirst\FindNext заполнить массив из 2. Это наши данные, мы их получили и храним.

Далее определяемся с котролом. ХЗ что из себя представляет TreeView, но думаю (уверен) в нем можно организовать овнердрав и привязать внешние данные к узлам. Создаем узлы и привязываем к ним инфу в виде индекса в нашем массиве данных или непосредственно указателя на данные. Овнердрав процедура отображает имя ноды на основе данных взятых по индексу\указателю в соответствии с настройками, процедура сортировки сортирует ноды на основе данных взятых по индексу\указателю на основе настройки способа сортировки. Настройки отображения\сортировки можно менять налету без пересоздания дерева.
Возможно вместо TreeView больше подойдет VirtualTree

Re: Поиск правильного решения

СообщениеДобавлено: 06.02.2017 22:58:25
vitaly_l
zub писал(а):привязываем к ним инфу в виде индекса в нашем массиве данных или непосредственно указателя на данные

Не знаю как ТС, но серо-художественное вещество передаёт замечательно полученную инфу, в бело-художественный отдел. Информация, оказалась ОЧЕНЬ кстати, в смысле актуальной на все 100500, т.к. я сейчас решаю именно эту задачу (дорога ложка к обеду). И хотел было привязывать имена файлов, но предложенная схема нравится больше, т.к. потом, можно будет это использовать как дополнительно-удобный сервис. Художественное спасибо за офигенно полезный ликбез! :roll: Хорошего всем настроения! :wink:

.

Re: Поиск правильного решения

СообщениеДобавлено: 06.02.2017 23:44:21
zub
>>но предложенная схема нравится больше
Ждем тему про непонятный вылет при закрытии и забагованость canclose))

Re: Поиск правильного решения

СообщениеДобавлено: 07.02.2017 06:35:12
sign
zub писал(а):>>Данные лежат в виде списка файлов на диске и им пофигу сортировка, соответственно - в дереве их представление.
Я бы делал так:
1 - Нафиг FindAllFiles и StringList. определяем данные которые нам понадобятся и рожаем тип в котором будет полностью описывать файл, чтото типа:
Код: Выделить всё
TMyFileInfo=record
  Path,Name:String;
  CreateTime,ModifyTime:TDateTime;
  Attr:TMyFileAttr;
end;


Это наши данные, мы их получили и храним.

Возможно вместо TreeView больше подойдет VirtualTree

VT просто напрашивается.
Там и с хранением данных, и с сортировкой, и с внешним видом данных - всё замечательно.