B4J pmfiles: a file explorer example using a treeview, breadcrumbs and various viewers

PaulMeuris

Active Member
Licensed User
This application is getting better and better... check out the latest update...
Version 6 (+extract zip-files and full-screen image paging): in message #10
Version 5 (+SQLite database support): in message #9
Version 4 (+full-screen mode): in message #8
Version 3 (+MediaView controller and PDF controls): in message #7
Version 2 (+ MSOffice files convert to PDF): in message #6
Version 1 (+ webpage and file info list): in message #3
Check out the latest version!


With this application you can explore your drives, folders and files.
1718937977031.png

With the B4XComboBox on the top left you can select a drive letter. The list gets updated every time you change it.
This means that you can add a USB device that gets a drive letter (a smartphone doesn't get a drive letter by default).
After you select a different drive letter from the existing list the new drive letter will appear in the list.
The Treeview will contain a list of the top level folders and files and their sub folders and files.
The filling of the Treeview doesn't go over all the sub folders and its files (using recursive subroutine) because that takes to much time to load.
When you click on a folder the next levels are loaded for that folder. Clicking on a file in an expanded sub folder will fill the Treeview with its parents folders and files.
The search text field will allow you to quickly open a sub folder that starts with the entered letters.
You can use the breadcrumbs to navigate to a previously opened folder or drive.
The blue label shows the file attributes and name of the selected file (in the Treeview). The DOS attrib command is used for this.
If you click on the info button then a message is displayed showing the file details. The wmic command is used for this. (It should still work in Windows 10 and 11)
And here's the code to select a file viewer:
B4X:
    Try
        Select ext.ToLowerCase
            Case "mp3","mp4","wav"
                show_mv1
                play_sound(fpath,fname)
            Case "jpg","png","jpeg","gif","bmp"
                Dim im As Image
                im.Initialize(fpath,fname)
                show_ziv1
                ziv1.SetBitmap(im)
                Dim imleft As Int = 10
                Dim imtop As Int = 10
                If im.Width < 150 Then imleft = 200
                If im.Height < 150 Then imtop = 200
                If im.Width < 150 And im.Height < 150 Then
                    ziv1.ImageView.SetLayoutAnimated(0,imleft,imtop,im.Width,im.Height)           
                End If
                btnrotate.Tag = filename
                btnsize.Tag = filename
            Case "pdf"
    '            show_sp1
                show_sppagepdf
                pdffile = item.Trim
                initpage
                renderpage(1)
    '            renderallpages
            Case "txt","log","ini","bat","csv","meta"
                show_ta1
                Dim strtext As String = File.ReadString(fpath.Trim,fname.Trim)
                ta1.Text = strtext
                btnsave.Tag = filename
'            Case "htm","html"
'                show_wv1
'                Dim strtext As String = File.ReadString(fpath.Trim,fname.Trim)
'                wv1.LoadHtml(strtext)
'                wv1.Zoom = 0.8
            Case "html","htm","css","js","bas","b4a","b4i","b4j","vb","php","xml","json","sql","java","vbs","ps1"
                show_wv1
                Dim strtext As String = File.ReadString(fpath.Trim,fname.Trim)
                If strtext.IndexOf("codemirror.js") <> -1 Then
                    If strtext.IndexOf("textarea") <> -1 Then
                        strtext = strtext.Replace("textarea","div")    ' to display the codemirror settings
                        xui.MsgboxAsync("<textarea id='editor'> and </textarea> was changed to show the codemirror code!","Codemirror")
                    End If
                End If
                Dim mode As String = set_editor_mode(ext)
                Dim htmlstring As String = hclass.set_htmlpage(strtext,mode,"eclipse")
                wv1.LoadHtml(htmlstring)
                btnsave.Tag = filename
            Case "sys","exe","com","dll"
                show_ta1
                ta1.Text = CRLF & "No viewer available for this file."
            Case Else
                show_ta1
                ta1.Text = CRLF & "No viewer available for this file."
        End Select
    Catch
        Log(LastException)
        show_ta1
        ta1.Text = "There was an error accessing this file." & CRLF & _
                   "Maybe access to this file is denied." & CRLF & _
                   "Or the path and filename may include illegal characters."
    End Try
The code checks the file extension and selects a view to display the contents.
Sound and video files use a MediaView, image files use a ZoomImageView, pdf files use pdfbox code in a ScrollPane, text files use a TextArea, code files use a WebView with the CodeMirror editor and for the rest of the files you will see a message in the TextArea.
You can use the Save button on the top right to save the changes you have made in the textfiles or in the codefiles.
Be aware that changing code this way can cause problems!
The CodeMirror editor uses the mode that is most suited for the file extension.
This application uses a limited list of file extensions. You can add more if you like.
There are some "special" actions you can take on images or sound and video files. Have a look!
The pdf viewer shows the first page in the ScrollPane. If you click on the ScrollPane you can choose to open the rest of the document. Loading many pages can be a slow process.
BTW, if you build a standalone package from the application then you can run multiple instances from it: in one instance you play your favorite music, in another instance you review your photos and in yet another instance you do some code reviewing.
The source code is in the attachment.
 

Attachments

  • pmfiles.zip
    227.5 KB · Views: 88
Last edited:

PaulMeuris

Active Member
Licensed User
It would be nice to see the result of a local .html (.htm) page, right?
1718966584471.png
1718966630789.png

You can change some code and add a WebView and a Button to accomplish that.
In the show_ subroutines add the following 2 lines:
B4X:
    wv2.Visible = False
    btnweb.Visible = False
In the show_selected_file_content subroutine add the following highlighted lines:
B4X:
                wv1.LoadHtml(htmlstring)
                btnsave.Tag = filename
                If ext.ToLowerCase = "html" Or ext.ToLowerCase = "htm" Then
                    btnweb.Visible = True
                    btnweb.Text = "Webpage"
                    btnweb.Tag = filename
                Else
                    btnweb.Tag = ""
                    btnweb.Visible = False   
                End If
And at the bottom of the code add these lines:
B4X:
Private Sub btnweb_Click
    Dim btn As Button = Sender
    If btn.Text = "Close" Then
        wv2.Visible = False       
        btn.Text = "Webpage"
        Return
    End If
    If btn.Tag <> "" Then
        Dim tag As String = btn.Tag
        Dim fpath As String = tag.SubString2(0,tag.LastIndexOf("\"))
        If fpath.EndsWith(":") Then fpath = fpath & "\"
        Dim fname As String = tag.SubString(tag.LastIndexOf("\")+1)
        Dim strtext As String = File.ReadString(fpath.Trim,fname.Trim)
        wv2.Visible = True
        wv2.LoadHtml(strtext)
        wv2.Zoom = 0.8
        btn.Text = "Close"
    End If
End Sub
Make sure to put the wv2 WebView in the designer under the wv1 WebView.
1718966783714.png

And that's it.
Note: this addition only works with local html files and doesn't use a webserver.
You can have a look at my Try-it-yourself tutorial to learn how to use a local webserver.
 

PaulMeuris

Active Member
Licensed User
In this version of the application I decided to replace the file info message box with a B4Xdialog that contains a CustomListView.
This was the old look:
1719319180652.png

And this is the new look:
1719319229600.png

Everything seemed to be working fine until I ran the application in Release mode.
That’s when I encountered the first issue…
Issue number 1: using a B4Xdialog component in Release mode generates an error.
The error stated that the Asset file “Dialog.css” was not found.
1719319324599.png

I checked in the Files Manager and there it was…
1719319362506.png

So what could be causing this error?
Well as it turns out the B4Xdialog library uses a “Dialog.css” file internally. I checked the library using my B4Xsources application (look for my tutorial with that name).
1719319421966.png

BUT the file in the Files Manager belongs to the Codemirror editor (dialog.js and dialog.css).
So by renaming the dialog.css file to dialog_codemirror.css and changing the filename in the html_header subroutine from the htmlclass the issue was resolved.
1719319480466.png

On to the next challenge…
Issue number 2: the file_info.txt output from the wmic command is not in the UTF-8 character encoding
This issue was difficult to identify. It all started when I tried to use the following test (see highlighted line):
B4X:
    Dim lst As List = Regex.Split(CRLF,strinfo)
    clv1.Clear
    For i = 0 To lst.Size -1
        Dim item As String = lst.Get(i)
        Dim strkey As String = item.SubString2(0,item.IndexOf("=")).Trim
        Dim strdata As String = item.SubString(item.IndexOf("=")+1).Trim
        If item.StartsWith("CreationDate") Or item.StartsWith("InstallDate") Or item.StartsWith("LastAccessed") Or item.StartsWith("LastModified") Then
            Dim strdate As String = strdata.SubString2(0,8)
            Dim strtime As String = strdata.SubString2(8,14)
            strdata = strdate.SubString2(0,4) & "-" & strdate.SubString2(4,6) & "-" & strdate.SubString2(6,8) & _
                      " " & strtime.SubString2(0,2) & ":" & strtime.SubString2(2,4) & ":" & strtime.SubString2(4,6)
        End If
        Dim pn As Pane = set_infoitem(strkey,strdata)
        clv1.Add(pn,i)
    Next
The test result never became true even though the log texts showed that the item string does start with “CreationDate”.
Why was this happening? That’s not logical.
After a few hours of searching I found the answer. The wmic command writes the text to the file_info.txt file in a UTF-16LE character encoding.
The item string was in the UTF-16LE encoding and the literal “CreationDate” is by default in the UTF-8 encoding. Therefore the tests never became true.
First I tried to solve it with the Byteconverter library but that didn't seem to work.
And then I thought maybe I can change the character encoding from the output file (file_info.txt).
I found a thread in the StackOverflow forum that provides a solution.
B4X:
    Try
        path = path.Replace("\","\\")
        Dim sh As Shell
        If fname <> "" Then
            'https://stackoverflow.com/questions/55310573/wmic-command-in-batch-outputting-non-utf-8-text-files
            Dim strparam As String = "/C wmic datafile where Name=""" & path & fname & """ list /format:list | find /v """" >" & xui.DefaultFolder & "\file_info.txt"
        End If
        Dim args As List = Array(strparam)
        sh.InitializeDoNotHandleQuotes("shl", "cmd.exe", args)
        sh.WorkingDirectory = xui.DefaultFolder
        sh.RunSynchronous(-1)            ' the process must complete
    Catch
        Log(LastException)
        show_ta1
        ta1.Text = "There was an error accessing this file. Probably access is denied."
    End Try
Adding the pipe command and a find command before sending the result to the output file works.
So after this change the dates in the file info text now get a more readable layout (see the code below the date tests).
And this concludes the addition of a B4Xdialog with a CustomListView to this application.
You can find the source code for this version in the attachment.
 

Attachments

  • pmfiles_v1.zip
    230.5 KB · Views: 63

PaulMeuris

Active Member
Licensed User
In this project there is a file dialog.css (small caps) that is used in the WebView with the Codemirror editor javascript.
When i added a B4XDialog and initialized it and then ran the code in Release mode it generated an error (see above in red).
The B4XDialog initialization code contains a line to add a stylesheet with the filename Dialog.css (capital D) to the list.
Test code:
B4X:
    dialog.Initialize(Root)
    Dim node As JavaObject = dialog.mParent
    Dim stylesheets As List = node.RunMethodJO("getScene", Null).RunMethod("getStylesheets", Null)
    Log(stylesheets)
() [jar:file:/E:/B4J/testenvironment68/B4J/Objects/testenvironment68.jar!/Files/Dialog.css]
This can allow you to create a Dialog.css file and put some css styling for the dialog in it.
It is however not recommended ( see this link ).
The error might be a bug in the B4XDialog library code.
 
Last edited:

PaulMeuris

Active Member
Licensed User
A new version... support for MS Office files...
If you have MS Office installed on your computer then you can use this pmfiles application to convert
Word documents, Excel spreadsheets and PowerPoint presentations to a PDF format.
After the conversion the PDF viewer will show the document, spreadsheet or presentation as a PDF document.
1719731257598.png

The PDF viewer shows the first page and when you click on the viewer you can choose to load and show
all the other pages (if there are some).
1719731380850.png

A message box will appear to let you know that all pages are loaded.
1719731429240.png

Did you see the strange file name: "pmfiles -+(){}[]&@#§!^$%=;,.docx" ?
The space character and the other special characters are being escaped.
The Powershell scripts know how to deal with these characters.
You should however try to avoid using any of these characters in a file name.
Some source code for you to quickly review:
show_selected_file_content:
            Case "doc","docx","xls","xlsx","ppt","pptx"
                Dim caption As String = "Convert MSOffice file to PDF. Continue?" & CRLF & _
                        "The conversion will take some time" & CRLF & "depending on the size of the File." & CRLF & _
                        "An existing PDF file with the same name will be replaced!" & CRLF
                Dim answ As Object = xui.Msgbox2Async(caption, "Convert to PDF file", "Yes", "Cancel", "No", Null)
                Wait For (answ) Msgbox_Result (Result As Int)
                If Result = xui.DialogResponse_Positive Then
                    convert_to_pdf(fpath,fname,ext.ToLowerCase)
                    pdffile = item.SubString2(0,item.LastIndexOf(".")) & ".pdf"
                    If File.Exists(fpath,fname.SubString2(0,fname.LastIndexOf(".")) & ".pdf") = True Then
                        show_sppagepdf
                        initpage
                        renderpage(1)
                    Else
                        show_ta1
                        ta1.Text = "There was no PDF file created." & CRLF & _
                                "The file name probably contains special characters." & CRLF
                    End If
                End If
Using Powershell:
Private Sub convert_to_pdf(fpath As String,fname As String,ext As String)
    '    https://stackoverflow.com/questions/16534292/basic-powershell-batch-convert-word-docx-to-pdf
    If fpath.EndsWith("\") Then fpath = fpath.SubString2(0,fpath.Length-1)
    ' powershell uses the backtick character as an escape character (in stead of the backslash \)
    fpath = fpath.Replace("\","`\")        ' escape the backslash
    Dim strspec As String = " -+(){}[]&@#§!^$%=;,"    ' avoid using these characters in filenames!
    For i = 0 To strspec.Length -1
        fname = fname.Replace(strspec.CharAt(i),"`" & strspec.CharAt(i))
    Next
    Log(fname)
    Select ext
        Case "doc","docx"           
            If fname <> "" Then
                Dim pspath As String = xui.DefaultFolder & "`\convert_word_to_pdf.ps1"
            End If
        Case "xls","xlsx"
            If fname <> "" Then
                Dim pspath As String = xui.DefaultFolder & "`\convert_excel_to_pdf.ps1"
            End If
        Case "ppt","pptx"
            If fname <> "" Then
                Dim pspath As String = xui.DefaultFolder & "`\convert_powerpoint_to_pdf.ps1"
            End If
    End Select
    Try
        Dim sh As Shell
        Dim docpath As String = """" & fpath & """"
        Dim docfilter As String = """" & fname & """"
        Dim strparam As String = pspath & " " & docpath & " " & docfilter
        Dim args As List = Array(strparam)
        sh.InitializeDoNotHandleQuotes("shl", "C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe", args)
        sh.WorkingDirectory = xui.DefaultFolder
        sh.RunSynchronous(-1)
    Catch
        Log(LastException)
        show_ta1
        ta1.Text = "There was an error converting this file." & CRLF
    End Try
End Sub
You can find the complete source code in the attachment.
Enjoy.
 

Attachments

  • pmfiles_v2.zip
    232.6 KB · Views: 60

PaulMeuris

Active Member
Licensed User
In this minor update you can test some modifications.
The MediaViewController has been moved to the bottom and the volume B4XSeekBar has also moved more down.
If an opened folder contains audio and/or video files then a playlist is created that holds all the paths and filenames to the files.
The supported file extensions are mp3, mp4 and wav.
When the playing of one file is finished the playlist is used to automatically start the next file.
After the last file from the list the index is reset and the first file is started next.
So in a way it's a simple media player.
1719992556465.png

The second update is about the PDF rendering.
With the B4XSeekBar you can control the zoom of the page or pages (from 0.1 to 0.9).
The blue label shows the total number of pages in the PDF file.
With the B4XFloatTextField (page #) you can jump to a page in the PDF document.
If all the pages are loaded then you can scroll on from the selected page.
1719992641605.png

And that's it.
Note: some issues with the special characters in a filename are also tested and an appropriate response is given.
Enjoy.
Source code (pmfiles_v3.zip) in the attachment...
 

Attachments

  • pmfiles_v3.zip
    233.6 KB · Views: 60

PaulMeuris

Active Member
Licensed User
It would be nice if you could see the contents of a file in full-screen mode, right?
Well, now you can with this update.
1720579949082.png

If you click on the "Fullscreen" button a new B4XPage is opened in full-screen mode.
1720580057467.png

This mode works with the TextArea, the ZoomImageView, the MediaView, the WebView and the ScrollPanes.
These views are attached to the "pnfullscreen" pane of the B4XFullscreen page.
In the B4XFullscreen page the following code is used to set the full-screen mode:
B4X:
    Dim jo As JavaObject = B4XPages.GetNativeParent(Me)
    Dim jos As JavaObject = jo.GetFieldJO("stage")
    jos.RunMethod("setFullScreen", Array(True))
The KeyPressed_Event subroutine checks if the ESCAPE key was pressed and closes the B4XFullscreen page.
B4X:
B4XPages.ClosePage(Me)
B4X:
    pnfullscreen.RequestFocus    ' escape key works when the pane has focus
If you edit source code in the full-screen mode then the closing of the B4XFullscreen page will not work after pressing the ESC key.
You will have to close it with the top right button.
The zoom B4Xseekbar for the PDF viewer now allows you to enlarge the document (x2).
If you have to make a lot of presentations then this update might be something to consider using.
The source code is in the attachment.
 

Attachments

  • pmfiles_v4.zip
    236.2 KB · Views: 57

PaulMeuris

Active Member
Licensed User
Another small addition to this growing (or maybe great) application... support for SQLite databases.
Files with the extension .db or .db3 will be treated as a SQLite database.
A TableView is added to show the data from the database tables.
In the B4XComboBox you can choose the table from the database to view.
1720672183407.png

The data is converted to strings.
You can use the default sorting of the TableView when you click on the name of the column.
And of course the table data can be viewed in full-screen mode.
1720673214218.png

Please note that you need to have the SQLite library:
B4X:
#Region Project Attributes
    #MainFormWidth: 1300
    #MainFormHeight: 650
    #AdditionalJar: pdfbox-app-2.0.26.jar
    #AdditionalJar: sqlite-jdbc-3.7.2
    #PackagerProperty: IncludedModules = javafx.web
#End Region

The source code is in the attachment.
 

Attachments

  • pmfiles_v5.zip
    237.9 KB · Views: 66

PaulMeuris

Active Member
Licensed User
In this version you can test 2 more updates.
  1. When you click on a zip-file then you can choose to unzip that file.
    A folder with the same name is created in the parent folder and all the files and folders are extracted in it.
    1720862081036.png

    After the extraction process a text file with the same name and the extension ".txt" is created. It contains a report of the process.
    1720862406770.png

    The treeview and breadcrumbs are updated.
    The supported extensions are: "zip","7z","gz","tar","b4xlib".
  2. If a folder contains images ("jpg","png","jpeg","gif","bmp") then an imagelist is created internally.
    In the full-screen mode the ZoomImageView gets the focus and the left and right arrow keys can be used to move to the next or previous image.
    B4X:
    Select KeyCode               
                    Case "ESCAPE"
    '                    Log("escape pressed")
                        B4XPages.ClosePage(Me)
                    Case "LEFT"
    '                    Log("LEFT pressed")
                        get_previous_image
                    Case "RIGHT"
    '                    Log("RIGHT pressed")
                        get_next_image
    End Select
This concludes the series of updates of this application. Unless of course you or i have some more idea's on how to improve this application...
Bug reports are always welcome.
You can download the source code that includes the 7za.exe with this link: pmfiles_v6.zip
 
Last edited:
Top