' Gambas class file PUBLIC sBaseDir AS String = "/usr/share/vine-app-install-data/" PUBLIC sPathLua AS String = "/usr/share/vine-app-install/list-package-info.lua" PUBLIC sPathTmpLst AS String = "/tmp/v-a-i." & CStr(Int(Rnd(10000, 99999))) PUBLIC sPathTmpRes AS String = "/tmp/v-a-i." & CStr(Int(Rnd(10000, 99999))) PUBLIC sIconDir AS String = "/usr/share/icons/gnome/24x24/categories/" PUBLIC iHeightHBox AS Integer = Desktop.Scale * 5 ' default row height of gridview PUBLIC cApplications AS NEW Collection ' store application information (multi dimension), = Name PUBLIC sAppName AS String ' store app name globaly (used for reading apt-cache's output) PUBLIC iCount AS Integer ' for progress bar PUBLIC bScriptError AS Boolean = FALSE ' set TRUE if apt-get script outputs any error messages PUBLIC idSumm AS Integer = 0 ' : Summary PUBLIC idDesc AS Integer = 1 ' : Description PUBLIC idCat AS Integer = 2 ' : Category PUBLIC idStat AS Integer = 3 ' : State (Installed/NotInstalled) PUBLIC idCkBox AS Integer = 4 ' : Checkbox State (On / Off) PUBLIC SUB Form_Open() 'setup left(category) panel hspMain.Layout = "180," & CStr(hspMain.Width - 180) AddCategories("All", ("All"), Stock["24/package"]) AddCategories("Accessories", ("Accessories"), Picture[sIconDir & "applications-accessories.png"]) AddCategories("Internet", ("Internet"), Picture[sIconDir & "applications-internet.png"]) AddCategories("Office", ("Office"), Picture[sIconDir & "applications-office.png"]) AddCategories("Graphics", ("Graphics"), Picture[sIconDir & "applications-graphics.png"]) AddCategories("Multimedia", ("Multimedia"), Picture[sIconDir & "applications-multimedia.png"]) AddCategories("Games", ("Games"), Picture[sIconDir & "applications-games.png"]) AddCategories("System", ("System"), Picture[sIconDir & "applications-system.png"]) AddCategories("Development", ("Development"), Picture[sIconDir & "applications-development.png"]) AddCategories("Other", ("Other"), Picture[sIconDir & "applications-other.png"]) AddCategories("Tasks", ("Tasks"), Stock["24/component"]) AddCategories("Restricted", ("Restricted"), Stock["24/lock"]) ' start with "All" is selected lctCategory.Select(lctCategory.Children[0]) END PUBLIC SUB Form_Show() ' a bit wait for widget drawing WAIT 1 LoadAppData() END PUBLIC SUB Form_Close() ' remove temporary files IF Exist(sPathTmpLst) THEN KILL sPathTmpLst IF Exist(sPathTmpRes) THEN KILL sPathTmpRes END PUBLIC SUB btnClose_Click() ME.Close END PUBLIC SUB lctApps_MouseDown() DIM sApp AS String DIM iSsHeight AS Integer DIM hPict AS Picture ' return immediately while loading the app list IF lctApps.Current = NULL THEN RETURN 'make visible and expand the detail pane IF svwDetail.Visible = FALSE THEN svwDetail.Visible = TRUE vspRight.Layout = CStr(vspRight.Height / 2) & "," & CStr(vspRight.Height / 2) ENDIF ' set icon(large) and description of selected package sApp = lctApps.Current.Name tlbAppDesc.Text = "" & sApp & "

" tlbAppDesc.Text &= cApplications[sApp][idDesc] IF Exist(sBaseDir &/ cApplications[sApp][idCat] &/ "icons" &/ sApp & ".png") = TRUE THEN pbxDetail.Picture = Image.Load(sBaseDir &/ cApplications[sApp][idCat] &/ "icons" &/ sApp & ".png").stretch(48, 48).Picture ELSE pbxDetail.Picture = Picture["noicon.png"] ENDIF ' set screenshot if available IF Exist(sBaseDir &/ cApplications[sApp][idCat] &/ "screenshots" &/ sApp & ".png") = TRUE THEN hPict = Picture[sBaseDir &/ cApplications[sApp][idCat] &/ "screenshots" &/ sApp & ".png"] iSsHeight = hPict.Height / hPict.Width * pbxThumb.Width pbxThumb.Picture = hPict.Image.Stretch(pbxThumb.Width, iSsHeight).Picture pbxThumb.Mouse = Mouse.Pointing pbxThumb.Visible = TRUE ELSE pbxThumb.Mouse = Mouse.Default pbxThumb.Visible = FALSE ENDIF END PUBLIC SUB pbxThumb_MouseUp() DIM sName AS String sName = lctApps.Current.Name EXEC ["xdg-open", sBaseDir &/ cApplications[sName][idCat] &/ "screenshots" &/ sName & ".png"] END PUBLIC SUB CheckBoxes_Click() DIM sApp AS String ' ignore useless event call while loading the application data IF FMain.Enabled = FALSE THEN RETURN sApp = LAST.Parent.Name ' synchronize checkbox valu and idCkBox value IF LAST.Value = CheckBox.True THEN cApplications[sApp][idCkBox] = "On" ELSE cApplications[sApp][idCkBox] = "Off" ENDIF ' change color of selected application IF LAST.Value = CheckBox.TRUE AND cApplications[sApp][idStat] = "NotInstalled" THEN LAST.Parent.Children[1].Background = Color.DarkGreen LAST.Parent.Children[2].Background = Color.DarkGreen LAST.Parent.Children[3].Background = Color.DarkGreen LAST.Parent.Children[3].Foreground = Color.White ELSE IF LAST.Value = CheckBox.False AND cApplications[sApp][idStat] = "Installed" THEN LAST.Parent.Children[1].Background = Color.Darkred LAST.Parent.Children[2].Background = Color.Darkred LAST.Parent.Children[3].Background = Color.Darkred LAST.Parent.Children[3].Foreground = Color.White ELSE LAST.Parent.Children[1].Background = Color.Default LAST.Parent.Children[2].Background = Color.Default LAST.Parent.Children[3].Background = Color.Default LAST.Parent.Children[3].Foreground = Color.Default ENDIF END PUBLIC SUB lctCategory_Click() FilterLctApps() END PUBLIC SUB cbxState_Click() FilterLctApps() END PUBLIC SUB btnSearch_Click() btnSearch.SetFocus FilterLctApps() END PUBLIC SUB btnApply_Click() DIM sSelection AS String DIM hProcess AS Stream DIM element AS String[] FOR EACH element IN cApplications IF element[idCkBox] = "On" AND element[idStat] = "NotInstalled" THEN sSelection &= cApplications.Key & " " & "install" & "\n" ELSE IF element[idCkBox] = "Off" AND element[idStat] = "Installed" THEN sSelection &= cApplications.Key & " " & "delete" & "\n" ENDIF NEXT IF Len(sSelection) > 0 THEN FMain.Enabled = FALSE FMain.Mouse = Mouse.Wait hProcess = EXEC ["synaptic", "--non-interactive", "--hide-main-window", "--set-selections", "<"] FOR WRITE AS "ShellSynaptic" PRINT #hProcess, sSelection; CLOSE #hProcess ELSE Message.Error(("Nothing marked as install and/or remove")) ENDIF END PUBLIC SUB ShellSynaptic_kill() LoadAppData() END PUBLIC SUB tbxSearch_GotFocus() IF tbxSearch.Text = ("Enter search term") THEN tbxSearch.Clear tbxSearch.Foreground = Color.TextForeground ELSE tbxSearch.SelectAll ENDIF END PUBLIC SUB tbxSearch_LostFocus() IF tbxSearch.Text = "" THEN tbxSearch.Foreground = Val("&HA0A0A0&") tbxSearch.Text = ("Enter search term") ENDIF END PUBLIC SUB Form_KeyPress() ' set focus on search field when Ctrl + K pressed IF Key.Control = TRUE AND Key.Code = Key["K"] THEN tbxSearch.SetFocus END PUBLIC SUB tbxSearch_KeyPress() ' press enter key then start serch IF Key.Code = Key.Return THEN FilterLctApps() END ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' procedures and functions (including process event) ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PUBLIC SUB AddCategories(sName AS String, sText AS String, pIcon AS Picture) ' add set of HBox, PictureBox and TextLabel in list container DIM hBox AS HBox DIM hLabel AS Label DIM hPict AS PictureBox ' create HBox hBox = NEW HBox(lctCategory) hBox.Padding = 4 hBox.Spacing = 8 hBox.Height = 32 hBox.Name = sName ' create PictureBox for icon hPict = NEW PictureBox(hBox) hPict.Picture = pIcon hPict.Resize(24, 24) ' create TextLaber for group name hLabel = NEW Label(hBox) hLabel.Expand = TRUE hLabel.Text = sText END PUBLIC SUB LoadAppData() DIM hFile AS File ' handler for temporary file DIM aFileAndDir AS NEW String[] ' used for sorting DIM sAppList AS String ' list of application names DIM sDir AS String DIM sFile AS String DIM i AS Integer ' setup progress bar and counter iCount = 1 pgbProgress.Value = 0 pgbProgress.Visible = TRUE ' get file name & dirctory and sort them by file name (*not directory name) FOR EACH sDir IN Dir(sBaseDir, "*", gb.Directory) FOR EACH sFile IN Dir(sBaseDir &/ sDir, "*", gb.File) aFileAndDir.Add(sFile & ":" & sDir) sAppList &= sFile & " " NEXT NEXT aFileAndDir.Sort ' store name & category into collection (also reload it) IF cApplications.Count > 0 THEN cApplications.Clear FOR i = 0 TO aFileAndDir.Max cApplications.Add(["", "", Split(aFileAndDir[i], ":")[1], "", ""], Split(aFileAndDir[i], ":")[0]) NEXT ' extract package info from apt cache and store it to gridview hFile = OPEN sPathTmpLst FOR CREATE PRINT #hFile, sAppList CLOSE #hFile ' execute helper lua script an redirect standard output to temporary file ' and we should use a file to pass large number of application names (possibly a bug or not?). SHELL "apt-get script " & sPathLua & " < " & sPathTmpLst & " | tee " & sPathTmpRes FOR READ AS "AptScript" END PUBLIC SUB AptScript_Read() DIM sLine AS String LINE INPUT #LAST, sLine IF sLine LIKE ("Reading Package Lists*") OR sLine LIKE ("Building Dependency Tree*") OR sLine LIKE "Package: *" THEN pgbProgress.Value = iCount / (cApplications.Count + 2) INC iCount WAIT 0.001 ' wait a mili second for progress bar drawing ENDIF END PUBLIC SUB AptScript_Error(sStr AS String) bScriptError = TRUE END PUBLIC SUB AptScript_Kill() IF bScriptError = TRUE THEN Message.Error(("Error while extracting package information.

Please resolve the problem using apt-get command or synaptic package manager.
"), ("&Close")) ME.Close ELSE CreateAppData() CreateAppList() FilterLctApps() pgbProgress.Visible = FALSE FMain.Mouse = Mouse.Default FMain.Enabled = TRUE ' should set forcus on something to catch key event (as workaround?) btnClose.SetFocus ENDIF END PUBLIC SUB CreateAppData() DIM hFile AS File ' handler for temporary file DIM sLine AS String ' read one line from file (output of lua script) IF Exist(sPathTmpRes) = TRUE THEN hFile = OPEN sPathTmpRes FOR INPUT WHILE NOT Eof(hFile) LINE INPUT #hFile, sLine IF InStr(sLine, ": ") THEN SELECT CASE Split(sLine, ":")[0] CASE "Package" ' Name sLine = Right(sLine, Len(sLine) - 9) ' pacakge name sAppName = sLine ' hold current app name CASE "State" IF Right(sLine, Len(Sline) - 7) = "Installed" THEN cApplications[sAppName][idCkBox] = "On" cApplications[sAppName][idStat] = "Installed" ELSE cApplications[sAppName][idCkBox] = "Off" cApplications[sAppName][idStat] = "NotInstalled" END IF CASE "Summary" cApplications[sAppName][idSumm] = Right(sLine, Len(sLine) - 9) CASE "Description" END SELECT ELSE ' assume only description has multi line text IF sAppName <> "" THEN cApplications[sAppName][idDesc] &= sLine & "
" ENDIF ENDIF WEND ENDIF END PUBLIC SUB CreateAppList() DIM hBox AS HBox DIM hCheckbox AS CheckBox DIM hTextLabel AS TextLabel DIM hPict AS PictureBox DIM hPanel AS Panel DIM element AS String[] DIM i AS Integer IF lctApps.Count > 0 THEN lctApps.Clear FOR EACH element IN cApplications ' create HBox hBox = NEW HBox(lctApps) hBox.Padding = 1 hBox.Spacing = 0 hBox.Height = iHeightHBox hBox.Name = cApplications.Key 'create panel (for space adjustment) hPanel = NEW Panel(hBox) HPanel.Width = 4 HPanel.Height = iHeightHBox ' create checkbox hCheckbox = NEW CheckBox(hBox) AS "CheckBoxes" hCheckbox.Width = 20 hCheckbox.Height = 24 IF element[idStat] = "Installed" THEN hCheckbox.Value = TRUE ELSE hCheckbox.Value = FALSE ENDIF ' create PictureBox for icon hPict = NEW PictureBox(hBox) hPict.Alignment = Align.Center hPict.Width = 32 hPict.Height = 24 IF Exist(sBaseDir &/ element[idCat] &/ "icons" &/ cApplications.Key & ".png") = TRUE THEN hPict.Picture = Image.Load(sBaseDir &/ element[idCat] &/ "icons" &/ cApplications.Key & ".png").stretch(24, 24).Picture ELSE hPict.Picture = Picture["noicon24.png"] ENDIF ' create TextLabel for application name hTextLabel = NEW TextLabel(hBox) hTextLabel.Expand = TRUE hTextLabel.Alignment = Align.Normal hTextLabel.Text = " " & cApplications.Key & "
" hTextLabel.Text &= "  " & element[idSumm] NEXT END PUBLIC SUB FilterLctApps() DIM i AS Integer DIM sName AS String ' hide unmatch application with specified category and state FOR i = 0 TO lctApps.Children.Count - 1 sName = lctApps.Children[i].Name IF CkCategory(sName) = TRUE AND CkState(sName) = TRUE AND CkSearch(sName) = TRUE THEN lctApps.Children[i].Height = iHeightHBox lctApps.Children[i].Visible = TRUE ELSE lctApps.Children[i].Height = 0 lctApps.Children[i].Visible = FALSE ENDIF NEXT lctApps.Refresh() END FUNCTION CkCategory(sApp AS String) AS Boolean ' return TRUE if an application shold be shown IF cApplications[sApp][idCat] = lctCategory.Current.Name OR lctCategory.Current.Name = "All" THEN ' show all rows if "All" is selected RETURN TRUE ELSE RETURN FALSE ENDIF END FUNCTION CkState(sApp AS String) AS Boolean ' return TRUE if an application shold be shown SELECT CASE cbxState.Text CASE ("Installed") IF cApplications[sApp][idStat] = "Installed" THEN RETURN TRUE ELSE RETURN FALSE ENDIF CASE ("Not installed") IF cApplications[sApp][idStat] = "NotInstalled" THEN RETURN TRUE ELSE RETURN FALSE ENDIF CASE ("Marked changes") IF cApplications[sApp][idStat] = "Installed" AND cApplications[sApp][idCkBox] = "Off" THEN RETURN TRUE ELSE IF cApplications[sApp][idStat] = "NotInstalled" AND cApplications[sApp][idCkBox] = "On" THEN RETURN TRUE ELSE RETURN FALSE ENDIF DEFAULT RETURN TRUE END SELECT END PUBLIC SUB CkSearch(sApp AS String) AS Boolean ' return TRUE if serch term is not specified IF tbxSearch.Text = "" OR tbxSearch.Text = ("Enter search term") THEN RETURN TRUE ' return TRUE if name , summary or description contains serch term IF InStr(sApp, tbxSearch.Text, 0, gb.Text) > 0 OR InStr(cApplications[sApp][idSumm], tbxSearch.Text, 0, gb.Text) > 0 OR InStr(cApplications[sApp][idDesc], tbxSearch.Text, 0, gb.Text) > 0 THEN RETURN TRUE ELSE RETURN FALSE ENDIF END