Vorbereitete Datenverzeichnise
-
- Beiträge: 200
- Registriert: So 11. Jul 2010, 18:39
- OS, Lazarus, FPC: Linux
- CPU-Target: 64 Bit
- Wohnort: Wien
- Kontaktdaten:
Vorbereitete Datenverzeichnise
Es ist ja bei Betriebssystemen bzw. Oberflächen schon lange üblich, vorbereitete Verzeichnisse für gewisse Großgruppen von Daten einzurichten, wie z.B. Dokumente, Bilder und Videos. Hat Lazarus bzw. FPC Funktionen, die diese Verzeichnisse abfragen? Ich meine damit, dass, wenn ein Windoof-Kompilat diese Funktion benutzt, wird auf das passende Verzeichnis für Windoof verwiesen; das gleiche bei Mac, KDE, Gnome usw. usf.
Also so ähnich wie GetUserDir, nur halt etwas spezialiserter für diese Großǵruppen.
Gibt's sowas?
Also so ähnich wie GetUserDir, nur halt etwas spezialiserter für diese Großǵruppen.
Gibt's sowas?
Ceterum censeo computatores per Pascal docendos esse.
-
- Beiträge: 2120
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Vorbereitete Datenverzeichnise
Unter windows kannst du Umgebungsvariablen lesen. Z.B. um an den AppData ordner zu kommen:
Unter Unix ist es ganz einfach, ~ ist der homeordner. Also ~/Documents entspricht /home/username/documents, bzw. wo auch immer das userverzeichnis liegt (das kann man ja beliebig wählen)
Eine Plattformübergreifende Funktion gibt es soweit ich weiß nicht. Vor allem aber weil bei Linux die Ordnervergebung von der Distribution abbhängt und es kein "allgemeingültes" standardschema gibt (ganz dumm, ein OpenSuse ohne grafisches UI hat weder Documents noch Downloads oder sonst irgendein standard user directory)
Code: Alles auswählen
GetEnvironmentVariable('APPDATA')
Eine Plattformübergreifende Funktion gibt es soweit ich weiß nicht. Vor allem aber weil bei Linux die Ordnervergebung von der Distribution abbhängt und es kein "allgemeingültes" standardschema gibt (ganz dumm, ein OpenSuse ohne grafisches UI hat weder Documents noch Downloads oder sonst irgendein standard user directory)
Re: Vorbereitete Datenverzeichnise
Ist mir nicht bekannt, dass es so etwas fixfertig gibt.
Vllt. hilft das:
http://wiki.lazarus.freepascal.org/Wind ... .2C_etc.29
https://www.freedesktop.org/wiki/Softwa ... user-dirs/
Bei mir auf OpenSUSE sieht /home/theo/.config/user-dirs.dirs z.B. so aus
Vllt. hilft das:
http://wiki.lazarus.freepascal.org/Wind ... .2C_etc.29
https://www.freedesktop.org/wiki/Softwa ... user-dirs/
Bei mir auf OpenSUSE sieht /home/theo/.config/user-dirs.dirs z.B. so aus
Code: Alles auswählen
# This file is written by xdg-user-dirs-update
# If you want to change or add directories, just edit the line you're
# interested in. All local changes will be retained on the next run
# Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped
# homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an
# absolute path. No other format is supported.
#
XDG_DESKTOP_DIR="$HOME/Schreibtisch"
XDG_DOWNLOAD_DIR="$HOME/Downloads"
XDG_TEMPLATES_DIR="$HOME/Vorlagen"
XDG_PUBLICSHARE_DIR="$HOME/Öffentlich"
XDG_DOCUMENTS_DIR="$HOME/Dokumente"
XDG_MUSIC_DIR="$HOME/Musik"
XDG_PICTURES_DIR="$HOME/Bilder"
XDG_VIDEOS_DIR="$HOME/Videos"
-
- Beiträge: 200
- Registriert: So 11. Jul 2010, 18:39
- OS, Lazarus, FPC: Linux
- CPU-Target: 64 Bit
- Wohnort: Wien
- Kontaktdaten:
Re: Vorbereitete Datenverzeichnise
Tja. Schade. Danke für die Auskunft in jedem Fall. Ununteressant ist das ja nicht. Man müsste es also selbst machen, mit einer Ḱaskade von Compilerschlatern, könnte man es hinkriegen. Und der Default ist halt das Userverzeichnis. Was solls. Danke nochmal.
Ceterum censeo computatores per Pascal docendos esse.
-
- Beiträge: 2120
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Vorbereitete Datenverzeichnise
Es geht eigentlich, du brauchst eigentlich nur einmal Compilerswitches:diogenes hat geschrieben:Tja. Schade. Danke für die Auskunft in jedem Fall. Ununteressant ist das ja nicht. Man müsste es also selbst machen, mit einer Ḱaskade von Compilerschlatern, könnte man es hinkriegen. Und der Default ist halt das Userverzeichnis. Was solls. Danke nochmal.
Code: Alles auswählen
type
TUserDirectories = record
Home,
Documents,
... : String;
end;
var UserDirectories: TUserDirectories ;
...
{$IF Defined(Windows)}
function DefaultDirectories: TUserDirectories;
begin
Result.Home = ... // keine ahnung auswendig
end;
{$ELSEIF Defined(Linux)}
function DefaultDirectories: TUserDirectories;
begin
Result.Home = '~';
// Lese xdg file
end;
{$ELSEIF Defined(Darwin)}
function DefaultDirectories: TUserDirectories;
begin
Result.Home = '~';
// Rest hardcoden
end;
{$ENDIF}
initialization
UserDirectories := DefaultDirectories;
end;
Du kannst den Windows Linux und Mac Part auch in separate .inc files schreiben und die dann über {$I} (glaube ich) includen. Dann ist alles schön getrennt was das editieren einfacher macht, und in deiner Hauptdatei ist nur Betriebsystemabhängiger Code
-
- Beiträge: 200
- Registriert: So 11. Jul 2010, 18:39
- OS, Lazarus, FPC: Linux
- CPU-Target: 64 Bit
- Wohnort: Wien
- Kontaktdaten:
Re: Vorbereitete Datenverzeichnise
Ja, so ähnlich hab ich mir das vorgestellt. Die Idee mit dem Record ist gut, ich hätte nicht daran gedacht 

Ceterum censeo computatores per Pascal docendos esse.
-
- Beiträge: 200
- Registriert: So 11. Jul 2010, 18:39
- OS, Lazarus, FPC: Linux
- CPU-Target: 64 Bit
- Wohnort: Wien
- Kontaktdaten:
Re: Vorbereitete Datenverzeichnise
Noch eine Frage zu den xdg-Dateien: wie liest man die? muss man die selbst parsen?
Ich hätte die Idee, die Datei in eine Stringliste zu lesen, dann alle Zeilen, die mit '#" oder leer sind, beginnen, zu entfernen, und dann mit '=' als Separator zwweischen Key und Value auszulesen. Geht das einfacher?
Ich hätte die Idee, die Datei in eine Stringliste zu lesen, dann alle Zeilen, die mit '#" oder leer sind, beginnen, zu entfernen, und dann mit '=' als Separator zwweischen Key und Value auszulesen. Geht das einfacher?
Ceterum censeo computatores per Pascal docendos esse.
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Vorbereitete Datenverzeichnise
Nein; du musst zusätzlich alle Umgebungsvariablen (z.B. $HOME) ersetzen.diogenes hat geschrieben:Ich hätte die Idee, die Datei in eine Stringliste zu lesen, dann alle Zeilen, die mit '#" oder leer sind, beginnen, zu entfernen, und dann mit '=' als Separator zwweischen Key und Value auszulesen. Geht das einfacher?
Alternativ rufst du das Programm xdg-user-dirs auf:
Code: Alles auswählen
simon@debian:~/.config$ xdg-user-dir DESKTOP
/home/simon/Schreibtisch
Code: Alles auswählen
uses Process;
var
DirectoryName: String;
begin
RunCommand('xdg-user-dir', ['DESKTOP'], DirectoryName);
WriteLn(DirecotryName);
end;
Code: Alles auswählen
DESKTOP
DOWNLOAD
TEMPLATES
PUBLICSHARE
DOCUMENTS
MUSIC
PICTURES
VIDEOS
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
-
- Beiträge: 200
- Registriert: So 11. Jul 2010, 18:39
- OS, Lazarus, FPC: Linux
- CPU-Target: 64 Bit
- Wohnort: Wien
- Kontaktdaten:
Re: Vorbereitete Datenverzeichnise
Aha. Kann ich annehmen, dass das programm zur Verfügung ist, wenn die Datei exisitert?
Ceterum censeo computatores per Pascal docendos esse.
-
- Beiträge: 2120
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Vorbereitete Datenverzeichnise
Ja, die datei ist ja von xdg erzeugt daher wäre es recht unwahrscheinlich das die datei ohne XDG exsistert. Bzw. wenn die datei ohne XDG existieren würde kannst du auch nicht sicher sein ob sie korrekt ist.diogenes hat geschrieben:Aha. Kann ich annehmen, dass das programm zur Verfügung ist, wenn die Datei exisitert?
-
- Beiträge: 200
- Registriert: So 11. Jul 2010, 18:39
- OS, Lazarus, FPC: Linux
- CPU-Target: 64 Bit
- Wohnort: Wien
- Kontaktdaten:
Re: Vorbereitete Datenverzeichnise
Danke. Ich werde mien vorläufige Ergebnis hier posten 

Ceterum censeo computatores per Pascal docendos esse.
-
- Beiträge: 200
- Registriert: So 11. Jul 2010, 18:39
- OS, Lazarus, FPC: Linux
- CPU-Target: 64 Bit
- Wohnort: Wien
- Kontaktdaten:
Re: Vorbereitete Datenverzeichnise
Soweit mein bisheriges Ergebnis. ich hab' das absichtich auf Erweiterbarkeit gebaut

Code: Alles auswählen
unit Zystem;
{************************************
* extension of System and SysUtils *
************************************
Copyright (C) 2018 By Robert H. Mangl
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.}
{$mode objfpc}{$H+}
interface
uses SysUtils;
{**********************
* exception handling *
**********************}
type
EZett = class( Exception);
EZettClass = class of EZett;
{******************************
* preperaed user directories *
******************************}
type
TDefaultDires = record
Home: string;
Desktop: string;
Download: string;
Templates: string;
PublicShare: string;
Documents: string;
Pictures: string;
Music: string;
Videos: string;
end;
var
DefaultDires: TDefaultDires;
{*****************
* miscellaneous *
*****************}
function Voided( Ptr: Pointer): Boolean; inline;
{returns True if the Ptr points to NIL -- it's ust a "not
Assigned( Ptr)"}
procedure NoOperation; inline;
{does nothiong. can clarify if-then-else structures
greatly}
function AssertDire( const Dire: string; DoForce: Boolean= True): string;
{assuming the passed Path is a directory path, this
function corrects separators and adds one if it is
missing at the end. this makes sure that you simply can
add a file name to create a complete locator. by default,
it will also force the directory's existence. you can
switch off this}
implementation
uses Classes, Process, StrUtils;
procedure SetupDefaultDires( var Dires: TDefaultDires); forward;
{set up Dires sith the GUI's default directories.
tries to be platform independent. where the
platform-specific directories cannot retrieved, the
usr's home direcotry is returned}
function GetHomeDefault: TDefaultDires; forward;
{return a user directories record that has the user's
home directoy in every field}
function AssertDire( const Dire: string; DoForce: Boolean): string;
begin
Result := Dire;
DoDirSeparators( Result);
if not AnsiEndsStr( DirectorySeparator, Result)
then Result := Result + DirectorySeparator;
while Result[ Length( Result) - 1] = DirectorySeparator do
Delete( Result, Length( Result) - 1, 1);
if DoForce
then ForceDirectories( Result)
end;
function GetHomeDefault: TDefaultDires;
begin
with Result do begin
Home := AssertDire( GetUserDir, False);
Desktop := Home;
Download := Home;
Templates := Home;
PublicShare := Home;
Documents := Home;
Pictures := Home;
Music := Home;
Videos := Home;
end
end;
{$IF DEFINED(LINUX)}
procedure SetupDefaultDires( var Dires: TDefaultDires);
var
HomeDire: string;
procedure ReadFromUserDirsDirs;
function ValueOf( Key: string): string;
begin
RunCommand( 'xdg-user-dir', [Key], Result);
if Result = ''
then Result := HomeDire
else if AnsiEndsStr( LineEnding, Result)
then Result := LeftStr( Result,
Length( Result) - Length( LineEnding))
end;
begin
with Dires do begin
Home := HomeDire;
Desktop := ValueOf( 'DESKTOP');
Download := ValueOf( 'DOWNLOAD');
Templates := ValueOf( 'TEMPLATES');
PublicShare := ValueOf( 'PUBLICSHARE');
Documents := ValueOf( 'DOCUMENTS');
Pictures := ValueOf( 'PICTURES');
Music := ValueOf( 'MUSIC');
Videos := ValueOf( 'VIDEOS')
end
end;
begin
HomeDire := AssertDire( GetUserDir, False);
if FileExists( HomeDire + '.config/user-dirs.dirs')
then ReadFromUserDirsDirs
end;
{$ELSEIF DEFINED(WINDOWS)}
procedure SetupDefaultDires( var Dires: TDefaultDires);
begin
end;
{$ELSE}
procedure SetupDefaultDires( var Dires: TDefaultDires);
begin
end;
{$ENDIF}
procedure NoOperation; begin end;
function Voided(Ptr: Pointer): Boolean;
begin
Result := not Assigned( Ptr)
end;
initialization
SetupDefaultDires( DefaultDires)
end.
Ceterum censeo computatores per Pascal docendos esse.
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Vorbereitete Datenverzeichnise
Hallo diogenes,
vielen Dank, dass du deine Unit hier veröffentlichst. Würde es dir etwas ausmachen, diese Unit unter der LGPL mit Linking Exception wie die LCL zu veröffentlichen? Dann könnte man das umbauen und in Free Pascal oder Lazarus ausliefern. Andernfalls wird jede Software, die deine Unit verwendet automatisch zu GPL-Software. Falls du das so bedacht und gewollt hast, ist das natürlich auch in Ordnung.
Zur Vollständigkeit: Für MS Office kann man die Vorlagenverzeichnisse (User und Public) aus der Registry auslesen: Verwalten von Vorlagen in Office 2007-Programmen Man müsste es wohl aber für alle Versionen abfragen.
vielen Dank, dass du deine Unit hier veröffentlichst. Würde es dir etwas ausmachen, diese Unit unter der LGPL mit Linking Exception wie die LCL zu veröffentlichen? Dann könnte man das umbauen und in Free Pascal oder Lazarus ausliefern. Andernfalls wird jede Software, die deine Unit verwendet automatisch zu GPL-Software. Falls du das so bedacht und gewollt hast, ist das natürlich auch in Ordnung.
Zur Vollständigkeit: Für MS Office kann man die Vorlagenverzeichnisse (User und Public) aus der Registry auslesen: Verwalten von Vorlagen in Office 2007-Programmen Man müsste es wohl aber für alle Versionen abfragen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Re: Vorbereitete Datenverzeichnise
Hmmm... Also wenn ich zu entscheiden hätte, die Unit in Lazarus oder FPC aufzunehmen, würde ich sie ablehen. Ich will nicht sagen, dass sie schlecht ist, aber ich fände für diese konkrete Implementierung keine Anwendung. Der Hauptkritikpunkt ist: Warum packst du die einzelnen Verzeichnisse in einen Record? Denn das bedeutet, dass ich, wenn ich z.B. nur das Documents-Directory brauche, auch das Music-, Pictures-, Videos- etc. Directory in meinem Programm mitschleppen muss.
Ich hätte eine Aufzählung TSpecialDirectory = (sdHome, sdDocuments, sdMusic, ... usw) deklariert und dann eine Funktion "GetSpecialDirectory" geschrieben, die den Aufzählungswert für das gewünschte Verzeichnis als Parameter erhält, also "GetSpecialDirectory(sdMusic)" --> ValueOf('MUSIC") usw.
Für Windows gibt es eine Unit WinDirs (in fpc/source/rtl/win) mit Konstanten CSIDL_PROGRAMS, CSIDL_PERSONAL usw, und den Funktionen GetWindowsSpecialDir(),GetWindowsSpecialDirUnicode(), die damit aufgerufen werden können und das entsprechende Spezial-Verzeichnis zurückgeben.
Was kann Voided() mehr als das standardmäßig vorhandene Assigned()?
Bei den Bezeichnern würde ich mich fragen: was meint er damit? "dire" lt. https://de.langenscheidt.com/englisch-deutsch/dire: "gräßlich", "entsetzlich", Warum nicht einfach "Dir", so wie es jeder in "mkdir" oder "rmdir" kennt? Und bei den Typen "EZett" und "EZettClass", sowie bei dem Unitnamen "Zystem" frage ich ich: Welche Gags habe ich nun wieder nicht verstanden?
Ich hätte eine Aufzählung TSpecialDirectory = (sdHome, sdDocuments, sdMusic, ... usw) deklariert und dann eine Funktion "GetSpecialDirectory" geschrieben, die den Aufzählungswert für das gewünschte Verzeichnis als Parameter erhält, also "GetSpecialDirectory(sdMusic)" --> ValueOf('MUSIC") usw.
Für Windows gibt es eine Unit WinDirs (in fpc/source/rtl/win) mit Konstanten CSIDL_PROGRAMS, CSIDL_PERSONAL usw, und den Funktionen GetWindowsSpecialDir(),GetWindowsSpecialDirUnicode(), die damit aufgerufen werden können und das entsprechende Spezial-Verzeichnis zurückgeben.
Was kann Voided() mehr als das standardmäßig vorhandene Assigned()?
Bei den Bezeichnern würde ich mich fragen: was meint er damit? "dire" lt. https://de.langenscheidt.com/englisch-deutsch/dire: "gräßlich", "entsetzlich", Warum nicht einfach "Dir", so wie es jeder in "mkdir" oder "rmdir" kennt? Und bei den Typen "EZett" und "EZettClass", sowie bei dem Unitnamen "Zystem" frage ich ich: Welche Gags habe ich nun wieder nicht verstanden?
-
- Beiträge: 2120
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Vorbereitete Datenverzeichnise
Die Verzeichnisse machen nicht mal 1KB aus, weniger als 1/20tel der minimalen größe unter OSX, mit LCL sind die Dateien im MB Bereich. Man muss schon auf sehr eingeschränkten Systemen arbeiten damit 1KB wichtig ist, und auf denen kann man die unit auch einfach nicht verwenden.wp_xyz hat geschrieben:Hmmm... Also wenn ich zu entscheiden hätte, die Unit in Lazarus oder FPC aufzunehmen, würde ich sie ablehen. Ich will nicht sagen, dass sie schlecht ist, aber ich fände für diese konkrete Implementierung keine Anwendung. Der Hauptkritikpunkt ist: Warum packst du die einzelnen Verzeichnisse in einen Record? Denn das bedeutet, dass ich, wenn ich z.B. nur das Documents-Directory brauche, auch das Music-, Pictures-, Videos- etc. Directory in meinem Programm mitschleppen muss.
Ich hätte eine Aufzählung TSpecialDirectory = (sdHome, sdDocuments, sdMusic, ... usw) deklariert und dann eine Funktion "GetSpecialDirectory" geschrieben, die den Aufzählungswert für das gewünschte Verzeichnis als Parameter erhält, also "GetSpecialDirectory(sdMusic)" --> ValueOf('MUSIC") usw.
Für Windows gibt es eine Unit WinDirs (in fpc/source/rtl/win) mit Konstanten CSIDL_PROGRAMS, CSIDL_PERSONAL usw, und den Funktionen GetWindowsSpecialDir(),GetWindowsSpecialDirUnicode(), die damit aufgerufen werden können und das entsprechende Spezial-Verzeichnis zurückgeben.
Was kann Voided() mehr als das standardmäßig vorhandene Assigned()?
Bei den Bezeichnern würde ich mich fragen: was meint er damit? "dire" lt. https://de.langenscheidt.com/englisch-deutsch/dire: "gräßlich", "entsetzlich", Warum nicht einfach "Dir", so wie es jeder in "mkdir" oder "rmdir" kennt? Und bei den Typen "EZett" und "EZettClass", sowie bei dem Unitnamen "Zystem" frage ich ich: Welche Gags habe ich nun wieder nicht verstanden?
Vor allem wird damit die ganze Ladephase an den Programmstart versetzt und jeder sukzessive zugriff ist (zumindest für linux) kostenlos, denn Runcommand dauert viel länger als der zugriff auf einen record (ich würde so einen Faktor 100 oder so schätzen).
Mit der Namensgebung geb ich dir recht, irgendwie ergeben die für mich nicht so sinn