ListViewGadget leeren und neu befüllen

Anfängerfragen zum Programmieren mit PureBasic.
frankmannb
Beiträge: 47
Registriert: 21.02.2010 13:02

ListViewGadget leeren und neu befüllen

Beitrag von frankmannb »

Hallo Spezialisten,

da ich mich jetzt zunehmend immer mehr an PureBasic erfreue habe ich angefangen ein kleines Programm zu schreiben. Dieses soll einen bestimmten Filmpfad abfragen und den Inhalt in eine festzulegende CSV-Datei speichern. Alternativ soll man zu Backup-Zwecken eine zweite CSV-Datei angeben welche den Inahlt des Filmpfades mit dem Inhalt der CSV-Datei abzugleichen und eventuelle Differenzen auf dem Backup-Medium in einem ListViewGadget sichtbar machen. Mein Problem gliedert sich in zwei Abschnitte.

1. Läßt man das Programm das erste Mal laufen so werden die Differenzen innerhalb des ListViewGadget angezeigt. Drückt man aber erneut auf den Startbutton sind die selben Differenzen im Gadget doppelt vorhanden bzw. so oft wie man auf den Start-Knopf gedrückt hat. MIt ClearGadgetItem habe ich es schon versucht ebenfalls mit dem neu erzeugen des ListViewGadget. Irgendwie werden die Einträge aus dem ersten Druck des Start-Buttons nicht gelöscht.

2. Ich möchte noch zusätzlich die Möglichkeit einbauen die Markierten Differenzen auf das Backup-Medium seiner Wahl zu kopieren. Wie frage ich allerdings das GadgetItem ab ob es markiert ist oder nicht?

so und jetzt der Code des Programmes. Ich hoffe ihr kommt damit klar.
Danke schonmal vorab für eure Hilfe.

Code: Alles auswählen

