Aufgaben für den Worker

Verfasst am: Montag, 08. Nov. 2010 um 22:55

Im letzten Blogpost hatte ich es bereits angekündigt, mit der Version 2.0.0.11 sollten die Aufgaben für den Worker hinzukommen. Und genau das ist bis zum heutigen Tag geschehen. Ich muss zugeben, die neue Version ist diesmal eher etwas für neugierige Tester. Die Aufgaben sind zwar fertig programmiert, aber ihre Einbettung in die Oberfläche muss dringend noch verbessert werden. Ich habe mich aber dafür entschieden, die Version hier trotzdem so zur Verfügung zu stellen, da ich ansonsten mein gewolltes Veröffentlichungsraster nicht einhalten könnte.

Es gibt nun einen Automatismus zum Datenimport von Bildern in die Datenbank, den der Anwender in der Toolbar an und ausschalten kann. Bei aktivem Automatismus werden, nachdem auf ein Verzeichnis mit Bildern geklickt wurde, alle Bilder im Worker als Aufgaben eingestellt. Dieser arbeitet die Aufgaben nach und nach ab, speichert die Bilder also in der Datenbank. Fehlen tut hier noch, das vor dem Einfügen des Bildes überprüft wird, ob dieses sich bereits in der Datenbank befindet: siehe Bugtracker Meldung 101

Als zweite Workeraufgabe habe ich das Löschen von Bildern umgesetzt. In einem Popupmenü über der Bildliste befindet sich der Eintrag zum Löschen. Die Funktion ist sowohl für Dateien auf der Festplatte, als auch für Dateien in der Datenbank möglich. Aber Vorsicht, es erscheint keinerlei Sicherheitsabfrage. Wenn löschen geklickt wird, wird auch gelöscht. Was beim Löschen noch fehlt, ist das die Programmoberfläche anschließend aktualisiert wird. Das gelöschte Bild muss aus der Liste entfernt werden und die darunterliegende Scrollbar angepasst werden: siehe Bugtracker Meldung 102

Fazit: Auch wenn in den letzten Wochen einiges an Software entstanden ist, so bleibt noch eine ganze Menge zu tun.

Der Worker

Verfasst am: Donnerstag, 28. Okt. 2010 um 21:35

Es ist wieder einmal Zeit, das BVASystem zu aktualisieren. Neu hinzugekommen in der Software ist dieses Mal ein System, für welches ich leider keinen sinnvollen deutschen Namen gefunden habe.

Worum geht es?

Die Bilder, die in einer Bildverwaltung archiviert werden sollen, müssen logischerweise irgendwie in das System eingefügt werden. Wer das alte BVASystem kennt, sollte wissen, das dies damals über einen Importdialog gelöst wurde. Während des Importierens war die Anwendung dann für den Anwender nicht weiter bedienbar.  Im neuen System dagegen soll der Import so ablaufen, das der Anwender währenddessen das Programm weiter bedienen kann.

Da ich alles immer möglichst allgemein halte, überlegte ich mir, was in einer Bildverwaltung noch so alles durchgeführt werden muss.   Gedacht habe ich zum Beispiel an das Löschen von Dateien, an das Kopieren von Dateien und natürlich an den In- und Export von Bilddaten. Also habe ich ein System entwickelt, das alle diese Aufgaben erledigen kann.

Es sind noch 9 Aufgaben im Worker

Worker

Der Anwender bekommt von dem System im Hintergrund relativ wenig mit, nur oben rechts in der Ecke kann der Status des Systems abgelesen werden. Relativ einfach ist dort zu erkennen, ob noch Aufgaben abzuarbeiten sind. Sofern Aufgaben vorhanden sind, ist durch eine sinkende Aufgabenanzeige zu erkennen, das das System arbeitet. Will der Anwender die Software beenden, wenn noch Aufgaben im System sind, wird natürlich eine Warnung angezeigt.

Da noch keine richtige Aufgabe für das System programmiert wurde, kann über den Knopf „WorkerTest“ das System mit 2 Testaufgaben bestückt werden. Dieser wird in rund 14 Tagen wieder verschwunden sein, da ich bis dahin richtige Aufgaben für das System umsetzen möchte.

Warum heißt das System nun „Worker“?

Die Funktionsweise des Systems hatte ich mir relativ schnell ausgedacht. Ich wollte etwas schaffen, das Aufgaben im Hintergrund der Anwendung abarbeitet und nur möglichst knapp dem Anwender mitteilt, was es gerade tut. Die Namenswahl war mir eigentlich recht egal. Dies änderte sich, als ich die Beschriftungen für den Dialogteil, der auf dem Bild zu sehen ist, festlegen wollte. Ich brauchte einen kurzen prägnanten Namen, der gut in das Dialogelement passt.

Den in der Informatik bekannten Fachbegriff Thread wollte ich nicht nehmen, da ein Normalanwender damit wohl kaum etwas anfangen kann. „Aufgabenbearbeitungssystem“ war für den kleinen Dialogbereich einfach zu lang. Der deutsche Begriff „Arbeiter“ klang irgendwie blöd. Also fiel meine Wahl auf dem Begriff „Worker“. Aber falls jemand eine bessere Idee hat, wie ich den „Worker“ nennen könnte, so soll er mir dies hier per Kommentar mitteilen. Danke.

Kein Datenträger

Verfasst am: Mittwoch, 20. Okt. 2010 um 22:13

Schon in der Version 1.x des BVASystems ärgerte ich mich über einen Fehler, den ich nicht wirklich nachvollziehen bzw. beheben konnte. Gestern trat dieser dann auch bei der neuen Software auf.

Beim Einlesen des Verzeichnisbaumes wird überprüft, ob sich auf den Laufwerken des Computers Unterverzeichnisse befinden. Auch auf Wechseldatenträgern muss der Versuch gestartet werden, die Unterverzeichnisse einzulesen, da es keine andere Möglichkeit gibt, herrauszufinden ob sich ein Datenträger im Laufwerk befindet. Die Funktion ist seit der ersten Version des BVASystems 2.0 unverändert in der Software enthalten. Gestern zeigte sich ein Fehlerdialog mit der Aufschrift: „Es befindet sich kein Datenträger im Laufwerk. Legen Sie einen Datenträger in Laufwerk … ein.“

Diese Fehlermeldung erschien im BVASystem, wenn sich in einem Laufwerk kein Datenträger befand.

Fehlerdialog: Kein Datenträger

Auf meinem Testrechner machte sich der Fehler durch einen anderen Fehlerdialog bemerkbar. Dort kam es zu einer „Exception Processing Message c0000013“. Ohne die Überschrift hätte ich nicht verstanden, was die Fehlermeldung mir sagen will.

Auf dem Testrechner sah die Fehlermeldung dagegen so aus.

Exception: Kein Datenträger

Ich stellte fest, das die Fehlermeldung aufgetreten war, nachdem ich am Entwicklungsrechner den Kartenleser genutzt hatte, um die Bilder meine Digitalkamera auf den Rechner zu spielen. Nach einem Neustart des Rechners und einer anschließenden Neuübersetzung der Bilddatenbank war der Fehler wieder weg. Da ich meinen Kartenleser gerne weiterbenutzen will, ohne ständig den Rechner neu zu starten, suchte ich weiter.

Durch die weitere Recherche kam ich dann auf die Windowsfunktion „SetErrorMode“. Mit ihr kann eingestellt werden, wie das Betriebssystem auf bestimmte Fehler reagieren soll. Meine Vermutung ist, das der Treiber meines Kartenlesers diesen „ErrorMode“ verstellt hat und daher die Fehlermeldungen angezeigt wurden.

Unterbinden lassen sich die Fehlermeldungen nun ganz einfach dadurch, das der „ErrorMode“ auf SEM_FAILCRITICALERRORS setzt. Die Problemlösung sieht also wie folgt aus:

var OldErrorMode: Integer;
 begin
  OldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
  try
   ReadDirectorys();
  finally
  SetErrorMode(OldErrorMode);
  end;
 end;

Änderungen an der Oberfläche

Verfasst am: Montag, 18. Okt. 2010 um 21:08

Dieses Mal gibt es bereits nach einer Woche schon wieder eine neue Programmversion zum Download. Auch wenn die Änderungen, vom Aufwand her, für die Programmversion 2.0.0.9 relativ gering waren, so fallen sie doch deutlich ins Auge. Denn alle Korrekturen und Erweiterungen betrafen die Programmoberfläche.

Lange habe ich den einen Fehler in der Baumdarstellung vor mir hergeschoben. Aus Bequemlichkeit hatte ich in jedem Level des Baumes die Striche einfach bis zum Ende durchgezeichnet. Nun habe ich mir aber endlich die Zeit genommen und diesen Umstand korrigiert. Die Linien zwischen den Baumknoten sind nun korrekt, wo kein Strich hingehört befindet sich auch keiner mehr.

Das BVASystem 2.0.0.9 hat nun einen Graustufenmodus.

BVASystem im Graustufenmodus

Persönlich schaue ich mir meine Fotos auch gerne mal in Schwarz-Weiß an. Nicht alle, aber einige Bilder gewinnen durch die Umwandlung in Graustufen an Ausdruckskraft. Da liegt es natürlich Nahe, im Bildbetrachter gleich eine Ansicht zu haben, mit der getestet werden kann, wie das Bild, oder die Bilder in Graustufen wirken. Ab der heutigen Version ist diese Funktion nun in der Toolbarleiste unter dem Vorschaubild integriert.

Die dritte Baustelle der Woche betraf die Startparameter des Programmes. Startet man das BVASystem beispielsweise mit: „bvasystem.exe c:\testbilder\test.jpg“, so wird gleich nach dem Programmstart das Verzeichnis „Testbilder“ und dort das Bild „test.jpg“ geöffnet. Diese Funktion benötigt man, wenn man die Dateiendung „jpg“ mit dem BVASystem verknüpfen will. Dann soll nämlich, durch Doppelklick auf eine Bilddatei, dieses Bild auch gleich geöffnet werden. Vom Prinzip her wäre das nun möglich, aber da der Optionsdialog noch fehlt, müsste die Verknüpfung manuell hergestellt werden.

Der gefürchtete Fehlerfall

Verfasst am: Dienstag, 12. Okt. 2010 um 23:04

Eine sehr unangenehme Seite der Softwareentwicklung ist, das es quasi unmöglich ist, ein fehlerfreies Programm zu schreiben. Mit diesem Wissen im Hinterkopf muss man auch daran denken, wie man mit Fehlern umgehen wird. Im BVASystem gibt es zum Beispiel eigentlich ab der ersten Version, die es hier zum Download gab,  eine  Trace-Funktionalität.

Startet man die Anwendung mit dem Parameter „-trace“, werden die einzelnen Funktionsaufrufe, die das Programm ausführt, in eine Datei protokolliert.  Die Trace-Datei „bvatrace.log“ findet man dann im Anwendungsverzeichnis des BVASystems. Im Fehlerfall kann mir diese Datei dann zugeschickt, oder im Bugtracker hochgeladen werden.

Neu in der nächsten Version ist, das es einen aussagekräftigen Dialog gibt, wenn ein unerwarteter Fehlerfall auftritt. In den bisherigen Versionen war es so, das dort der Anwender ein schlichtes „Es ist ein unbekannter Fehler aufgetreten.“ angezeigt bekommen hat. Auch wenn der Anwender mit der Fehlermeldung nicht wirklich etwas anfangen kann, so wird er trotzdem nicht gänzlich ohne Informationen im Regen stehen gelassen. Ab sofort wird der Dialog wie folgt aussehen:

Nullpointer-Exception Dialog

Nullpointer-Exception Dialog

Eigentlich habe ich den Dialog bisher immer mit einer Division durch 0 getestet. Aber extra für Lord-Fake, der die Homepage http://www.nullpointer.at betreibt, hab ich die Testroutine nochmals angepasst. Bitte Fake :-D

Der nächste Meilenstein

Verfasst am: Donnerstag, 07. Okt. 2010 um 21:20

Mit dem heutigen Tag ist wieder ein Meilenstein in der Entwicklung des BVASystems erreicht. Die Version 2.0.0.8 kann, wie immer, unter Download herruntergeladen werden. Vor wenigen Tagen berichtete ich, warum es wichtig ist, eine klare Trennung zwischen Oberfläche und den eigentlichen Daten herzustellen. Diese Trennung ist nun komplett umgesetzt. Der letzte direkte Zugriff der Oberfläche auf die Daten ist entfernt, alles läuft nun, so wie gewünscht, über die Datenschicht.

Gestern abend habe ich weiterhin die Roadmap für die nächsten 3 Entwicklungsetappen abgesteckt. Die nächste Version wird für mich etwas zum verschnaufen sein, denn ich will dort nur Änderungen an der Oberfläche vornehmen. Die Änderungen sollten nicht sonderlich kompliziert werden. Aber wenn sie gemacht sind, stärkt es die Bildbetrachter-Funktionen des BVASystems.

Anschließend kommt wieder etwas komplizierteres, welches ich in 2 Etappen umsetzen möchte. Ich möchte dann ein Modul schaffen, das für alle Änderungen am Datenbestand zuständig sein soll. Das Modul soll als Thread im Hintergrund der Anwendung laufen. Damit ist es zum Beispiel möglich, das während sich der Anwender Bilder anschaut, diese automatisch in der Datenbank aufgenommen werden.  Oder aber das Programm löscht, im Hintergrund, die vom Nutzer markierten Bilder, während er sich schon wieder andere Bilder anschaut.

Nachdem die 3 Etappen erreicht sind, habe ich einen schönen abgeschlossenen Prototypen erreicht, der dann wirklich als Bilddatenbank benützt werden kann.  Vor allem wäre dann der letzte „Testbutton“ aus dem Programm wieder entfernt.

3-Schichten-Modell

Verfasst am: Montag, 04. Okt. 2010 um 21:13

Seit nun knapp einen Monat bin ich am werkeln, damit die nötigen Baumstrukturen für die Verzeichnisse bzw. für die Datenbankrubriken aus einer extra Datenschicht kommen. Aber warum betreibe ich den Aufwand? Warum habe ich den bereits fertigen Baum mit den Verzeichnissen nicht einfach behalten? Und warum habe ich nicht einfach schnell einen zweiten Baum, nach gleichem Vorbild, für die Datenbankfunktionalität geschrieben?

Die Struktur, die ich für die Bilddatenbank BVASystem gewählt habe, ist in der Informatik als 3-Schichten-Achitektur bzw. als 3-Schichten-Modell bekannt. Sie hat den entscheidenden Vorteil, das durch die Aufteilung in Schichten, die Komplexität des Gesamtprogrammes abnimmt. Zum einen wird es damit einfacher das System zu erweitern und ebenfalls wird es dadurch für mich einfacher, wenn ich zu einem späteren Zeitpunkt auf den Quelltext der Bildverwaltung schauen muss, um einen Fehler zu beheben. Außerdem kann ich relativ einfach eine veränderte oder komplett neue Oberfläche für die Datenbank designen, da ich dafür nur die Anwendungsschicht neu gestalten muss.

3-Schichten-Modell des BVASystems

3-Schichten-Modell des BVASystems

Eine Besonderheit beim BVASystem ist, das die Datenschicht aus einer abstrakten Datenschicht und 2 Präzisierungen besteht. Dadurch kann ich die Oberfläche, sowohl für die Dateiansicht, als auch für die Datenbankansicht verwenden. Das Ergebnis ist, das sich die Komplexität der Oberfläche bzw. die der Datenschicht-Präzisierungen wiederrum reduziert.

Fazit: Es lohnt sich also sehr wohl, etwas mehr Zeit in saubere Strukturen zu investieren.

Erste Bildverwaltungsfunktion

Verfasst am: Montag, 27. Sep. 2010 um 21:15

Eine Woche ist mein Urlaub nun schon wieder vorbei und der Arbeitsalltag hat mich wieder eingeholt. Aber eigentlich ist es auch ganz schön so. Jeden Tag unterwegs sein, zwischen Wandern, Shoppen und Spielen, kann schon ziemlich anstrengend sein. Und außerdem geht es mit dem BVASystem ja nur weiter, wenn ich zu Hause bin. :-D

So hab ich nun auch gleich die frohe Botschaft, das aus dem BVASystem nun langsam wieder eine richtige Bildverwaltung wird. Als erste Bildverwaltungsfunktion kann das BVASystem nun die Bilder, die sich in der Datenbank befinden, in einer Baumstruktur darstellen. Vielen Fotografen sollte diese Vorgehensweise bekannt vorkommen. Ich selber habe Jahre lang meine Bilder so auf einer externen Festplatte abgelegt: Ein Ordner fürs Jahr, 12 Unterordner für die Monate und da dann wiederrum bis zu 31 Unterordner für die Tage.

Ok, beim BVASystem es ist noch etwas umständlich, das jedes Bild einzeln in die Datenbank aufgenommen werden muss. Von daher glaube ich nicht, das jemand bereit ist, die Funktion wie sie jetzt ist, groß einzusetzen. Aber dies soll sich in den nächsten Versionen des BVASystems dann ändern. Mit der nächsten Version wird der Verzeichnisbaum dann ebenfalls, wie jetzt der Aufnahmedatumbaum, aus der abstrakten Datenschicht kommen. Anschließend ist es für mich dann die wichtigste Aufgabe, die Bilder möglichst automatisch in die Datenbank aufzunehmen.

Wie leicht man sich zeitlich überschätzen kann.

Verfasst am: Donnerstag, 09. Sep. 2010 um 21:51

Für die Version 2.0.0.6 des BVASystems hatte ich mir vorgenommen, die Baumstruktur mit in die Datenschicht aufzunehmen. Während ich mich jeden Abend daran geschafft habe, das Vorhaben umzusetzen, bemerkte ich, das ich mich zeitlich total verschätzt habe. Für das Ziel ist es notwendig, knapp ein Dutzend Klassen zu erstellen bzw. anzupassen. Da ich mir jetzt angewöhnt habe, rund alle 14 Tage eine aktualisierte BVASystem Version hier in den Blog zu stellen, war schnell klar, das das nicht zu schaffen ist. Vorgestern Abend habe ich dann meine Roadmap überarbeitet und heute eine neue Programmversion hochgeladen.

Screenshot vom BVASystem 2.0.0.6

Screenshot vom BVASystem 2.0.0.6

In der jetzt Online gestellten Version habe ich ein paar Bugs behoben. Außerdem bin ich mit der Entwicklung der Datenschicht soweit, das die Datenschicht aufgefordert werden kann, den jeweiligen Baum zu initialisieren bzw. zu erweitern. Oben in der Toolbar befindet sich ein temporärer Button, mit dem das getestet werden kann. Normalerweise sollte nach Klick des Buttons die unspektakuläre Messagebox „Füge Node „TestItem“ zum Baun hinzu.“ angezeigt werden.

Für die nächsten beiden Versionen ist dann geplant, den Baum nach und nach per Datenschicht aufzubauen. Zuerst den Rubrikenbaum aus der Datenbank und sobald das fertig ist, dann der Dateibaum. Nebenbei werde ich natürlich anfallende Bugs beheben. Ich schätze, das ich damit gut 4 … wahrscheinlich eher 5 Wochen zu tun haben werde, da ich mir die nächste Woche im Urlaub „entwicklungsfrei“ gönne.

Ein globales OnClick() in Delphi

Verfasst am: Donnerstag, 02. Sep. 2010 um 22:12

Gestern abend konnte ich eines von Murpyhs Gesetzen verifizieren, es lautet:  „In jedem kleinen Problem, steckt ein Großes, das gerne heraus möchte.“ Eigentlich wollte ich nur eine kleine Verbesserung an der Slideshow-Funktionalität vornehmen, aber dann entdeckte ich das große Problem, welches mich den ganzen Abend beschäftigte.

Folgendes Verhalten wollte ich bei der Slideshow umsetzen:

  • die Slideshow soll über den Button in der Toolleiste aktivierbar sein
  • ein zweiter Klick auf den Button soll sie wieder deaktivieren
  • und ein Klick auf irgendein anderes Steuerelement soll die Slideshow ebenfalls deaktivieren

Die ersten beiden Punkte sind einfach umzusetzen. Das Problem liegt in dem dritten Punkt. Im alten BVASystem hatte ich die Funktionalität dadurch erreicht, indem ich bei jedem OnClick() Event ein:

procedure TfrmMain.Toolbutton1Click(Sender: TObject);
begin
 if (Slideshow.Aktiv = true) then Slideshow.Aktiv := false;
 ...
end;

eingebaut habe. Das wollte ich dieses mal aber um jeden Preis vermeiden, da die Slideshow sich im neuen Programm im Hauptdialog befindet. Dort wären weit mehr Funktionen zu erweitern, als es im alten Programm in der Vollbildansicht der Fall war.

Gelöst habe ich das Problem schlussendlich mit einem globalen OnClick Ereignis.  In der Komponetensammlung von Delphi befindet sich eine Klasse TApplicationEvents, die einen Eventhandler für OnMessage() besitzt.  Dieses Event wird vor jeder Windowsbotschaft, die die Anwendung empfängt, geworfen. Damit ist es relativ leicht möglich, hier die Botschaft „WM_LBUTTONUP“ abzufangen, die Slideshow gegebenenfalls zu deaktivieren und anschließend die Botschaft an das dementsprechende Steuerelement weiterzuleiten.

Aber Vorsicht Falle. Für den Button, der die Slideshow eh deaktivieren soll, darf entweder die Slideshow nicht im OnMessage() gestoppt werden, oder aber das Event darf den Button nie erreichen. Ich entschied mich für die zweitere Variante:

procedure TfrmMain.ApplicationEventsMessage(var Msg: tagMSG; var Handled: Boolean);
var p:TPoint;
    wc:TWinControl;
    ctrl:TControl;
begin
 case Msg.message of
  WM_LBUTTONUP:begin
   //Aktuelle Mausposition bestimmen
   P.X := Mouse.CursorPos.X;
   P.Y := Mouse.CursorPos.Y;
   //TWinControl bestimmen welches sich an der Mausposition befindet
   wc := FindVCLWindow(P);
   if Assigned(wc) then begin
    //TControl bestimmen welches sich an der Mausposition befinden
    ctrl := wc.ControlAtPos(wc.ScreenToClient((P)), false, false);
    if Assigned(ctrl) then begin
     if ctrl.Name = 'btnSlideshow' then Handled := true;
    end;
   end;
   If SlideShow.Aktiv then SlideShow.Aktiv := false;
  end;
 end;
end;

Ich bestimme also zuerst die Position der Maus auf dem Desktop. Anschließend kann ich mit „FindVCLWindow“ das TWinControl bestimmen, welches sich an der MausPosition befindet. Da die Buttons aber nicht fensterorientierte Steuerelemente sind, werden sie von der Funktion nicht entdeckt. Daher ist als zweiter Schritt ControlAtPos() notwendig. Anschließend muss nur noch überprüft werden, ob das Control der Slideshowbutton ist. Ist er es, wird das Event durch „Handled := true“ aus der Windowsbotschaftenliste gelöscht.

Am Ende muss dann nur noch die Slideshow deaktiviert werden, um das von mir gewünschte Verhalten umzusetzen.