' Gambas class file PUBLIC sBaseDir AS String = "/usr/share/vine-app-install-data/" PUBLIC sPathTmpLst AS String = Temp$("v-a-i-List") PUBLIC sPathTmpRes AS String = Temp$("v-a-i-Result") 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 idVersion AS Integer = 5 PUBLIC idInstSize AS Integer = 6 PUBLIC idDLSize AS Integer = 7 PUBLIC SUB Form_Open() DIM hSep AS Separator ' enable main form whlie adding categories (workaround for ) FMain.Enabled = TRUE 'setup left(category) panel hspMain.Layout = "180," & CStr(hspMain.Width - 180) AddCategories("All", ("All"), Stock["24/package"]) ' add separator just below all category hSep = NEW Separator(lctCategory) hSep.Height = 4 hSep.Enabled = FALSE 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]) ' adjust some widgets size according to it's font size ''' bottom buttons btnHelp.Width = btnHelp.Font.Width(btnHelp.Text) + 44 btnSwitch.Width = btnSwitch.Font.Width(btnSwitch.Text) + 44 btnApply.Width = btnApply.Font.Width(btnApply.Text) + 44 btnClose.Width = btnClose.Font.Width(btnClose.Text) + 44 btnSwitch.Width = btnSwitch.Font.Width(btnSwitch.Text) + 44 btnThumb.Height = btnThumb.Font.Height(btnThumb.Text) + 8 hbxBottom.Height = btnClose.Font.Height(btnClose.Text) + 16 ''' top combo box and serarch area hbxTop.Height = tbxSearch.Font.Height(tbxSearch.Text) + 16 ''' keep search button square btnSearch.Width = btnSearch.Height ' disable main form after categories added (workaround for ) FMain.Enabled = FALSE 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_Click() DIM sApp AS String DIM iSsHeight AS Integer DIM hPict AS Picture DIM sURL AS String ' store URL extract from rpm database ' 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 description of selected package sApp = lctApps.Current.Name tlbAppName.Text = "" & sApp & "" tlbAppDesc.Text = Replace(cApplications[sApp][idDesc], "

", "
", gb.Text) tlbAppDesc.Text &= " " & ("Version: ") & cApplications[sApp][idVersion] & "
" tlbAppDesc.Text &= " " & ("Install Size: ") & ConvUnit(cApplications[sApp][idInstSize]) & "" tlbAppDesc.Text &= " (" & ("Download Size: ") & ConvUnit(cApplications[sApp][idDLSize]) & ")" ' set icon(large) of selected package 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 & "_small.jpg") = TRUE THEN pbxThumb.Picture = Picture[sBaseDir &/ cApplications[sApp][idCat] &/ "screenshots" &/ sApp & "_small.jpg"] pbxThumb.Height = pbxThumb.Picture.Height pbxThumb.Mouse = Mouse.Pointing pbxThumb.Visible = TRUE btnThumb.Visible = TRUE vbxThumb.Visible = TRUE ELSE pbxThumb.Mouse = Mouse.Default pbxThumb.Visible = FALSE btnThumb.Visible = FALSE vbxThumb.Visible = FALSE ENDIF ' scroll back to top svwDetail.Scroll(0, 0) END PUBLIC SUB pbxThumb_MouseUp() DIM sName AS String DIM iRet AS Integer DIM hProcess AS Stream ' return immediately if no app is selected in listview IF lctApps.Current = NULL THEN RETURN sName = lctApps.Current.Name IF Exist(sBaseDir &/ cApplications[sName][idCat] &/ "screenshots" &/ sName & ".png") THEN EXEC ["xdg-open", sBaseDir &/ cApplications[sName][idCat] &/ "screenshots" &/ sName & ".png"] ELSE ' prompt to install vine-app-install-data-screenshots if no screenshots available iRet = Message.Question(("There is no screenshot available.\n\nYou should install additional package \n(vine-app-install-data-screenshots) to show the screenshot.\n\nWolud you like to download and install it?"), ("&Cancel"), ("&OK")) IF iRet = 2 THEN FMain.Enabled = FALSE FMain.Mouse = Mouse.Wait hProcess = EXEC ["synaptic", "--non-interactive", "--hide-main-window", "--set-selections", "<"] FOR WRITE AS "ShellSynapticSS" PRINT #hProcess, "vine-app-install-data-screenshots install\n"; CLOSE #hProcess ENDIF ENDIF END PUBLIC SUB ShellSynapticSS_kill() ' re-enable main form after screenshot data is installed FMain.Mouse = Mouse.Default FMain.Enabled = TRUE END PUBLIC SUB CheckBoxes_Click() DIM sApp AS String 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 btnHelp_Click() ' show html help EXEC ["xdg-open", "/usr/share/doc/vine-app-install-" & Application.Version & "/help/index.html"] 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 PUBLIC SUB btnThumb_Click() pbxThumb_MouseUp() END PUBLIC SUB btnSwitch_Click() DIM iBtn AS Integer iBtn = Message.Question(("Do you want to switch to synaptic package manager?"), ("&No"), ("&Yes")) IF iBtn = 2 THEN EXEC ["gksu", "-D", "\"synaptic\"", "synaptic"] ME.Close ENDIF 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 = Desktop.Scale * 4 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 and redirect standard output to temporary file. ' we should use a file to pass large number of application names (possibly a bug of gambas?). SHELL "apt-cache show `cat " & sPathTmpLst & "` | tee " & sPathTmpRes FOR READ AS "AptScript" END PUBLIC SUB AptScript_Read() DIM sLine AS String LINE INPUT #LAST, sLine IF sLine LIKE "Package: *" THEN pgbProgress.Value = iCount / (cApplications.Count) 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() ' back to original condition 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) DIM sOutput AS String ' keep command standard output DIM aRes AS String[] ' keep splitted sRes as array DIM sRes AS String 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 ' set default value as "not installed" cApplications[sAppName][idCkBox] = "Off" cApplications[sAppName][idStat] = "NotInstalled" CASE "Summary" cApplications[sAppName][idSumm] = Right(sLine, Len(sLine) - 9) CASE "Installed Size" cApplications[sAppName][idInstSize] = Right(sLine, Len(sLine) - 16) CASE "Version" cApplications[sAppName][idVersion] = Right(sLine, Len(sLine) - 9) CASE "Size" cApplications[sAppName][idDLSize] = Right(sLine, Len(sLine) - 6) CASE "Description" END SELECT ELSE ' assume only description has multi line text IF sAppName <> "" THEN cApplications[sAppName][idDesc] &= sLine & "
" ENDIF ENDIF WEND ' check package is installed or not SHELL "rpm -q --queryformat %{NAME}\"\n\" `cat " & sPathTmpLst & "` | grep -v " & ("is not installed") TO sOutput aRes = Split(sOutput, "\n") FOR EACH sRes IN aRes IF Len(sRes) > 0 THEN cApplications[sRes][idCkBox] = "On" cApplications[sRes][idStat] = "Installed" ENDIF NEXT 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 ' enable main form whlie adding items (workaround for ) FMain.Enabled = TRUE 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 = 8 HPanel.Height = iHeightHBox ' create checkbox hCheckbox = NEW CheckBox(hBox) AS "CheckBoxes" hCheckbox.Width = 20 hCheckbox.Height = 24 ' create PictureBox for icon hPict = NEW PictureBox(hBox) hPict.Alignment = Align.Center hPict.Width = 48 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] ' change checkbox state here to avoid error in CheckBoxes_Click ' (workaround for ) IF element[idStat] = "Installed" THEN hCheckbox.Value = TRUE ELSE hCheckbox.Value = FALSE ENDIF NEXT ' disable main form again (workaround for ) FMain.Enabled = FALSE END PUBLIC SUB FilterLctApps() DIM i AS Integer DIM iCount AS Integer = 0 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 INC iCount lctApps.Children[i].Height = iHeightHBox lctApps.Children[i].Visible = TRUE IF iCount MOD 2 = 0 THEN lctApps.Children[i].Background = Color.Background ELSE lctApps.Children[i].Background = Color.Default ENDIF 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 FUNCTION ConvUnit(sSize AS String) AS String DIM iConv AS Integer = 0 DIM fConv AS Float = 0 IF Val(sSize) < 1024 THEN RETURN sSize & "Byte" ELSE IF Val(sSize) < 1048576 THEN iConv = Int(Val(sSize) / 1024) RETURN Str(iConv) & "KB" ELSE fConv = Val(sSize) / 1024 / 1024 RETURN Str(Format(fConv, "####.#")) & "MB" ENDIF END