Cursussen/Courses Codesnippets     Top 
B4A-database - Database manager


1. App description
In this tutorial you can learn how to make a database manager app in B4A.
The app uses 2 B4XTables, one for the data from the selected table and one for the table structure of the selected table.
With the hamburger menu or by swiping from the left edge of the screen you can open the drawer. The drawer contains all the file names from the import folder. Clicking or tapping on one imports the database and makes it the active database.
The table names of the active database are loaded in the B4XComboBox.
Selecting a table fills the B4XTable below the B4XComboBox with the data from that table.
If you click or tap on the switch at the bottom middle of the screen the second B4XTable becomes visible and shows the table structure.
You can change the contents of one field (except for the blob or graphic type of fields).
You can add a record to the table (no type checking though).
You can remove a record from the table by clicking or tapping on the rowid cell.
Below you can see some screenshots of how it will look like once assembled.
B4XTable1 - B4XDrawer - B4XComboBox:
B4XTable2 - B4XDialog - B4XDialog:
BLOB - B4XDialog - Messagebox:
CustomListViews:


2. Layouts
The following layouts are used to display information.
In the MainPage_layout the B4XTables are in the same place. In the code the visible property of the B4XTables is changed when needed.
The CustomListView (clv1) from the drawer_layout contains the database file names.
The ScrollView from the adddialog_layout will be filled with Labels en EditText fields in the code.
In the exportdialog_layout the B4XFloatTextField contains the database file name to be exported.
In the changedialog_layout the B4XFloatTextField contains the data to be changed.
In the photodialog_layout the ImageView will be filled with the bitmap from the database blob or graphic field if the data can be converted to a bitmap.
In the folders_layout the CustomListViews contain the database file names from the import or export folder.


3. Initializations
The app uses the following libraries:
The declarations of the variables and the initializations are coded in the Class_Globals and B4XPage_Created subroutines.
A menu item is created for the B4XPage FoldersPage.
Sub Class_Globals
	Private Root As B4XView
	Private xui As XUI
	Private db As database
	Private B4XTbl1 As B4XTable
	Private rtpermissions As RuntimePermissions
	Public exportfolder As String
	Public importfolder As String
	Public databasename As String
	Private drawer As B4XDrawer
	Private clv1 As CustomListView
	Private HamburgerIcon As B4XBitmap
	Public tablename As String
	Private changedialog As B4XDialog
	Private ftf1 As B4XFloatTextField
	Private rowCol As B4XTableColumn
	Public adddialog As B4XDialog
	Public newdbname As String
	Private exportdialog As B4XDialog
	Private ftfexportdb As B4XFloatTextField
	Private Panel2 As Panel
	Private btnadd As Button
	Private cbxtables As B4XComboBox
	Private btnexport As Button
	Private svadd As ScrollView
	Private folpage As FoldersPage
	Private B4XTbl2 As B4XTable
	Private Switch1 As Switch
	Private photodialog As B4XDialog
	Private ivphotodialog As ImageView
End Sub
Public Sub Initialize
	B4XPages.GetManager.LogEvents = True
End Sub
Private Sub B4XPage_Created (Root1 As B4XView)
	Root = Root1
	Root.LoadLayout("MainPage_layout")
	B4XPages.SetTitle(Me,"Database manager")
	folpage.Initialize
	B4XPages.AddPage("Folders",folpage)
	menuitem_add(Me, "Folders")
	' drawer
	drawer.Initialize(Me,"Drawer",Root,240dip)
	drawer.CenterPanel.LoadLayout("MainPage_layout")
	drawer.LeftPanel.LoadLayout("drawer_layout")
	drawer.LeftPanel.Height = 460dip
	clv1.sv.Height = 430dip
	HamburgerIcon = xui.LoadBitmapResize(File.DirAssets, "hamburger.png", 32dip, 32dip, True)
	' folders
	exportfolder = rtpermissions.GetSafeDirDefaultExternal("Export")
	importfolder = rtpermissions.GetSafeDirDefaultExternal("Import")
	' dialogs
	changedialog.Initialize(Root)
	changedialog.PutAtTop = True
	changedialog.BackgroundColor = Colors.LightGray
	changedialog.BodyTextColor = Colors.Blue
	adddialog.Initialize(Root)
	adddialog.PutAtTop = True
	adddialog.BackgroundColor = Colors.White
	exportdialog.Initialize(Root)
	exportdialog.PutAtTop = True
	exportdialog.BackgroundColor = Colors.White
	photodialog.Initialize(Root)
	photodialog.PutAtTop = True
	photodialog.BackgroundColor = Colors.White
End Sub
Private Sub menuitem_add(objpage As Object, itemname As String)
	Private mnuitem As B4AMenuItem = B4XPages.AddMenuItem(objpage,itemname)
	If itemname = "Folders" Then
		mnuitem.Bitmap = xui.LoadBitmap(File.DirAssets,"folders_icon_yellow.png")
	End If
	mnuitem.AddToBar = True
End Sub
Sub B4XPage_MenuClick (Tag As String)
	B4XPages.ShowPage(Tag)
End Sub


4. B4XDrawer
In the B4XPage_Appear subroutine the hamburger menu is set and a call is made to the fill_drawer subroutine.
Private Sub B4XPage_Appear
	B4XPages.GetManager.ActionBar.RunMethod("setDisplayHomeAsUpEnabled", Array(True))
	Dim bd As BitmapDrawable
	bd.Initialize(HamburgerIcon)
	B4XPages.GetManager.ActionBar.RunMethod("setHomeAsUpIndicator", Array(bd))
	B4XTbl1.mBase.Visible = False
	Panel2.Visible = False
	fill_drawer
	If clv1.Size > 0 Then
		clv1_ItemClick (0, clv1.GetValue(0))
	End If
End Sub
In the fill_drawer subroutine the list of database file names is filled.
Private Sub fill_drawer
	clv1.Clear
	Private lst As List = File.ListFiles(importfolder)
	For i = 0 To lst.Size -1
		Dim pnl As Panel = drawer_item(lst.Get(i))
		clv1.Add(pnl,lst.Get(i))
		'clv1.AddTextItem(lst.Get(i),lst.Get(i))
	Next
End Sub
Private Sub drawer_item(drname As String) As Panel
	Dim pnl As Panel
	pnl.Initialize("")
	pnl.Width = 220dip
	pnl.Height = 50dip
	pnl.Color = Colors.White
	Dim lbl As Label
	lbl.Initialize("lbl")
	lbl.Color = Colors.ARGB(100,255,232,132)
	lbl.Gravity = Bit.Or(Gravity.CENTER_HORIZONTAL,Gravity.CENTER_VERTICAL)
	lbl.Text = drname
	lbl.Typeface = Typeface.DEFAULT_BOLD
	lbl.Tag = "drawer"
	pnl.AddView(lbl,10dip,0dip,200dip,50dip)
	Return pnl
End Sub
Some extra code is needed for the ActionBar to open or close the drawer.
Private Sub B4XPage_Disappear
	If databasename <> "" And tablename <> "" Then
		db.export_database(databasename,exportfolder,importfolder,databasename)
	End If
	B4XPages.GetManager.ActionBar.RunMethod("setHomeAsUpIndicator", Array(0))
End Sub

Private Sub B4XPage_CloseRequest As ResumableSub
	#if B4A
	'home button
	If Main.ActionBarHomeClicked Then
		drawer.LeftOpen = Not(drawer.LeftOpen)
		Return False
	End If
	'back key
	If drawer.LeftOpen Then
		drawer.LeftOpen = False
		Return False
	End If
	#end if
	Return True
End Sub

Sub Activity_KeyPress (KeyCode As Int) As Boolean
	If KeyCode = KeyCodes.KEYCODE_BACK And drawer.LeftOpen Then
		drawer.LeftOpen = False
		Return True
	End If
	Return False
End Sub


5. B4XComboBox
When the user clicks or taps on an item in the drawer list (clv1) then the B4XComboBox with the table names from the selected database is filled.
The database is set as the current database and is initialized.
Private Sub clv1_ItemClick (Index As Int, Value As Object)	' drawer list
	Panel2.Visible = True
	B4XTbl1.mBase.Visible = True
	databasename = Value
	db.import_database(databasename,importfolder)
	set_current_db(databasename)
	B4XPages.SetTitle(Me,"DB: " & databasename)
	fill_cbxtables
End Sub
Private Sub fill_cbxtables
	Private lst As List = db.get_tablenames
	cbxtables.SetItems(lst)
	B4XTbl1.Clear
	If lst.Size > 0 Then
		cbxtables.SelectedIndex = 0
		tablename = cbxtables.SelectedItem
		Panel2.Visible = True
		B4XTbl1.mBase.Visible = True
		fill_B4XTable
	End If
End Sub
Private Sub cbxtables_SelectedIndexChanged (Index As Int)
	If databasename <> "" And tablename <> "" Then
		db.export_database(databasename,exportfolder,importfolder,databasename)
	End If
	tablename = cbxtables.SelectedItem
	fill_B4XTable
End Sub
Private Sub set_current_db(dbname As String)
	databasename = dbname
	db.Initialize("database_manager",databasename,True,False)
	B4XPages.SetTitle(Me,"DB manager " & databasename)
End Sub


6. B4XTables
After the B4XComboBox is filled the first item in the list is selected and the first B4XTable is filled with the data from the selected table.
The B4XTable uses the field names list and field types list from the database class (see next chapter).
The first column width is set to 75dip. This column contains the rowid.
The column types are all set to COLUMN_TYPE_TEXT to keep it simple. Feel free to adjust the code to accommodate for the different data types.
The field data from the type BLOB and GRAPHIC are not used. The data type text is inserted in the cell.
When the user clicks or taps on the switch at the bottom of the screen (yellow panel) then the show_structure subroutine is called. The second B4XTable is filled with the table structure from the selected table. The get_structure method from the database class is used.
Private Sub fill_B4XTable
	B4XTbl1.mBase.Visible = True
	B4XTbl2.mBase.Visible = False
	Switch1.Checked = False
	B4XTbl1.Clear
	Private fldlst As List = db.get_fieldnames(tablename)
	Private typeslst As List = db.get_fieldtypes(tablename)
	For i = 0 To fldlst.Size - 1
		If i = 0 Then
			rowCol = B4XTbl1.AddColumn(fldlst.Get(i), B4XTbl1.COLUMN_TYPE_TEXT)
			rowCol.Width = 75dip
		Else
			B4XTbl1.AddColumn(fldlst.Get(i), B4XTbl1.COLUMN_TYPE_TEXT)
		End If
	Next
	Private data As List
	data.Initialize
	Private rs1 As ResultSet = db.select_all_records(tablename,"")
	Do While rs1.NextRow	
		Dim rec As List
		rec.Initialize
		For i = 0 To fldlst.Size -1
			If typeslst.Get(i) <> "BLOB" And typeslst.Get(i) <> "GRAPHIC" Then
				'Log(typeslst.Get(i))
				rec.Add(rs1.GetString2(i))
			Else
				rec.Add(typeslst.Get(i))
			End If
		Next
		'Log(rec)
		data.Add(rec)
	Loop
	'Log(data)
	B4XTbl1.SetData(data)
	B4XTbl1.NumberOfFrozenColumns = 1
End Sub
Private Sub Switch1_CheckedChange(Checked As Boolean)
	If Checked Then
		show_structure
	Else
		fill_B4XTable
	End If
End Sub
Private Sub show_structure
	B4XTbl1.mBase.Visible = False
	B4XTbl2.mBase.Visible = True	
	B4XTbl2.Clear
	rowCol = B4XTbl2.AddColumn("cid", B4XTbl2.COLUMN_TYPE_TEXT)
	rowCol.Width = 75dip
	B4XTbl2.AddColumn("name", B4XTbl2.COLUMN_TYPE_TEXT)
	B4XTbl2.AddColumn("type", B4XTbl2.COLUMN_TYPE_TEXT)
	Private data As List
	data.Initialize
	Private rs1 As ResultSet = db.get_structure(tablename)
	Do While rs1.NextRow
		Dim rec As List
		rec.Initialize
		rec.Add(rs1.GetString("cid"))
		rec.Add(rs1.GetString("name"))
		rec.Add(rs1.GetString("type"))
		'Log(rec)
		data.Add(rec)
	Loop
	Log(data)
	B4XTbl2.SetData(data)
End Sub


7. B4XDialogs
When the user clicks or taps on the bottom left button with the + sign the show_adddialog subroutine is called.
Private Sub btnadd_Click
	If tablename <> "" Then
		show_adddialog
	End If
End Sub
For each field a panel with a fieldname Label and an EditText view is set up.
Then these panels are added to the ScrollView (svadd).
private Sub show_adddialog
	Dim pnl1 As Panel = setup_adddialog("adddialog_layout")
	Dim rsub1 As ResumableSub =  adddialog.ShowCustom(pnl1, "OK", "", "CANCEL")
	Wait For (rsub1) Complete (Result As Int)
	If Result = xui.dialogResponse_Positive Then
		' views van pnl1 met tags "edt_" & i overlopen en in valuelist stoppen
		Dim valuelst As List
		valuelst.Initialize
		For Each vw As View In pnl1.GetAllViewsRecursive
			Dim tg As String = vw.Tag
			If tg.StartsWith("edt_") Then
				valuelst.Add(vw.As(EditText).Text)
			End If
		Next
		Log(valuelst)
		If valuelst.Get(0) <> "" Then
			db.add_record(tablename, valuelst)
			db.export_database(databasename,exportfolder,importfolder,databasename)
			fill_B4XTable
		End If
	End If
End Sub
private Sub setup_adddialog(strlayout As String) As Panel
	Dim pnl As B4XView = xui.CreatePanel("")
	pnl.SetLayoutAnimated(0dip, 0dip, 0dip, 340dip, 200dip)
	pnl.LoadLayout(strlayout)
	pnl.RemoveAllViews
	Dim lbl As Label = set_label("Add record to " & tablename,Colors.ARGB(100,255,232,132),"",18)
	pnl.AddView(lbl,0dip,0dip,340dip,30dip)
	svadd.RemoveView
	Dim lst As List = db.get_fieldnames(tablename)
	For i = 1 To lst.Size - 1
		Dim edt As EditText
		edt.Initialize("")
		edt.Tag = "edt_" & i
		Dim p1 As Panel = set_field_panel(lst.Get(i),edt,60dip)
		svadd.panel.AddView(p1,0dip,(i-1)*80dip,340dip,80dip)
	Next
	svadd.Panel.Height = (lst.Size-1)*80dip + 300dip				'1000dip
	svadd.Panel.Color = Colors.ARGB(100,249,249,221)
	svadd.Color = Colors.ARGB(100,249,249,221)
	pnl.AddView(svadd,0dip,30dip,340dip,400dip)
	Return pnl
End Sub
Private Sub set_field_panel(fldname As String, e1 As EditText,fldheight As Int) As Panel
	Dim fldpnl As Panel
	fldpnl.Initialize("")
	Dim lblhint As Label = set_label(fldname,Colors.ARGB(100,255,255,97),"",12)
	fldpnl.AddView(lblhint,0dip,0dip,170dip,20dip)
	e1.Color = Colors.White
	fldpnl.AddView(e1,0dip,20dip,340dip,fldheight)
	Dim l1 As Label = set_label("",Colors.Black,"",1)
	fldpnl.AddView(l1,0dip,20dip+fldheight-1,340dip,1dip)
	fldpnl.Color = Colors.ARGB(100,249,249,203)
	Return fldpnl
End Sub
private Sub set_label(lbltext As String, intbackground As Int, lbltag As String, txtsize As Int) As Label
	Private lbl As Label
	lbl.Initialize(lbltag)
	lbl.Background = set_background(intbackground)
	lbl.Typeface = Typeface.DEFAULT_BOLD
	lbl.TextSize = txtsize
	lbl.Text = lbltext
	lbl.Gravity = Bit.Or(Gravity.LEFT,Gravity.TOP)
	lbl.Padding = Array As Int (5dip, 0dip, 3dip, 0dip)
	Return lbl
End Sub
Private Sub set_background(intcolor As Int) As StateListDrawable
	Private cd,cd2 As ColorDrawable
	Private sd As StateListDrawable
	cd.Initialize2(intcolor,5,1,Colors.Black)
	cd2.Initialize2(Colors.Red,5,1,Colors.Black)
	sd.Initialize
	sd.AddState(sd.State_Pressed,cd2)
	sd.AddState(sd.State_Enabled,cd)
	Return sd
End Sub
When the user clicks or taps on the export button (the button in the bottom right corner of the screen) then the show_exportdialog subroutine is called.
Private Sub btnexport_Click
	show_exportdialog
End Sub
private Sub show_exportdialog
	Dim pnl As B4XView = xui.CreatePanel("")
	pnl.SetLayoutAnimated(0, 0, 0, 340dip, 150dip)
	pnl.LoadLayout("exportdialog_layout")
	Dim rs As ResumableSub =  exportdialog.ShowCustom(pnl, "OK", "", "CANCEL")
	ftfexportdb.Text = databasename
	Wait For (rs) Complete (Result As Int)
	If Result = xui.DialogResponse_Positive Then
		Log(ftfexportdb.Text)
		If ftfexportdb.Text <> "" Then
			db.export_database(databasename,exportfolder,importfolder,ftfexportdb.Text)
		End If
	End If
End Sub
When the user clicks or taps on a cell in the B4XTable then one of 3 B4XDialogs can be called.
If the cell is part of the first column (rowid) then the show_remove_dialog is called.
If the cell is part of a column that has a BLOB or GRAPHIC type indication then the show_photodialog is called.
In all other cases the show_change_dialog is called.
Private Sub B4XTbl1_CellClicked (ColumnId As String, RowId As Long)
	Dim RowData As Map = B4XTbl1.GetRow(RowId)
	Dim cell As String = RowData.Get(ColumnId)
	Dim recid As Int = RowData.Get("rowid")
	'Log(cell)
	Dim fname As String = ColumnId
	fname = fname.SubString2(1,fname.Length-1)	' remove []
	Log(fname)
	If ColumnId <> "rowid" Then
		'Log(recid)
		If cell <> "BLOB" And cell <> "GRAPHIC" Then
			show_change_dialog(recid,fname)
		Else
			show_photodialog(recid,fname)
		End If
	Else
		'Log(recid)
		show_remove_dialog(recid)
	End If
End Sub
Private Sub show_change_dialog(rowid As Int, colid As String)
	'Dim fldlst As List = db.get_fieldnames(tablename)
	Dim pnl1 As Panel = setup_dialog("changedialog_layout"," Edit " & tablename & " rowid=" & rowid, Colors.ARGB(100,255,232,132))
	Dim rsub1 As ResumableSub =  changedialog.ShowCustom(pnl1, "SAVE", "", "CANCEL")
	Private rs1  As ResultSet = db.find_record(tablename,rowid)
	If rs1.NextRow Then
		ftf1.Text = rs1.GetString(colid)
	End If
	ftf1.HintText = colid
	ftf1.Update
	Wait For (rsub1) Complete (Result As Int)
	If Result = xui.dialogResponse_Positive Then
		If ftf1.Text <> "" Then
			db.change_field_content(tablename, Array As String(ftf1.Text),rowid,colid)
			db.export_database(databasename,exportfolder,importfolder,databasename)
			fill_B4XTable
		End If
	End If
End Sub
Private Sub show_remove_dialog(rowid As Int)
	'Dim fldlst As List = db.get_fieldnames(tablename)
	Dim pnl1 As Panel = setup_dialog("changedialog_layout"," Remove " & tablename & " rowid=" & rowid, Colors.ARGB(100,255,153,153))
	Dim rsub1 As ResumableSub =  changedialog.ShowCustom(pnl1, "YES", "NO", "CANCEL")
	Private rs1  As ResultSet = db.find_record(tablename,rowid)
	If rs1.NextRow Then
		ftf1.Text = rs1.GetString2(1)
	End If
	ftf1.HintText = ""
	ftf1.Update
	Wait For (rsub1) Complete (Result As Int)
	If Result = xui.dialogResponse_Positive Then
		If ftf1.Text <> "" Then
			db.remove_record(tablename,rowid)
			db.export_database(databasename,exportfolder,importfolder,databasename)
			fill_B4XTable
		End If
	End If
End Sub
private Sub setup_dialog(strlayout As String,lbltext As String,lblcolor As Int) As Panel
	Dim pnl As B4XView = xui.CreatePanel("")
	pnl.SetLayoutAnimated(0, 0, 0, 340dip, 200dip)
	pnl.LoadLayout(strlayout)
	Dim lbl As Label
	lbl.Initialize("")
	lbl.Text = lbltext
	lbl.TextSize = 18
	lbl.TextColor = Colors.Black
	lbl.Color = lblcolor
	pnl.AddView(lbl,0,0dip,340dip,50dip)
	Return pnl
End Sub
The show_photodialog tries to display the BLOB or GRAPHIC that is in the database.
The sample code in the comments changes the content of a BLOB field in the database (EDIT: Android version)
That image can be displayed where others can not.
You can do some tests with the demo database that comes with the SQLite Expert Personal windows program.
EDIT: you can test the content of the blob by using a Hex dump of the buffer. Add the ByteConverter library.
If the Hex string contains certain hex-values than you can determine which image format it is and at which offset to read the buffer. Initialize the inputstream accordingly.
You can find the Hex strings to use for testing in this list: Wikipedia: list of file signatures.
Now only one problem left to solve: the GRAPHIC field type doesn't show in the photodialog.
private Sub show_photodialog(rowid As Int,colid As String)
	Dim pnl As B4XView = xui.CreatePanel("")
	pnl.SetLayoutAnimated(0dip, 0dip, 0dip, 340dip, 500dip)
	pnl.LoadLayout("photodialog_layout")
	pnl.RemoveAllViews
	' get BLOB from database
	Dim rs As ResultSet = db.find_record(tablename,rowid)
	rs.NextRow
	Try
		Log(rs.GetString("rowid"))
		Log(rowid)
		Log(colid)
		' saving an example image to the database
'		ivphotodialog.Bitmap = LoadBitmapResize(exportfolder,"angelfish.jpg",300dip,300dip,True)
'		Dim bmp As Bitmap = ivphotodialog.Bitmap
'		Dim OutputStream1 As OutputStream
'		OutputStream1.InitializeToBytesArray(1000)
'		bmp.WriteToStream(OutputStream1, 90, "JPEG")
'		Dim Buffer() As Byte = OutputStream1.ToBytesArray
'		db.change_field_content(tablename,Array As Object(Buffer),rowid,colid)
		'
		Dim Buffer() As Byte  = rs.GetBlob(colid)
		Log(Buffer.Length)
		Dim bc As ByteConverter
		Dim hex As String = bc.HexFromBytes(Buffer)
		Log(hex)
		Dim InputStream1 As InputStream
		If hex.Contains("FFD8FF") Then		' jpg, jpeg
			InputStream1.InitializeFromBytesArray(Buffer, 0, Buffer.Length)
		End If
		If hex.Contains("424D") Then		' bmp
			InputStream1.InitializeFromBytesArray(Buffer, 8, Buffer.Length)
		End If
		If hex.Contains("47494638") Then	' gif
			InputStream1.InitializeFromBytesArray(Buffer, 0, Buffer.Length)
		End If
		If hex.Contains("4D4D002A") Or hex.Contains("49492A00") Then	' tiff
			InputStream1.InitializeFromBytesArray(Buffer, 0, Buffer.Length)
		End If
		If hex.Contains("89504E470D0A1A0A") Then	' png
			InputStream1.InitializeFromBytesArray(Buffer, 0, Buffer.Length)
		End If
		Dim bmp As Bitmap
		bmp.Initialize2(InputStream1)
		InputStream1.Close
		ivphotodialog.Bitmap = bmp
		ivphotodialog.Gravity = Gravity.FILL
		pnl.AddView(ivphotodialog,0dip,0dip,340dip,490dip)
		Dim rsub1 As ResumableSub =  photodialog.ShowCustom(pnl, "OK", "", "")
		Wait For (rsub1) Complete (Result As Int)
		If Result = xui.dialogResponse_Positive Then
			'
		End If
	Catch
		Log(LastException)
		xui.MsgboxAsync("Can not load bitmap image","Bitmap image")
	End Try
