Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested Items in Table Widgets #171

Merged
merged 18 commits into from
Oct 9, 2020
Merged

Nested Items in Table Widgets #171

merged 18 commits into from
Oct 9, 2020

Conversation

shundhammer
Copy link
Contributor

@shundhammer shundhammer commented Sep 10, 2020

Trello

https://trello.com/c/dC5eSlNw/1957-8-nested-tables-widget

This is the libyui part.

Bugzilla

https://bugzilla.suse.com/show_bug.cgi?id=1176402

Problem

In certain situations we are displaying a hierarchy in a table: We have items that really have a tree structure, yet we need multiple columns to display all the information a user needs. The partitioner is such an example.

storage-flat

Simplified from a UI example; this is not the real partitioner, but it displays very similar contents

The hierarchy is not clear from this. A user needs to have some context information like knowing how Linux device names are structured to make sense of the hierarchy: He needs to know that /dev/sda is a disk while /dev/sda1 is a partition on that disk.

This display is unwieldy already with the 3 disks displayed here (this is a real-life setup from my home PC). This already does not give a good overview. There is also no way to collapse tree branches that are irrelevant to the user right now: Knowing that /dev/sdb is an old rotating disk and the relevant data are now really on the /dev/sdc SSD, a user still cannot get all the partitions on /dev/sdb out of the way.

Solution

Extend the concept to display the tree hierarchy in a table. A YItem can already have child items (which again can have child items, each of which can again have child items etc.). This is used in the Tree widget, but with only one column. We need to combine the concepts of the Tree and the Table widgets.

Qt UI

Qt provides the QTreeWidget which is actually what we are already using for our YQTable widget; we are just not making use of the tree part.

storage-nested-2

Tree-nested-items.rb UI example from yast-ycp-ui-bindings/examples, all items expanded

storage-nested-1

Tree-nested-items.rb UI example from yast-ycp-ui-bindings/examples, branch /dev/sdb collapsed

NCurses UI

In the NCurses UI, we have no such luxury. But the NCTree widget and the NCTable widget are closely related: They use an NCTreePad and an NCTablePad, respectively, that had a lot of common code ("inheritance by copy & paste").

See NCurses-UI PR for more details: libyui/libyui-ncurses#103

nc-storage-nested-1

nc-storage-nested-2

New UI Syntax

      Table(Id(:mytable),
        Header("Device", "Size", "Type", "Mount Point"),
        [
          Item(Id(:sda), "/dev/sda", "931.5G", sda_items, :open),
          Item(Id(:sdb), "/dev/sdb", "931.5G", sdb_items, :closed),
          Item(Id(:sdc), "/dev/sdc", "232.9G", sdc_items, :open)
        ]
      )
    ...
    ...
    def sda_items
      [
        Item(Id(:sda1), "/dev/sda1",  "97.7G", "ntfs", "/win/boot" ),
        Item(Id(:sda2), "/dev/sda2", "833.9G", "ntfs", "/win/app"  )
      ]
    end

:open and :closed are special symbols to make a clear difference between an item's boolean selected status (which of course is still there) and the branch open/closed status.

Full UI Example (Ruby):

