ibridgesgui 2.1.0__tar.gz → 2.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/PKG-INFO +1 -1
- ibridgesgui-2.1.2/coverage.svg +1 -0
- ibridgesgui-2.1.2/docs/userdoc.qmd +148 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/_version.py +3 -3
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/browsertab/browser.py +47 -1
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/browsertab/browser_controller.py +7 -1
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/browsertab/irods_browser_service.py +108 -14
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/config.py +4 -3
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/gui_utils.py +5 -3
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/info.py +8 -1
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/irods_tree_model.py +2 -1
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/login.py +6 -3
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/mainmenu/main_window.py +3 -2
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/mainmenu/tab_manager.py +2 -1
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/popup_widgets/__init__.py +2 -0
- ibridgesgui-2.1.2/ibridgesgui/popup_widgets/resc_tree.py +98 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/popup_widgets/upload_data.py +3 -2
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/searchtab/search.py +2 -2
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/searchtab/search_controller.py +6 -5
- ibridgesgui-2.1.2/ibridgesgui/ui_files/rescTree.py +97 -0
- ibridgesgui-2.1.2/ibridgesgui/ui_files/rescTree.ui +101 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/tabBrowser.py +27 -21
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/tabBrowser.ui +2 -2
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/tabInfo.py +11 -5
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/tabInfo.ui +7 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/uploadData.py +4 -4
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/uploadData.ui +1 -1
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui.egg-info/PKG-INFO +1 -1
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui.egg-info/SOURCES.txt +5 -0
- ibridgesgui-2.1.2/ibridgesgui.egg-info/scm_file_list.json +150 -0
- ibridgesgui-2.1.2/ibridgesgui.egg-info/scm_version.json +8 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/pyproject.toml +6 -1
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/browser/test_irods_browser_service.py +6 -4
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/search/conftest.py +6 -7
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/search/test_search_controller.py +2 -3
- ibridgesgui-2.1.0/coverage.svg +0 -1
- ibridgesgui-2.1.0/docs/userdoc.qmd +0 -138
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/.flake8 +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/.github/dependabot.yml +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/.github/workflows/linter.yml +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/.github/workflows/nuitka_release.yml +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/.github/workflows/publish.yml +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/.github/workflows/pypi_release.yml +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/.github/workflows/tests.yml +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/.gitignore +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/LICENSE +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/README.md +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/_quarto.yml +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/build_tools/build_script.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/build_tools/ui_to_py.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/developers.qmd +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/faq.qmd +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/getting-started.qmd +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/info.qmd +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/screenshots/add_check_config.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/screenshots/add_new_config.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/screenshots/browser.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/screenshots/login.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/screenshots/metadata.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/screenshots/permissions.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/screenshots/replicas.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/screenshots/search.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/screenshots/start_ibridges.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/docs/screenshots/sync.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/__init__.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/__main__.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/browsertab/__init__.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/browsertab/browser_model.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/icons/arrow-left.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/icons/arrow-right.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/icons/arrow-up.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/icons/christmas-logo.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/icons/home.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/icons/iBridges.ico +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/icons/loading_circle.gif +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/icons/logo.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/icons/nosync.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/icons/refresh.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/icons/syncing.png +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/logviewer.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/mainmenu/__init__.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/mainmenu/config_manager.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/mainmenu/plugin_manager.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/mainmenu/session_manager.py +2 -2
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/md_schemas/ibridges_metadata_schema.json +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/popup_widgets/base.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/popup_widgets/check_config.py +1 -1
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/popup_widgets/create_collection.py +1 -1
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/popup_widgets/create_directory.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/popup_widgets/download_data.py +1 -1
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/popup_widgets/rename_item.py +1 -1
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/searchtab/__init__.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/searchtab/search_model.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/synctab/__init__.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/synctab/sync.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/synctab/sync_controller.py +1 -1
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/synctab/sync_model.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/threads.py +2 -2
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/MainMenu.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/MainMenu.ui +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/__init__.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/configCheck.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/configCheck.ui +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/createCollection.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/createCollection.ui +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/downloadData.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/downloadData.ui +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/irodsLogin.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/irodsLogin.ui +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/renameItem.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/renameItem.ui +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/tabLogging.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/tabLogging.ui +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/tabSearch.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/tabSearch.ui +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/tabSync.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/tabSync.ui +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/transferData.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/transferData.ui +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/welcome.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/ui_files/welcome.ui +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui/welcome.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui.egg-info/dependency_links.txt +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui.egg-info/requires.txt +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/ibridgesgui.egg-info/top_level.txt +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/index.qmd +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/setup.cfg +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/browser/conftest.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/browser/test_browser_controller.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/browser/test_browser_model.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/conftest.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/gui/test_info_tab.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/gui/test_login.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/gui/test_main.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/main_window/conftest.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/main_window/test_config_manager.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/main_window/test_main_window.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/main_window/test_session_manager.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/main_window/test_tab_manager.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/popup/conftest.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/popup/test_check_config.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/popup/test_download_data.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/popup/test_simple_dialogs.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/popup/test_transfer_dialog_base.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/popup/test_upload_data.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/search/test_search_model.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/sync/conftest.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/sync/test_sync_controller.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/sync/test_sync_model.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/threads/conftest.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/threads/test_search_thread.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/threads/test_sync_thread.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/threads/test_transfer_thread.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/unit/test_config.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/unit/test_gui_utils.py +0 -0
- {ibridgesgui-2.1.0 → ibridgesgui-2.1.2}/tests/unit/test_irods_tree_model.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="114" height="20" role="img" aria-label="coverage: 83.18%"><title>coverage: 83.18%</title><filter id="blur"><feGaussianBlur stdDeviation="16"/></filter><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="114" height="20" rx="3"/></clipPath><g clip-path="url(#r)"><rect width="61" height="20" fill="#555"/><rect x="61" width="53" height="20" fill="#67ac09"/><rect width="114" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="315" y="150" fill-opacity=".8" filter="url(#blur)" textLength="510">coverage</text><text x="315" y="150" fill-opacity=".3" textLength="510">coverage</text></g><text x="315" y="140" textLength="510">coverage</text></g><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="865" y="150" fill-opacity=".8" filter="url(#blur)" textLength="430">83.18%</text><text x="865" y="150" fill-opacity=".3" textLength="430">83.18%</text></g><text x="865" y="140" textLength="430">83.18%</text></g></g></svg>
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# iBridges User Documentation
|
|
2
|
+
|
|
3
|
+
## Synopsis
|
|
4
|
+
|
|
5
|
+
iBridges is a **GUI for any data‑management platform based on iRODS**. It exposes iRODS functionality through a graphical interface. The GUI groups related functionality into separate views, each representing a specific function area.
|
|
6
|
+
|
|
7
|
+
Default iBridges‑GUI views:
|
|
8
|
+
|
|
9
|
+
- **Browser** — browse iRODS collections, inspect data objects and collections, **edit metadata and permissions**, and **delete data**.
|
|
10
|
+
- **Data Synchronisation** — synchronise local directories with their corresponding iRODS collections.
|
|
11
|
+
- **Search** — search for data collections and objects.
|
|
12
|
+
- **Info** — summarises information such as the user’s role, groups, and the storage resources on the iRODS server, including their status and available capacity.
|
|
13
|
+
|
|
14
|
+
## Views and Plugins
|
|
15
|
+
|
|
16
|
+
In the main menu (next to the configuration menu), you will find a drop‑down menu called **“Views and Plugins”**. Selecting or deselecting items in this menu will show or hide the corresponding tabs in the GUI. All checked tabs and plugins will automatically be restored in the next session.
|
|
17
|
+
|
|
18
|
+
On first launch, the default views `Welcome`, `Browser`, `Synchronise Data`, `Search`, `Info`, and `Logs` are shown.
|
|
19
|
+
|
|
20
|
+
## Browsing through your iRODS collections
|
|
21
|
+
|
|
22
|
+
After logging into iRODS, the first view you see is the **Browser**. This view has three sections:
|
|
23
|
+
|
|
24
|
+
1. Navigation
|
|
25
|
+
2. Listing
|
|
26
|
+
3. Detailed inspection of data objects and collections
|
|
27
|
+
|
|
28
|
+

