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.
Files changed (88) hide show
  1. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/PKG-INFO +10 -3
  2. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/README.md +8 -1
  3. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/getting-started.qmd +1 -2
  4. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/__main__.py +21 -7
  5. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/_version.py +2 -2
  6. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/browser.py +1 -8
  7. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/gui_utils.py +1 -0
  8. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/irods_tree_model.py +4 -1
  9. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/login.py +35 -3
  10. ibridgesgui-0.2.2/ibridgesgui/logviewer.py +50 -0
  11. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/popup_widgets.py +27 -0
  12. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/search.py +2 -1
  13. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/sync.py +7 -5
  14. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/configCheck.py +8 -3
  15. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/configCheck.ui +10 -1
  16. ibridgesgui-0.2.2/ibridgesgui/ui_files/tabLogging.py +49 -0
  17. ibridgesgui-0.2.2/ibridgesgui/ui_files/tabLogging.ui +51 -0
  18. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/welcome.py +2 -1
  19. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui.egg-info/PKG-INFO +10 -3
  20. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui.egg-info/SOURCES.txt +3 -0
  21. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui.egg-info/requires.txt +1 -1
  22. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/pyproject.toml +1 -1
  23. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/requirements_dev.txt +1 -1
  24. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.flake8 +0 -0
  25. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  26. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  27. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.github/dependabot.yml +0 -0
  28. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.github/workflows/linter.yml +0 -0
  29. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.github/workflows/publish.yml +0 -0
  30. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.github/workflows/pypi_release.yml +0 -0
  31. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/.gitignore +0 -0
  32. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/LICENSE +0 -0
  33. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/_quarto.yml +0 -0
  34. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/info.qmd +0 -0
  35. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/add_check_config.png +0 -0
  36. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/add_new_config.png +0 -0
  37. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/browser.png +0 -0
  38. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/delete.png +0 -0
  39. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/login.png +0 -0
  40. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/metadata.png +0 -0
  41. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/permissions.png +0 -0
  42. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/replicas.png +0 -0
  43. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/search.png +0 -0
  44. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/start_ibridges.png +0 -0
  45. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/screenshots/sync.png +0 -0
  46. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/docs/userdoc.qmd +0 -0
  47. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/__init__.py +0 -0
  48. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/config.py +0 -0
  49. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/arrow-left.png +0 -0
  50. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/arrow-right.png +0 -0
  51. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/arrow-up.png +0 -0
  52. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/home.png +0 -0
  53. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/iBridges.ico +0 -0
  54. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/loading_circle.gif +0 -0
  55. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/logo.png +0 -0
  56. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/nosync.png +0 -0
  57. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/refresh.png +0 -0
  58. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/icons/syncing.png +0 -0
  59. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/info.py +0 -0
  60. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/threads.py +0 -0
  61. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/.py +0 -0
  62. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/ExampleTab.py +0 -0
  63. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/ExampleTab.ui +0 -0
  64. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/MainMenu.py +0 -0
  65. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/MainMenu.ui +0 -0
  66. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/__init__.py +0 -0
  67. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/createCollection.py +0 -0
  68. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/createCollection.ui +0 -0
  69. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/irodsLogin.py +0 -0
  70. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/irodsLogin.ui +0 -0
  71. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/renameItem.py +0 -0
  72. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/renameItem.ui +0 -0
  73. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabBrowser.py +0 -0
  74. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabBrowser.ui +0 -0
  75. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabInfo.py +0 -0
  76. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabInfo.ui +0 -0
  77. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabSearch.py +0 -0
  78. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabSearch.ui +0 -0
  79. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabSync.py +0 -0
  80. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/tabSync.ui +0 -0
  81. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/welcome.py +0 -0
  82. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui/ui_files/welcome.ui +0 -0
  83. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui.egg-info/dependency_links.txt +0 -0
  84. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui.egg-info/entry_points.txt +0 -0
  85. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/ibridgesgui.egg-info/top_level.txt +0 -0
  86. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/index.qmd +0 -0
  87. {ibridgesgui-0.2.1 → ibridgesgui-0.2.2}/requirements.txt +0 -0
  88. {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.1
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.1
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
- - As python package
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
- - As python package
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
@@ -4,8 +4,7 @@
4
4
  ## Install iBridges-gui
5
5
 
6
6
  ```
7
- pip install ibridges==0.1.6
8
- pip install pip install git+https://github.com/chStaiger/iBridges-Gui.git@main
7
+ pip install ibridgesgui
9
8
  ```
10
9
 
11
10
  ## Start the program
@@ -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
- if getattr(sys, "frozen", False):
38
- super().setupUi(self)
39
- else:
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("error")
160
- init_logger(THIS_APPLICATION, "error")
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)
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.2.1'
16
- __version_tuple__ = version_tuple = (0, 2, 1)
15
+ __version__ = version = '0.2.2'
16
+ __version_tuple__ = version_tuple = (0, 2, 2)
@@ -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
- if root_path.collection_exists():
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
 
@@ -18,6 +18,7 @@ except ImportError:
18
18
  UI_FILE_DIR = files(__package__) / "ui_files"
19
19
  LOGO_DIR = files(__package__) / "icons"
20
20
 
21
+
21
22
  # Widget utils
22
23
  def populate_table(table_widget, rows: int, data_by_row: list):
23
24
  """Populate a table-like pyqt widget with data."""
@@ -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 parent_coll.subcollections + parent_coll.data_objects:
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
- del key_vals[""]
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 = [(ipath, lpath, ipath.size)
280
- for ipath, lpath in thread_output["result"]["download"]] + \
281
- [(lpath, ipath, lpath.stat().st_size)
282
- for lpath, ipath in thread_output["result"]["upload"]]
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.6.1
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, 429)
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>429</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.1
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.1
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
- - As python package
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
@@ -1,5 +1,5 @@
1
1
  PyQt6>=6.4.2
2
- ibridges==0.2.1
2
+ ibridges==0.2.2
3
3
  setproctitle==1.3.3
4
4
 
5
5
  [:python_version <= "3.10"]
@@ -22,7 +22,7 @@ classifiers = [
22
22
 
23
23
  dependencies = [
24
24
  "PyQt6>=6.4.2",
25
- "ibridges==0.2.1",
25
+ "ibridges==0.2.2",
26
26
  "setproctitle==1.3.3",
27
27
  "importlib-resources;python_version<='3.10'",
28
28
  ]
@@ -1,4 +1,4 @@
1
- flake8==7.0.0
1
+ flake8==7.1.0
2
2
  pylint==3.2.3
3
3
  pytest==8.2.2
4
4
  pytest-cov==5.0.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes