Gambas3 op iMac/OSX

Gambas draait niet “native” op Mac OS/X. Maar je kan een virtual machine met Linux installeren, en daarin Gambas.

Een voorbeeld, geïnstalleerd in 2024: Apple M1 met 16 GB en macOS Sequoia versie 15.6.1 met UTM Version 4.5.3 (99), met daarin OpenSuse Leap 15.5.

Deze virtuele openSUSE werkt vlot, in een venster dat je op een deel van het scherm kan draaien, vergroten, enz. Het werkt niet helemaal perfect; zo zie ik dat Firefox een zwarte “rand” heeft, het lijkt wel een zwart “kader” rond het venster van de browser.

Maar er zijn ook wel een paar Gambas dingen die niet perfect werken. Na wat problemen met elementen op het scherm heb ik mijn gambas3 applicatie (voor de desktop) wat aangepast, in grote lijnen komt het er op neer dat ik een aantal typische QT dingen niet gebruik. Ik heb mijn desktop keuze in Gambas ingesteld op iets LXDE of XFCE achtig, en nu kan ik de software perfect draaien.

En het valt me op dat Gambas daar razendsnel op draait, ondanks dat het “maar” in een VM is…

Wat is gambas?

Featured

  • Gambas is een laagdrempelige programmeeromgeving op Linux om Linuxprogramma’s te maken.
  • De Gambas programmeertaal is een object georiënteerde knipoog naar visual basic, maar voelt vooral erg native Linux aan, en de IDE is volledig in Gambas geschreven…. Continue reading

Programmeer of gebruiksversie

Ik heb doorgaans problemen bij het tegelijk schrijven en gebruiken van software

  1. de gegevens (database): ik wil niet het risico lopen om gegevens te verliezen door programmeerwerk dat nog niet in orde is, dus moet mijn programmeren gebeuren met andere data dan mijn “gebruik”.
  2. de bestanden: als ik bestanden gebruik om te lezen of te manipuleren (verplaatsen naar ander directories bv), wil ik ook niet bij het programmeren door fouten daar bestanden verliezen of wanorde creëren in de structuur.
  3. Extreem uit elkaar lopende versies, wat gemakkelijk kan met git, levert mij bij eenzelfde gambas programma het probleem op dat het uitvoerbare programma dat gemaakt wordt dezelfde naam heeft, en dat bv de executable van de programmeerversie de “goede” versie die in gebruik is, zal overschrijven.

Scripting

In forum.gambas.one vind je een voorbeeld om snel te starten:

#!/usr/bin/env gbs3
 Public Sub Main()
    Dim strFiles as String

    Exec ["ls", "-l"] To strFiles
    Print strFiles
 End

Bewaar het als script, met een naam bv Gb3TestScript1.gbs en maak het uitvoerbaar (chmod +x of in je bestandsbeheerder).

Om het te starten ga je in die directorie staan en doet

./Gb3TestScript1.gbs

Dit scipt doet niet veel bijzonders, maar het is een aanknopingspunt; zo kan je de uitvoer bv

  • op een gedeelde locatie zetten (bv nextcloud) om beschikbaar te maken voor collega’s
  • in html opmaken en in een directory van de webserver bewaren om zichtbaar te maken enz.

Programmanaam en datum

Gegevens over het gambas programma zelf krijg je vanuit code met Application

Print Application.Name
Print Application.Version

* Name is niet noodzakelijk hetzelfde als Application.Title (die kan anders gekozen zijn – zie Project Eigenschappen, Titel; het is een vrije tekst. Dit in tegenstelling tot de naam die overeenkomt met de projectmap-naam).

Moeilijker is de datum van het programma zelf, want terwijl je werkt in de IDE is dat eigenlijk niet gedefinieerd. Pas als je een executable hebt gemaakt (Project, Maak uitvoeringsbestand) kan je weten wat de datum van het uitvoerbare programma is.

Gegevens van een bestand vraag je op de commandolijn op met stat, en dat is overgenomen in Gambas in het commando Stat

De naam van de executable kan je niet direct opvragen, maar wel samenstellen uit pad, naam en de uitgang .gambas

De datum van een bestand: Stat(“naamvaneenbestand”) kan je zo invullen:

Stat(Application.Path &/ Application.Name & ".gambas").LastModified

Maar! als je deze code draait vanuit de IDE (F5 uitvoeren) krijg je een foutmelding: “File or directory does not exist”

Dat kan je opvangen door er Try voor te zetten, toon eventueel de foutmelding ergens:

' (er is een TextLabel voor de titel gemaakt) 
txlbTitle.Text = Application.Name & " (datum ...)"
Try txlbTitle.Tooltip = Stat(Application.Path &/ Application.Name & ".gambas").LastModified
If Error Then
txlbTitle.Tooltip &= " tried path/name: " & Application.Path &/ Application.Name & ".gambas" & " err: " & Error.Text
Endif

Bladwijzer in de broncode (bookmark)

Als je een probleem in de broncode aan het oplossen bent, moet je kunnen heen en weer springen tussen verschillende stukken code. Daarvoor kan je een bladwijzer zetten om je vorige positie te onthouden: sta op een lijn en druk Ctrl-B. Er verschijnt een zacht (lichtblauw bij mij) pijltje voor de lijn.

Ga naar een willekeurige andere lijn in je text (als je weet dat je rond 500 bezig was, druk Ctrl-G 500.

Ga nu snel terug naar je bookmark met Alt-PageUp of Alt-PageDown.

Dat is handiger dan er breekpunten voor te gebruiken, die kunnen later hinderen.

Combobox titel

Ik heb een eigenaardigheid op een rapsberry pi met het gebruik van comboboxen: als je bv 3 elementen toevoegt, dan zal de combobox bij opstarten toch een lege text hebben (niet de waarde van bv eerste item). Maar je kan niet zelf iets zetten in die lege tekst (bv een titel zou handig zijn, die aangeeft wat de inhoud van de keuze is).

Dit in FMain:

Public Sub Form_Open()
'ComboBox1.Add("Choose here..")
ComboBox1.Text = "Choose here"
ComboBox1.Add("ABC")
ComboBox1.Add("Def")
ComboBox1.Add("Ghi")
'ComboBox1.Index = 0
ComboBox1.ReadOnly = True
'
ComboBox2.Add("Choose here")
ComboBox2.Add("ABC")
ComboBox2.Add("Def")
ComboBox2.Add("Ghi")
'ComboBox2.Index = 0
ComboBox2.ReadOnly = True
End
'
Public Sub ComboBox1_Click()
Message.Info(ComboBox1.Index)
End
'
Public Sub ComboBox2_Click()
Message.Info(ComboBox2.Index)
End

De ComboBox1.Text geeft geen foutmelding, maar is ook niet zichtbaar.

KDE: Vanaf je gekozen hebt in de combobox, verdwijnt de “lege lijn” bovenaan.

In tegenstelling to op de Pi: Je kan altijd terug naar de “lege” toestand.


Datacontext voor directories voorbeeld

Datacontext voor directories: een voorbeeld (met in groen hoe het er uit ziet in het configuratie/settings bestand)

De code

dim bOk as boolean

We leggen bv eerst vast hoe onze dirset gaat heten*:

bOk = newDirSet("Export")

[DirSet]
Export = ""

Best een beschrijving geven om uit te leggen wat hiermee moet gebeuren:

updDirSet(“Export”, “Dir for data export from this application”)

[DirSet]
Export = "Dir for data export from this application"

Kan ook in één keer:

bOk = newDirSet("Export", "Dir for data export from this application")

.. met hetzelfde resultaat als boven in het settings bestand; toon beschrijving van..

print getDirSetDescription("Export")

Dir for data export from this application

We kunnen alle (in configuratiebestand) bestaande dirsets opvragen:

arrString[] = getAllDirSetNames()

Directory path opslaan

En nu het belangrijkste: een directorypath bewaren voor een bepaalde dirset; hier context 0 **:

setDirValue(0, "Export", "path", "/home/copyleft/Data/Export")

[Datacontext0-Export]
path = "/home/copyleft/Data/Export"

(**) Als een datacontext in gebruik is kan je de huidige id opvragen:

print hDataContext.getCurrentContextId()

En dan écht het belangrijkste: getDirValue opvragen; hier tonen we hem enkel:

print "We export to: " & getDirValue(hDataContext.getCurrentContextId(), "Export", "path")

We export to: /home/copyleft/Data/Export

De directory opvragen gebeurt in je applicatie op het moment dat je daar iets mee wil doen; bv een tekst bewaren in een bestand:

File.Save(getDirValue(0, "Export", "path") &/ "ExportOfTheDay.txt", sText);

Intern gebruikt DataContext deze methode om de Settings te maken:

print getContextDirSet(0, "Export")

Datacontext0-Export

Wat er in het bestand zo uitziet (zie ook hierboven):
[Datacontext0-Export]
...

(*) De naam “Export” zal misschien vastliggen in je applicatie, of laat je daar kiezen.

Ook de sleutel “path” kan je in principe kiezen. De Datacontext bewaart er verder nog de datum van aanmaak en laatste wijziging bij, die kan je nazien in het configuratiebestand (momenteel nog niet vanuit een methode in de library, tenzij je in getDirValue de juiste sleutel meegeeft, zoals csKEYMODIFIED, zie definities in DataContext class).

Andere voorbeelden

  • Import : bv om txt bestanden in te lezen
  • Pictures: bv iconen of beeldmateriaal waarnaar gelinkt wordt / om ze te laden in de applicatie
  • Export : zoals hierboven, bv om vanuit een applicatie een CSV export bestand te maken en dat op een vaste plaats voor de gebruiker te bewaren.
  • Cam: opgenomen beeld met webcam

DataContext: het unieke van het gebruik met het datacontext concept is dat je voor iedere “DataContext” aangepaste directory locaties kan opslaan. Door de datacontext om te schakelen gebruik je andere databases en andere directories, bv:

  • Datacontext0 = “Dev”, locale map op mijn laptop waarop ik programmeer; en de databaseverbindingen gaan naar mijn “localhost” database met testgegevens.
  • Datacontext1 = “live”, een map op een server of nextcloud die gedeeld wordt met andere gebruikers, en de database instellingen spreken de echte servers met live aan.

Toegepast op ons voorbeeld zou ons instellingenbestand zoiets bevatten (de database gegevens even weggelaten):

[DataContext0]
Name = "Live"
Description = "Echte gegevens, in gebruik

[DataContext1]
Name = "Dev"
Description = "Ontwikkelomgeving local(host)"

[DirSet]
Name = "Export"
Description = "Export csv files here"

[DataContext0-Export]
path = "/nextcloud/shared/myappdata/out"
created = "01/01/2024"

[DataContext1-Export]
path = "/home/username/myappdata/out"
created = "03/01/2024"

...


Datacontext voor directories

Ik pas al een tijdje het “datacontext” begrip toe in mijn eigen programma’s, waarbij ik gemakkelijk kan omschakelen tussen database-servers voor “development” en “live” data.

Nu wil ik samen daarmee ook andere directories gebruiken, bv voor uitvoer (“Export”). Standaard had ik daarvoor in “/home/user/Data/myApp/” een map “Export/”, maar nu wil ik schakelen tussen
“live/Export” en “dev/Export”.

In mijn configuratie-bestand maak (definieer) ik daarvoor volgende settings:
(ik gebruik het DataContext object myContext)

myContext.newDirSet("Export", "Export of data here")

Dat bewaart:

[DirSet]
Export="Export of data here"
..

Uitgebreider voorbeeld: een programma dat gegevens met foto’s opslaat in een database, daarvoor kan importeren en er ook uit kan exporteren zou volgende directories kunnen gebruiken:
(telkens de naam en de verklaring)

[DirSet]
Export=”Export of data here”
Import=”Import of data here”
Cam=”Camera images come here”
DbPictures=”Database URL’s to pictures here”

Je kan ze inlezen in een array van strings:
myContext.getAllDirSetNames()
(en zo ook tellen met array.Count)

Ik houd bovenstaande omschakelmogelijkheden aan tussen mijn echt gebruikte gegevens en mijn ontwikkelomgeving:
(terug te vinden in ~.config/gambas3/myApp.conf)


[DataContext0]
Name="live"
...

[DataContext1]
Name="dev"
...

Met het omschakelen van DataContext 0 naar 1 moeten ook de Dirset keuzes aangepast van 0 naar 1.

Daarvoor heb ik config settings nodig:

[Dirset0-Export]
Dir="/home/user/Data/myApp/live/Export"

[Dirset1-Export]
Dir="/home/user/Data/myApp/dev/Export"

Die maak ik met:

myContext.setDirValue(0, "Export", "path", User.Home)
(maak een variabele om te gebruiken ipv User.Home)

In de klasse CDataContext heb ik voor de directory instellingen dus:

newDirSet(sName As String, Optional sDescription As String) As Boolean

updDirSet(sName As String, sNewDescription As String) As Boolean

getDirSetDescription(sName As String) As String


getContextDirSet(iContextId As Integer, sDirSetName As String) As String


getDirValue(iContextId As Integer, sDirSetName As String, sKey As String) As String


setDirValue(iContextId As Integer, sDirSetName As String, sKey As String, sDir As String) As Boolean


getAllDirSetNames() As String[]

Met de bedoeling redelijk universeel toepasbaar te zijn, vanaf je een DataContext hebt gedefinieerd kan je het gebruiken, ook los van database instellingen:

https://sourceforge.net/projects/garlic3/files/Lib/DataContext/

Gebruik: het project bevat Classes en een Module, en een uitvoerbaar (desktop) programma met FMain en een menu om te testen wat het doet.

Als je het compileert als “library” dan gaat die code niet mee, en kan je het als (project properties) “library” gebruiken in een ander Gambas3 project.

Zie ook DataContext voor directories voorbeeld

Gambas is back! Gambas3 is terug in openSUSE!

Na een onderbreking van een paar maanden ben ik verheugd Gambas terug gemakkelijk te kunnen installeren in OpenSUSE, namelijk in versie 15.6. (geïnstalleerd, upd: ook gebruikt), en (upd 1/2/2025) ook in Tumbleweed via software.opensuse.org.

Stappen:/
verse 15.6
Na een update van opensuse 15.5 naar 15.6 ging ik op zoek naar de vroegere bron van Gambas(3) in openSUSE: Munix.

Munix repo
Repository toegevoegd via YAST:
https://download.opensuse.org/repositories/home:/munix9/ (URL link)
En met 15.6 hebben we geluk: gambas3 is weer voorzien:
bv gambas3-runtime-3.19.5-lp156.2.1.x86_64.rpm
ps: En (voorlopig nog) niet in 16.0.

Software Installeren: gambas3
Selecteren:
gambas3 – Complete visual development environment for Gambas
Version: 3.19.5  (ps: in juni 2026 toch terug problemen met versie 3.20.x)

Installation Successfully Finished
Packages
Installed Packages: 139
autoconf, automake, bison, bison-lang, dwz, gambas3, gambas3-dev-tools, gambas3-gb-args…

(more)

Continue reading