1
1
Fork 0

๐ŸŽจ Black formatting

develop
corentin 11 months ago
parent 35ff76dd24
commit 2ed7492a14
  1. 4
      README.md
  2. 2
      apps/center/api/__init__.py
  3. 24
      apps/center/app.py
  4. 17
      apps/center/ui/admin/annoucements.py
  5. 46
      apps/center/ui/admin/config/server.py
  6. 62
      apps/center/ui/admin/main.py
  7. 22
      apps/center/ui/admin/toolbox.py
  8. 20
      apps/center/ui/admin/users/edit.py
  9. 8
      apps/center/ui/admin/users/list.py
  10. 6
      apps/center/ui/home/dashboard.py
  11. 22
      apps/center/ui/home/main.py
  12. 2
      apps/center/ui/home/projects/__init__.py
  13. 8
      apps/center/ui/home/projects/list.py
  14. 36
      apps/center/ui/home/projects/new.py
  15. 5
      apps/center/ui/home/user_activity.py
  16. 29
      apps/center/ui/project/group_editor.py
  17. 45
      apps/center/ui/project/group_list.py
  18. 25
      apps/center/ui/project/item_editor.py
  19. 34
      apps/center/ui/project/item_list.py
  20. 43
      apps/center/ui/project/main.py
  21. 22
      apps/center/ui/settings/config.py
  22. 19
      apps/center/ui/settings/database.py
  23. 51
      apps/center/ui/settings/launcher.py
  24. 24
      apps/center/ui/settings/main.py
  25. 24
      apps/center/ui/settings/password.py
  26. 38
      apps/center/ui/settings/profile.py
  27. 12
      apps/center/ui/settings/project.py
  28. 65
      apps/center/ui/settings/version.py
  29. 5
      apps/center/ui/utils/loading_error.py
  30. 4
      apps/demo/app.py
  31. 133
      apps/demo/ui.py
  32. 6
      apps/explorer/api.py
  33. 7
      apps/explorer/app.py
  34. 23
      apps/explorer/hosted.py
  35. 35
      apps/explorer/ui/main.py
  36. 14
      apps/explorer/ui/results.py
  37. 12
      apps/launcher/app.py
  38. 2
      apps/launcher/ui/main.py
  39. 6
      apps/launcher/ui/search/app_grid.py
  40. 7
      apps/launcher/ui/search/results/batch_widget.py
  41. 2
      apps/launcher/ui/specials/bubble.py
  42. 2
      apps/launcher/ui/specials/login.py
  43. 2
      apps/launcher/ui/specials/splash.py
  44. 4
      apps/updater/view.py
  45. 146
      bip/deprecated/app.py
  46. 2
      bip/link/batch.py
  47. 63
      bip/link/component.py
  48. 20
      bip/link/config.py
  49. 6
      bip/link/data.py
  50. 28
      bip/link/group.py
  51. 18
      bip/link/item.py
  52. 3
      bip/link/metadata.py
  53. 22
      bip/link/model.py
  54. 54
      bip/link/project.py
  55. 133
      bip/link/specials.py
  56. 7
      bip/link/task.py
  57. 2
      bip/link/tools/decorators.py
  58. 42
      bip/link/tools/pattern.py
  59. 8
      bip/link/tools/permissions.py
  60. 7
      bip/link/tools/template.py
  61. 32
      bip/link/user.py
  62. 20
      bip/link/version.py
  63. 2
      bip/mink/__init__.py
  64. 8
      bip/mink/batches.py
  65. 4
      bip/mink/logs.py
  66. 25
      bip/mink/plugins/loader.py
  67. 2
      bip/mink/start.py
  68. 1
      bip/mink/tips.py
  69. 9
      bip/mink/uninstall.py
  70. 14
      bip/mink/update.py
  71. 1
      bip/pink/content.py
  72. 41
      bip/pink/system.py
  73. 6
      bip/sdk/app/decorators.py
  74. 183
      bip/sdk/app/main.py
  75. 14
      bip/sdk/plugin/host.py
  76. 2
      bip/sdk/plugin/tracker.py
  77. 6
      bip/sink/component.py
  78. 14
      bip/sink/internal.py
  79. 4
      bip/sink/item.py
  80. 4
      bip/sink/task.py
  81. 12
      bip/sink/user.py
  82. 24
      bip/uink/app/notification.py
  83. 23
      bip/uink/app/view.py
  84. 1
      bip/uink/internal/loading.py
  85. 4
      bip/uink/library/animated_stack.py
  86. 23
      bip/uink/library/boxed_list.py
  87. 40
      bip/uink/library/button.py
  88. 1
      bip/uink/library/centered_group.py
  89. 47
      bip/uink/library/dialog.py
  90. 2
      bip/uink/library/dropdown.py
  91. 3
      bip/uink/library/floating_group.py
  92. 1
      bip/uink/library/group_check.py
  93. 10
      bip/uink/library/head_bar.py
  94. 16
      bip/uink/library/list.py
  95. 10
      bip/uink/library/menu_tab.py
  96. 3
      bip/uink/library/spinbox.py
  97. 12
      bip/uink/library/switch.py
  98. 50
      bip/uink/library/window.py
  99. 11
      bip/uink/utils.py
  100. 2
      bip/utils/formating.py
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,8 +1,10 @@
![version](https://img.shields.io/badge/status-in%20progress-orange)
[![VFX Platform](https://img.shields.io/badge/vfxplatform-2020-blue.svg)](http://www.vfxplatform.com/)
[![Python 3.7](https://img.shields.io/badge/python-3.7-blue.svg)](https://www.python.org/)
[![Reference Documentation](http://img.shields.io/badge/doc-reference-purple.svg)](https://bip.blinkink.co.uk)
[![License](http://img.shields.io/badge/license-MIT-green.svg)](https://opensource.org/licenses/MIT)
[![Code style: black](https://img.shields.io/badge/code%20style-black-black.svg)](https://github.com/psf/black)
![SemVer](https://img.shields.io/badge/semver-2.0.0-green)
# Bip Client
## Introduction

@ -1 +1 @@
from . import user_activity
from . import user_activity

@ -13,8 +13,8 @@ from center import api
from center.ui.main import MainWidget
parser = argparse.ArgumentParser()
parser.add_argument('-v', '--view', type=str, required=False, default=None)
parser.add_argument('-l', '--lock', type=bool, required=False, default=False)
parser.add_argument("-v", "--view", type=str, required=False, default=None)
parser.add_argument("-l", "--lock", type=bool, required=False, default=False)
args = parser.parse_args()
start_view = args.view
@ -25,7 +25,15 @@ class Center(App):
name = "Control Center"
identifier = "center"
def __init__(self, context, logger, host=None, callback=None, start_view=start_view, lock_view=lock_view):
def __init__(
self,
context,
logger,
host=None,
callback=None,
start_view=start_view,
lock_view=lock_view,
):
super().__init__(context, logger, host, callback=callback)
self._start_view = start_view
@ -222,14 +230,12 @@ class Center(App):
def open_path(self, path):
if not os.path.exists(path):
return self.error_dialog("Impossible to open", f'The path "{path} does not exist.')
return self.error_dialog(
"Impossible to open", f'The path "{path} does not exist.'
)
subprocess.Popen(["explorer", path.replace('/', '\\')])
subprocess.Popen(["explorer", path.replace("/", "\\")])
if __name__ == "__main__":
run(Center)

@ -41,14 +41,15 @@ class Announcements(CenteredGroup):
self.force_button = Button(
"Force announcement for every user",
description="Even if they closed it since it has been published.",
size=Button.GIANT
)
size=Button.GIANT,
)
self.tools.add_row(widget=self.force_button)
self.clear_button = Button(
"Clear announcement for every user",
description="Even if they haven not seen it yet.",
size=Button.GIANT)
size=Button.GIANT,
)
self.tools.add_row(widget=self.clear_button)
self.save_button = Button("Save", size=Button.LARGE, level=Button.INFO)
@ -64,13 +65,16 @@ class Announcements(CenteredGroup):
self.app.show_loading(
"Updating announcement settings",
"Please wait. It usually takes a few seconds...")
"Please wait. It usually takes a few seconds...",
)
self.thread.start()
def _failed(self, exception):
self.app.close_loading()
self.app.error_dialog("An error occurred", str(exception), exception, hidden_details=True)
self.app.error_dialog(
"An error occurred", str(exception), exception, hidden_details=True
)
def _successful(self, result):
self.app.close_loading()
@ -96,6 +100,3 @@ class Announcements(CenteredGroup):
self.message.setText(config.announcement_message)
self.level.select(config.announcement_level)
self.closable_switch.set_checked(bool(config.closable_announcement))

@ -32,14 +32,16 @@ class ConfigServer(CenteredGroup):
widget=self.bip_source,
text="Bip",
horizontal=False,
description="URL of the Git repository that must be used for the updates.")
description="URL of the Git repository that must be used for the updates.",
)
self.content_source = QLineEdit()
self.sources.add_row(
widget=self.content_source,
text="Content",
horizontal=False,
description="URL of the Git repository that must be used for the custom content.")
description="URL of the Git repository that must be used for the custom content.",
)
self.offline = self.sources.add_expanding_row(text="Offline", optional=True)
@ -49,7 +51,8 @@ class ConfigServer(CenteredGroup):
"Python package repository",
horizontal=False,
description="If your Bip instance cannot reach Internet, you must provide an "
"alternative repository to PyPI.")
"alternative repository to PyPI.",
)
self.version = BoxedList(title="Version")
self.add_widget(self.version)
@ -61,7 +64,8 @@ class ConfigServer(CenteredGroup):
self.recommended_version,
horizontal=False,
text="Recommended",
description="Pick what version will be recommended to the users.")
description="Pick what version will be recommended to the users.",
)
self.minimal_version = SearchList(item_size=24)
self.minimal_version.sorting_direction = SearchList.ASC
@ -71,7 +75,8 @@ class ConfigServer(CenteredGroup):
self.minimal_version,
horizontal=False,
text="Minimal",
description="Pick the lowest version accepted by the server.")
description="Pick the lowest version accepted by the server.",
)
self.preferences = BoxedList(title="Preferences")
self.add_widget(self.preferences)
@ -80,7 +85,8 @@ class ConfigServer(CenteredGroup):
self.preferences.add_row(
self.active_project_timeout,
"Active project timeout (days)",
"After how many days of user inactivity does the active project get reset.")
"After how many days of user inactivity does the active project get reset.",
)
self.save_button = Button("Save", size=Button.LARGE, level=Button.INFO)
self.save_button.clicked.connect(self.save)
@ -97,19 +103,24 @@ class ConfigServer(CenteredGroup):
self.thread.errored.connect(self._failed_tag_loading)
self.thread.completed.connect(self._successful_tag_loading)
self.app.show_loading(
"Downloading tags",
f"Compatible tags from {url}...")
self.app.show_loading("Downloading tags", f"Compatible tags from {url}...")
self.thread.start()
def _failed_tag_loading(self, exception):
self.app.close_loading()
self.app.error_dialog("Impossible to download tags", str(exception), exception, hidden_details=True)
self.app.error_dialog(
"Impossible to download tags",
str(exception),
exception,
hidden_details=True,
)
def _successful_tag_loading(self, tags):
self.minimal_version.add_item("Latest", LATEST, sorter=version.parse("v99999"))
self.recommended_version.add_item("Latest", LATEST, sorter=version.parse("v99999"))
self.recommended_version.add_item(
"Latest", LATEST, sorter=version.parse("v99999")
)
for tag in tags:
sorter = version.parse(tag)
@ -134,14 +145,16 @@ class ConfigServer(CenteredGroup):
self.thread.completed.connect(self._successful)
self.app.show_loading(
"Updating server config",
"Please wait. It usually takes a few seconds...")
"Updating server config", "Please wait. It usually takes a few seconds..."
)
self.thread.start()
def _failed(self, exception):
self.app.close_loading()
self.app.error_dialog("An error occurred", str(exception), exception, hidden_details=True)
self.app.error_dialog(
"An error occurred", str(exception), exception, hidden_details=True
)
def _successful(self, result):
self.app.close_loading()
@ -155,7 +168,7 @@ class ConfigServer(CenteredGroup):
"minimal_version": self.minimal_version.selected,
"active_project_timeout": self.active_project_timeout.value(),
"offline": self.offline.is_checked,
"python_package_repository": self.python_package_repository.text()
"python_package_repository": self.python_package_repository.text(),
}
def clear(self):
@ -178,6 +191,3 @@ class ConfigServer(CenteredGroup):
self.active_project_timeout.setValue(self.config.active_project_timeout)
self.offline.set_checked(self.config.offline)
self.python_package_repository.setText(self.config.python_package_repository)