Global dvd_verzeichnis$
Global dvd_pfad$
Global dvd_size$
Global vorhanden
Global differenz
Global benutzername$ = Space(255)
GetEnvironmentVariable_("USERNAME", @benutzername$, Len(benutzername$))
Procedure.q GetDirectorySize(path.s, recursive = #True)
  PathAddBackslash_(@path)
  Protected dir.l = ExamineDirectory(#PB_Any, path, ""), size.q
  If dir
    While NextDirectoryEntry(dir)
      If DirectoryEntryType(dir) = #PB_DirectoryEntry_File
        size + DirectoryEntrySize(dir)
        Continue
      ElseIf recursive And DirectoryEntryName(dir) <> "." And DirectoryEntryName(dir) <> ".."
        size + GetDirectorySize(path + DirectoryEntryName(dir) + "\", 1)
      EndIf
    Wend
    FinishDirectory(dir)
    ProcedureReturn size
  EndIf
EndProcedure
; ----------------------------Umrechnung Byte in KB,MB,GB---------------------------------------------------------------------

Procedure.s byterechner(byte.q, NbDecimals.l = 2)
  If byte < 1024
    If byte < 0
      ProcedureReturn "0 Byte"
    EndIf
    ProcedureReturn Str(byte) + " Byte"
  ElseIf byte >= 1 << 60
    ProcedureReturn StrD(byte / 1 << 60, NbDecimals) + " EB"
  ElseIf byte >= 1 << 50
    ProcedureReturn StrD(byte / 1 << 50, NbDecimals) + " PB"
  ElseIf byte >= 1 << 40
    ProcedureReturn StrD(byte / 1 << 40, NbDecimals) + " TB"
  ElseIf byte >= 1 << 30
    ProcedureReturn StrD(byte / 1 << 30, NbDecimals) + " GB"
  ElseIf byte >= 1 << 20
    ProcedureReturn StrD(byte / 1 << 20, NbDecimals) + " MB"
  Else
    ProcedureReturn StrD(byte / 1024, NbDecimals) + " KB"
  EndIf
EndProcedure

Structure inhalt
  pfad$
  verzeichnisname$
  dateigroesse$
  datum$
  endung$
  vorhanden$
EndStructure

Global NewList filme.inhalt()
Global NewList filme2.inhalt()

; ---------Rekursive Suche von Dateien mit angegebener Dateiendung------------------------

Procedure RekursiveDateisuche(Eingabepfad.s)

  ;Eingabepfad + "\" ; Backslash wird zum Pfad hinzugefügt
  PathAddBackslash_(@eingabepfad)

  Verzeichnis = ExamineDirectory(#PB_Any, Eingabepfad, "*.*")

  While NextDirectoryEntry(Verzeichnis)

    Verzeichnis_Type.l = DirectoryEntryType(Verzeichnis)
    Verzeichnis_Name.s = DirectoryEntryName(Verzeichnis)
    Verzeichnis_Pfad.s = eingabepfad + verzeichnis_name

    If Verzeichnis_Name = "." Or Verzeichnis_name = ".." Or verzeichnis_name = "PRIVAT"
      Continue
    EndIf

    If Verzeichnis_Type = #PB_DirectoryEntry_File
      If GetExtensionPart(verzeichnis_name) = "mkv" Or GetExtensionPart(verzeichnis_name) = "mpg"
        VerzeichnisDateiSize.s   = byterechner(FileSize(verzeichnis_pfad))
        Verzeichnis_CreateDate.s = FormatDate("%dd.%mm.%yyyy", GetFileDate(Verzeichnis_pfad, #PB_Date_Created))
        AddElement(filme())
        ;filme()\pfad$            = ReplaceString(eingabepfad, "\\", "\")
        filme()\pfad$            = eingabepfad
        filme()\verzeichnisname$ = verzeichnis_name
        filme()\dateigroesse$    = VerzeichnisDateiSize
        filme()\datum$           = verzeichnis_createdate
        filme()\endung$          = GetExtensionPart(verzeichnis_name)
      EndIf
    EndIf

    If Verzeichnis_Type = #PB_DirectoryEntry_Directory
      If verzeichnis_name = "AUDIO_TS"
        dvd_size$                = byterechner(GetDirectorySize(dvd_pfad$))
        Verzeichnis_CreateDate.s = FormatDate("%dd.%mm.%yyyy", GetFileDate(dvd_pfad$, #PB_Date_Created))
        AddElement(filme())
        ;filme()\pfad$            = ReplaceString(eingabepfad, "\\", "\")
        filme()\pfad$            = eingabepfad
        filme()\verzeichnisname$ = dvd_verzeichnis$
        filme()\dateigroesse$    = dvd_size$
        filme()\datum$           = verzeichnis_createdate
        filme()\endung$          = "DVD"
      EndIf

      dvd_verzeichnis$ = verzeichnis_Name
      dvd_pfad$        = verzeichnis_pfad
      RekursiveDateisuche(eingabepfad + verzeichnis_Name)
    EndIf
  Wend
  FinishDirectory(verzeichnis)
EndProcedure

; ----------------------------Programmaufruf------------------------------------

NewList pfadliste$()
If OpenWindow(0, 200, 200, 400, 500, "Meine Filme", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
  ; ButtonGadget(1,ButtonID,links,oben,breite,höhe)
  ButtonGadget(1, 200, 130, 100, 25, "ABBRUCH")
  ButtonGadget(2, 100, 130, 100, 25, "START")
  StringGadget(3, 50, 20, 220, 20, "Pfad zu den Filmen...")
  ButtonGadget(4, 270, 20, 30, 20, "...")
  StringGadget(5, 50, 50, 220, 20, "Filmdatei speichern unter ...")
  ButtonGadget(6, 270, 50, 30, 20, "...")
  OptionGadget(7, 70, 80, 120, 20, "Datei auslesen")
  OptionGadget(8, 70, 100, 120, 20, "Dateien vergleichen")
  ListViewGadget(9, 10, 220, 370, 230, #PB_ListView_ClickSelect | #PB_ListView_MultiSelect)
  ProgressBarGadget(11,  10, 165, 370,  30, 0, 1000, #PB_ProgressBar_Smooth)
  TextGadget(12, 50, 200, 300, 20, "Mehrfachselektion durch STRG- oder SHIFTTASTE möglich")

  SetGadgetState(7, 1)
  SetGadgetState(11, 0)
  auswahl$ = "schreiben"
  Repeat

    ; ABBRUCHBEDINGUNG
    If EventID = #PB_Event_Gadget

      If EventGadget() = 1
        quit = 1
      EndIf

      ; START DES PROGRAMMS bei Auswahl der Option Datei schreiben
      If EventGadget() = 2
        ClearGadgetItems(9)
        ClearList(filme())
        ClearList(filme2())
        If auswahl$ = "schreiben"
          If OpenFile(0, file$)
            ForEach pfadliste$()
              RekursiveDateisuche(pfadliste$())
            Next
            WriteStringN(0, "Dateipfad" + Chr(59) + "Verzeichnisname" + Chr(59) + "Dateiendung" + Chr(59) + "Größe" + Chr(59) + "Datum")
            ForEach filme()
              WriteStringN(0, filme()\pfad$ + Chr(59) + filme()\verzeichnisname$ + Chr(59) + filme()\endung$ + Chr(59) + filme()\dateigroesse$ + Chr(59) + filme()\datum$)
            Next
            CloseFile(0)
            result = MessageRequester("Ende", "Auslesen der Filme erfolgreich beendet, soll das Programm geschlossen werden ", #PB_MessageRequester_YesNo)
            If result = #PB_MessageRequester_Yes
              quit = 1
            EndIf

          Else
            MessageRequester("FEHLER", "Ein- oder Ausgabedatei fehlt", 0)
          EndIf
        ElseIf auswahl$ = "vergleichen"
          If ReadFile(0, file$)

            ForEach pfadliste$()
              RekursiveDateisuche(pfadliste$())
            Next

            While Eof(0) = 0
              zeile$   = ReadString(0)
              zaehler2 = zaehler2 + 1
              If zaehler2 > 1
                AddElement(filme2())
                filme2()\pfad$            = StringField(zeile$, 1, ";")
                filme2()\verzeichnisname$ = StringField(zeile$, 2, ";")
                filme2()\endung$          = StringField(zeile$, 3, ";")
                filme2()\dateigroesse$    = StringField(zeile$, 4, ";")
                filme2()\datum$           = StringField(zeile$, 5, ";")
              EndIf
            Wend

            ForEach filme()
              If filme()\vorhanden$ <> "1"
                film$ = filme()\verzeichnisname$ + filme()\endung$
                ForEach filme2()
                  If filme2()\vorhanden$ <> "1"
                    film2$ = filme2()\verzeichnisname$ + filme2()\endung$
                    If film2$ = film$
                      filme()\vorhanden$  = "1"
                      filme2()\vorhanden$ = "1"
                      Break
                    EndIf
                  EndIf
                Next
              EndIf
              If filme()\vorhanden$ <> "1"
                z = z + 1
                If z = 1
                  ButtonGadget(10, 50, 465, 150, 25, "Selektierte Filme kopieren...")
                  ButtonGadget(13, 200, 465, 150, 25, "Kopiervorgang abbrechen")
                EndIf
                AddGadgetItem(9, -1, filme()\verzeichnisname$)
                differenz = 1
              EndIf
            Next
            CloseFile(0)
            MessageRequester("Vergleich", "Vergleich der Filme beendet!")
          EndIf
        EndIf
      EndIf
      ; Pfad zu den Filmen
      If EventGadget() = 4
        ClearGadgetItems(9)
        ClearList(filme())
        ClearList(filme2())
        Repeat
          string_gadget_text$ = PathRequester("Bitte Pfad zu den Filmen wählen", "" )
          abfrage             = #PB_MessageRequester_No
          If string_gadget_text$ <> ""
            SetGadgetText(3, string_gadget_text$)
            AddElement(pfadliste$())
            pfadliste$() = string_gadget_text$
            abfrage      = MessageRequester("Pfadauswahl", "Weiteren Filmpfad wählen?", #PB_MessageRequester_YesNo)
          EndIf
        Until abfrage = #PB_MessageRequester_No
      EndIf

      If EventGadget() = 6
        ausgabedatei$ = "c:\meine_filme_" + benutzername$ + ".csv"
        If auswahl$ = "schreiben"
          File$ = SaveFileRequester("Ausgabedatei waehlen", ausgabedatei$, "CSV-Exceldatei (*.csv)|*.csv", 0)
        Else
          file$ = OpenFileRequester("Filmdatei zum vergleichen...", ausgabedatei$, "CSV-Exceldatei (*.csv)|*.csv", 0)
        EndIf
        If file$ <> ""
          SetGadgetText(5, file$)
        EndIf
      EndIf

      If EventGadget() = 7
        SetGadgetText(3, "Pfad zu den Filmen...")
        SetGadgetText(5, "Filmdatei speichern unter...")
        auswahl$ = "schreiben"
      EndIf

      If EventGadget() = 8
        SetGadgetText(3, "Pfad zu den Filmen...")
        SetGadgetText(5, "Datei zum vergleichen wählen")
        auswahl$ = "vergleichen"
      EndIf

      If EventGadget() = 10

        For i = 0 To CountGadgetItems(9) - 1
          If GetGadgetItemState(9, i) & #PB_ListIcon_Selected
            fs_zaehler = fs_zaehler + 1
            If fs_zaehler = 1
              backuppfad$ = PathRequester("Bitte Speicherpfad auswählen", "" )
            EndIf
          EndIf
        Next i
        update = 1000 / fs_zaehler
        If backuppfad$ <> ""
          For i = 0 To CountGadgetItems(9) - 1
            If GetGadgetItemState(9, i) & #PB_ListIcon_Selected
              fs = fs + update
              SetGadgetState(11, fs)
              ForEach filme()
                If filme()\verzeichnisname$ = GetGadgetItemText(9, i)
                  If filme()\endung$ <> "DVD"
                    backupdatei$ = filme()\pfad$ + filme()\verzeichnisname$
                    CopyFile(backupdatei$, backuppfad$ + filme()\verzeichnisname$)
                  Else
                    backupdatei$ = filme()\pfad$
                    CopyDirectory(backupdatei$, backuppfad$, "", #PB_FileSystem_Recursive)
                  EndIf
                EndIf
                If EventGadget() = 13
                  Break(3)
                EndIf
              Next
            EndIf
          Next i
          MessageRequester("Ende", "Kopieren erfolgreich beendet!", #PB_MessageRequester_Ok)
        EndIf
        quit = 1
      EndIf
    EndIf ; If Event-ID

    EventID = WaitWindowEvent()
    If EventID = #PB_Event_CloseWindow
      Quit = 1
    EndIf
  Until quit = 1
EndIf
Zuletzt geändert von frankmannb am 14.04.2010 14:14, insgesamt 3-mal geändert.
Benutzeravatar
man-in-black
Beiträge: 362
Registriert: 21.08.2006 17:39

Re: ListViewGadget leeren und neu befüllen

Beitrag von man-in-black »

selben Differenzen im Gadget doppelt vorhanden bzw. so oft wie man auf den Start-Knopf gedrückt hat

wieso wohl?^^
wo holst du dir denn die daten her? aus der liste!
hast du sie gelöscht? nein! :allright:
(hab alles, kann alles, weiß alles!!^^)

Bild
frankmannb
Beiträge: 47
Registriert: 21.02.2010 13:02

Re: ListViewGadget leeren und neu befüllen

Beitrag von frankmannb »

leider hilft mir dein Kommentar nich wirklich weiter. Ja klar ich erstelle durch die ForEach-Schleife die relevanten Differenzen und gebe diese in einem listviewgadget aus. Ich würde nicht fragen wenn ich die Lösung kennen würde. Daher wäre es hilfreich zu wissen wie ich Sie lösche!
man-in-black hat geschrieben:
selben Differenzen im Gadget doppelt vorhanden bzw. so oft wie man auf den Start-Knopf gedrückt hat

wieso wohl?^^
wo holst du dir denn die daten her? aus der liste!
hast du sie gelöscht? nein! :allright:
Benutzeravatar
man-in-black
Beiträge: 362
Registriert: 21.08.2006 17:39

Re: ListViewGadget leeren und neu befüllen

Beitrag von man-in-black »

naja, du hast dir doch listen erstellt:

Code: Alles auswählen

Global NewList filme.inhalt()
Global NewList filme2.inhalt()
und diese verglichen und in einem gadget ausgegeben.

bevor du aber erneut alles reinschreibst, musst du beide listen (filme/filme2) löschen, sowie den gadgetinhalt.

Code: Alles auswählen

ClearGadgetItems(#Gadget) ;für den gadgetinhalt
ClearList(LinkedList()) ;für die beiden Listen
(hab alles, kann alles, weiß alles!!^^)

Bild
frankmannb
Beiträge: 47
Registriert: 21.02.2010 13:02

Re: ListViewGadget leeren und neu befüllen

Beitrag von frankmannb »

@men-in-black

Super :-) ich danke dir. Der Denkantoss hatte mir gefehlt. Die Gadget hatte ich schon im Vorfeld probiert zu löschen was auch geklappt hatte. Die Listen allerdings hatte ich vergessen.

somit bleibt nur noch punkt 2 offen. Kannst du mir hierfür auch noch einen tipp geben.

man-in-black hat geschrieben:naja, du hast dir doch listen erstellt:

Code: Alles auswählen

Global NewList filme.inhalt()
Global NewList filme2.inhalt()
und diese verglichen und in einem gadget ausgegeben.

bevor du aber erneut alles reinschreibst, musst du beide listen (filme/filme2) löschen, sowie den gadgetinhalt.

Code: Alles auswählen

ClearGadgetItems(#Gadget) ;für den gadgetinhalt
ClearList(LinkedList()) ;für die beiden Listen
Benutzeravatar
man-in-black
Beiträge: 362
Registriert: 21.08.2006 17:39

Re: ListViewGadget leeren und neu befüllen

Beitrag von man-in-black »

guck dir mal diesen befehl in der hilfe an: GetGadgetItemState(#Gadget, Eintrag)
(hab alles, kann alles, weiß alles!!^^)

Bild
frankmannb
Beiträge: 47
Registriert: 21.02.2010 13:02

Re: ListViewGadget leeren und neu befüllen

Beitrag von frankmannb »

Hallo Leute,

die Programmerstellung geht weiter und schwupps stehe ich vor einem neuen Problem.

Starte ich das Programm mit der Option (dateien vergleichen) und fange nach Selektion der zu kopierenden Filme an diese an den gewünschten Pfad zu kopieren, ist es nicht mehr möglich das Programm auf normalem Wege zu verlassen. Ich hatte hierfür den Button "Kopiervorgang abbrechen" vorgesehen der nach Betätigung die betroffenen Schleifen verlassen soll. Leider ist aber ein Eingriff in das laufende PRogramm nicht möglich (Die Sanduhr/Eieruhr wird angezeigt und dann steht nach kurzer Zeit im Fenster keine Rückmeldung). Das Programm läuft auch sauber weiter aber ein Abbruch in der Abarbeitung ist nicht möglich.

Kann mir jemand von euch verratne, wie ich das am besten realisieren kann?
Wie immer mit bestem Dank im Vorraus.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: ListViewGadget leeren und neu befüllen

Beitrag von ts-soft »

Erstelle einen Timer und rufe von dort die Procedure zum kopieren auf, diese kopiert
immer nur einen kleinen teil und merkt sich das zuletzt kopierte in einer statischen
variable. Oder Du nimmst eine linklist, arbeitest z.B. in der TimerProc nur 5 ab, die Du
gleich dort löscht, bis die Liste Leer ist. Der Button, der dieses Kopieren in gange setzt
muß natürlich disabled werden, bis der Durchgang fertig ist.
Zuletzt geändert von ts-soft am 14.04.2010 16:17, insgesamt 1-mal geändert.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
frankmannb
Beiträge: 47
Registriert: 21.02.2010 13:02

Re: ListViewGadget leeren und neu befüllen

Beitrag von frankmannb »

ts-soft hat geschrieben:Erstelle einen Timer und rufe von dort die Procedure zum kopieren auf, diese kopiert
immer nur einen kleinen teil und merkt sich das zuletzt kopierte in einer statischen
variable. Oder Du nimmst eine linklist, arbeitest z.B. in der TimerProc nur 5 ab, die Du
gleich dort löscht, bis die Liste Leer ist. Der Button, der dieses Kopieren in gange setzt
muß natürlich disabled werden, bis der Durchgang fertig ist.
mmhh leider verstehe ich nicht wie du das meinst. Kannst du hierfür ein kleines Beispiel liefern?
Ist es nicht möglich das Programm sofort zu beenden?
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: ListViewGadget leeren und neu befüllen

Beitrag von NicTheQuick »

Wichtig ist im Grunde, dass du während dem Kopieren keine Events verschluckst. Das heißt du musst auch während deiner Kopierschleife weiterhin 'WaitWindowEvent()' oder Konsorten aufrufen, damit ankommende Events abgearbeitet werden können. Tust du das nicht, sagt Windows "(Keine Rückmeldung)". Du kannst es deshalb so machen wir Kaeru es vorgeschlagen hat, also immer Stückweise kopieren und zwischendurch nochmal in die Eventschleife wechseln oder du machst es so, wie ich es machen würde, nämlich den kompletten Kopiervorgang in einem Thread abhandeln. Aber bevor du dich mit Threads rumschlägst, probiere erstmal die andere Methode. :allright:
Antworten