End Sub


8. Database Folders
In the B4XPage FoldersPage the contents of the import and export folders are displayed.
If the user clicks or taps on an item in the list a delete message appears and the user can choose to delete the database file.
If you have a database file that you have exported from another app then you can copy the database file to the import folder of the database manager app. When you start the database manager app the added database is available in the drawer.
You can check the presence of the file in the import folder list of the FoldersPage.
The copying of files needs to be done with a file manager app. It should have access to the Files folder of the database manager app.
The full path in the file manager app is something like: Main storage / Android / data / b4a.database_manager / files / Import or Export folder.
Sub Class_Globals
	Private Root As B4XView 'ignore
	Private xui As XUI 'ignore
	Private db As database
	Private rtpermissions As RuntimePermissions
	Public exportfolder As String
	Public importfolder As String
	Private clv2 As CustomListView
	Private clv3 As CustomListView
End Sub
Public Sub Initialize As Object
	Return Me
End Sub
Private Sub B4XPage_Created (Root1 As B4XView)
	Root = Root1
	Root.LoadLayout("folders_layout")
	B4XPages.SetTitle(Me,"Database manager - folders")
	' folders
	exportfolder = rtpermissions.GetSafeDirDefaultExternal("Export")
	importfolder = rtpermissions.GetSafeDirDefaultExternal("Import")
	' database
	db.Initialize("database_manager",B4XPages.MainPage.databasename,True,False)
End Sub

Private Sub B4XPage_Appear
	fill_clv2
	fill_clv3
End Sub

Private Sub fill_clv2
	clv2.Clear
	Private lst As List = File.ListFiles(importfolder)
	For i = 0 To lst.Size -1
		clv2.AddTextItem(lst.Get(i),lst.Get(i))
	Next
End Sub
Private Sub fill_clv3
	clv3.Clear
	Private lst As List = File.ListFiles(exportfolder)
	For i = 0 To lst.Size -1
		'Dim pnl As Panel = set_clv_item(lst.Get(i))
		'clv3.Add(pnl,lst.Get(i))
		clv3.AddTextItem(lst.Get(i),lst.Get(i))
	Next
End Sub
Private Sub set_clv_item(value As String) As Panel
	Dim pnl As Panel
	pnl.Initialize("")
	pnl.Width = 320dip
	pnl.Height = 50dip
	pnl.Padding = Array As Int (5dip, 2dip, 5dip, 5dip)
	Dim lbl As Label
	lbl.Initialize("")
	lbl.Color = Colors.ARGB(100,255,232,132)
	lbl.Typeface = Typeface.DEFAULT_BOLD
	lbl.Text = value
	lbl.TextSize = 18
	lbl.Gravity = Bit.Or(Gravity.LEFT,Gravity.CENTER_VERTICAL)
	lbl.Padding = Array As Int (5dip, 0dip, 3dip, 0dip)
	pnl.AddView(lbl,3dip,0dip,300dip,50dip)
	Return pnl
End Sub

Private Sub clv2_ItemClick (Index As Int, Value As Object)
	If File.Exists(importfolder,Value) Then
		Dim conf As Object = xui.Msgbox2Async("Delete file " & Value & CRLF & "Are you sure?","Import folder - delete file","Yes","Cancel","No",Null)
		Wait For (conf) Msgbox_Result (Result As Int)
		If Result = xui.DialogResponse_Positive Then
			File.Delete(importfolder,Value)
			fill_clv2
		End If
	End If

End Sub

Private Sub clv3_ItemClick (Index As Int, Value As Object)
	If File.Exists(exportfolder,Value) Then
		Dim conf As Object = xui.Msgbox2Async("Delete file " & Value & CRLF & "Are you sure?","Export folder - delete file","Yes","Cancel","No",Null)
		Wait For (conf) Msgbox_Result (Result As Int)
		If Result = xui.DialogResponse_Positive Then
			File.Delete(exportfolder,Value)
			fill_clv3
		End If
	End If
End Sub