ibridgesgui 0.2.1__tar.gz → 0.2.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-0.2.1 → ibridgesgui-0.2.2}/PKG-INFO +10 -3
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/README.md +8 -1
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/getting-started.qmd +1 -2
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/__main__.py +21 -7
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/_version.py +2 -2
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/browser.py +1 -8
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/gui_utils.py +1 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/irods_tree_model.py +4 -1
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/login.py +35 -3
- ibridgesgui-0.2.2/ibridgesgui/logviewer.py +50 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/popup_widgets.py +27 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/search.py +2 -1
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/sync.py +7 -5
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/configCheck.py +8 -3
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/configCheck.ui +10 -1
- ibridgesgui-0.2.2/ibridgesgui/ui_files/tabLogging.py +49 -0
- ibridgesgui-0.2.2/ibridgesgui/ui_files/tabLogging.ui +51 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/welcome.py +2 -1
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui.egg-info/PKG-INFO +10 -3
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui.egg-info/SOURCES.txt +3 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui.egg-info/requires.txt +1 -1
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/pyproject.toml +1 -1
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/requirements_dev.txt +1 -1
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.flake8 +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.github/dependabot.yml +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.github/workflows/linter.yml +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.github/workflows/publish.yml +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.github/workflows/pypi_release.yml +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.gitignore +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/LICENSE +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/_quarto.yml +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/info.qmd +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/add_check_config.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/add_new_config.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/browser.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/delete.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/login.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/metadata.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/permissions.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/replicas.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/search.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/start_ibridges.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/sync.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/userdoc.qmd +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/__init__.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/config.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/arrow-left.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/arrow-right.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/arrow-up.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/home.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/iBridges.ico +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/loading_circle.gif +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/logo.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/nosync.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/refresh.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/syncing.png +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/info.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/threads.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/ExampleTab.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/ExampleTab.ui +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/MainMenu.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/MainMenu.ui +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/__init__.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/createCollection.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/createCollection.ui +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/irodsLogin.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/irodsLogin.ui +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/renameItem.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/renameItem.ui +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabBrowser.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabBrowser.ui +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabInfo.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabInfo.ui +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabSearch.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabSearch.ui +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabSync.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabSync.ui +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/welcome.py +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/welcome.ui +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui.egg-info/dependency_links.txt +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui.egg-info/entry_points.txt +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui.egg-info/top_level.txt +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/index.qmd +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/requirements.txt +0 -0
- {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ibridgesgui
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Graphical user interface for accessing data and metadata on iRODS servers.
|
|
5
5
|
Author-email: Christine Staiger <c.staiger@uu.nl>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -690,7 +690,7 @@ Requires-Python: >=3.9
|
|
|
690
690
|
Description-Content-Type: text/markdown
|
|
691
691
|
License-File: LICENSE
|
|
692
692
|
Requires-Dist: PyQt6>=6.4.2
|
|
693
|
-
Requires-Dist: ibridges==0.2.
|
|
693
|
+
Requires-Dist: ibridges==0.2.2
|
|
694
694
|
Requires-Dist: setproctitle==1.3.3
|
|
695
695
|
Requires-Dist: importlib-resources; python_version <= "3.10"
|
|
696
696
|
Provides-Extra: test
|
|
@@ -732,11 +732,18 @@ The git repository contains a generic *iRODS* graphical user interface. The iRO
|
|
|
732
732
|
- Safe default options when working with your data.
|
|
733
733
|
|
|
734
734
|
## Installation
|
|
735
|
-
-
|
|
735
|
+
- The python package
|
|
736
736
|
|
|
737
737
|
```bash
|
|
738
738
|
pip install ibridgesgui
|
|
739
739
|
```
|
|
740
|
+
|
|
741
|
+
- A specific branch of the git repository (testers, developers)
|
|
742
|
+
|
|
743
|
+
```bash
|
|
744
|
+
pip install git+https://github.com/chStaiger/iBridges-Gui.git@branch-name
|
|
745
|
+
```
|
|
746
|
+
|
|
740
747
|
- Locally from code (for developers)
|
|
741
748
|
|
|
742
749
|
```bash
|
|
@@ -30,11 +30,18 @@ The git repository contains a generic *iRODS* graphical user interface. The iRO
|
|
|
30
30
|
- Safe default options when working with your data.
|
|
31
31
|
|
|
32
32
|
## Installation
|
|
33
|
-
-
|
|
33
|
+
- The python package
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
36
|
pip install ibridgesgui
|
|
37
37
|
```
|
|
38
|
+
|
|
39
|
+
- A specific branch of the git repository (testers, developers)
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install git+https://github.com/chStaiger/iBridges-Gui.git@branch-name
|
|
43
|
+
```
|
|
44
|
+
|
|
38
45
|
- Locally from code (for developers)
|
|
39
46
|
|
|
40
47
|
```bash
|
|
@@ -12,9 +12,9 @@ import setproctitle
|
|
|
12
12
|
|
|
13
13
|
from ibridgesgui.browser import Browser
|
|
14
14
|
from ibridgesgui.config import get_log_level, init_logger, set_log_level
|
|
15
|
-
from ibridgesgui.gui_utils import UI_FILE_DIR
|
|
16
15
|
from ibridgesgui.info import Info
|
|
17
16
|
from ibridgesgui.login import Login
|
|
17
|
+
from ibridgesgui.logviewer import LogViewer
|
|
18
18
|
from ibridgesgui.popup_widgets import CheckConfig
|
|
19
19
|
from ibridgesgui.search import Search
|
|
20
20
|
from ibridgesgui.sync import Sync
|
|
@@ -34,10 +34,9 @@ class MainMenu(PyQt6.QtWidgets.QMainWindow, Ui_MainWindow):
|
|
|
34
34
|
def __init__(self, app_name):
|
|
35
35
|
"""Initialise the main window."""
|
|
36
36
|
super().__init__()
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
PyQt6.uic.loadUi(UI_FILE_DIR / "MainMenu.ui", self)
|
|
37
|
+
super().setupUi(self)
|
|
38
|
+
|
|
39
|
+
app.aboutToQuit.connect(self.close_event)
|
|
41
40
|
|
|
42
41
|
self.logger = logging.getLogger(app_name)
|
|
43
42
|
|
|
@@ -49,6 +48,7 @@ class MainMenu(PyQt6.QtWidgets.QMainWindow, Ui_MainWindow):
|
|
|
49
48
|
"tabSync": self.init_sync_tab,
|
|
50
49
|
"tabSearch": self.init_search_tab,
|
|
51
50
|
"tabInfo": self.init_info_tab,
|
|
51
|
+
"tabLog": self.init_log_tab
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
self.session = None
|
|
@@ -61,6 +61,7 @@ class MainMenu(PyQt6.QtWidgets.QMainWindow, Ui_MainWindow):
|
|
|
61
61
|
self.action_check_configuration.triggered.connect(self.inspect_env_file)
|
|
62
62
|
self.tab_widget.setCurrentIndex(0)
|
|
63
63
|
|
|
64
|
+
|
|
64
65
|
def disconnect(self):
|
|
65
66
|
"""Close iRODS session."""
|
|
66
67
|
self.error_label.clear()
|
|
@@ -82,6 +83,7 @@ class MainMenu(PyQt6.QtWidgets.QMainWindow, Ui_MainWindow):
|
|
|
82
83
|
login_window = Login(self.session_dict, self.app_name)
|
|
83
84
|
login_window.exec()
|
|
84
85
|
# Trick to get the session object from the QDialog
|
|
86
|
+
|
|
85
87
|
if "session" in self.session_dict:
|
|
86
88
|
self.session = self.session_dict["session"]
|
|
87
89
|
try:
|
|
@@ -89,6 +91,8 @@ class MainMenu(PyQt6.QtWidgets.QMainWindow, Ui_MainWindow):
|
|
|
89
91
|
except:
|
|
90
92
|
self.session = None
|
|
91
93
|
raise
|
|
94
|
+
else:
|
|
95
|
+
self.logger.exception("No session created. %s", self.session_dict)
|
|
92
96
|
|
|
93
97
|
def exit(self):
|
|
94
98
|
"""Quit program."""
|
|
@@ -106,6 +110,11 @@ class MainMenu(PyQt6.QtWidgets.QMainWindow, Ui_MainWindow):
|
|
|
106
110
|
else:
|
|
107
111
|
pass
|
|
108
112
|
|
|
113
|
+
def close_event(self):
|
|
114
|
+
"""Close program properly if main window is closed."""
|
|
115
|
+
self.disconnect()
|
|
116
|
+
sys.exit()
|
|
117
|
+
|
|
109
118
|
def setup_tabs(self):
|
|
110
119
|
"""Init tab view."""
|
|
111
120
|
for tab_fun in self.ui_tabs_lookup.values():
|
|
@@ -122,6 +131,11 @@ class MainMenu(PyQt6.QtWidgets.QMainWindow, Ui_MainWindow):
|
|
|
122
131
|
irods_info = Info(self.session)
|
|
123
132
|
self.tab_widget.addTab(irods_info, "Info")
|
|
124
133
|
|
|
134
|
+
def init_log_tab(self):
|
|
135
|
+
"""Create log tab."""
|
|
136
|
+
ibridges_log = LogViewer(self.logger)
|
|
137
|
+
self.tab_widget.addTab(ibridges_log, "Logs")
|
|
138
|
+
|
|
125
139
|
def init_browser_tab(self):
|
|
126
140
|
"""Create browser."""
|
|
127
141
|
self.irods_browser = Browser(self.session, self.app_name)
|
|
@@ -156,8 +170,8 @@ def main():
|
|
|
156
170
|
if log_level is not None:
|
|
157
171
|
init_logger(THIS_APPLICATION, log_level)
|
|
158
172
|
else:
|
|
159
|
-
set_log_level("
|
|
160
|
-
init_logger(THIS_APPLICATION, "
|
|
173
|
+
set_log_level("debug")
|
|
174
|
+
init_logger(THIS_APPLICATION, "debug")
|
|
161
175
|
main_widget = PyQt6.QtWidgets.QStackedWidget()
|
|
162
176
|
main_app = MainMenu(THIS_APPLICATION)
|
|
163
177
|
main_widget.addWidget(main_app)
|
|
@@ -48,14 +48,7 @@ class Browser(PyQt6.QtWidgets.QWidget, Ui_tabBrowser):
|
|
|
48
48
|
self.session, f"/{self.session.zone}/home/{self.session.username}"
|
|
49
49
|
)
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
self.root_coll = IrodsPath(self.session, root_path).collection
|
|
53
|
-
elif IrodsPath(self.session, f"/{self.session.zone}/home").collection_exists():
|
|
54
|
-
self.root_coll = IrodsPath(self.session, f"/{self.session.zone}/home").collection
|
|
55
|
-
else:
|
|
56
|
-
self.error_label.setText(
|
|
57
|
-
'Cannot set root collection. Set "irods_home" in your environment.json'
|
|
58
|
-
)
|
|
51
|
+
self.root_coll = IrodsPath(self.session, root_path).collection
|
|
59
52
|
self.reset_path()
|
|
60
53
|
self.browse()
|
|
61
54
|
|
|
@@ -105,9 +105,12 @@ class IrodsTreeModel(PyQt6.QtGui.QStandardItemModel):
|
|
|
105
105
|
_, level, _, _, _, abs_irods_path = tree_item_data
|
|
106
106
|
parent_coll = IrodsPath(self.session, abs_irods_path).collection
|
|
107
107
|
|
|
108
|
+
# the irods root also contains the irods root as subcollection
|
|
109
|
+
subcolls = [c for c in parent_coll.subcollections if c.path != "/"]
|
|
110
|
+
dataobjs = parent_coll.data_objects
|
|
108
111
|
# we assume that tree_item has no children yet.
|
|
109
112
|
new_nodes = {}
|
|
110
|
-
for item in
|
|
113
|
+
for item in subcolls + dataobjs:
|
|
111
114
|
row = self._tree_row_from_irods_item(item, parent_coll.id, int(level))
|
|
112
115
|
tree_item.appendRow(row)
|
|
113
116
|
new_nodes[item.id] = tree_item.child(tree_item.rowCount() - 1)
|
|
@@ -4,8 +4,10 @@ import logging
|
|
|
4
4
|
import sys
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
|
-
from ibridges import Session
|
|
7
|
+
from ibridges import IrodsPath, Session
|
|
8
|
+
from ibridges.resources import Resources
|
|
8
9
|
from ibridges.session import LoginError, PasswordError
|
|
10
|
+
from irods.exception import ResourceDoesNotExist
|
|
9
11
|
from PyQt6.QtWidgets import QDialog, QLineEdit
|
|
10
12
|
from PyQt6.uic import loadUi
|
|
11
13
|
|
|
@@ -77,7 +79,6 @@ class Login(QDialog, Ui_irodsLogin):
|
|
|
77
79
|
else:
|
|
78
80
|
session = Session(irods_env=env_file, password=self.password_field.text())
|
|
79
81
|
self.logger.debug("Login with %s and password from prompt.", env_file)
|
|
80
|
-
self.session_dict["session"] = session
|
|
81
82
|
self.logger.info(
|
|
82
83
|
"Logged in as %s to %s; working coll %s",
|
|
83
84
|
session.username,
|
|
@@ -85,17 +86,48 @@ class Login(QDialog, Ui_irodsLogin):
|
|
|
85
86
|
session.home,
|
|
86
87
|
)
|
|
87
88
|
session.write_pam_password()
|
|
89
|
+
self.session_dict["session"] = session
|
|
88
90
|
set_last_ienv_path(env_file.name)
|
|
89
|
-
self.close()
|
|
90
91
|
except LoginError:
|
|
91
92
|
self.error_label.setText("irods_environment.json not setup correctly.")
|
|
93
|
+
self.logger.error("irods_environment.json not setup correctly.")
|
|
92
94
|
except PasswordError:
|
|
93
95
|
self.error_label.setText("Wrong password!")
|
|
96
|
+
self.logger.error("Wrong password provided.")
|
|
94
97
|
except ConnectionError:
|
|
95
98
|
self.error_label.setText(
|
|
96
99
|
"Cannot connect to server. Check Internet, host name and port."
|
|
97
100
|
)
|
|
101
|
+
self.logger.exception("Network error.")
|
|
98
102
|
except Exception as err:
|
|
99
103
|
log_path = Path("~/.ibridges")
|
|
100
104
|
self.logger.exception("Failed to login: %s", repr(err))
|
|
101
105
|
self.error_label.setText(f"Login failed, consult the log file(s) in {log_path}")
|
|
106
|
+
|
|
107
|
+
#check irods_home
|
|
108
|
+
fail_home = True
|
|
109
|
+
if not IrodsPath(self.session_dict["session"]).collection_exists():
|
|
110
|
+
self.error_label.setText(f'"irods_home": "{session.home}" does not exist.')
|
|
111
|
+
self.logger.error("irods_home does not exist.")
|
|
112
|
+
else:
|
|
113
|
+
fail_home = False
|
|
114
|
+
|
|
115
|
+
#check existance of default resource
|
|
116
|
+
fail_resc = True
|
|
117
|
+
try:
|
|
118
|
+
resc = Resources(self.session_dict["session"]).get_resource(session.default_resc)
|
|
119
|
+
if resc.parent is None:
|
|
120
|
+
fail_resc = False
|
|
121
|
+
else:
|
|
122
|
+
self.error_label.setText(f'"default_resource": "{session.default_resc}" not valid.')
|
|
123
|
+
except ResourceDoesNotExist:
|
|
124
|
+
self.error_label.setText(
|
|
125
|
+
f'"default_resource": "{session.default_resc}" does not exist.')
|
|
126
|
+
self.logger.error("Default resource does not exist.")
|
|
127
|
+
except AttributeError:
|
|
128
|
+
self.error_label.setText(f'"default_resource": "{session.default_resc}" not valid.')
|
|
129
|
+
|
|
130
|
+
if fail_resc or fail_home:
|
|
131
|
+
del self.session_dict["session"]
|
|
132
|
+
else:
|
|
133
|
+
self.close()
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Logging tab."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
import PyQt6
|
|
7
|
+
|
|
8
|
+
from ibridgesgui.config import CONFIG_DIR
|
|
9
|
+
from ibridgesgui.gui_utils import UI_FILE_DIR
|
|
10
|
+
from ibridgesgui.ui_files.tabLogging import Ui_tabLogging
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class QTextEditLogger(logging.Handler, PyQt6.QtCore.QObject):
|
|
14
|
+
"""Logging in a Qt text browser."""
|
|
15
|
+
|
|
16
|
+
append_plain_text = PyQt6.QtCore.pyqtSignal(str)
|
|
17
|
+
|
|
18
|
+
def __init__(self, text_browser):
|
|
19
|
+
"""Initialise."""
|
|
20
|
+
super().__init__()
|
|
21
|
+
PyQt6.QtCore.QObject.__init__(self)
|
|
22
|
+
self.widget = text_browser
|
|
23
|
+
self.widget.setReadOnly(True)
|
|
24
|
+
self.append_plain_text.connect(self.widget.insertPlainText)
|
|
25
|
+
|
|
26
|
+
def emit(self, record):
|
|
27
|
+
"""Emit when new logging accurs."""
|
|
28
|
+
msg = self.format(record)+"\n"
|
|
29
|
+
self.append_plain_text.emit(msg)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class LogViewer(PyQt6.QtWidgets.QWidget, Ui_tabLogging):
|
|
33
|
+
"""Set iBridges logging in GUI."""
|
|
34
|
+
|
|
35
|
+
def __init__(self, logger):
|
|
36
|
+
"""Initialise the tab."""
|
|
37
|
+
super().__init__()
|
|
38
|
+
if getattr(sys, "frozen", False):
|
|
39
|
+
super().setupUi(self)
|
|
40
|
+
else:
|
|
41
|
+
PyQt6.uic.loadUi(UI_FILE_DIR / "tabLogging.ui", self)
|
|
42
|
+
|
|
43
|
+
self.logger = logger
|
|
44
|
+
self.log_label.setText(str(CONFIG_DIR))
|
|
45
|
+
self.log_text = QTextEditLogger(self.log_browser)
|
|
46
|
+
self.log_text.setFormatter(
|
|
47
|
+
logging.Formatter(
|
|
48
|
+
'%(asctime)s %(levelname)s %(module)s %(funcName)s %(message)s'))
|
|
49
|
+
self.logger.addHandler(self.log_text)
|
|
50
|
+
self.logger.setLevel(logging.DEBUG)
|
|
@@ -6,6 +6,7 @@ import sys
|
|
|
6
6
|
|
|
7
7
|
import irods
|
|
8
8
|
from ibridges import IrodsPath
|
|
9
|
+
from ibridges.util import find_environment_provider, get_environment_providers
|
|
9
10
|
from PyQt6 import QtCore
|
|
10
11
|
from PyQt6.QtWidgets import QDialog, QFileDialog
|
|
11
12
|
from PyQt6.uic import loadUi
|
|
@@ -140,8 +141,10 @@ class CheckConfig(QDialog, Ui_configCheck):
|
|
|
140
141
|
self.env_path = env_path
|
|
141
142
|
self.setWindowTitle("Create, edit and inspect iRODS environment")
|
|
142
143
|
self._init_env_box()
|
|
144
|
+
self._init_template_box()
|
|
143
145
|
|
|
144
146
|
self.envbox.activated.connect(self.load_env)
|
|
147
|
+
self.template_box.activated.connect(self.load_template)
|
|
145
148
|
self.new_button.clicked.connect(self.create_env)
|
|
146
149
|
self.check_button.clicked.connect(self.check_env)
|
|
147
150
|
self.save_button.clicked.connect(self.save_env)
|
|
@@ -155,6 +158,30 @@ class CheckConfig(QDialog, Ui_configCheck):
|
|
|
155
158
|
self.envbox.addItems(env_jsons)
|
|
156
159
|
self.envbox.setCurrentIndex(0)
|
|
157
160
|
|
|
161
|
+
def _init_template_box(self):
|
|
162
|
+
self.template_box.clear()
|
|
163
|
+
providers = get_environment_providers()
|
|
164
|
+
|
|
165
|
+
if len(providers) == 0:
|
|
166
|
+
self.template_box.hide()
|
|
167
|
+
return
|
|
168
|
+
|
|
169
|
+
templates = [key+": "+descr for p in providers
|
|
170
|
+
for key, descr in p.descriptions.items()]
|
|
171
|
+
if len(templates) > 0:
|
|
172
|
+
self.template_box.addItems(templates)
|
|
173
|
+
self.template_box.setCurrentIndex(0)
|
|
174
|
+
|
|
175
|
+
def load_template(self):
|
|
176
|
+
"""Load environment template into text field."""
|
|
177
|
+
self.error_label.clear()
|
|
178
|
+
template = self.template_box.currentText()
|
|
179
|
+
key = template.split(": ")[0]
|
|
180
|
+
env_json = find_environment_provider(get_environment_providers(), key).\
|
|
181
|
+
environment_json(key, "USERNAME").split("\n")
|
|
182
|
+
populate_textfield(self.env_field, env_json)
|
|
183
|
+
self.error_label.setText("Please fill in your user name.")
|
|
184
|
+
|
|
158
185
|
def load_env(self):
|
|
159
186
|
"""Load json into text field."""
|
|
160
187
|
self.error_label.clear()
|
|
@@ -184,7 +184,8 @@ class Search(PyQt6.QtWidgets.QWidget, Ui_tabSearch):
|
|
|
184
184
|
key.text(): "%" if val.text() == "" else val.text()
|
|
185
185
|
for key, val in zip(self.keys, self.vals)
|
|
186
186
|
}
|
|
187
|
-
|
|
187
|
+
if "" in key_vals:
|
|
188
|
+
del key_vals[""]
|
|
188
189
|
|
|
189
190
|
path = self.path_field.text() if self.path_field.text() != "" else None
|
|
190
191
|
checksum = self.checksum_field.text() if self.checksum_field.text() != "" else None
|
|
@@ -89,7 +89,7 @@ class Sync(PyQt6.QtWidgets.QWidget, Ui_tabSync):
|
|
|
89
89
|
def irods_root(self):
|
|
90
90
|
"""Retrieve lowest visible level in the iRODS tree for the user."""
|
|
91
91
|
lowest = IrodsPath(self.session).absolute()
|
|
92
|
-
while lowest.parent.exists():
|
|
92
|
+
while lowest.parent.exists() and str(lowest) != "/":
|
|
93
93
|
lowest = lowest.parent
|
|
94
94
|
return lowest
|
|
95
95
|
|
|
@@ -276,10 +276,12 @@ class Sync(PyQt6.QtWidgets.QWidget, Ui_tabSync):
|
|
|
276
276
|
return
|
|
277
277
|
|
|
278
278
|
self.error_label.clear()
|
|
279
|
-
table_data = [
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
279
|
+
table_data = [
|
|
280
|
+
(ipath, lpath, ipath.size) for ipath, lpath in thread_output["result"]["download"]
|
|
281
|
+
] + [
|
|
282
|
+
(lpath, ipath, lpath.stat().st_size)
|
|
283
|
+
for lpath, ipath in thread_output["result"]["upload"]
|
|
284
|
+
]
|
|
283
285
|
populate_table(self.diff_table, len(table_data), table_data)
|
|
284
286
|
if len(table_data) == 0:
|
|
285
287
|
self.error_label.setText("Data is already synchronised.")
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
# Form implementation generated from reading ui file 'ibridgesgui/ui_files/configCheck.ui'
|
|
2
2
|
#
|
|
3
|
-
# Created by: PyQt6 UI code generator 6.
|
|
3
|
+
# Created by: PyQt6 UI code generator 6.4.2
|
|
4
4
|
#
|
|
5
5
|
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
|
6
6
|
# run again. Do not edit this file unless you know what you are doing.
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
from PyQt6 import QtCore, QtWidgets
|
|
9
|
+
from PyQt6 import QtCore, QtGui, QtWidgets
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class Ui_configCheck(object):
|
|
13
13
|
def setupUi(self, Dialog):
|
|
14
14
|
Dialog.setObjectName("Dialog")
|
|
15
|
-
Dialog.resize(1034,
|
|
15
|
+
Dialog.resize(1034, 373)
|
|
16
16
|
Dialog.setStyleSheet("QWidget\n"
|
|
17
17
|
"{\n"
|
|
18
18
|
" background-color: rgb(211,211,211);\n"
|
|
@@ -56,6 +56,10 @@ class Ui_configCheck(object):
|
|
|
56
56
|
self.envbox = QtWidgets.QComboBox(parent=Dialog)
|
|
57
57
|
self.envbox.setObjectName("envbox")
|
|
58
58
|
self.horizontalLayout.addWidget(self.envbox)
|
|
59
|
+
self.template_box = QtWidgets.QComboBox(parent=Dialog)
|
|
60
|
+
self.template_box.setObjectName("template_box")
|
|
61
|
+
self.template_box.addItem("")
|
|
62
|
+
self.horizontalLayout.addWidget(self.template_box)
|
|
59
63
|
self.new_button = QtWidgets.QPushButton(parent=Dialog)
|
|
60
64
|
self.new_button.setObjectName("new_button")
|
|
61
65
|
self.horizontalLayout.addWidget(self.new_button)
|
|
@@ -101,6 +105,7 @@ class Ui_configCheck(object):
|
|
|
101
105
|
def retranslateUi(self, Dialog):
|
|
102
106
|
_translate = QtCore.QCoreApplication.translate
|
|
103
107
|
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
|
|
108
|
+
self.template_box.setItemText(0, _translate("Dialog", "Server Templates"))
|
|
104
109
|
self.new_button.setText(_translate("Dialog", "New Config"))
|
|
105
110
|
self.check_button.setText(_translate("Dialog", "Check"))
|
|
106
111
|
self.save_button.setText(_translate("Dialog", "Save"))
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<x>0</x>
|
|
8
8
|
<y>0</y>
|
|
9
9
|
<width>1034</width>
|
|
10
|
-
<height>
|
|
10
|
+
<height>373</height>
|
|
11
11
|
</rect>
|
|
12
12
|
</property>
|
|
13
13
|
<property name="windowTitle">
|
|
@@ -57,6 +57,15 @@ QTabWidget#info_tabs
|
|
|
57
57
|
<item>
|
|
58
58
|
<widget class="QComboBox" name="envbox"/>
|
|
59
59
|
</item>
|
|
60
|
+
<item>
|
|
61
|
+
<widget class="QComboBox" name="template_box">
|
|
62
|
+
<item>
|
|
63
|
+
<property name="text">
|
|
64
|
+
<string>Server Templates</string>
|
|
65
|
+
</property>
|
|
66
|
+
</item>
|
|
67
|
+
</widget>
|
|
68
|
+
</item>
|
|
60
69
|
<item>
|
|
61
70
|
<widget class="QPushButton" name="new_button">
|
|
62
71
|
<property name="text">
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Form implementation generated from reading ui file 'ibridgesgui/ui_files/tabLogging.ui'
|
|
2
|
+
#
|
|
3
|
+
# Created by: PyQt6 UI code generator 6.4.2
|
|
4
|
+
#
|
|
5
|
+
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
|
6
|
+
# run again. Do not edit this file unless you know what you are doing.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
from PyQt6 import QtCore, QtGui, QtWidgets
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Ui_tabLogging(object):
|
|
13
|
+
def setupUi(self, Form):
|
|
14
|
+
Form.setObjectName("Form")
|
|
15
|
+
Form.resize(400, 244)
|
|
16
|
+
Form.setStyleSheet("QWidget\n"
|
|
17
|
+
"{\n"
|
|
18
|
+
" background-color: rgb(211,211,211);\n"
|
|
19
|
+
" color: rgb(88, 88, 90);\n"
|
|
20
|
+
" selection-background-color: rgb(21, 165, 137);\n"
|
|
21
|
+
" selection-color: rgb(245, 244, 244)\n"
|
|
22
|
+
"}\n"
|
|
23
|
+
"\n"
|
|
24
|
+
"QLabel\n"
|
|
25
|
+
"{\n"
|
|
26
|
+
" background-color: rgb(211,211,211);\n"
|
|
27
|
+
"}\n"
|
|
28
|
+
"\n"
|
|
29
|
+
"QTextBrowser\n"
|
|
30
|
+
"{\n"
|
|
31
|
+
" background-color: rgb(245, 244, 244)\n"
|
|
32
|
+
"}\n"
|
|
33
|
+
"")
|
|
34
|
+
self.verticalLayout = QtWidgets.QVBoxLayout(Form)
|
|
35
|
+
self.verticalLayout.setObjectName("verticalLayout")
|
|
36
|
+
self.log_label = QtWidgets.QLabel(parent=Form)
|
|
37
|
+
self.log_label.setObjectName("log_label")
|
|
38
|
+
self.verticalLayout.addWidget(self.log_label)
|
|
39
|
+
self.log_browser = QtWidgets.QTextBrowser(parent=Form)
|
|
40
|
+
self.log_browser.setObjectName("log_browser")
|
|
41
|
+
self.verticalLayout.addWidget(self.log_browser)
|
|
42
|
+
|
|
43
|
+
self.retranslateUi(Form)
|
|
44
|
+
QtCore.QMetaObject.connectSlotsByName(Form)
|
|
45
|
+
|
|
46
|
+
def retranslateUi(self, Form):
|
|
47
|
+
_translate = QtCore.QCoreApplication.translate
|
|
48
|
+
Form.setWindowTitle(_translate("Form", "Form"))
|
|
49
|
+
self.log_label.setText(_translate("Form", "Log file"))
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<ui version="4.0">
|
|
3
|
+
<class>Form</class>
|
|
4
|
+
<widget class="QWidget" name="Form">
|
|
5
|
+
<property name="geometry">
|
|
6
|
+
<rect>
|
|
7
|
+
<x>0</x>
|
|
8
|
+
<y>0</y>
|
|
9
|
+
<width>400</width>
|
|
10
|
+
<height>244</height>
|
|
11
|
+
</rect>
|
|
12
|
+
</property>
|
|
13
|
+
<property name="windowTitle">
|
|
14
|
+
<string>Form</string>
|
|
15
|
+
</property>
|
|
16
|
+
<property name="styleSheet">
|
|
17
|
+
<string notr="true">QWidget
|
|
18
|
+
{
|
|
19
|
+
background-color: rgb(211,211,211);
|
|
20
|
+
color: rgb(88, 88, 90);
|
|
21
|
+
selection-background-color: rgb(21, 165, 137);
|
|
22
|
+
selection-color: rgb(245, 244, 244)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
QLabel
|
|
26
|
+
{
|
|
27
|
+
background-color: rgb(211,211,211);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
QTextBrowser
|
|
31
|
+
{
|
|
32
|
+
background-color: rgb(245, 244, 244)
|
|
33
|
+
}
|
|
34
|
+
</string>
|
|
35
|
+
</property>
|
|
36
|
+
<layout class="QVBoxLayout" name="verticalLayout">
|
|
37
|
+
<item>
|
|
38
|
+
<widget class="QLabel" name="log_label">
|
|
39
|
+
<property name="text">
|
|
40
|
+
<string>Log file</string>
|
|
41
|
+
</property>
|
|
42
|
+
</widget>
|
|
43
|
+
</item>
|
|
44
|
+
<item>
|
|
45
|
+
<widget class="QTextBrowser" name="log_browser"/>
|
|
46
|
+
</item>
|
|
47
|
+
</layout>
|
|
48
|
+
</widget>
|
|
49
|
+
<resources/>
|
|
50
|
+
<connections/>
|
|
51
|
+
</ui>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Welcome tab."""
|
|
2
|
+
|
|
2
3
|
import sys
|
|
3
4
|
|
|
4
5
|
import PyQt6.QtCore
|
|
@@ -37,6 +38,6 @@ class Welcome(PyQt6.QtWidgets.QWidget, Ui_Welcome):
|
|
|
37
38
|
self.grid.addWidget(self.tag, 2, 1)
|
|
38
39
|
self.setLayout(self.grid)
|
|
39
40
|
|
|
40
|
-
self.setGeometry(150,150,300,300)
|
|
41
|
+
self.setGeometry(150, 150, 300, 300)
|
|
41
42
|
|
|
42
43
|
self.show()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ibridgesgui
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Graphical user interface for accessing data and metadata on iRODS servers.
|
|
5
5
|
Author-email: Christine Staiger <c.staiger@uu.nl>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -690,7 +690,7 @@ Requires-Python: >=3.9
|
|
|
690
690
|
Description-Content-Type: text/markdown
|
|
691
691
|
License-File: LICENSE
|
|
692
692
|
Requires-Dist: PyQt6>=6.4.2
|
|
693
|
-
Requires-Dist: ibridges==0.2.
|
|
693
|
+
Requires-Dist: ibridges==0.2.2
|
|
694
694
|
Requires-Dist: setproctitle==1.3.3
|
|
695
695
|
Requires-Dist: importlib-resources; python_version <= "3.10"
|
|
696
696
|
Provides-Extra: test
|
|
@@ -732,11 +732,18 @@ The git repository contains a generic *iRODS* graphical user interface. The iRO
|
|
|
732
732
|
- Safe default options when working with your data.
|
|
733
733
|
|
|
734
734
|
## Installation
|
|
735
|
-
-
|
|
735
|
+
- The python package
|
|
736
736
|
|
|
737
737
|
```bash
|
|
738
738
|
pip install ibridgesgui
|
|
739
739
|
```
|
|
740
|
+
|
|
741
|
+
- A specific branch of the git repository (testers, developers)
|
|
742
|
+
|
|
743
|
+
```bash
|
|
744
|
+
pip install git+https://github.com/chStaiger/iBridges-Gui.git@branch-name
|
|
745
|
+
```
|
|
746
|
+
|
|
740
747
|
- Locally from code (for developers)
|
|
741
748
|
|
|
742
749
|
```bash
|
|
@@ -36,6 +36,7 @@ ibridgesgui/gui_utils.py
|
|
|
36
36
|
ibridgesgui/info.py
|
|
37
37
|
ibridgesgui/irods_tree_model.py
|
|
38
38
|
ibridgesgui/login.py
|
|
39
|
+
ibridgesgui/logviewer.py
|
|
39
40
|
ibridgesgui/popup_widgets.py
|
|
40
41
|
ibridgesgui/search.py
|
|
41
42
|
ibridgesgui/sync.py
|
|
@@ -75,6 +76,8 @@ ibridgesgui/ui_files/tabBrowser.py
|
|
|
75
76
|
ibridgesgui/ui_files/tabBrowser.ui
|
|
76
77
|
ibridgesgui/ui_files/tabInfo.py
|
|
77
78
|
ibridgesgui/ui_files/tabInfo.ui
|
|
79
|
+
ibridgesgui/ui_files/tabLogging.py
|
|
80
|
+
ibridgesgui/ui_files/tabLogging.ui
|
|
78
81
|
ibridgesgui/ui_files/tabSearch.py
|
|
79
82
|
ibridgesgui/ui_files/tabSearch.ui
|
|
80
83
|
ibridgesgui/ui_files/tabSync.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|