@ -63,46 +63,70 @@ class Admin(QWidget):
self.menu_bar.add_item(self.users_list, "List", scrollable=False, parent=group)
self.users_roles = Temp()
self.menu_bar.add_item(self.users_roles, "Roles", scrollable=False, parent=group)
self.menu_bar.add_item(
self.users_roles, "Roles", scrollable=False, parent=group
)
self.users_privileges = Temp()
self.menu_bar.add_item(self.users_privileges, "Privileges", scrollable=False, parent=group)
self.menu_bar.add_item(
self.users_privileges, "Privileges", scrollable=False, parent=group
)
self.users_settings = Temp()
self.menu_bar.add_item(self.users_settings, "Settings", scrollable=False, parent=group)
self.menu_bar.add_item(
self.users_settings, "Settings", scrollable=False, parent=group
)
icon = os.path.join(symbols_directory, "folder.png")
group = self.menu_bar.add_group("Projects", icon=icon)
self.project_tags = Temp()
self.menu_bar.add_item(self.project_tags, "Tags", scrollable=False, parent=group)
self.menu_bar.add_item(
self.project_tags, "Tags", scrollable=False, parent=group
)
self.project_models = Temp()
self.menu_bar.add_item(self.project_models, "Data models", scrollable=False, parent=group)
self.menu_bar.add_item(
self.project_models, "Data models", scrollable=False, parent=group
)
self.project_groups = Temp()
self.menu_bar.add_item(self.project_groups, "Groups", scrollable=False, parent=group)
self.menu_bar.add_item(
self.project_groups, "Groups", scrollable=False, parent=group
)
icon = os.path.join(symbols_directory, "puzzle.png")
group = self.menu_bar.add_group("Content", icon=icon)
self.content_batches = Temp()
self.menu_bar.add_item(self.content_batches, "Batches", scrollable=False, parent=group)
self.menu_bar.add_item(
self.content_batches, "Batches", scrollable=False, parent=group
)
self.content_commands = Temp()
self.menu_bar.add_item(self.content_commands, "Commands", scrollable=False, parent=group)
self.menu_bar.add_item(
self.content_commands, "Commands", scrollable=False, parent=group
)
self.content_customization = Temp()
self.menu_bar.add_item(self.content_customization, "Customization", scrollable=False, parent=group)
self.menu_bar.add_item(
self.content_customization, "Customization", scrollable=False, parent=group
)
self.content_config = Temp()
self.menu_bar.add_item(self.content_config, "Config", scrollable=False, parent=group)
self.menu_bar.add_item(
self.content_config, "Config", scrollable=False, parent=group
)
self.content_routines = Temp()
self.menu_bar.add_item(self.content_routines, "Routines", scrollable=False, parent=group)
self.menu_bar.add_item(
self.content_routines, "Routines", scrollable=False, parent=group
)
self.content_presets = Temp()
self.menu_bar.add_item(self.content_presets, "Presets", scrollable=False, parent=group)
self.menu_bar.add_item(
self.content_presets, "Presets", scrollable=False, parent=group
)
self.incidents = Temp()
icon = os.path.join(symbols_directory, "question.png")
@ -110,7 +134,9 @@ class Admin(QWidget):
self.announcements = Announcements(self.app, self)
icon = os.path.join(symbols_directory, "message.png")
self.menu_bar.add_item(self.announcements, "Announcements", scrollable=False, icon=icon)
self.menu_bar.add_item(
self.announcements, "Announcements", scrollable=False, icon=icon
)
self.toolbox = Toolbox(self.app, self)
icon = os.path.join(symbols_directory, "swiss-knife.png")
@ -126,7 +152,9 @@ class Admin(QWidget):
self.config_server = ConfigServer(self.app, self)
icon = os.path.join(symbols_directory, "config.png")
self.menu_bar.add_item(self.config_server, "Configuration", scrollable=True, icon=icon)
self.menu_bar.add_item(
self.config_server, "Configuration", scrollable=True, icon=icon
)
self.menu_bar.changed.connect(self._update_views)
@ -152,8 +180,8 @@ class Admin(QWidget):
pass
if widget:
self.loading_error.attempt_requested.connect(lambda: self.menu_bar.set_view(widget))
self.loading_error.attempt_requested.connect(
lambda: self.menu_bar.set_view(widget)
)
self.menu_bar.set_view(self.loading_error)

@ -6,7 +6,6 @@ from bip.uink.tools import Execute
from bip.uink.library import *
class Toolbox(CenteredGroup):
def __init__(self, app, view, parent=None):
super().__init__(vertical=True, horizontal=True, parent=parent)
@ -21,26 +20,27 @@ class Toolbox(CenteredGroup):
self.force_button = Button(
"Force announcement for every user",
description="Even if they closed it since it has been published.",
size=Button.GIANT
)
size=Button.GIANT,
)
self.force_button.clicked.connect(self.app.reset_announcement_views)
self.add_widget(widget=self.force_button)
self.clear_button = Button(
"Clear announcement for every user",
description="Even if they haven not seen it yet.",
size=Button.GIANT)
size=Button.GIANT,
)
self.clear_button.clicked.connect(self.app.clear_announcement_views)
self.add_widget(widget=self.clear_button)
self.force_welcome_button = Button(
"Force welcome tutorial for every user",
description="Even if they have seen it already.",
size=Button.GIANT)
size=Button.GIANT,
)
self.force_welcome_button.clicked.connect(self.app.force_welcome_tutorial)
self.add_widget(widget=self.force_welcome_button)
def save(self):
data = self.to_dict()
@ -50,13 +50,16 @@ class Toolbox(CenteredGroup):
self.app.show_loading(
"Updating announcement settings",
"Please wait. It usually takes a few seconds...")
"Please wait. It usually takes a few seconds...",
)
self.thread.start()
def _failed(self, exception):
self.app.close_loading()
self.app.error_dialog("An error occurred", str(exception), exception, hidden_details=True)
self.app.error_dialog(
"An error occurred", str(exception), exception, hidden_details=True
)
def _successful(self, result):
self.app.close_loading()
@ -81,6 +84,3 @@ class Toolbox(CenteredGroup):
self.message.setText(config.announcement_message)
self.level.select(config.announcement_level)
self.closable_switch.set_checked(bool(config.closable_announcement))

@ -59,7 +59,9 @@ class EditUserPopup(QFrame):
self.profile.add_row(self.last_name_edit, "Last name")
self.initials_edit = QLineEdit()
self.initials_edit.setEnabled(self.app.current_user.privilege.slug == "administrator")
self.initials_edit.setEnabled(
self.app.current_user.privilege.slug == "administrator"
)
self.profile.add_row(self.initials_edit, "Initials")
self.email_edit = QLineEdit()
@ -72,7 +74,9 @@ class EditUserPopup(QFrame):
container.layout().addWidget(self.auth)
self.username_edit = QLineEdit()
self.username_edit.setEnabled(self.app.current_user.privilege.slug == "administrator")
self.username_edit.setEnabled(
self.app.current_user.privilege.slug == "administrator"
)
self.auth.add_row(self.username_edit, "Username")
if self.create_mode:
@ -165,7 +169,9 @@ class EditUserPopup(QFrame):
initials = first_name[0] + last_name[0]
initials = initials.upper()
username = string_cleaner(first_name).lower() + '.' + string_cleaner(last_name).lower()
username = (
string_cleaner(first_name).lower() + "." + string_cleaner(last_name).lower()
)
self.initials_edit.setText(initials)
self.username_edit.setText(username)
@ -179,8 +185,8 @@ class EditUserPopup(QFrame):
self.thread.completed.connect(self._successful_creation)
self.app.show_loading(
"Creating user",
"Please wait. It usually takes a few seconds...")
"Creating user", "Please wait. It usually takes a few seconds..."
)
self.thread.start()
else:
@ -189,8 +195,8 @@ class EditUserPopup(QFrame):
self.thread.completed.connect(self._successful_creation)
self.app.show_loading(
"Updating user",
"Please wait. It usually takes a few seconds...")
"Updating user", "Please wait. It usually takes a few seconds..."
)
self.thread.start()

@ -44,7 +44,9 @@ class UsersList(CenteredGroup):
self.header.layout().addStretch(1)
font = Font(bold=True)
self.new_button = Button("New user", size=Button.LARGE, level=Button.SUCCESS, font=font)
self.new_button = Button(
"New user", size=Button.LARGE, level=Button.SUCCESS, font=font
)
self.new_button.setMinimumWidth(150)
self.new_button.clicked.connect(self._new_user)
self.header.layout().addWidget(self.new_button)
@ -122,7 +124,3 @@ class User(QWidget):
self.layout().setColumnStretch(1, 10)
self.layout().setColumnStretch(2, 0)

@ -39,7 +39,8 @@ class Dashboard(CenteredGroup):
self.add_widget(title)
message = QLabel(
"This application is under active development. Only the following views are implemented.")
"This application is under active development. Only the following views are implemented."
)
message.setFont(Font(size=11, italic=True))
message.setStyleSheet("QLabel {color: #7a7a7a}")
message.setAlignment(Qt.AlignCenter)
@ -58,6 +59,3 @@ class Dashboard(CenteredGroup):
button.setFixedWidth(150)
button.clicked.connect(lambda: self.view_requested.emit(self.view.project_list))
container.layout().addWidget(button, 0, 0)

@ -62,7 +62,9 @@ class Home(QWidget):
self.project_list = ProjectsList(self.app, self)
icon = os.path.join(symbols_directory, "folder.png")
self.menu_bar.add_item(self.project_list, "Projects", scrollable=False, icon=icon)
self.menu_bar.add_item(
self.project_list, "Projects", scrollable=False, icon=icon
)
self.menu_bar.add_category("Utilities")
@ -70,14 +72,20 @@ class Home(QWidget):
group = self.menu_bar.add_group("Activity", icon=icon)
self.tracking_usage = UserActivity(self.app, self)
self.menu_bar.add_item(self.tracking_usage, "Users", scrollable=True, parent=group)
self.menu_bar.add_item(
self.tracking_usage, "Users", scrollable=True, parent=group
)
self.tracking_licenses = Temp()
self.menu_bar.add_item(self.tracking_licenses, "Licenses", scrollable=False, parent=group)
self.menu_bar.add_item(
self.tracking_licenses, "Licenses", scrollable=False, parent=group
)
self.issues = Temp()
icon = os.path.join(symbols_directory, "issue.png")
self.menu_bar.add_item(self.issues, "Report an issue", scrollable=False, icon=icon)
self.menu_bar.add_item(
self.issues, "Report an issue", scrollable=False, icon=icon
)
self.help = Temp()
icon = os.path.join(symbols_directory, "help.png")
@ -110,8 +118,8 @@ class Home(QWidget):
pass
if widget:
self.loading_error.attempt_requested.connect(lambda: self.menu_bar.set_view(widget))
self.loading_error.attempt_requested.connect(
lambda: self.menu_bar.set_view(widget)
)
self.menu_bar.set_view(self.loading_error)

@ -1 +1 @@
from .list import ProjectsList
from .list import ProjectsList

@ -43,7 +43,9 @@ class ProjectsList(CenteredGroup):
self.header.layout().addStretch(1)
font = Font(bold=True)
self.new_button = Button("New project", size=Button.LARGE, level=Button.SUCCESS, font=font)
self.new_button = Button(
"New project", size=Button.LARGE, level=Button.SUCCESS, font=font
)
self.new_button.setMinimumWidth(150)
self.new_button.clicked.connect(self._new_project)
self.header.layout().addWidget(self.new_button)
@ -124,7 +126,3 @@ class Project(QWidget):
self.layout().setColumnStretch(1, 10)
self.layout().setColumnStretch(2, 0)

@ -77,7 +77,9 @@ class NewProjectPopup(QFrame):
self.model_combo = Dropdown()
self.model_combo.changed.connect(self.update_model_info)
expanding_row = self.model.add_expanding_row(self.model_combo, "Template", expanded=True)
expanding_row = self.model.add_expanding_row(
self.model_combo, "Template", expanded=True
)
model_info = QFrame()
model_info.setLayout(QVBoxLayout())
@ -104,7 +106,8 @@ class NewProjectPopup(QFrame):
self.lock_model_switch,
"Lock",
description="If turned on, the data model cannot be modified after the project creation. "
"It is recommended to leave turned on for preserving data consistency.")
"It is recommended to leave turned on for preserving data consistency.",
)
self.groups = BoxedList(title="Groups")
container.layout().addWidget(self.groups)
@ -112,13 +115,17 @@ class NewProjectPopup(QFrame):
self.tracker = BoxedList(title="Production tracker")
container.layout().addWidget(self.tracker)
self.use_tracker = self.tracker.add_expanding_row(text="Use external tracker", optional=True)
self.use_tracker = self.tracker.add_expanding_row(
text="Use external tracker", optional=True
)
self.tracker_combo = Dropdown()
self.tracker_combo.changed.connect(self.update_trackers_ui)
self.use_tracker.add_row(self.tracker_combo, "Tracker")
self.tracker_sync = self.tracker.add_expanding_row(text="Synchronize", optional=True)
self.tracker_sync = self.tracker.add_expanding_row(
text="Synchronize", optional=True
)
self.tracker_sync.setEnabled(False)
self.tracker_direction_combo = Dropdown()
@ -174,8 +181,8 @@ class NewProjectPopup(QFrame):
self.thread.completed.connect(self._successful_creation)
self.app.show_loading(
"Creating project",
"Please wait. It usually takes a few seconds...")
"Creating project", "Please wait. It usually takes a few seconds..."
)
self.thread.start()
@ -200,7 +207,6 @@ class NewProjectPopup(QFrame):
"use_tracker": self.use_tracker.is_checked,
"tracker": self.tracker_combo.current.slug,
"tracker_settings": tracker_settings,
}
def _failed_creation(self, error):
@ -250,8 +256,14 @@ class NewProjectPopup(QFrame):
for setting_key, setting_details in tracker.settings.items():
type_ = setting_details["type"]
name = setting_details["name"]
description = setting_details["description"] if "description" in setting_details else None
default = setting_details["default"] if "default" in setting_details else None
description = (
setting_details["description"]
if "description" in setting_details
else None
)
default = (
setting_details["default"] if "default" in setting_details else None
)
values = setting_details["values"] if "values" in setting_details else None
if type_ is str:
@ -285,8 +297,10 @@ class NewProjectPopup(QFrame):
widget.set_checked(default)
else:
raise TypeError(f"This application does not support the tracker setting type \"{str(type_)}\". "
f"Please contact the developer.")
raise TypeError(
f'This application does not support the tracker setting type "{str(type_)}". '
f"Please contact the developer."
)
row = self.use_tracker.add_row(widget, name, description=description)
self._tracker_settings_widgets[setting_key] = (row, getter)

@ -66,7 +66,10 @@ class User(QFrame):
profile_picture.setFont(Font(relative=16, weight=10))
profile_picture.setAlignment(Qt.AlignCenter)
color = string_to_color(data["name"])
css = "#user_activity_profile_picture {background-color: %s; border-radius: 32px; color: #222222;}" % color
css = (
"#user_activity_profile_picture {background-color: %s; border-radius: 32px; color: #222222;}"
% color
)
profile_picture.setStyleSheet(css)
profile_picture.setText(data["initials"])

@ -7,6 +7,7 @@ from bip.uink.tools import Execute
from bip.uink.utils import Font
from bip.sdk.app.decorators import error_handler
class GroupEditor(QFrame):
completed = Signal()
@ -17,7 +18,11 @@ class GroupEditor(QFrame):
self.group = group
self.container_groups = container_groups
self.container_group_tags = group_tag.get_required_memberships() if group_tag.has_required_memberships else []
self.container_group_tags = (
group_tag.get_required_memberships()
if group_tag.has_required_memberships
else []
)
self._container_group_widgets = {}
self.setFixedWidth(500)
@ -55,13 +60,13 @@ class GroupEditor(QFrame):
self.name = QLineEdit()
description = None
if self.group_tag.name_hint:
description = f"Example: \"<b>{self.group_tag.name_hint}</b>\""
description = f'Example: "<b>{self.group_tag.name_hint}</b>"'
self.general.add_row(self.name, "Name", description=description)
self.folder_name = QLineEdit()
description = None
if self.group_tag.folder_name_hint:
description = f"Example: \"<b>{self.group_tag.folder_name_hint}</b>\""
description = f'Example: "<b>{self.group_tag.folder_name_hint}</b>"'
self.general.add_row(self.folder_name, "Folder name", description=description)
self.code = QLineEdit()
@ -107,7 +112,9 @@ class GroupEditor(QFrame):
self.footer.layout().addWidget(self.cancel_button)
self.save_button = Button("Create" if not group else "Save", size=Button.LARGE, level=Button.SUCCESS)
self.save_button = Button(
"Create" if not group else "Save", size=Button.LARGE, level=Button.SUCCESS
)
self.save_button.setMinimumWidth(120)
self.save_button.pressed.connect(self.save)
self.footer.layout().addWidget(self.save_button)
@ -134,7 +141,6 @@ class GroupEditor(QFrame):
if not self.folder_name.text():
return self.app.error_dialog("Missing value", "Please enter a folder name.")
data = self.to_dict()
changed_container_groups = []
for tag in self._container_group_widgets:
@ -151,13 +157,19 @@ class GroupEditor(QFrame):
if old is not new:
changed_container_groups.append((old, new))
self.thread = Execute(lambda: self.app.save_group(data, group=self.group, changed_container_groups=changed_container_groups))
self.thread = Execute(
lambda: self.app.save_group(
data,
group=self.group,
changed_container_groups=changed_container_groups,
)
)
self.thread.errored.connect(self._failed)
self.thread.completed.connect(self._successful)
self.app.show_loading(
"Creating group",
"Please wait. It usually takes a few seconds...")
"Creating group", "Please wait. It usually takes a few seconds..."
)
self.thread.start()
@ -170,7 +182,6 @@ class GroupEditor(QFrame):
"suffix": self.suffix.text(),
"description": self.description.toPlainText(),
"groups": [w.current for w in self._container_group_widgets.values()],
}
def _failed(self, error):

@ -46,7 +46,12 @@ class GroupList(QFrame):
self.header.layout().addStretch(1)
font = Font(bold=True)
self.new_button = Button(f"New {group_tag.name.lower()}", size=Button.LARGE, level=Button.SUCCESS, font=font)
self.new_button = Button(
f"New {group_tag.name.lower()}",
size=Button.LARGE,
level=Button.SUCCESS,
font=font,
)
self.new_button.setMinimumWidth(150)
self.new_button.clicked.connect(lambda: self._edit_group())
self.header.layout().addWidget(self.new_button)
@ -92,7 +97,9 @@ class GroupList(QFrame):
def _failed_loading(self, exception):
self.app.close_loading()
self.app.error_dialog("Impossible to load data", str(exception), exception, hidden_details=True)
self.app.error_dialog(
"Impossible to load data", str(exception), exception, hidden_details=True
)
self.view.set_error_view(widget=self)
def _successful_loading(self):
@ -102,7 +109,13 @@ class GroupList(QFrame):
self.number.setText(str(len(self._groups)))
for group, container_groups in self._groups.items():
self.list.add_item(group.name, group, widget=Group, widget_args=[group, container_groups], silent=True)
self.list.add_item(
group.name,
group,
widget=Group,
widget_args=[group, container_groups],
silent=True,
)
self.list.filter()
self.list.clear_selection()
@ -115,26 +128,28 @@ class GroupList(QFrame):
self.thread.errored.connect(self._failed_loading)
self.thread.completed.connect(self._successful_loading)
self.app.show_loading(
"Loading",
f"Fetching data from database...")
self.app.show_loading("Loading", f"Fetching data from database...")
self.thread.start()
def _edit_group(self, group=None):
container_groups = self._groups[group] if group else []
widget = GroupEditor(self.app, group_tag=self.group_tag, group=group, container_groups=container_groups)
widget = GroupEditor(
self.app,
group_tag=self.group_tag,
group=group,
container_groups=container_groups,
)
widget.completed.connect(self.load)
self.app.popup(widget, escape_allowed=False)
@error_handler
def _delete_group(self, group, force=False):
title = f"Are you sure?"
description = f"Do you really want to delete {group.name}? This action cannot be undone."
result = self.app.warning_dialog(
title,
description,
mode=Dialog.DOUBLE)
description = (
f"Do you really want to delete {group.name}? This action cannot be undone."
)
result = self.app.warning_dialog(title, description, mode=Dialog.DOUBLE)
if not result:
return
@ -161,11 +176,7 @@ class Group(QWidget):
self.layout().addWidget(name)
if container_groups:
label = QLabel(', '.join([g.name for g in container_groups]))
label = QLabel(", ".join([g.name for g in container_groups]))
label.setFont(Font(relative=-2))
label.setObjectName("user_widget_role")
self.layout().addWidget(label)

@ -17,7 +17,11 @@ class ItemEditor(QFrame):
self.item = item
self.groups = groups
self.group_tags = item_tag.get_required_memberships() if item_tag.has_required_memberships else []
self.group_tags = (
item_tag.get_required_memberships()
if item_tag.has_required_memberships
else []
)
self._group_widgets = {}
self.setFixedWidth(500)
@ -55,13 +59,13 @@ class ItemEditor(QFrame):
self.name = QLineEdit()
description = None
if self.item_tag.name_hint:
description = f"Example: \"<b>{self.item_tag.name_hint}</b>\""
description = f'Example: "<b>{self.item_tag.name_hint}</b>"'
self.general.add_row(self.name, "Name", description=description)
self.folder_name = QLineEdit()
description = None
if self.item_tag.folder_name_hint:
description = f"Example: \"<b>{self.item_tag.folder_name_hint}</b>\""
description = f'Example: "<b>{self.item_tag.folder_name_hint}</b>"'
self.general.add_row(self.folder_name, "Folder name", description=description)
self.code = QLineEdit()
@ -107,7 +111,9 @@ class ItemEditor(QFrame):
self.footer.layout().addWidget(self.cancel_button)
self.save_button = Button("Create" if not item else "Save", size=Button.LARGE, level=Button.SUCCESS)
self.save_button = Button(
"Create" if not item else "Save", size=Button.LARGE, level=Button.SUCCESS
)
self.save_button.setMinimumWidth(120)
self.save_button.pressed.connect(self.save)
self.footer.layout().addWidget(self.save_button)
@ -150,13 +156,17 @@ class ItemEditor(QFrame):
if old is not new:
changed_groups.append((old, new))
self.thread = Execute(lambda: self.app.save_item(data, item=self.item, changed_groups=changed_groups))
self.thread = Execute(
lambda: self.app.save_item(
data, item=self.item, changed_groups=changed_groups
)
)
self.thread.errored.connect(self._failed)
self.thread.completed.connect(self._successful)
self.app.show_loading(
"Creating item",
"Please wait. It usually takes a few seconds...")
"Creating item", "Please wait. It usually takes a few seconds..."
)
self.thread.start()
@ -169,7 +179,6 @@ class ItemEditor(QFrame):
"suffix": self.suffix.text(),
"description": self.description.toPlainText(),
"groups": [w.current for w in self._group_widgets.values()],
}
def _failed(self, error):

@ -46,7 +46,12 @@ class ItemList(QFrame):
self.header.layout().addStretch(1)
font = Font(bold=True)
self.new_button = Button(f"New {item_tag.name.lower()}", size=Button.LARGE, level=Button.SUCCESS, font=font)
self.new_button = Button(
f"New {item_tag.name.lower()}",
size=Button.LARGE,
level=Button.SUCCESS,
font=font,
)
self.new_button.setMinimumWidth(150)
self.new_button.clicked.connect(lambda: self._edit_item())
self.header.layout().addWidget(self.new_button)
@ -102,7 +107,9 @@ class ItemList(QFrame):
def _failed_loading(self, exception):
self.app.close_loading()
self.app.error_dialog("Impossible to load data", str(exception), exception, hidden_details=True)
self.app.error_dialog(
"Impossible to load data", str(exception), exception, hidden_details=True
)
self.view.set_error_view(widget=self)
def _successful_loading(self):
@ -112,7 +119,9 @@ class ItemList(QFrame):
self.number.setText(str(len(self._items)))
for item, groups in self._items.items():
self.list.add_item(item.name, item, widget=Item, widget_args=[item, groups], silent=True)
self.list.add_item(
item.name, item, widget=Item, widget_args=[item, groups], silent=True
)
self.list.filter()
self.list.clear_selection()
@ -124,9 +133,7 @@ class ItemList(QFrame):
self.thread.errored.connect(self._failed_loading)
self.thread.completed.connect(self._successful_loading)
self.app.show_loading(
"Loading",
f"Fetching data from database...")
self.app.show_loading("Loading", f"Fetching data from database...")
self.thread.start()
@ -142,11 +149,10 @@ class ItemList(QFrame):
@error_handler
def _delete_item(self, item, force=False):
title = f"Are you sure?"
description = f"Do you really want to delete {item.name}? This action cannot be undone."
result = self.app.warning_dialog(
title,
description,
mode=Dialog.DOUBLE)
description = (
f"Do you really want to delete {item.name}? This action cannot be undone."
)
result = self.app.warning_dialog(title, description, mode=Dialog.DOUBLE)
if not result:
return
@ -173,11 +179,7 @@ class Item(QWidget):
self.layout().addWidget(name)
if groups:
label = QLabel(', '.join([g.name for g in groups]))
label = QLabel(", ".join([g.name for g in groups]))
label.setFont(Font(relative=-2))
label.setObjectName("user_widget_role")
self.layout().addWidget(label)

@ -59,7 +59,9 @@ class Project(QWidget):
self.information = Temp()
icon = os.path.join(symbols_directory, "information.png")
self.menu_bar.add_item(self.information, "Information", scrollable=False, icon=icon)
self.menu_bar.add_item(
self.information, "Information", scrollable=False, icon=icon
)
self.dashboard = Temp()
icon = os.path.join(symbols_directory, "meter.png")
@ -78,16 +80,22 @@ class Project(QWidget):
metadata = self.menu_bar.add_group("Metadata", icon=icon)
self.metadata_browse = Temp()
self.menu_bar.add_item(self.metadata_browse, "Browse", scrollable=False, parent=metadata)
self.menu_bar.add_item(
self.metadata_browse, "Browse", scrollable=False, parent=metadata
)
self.metadata_definition = Temp()
self.menu_bar.add_item(self.metadata_definition, "Definitions", scrollable=False, parent=metadata)
self.menu_bar.add_item(
self.metadata_definition, "Definitions", scrollable=False, parent=metadata
)
icon = os.path.join(symbols_directory, "checked.png")
tasks = self.menu_bar.add_group("Tasks", icon=icon)
self.tasks_browse = Temp()
self.menu_bar.add_item(self.tasks_browse, "Browse", scrollable=False, parent=tasks)
self.menu_bar.add_item(
self.tasks_browse, "Browse", scrollable=False, parent=tasks
)
self.tasks_tags = Temp()
self.menu_bar.add_item(self.tasks_tags, "Tags", scrollable=False, parent=tasks)
@ -103,7 +111,9 @@ class Project(QWidget):
self.data_model = Temp()
icon = os.path.join(symbols_directory, "book.png")
self.menu_bar.add_item(self.data_model, "Data model", scrollable=False, icon=icon)
self.menu_bar.add_item(
self.data_model, "Data model", scrollable=False, icon=icon
)
self.settings = Temp()
icon = os.path.join(symbols_directory, "settings.png")
@ -121,19 +131,31 @@ class Project(QWidget):
for item_tag in item_tags:
view = ItemList(self.app, self, item_tag)
self.menu_bar.add_item(view, item_tag.plural.capitalize(), scrollable=False, parent=self.items)
self.menu_bar.add_item(
view, item_tag.plural.capitalize(), scrollable=False, parent=self.items
)
self._dynamic_views.append(view)
for group_tag in group_tags:
if group_tag.local:
continue
view = GroupList(self.app, self, group_tag)
self.menu_bar.add_item(view, group_tag.plural.capitalize(), scrollable=False, parent=self.groups)