See yast-ycp-ui-bindings/examples/Table-nested-items.rb (in PR, in master): (yast/yast-ycp-ui-bindings#55)

(Click the arrow to open)

# encoding: utf-8

# Example for table with nested items

module Yast
  class TableNestedItems < Client
    Yast.import "UI"

    def main
      UI.OpenDialog(main_dialog)
      handle_events
      UI.CloseDialog
    end

    def main_dialog
      MinSize(
        74, 17,
        MarginBox(
          1, 0.4,
          VBox(
            Left(
              Heading("Storage Overview")
            ),
            VSpacing(0.2),
            table,
            VSpacing(0.2),
            Left(Label("Selected:")),
            Label(Id(:selected), Opt(:outputField, :hstretch), ""),
            VSpacing(0.5),
            Right(
              PushButton(Id(:close), "&Close")
            )
          )
        )
      )
    end

    def table
      Table(
        Id(:table),
        Opt(:notify, :immediate),
        Header("Device", "Size", "Type", "Mount Point"),
        disk_items
      )
    end

    def disk_items
      [
        Item(Id(:sda), "/dev/sda", "931.5G", sda_items, :open),
        Item(Id(:sdb), "/dev/sdb", "931.5G", sdb_items, :closed),
        Item(Id(:sdc), "/dev/sdc", "232.9G", sdc_items, :open)
      ]
    end

    def sda_items
      [
        Item(Id(:sda1), "/dev/sda1",  "97.7G", "ntfs", "/win/boot" ),
        Item(Id(:sda2), "/dev/sda2", "833.9G", "ntfs", "/win/app"  )
      ]
    end

    def sdb_items
      [
        Item(Id(:sdb1), "/dev/sdb1",   "2.0G", "swap" ),
        Item(Id(:sdb2), "/dev/sdb2",  "29.4G", "ext4", "/hd-root-leap-42"   ),
        Item(Id(:sdb3), "/dev/sdb3",  "29.4G", "ext4", "/hd-root-leap-15-0" ),
        Item(Id(:sdb4), "/dev/sdb4", "855.8G", "xfs",  "/work" )
      ]
    end

    def sdc_items
      [
        Item(Id(:sdc1), "/dev/sdc1",   "2.0G", "swap", "[swap]" ),
        Item(Id(:sdc2), "/dev/sdc2",  "29.4G", "ext4", "/ssd-root-leap-15-1" ),
        Item(Id(:sdc3), "/dev/sdc3",  "29.4G", "ext4", "/" ),
        Item(Id(:sdc4), "/dev/sdc4", "167.2G", "ext4", "/ssd-work" )
      ]
    end

    def handle_events
      while true
        id = UI.UserInput
        case id

        when :close, :cancel # :cancel is WM_CLOSE
          break # leave event loop
        when :table
          update_selected(current_table_item)
        end
        id
      end
    end

    def current_table_item
      UI.QueryWidget(Id(:table), :CurrentItem)
    end

    def update_selected(id)
      id ||= "<nil>"
      UI.ChangeWidget(Id(:selected), :Value, id.to_s)
    end
  end
end

Yast::TableNestedItems.new.main

New Docs

New document:

https://github.com/shundhammer/libyui-ncurses/blob/huha-tree-table-01/doc/nctable-and-nctree.md

scary-nc-01

scary-nc-02

Included here: Ivan's PR

This PR also includes Ivan's work for this sprint about multiple keyboard shortcuts for selection widgets (MenuBar, ItemSelector) to avoid one round of PRs just for bumping the SO version of libyui. Ivan's PRs are already reviewed; they were merged to branch sprint-108 which was merged to this branch.

This PR will be merged into sprint-108 branch, which already includes several new features (e.g., https://github.com/libyui/libyui/pull/170) that also require to bump the SO version of libyui. Then, sprint-108 will be merged into master.

Releated PRs

libyui SO Version Bump PRs

@mvidner
Copy link
Member

mvidner commented Sep 22, 2020

When you say "Nested Items in Table Widgets" it made me first think of tables within tables, a table cell having micro rows and columns.
Could we instead call this "Nested Table Rows", or "Tree-like Tables"?

Copy link
Member

@mvidner mvidner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

src/YSelectionWidget.h Outdated Show resolved Hide resolved
src/YTree.h Outdated Show resolved Hide resolved
@shundhammer
Copy link
Contributor Author

When you say "Nested Items in Table Widgets" it made me first think of tables within tables, a table cell having micro rows and columns.

Could we instead call this "Nested Table Rows", or "Tree-like Tables"?

I fear we are way beyond that point now - about 4 weeks over it. It's everywhere.

But it says "nested items", not "nested tables", so I don't think many readers will be confused by this.

@joseivanlopez
Copy link
Contributor

This PR should be merged into the sprint-108 branch instead of master. There are more features to include (e.g., show/hide menu options) before bumping the so versions.

@joseivanlopez joseivanlopez changed the base branch from master to sprint-108 October 7, 2020 14:17
@joseivanlopez joseivanlopez changed the title WIP: Nested Items in Table Widgets Nested Items in Table Widgets Oct 8, 2020
@joseivanlopez
Copy link
Contributor

joseivanlopez commented Oct 8, 2020

I have rebased shundhammer/huha-tree-table-01 branch over sprint-108 branch to ensure that everything can be merged without conflicts. I have directly rebased the branch from the shundhammer repository to avoid to create a new PR. But after doing that, now all commits are marked with me as co-author. I will avoid to rebase for the rest of PRs.

@shundhammer note that now you cannot merge your local branch with your remote one (sorry). Please, rename you local branch locally and fetch this remote one again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants