Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Listenelemente bedingt löschen (https://www.delphipraxis.net/141771-listenelemente-bedingt-loeschen.html)

Björn Ole 15. Okt 2009 20:33


Listenelemente bedingt löschen
 
Nabend zusammen,


ich bräuchte mal ein ppar Optimierungsanstöße. Und zwar:

In meiner Anwendung befindet sich eine Liste mit Elementen.
Mit Hilfe einer procedure sollen nun entweder alle oder alle selektierten Elementen gelöscht werden.
Wird jedoch mit einem zu löschenden Element gerade gearbeitet (Thread im Hintergrund),
soll es übersprungen werden, es sei denn, der Benutzer will es trotzdem löschen.

Hier mal mein Ansatz.

Delphi-Quellcode:
procedure DeleteItems(AOnlySelected: boolean);
var
  i: integer;
  bIsBusy: boolean; // true, wenn Item gerade in Benutzung
  bDeleteAllBusy: boolean; // true, wenn der Benutzer Item trotzdem löschen will
  bCanDelete: boolean;
begin
  for i := Items.Count - 1 downto do
  begin
    bIsBusy := IsItemBusy(i){prüft, ob Item gerade vom Thread bearbeitet wird};
    if bIsBusy then
      bDeleteAllBusy := UserWantsToDeleteAllBusyItems{kümmert sich um UserAbfrage};

    if bIsBusy and (not bDeleteAllBusy) then
      Continue; // Item überspringen, da busy und Benutzer nicht löschen will

    bCanDelete := not (AOnlySelected and not Items[i].Selected);
    if bCanDelete then
      Delete(i);
  end;
end;
Mir kommt die Umsetzung von der Logik her viel zu aufgebläht und unschön vor.
Habt ihr einen besseren Weg?

Sehr sinnvoll wäre es zusätzlich noch, wenn die Benutzerabfrage nur einmal erscheinen würde, so nach dem Motto
"Zu löschende Elemente sind in Benutzung. Trotzdem alle (selektierten) löschen? Ja/Nein/Abbrechen"

Meine Birne qualmt allein schon von der Problembeschreibung... :freak:


Dankerli,
Björn

himitsu 15. Okt 2009 21:39

Re: Listenelemente bedingt löschen
 
Hat sich Delphi eigentlich nicht wegen des bDeleteAllBusy beschwert,
welches bei (not bIsBusy) nicht initialisiert wird?

erste Zusammenfassung:
Delphi-Quellcode:
for i := Items.Count - 1 downto 0 do
begin
  if IsItemBusy(i) and not UserWantsToDeleteAllBusyItems then
    Continue;

  bCanDelete := not (AOnlySelected and not Items[i].Selected);
  if bCanDelete then
    Delete(i);
end;
zweite/weitere Zusammenfassung:
Delphi-Quellcode:
var
  i: integer;

begin
  for i := Items.Count - 1 downto 0 do
    if not (IsItemBusy(i) and not UserWantsToDeleteAllBusyItems)
        and not (AOnlySelected and not Items[i].Selected) then
      Delete(i);
end;
und mit der Userabfrage eventuell so :gruebel:
Delphi-Quellcode:
var
  i: integer;
  UWD, CalledUWD: boolean;

  function GetUWD;
  begin
    if not CalledUWD then
    begin
      UWD := UserWantsToDeleteAllBusyItems;
      CalledUWD := true;
    end;
    Result := UWD;
  end;

begin
  UWD := false;
  CalledUWD := false;
  for i := Items.Count - 1 downto 0 do
    if not (IsItemBusy(i) and not GetUWD)
        and not (AOnlySelected and not Items[i].Selected) then
      Delete(i);
end;

jetzt bleibt noch eine Frage: hat sich der himi da irgendwo vertan?


[edit]
OK, ein Fehlerchen in GetUWD war schonmal drinnen :angel2:

Björn Ole 15. Okt 2009 22:31

Re: Listenelemente bedingt löschen
 
Danke für Deine so flotte Antwort.

Zitat:

Zitat von himitsu
Hat sich Delphi eigentlich nicht wegen des bDeleteAllBusy beschwert,
welches bei (not bIsBusy) nicht initialisiert wird?

Ja, aber da bDeleteAllBusy nur gesetzt und ausgelesen wird, wenn bIsBusy = true ist, hab ich darauf erstmal keine Rücksicht genommen.


Es gibt (nur) noch zwei Ungereimtheiten bei deiner Version:

1) Die Userabfrage wird genau andersrum gewertet, d.h. klickt der User auf Ja (= trotzdem entfernen) wird aufgehört, bei Nein wird munter weitergelöscht.
Edit: Beim Klick auf Absenden kam mir der Geistesblitz, UWD := MessageBox({Weiterlöschen Ja/Nein?}) = ID_NO; :thumb:

2) Wenn nur selektierte Einträge gelöscht werden sollen, wird trotzdem über das Löschen von nicht selektierten, jedoch in Arbeit befindlichen Einträgen gefragt.

Ich werd mich selbst auch mal versuchen, muss aber deinen, übrigens sehr viel hübscheren Code, erstmal vollständig verdauen. :stupid:

himitsu 15. Okt 2009 22:53

Re: Listenelemente bedingt löschen
 
Zitat:

Zitat von Björn Ole
Edit: Beim Klick auf Absenden kam mir ...

war bei mir vorhin nicht anders :lol:

und wegen der Ungereimtheiten:
eigentlich/theoretisch sollte sich nichts verändert haben,
gegenüber deinem ursprünglichen Code :gruebel:


Ach ja, normaler Weise wird in Delphi nicht immer ALLES ausgewertet

Delphi-Quellcode:
if a or b then
ist hier z.B. a = true, dann steht das Ergebnis schon fest
und b wird nicht mehr verarbeitet ... also wenn b eine Funktion ist, dann würde sie nicht aufgerufen.


gut, da war och ein Fehler, aber auf beiden Seiten
hab was falsch zusammengesetzt

und wenn ich das jetzt nochmal versuche,
Delphi-Quellcode:
bIsBusy := IsItemBusy(i);
if bIsBusy then
  bDeleteAllBusy := UserWantsToDeleteAllBusyItems;

if bIsBusy and (not bDeleteAllBusy) then
  Continue;

//bCanDelete := not (AOnlySelected and not Items[i].Selected);
//if bCanDelete then
//  Delete(i);
Delphi-Quellcode:
bIsBusy := IsItemBusy(i);
DeleteAllBusy := bIsBusy and UserWantsToDeleteAllBusyItems;

if bIsBusy and (not bDeleteAllBusy) then
  Continue;
Delphi-Quellcode:
bIsBusy := IsItemBusy(i);

if bIsBusy and (not (bIsBusy and UserWantsToDeleteAllBusyItems)) then
  Continue;
Delphi-Quellcode:
bIsBusy := IsItemBusy(i);

if bIsBusy and not (bIsBusy and UserWantsToDeleteAllBusyItems) then
  Continue;
dann kommt auch ein Problem deiner Seits raus
bIsBusy and not bIsBusy kann ja wohl nicht gehn und würde immer FALSE ergeben


[add]
Delphi-Quellcode:
procedure DeleteItems(AOnlySelected: boolean);
var
  i: integer;
  UWD, CalledUWD: boolean;

  function GetUWD;
  begin
    if not CalledUWD then
    begin
      UWD := UserWantsToDeleteAllBusyItems;
      CalledUWD := true;
    end;
    Result := UWD;
  end;

begin
  for i := Items.Count - 1 downto 0 do
  begin
    if (not IsItemBusy(i) or UserWantsToDeleteAllBusyItems)
        and (not AOnlySelected or Items[i].Selected) then
      Delete(i);
  end;
end;
mal sehn, ob ich's jetzt kappiert hab
- nur löschen wenn nicht IsItemBusy oder der User will es doch
- und nur löschen wenn selektiert bzw. AOnlySelected=nein

Björn Ole 16. Okt 2009 02:07

Re: Listenelemente bedingt löschen
 
Ja Du hast recht, jetzt wo ich das so aufgebröselt sehe, fällt mir das auch auf...

Danke für deinen letzten Vorschlag.
Ein Fehlverhalten hat er noch, und zwar wenn ein Item selektiert ist, das gerade nicht bearbeitet wird,
dazu ein nicht selektiertes Item, was bearbeitet wird. Nun ein DeleteItems(true) und es kommt trotzdem eine Abfrage.

Problem lässt sich allerdings leicht beheben, nämlich einfach die beiden if Bedingungen vertauschen:

Delphi-Quellcode:
for i := Items.Count - 1 downto 0 do
  if (not AOnlySelected or Items[i].Selected)
    and (not IsItemBusy(i) or GetUWD) then
    Delete(i);
Jetzt läufts genau so wie ich mir das vorgestellt habe.
Vielen Dank himi! :hello:


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz