Components for Delphi and C++ Builder.

Перейти в английский форум
Перейти на EhLib.com
Текущее время: 27 апр 2024, 16:25

Часовой пояс: UTC




Начать новую тему Ответить на тему  [ Сообщений: 7 ] 
Автор Сообщение
 Заголовок сообщения: Ошибка в списке букмарков
СообщениеДобавлено: 18 мар 2022, 08:24 
Не в сети

Зарегистрирован: 02 ноя 2012, 13:51
Сообщений: 241
Код внутри ToolCtrlsEh.pas

Код:
function TBMListEh.Find(const Item: TUniBookmarkEh; var Index: Integer): Boolean;
var
  L, H, I, C: Integer;
begin
  if (Compare(Item, FCache) = 0) and (FCacheIndex >= 0) then
  begin
    Index := FCacheIndex;
    Result := FCacheFind;
    Exit;
  end;
  Result := False;
  L := 0;
  H := GetCount - 1;
  if H >= 0 then
  begin
    if Compare(FList[L], Item) > 0 then
      L := 0
    else if Compare(FList[H], Item) < 0 then
      L := H + 1
    else
    begin
      while L <= H do
      begin
        I := (L + H) shr 1;
        C := Compare(FList[I], Item);
        if C < 0 then L := I + 1 else
        begin
          H := I - 1;
          if C = 0 then
          begin
            Result := True;
            L := I;
          end;
        end;
      end;
    end;
  end;
  Index := L;
  FCache := Item;
  FCacheIndex := Index;
  FCacheFind := Result;
end;


Если в списке два букмарка и первый из них совпадает с искомым, то ваш "бинарный поиск" его не найдёт. Поскольку первая ветка не исполнится (Compare = 0), вторая ветка установит L := 2 и после этого мы выйдем из функции ничего не найдя. Рабочий код такой (копипаста из System.Classes фактически)



Код:
L := 0;
  H := GetCount - 1;
  while L <= H do
  begin
    I := (L + H) shr 1;
    C := Compare(FList[I], Item);
    if C < 0 then L := I + 1 else
    begin
      H := I - 1;
      if C = 0 then
      begin
        Result := True;
        L := I;
      end;
    end;
  end;


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Ошибка в списке букмарков
СообщениеДобавлено: 18 мар 2022, 11:17 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1549
Добрый день.

Пришлите, пожалуйста, пример, который воспроизводит проблему.
Согласно логике метода
procedure TBMListEh.AppendBookmark(Item: TUniBookmarkEh);
в BookmarkList нельзя добавить два одинаковых букмарка.

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Ошибка в списке букмарков
СообщениеДобавлено: 18 мар 2022, 14:25 
Не в сети

Зарегистрирован: 02 ноя 2012, 13:51
Сообщений: 241
А я и не говорю о списке из двух одинаковых. Разных. Первый из них совпадает с искомым. Этот код его не найдёт. Пример могу сделать, но оно и так видно.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Ошибка в списке букмарков
СообщениеДобавлено: 18 мар 2022, 15:49 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1549
Добрый день.

На простом Демо проекти ошибку воспроизвести не удается.
Вот пример кода

Код:
  public
    { Public declarations }
    Row0Bookmark: TUniBookmarkEh;
    Row1Bookmark: TUniBookmarkEh;
  end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Row0Bookmark := MemTableEh1.Bookmark;
  DBGridEh1.SelectedRows.CurrentRowSelected := True;
  MemTableEh1.Next;
  DBGridEh1.SelectedRows.CurrentRowSelected := True;
  Row1Bookmark := MemTableEh1.Bookmark;

  DBMemoEh1.Lines.Add('Two rows seleced');
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Idx: Integer;
begin
  if (DBGridEh1.SelectedRows.Find(Row0Bookmark, Idx)) then
    DBMemoEh1.Lines.Add('Row0Bookmark is in Index = ' + Idx.ToString)
  else
    DBMemoEh1.Lines.Add('Row0Bookmark is not found');

  if (DBGridEh1.SelectedRows.Find(Row1Bookmark, Idx)) then
    DBMemoEh1.Lines.Add('Row1Bookmark is in Index = ' + Idx.ToString)
  else
    DBMemoEh1.Lines.Add('Row1Bookmark is not found');
end;


Вложения:
2022-03-17-KeepSelectionOnGridFilter.zip [5.17 KiB]
Скачиваний: 96
sshot-240.png
sshot-240.png [ 24.52 KiB | Просмотров: 1275 ]

_________________
Best regards
EhLib support Team
Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Ошибка в списке букмарков
СообщениеДобавлено: 18 мар 2022, 18:52 
Не в сети

Зарегистрирован: 02 ноя 2012, 13:51
Сообщений: 241
А с FireDac TFDMemTable уже не работает


Вложения:
Project1.zip [91.31 KiB]
Скачиваний: 94
Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Ошибка в списке букмарков
СообщениеДобавлено: 19 мар 2022, 01:00 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1549
Добрый день.

Напишите, пожалуйста, логику вашего тестирование.

В вашем Демо проекте в Button1Click
Row0Bookmark присваивается из MemTableEh1.Bookmark

А по Button2Click запрашиваются данные из грида который привязан FDMemTable1.

Если вы копировали данные в FDMemTable1 из MemTableEh1, то букмарки не копируются.
Букмарки обычно генерируются при создании записи.
В FDMemTable1 будут сгенерированы свои букмарки, в MemTableEh1 свои, по своей внутренней логике каждого Датасета.

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Ошибка в списке букмарков
СообщениеДобавлено: 19 мар 2022, 08:42 
Не в сети

Зарегистрирован: 02 ноя 2012, 13:51
Сообщений: 241
Да. Пример мой неправильный, но я уже установил причину своих затруднений. Вопрос оказался и сложнее и проще. DataSet.CompareBookmark сравнивает закладки в порядке следования в текущем отображении. Если букмарки скажем указывают на строки не попадающие в текущий фильтр, то CompareBookmark у FireDac сравнивает такие строки как идентичные FSourceView.IndexOf вернёт -1. Что нарушает бинарный поиск в данном случае.

Код:
   
    oRow1 := GetRowFromBookmark(Bookmark1, i1, iRS1);
    oRow2 := GetRowFromBookmark(Bookmark2, i2, iRS2);
    if oRow1 = oRow2 then
      Result := 0
    else if not IsRowValid(oRow1, iRS1) or not IsRowValid(oRow2, iRS2) then
      Result := -1
    else begin
      i1 := FSourceView.IndexOf(oRow1, rvDefault, i1);
      i2 := FSourceView.IndexOf(oRow2, rvDefault, i2);
      if i1 < i2 then
        Result := -1
      else if i1 > i2 then
        Result := 1
      else
        Result := 0;
    end;


Надо думать


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 7 ] 

Часовой пояс: UTC


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 23


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB