After the explanations in the last two chapters, you will be introduced to the project PathProject, which creates the executable file PathProject.gambas as a Gambas archive. The programme was designed and tested for the following three scenarios under the aspect of 'working with paths in Gambas':
1. start in the IDE (F5 or via the button in the toolbar with the ► symbol).
2. start in the project directory with
2.1 $ gbx3 $HOME/GB3BOOK/6K_Stream/6.1_Paths/BookProgram/PathProject
or
2.2 $ gbr3 $HOME/GB3BOOK/6K_Stream/6.1_Paths/BookProgram/PathProject/PathProject.gambas
3. start on the desktop with hans@mint-183 ~/Desk $ ./PathProject.gambas, if for example only the Gambas archive was copied to the desktop.
The project implements a simple database client. A SQLite3 database with a table (file contacts.s3db) and further files (help file, script file, sound files and image files) are provided in special directories in the project directory or created there. The database table can be read and changed.
|~/GB3BUCH/6K_Stream/6.1_Pfade/BuchProgramm/PathProject ├── data │ ├── databases │ │ ├── contacts_original.s3db │ │ └── contacts.s3db │ ├── texts │ └── xml ├── help │ └── help.txt ├── leds │ ├── gray16.png │ ├── green16.png │ └── red16.png ├── scripts │ └── dump.sh ├── sounds │ ├── sound_e.wav │ ├── sound_s.wav │ └── start.ogg └── symbols ├── db32.png ├── form_icon.png ├── logo3.png └── project_icon.png
Initial considerations with regard to working with files are also generally applied in this project to the answers to questions such as these:
In case you need to copy files to a suitable directory in the system temporarily or permanently, you should follow the following general suggestions and recommendations.
Configuration file:
For configuration files, consistently use the gb.settings component. Do not use the default path as the path for the configuration file. In this case, set ~/Desktop.ConfigDir/… as the base directory. as the base directory. In the case of a CSS file, for example, you must decide whether it is to be regarded as a configuration file or as a data file.
Data file:
If data must be available (permanently) even after a system restart, then these data files belong in the basic directory ~/Desktop.DataDir/… . Data that is generated and stored as intermediate results at runtime should be stored in temporary files either in /tmp/… or ~/Desktop.RuntimeDir/… . After /tmp/… or ~/Desktop.RuntimeDir/… also belong NamedPipes and local UnixSockets, because they are bound to the runtime of the Gambas process.
Database (DB):
A database or its DB tables only need to be read if you only want to display its records. If changes to the DB tables are permitted, the database and its tables must be readable and writable by the user. Note: After creation, an SQLite3 database automatically has only the rights: rw-r–r– .
Script file:
Scripts “*.{sh,sql,pl,py,gbs,…}” must be able to be read and executed. Since the shell and exec instructions require absolute paths, you must copy the scripts to a suitable directory in the system and make them executable with CHMOD path2script TO permission_string. Since shell scripts are only used temporarily, they belong in /tmp/… or ~/Desktop.RuntimeDir/… .
It has been specified that the shell script dump.sh is only used temporarily and is therefore copied to the directory /run/user/user-id/gambasbook/pathproject/scripts.
Sound file:
A sound file must only be read. However, if you give the user the chance to replace the sound files - under the old file names - then you must copy the sound files into a suitable base directory such as ~/Desktop.DataDir/… permanently.
Image file:
If you need a special icon for each of certain controls, then these only need to be read.
Help file:
A help file must normally be read only. However, the user may be interested in modifying the help file outside the programme, for example to insert a translation in another language.If there is no such interest, then it remains hidden in the project files - otherwise it must be copied permanently to a suitable basic directory such as ~/Desktop.DataDir/…. permanently.
In the following table you can see an overview of the intended paths of special directories:
Files | Type | Rwx | Directory path |
---|---|---|---|
image-files1 | local | r | project-directory/leds |
image-files2 | local | r | project directory/symbols |
Help files | local | r | Project directory/help |
Sound files | local | r | Project directory/sounds |
Script files | local | - | Project directory/scripts |
Data files | local | - | Project directory/data |
Databases | local | - | Project directory/data/database |
Data files | global | rw | ~/.local/share/gambasbook/pathproject/data |
Database | global | rw | ~/.local/share/gambasbook/pathproject/data/database |
Sound files | global | r | ~/.local/share/gambasbook/pathproject/sounds |
Script files | global | rx | /run/user/user-id/gambasbook/pathproject/scripts (temporary) |
configuration files | global | rw | ~/.config/gambasbook/pathproject |
Table 6.1.3.1 : Overview of the used (base) directories
The combination of provider-name/project-name as gambasbook/pathproject consistently serves as NameSpace. Note that both the vendor name (Vendor) - often it is the name of the developer - and the name of the application have been hard coded in the two variables sVendor and sAppName. The reason for the project name is that you cannot safely use the Application.Name property, which was discussed in the previous chapter. You could read out the name of the vendor from the (hidden) file .project - but this presupposes that this name has been entered in the project properties. If this is not the case, then it is set:
If Exist(".../.project") Then For Each sRow In Split(File.Load(".../.project"), gb.NewLine) If sRow Begins "Vendor" Then sVendor = Scan(sRow, "*=*")[1] Endif Next Endif If Not sVendor Then sVendor = "gambasbook" ' The vendor for all projects of the author is `gambasbook`.
Figure 6.1.3.1: 'Paths in Gambas' demonstration programme
The source code for the class FMain.class for the project `PathProject` is given in full. All other classes and modules can be found in the download directory in the project archive.
' Gambas class file ' SQLite has no concept of users. Access to a database is controlled by the actual file permissions ' of the database file. This means that the Login is always the user id executing the Gambas program. Public cC As Component Public sTempDir As String '---------------------------------- Public sGlobalConfigDir As String Public sGlobalRuntimeDir As String Public sGlobalDataDir As String Public sGlobalDBHostDir As String Public sGlobalScriptsDir As String Public sGlobalSoundsDir As String '---------------------------------- Public sLocalDataDir As String Public sLocalDBHostDir As String Public sLocalHelpDir As String Public sLocalLEDsDir As String Public sLocalScriptsDir As String Public sLocalSoundsDir As String Public sLocalSymbolsDir As String '---------------------------------- Public sVendor As String Public sAppName As String Public sDBName As String Public sFile As String Public hSettings As Settings Public sMessage As String Public sDBTableName As String Public Sub _new() Dim sRow As String If Exist(".../.project") Then For Each sRow In Split(File.Load(".../.project"), gb.NewLine) If sRow Begins "Vendor" Then sVendor = Scan(sRow, "*=*")[1] Endif Next Endif If Not sVendor Then sVendor = "gambasbook" sAppName = "PathProject" sDBName = "contacts.s3db" sDBTableName = "contacts" '------------------------------ sLocalDataDir = "data" sLocalDBHostDir = "databases" sLocalHelpDir = "help" sLocalLEDsDir = "leds" sLocalScriptsDir = "scripts" sLocalSoundsDir = "sounds" sLocalSymbolsDir = "symbols" '------------------------------------------------------------------------------------------------ sGlobalConfigDir = Desktop.ConfigDir &/ sVendor &/ Lower(sAppName) If Not Exist(sGlobalConfigDir) Then Shell.MkDir(sGlobalConfigDir) '------------------------------------------------------------------------------------------------ sGlobalRuntimeDir = Desktop.RuntimeDir &/ sVendor &/ Lower(sAppName) If Not Exist(sGlobalRuntimeDir) Then Shell.MkDir(sGlobalRuntimeDir) '------------------------------------------------------------------------------------------------ sGlobalDataDir = Desktop.DataDir &/ sVendor &/ Lower(sAppName) &/ GetDirPath(sLocalDataDir) If Not Exist(sGlobalDataDir) Then Shell.MkDir(sGlobalDataDir) '------------------------------------------------------------------------------------------------ sGlobalDBHostDir = sGlobalDataDir &/ sLocalDBHostDir If Not Exist(sGlobalDBHostDir) Then Shell.MkDir(sGlobalDBHostDir) For Each sFile In Dir(sLocalDataDir &/ sLocalDBHostDir, "*.s3db") If Not Exist(sGlobalDBHostDir &/ sFile) Then Copy sLocalDataDir &/ sLocalDBHostDir &/ sFile To sGlobalDBHostDir &/ sFile Endif Next '------------------------------------------------------------------------------------------------ sGlobalScriptsDir = sGlobalRuntimeDir &/ GetDirPath(sLocalScriptsDir) If Not Exist(sGlobalScriptsDir) Then Shell.MkDir(sGlobalScriptsDir) Endif For Each sFile In Dir(sLocalScriptsDir, "*.{sh,sql,pl,py,gbs}") If Not Exist(sGlobalScriptsDir &/ sFile) Then Copy sLocalScriptsDir &/ sFile To sGlobalScriptsDir &/ sFile Chmod sGlobalScriptsDir &/ sFile To "..x......" Endif Next '------------------------------------------------------------------------------------------------ sGlobalSoundsDir = Desktop.DataDir &/ sVendor &/ Lower(sAppName) &/ GetDirPath(sLocalSoundsDir) If Not Exist(sGlobalSoundsDir) Then Shell.MkDir(sGlobalSoundsDir) Endif For Each sFile In Dir(sLocalSoundsDir, "*.{ogg,wav}") If Not Exist(sGlobalSoundsDir &/ sFile) Then Copy sLocalSoundsDir &/ sFile To sGlobalSoundsDir &/ sFile Endif Next '------------------------------------------------------------------------------------------------ hSettings = New Settings(sGlobalConfigDir &/ File.SetExt(Lower(sAppName), "conf")) SetNotification("dialog-information", "Attention!") End Public Sub Form_Open() Dim i As Integer If Not System.Exist("sqlite3") Then sMessage = "<b><font size='+1', color='DarkRed'>" sMessage &= "The application requires the program 'sqlite3'." sMessage &= "</b></font><hr>" sMessage &= "Installation console (MINT): $ sudo apt-get install sqlite3" sMessage &= "\nThe application is therefore terminated!" MAddOns.PlaySound(sGlobalSoundsDir &/ "sound1.ogg") Message.Info(sMessage) Quit Else ' Message.Info("The programm path from 'sqlite3' is: " & System.Find("sqlite3")) Endif ' The 'About ...' window is displayed exactly twice. If hSettings["First/Value", 0] < 2 Then i = hSettings["First/Value", 0] Inc i hSettings["First/Value"] = i hSettings.Save() FAbout.ShowModal() Endif DataSource1.Connection = DBCS.DBConnection sGlobalDBHostDir = DBCS.DBConnection.Host DataSource1.Table = sDBTableName SetDBBrowserProperties() SetDataControlProperties() btnShowDumpData.Enabled = False pboxOnOff.Picture = Picture.Load(".../leds/green16.png") ' pboxOnOff.Picture = Picture["leds/green16.png"] ' Alternative FMain.Icon = Picture[sLocalSymbolsDir &/ "project_icon.png"] End Public Sub btnDBSicherungDumpE_Click() btnShowDumpData.Enabled = True MAddOns.PlaySound(sGlobalSoundsDir &/ "sound_e.wav") pboxOnOff.Picture = Picture["leds/red16.png"] GetDBDumpExec() Wait 0.2 pboxOnOff.Picture = Picture["leds/green16.png"] End Public Sub btnDBSicherungDumpS_Click() btnShowDumpData.Enabled = True MAddOns.PlaySound(sGlobalSoundsDir &/ "sound_s.wav") pboxOnOff.Picture = Picture.Load(".../leds/red16.png") GetDBDumpShell() Wait 0.2 pboxOnOff.Picture = Picture.Load(".../leds/green16.png") End Public Sub btnHelp_Click() FHelp.ShowModal() End Public Sub btnShowDumpData_Click() FShowDump.ShowModal() btnShowDumpData.Enabled = False End Public Sub btnHelpLibrary_Click() Dim cl As Class cC = Component.Load(":gambasbook/LPathProject:1.2") cl = Class.Load("Module1") Object.Call(cl, cl.Symbols[0], Zero) Catch Message.Error(Error.Text) End Private Sub SetDBBrowserProperties() DataBrowser1.Labels = ["ID", "First name", "Surname", "Postcode", "Residence", "Street", "E-mail address"] DataBrowser1.CanCreate = True DataBrowser1.CanDelete = True DataBrowser1.Editable = False DataBrowser1.View.Clear() DataBrowser1.Columns = ["id", "first name", "surname", "postcode", "residence", "street", "e-mail address"] DataBrowser1.View.Columns[0].Width = 30 DataBrowser1.View.Columns[1].Width = 90 DataBrowser1.View.Columns[2].Width = 90 DataBrowser1.View.Columns[3].Width = 45 DataBrowser1.View.Columns[4].Width = 120 DataBrowser1.View.Columns[5].Width = 125 DataBrowser1.View.Columns[6].Width = 1 DataBrowser1.View.MoveTo(0, 0) ' … necessary! End Private Sub SetDataControlProperties() dcVorname.Field = "first name" ' Data control - DB fields are data-sensitive! dcNachname.Field = "surname" dcPLZ.Field = "postcode" cdWohnort.Field = "residence" dcStrasse.Field = "street" dcEMailAdresse.Field = "e-mail" End Private Sub GetDBDumpShell() Dim sShellCommand, sParameter1, sParameter2 As String ' The file extension .sql is automatically supplemented with the Dump command! ' The quotation marks prevent the interpretation of the blanks as a tax mark. sParameter1 = Shell$(sGlobalDBHostDir &/ sDBName) sParameter2 = Shell$(sGlobalDBHostDir &/ "dump." & sDBTableName) sShellCommand = Subst$("sqlite3 &1 .dump .quit > &2.sql", sParameter1, sParameter2) Shell sShellCommand Wait End Private Sub GetDBDumpExec() Dim aExecCommand As String[] Dim sTempScriptPath, sLocalScriptPath As String sLocalScriptPath = sLocalScriptsDir &/ "dump.sh" sTempScriptPath = Temp(File.BaseName(sLocalScriptPath)) & ".sh" ' Absolute path! ' The query is necessary because an existing file is not overwritten. If Not Exist(sTempScriptPath) Then Copy sLocalScriptPath To sTempScriptPath ' Chmod sTempScriptPath To "rwxr--r--" ' All rights are *explicitly* set anew! ' Only the "Execute" permission is set for the owner - all others are retained. Chmod sTempScriptPath To "..x......" ' The file extension .sql is automatically supplemented with the Dump command! aExecCommand = [sTempScriptPath, sGlobalDBHostDir &/ sDBName, sGlobalDBHostDir &/ "dump." & sDBTableName] Exec aExecCommand Wait End Private Function GetDirPath(sDir As String) As String If sDir Not Begins "." Then Return sDir Else Return Scan(sDir, "*/*")[1] Endif End Private Sub SetNotification(Icon As String, BaseText As String) Dim sNotificationIcon, sNotificationBaseText, sNotificationText As String sNotificationIcon = Icon ' Options: "dialog-information" or "dialog-warning" sNotificationBaseText = BaseText ' For example: "Attention!" sNotificationText = ("The program demonstrates the use of file paths in Gambas.") MAddOns.SendNotification(sNotificationIcon, sNotificationBaseText, sNotificationText, -1) MAddOns.PlaySound(sGlobalSoundsDir &/ "start.ogg") End Public Sub btnClose_Click() If DBCS.DBConnection.Opened Then DBCS.DBConnection.Close() FMain.Close() End Public Sub Form_Close() DBCS.DBConnection.Close() End