My simple, unoptimised blob database if anyone wants it. Or not.
Code: Select all
;- Window Constants
Enumeration 1
#Window_Blobby
#Window_BlobbyData
EndEnumeration
#WindowIndex = #PB_Compiler_EnumerationValue
;- Gadget Constants
Enumeration 1
; Window_Blobby
#Gadget_Blobby_cBlobList
#Gadget_Blobby_BlobList
#Gadget_Blobby_cPicture
#Gadget_Blobby_Picture
#Gadget_Blobby_cDetails
#Gadget_Blobby_cControl
#Gadget_Blobby_Add
#Gadget_Blobby_Delete
#Gadget_Blobby_Edit
#Gadget_Blobby_Save
#Gadget_Blobby_cMessages
#Gadget_Blobby_Details
#Gadget_Blobby_iMessages
#Gadget_Blobby_Messages
#Gadget_Blobby_Exit
; Window_BlobbyData
#Gadget_BlobbyData_cPicture
#Gadget_BlobbyData_Picture
#Gadget_BlobbyData_cDetails
#Gadget_BlobbyData_Details
#Gadget_BlobbyData_cControl
#Gadget_BlobbyData_Save
#Gadget_BlobbyData_Camera
#Gadget_BlobbyData_Exit
#Gadget_BlobbyData_Mode
#Gadget_BlobbyData_Record
#Gadget_BlobbyData_lMode
EndEnumeration
#GadgetIndex = #PB_Compiler_EnumerationValue
;- Image Constants
Enumeration 1
#Image_Blobby_Add
#Image_Blobby_Delete
#Image_Blobby_Edit
#Image_Blobby_Save
#Image_Blobby_iMessages
#Image_Blobby_Exit
#Image_BlobbyData_Save
#Image_BlobbyData_Camera
#Image_BlobbyData_Exit
EndEnumeration
#ImageIndex = #PB_Compiler_EnumerationValue
;- Load Images
CatchImage(#Image_Blobby_Add, ?_OPT_Blobby_Add)
CatchImage(#Image_Blobby_Delete, ?_OPT_Blobby_Delete)
CatchImage(#Image_Blobby_Edit, ?_OPT_Blobby_Edit)
CatchImage(#Image_Blobby_Save, ?_OPT_Blobby_Save)
CatchImage(#Image_Blobby_iMessages, ?_OPT_Blobby_iMessages)
CatchImage(#Image_Blobby_Exit, ?_OPT_Blobby_Exit)
CatchImage(#Image_BlobbyData_Save, ?_OPT_Blobby_Save)
CatchImage(#Image_BlobbyData_Camera, ?_OPT_BlobbyData_Camera)
CatchImage(#Image_BlobbyData_Exit, ?_OPT_Blobby_Exit)
DataSection
_OPT_Blobby_Add : IncludeBinary "Images\add32x32.ico"
_OPT_Blobby_Delete : IncludeBinary "Images\delete32x32.ico"
_OPT_Blobby_Edit : IncludeBinary "Images\edit32x32.ico"
_OPT_Blobby_Save : IncludeBinary "Images\save32x32.ico"
_OPT_Blobby_iMessages : IncludeBinary "Images\messages16x16.ico"
_OPT_Blobby_Exit : IncludeBinary "Images\exit32x32.ico"
_OPT_BlobbyData_Camera : IncludeBinary "Images\camera32x32.ico"
EndDataSection
Procedure.l Window_Blobby()
If OpenWindow(#Window_Blobby, 52, 73, 805, 650, "View BLOB picture in database", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered|#PB_Window_Invisible)
SetWindowColor(#Window_Blobby, $A2A2A2)
ContainerGadget(#Gadget_Blobby_cBlobList, 5, 5, 300, 545, #PB_Container_Flat|#PB_Container_BorderLess)
SetGadgetColor(#Gadget_Blobby_cBlobList, #PB_Gadget_BackColor, $BFBFBF)
ListIconGadget(#Gadget_Blobby_BlobList, 5, 5, 290, 535, "Picture name", 286, #PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
SetGadgetColor(#Gadget_Blobby_BlobList, #PB_Gadget_BackColor, $DBDBDB)
AddGadgetColumn(#Gadget_Blobby_BlobList, 1, "Record", 0)
SetGadgetFont(#Gadget_Blobby_BlobList, LoadFont(#Gadget_Blobby_BlobList, "Comic Sans MS", 10, 0))
CloseGadgetList()
ContainerGadget(#Gadget_Blobby_cPicture, 310, 5, 490, 440, #PB_Container_Flat|#PB_Container_BorderLess)
SetGadgetColor(#Gadget_Blobby_cPicture, #PB_Gadget_BackColor, $BFBFBF)
ImageGadget(#Gadget_Blobby_Picture, 5, 5, 480, 430, 0)
CloseGadgetList()
ContainerGadget(#Gadget_Blobby_cDetails, 310, 450, 490, 100, #PB_Container_Flat|#PB_Container_BorderLess)
SetGadgetColor(#Gadget_Blobby_cDetails, #PB_Gadget_BackColor, $BFBFBF)
EditorGadget(#Gadget_Blobby_Details, 5, 5, 480, 90, #PB_Editor_ReadOnly|#PB_Editor_WordWrap)
SetGadgetColor(#Gadget_Blobby_Details, #PB_Gadget_BackColor, $DBDBDB)
SetGadgetFont(#Gadget_Blobby_Details, LoadFont(#Gadget_Blobby_Details, "Comic Sans MS", 10, 0))
CloseGadgetList()
ContainerGadget(#Gadget_Blobby_cControl, 5, 555, 795, 60, #PB_Container_Flat|#PB_Container_BorderLess)
SetGadgetColor(#Gadget_Blobby_cControl, #PB_Gadget_BackColor, $BFBFBF)
ButtonImageGadget(#Gadget_Blobby_Add, 5, 5, 45, 45, ImageID(#Image_Blobby_Add))
ButtonImageGadget(#Gadget_Blobby_Delete, 50, 5, 45, 45, ImageID(#Image_Blobby_Delete))
ButtonImageGadget(#Gadget_Blobby_Edit, 95, 5, 45, 45, ImageID(#Image_Blobby_Edit))
ButtonImageGadget(#Gadget_Blobby_Save, 140, 5, 45, 45, ImageID(#Image_Blobby_Save))
ButtonImageGadget(#Gadget_Blobby_Exit, 745, 5, 45, 45, ImageID(#Image_Blobby_Exit))
CloseGadgetList()
ContainerGadget(#Gadget_Blobby_cMessages, 5, 620, 795, 24, #PB_Container_Flat|#PB_Container_BorderLess)
SetGadgetColor(#Gadget_Blobby_cMessages, #PB_Gadget_BackColor, $BFBFBF)
ImageGadget(#Gadget_Blobby_iMessages, 5, 3, 16, 16, ImageID(#Image_Blobby_iMessages))
StringGadget(#Gadget_Blobby_Messages, 25, 0, 765, 21, "", #PB_String_BorderLess)
SetGadgetColor(#Gadget_Blobby_Messages, #PB_Gadget_BackColor, $BFBFBF)
SetGadgetFont(#Gadget_Blobby_Messages, LoadFont(#Gadget_Blobby_Messages, "Comic Sans MS", 11, 0))
CloseGadgetList()
HideWindow(#Window_Blobby, 0)
ProcedureReturn WindowID(#Window_Blobby)
EndIf
EndProcedure
Procedure.l Window_BlobbyData()
If OpenWindow(#Window_BlobbyData, 80, 75, 500, 630, "", #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_Invisible, WindowID(#Window_Blobby))
SetWindowColor(#Window_BlobbyData, $A2A2A2)
ContainerGadget(#Gadget_BlobbyData_cPicture, 5, 5, 490, 440, #PB_Container_Flat|#PB_Container_BorderLess)
SetGadgetColor(#Gadget_BlobbyData_cPicture, #PB_Gadget_BackColor, $BFBFBF)
ImageGadget(#Gadget_BlobbyData_Picture, 5, 5, 480, 430, 0)
CloseGadgetList()
ContainerGadget(#Gadget_BlobbyData_cDetails, 5, 450, 490, 110, #PB_Container_Flat|#PB_Container_BorderLess)
SetGadgetColor(#Gadget_BlobbyData_cDetails, #PB_Gadget_BackColor, $BFBFBF)
EditorGadget(#Gadget_BlobbyData_Details, 5, 5, 480, 100, #PB_Editor_WordWrap)
SetGadgetColor(#Gadget_BlobbyData_Details, #PB_Gadget_BackColor, $DBDBDB)
SetGadgetFont(#Gadget_BlobbyData_Details, LoadFont(#Gadget_BlobbyData_Details, "Comic Sans MS", 10, 0))
CloseGadgetList()
ContainerGadget(#Gadget_BlobbyData_cControl, 5, 565, 490, 60, #PB_Container_Flat|#PB_Container_BorderLess)
SetGadgetColor(#Gadget_BlobbyData_cControl, #PB_Gadget_BackColor, $BFBFBF)
ButtonImageGadget(#Gadget_BlobbyData_Save, 5, 5, 45, 45, ImageID(#Image_BlobbyData_Save))
ButtonImageGadget(#Gadget_BlobbyData_Camera, 50, 5, 45, 45, ImageID(#Image_BlobbyData_Camera))
ButtonImageGadget(#Gadget_BlobbyData_Exit, 440, 5, 45, 45, ImageID(#Image_BlobbyData_Exit))
StringGadget(#Gadget_BlobbyData_Mode, 105, 10, 145, 20, "", #PB_String_ReadOnly|#PB_String_BorderLess)
SetGadgetColor(#Gadget_BlobbyData_Mode, #PB_Gadget_BackColor, $DBDBDB)
SetGadgetColor(#Gadget_BlobbyData_Mode, #PB_Gadget_FrontColor, $FF0000)
SetGadgetFont(#Gadget_BlobbyData_Mode, LoadFont(#Gadget_BlobbyData_Mode, "Comic Sans MS", 10, 0))
StringGadget(#Gadget_BlobbyData_Record, 285, 10, 145, 20, "", #PB_String_ReadOnly|#PB_String_BorderLess)
SetGadgetColor(#Gadget_BlobbyData_Record, #PB_Gadget_BackColor, $DBDBDB)
SetGadgetColor(#Gadget_BlobbyData_Record, #PB_Gadget_FrontColor, $FF0000)
SetGadgetFont(#Gadget_BlobbyData_Record, LoadFont(#Gadget_BlobbyData_Record, "Comic Sans MS", 10, 0))
TextGadget(#Gadget_BlobbyData_lMode, 105, 35, 325, 15, " Current mode Record number")
SetGadgetColor(#Gadget_BlobbyData_lMode, #PB_Gadget_BackColor, $BFBFBF)
SetGadgetFont(#Gadget_BlobbyData_lMode, LoadFont(#Gadget_BlobbyData_lMode, "Comic Sans MS", 8, 0))
CloseGadgetList()
HideWindow(#Window_BlobbyData, 0)
ProcedureReturn WindowID(#Window_BlobbyData)
EndIf
EndProcedure
;
Declare OpenSystemDatabase() ; Try to open the system database and create missing tables
Declare.s DatabaseLastInsertRowId() ; Get the ID of the last inserted record
;
Declare.s ByteCalc(Byte.q, NbDecimals = 2) ; AND51's correct file size calculation code
Declare CloseMyWindow(WindowId.i) ; Fade the window out gently, close it and reset the mutex
Declare.s KillQuote(Instring.s) ; Kill double quotes in strings for display purposes
Declare LastLine(Gadget.i, LineNumber.i) ; Go to the last line of a ListIconGadget
Declare.s LastRecord(TableField.s, TableName.s) ; Find the last record number in the database, not necessarily the last record though due to deletions (fang)
Declare.s RepQuote(Instring.s) ; Uncle Berikco's routine to properly replace single quotes with double for SQL passing
;
Declare ListPicturesMainForm() ; Load and display all pictures in the database
Declare DisplayPictureMainForm() ; Show the picture for a selected record
;
Declare AddPicture() ; Add a new picture to the database
Declare DeletePictureFromDatabase() ; Delete a picture from the database
Declare EditPicture() ; Edit the currently selected picture
Declare LoadPictureFromDisk() ; Load a picture from disk into the data form
Declare SavePictureToDatabase() ; Save a new or edited picture to the database
Declare SavePictureToDisk() ; Save a picture back to disk from the database
; Use for viewing various picture formats
UseJPEG2000ImageDecoder()
UseJPEGImageDecoder()
UsePNGImageDecoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()
; Use the SQLite database environment
UseSQLiteDatabase()
; Keep track of various program parameters
Structure ProgramData
QuitFlag.i
MutexVal.i
LastWindow.s
DatabaseHandle.i
DatabaseName.s
CurrentDir.s
CurrentLine.i
CurrentRecord.s
ImageWidth.i
ImageHeight.i
OldPictureName.s
NewPictureName.s
EndStructure
; Database structure
Structure DatabaseData
BlobData.s ; 0
BlobName.s ; 1
BlobPath.s ; 2
BlobSize.s ; 3
BlobDate.s ; 4
BlobComment.s ; 5
BlobRecord.s ; 6
EndStructure
; Make sure the structure data is globally available
Global Program.ProgramData
Global Database.DatabaseData
;
Program\CurrentDir = GetCurrentDirectory()
Program\DatabaseName = Program\CurrentDir + "Database\Blobby.db3"
;
Program\ImageWidth = 480
Program\ImageHeight = 430
;
Enumeration #ImageIndex
#Image_Blobby_BlobList
EndEnumeration
;
CatchImage(#Image_Blobby_BlobList, ?_OPT_Blobby_BlobList)
;
DataSection
_OPT_Blobby_BlobList : IncludeBinary "Images\blob16x16.ico"
EndDataSection
; Get the ID of the last inserted record
Procedure.s DatabaseLastInsertRowId()
If DatabaseQuery(Program\DatabaseHandle, "SELECT last_insert_rowid()")
If FirstDatabaseRow(Program\DatabaseHandle)
RecordId.s = GetDatabaseString(Program\DatabaseHandle, 0)
EndIf
FinishDatabaseQuery(Program\DatabaseHandle)
Else
RecordId.s = ""
EndIf
ProcedureReturn RecordId.s
EndProcedure
; Find the last record number in the database, not necessarily the last record though due to deletions (fang)
Procedure.s LastRecord(TableField.s, TableName.s)
; Always create long winded queries for readability
SqlQueryString.s = "SELECT MAX(" + TableField.s + ") As LASTREC FROM " + TableName.s + ""
If DatabaseQuery(Program\DatabaseHandle, SqlQueryString.s)
While NextDatabaseRow(Program\DatabaseHandle)
LastRecord.s = GetDatabaseString(Program\DatabaseHandle, 0)
Wend
FinishDatabaseQuery(Program\DatabaseHandle)
ProcedureReturn LastRecord.s
Else
SetGadgetText(#Gadget_Blobby_Messages, "Failed to get the last record inserted: " + DatabaseError())
EndIf
EndProcedure
; Try to open the system database and create missing tables
Procedure OpenSystemDatabase()
; Create the database if it doesn't already exist.
DbFileHandle.i = OpenFile(#PB_Any, Program\DatabaseName)
If DbFileHandle.i
CloseFile(DbFileHandle.i)
Program\DatabaseHandle = OpenDatabase(#PB_Any, Program\DatabaseName, "", "")
If Program\DatabaseHandle
; Turn on auto database vacuum
If Not DatabaseUpdate(Program\DatabaseHandle, "PRAGMA auto_vacuum = on")
SetGadgetText(#Gadget_Blobby_Messages, "Could not turn on automatic wasted space vacuuming." + DatabaseError())
EndIf
; Write the Blobby table out
SqlQueryString.s = "CREATE TABLE IF NOT EXISTS Blobby("
SqlQueryString.s + "BlobData BLOB, BlobName Text, BlobPath Text, BlobSize Text, BlobDate Text, "
SqlQueryString.s + "BlobComment Text, "
SqlQueryString.s + "BlobRecord INTEGER PRIMARY KEY AUTOINCREMENT)"
If Not DatabaseUpdate(Program\DatabaseHandle, SqlQueryString.s)
SetGadgetText(#Gadget_Blobby_Messages, "Could not add missing tables to blobtest database." + DatabaseError())
EndIf
; We had a problem getting the database handle
Else
MessageRequester("Database open error", "Error attempting to connect to system database.", #PB_MessageRequester_Ok)
EndIf
Else
MessageRequester("Database open error", "Could not open or create raw database file.", #PB_MessageRequester_Ok)
EndIf
EndProcedure
; AND51's correct file size calculation code
Procedure.s ByteCalc(Byte.q, NbDecimals = 2)
Protected Unit.b = Round(Log(Byte) / Log(1024), 0)
ProcedureReturn StrD(Byte / Pow(1024, Unit), NbDecimals * (Unit & 1)) + " " + StringField("Byte,KB,MB,GB,TB,PB,EB", Unit + 1, ",")
EndProcedure
; Fade the window out gently, close it and reset the mutex
Procedure CloseMyWindow(WindowId.i)
; Close the requested form window if it is not the master window
If WindowId.i <> #Window_Blobby
; Close the specified window
CloseWindow(WindowId.i)
; Re-enable main window
DisableWindow(#Window_Blobby, 0)
; Set focus on main window
SetActiveWindow(#Window_Blobby)
; Activate the item list
SetActiveGadget(#Gadget_Blobby_BlobList)
; Go to the previously selected line
LastLine(#Gadget_Blobby_BlobList, Program\CurrentLine)
; Activate the previously selected line
SetGadgetState(#Gadget_Blobby_BlobList, Program\CurrentLine)
; Trigger a change event on the selected line
SetGadgetItemState(#Gadget_Blobby_BlobList, Program\CurrentLine, #PB_ListIcon_Selected)
; Clean up all loose variables
Program\MutexVal = 0 ; Make sure other windows can open now
Program\CurrentLine = -1 ; Make sure no line can be selected accidentally
Program\CurrentRecord = "" ; Nullify the current record number to avoid mistakes
Program\LastWindow = "" ; Clear last used windows state
Program\NewPictureName = "" ; Clear the new picture name on any exit
Program\OldPictureName = "" ; Clear the old picture name on any exit
EndIf
EndProcedure
; Kill double quotes in strings for display purposes
Procedure.s KillQuote(Instring.s)
ProcedureReturn ReplaceString(Instring.s, "''", "'", 1, 1)
EndProcedure
; Go to the last line of a ListIconGadget
Procedure LastLine(Gadget.i, LineNumber.i)
; Make sure the current line is visible
SendMessage_(GadgetID(Gadget.i), #LVM_ENSUREVISIBLE, LineNumber.i, 0)
EndProcedure
; Uncle Berikco's routine to properly replace single quotes with double for SQL passing
Procedure.s RepQuote(Instring.s)
For i = 1 To Len(Instring.s)
If Mid(Instring.s, i, 1) = "'"
TemporaryString.s = TemporaryString.s + "''"
Else
TemporaryString.s = TemporaryString.s + Mid(Instring.s, i, 1)
EndIf
Next i
ProcedureReturn TemporaryString.s
EndProcedure
; Show the picture for a selected record
Procedure DisplayPictureMainForm()
; Get the currently selected line
Program\CurrentLine = GetGadgetState(#Gadget_Blobby_BlobList)
; Only proceed if there is a current line
If Program\CurrentLine <> -1
; Get the record number from the selected line
Program\CurrentRecord = GetGadgetItemText(#Gadget_Blobby_BlobList, Program\CurrentLine, 1)
; Only proceed if there was a valid record number
If Program\CurrentRecord
SqlQueryString.s = "SELECT BlobData, BlobComment FROM Blobby WHERE BlobRecord = '" + Program\CurrentRecord + "'"
If DatabaseQuery(Program\DatabaseHandle, SqlQueryString.s)
While NextDatabaseRow(Program\DatabaseHandle)
BlobImageSize.i = DatabaseColumnSize(Program\DatabaseHandle, 0)
If BlobImageSize.i
*BlobbyBuffer = AllocateMemory(BlobImageSize)
If *BlobbyBuffer
If GetDatabaseBlob(Program\DatabaseHandle, 0, *BlobbyBuffer, BlobImageSize.i)
ImageNumber.i = CatchImage(#PB_Any, *BlobbyBuffer)
If ImageNumber.i
ResizeImage(ImageNumber.i, Program\ImageWidth, Program\ImageHeight, #PB_Image_Smooth)
SetGadgetState(#Gadget_Blobby_Picture, ImageID(ImageNumber.i))
SetGadgetText(#Gadget_Blobby_Details, KillQuote(GetDatabaseString(Program\DatabaseHandle, 1)))
Else
SetGadgetText(#Gadget_Blobby_Messages, "Did not get a valid image handle to display this picture")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not retrieve the blob data from the database")
EndIf
FreeMemory(*BlobbyBuffer)
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not allocate a buffer for the blob data")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "There is no image data stored in that recprd")
EndIf
Wend
FinishDatabaseQuery(Program\DatabaseHandle)
Else
SetGadgetText(#Gadget_Blobby_Messages, "The database query failed: " + DatabaseError())
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not get a record number from the first line")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "No active line selected")
EndIf
EndProcedure
; Load and display all pictures in the database
Procedure ListPicturesMainForm()
SqlQueryString.s = "SELECT * FROM Blobby"
If DatabaseQuery(Program\DatabaseHandle, SqlQueryString.s)
While NextDatabaseRow(Program\DatabaseHandle)
; BlobData.s = ?
BlobName.s = KillQuote(GetDatabaseString(Program\DatabaseHandle, 1))
BlobPath.s = KillQuote(GetDatabaseString(Program\DatabaseHandle, 2))
BlobSize.s = GetDatabaseString(Program\DatabaseHandle, 3)
BlobDate.s = GetDatabaseString(Program\DatabaseHandle, 4)
BlobComment.s = GetDatabaseString(Program\DatabaseHandle, 5)
BlobRecord.s = GetDatabaseString(Program\DatabaseHandle, 6)
AddGadgetItem(#Gadget_Blobby_BlobList, -1, BlobName.s + Chr(10) + BlobRecord.s, ImageID(#Image_Blobby_BlobList))
Wend
FinishDatabaseQuery(Program\DatabaseHandle)
EndIf
If CountGadgetItems(#Gadget_Blobby_BlobList) <> 0
SetActiveGadget(#Gadget_Blobby_BlobList)
SetGadgetState(#Gadget_Blobby_BlobList, 0)
Else
SetGadgetText(#Gadget_Blobby_Messages, "No items in the list to display pictures for")
EndIf
EndProcedure
; Add a new picture to the database
Procedure AddPictureWindow()
If Program\MutexVal <> 1
If Window_BlobbyData()
Program\MutexVal = 1
DisableWindow(#Window_Blobby, 1)
; Get the last record number in the database and give the next probable record number
NextRecord.i = Val(LastRecord("BlobRecord", "Blobby")) + 1
; Setup the common window message
Message.s = "Add New BlobTest Entry"
Program\LastWindow = Message.s
SetWindowTitle(#Window_BlobbyData, Message.s + " - (Record: " + Str(NextRecord.i) + " ?)")
SetGadgetText(#Gadget_BlobbyData_Mode, "Add new picture")
SetGadgetText(#Gadget_BlobbyData_Record, Str(NextRecord.i) + " ?")
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not open the blobby data window.")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "Another program window is already open, close that one first.")
EndIf
EndProcedure
; Delete a picture from the database
Procedure DeletePictureFromDatabase()
; Get the currently selected line
Program\CurrentLine = GetGadgetState(#Gadget_Blobby_BlobList)
; Only proceed if there is a current line
If Program\CurrentLine <> -1
; Get the record number from the selected line
Program\CurrentRecord = GetGadgetItemText(#Gadget_Blobby_BlobList, Program\CurrentLine, 1)
; Only proceed if there was a valid record number
If Program\CurrentRecord
SqlQueryString.s = "DELETE FROM Blobby WHERE BlobRecord = '" + Program\CurrentRecord + "'"
If DatabaseUpdate(Program\DatabaseHandle, SqlQueryString.s)
RemoveGadgetItem(#Gadget_Blobby_BlobList, Program\CurrentLine)
SetActiveGadget(#Gadget_Blobby_BlobList)
SetGadgetState(#Gadget_Blobby_BlobList, Program\CurrentLine)
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not delete the selected picture from the database")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "No record number found on the selected line.")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "No active line selected")
EndIf
EndProcedure
; Edit the currently selected picture
Procedure EditPictureWindow()
; Get the currently selected line
Program\CurrentLine = GetGadgetState(#Gadget_Blobby_BlobList)
; Only proceed if there is a current line
If Program\CurrentLine <> -1
; Get the record number from the selected line
Program\CurrentRecord = GetGadgetItemText(#Gadget_Blobby_BlobList, Program\CurrentLine, 1)
; Only proceed if there was a valid record number
If Program\CurrentRecord
If Program\MutexVal <> 1
If Window_BlobbyData()
Program\MutexVal = 1
; Setup the common window message
Message.s = "Edit Old BlobTest Entry"
Program\LastWindow = Message.s
SetWindowTitle(#Window_BlobbyData, Message.s)
SetGadgetText(#Gadget_BlobbyData_Mode, "Edit record mode")
SqlQueryString.s = "SELECT * FROM Blobby WHERE BlobRecord = '" + Program\CurrentRecord + "'"
If DatabaseQuery(Program\DatabaseHandle, SqlQueryString.s)
While NextDatabaseRow(Program\DatabaseHandle)
BlobImageSize.i = DatabaseColumnSize(Program\DatabaseHandle, 0)
If BlobImageSize.i
*BlobbyBuffer = AllocateMemory(BlobImageSize)
If *BlobbyBuffer
If GetDatabaseBlob(Program\DatabaseHandle, 0, *BlobbyBuffer, BlobImageSize.i)
ImageNumber.i = CatchImage(#PB_Any, *BlobbyBuffer)
If ImageNumber.i
ResizeImage(ImageNumber.i, Program\ImageWidth, Program\ImageHeight, #PB_Image_Smooth)
SetGadgetState(#Gadget_BlobbyData_Picture, ImageID(ImageNumber.i))
BlobName.s = KillQuote(GetDatabaseString(Program\DatabaseHandle, 1))
BlobPath.s = KillQuote(GetDatabaseString(Program\DatabaseHandle, 2))
BlobSize.s = GetDatabaseString(Program\DatabaseHandle, 3)
BlobDate.s = GetDatabaseString(Program\DatabaseHandle, 4)
BlobComment.s = KillQuote(GetDatabaseString(Program\DatabaseHandle, 5))
BlobRecord.s = GetDatabaseString(Program\DatabaseHandle, 6)
SetGadgetText(#Gadget_BlobbyData_Details, BlobComment.s)
SetGadgetText(#Gadget_BlobbyData_Record, BlobRecord.s)
Program\OldPictureName = BlobPath.s + BlobName.s
Else
SetGadgetText(#Gadget_Blobby_Messages, "Did not get a valid image handle to display this picture")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not retrieve the blob data from the database")
EndIf
FreeMemory(*BlobbyBuffer)
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not allocate a buffer for the blob data")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "There is no image data stored in that recprd")
EndIf
Wend
FinishDatabaseQuery(Program\DatabaseHandle)
Else
SetGadgetText(#Gadget_Blobby_Messages, "The database query failed: " + DatabaseError())
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not open the edit picture window")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "Another program window is already open, close that one first.")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "No record number found on the selected line.")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "No active line selected")
EndIf
EndProcedure
; Load a picture from disk into the data form
Procedure LoadPictureFromDisk()
PictureToLoad.s = OpenFileRequester("Select picture", "", "Jpeg (*.jpg *.jpeg *.jfif)|*.jpg;*.jpeg;*.jfif|Bitmap (*.bmp)|*.bmp|Targa (*.tga)|*.tga|Tiff (*.tif)|*.tif|Png (*.png)|*.png|Icon (*.ico)|*.ico|All files (*.*)|*.*", 0)
If PictureToLoad.s
ImageNumber.i = LoadImage(#PB_Any, PictureToLoad.s)
If ImageNumber.i
ResizeImage(ImageNumber.i, Program\ImageWidth, Program\ImageHeight, #PB_Image_Smooth)
SetGadgetState(#Gadget_BlobbyData_Picture, ImageID(ImageNumber.i))
Program\NewPictureName = PictureToLoad.s
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not get the image handle, nothing loaded")
Program\NewPictureName = ""
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "Nothing to load, user cancelled the process")
EndIf
EndProcedure
; Save a new or edited picture to the database
Procedure SavePictureToDatabase()
; BlobData.s The actual binary data to be stored
BlobName.s = RepQuote(GetFilePart(Program\NewPictureName))
BlobPath.s = RepQuote(GetPathPart(Program\NewPictureName))
BlobSize.s = ByteCalc(FileSize(BlobFile.s), 2)
BlobDate.s = FormatDate("%dd/%mm/%yyyy", GetFileDate(BlobFile.s, #PB_Date_Created))
BlobComment.s = RepQuote(GetGadgetText(#Gadget_BlobbyData_Details))
; Record.s Automatically generated field
Select Program\LastWindow
Case "Add New BlobTest Entry"
If Program\NewPictureName <> ""
FileIn.i = ReadFile(#PB_Any, Program\NewPictureName)
If FileIn.i
FileInSize.i = Lof(FileIn.i)
*Buffer = AllocateMemory(FileInSize.i)
If *Buffer
If ReadData(FileIn.i, *Buffer, FileInSize.i) = FileInSize.i
SetDatabaseBlob(Program\DatabaseHandle, 0, *Buffer, FileInSize.i)
SqlQueryString.s = "INSERT INTO Blobby ("
SqlQueryString.s + "BlobData, BlobName, BlobPath, BlobSize, BlobDate, BlobComment) "
SqlQueryString.s + "VALUES ("
SqlQueryString.s + "?, '" ; This is the picture data to be filled in from the buffer
SqlQueryString.s + BlobName.s + "', '"
SqlQueryString.s + BlobPath.s + "', '"
SqlQueryString.s + BlobSize.s + "', '"
SqlQueryString.s + BlobDate.s + "', '"
SqlQueryString.s + BlobComment.s + "'"
SqlQueryString.s + ")"
If DatabaseUpdate(Program\DatabaseHandle, SqlQueryString.s)
NewRecord.s = DatabaseLastInsertRowId()
If NewRecord.s
AddGadgetItem(#Gadget_Blobby_BlobList, -1, BlobName.s + Chr(10) + NewRecord.s, ImageID(#Image_Blobby_BlobList))
; New record was inserted okay
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not get the record number for this stored record???" + DatabaseError())
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "The database insertion failed: " + DatabaseError())
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not read data from designated input file")
EndIf
FreeMemory(*Buffer)
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not allocate memory to the input buffer")
EndIf
CloseFile(FileIn.i)
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not open the designated file to read from")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "Nothing to save, user didn't choose a picture")
EndIf
Case "Edit Old BlobTest Entry"
If Program\NewPictureName <> ""
FileIn.i = ReadFile(#PB_Any, Program\NewPictureName)
If FileIn.i
FileInSize.i = Lof(FileIn.i)
*Buffer = AllocateMemory(FileInSize.i)
If *Buffer
If ReadData(FileIn.i, *Buffer, FileInSize.i) = FileInSize.i
SetDatabaseBlob(Program\DatabaseHandle, 0, *Buffer, FileInSize.i)
SqlQueryString.s = "UPDATE Blobby SET "
SqlQueryString.s + "BlobData = ?, " ; This is the picture data to be filled in from the buffer
SqlQueryString.s + "BlobName = '" + BlobName.s + "', '"
SqlQueryString.s + "BlobName = '" + BlobName.s + "', '"
SqlQueryString.s + "BlobPath = '" + BlobPath.s + "', '"
SqlQueryString.s + "BlobSize = '" + BlobSize.s + "', '"
SqlQueryString.s + "BlobDate = '" + BlobDate.s + "', '"
SqlQueryString.s + "BlobComment = '" + BlobComment.s + "' "
SqlQueryString.s + "WHERE BlobRecord = '" + Program\CurrentRecord + "'"
If DatabaseUpdate(Program\DatabaseHandle, SqlQueryString.s)
SetGadgetText(#Gadget_Blobby_Messages, "The changed record was saved back to the database.")
Else
SetGadgetText(#Gadget_Blobby_Messages, "The database record update failed: " + DatabaseError())
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not read data from designated input file")
EndIf
FreeMemory(*Buffer)
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not allocate memory to the input buffer")
EndIf
CloseFile(FileIn.i)
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not open the designated file to read from")
EndIf
Else
SqlQueryString.s = "UPDATE Blobby SET "
SqlQueryString.s + "BlobComment = '" + BlobComment.s + "' "
SqlQueryString.s + "WHERE BlobRecord = '" + Program\CurrentRecord + "'"
If DatabaseUpdate(Program\DatabaseHandle, SqlQueryString.s)
SetGadgetText(#Gadget_Blobby_Messages, "The changed comment was saved back to the database.")
Else
SetGadgetText(#Gadget_Blobby_Messages, "The database comment update failed: " + DatabaseError())
EndIf
EndIf
EndSelect
CloseMyWindow(#Window_BlobbyData)
EndProcedure
; Save a picture back to disk from the database
Procedure SavePictureToDisk()
; Get the currently selected line
Program\CurrentLine = GetGadgetState(#Gadget_Blobby_BlobList)
; Only proceed if there is a current line
If Program\CurrentLine <> -1
; Get the record number from the selected line
Program\CurrentRecord = GetGadgetItemText(#Gadget_Blobby_BlobList, Program\CurrentLine, 1)
; Only proceed if there was a valid record number
If Program\CurrentRecord
SqlQueryString.s = "SELECT * FROM Blobby WHERE BlobRecord = '" + Program\CurrentRecord + "'"
If DatabaseQuery(Program\DatabaseHandle, SqlQueryString.s)
While NextDatabaseRow(Program\DatabaseHandle)
BlobImageSize.i = DatabaseColumnSize(Program\DatabaseHandle, 0)
If BlobImageSize.i
*BlobbyBuffer = AllocateMemory(BlobImageSize)
If *BlobbyBuffer
If GetDatabaseBlob(Program\DatabaseHandle, 0, *BlobbyBuffer, BlobImageSize.i)
BlobColumnSize.i = DatabaseColumnSize(Program\DatabaseHandle, 0)
BlobName.s = KillQuote(GetDatabaseString(Program\DatabaseHandle, 1))
BlobPath.s = KillQuote(GetDatabaseString(Program\DatabaseHandle, 2))
BlobSize.s = GetDatabaseString(Program\DatabaseHandle, 3)
BlobDate.s = GetDatabaseString(Program\DatabaseHandle, 4)
BlobComment.s = KillQuote(GetDatabaseString(Program\DatabaseHandle, 5))
BlobRecord.s = GetDatabaseString(Program\DatabaseHandle, 6)
BlobFileId.i = CreateFile(#PB_Any, Program\CurrentDir + BlobName.s)
If BlobFileId.i
WriteData(BlobFileId.i, *BlobbyBuffer, BlobColumnSize.i)
SetGadgetText(#Gadget_Blobby_Messages, "We saved: " + BlobName.s + " to disk")
CloseFile(BlobFileId.i)
Else
SetGadgetText(#Gadget_Blobby_Messages, "We didn't get the image back from the blob buffer")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not retrieve the blob data from the database")
EndIf
FreeMemory(*BlobbyBuffer)
Else
SetGadgetText(#Gadget_Blobby_Messages, "Could not allocate a buffer for the blob data")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "There is no image data stored in that record")
EndIf
Wend
FinishDatabaseQuery(Program\DatabaseHandle)
Else
SetGadgetText(#Gadget_Blobby_Messages, "The database query failed: " + DatabaseError())
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "No record number found on the selected line.")
EndIf
Else
SetGadgetText(#Gadget_Blobby_Messages, "No active line selected")
EndIf
EndProcedure
; Main program event handler
If Window_Blobby()
Program\QuitFlag = 0
OpenSystemDatabase()
ListPicturesMainForm()
SetGadgetText(#Gadget_Blobby_Messages, "Hello, Blobby is ready to work!")
Repeat
EventID = WaitWindowEvent()
MenuID = EventMenu()
GadgetID = EventGadget()
WindowID = EventWindow()
Select EventID
Case #PB_Event_CloseWindow
Select WindowID
Case #Window_Blobby : Program\QuitFlag = 1
Case #Window_BlobbyData : CloseMyWindow(#Window_BlobbyData)
EndSelect
Case #PB_Event_Gadget
Select GadgetID
Case #Gadget_Blobby_BlobList
Select EventType()
Case #PB_EventType_LeftDoubleClick : EditPictureWindow()
Case #PB_EventType_RightDoubleClick : AddPictureWindow()
Case #PB_EventType_Change : DisplayPictureMainForm()
EndSelect
; Main form controls
Case #Gadget_Blobby_Add : AddPictureWindow()
Case #Gadget_Blobby_Delete : DeletePictureFromDatabase()
Case #Gadget_Blobby_Edit : EditPictureWindow()
Case #Gadget_Blobby_Save : SavePictureToDisk()
Case #Gadget_Blobby_Exit : Program\QuitFlag = 1
; Data form controls
Case #Gadget_BlobbyData_Save : SavePictureToDatabase()
Case #Gadget_BlobbyData_Camera : LoadPictureFromDisk()
Case #Gadget_BlobbyData_Exit : CloseMyWindow(#Window_BlobbyData)
EndSelect
EndSelect
Until Program\QuitFlag
CloseWindow(#Window_Blobby)
EndIf
End