repobrowser.lua 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #! /usr/bin/env lua
  2. --
  3. -- Implementation of simple browser of lgi repository. This is mainly
  4. -- treeview usage demonstration.
  5. --
  6. local lgi = require 'lgi'
  7. local GObject = lgi.GObject
  8. local Gtk = lgi.require('Gtk', '3.0')
  9. local function RepoBrowser()
  10. local self = {}
  11. -- Create browser model.
  12. local column = {
  13. NAME = 1,
  14. VALUE = 2,
  15. }
  16. local model = Gtk.TreeStore.new {
  17. [column.NAME] = GObject.Type.STRING,
  18. [column.VALUE] = GObject.Type.STRING,
  19. }
  20. -- Merges repository table into the treemodel as child of given
  21. -- iterator.
  22. local blacklisted = {
  23. _parent = true, _implements = true, __index = true,
  24. }
  25. local function merge(parent, table)
  26. for name, value in pairs(table) do
  27. local string_value = ''
  28. if type(value) == 'string' then
  29. string_value = value
  30. elseif type(value) == 'number' then
  31. string_value = tonumber(value)
  32. elseif name == '_parent' then
  33. string_value = value._name
  34. end
  35. local iter = model:append(parent, {
  36. [column.NAME] = name,
  37. [column.VALUE] = string_value,
  38. })
  39. if type(value) == 'table' and not blacklisted[name] then
  40. merge(iter, value)
  41. end
  42. end
  43. end
  44. -- Loads specified repo namespace into the model.
  45. function self.add(namespace)
  46. local iter = model:append(nil, {
  47. [column.NAME] = namespace._name,
  48. [column.VALUE] = namespace._version,
  49. })
  50. merge(iter, namespace:_resolve(true))
  51. end
  52. -- Create treeview widget with columns.
  53. local sorted = Gtk.TreeModelSort { model = model }
  54. sorted:set_sort_func(column.NAME, function(model, a, b)
  55. a = model[a][column.NAME]
  56. b = model[b][column.NAME]
  57. if a == b then return 0
  58. elseif a < b then return -1
  59. else return 1 end
  60. end)
  61. sorted:set_sort_column_id(column.NAME, Gtk.SortType.ASCENDING)
  62. self.view = Gtk.TreeView {
  63. model = sorted,
  64. Gtk.TreeViewColumn {
  65. title = "Name", resizable = true, sort_column_id = column.NAME,
  66. { Gtk.CellRendererText(), expand = true, { text = column.NAME } },
  67. },
  68. Gtk.TreeViewColumn {
  69. { Gtk.CellRendererText(), { text = column.VALUE } },
  70. },
  71. }
  72. return self
  73. end
  74. -- Create application and its window.
  75. local app = Gtk.Application { application_id = 'org.lgi.repobrowser' }
  76. function app:on_activate()
  77. local browser = RepoBrowser()
  78. browser.add(lgi.GObject)
  79. -- Global window.
  80. local window = Gtk.Window {
  81. application = app,
  82. title = "LGI Repository Browser",
  83. default_width = 800, default_height = 640,
  84. Gtk.Grid {
  85. row_spacing = 5, column_spacing = 5, margin = 5,
  86. { Gtk.Label { label = "Namespace" } },
  87. { Gtk.Entry { id = 'name', hexpand = true }, left_attach = 1 },
  88. { Gtk.Label { label = "Version" }, left_attach = 2 },
  89. { Gtk.Entry { id = 'version', hexpand = true }, left_attach = 3 },
  90. { Gtk.Button { id = 'add', label = Gtk.STOCK_ADD, use_stock = true },
  91. left_attach = 4 },
  92. { Gtk.ScrolledWindow { expand = true, browser.view },
  93. left_attach = 0, top_attach = 1, width = 5 },
  94. }
  95. }
  96. function window.child.add:on_clicked()
  97. local version = window.child.version.text
  98. if version == '' then version = nil end
  99. local ok, data = pcall(lgi.require, window.child.name.text, version)
  100. if ok then
  101. browser.add(data)
  102. else
  103. local message = Gtk.MessageDialog {
  104. text = "Failed to load requested namespace",
  105. secondary_text = data,
  106. message_type = Gtk.MessageType.ERROR,
  107. buttons = Gtk.ButtonsType.CLOSE,
  108. transient_for = window,
  109. }
  110. message:run()
  111. message:destroy()
  112. end
  113. end
  114. window:show_all()
  115. end
  116. app:run { arg[0], ... }