' 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 sPathTmp 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 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]) FMain.Enabled = FALSE LoadAppData() END PUBLIC SUB Form_Close() IF Exist(sPathTmp) THEN KILL sPathTmp 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 hProcess AS Stream DIM hFile AS File DIM sDir AS String DIM sFile AS String DIM aFileAndDir AS NEW String[] ' used for sorting DIM sAppList AS String DIM i AS Integer DIM sTmp AS String ' 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 sPathTmp FOR CREATE PRINT #hFile, sAppList CLOSE #hFile ' should use file to pass large number of application names (possibly a bug or not?) hProcess = SHELL "apt-get script " & sPathLua & " < " & sPathTmp FOR INPUT AS "ShellAptScript" END PUBLIC SUB ShellAptScript_Read() DIM sLine AS String DIM sRpmq AS String DIM hPict AS Picture LINE INPUT #LAST, 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 END PUBLIC SUB ShellAptScript_Kill() CreateAppList() FilterLctApps() FMain.Mouse = Mouse.Default FMain.Enabled = TRUE ' should set forcus on something to catch key event (as workaround?) btnClose.SetFocus 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