|
|
29
|
+
|
|
30
|
+
### Navigation
|
|
31
|
+
|
|
32
|
+
- The navigation bar contains an **editable field** showing your current iRODS path. On startup, it points to your `irods_home` from the configuration file.
|
|
33
|
+
You can **navigate anywhere in the iRODS tree** by editing this field and pressing `<Enter>`.
|
|
34
|
+
|
|
35
|
+
- The **three buttons** next to the path field are:
|
|
36
|
+
- `Refresh` (circular arrows) — reload the listing
|
|
37
|
+
- `Up` (arrow) — go one level up
|
|
38
|
+
- `Home` (house icon) — jump to your home collection
|
|
39
|
+
|
|
40
|
+
- `Create Collection` creates a new collection at the path shown above.
|
|
41
|
+
|
|
42
|
+
- `Upload` opens a dialog to select files for upload. The destination is the path in the navigation field. You may also specify metadata files to be extracted upon upload and be stored as iRODS metadata.
|
|
43
|
+
|
|
44
|
+
- `Download` opens a dialog to choose a local destination. You may also export metadata alongside the download.
|
|
45
|
+
To download, select an item in the table below.
|
|
46
|
+
For downloading multiple items, see the **Search** section.
|
|
47
|
+
|
|
48
|
+
- `Delete` removes the selected collection or data object.
|
|
49
|
+
**Note: deleted data is permanently removed from the iRODS instance.**
|
|
50
|
+
|
|
51
|
+
### Listing
|
|
52
|
+
|
|
53
|
+
The table below the navigation bar lists all collections and data objects in the current path.
|
|
54
|
+
|
|
55
|
+
Columns:
|
|
56
|
+
|
|
57
|
+
- **Status** — `-C` for collections, or the replica status for data objects.
|
|
58
|
+
If a data object’s status is not `good`, the data is compromised. Contact your iRODS administrator. Do not use such data.
|
|
59
|
+
- **Name** — collection or data object name
|
|
60
|
+
- **Size** — size in bytes
|
|
61
|
+
- **Checksum** — a hash used to verify data integrity
|
|
62
|
+
- **Created / Modified** — timestamps for creation and last modification
|
|
63
|
+
|
|
64
|
+
- *Single click* loads details in the section below.
|
|
65
|
+
- *Double click* on a collection navigates into it.
|
|
66
|
+
|
|
67
|
+
### Inspect collections and data objects
|
|
68
|
+
|
|
69
|
+
This section shows detailed information about the selected item.
|
|
70
|
+
|
|
71
|
+
- **Preview** — lists the contents of a collection or shows the first lines of text, JSON, or CSV files.
|
|
72
|
+
|
|
73
|
+
- **Metadata** — displays iRODS metadata (key, value, units).
|
|
74
|
+
- *Single click* loads the metadata entry into the editable fields.
|
|
75
|
+
- To create metadata, fill in *key*, *value*, and *units*, then click `Add`.
|
|
76
|
+
Multiple entries with the same key but different values are allowed.
|
|
77
|
+
- `Update` updates the current selected metadata entry.
|
|
78
|
+
- `Delete` removes the metadata entry matching the fields.
|
|
79
|
+
|
|
80
|
+

|
|
81
|
+
|
|
82
|
+
- **Permissions** — shows access rights for the selected item.
|
|
83
|
+
The drop‑down menu `Access name` exposes the following rights:
|
|
84
|
+
|
|
85
|
+
| Rights/Action | upload file | write file | delete file | add metadata | update metadata | remove metadata |
|
|
86
|
+
|---------------|-------------|------------|-------------|--------------|------------------|------------------|
|
|
87
|
+
| delete_object | ✅ also `imkdir` | ✅ | ✅/❌ | ✅ | ❌ | ✅ |
|
|
88
|
+
| modify_object | ✅ also `imkdir` | ✅ | ✅/❌ | ✅ | ✅ | ✅ |
|
|
89
|
+
| create_object | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
|
|
90
|
+
| read_object | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
91
|
+
|
|
92
|
+

|
|
93
|
+
|
|
94
|
+
The **Creator** label shows who created the selected item.
|
|
95
|
+
|
|
96
|
+
Collections support `inherit` / `noinherit`.
|
|
97
|
+
`inherit` applies the collection’s permissions to newly added items.
|
|
98
|
+
|
|
99
|
+
To apply permission changes recursively to all existing members of a collection, enable `Recursive`.
|
|
100
|
+
|
|
101
|
+
- **Replicas** — shows the storage resources where a data object is stored.
|
|
102
|
+
Collections have no replicas.
|
|
103
|
+
|
|
104
|
+

|
|
105
|
+
|
|
106
|
+
Replica information is mainly for sysadmins. If a replica status is not `good`, send them this information.
|
|
107
|
+
|
|
108
|
+
## Data Synchronisation
|
|
109
|
+
|
|
110
|
+
`Synchronise Data` provides tools to **synchronise a local folder with an iRODS collection**.
|
|
111
|
+
Synchronisation works both ways:
|
|
112
|
+
|
|
113
|
+
- Local → iRODS (right‑pointing arrow)
|
|
114
|
+
- iRODS → Local (left‑pointing arrow)
|
|
115
|
+
|
|
116
|
+
Before synchronisation, differences are calculated and shown in the text field below.
|
|
117
|
+
**Note:** calculating differences may take some time.
|
|
118
|
+
|
|
119
|
+

|
|
120
|
+
|
|
121
|
+
Synchronisation works only for collections/directories, not for single files.
|
|
122
|
+
|
|
123
|
+
## Search
|
|
124
|
+
|
|
125
|
+
`Search` provides a form where you can enter path and metadata criteria.
|
|
126
|
+
Click `Search` to list matching collections and data objects.
|
|
127
|
+
|
|
128
|
+

|
|
129
|
+
|
|
130
|
+
### Search fields
|
|
131
|
+
|
|
132
|
+
- The path at the top defines where the search is performed.
|
|
133
|
+
It must exist; by default, your home collection is used.
|
|
134
|
+
|
|
135
|
+
- `Obj/Coll name` filters by name.
|
|
136
|
+
Example: entering `demo` finds all items named *demo*.
|
|
137
|
+
|
|
138
|
+
- Example above: searching for all `*.txt` objects in `my_books` using `my_books/%.txt`.
|
|
139
|
+
|
|
140
|
+
- Metadata filters narrow results further.
|
|
141
|
+
Example: key `author`, value containing `Doyle` → `%Doyle%`.
|
|
142
|
+
|
|
143
|
+
**Note: the wildcard is `%`.**
|
|
144
|
+
|
|
145
|
+
### Search results
|
|
146
|
+
|
|
147
|
+
- *Single click* or *Select all* → click `Download` to choose a destination and start downloading.
|
|
148
|
+
- *Double click* → open the item in the `Browser` for further inspection.
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '2.1.
|
|
22
|
-
__version_tuple__ = version_tuple = (2, 1,
|
|
21
|
+
__version__ = version = '2.1.2'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 1, 2)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gda2566526'
|
|
@@ -21,9 +21,55 @@ class Browser(PySide6.QtWidgets.QWidget, Ui_tabBrowser):
|
|
|
21
21
|
else:
|
|
22
22
|
load_ui(UI_FILE_DIR / "tabBrowser.ui", self)
|
|
23
23
|
|
|
24
|
+
self.setup_tooltips()
|
|
24
25
|
self.controller = BrowserController(self, session, app_name)
|
|
25
26
|
self.controller.init_browser()
|
|
26
27
|
|
|
28
|
+
def setup_tooltips(self):
|
|
29
|
+
"""Add tool tips to interactive elements."""
|
|
30
|
+
# --- Navigation ---
|
|
31
|
+
self.input_path.setToolTip("Enter an iRODS path and press Enter to navigate.")
|
|
32
|
+
self.refresh_button.setToolTip("Reload the current collection or data object.")
|
|
33
|
+
self.home_button.setToolTip("Go to your iRODS home collection.")
|
|
34
|
+
self.parent_button.setToolTip("Move to the parent collection of the current path.")
|
|
35
|
+
|
|
36
|
+
# --- CRUD operations ---
|
|
37
|
+
self.upload_button.setToolTip("Upload a file or directory to the current iRODS path.")
|
|
38
|
+
self.download_button.setToolTip("Download the selected iRODS item.")
|
|
39
|
+
self.create_coll_button.setToolTip("Create a new collection inside the current path.")
|
|
40
|
+
self.rename_button.setToolTip("Rename the selected iRODS item.")
|
|
41
|
+
self.delete_button.setToolTip("Delete the selected iRODS item.")
|
|
42
|
+
|
|
43
|
+
# --- Browser table ---
|
|
44
|
+
self.browser_table.setToolTip(
|
|
45
|
+
"Browse collections and data objects. Double‑click to open an item."
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# --- Info tabs ---
|
|
49
|
+
self.info_tabs.setToolTip(
|
|
50
|
+
"View metadata, ACLs, replicas, or a preview of the selected item."
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# --- Metadata ---
|
|
54
|
+
self.meta_table.setToolTip(
|
|
55
|
+
"Metadata attached to this item. Click a row to load it for editing."
|
|
56
|
+
)
|
|
57
|
+
self.add_meta_button.setToolTip("Add a new metadata attribute to this item.")
|
|
58
|
+
self.update_meta_button.setToolTip("Update the selected metadata attribute.")
|
|
59
|
+
self.delete_meta_button.setToolTip("Delete the selected metadata attribute.")
|
|
60
|
+
|
|
61
|
+
# --- ACLs ---
|
|
62
|
+
self.acl_table.setToolTip(
|
|
63
|
+
"Access Control List entries. Click a row to load it for editing."
|
|
64
|
+
)
|
|
65
|
+
self.add_acl_button.setToolTip("Add or update an ACL entry for this item.")
|
|
66
|
+
|
|
67
|
+
# --- Replicas ---
|
|
68
|
+
self.replica_table.setToolTip("Replica information for this data object.")
|
|
69
|
+
|
|
70
|
+
# --- Preview ---
|
|
71
|
+
self.preview_browser.setToolTip("Preview the selected data object, if supported.")
|
|
72
|
+
|
|
27
73
|
# --- Rendering helpers moved from controller ---
|
|
28
74
|
|
|
29
75
|
def render_metadata(self, data, irods_path):
|
|
@@ -35,7 +81,7 @@ class Browser(PySide6.QtWidgets.QWidget, Ui_tabBrowser):
|
|
|
35
81
|
|
|
36
82
|
populate_table(self.meta_table, len(data), data)
|
|
37
83
|
current_tab = self.info_tabs.currentWidget().objectName()
|
|
38
|
-
if current_tab == "metadata" and
|
|
84
|
+
if current_tab == "metadata" and len(data) == 0:
|
|
39
85
|
self.no_meta_label.setText(f"Metadata for {irods_path} is empty.")
|
|
40
86
|
self.meta_table.resizeColumnsToContents()
|
|
41
87
|
|
|
@@ -5,8 +5,8 @@ from typing import Optional
|
|
|
5
5
|
|
|
6
6
|
import irods.exception
|
|
7
7
|
import PySide6.QtWidgets
|
|
8
|
-
from ibridges import IrodsPath
|
|
9
8
|
|
|
9
|
+
from ibridges import IrodsPath
|
|
10
10
|
from ibridgesgui.browsertab.browser_model import BrowserModel
|
|
11
11
|
from ibridgesgui.browsertab.irods_browser_service import IrodsBrowserService
|
|
12
12
|
from ibridgesgui.gui_utils import populate_table
|
|
@@ -66,9 +66,11 @@ class BrowserController:
|
|
|
66
66
|
self.model.set_path(irods_path)
|
|
67
67
|
self.ui.input_path.setText(str(irods_path))
|
|
68
68
|
self._load_browser_table()
|
|
69
|
+
self.ui.browser_table.clearSelection()
|
|
69
70
|
|
|
70
71
|
def _refresh_browser(self) -> None:
|
|
71
72
|
path = self.service.path_from_text(self.ui.input_path.text())
|
|
73
|
+
self.ui.browser_table.clearSelection()
|
|
72
74
|
self._set_path(path)
|
|
73
75
|
|
|
74
76
|
def _go_to_parent(self) -> None:
|
|
@@ -197,6 +199,10 @@ class BrowserController:
|
|
|
197
199
|
|
|
198
200
|
self.ui.render_metadata(data, irods_path)
|
|
199
201
|
|
|
202
|
+
def get_possible_acl_strings(self):
|
|
203
|
+
"""Retrieve a list of GUI accepted and cleaned iRODS ACL skills."""
|
|
204
|
+
return self.service.get_acl_strings()
|
|
205
|
+
|
|
200
206
|
def _fill_acl_tab(self, irods_path, row):
|
|
201
207
|
if row not in self.model.acl_cache:
|
|
202
208
|
acls = self.service.get_acls(irods_path)
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import Iterable, Tuple
|
|
5
5
|
|
|
6
|
+
from irods.exception import CAT_NO_ACCESS_PERMISSION
|
|
7
|
+
|
|
6
8
|
from ibridges import IrodsPath
|
|
7
9
|
from ibridges.permissions import Permissions
|
|
8
10
|
from ibridges.util import obj_replicas
|
|
9
|
-
|
|
10
11
|
from ibridgesgui.gui_utils import get_irods_item
|
|
11
12
|
|
|
12
13
|
|
|
@@ -45,9 +46,26 @@ class IrodsBrowserService:
|
|
|
45
46
|
|
|
46
47
|
# -------- preview ---------
|
|
47
48
|
|
|
49
|
+
def is_text_bytes(self, data: bytes) -> bool:
|
|
50
|
+
"""Sniff if file contains text."""
|
|
51
|
+
# Null bytes → definitely binary
|
|
52
|
+
if b"\x00" in data:
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
# Try common encodings
|
|
56
|
+
for enc in ("utf-8", "latin-1", "cp1252"):
|
|
57
|
+
try:
|
|
58
|
+
data.decode(enc)
|
|
59
|
+
return True
|
|
60
|
+
except UnicodeDecodeError:
|
|
61
|
+
continue
|
|
62
|
+
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
|
|
48
66
|
def compute_preview(self, irods_path: IrodsPath):
|
|
49
67
|
"""Return preview content for a collection or data object."""
|
|
50
|
-
# Collections
|
|
68
|
+
# Collections
|
|
51
69
|
if irods_path.collection_exists():
|
|
52
70
|
subcolls, objs = self.list_collection(irods_path)
|
|
53
71
|
content = ["Collections:", "-----------------"]
|
|
@@ -56,10 +74,21 @@ class IrodsBrowserService:
|
|
|
56
74
|
content.extend([do.name for do in objs])
|
|
57
75
|
return content
|
|
58
76
|
|
|
59
|
-
# Data objects
|
|
77
|
+
# Data objects
|
|
60
78
|
if irods_path.dataobject_exists():
|
|
61
|
-
|
|
62
|
-
|
|
79
|
+
try:
|
|
80
|
+
# Read only the first few KB for sniffing
|
|
81
|
+
with irods_path.open("r") as stream:
|
|
82
|
+
head = stream.read(4096)
|
|
83
|
+
except Exception as error:
|
|
84
|
+
return [
|
|
85
|
+
f"No Preview for: {irods_path}",
|
|
86
|
+
repr(error),
|
|
87
|
+
"Storage resource might be down.",
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
# Decide based on content, not suffix
|
|
91
|
+
if self.is_text_bytes(head):
|
|
63
92
|
try:
|
|
64
93
|
return self.stream_obj(irods_path)
|
|
65
94
|
except Exception as error:
|
|
@@ -68,6 +97,7 @@ class IrodsBrowserService:
|
|
|
68
97
|
repr(error),
|
|
69
98
|
"Storage resource might be down.",
|
|
70
99
|
]
|
|
100
|
+
|
|
71
101
|
return [f"No Preview for: {irods_path}"]
|
|
72
102
|
|
|
73
103
|
return [f"No Preview for: {irods_path}"]
|
|
@@ -90,9 +120,41 @@ class IrodsBrowserService:
|
|
|
90
120
|
except Exception as err:
|
|
91
121
|
raise RuntimeError(f"Failed to load metadata for {irods_path}: {err}") from err
|
|
92
122
|
|
|
123
|
+
def find_irods_exception(self, exc):
|
|
124
|
+
"""Walk the exception chain to find the underlying iRODS exception."""
|
|
125
|
+
# NOTE: Work around for ibridges #412
|
|
126
|
+
seen = set()
|
|
127
|
+
stack = [exc]
|
|
128
|
+
|
|
129
|
+
while stack:
|
|
130
|
+
current = stack.pop()
|
|
131
|
+
if current in seen:
|
|
132
|
+
continue
|
|
133
|
+
seen.add(current)
|
|
134
|
+
|
|
135
|
+
# Found the real iRODS exception
|
|
136
|
+
if isinstance(current, CAT_NO_ACCESS_PERMISSION):
|
|
137
|
+
return current
|
|
138
|
+
|
|
139
|
+
# Walk deeper
|
|
140
|
+
if current.__cause__:
|
|
141
|
+
stack.append(current.__cause__)
|
|
142
|
+
if current.__context__:
|
|
143
|
+
stack.append(current.__context__)
|
|
144
|
+
|
|
145
|
+
return None
|
|
146
|
+
|
|
147
|
+
|
|
93
148
|
def add_metadata(self, path: IrodsPath, key: str, value: str, units: str):
|
|
94
149
|
"""Add metadata to coll or obj."""
|
|
95
|
-
|
|
150
|
+
try:
|
|
151
|
+
path.meta.add(key, value, units)
|
|
152
|
+
except Exception as err:
|
|
153
|
+
# user has no permission to modify metadata
|
|
154
|
+
irods_exc = self.find_irods_exception(err)
|
|
155
|
+
if irods_exc:
|
|
156
|
+
raise irods_exc from err
|
|
157
|
+
raise err
|
|
96
158
|
|
|
97
159
|
def update_metadata(
|
|
98
160
|
self,
|
|
@@ -105,20 +167,51 @@ class IrodsBrowserService:
|
|
|
105
167
|
new_units: str,
|
|
106
168
|
):
|
|
107
169
|
"""Update a single AVU on a path."""
|
|
108
|
-
|
|
109
|
-
|
|
170
|
+
try:
|
|
171
|
+
# Retrieve the specific AVU
|
|
172
|
+
avu = path.meta[old_key, old_value, old_units]
|
|
110
173
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
174
|
+
# Add new and delete old
|
|
175
|
+
path.meta.add(new_key, new_value, new_units)
|
|
176
|
+
path.meta.delete(avu.key, avu.value, avu.units)
|
|
177
|
+
except Exception as err:
|
|
178
|
+
# user has no permission to modify metadata
|
|
179
|
+
irods_exc = self.find_irods_exception(err)
|
|
180
|
+
if irods_exc:
|
|
181
|
+
raise irods_exc from err
|
|
182
|
+
raise err
|
|
115
183
|
|
|
116
184
|
def delete_metadata(self, path: IrodsPath, key: str, value: str, units: str):
|
|
117
185
|
"""Delete metadata."""
|
|
118
|
-
|
|
186
|
+
try:
|
|
187
|
+
path.meta.delete(key, value, units)
|
|
188
|
+
except Exception as err:
|
|
189
|
+
# user has no permission to modify metadata
|
|
190
|
+
irods_exc = self.find_irods_exception(err)
|
|
191
|
+
if irods_exc:
|
|
192
|
+
raise irods_exc from err
|
|
193
|
+
raise err
|
|
119
194
|
|
|
120
195
|
# -------- ACLs / permissions --------
|
|
121
196
|
|
|
197
|
+
PERM_MAP = {
|
|
198
|
+
"read_object": "read",
|
|
199
|
+
"modify_object": "write",
|
|
200
|
+
"null": "delete permission",
|
|
201
|
+
"delete_object": "delete",
|
|
202
|
+
"create_object": "create"
|
|
203
|
+
}
|
|
204
|
+
REVERSE_PERM_MAP = {v: k for k, v in PERM_MAP.items()}
|
|
205
|
+
|
|
206
|
+
def get_acl_strings(self):
|
|
207
|
+
"""Retrieve all possible acl modes from the irods instance and filter them."""
|
|
208
|
+
perm = Permissions(self.session, self.session.home)
|
|
209
|
+
# remove metadata permissions github.com/irods/irods/issues/6813
|
|
210
|
+
avail = [self.PERM_MAP.get(perm_str, perm_str)
|
|
211
|
+
for (perm_str, _) in perm.available_permissions.items()
|
|
212
|
+
if "metadata" not in perm_str]
|
|
213
|
+
return avail
|
|
214
|
+
|
|
122
215
|
def normalize_acls(self, acls):
|
|
123
216
|
"""Normalize iRODS ACLs into UI-friendly form."""
|
|
124
217
|
clean = []
|
|
@@ -152,8 +245,9 @@ class IrodsBrowserService:
|
|
|
152
245
|
"""Apply an ACL change to a collection or data object."""
|
|
153
246
|
obj = get_irods_item(path)
|
|
154
247
|
perms = Permissions(self.session, obj)
|
|
248
|
+
irods_access = self.REVERSE_PERM_MAP[access]
|
|
155
249
|
perms.set(
|
|
156
|
-
perm=
|
|
250
|
+
perm=irods_access,
|
|
157
251
|
user=user_name,
|
|
158
252
|
zone=user_zone,
|
|
159
253
|
recursive=recursive,
|
|
@@ -19,9 +19,6 @@ from json import JSONDecodeError
|
|
|
19
19
|
from pathlib import Path
|
|
20
20
|
from typing import Union
|
|
21
21
|
|
|
22
|
-
from ibridges.cli.config import IbridgesConf
|
|
23
|
-
from ibridges.session import Session, _translate_irods_error
|
|
24
|
-
from ibridges.util import open_irodsa
|
|
25
22
|
from irods.auth.pam import PamLoginException
|
|
26
23
|
from irods.connection import PlainTextPAMPasswordError
|
|
27
24
|
from irods.exception import (
|
|
@@ -33,6 +30,10 @@ from irods.exception import (
|
|
|
33
30
|
)
|
|
34
31
|
from irods.session import iRODSSession
|
|
35
32
|
|
|
33
|
+
from ibridges.cli.config import IbridgesConf
|
|
34
|
+
from ibridges.session import Session, _translate_irods_error
|
|
35
|
+
from ibridges.util import open_irodsa
|
|
36
|
+
|
|
36
37
|
try:
|
|
37
38
|
from importlib_metadata import version # Python < 3.10
|
|
38
39
|
except ImportError:
|
|
@@ -13,11 +13,11 @@ from typing import Iterable, Optional, Union
|
|
|
13
13
|
import PySide6.QtCore
|
|
14
14
|
import PySide6.QtUiTools
|
|
15
15
|
import PySide6.QtWidgets
|
|
16
|
-
from ibridges import IrodsPath
|
|
17
|
-
from ibridges.executor import Operations
|
|
18
16
|
from jsonschema import ValidationError, validate
|
|
19
17
|
|
|
20
18
|
import ibridgesgui.md_schemas
|
|
19
|
+
from ibridges import IrodsPath
|
|
20
|
+
from ibridges.executor import Operations
|
|
21
21
|
from ibridgesgui.config import get_last_ienv_path, is_session_from_config
|
|
22
22
|
|
|
23
23
|
try:
|
|
@@ -160,7 +160,9 @@ def prep_session_for_copy(session, error_label) -> Optional[Path]:
|
|
|
160
160
|
last_env_path = Path.home() / ".irods" / get_last_ienv_path()
|
|
161
161
|
session_env_path = session.irods_session.env_file
|
|
162
162
|
|
|
163
|
-
|
|
163
|
+
# irods session does not always contain the env path.
|
|
164
|
+
# this is the case when the session is created with a password
|
|
165
|
+
if session_env_path and (last_env_path != session_env_path):
|
|
164
166
|
error_label.setText(
|
|
165
167
|
"A different iRODS configuration was loaded outside this app. "
|
|
166
168
|
"Restart the session to continue."
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
|
|
5
|
-
from ibridges.resources import Resources
|
|
6
5
|
from PySide6 import QtCore, QtWidgets
|
|
7
6
|
|
|
7
|
+
from ibridges.resources import Resources
|
|
8
8
|
from ibridgesgui.config import CONFIG_DIR
|
|
9
9
|
from ibridgesgui.gui_utils import UI_FILE_DIR, load_ui, populate_table, populate_textfield
|
|
10
|
+
from ibridgesgui.popup_widgets.resc_tree import RescInfoDialog
|
|
10
11
|
from ibridgesgui.ui_files.tabInfo import Ui_tabInfo
|
|
11
12
|
|
|
12
13
|
|
|
@@ -20,6 +21,7 @@ class Info(QtWidgets.QWidget, Ui_tabInfo):
|
|
|
20
21
|
self.session = session
|
|
21
22
|
|
|
22
23
|
self.refresh_button.clicked.connect(self.refresh_info)
|
|
24
|
+
self.inspect_button.clicked.connect(self.inspect_rescs_info)
|
|
23
25
|
self.refresh_info()
|
|
24
26
|
|
|
25
27
|
def _load_ui(self):
|
|
@@ -28,6 +30,11 @@ class Info(QtWidgets.QWidget, Ui_tabInfo):
|
|
|
28
30
|
else:
|
|
29
31
|
load_ui(UI_FILE_DIR / "tabInfo.ui", self)
|
|
30
32
|
|
|
33
|
+
def inspect_rescs_info(self):
|
|
34
|
+
"""Open popup for rescs info."""
|
|
35
|
+
dlg = RescInfoDialog(self.session, self)
|
|
36
|
+
dlg.exec()
|
|
37
|
+
|
|
31
38
|
def refresh_info(self):
|
|
32
39
|
"""Refetch infor from iRODS."""
|
|
33
40
|
with self._wait_cursor():
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import irods
|
|
4
4
|
import irods.exception
|
|
5
|
-
from ibridges import IrodsPath
|
|
6
5
|
from PySide6 import QtCore, QtGui, QtWidgets
|
|
7
6
|
|
|
7
|
+
from ibridges import IrodsPath
|
|
8
|
+
|
|
8
9
|
|
|
9
10
|
class IrodsTreeModel(QtGui.QStandardItemModel):
|
|
10
11
|
"""Model for an iRODS tree view with lazy loading and path lookup."""
|
|
@@ -5,11 +5,11 @@ import os
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
|
-
from ibridges import Session
|
|
9
|
-
from ibridges.session import LoginError, PasswordError
|
|
10
8
|
from irods.exception import ResourceDoesNotExist
|
|
11
9
|
from PySide6.QtWidgets import QDialog, QLineEdit
|
|
12
10
|
|
|
11
|
+
from ibridges import Session
|
|
12
|
+
from ibridges.session import LoginError, PasswordError
|
|
13
13
|
from ibridgesgui.config import (
|
|
14
14
|
IRODSA,
|
|
15
15
|
check_irods_config,
|
|
@@ -129,7 +129,10 @@ class LoginDialog(QDialog, Ui_irodsLogin):
|
|
|
129
129
|
f.write(password)
|
|
130
130
|
return Session(irods_env=env_path)
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
session = Session(irods_env=env_path, password=password)
|
|
133
|
+
session.write_pam_password()
|
|
134
|
+
|
|
135
|
+
return session
|
|
133
136
|
|
|
134
137
|
def _on_connect(self):
|
|
135
138
|
self.error_label.clear()
|
|
@@ -5,7 +5,7 @@ import logging
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
7
|
from PySide6.QtGui import QAction
|
|
8
|
-
from PySide6.QtWidgets import QMainWindow, QMessageBox
|
|
8
|
+
from PySide6.QtWidgets import QApplication, QMainWindow, QMessageBox
|
|
9
9
|
|
|
10
10
|
from ibridgesgui.gui_utils import UI_FILE_DIR, load_ui
|
|
11
11
|
from ibridgesgui.mainmenu import (
|
|
@@ -98,7 +98,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
98
98
|
self.session_manager.disconnect()
|
|
99
99
|
|
|
100
100
|
def _on_exit(self) -> None:
|
|
101
|
-
self.close()
|
|
101
|
+
#self.close()
|
|
102
|
+
QApplication.quit()
|
|
102
103
|
|
|
103
104
|
def _on_create_env(self) -> None:
|
|
104
105
|
widget = CheckConfig(self.logger, Path("~/.irods").expanduser())
|
|
@@ -38,7 +38,8 @@ class TabManager:
|
|
|
38
38
|
|
|
39
39
|
def _create_search(self, session, app_name: str, _logger) -> Search:
|
|
40
40
|
browser = self.loaded_tabs.get("Browser")
|
|
41
|
-
|
|
41
|
+
browsercontroller = getattr(browser, "controller", None)
|
|
42
|
+
return Search(session, app_name, browsercontroller)
|
|
42
43
|
|
|
43
44
|
def _create_info(self, session, _app_name, _logger) -> Info:
|
|
44
45
|
return Info(session)
|
|
@@ -5,6 +5,7 @@ from ibridgesgui.popup_widgets.create_collection import CreateCollection
|
|
|
5
5
|
from ibridgesgui.popup_widgets.create_directory import CreateDirectory
|
|
6
6
|
from ibridgesgui.popup_widgets.download_data import DownloadData
|
|
7
7
|
from ibridgesgui.popup_widgets.rename_item import Rename
|
|
8
|
+
from ibridgesgui.popup_widgets.resc_tree import RescInfoDialog
|
|
8
9
|
from ibridgesgui.popup_widgets.upload_data import UploadData
|
|
9
10
|
|
|
10
11
|
__all__ = [
|
|
@@ -14,4 +15,5 @@ __all__ = [
|
|
|
14
15
|
"CheckConfig",
|
|
15
16
|
"UploadData",
|
|
16
17
|
"DownloadData",
|
|
18
|
+
"RescInfoDialog"
|
|
17
19
|
]
|