Skip to content

App

Bases: _Plugin

Bip Application class.

The App class provides convenient methods for creating a well-integrated Bip application. It comes with the following features: - Easy access to Bip data via link. - Bip-flavored window embedment, using Bip Qt stylesheet. - Threaded loading. - Support for hosted and standalone execution contexts. - Bip widgets (MessageBox, Notifications...). - Hosted address retrieving (see get_address() method). - Preset logger.

The recommended way to create a Bip application is to subclass and extend the App class. Then the instantiation of the App is handled by the sdk runner, which also executes the application.

Warning

Unless you are debugging,the subclassed application must be instantiated by the sdk runner.

This class provides special methods to override, such as init() and load(), which are respectively called during the threaded initialization (init()), and immediately after (load())

When executed, the application will automatically perform the following actions: - Instance arguments validity - Check connection with database - Retrieve the current user - Retrieve the user's active project - Retrieve the server configuration

Examples:

from bip.sdk import App, run
from myapp.ui import Widget
from myapp.api import get_data


class SampleApp(App):
    name = "Sample"
    slug = "sample"
    version = "v0.0.1"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.widget = Widget()
        self.set_widget(self.widget)

        self.data = None

    def init(self, callback):
        # Executed at initialization (threaded).
        self.data = get_data()

    def load(self):
        # Executed after initialization.
        self.widget.load(self.data)

app = run(SampleApp)

See the demo Chocolatine application for a complete example: https://git.blinkink.co.uk/bip/apps/chocolatine.

Todo

Find a better error handling system. For now, common errors like PermissionError and Connection error are handled in two different ways: - When not threaded: with from @error_handler (which requires the widget to have self.app). - When threaded: with the Worker failed signal.

Attributes:

Name Type Description
resizable bool

(class attribute) If True, the window can be resized. Defaults to False.

closable bool

(class attribute) If True, the window can be closed. Defaults to True.

minimizable bool

(class attribute) If True, the window can be minimized. Defaults to True.

maximizable bool

(class attribute) If True, the window can be maximized. resizable must be set to True. Defaults to False.

use_header bool

(class attribute) If True, the default Bip application window header is used. Defaults to True.

floating_header bool

(class attribute) If True, the window header overlaps the main widget. Defaults to False.

supported_contexts list

(class attribute) List of supported contexts for the application. Allowed context are: - bip.wink.HOSTED: The application can be executed from a host (DCC) runtime. - bip.wink.STANDALONE: The application can be executed as a standalone, using Bip default Python runtime. - bip.wink.REMOTE: The application is executed as a standalone from a host (DCC), using Bip default Python runtime.

context str

Current execution context. Accepted values are bip.wink.HOSTED and bip.wink.STANDALONE.

logger Logger

Application logger. If the app has been executed with the sdk runner, the logger is handled by bip.mink.logs.

host Host

If the application is hosted or remote, Host plugin of the current DCC, else None.

current_user User

Currently logged in Bip user.

active_project Project

Active project of the currently logged in Bip user.

config dict

Plugin configuration dictionary, if the plugin descriptor defines a config template.

mapping dict

Plugin mapping dictionary, if the plugin descriptor defines a mapping template.

default_settings dict

Plugin default settings dictionary, if the plugin descriptor defines a setting template.

settings dict

Plugin user settings dictionary, if the plugin descriptor defines a setting template.

Warning

If you extend the __init__ method behaviour, bear in mind that it is run before the application gets executed ('execute()'). That means:

  • The window is not yet shown, and any long operation ran there would be invisible, which is a bad UX design.
  • The connection with the database has not yet been verified, which means that any link call performed here could lead to an uncaught exception.
  • The attributes current_user, active_project and config are still undefined.

Parameters:

Name Type Description Default
context str

Execution context. Accepted values are wink.STANDALONE and wink.HOSTED.

required
host str

If the application is hosted, id of the host plugin to be run.

None
silent bool

If True, the window is not shown after execution. Defaults to False.

False
Source code in client/bip/sdk/app.py
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
def __init__(
    self, plugin, logger, context, host=None, silent=False, stylesheet=None
):
    """Initializes the application based on the given context.

    !!! warning
        If you extend the `__init__` method behaviour, bear in mind that it
        is run before the application gets executed ('execute()'). That means:

        - The window is not yet shown, and any long operation ran there would be invisible, which is a bad UX design.
        - The connection with the database has not yet been verified, which
        means that any `link` call performed here could lead to an uncaught exception.
        - The attributes `current_user`, `active_project` and `config` are still undefined.

    Args:
        context (str): Execution context. Accepted values are `wink.STANDALONE` and `wink.HOSTED`.
        host (str): If the application is hosted, id of the host plugin to be run.
        silent (bool): If `True`, the window is not shown after execution. Defaults to `False`.

    """
    super().__init__(plugin, logger)
    self.context = context
    self.host = None
    self.current_user = None
    self.active_project = None

    self._last_used_version = None

    self.__silent = silent
    self.__executed = False
    self.__window = None

    if host:
        self.host = mink.plugins.get_host(host)

    if context == REMOTE:
        self._listen()

    self.__parent = self.host.window if self.host else None
    self.__window = BipWindow(
        self,
        context=context,
        parent=self.__parent,
        callback=None,
        stylesheet=stylesheet,
    )

hosted property

Is the application hosted.

The application is hosted if the application is executed from a DCC runtime.

Returns:

Name Type Description
bool

True if hosted, False otherwise.

last_used_version property

Last version used.

Gives the latest version of the application that has been successfully started on the current machine. If BIP_DEBUG_PLUGIN is on, nothing is returned

Returns:

Name Type Description
str

Version number.

silent property

Is the application silent.

If the application has been set to silent, is it running without showing the window.

Returns:

Name Type Description
bool

True if silent, False otherwise.

stylesheet property

Complete stylesheet.

The complete compiled application stylesheet. It includes the SDK stylesheets, the bip.uink stylesheets as well as the custom stylesheet if any.

Returns:

Name Type Description
str

Raw stylesheet.

adjust_size()

Adjust the window size.

Source code in client/bip/sdk/app.py
335
336
337
def adjust_size(self):
    """Adjust the window size."""
    self.__window.adjust_size()

center()

Center the window.

Source code in client/bip/sdk/app.py
331
332
333
def center(self):
    """Center the window."""
    self.__window.center()

close()

Close the window.

Source code in client/bip/sdk/app.py
327
328
329
def close(self):
    """Close the window."""
    self.__window.close()

close_loading()

Closes the currently opened loading overlay.

Source code in client/bip/sdk/app.py
476
477
478
def close_loading(self):
    """Closes the currently opened loading overlay."""
    self.__window.close_loading()

close_popup()

Close the currently opened popup overlay.

Source code in client/bip/sdk/app.py
462
463
464
465
def close_popup(self):
    """Close the currently opened popup overlay."""

    self.__window.close_popup()

confirm_dialog(title, description, details=None, mode=Dialog.DOUBLE, choices=None, closable=True, overlay=True, hidden_details=False)

Convenient preset shortcut to App.dialog().

Level is set to Dialog.WARNING and mode is set to Dialog.DOUBLE.

Source code in client/bip/sdk/app.py
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
def confirm_dialog(
    self,
    title,
    description,
    details=None,
    mode=Dialog.DOUBLE,
    choices=None,
    closable=True,
    overlay=True,
    hidden_details=False,
):
    """Convenient preset shortcut to `App.dialog()`.

    Level is set to `Dialog.WARNING` and mode is set to `Dialog.DOUBLE`.
    """
    return self.dialog(
        title,
        description,
        details,
        WARNING,
        mode,
        choices,
        closable,
        overlay,
        hidden_details,
    )

dialog(title, description, details=None, level=NEUTRAL, mode=Dialog.SINGLE, choices=None, closable=True, overlay=True, hidden_details=False, log=True)

Shows a message dialog.

Tip

  • If an Exception is provided to the details argument, its traceback is automatically retrieved and added to the details text.
  • Any dialog message is automatically logged into the application logger. This can be deactivated by setting the log argument to False.

Examples:

Standard:

self.dialog(
    title="Hello world",
    description="This is a dialog demonstration.",
    level=Dialog.INFO
)

Double choices:

title = "Forbidden operation"
description = (
    "It is impossible to save this scene because you don't own this scene, "
    "do you want to save a new version?"
)
result = self.dialog(
    title=title,
    description=description,
    level=Dialog.WARNING,
    mode=Dialog.DOUBLE,
    choices=Dialog.YES_NO,
)
if result:
    save_up()

Multiple choices:

title = "Save changes?"
description = "The current scene has been modified, what do you want to do?"
choices = {"Save": "save", "Ignore": "ignore", "Cancel": "cancel"}
result = self.dialog(
    title=title,
    description=description,
    mode=Dialog.MULTIPLE,
    level=Dialog.WARNING,
    choices=choices,
)
if result == "save":
    save()
elif result == "cancel":
    return

Parameters:

Name Type Description Default
title str

Title of the dialog message.

required
description str

Description of the dialog message.

required
details str or Exception

Additional details displayed in a

None
level str

Level of the dialog. Accepted values are

NEUTRAL
mode str

Level of the dialog. Accepted values are

SINGLE
choices str or dict

Button(s) choice(s). They can be a hint or a custom dictionary. - Hint: Accepted values are Dialog.OK and Dialog.PROCEED if the mode is set to Dialog.SINGLE, Dialog.YES_NO and Dialog.OK_CANCEL if the mode is set to Dialog.DOUBLE - Custom: A dictionary with the display texts as keys, and the returned values as values.

None
closable bool

If True, the dialog can be closed normally,

True
overlay bool

If True, the dialog is a modal of the main

True
hidden_details bool

If True and if details are

False
log bool

If True, the message is automatically logged,

True

Raises:

Type Description
TypeError
  • title is not a string.
  • description is not a string.
ValueError
  • mode is invalid.
  • level is invalid.
  • choices is not valid (unknown hint or wrong length)
Source code in client/bip/sdk/app.py
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
def dialog(
    self,
    title,
    description,
    details=None,
    level=NEUTRAL,
    mode=Dialog.SINGLE,
    choices=None,
    closable=True,
    overlay=True,
    hidden_details=False,
    log=True,
):
    """Shows a message dialog.

    !!! tip
        - If an Exception is provided to the `details` argument,
        its traceback is automatically retrieved and added to the details text.
        - Any dialog message is automatically logged into the application logger. This can
        be deactivated by setting the log argument to False.

    Examples:
        Standard:
        ```python
        self.dialog(
            title="Hello world",
            description="This is a dialog demonstration.",
            level=Dialog.INFO
        )
        ```

        Double choices:
        ```python
        title = "Forbidden operation"
        description = (
            "It is impossible to save this scene because you don't own this scene, "
            "do you want to save a new version?"
        )
        result = self.dialog(
            title=title,
            description=description,
            level=Dialog.WARNING,
            mode=Dialog.DOUBLE,
            choices=Dialog.YES_NO,
        )
        if result:
            save_up()
        ```


        Multiple choices:
        ```python
        title = "Save changes?"
        description = "The current scene has been modified, what do you want to do?"
        choices = {"Save": "save", "Ignore": "ignore", "Cancel": "cancel"}
        result = self.dialog(
            title=title,
            description=description,
            mode=Dialog.MULTIPLE,
            level=Dialog.WARNING,
            choices=choices,
        )
        if result == "save":
            save()
        elif result == "cancel":
            return
        ```

    Args:
        title (str): Title of the dialog message.
        description (str, optional): Description of the dialog message.
        details (str or Exception, optional): Additional details displayed in a
        scrollable text box. Suitable for long texts such as error reports. If
        an Exception object is provided, the traceback is automatically
        retrieved.
        level (str, optional): Level of the dialog. Accepted values are
        `Dialog.NEUTRAL`, `Dialog.ERROR`, `Dialog.WARNING`, `Dialog.INFO`, `Dialog.SUCCESS`. Defaults to `NEUTRAL`.
        mode (str, optional): Level of the dialog. Accepted values are
        `Dialog.SINGLE`, `Dialog.DOUBLE`, `Dialog.MULTIPLE`. Defaults to `SINGLE`.
            - SINGLE: One validation button. If no `choices` specified, "ok" button.
            - DOUBLE: Two validation buttons. If no `choices` specified, "ok/cancel" buttons.
            - MULTIPLE: Multiple validation buttons. If used, a `choice` dictionary must be provided.
        choices (str or dict, optional): Button(s) choice(s). They can be a hint or a custom dictionary.
            - Hint: Accepted values are `Dialog.OK` and `Dialog.PROCEED` if the
            mode is set to `Dialog.SINGLE`, `Dialog.YES_NO` and
            `Dialog.OK_CANCEL` if the mode is set to `Dialog.DOUBLE`
            - Custom: A dictionary with the display texts as keys, and the returned values as values.
        closable (bool, optional): If `True`, the dialog can be closed normally,
        otherwise, a choice must be validated. Defaults to `True`.
        overlay (bool, optional): If `True`, the dialog is a modal of the main
        window, otherwise it is a regular window. Caution, if set to `True`, the
        application window must be visible. Defaults to `True`.
        hidden_details (bool, optional): If `True` and if `details` are
        provided, the details text box is collapsed by default. Defaults to `False`.
        log (bool, optional): If `True`, the message is automatically logged,
        with all the details provided. Defaults to `True`.

    Raises:
        TypeError:
            - `title` is not a string.
            - `description` is not a string.

        ValueError:
            - `mode` is invalid.
            - `level` is invalid.
            - `choices` is not valid (unknown hint or wrong length)

    """

    if self.__window and not self.__silent:
        self.__window.show_blank_overlay()
        container = self.__window.frame
    else:
        overlay = False
        container = None
    dialog = Dialog(
        title,
        description,
        context=self.context,
        details=details,
        level=level,
        mode=mode,
        choices=choices,
        container=container,
        parent=self.__parent,
    )

    dialog.closable = closable
    dialog.use_header = not overlay
    dialog.resizable = overlay
    dialog.hidden_details = hidden_details

    # Logging
    if log:
        if isinstance(details, Exception):
            title = details.__class__.__name__
            exc_info = True
        else:
            exc_info = False

        text = f"{title}  ({description})"

        if level in (NEUTRAL, INFO, SUCCESS):
            self.logger.info(text, exc_info=exc_info)
        elif level == WARNING:
            self.logger.warning(text, exc_info=exc_info)
        elif level == ERROR:
            self.logger.error(text, exc_info=exc_info)

    # Run
    force_on_top = self.context == REMOTE
    value = dialog.run(force_on_top)

    if self.__window and not self.__silent:
        self.__window.hide_blank_overlay()

    return value

error_dialog(title, description, details=None, mode=Dialog.SINGLE, choices=None, closable=True, overlay=True, hidden_details=False)

Convenient preset shortcut to App.dialog().

Level is set to Dialog.ERROR.

Source code in client/bip/sdk/app.py
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
def error_dialog(
    self,
    title,
    description,
    details=None,
    mode=Dialog.SINGLE,
    choices=None,
    closable=True,
    overlay=True,
    hidden_details=False,
):
    """Convenient preset shortcut to `App.dialog()`.

    Level is set to `Dialog.ERROR`.
    """
    return self.dialog(
        title,
        description,
        details,
        ERROR,
        mode,
        choices,
        closable,
        overlay,
        hidden_details,
    )

execute()

Execute (start) the application.

Executing the application shows the window if the application is not silent, and performs the internal and custom initialization operation.

Warning

This can only be run once.

Source code in client/bip/sdk/app.py
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
def execute(self):
    """Execute (start) the application.

    Executing the application shows the window if the application is not silent,
    and performs the internal and custom initialization operation.

    !!! warning
        This can only be run once.
    """
    if self.__executed:
        return

    if not self.__silent:
        self.__window.show()

    self.__window.threaded_loading(loader=self._load)

    self.__executed = True

get_address()

Returns a pink.Address object.

If the application is hosted, the Address object inspects the file currently loaded in the host, if any, and returns its Bip representation, if the file is a tracked Version.

Info

See the documentation of pink.Address for further information.

Returns:

Name Type Description
Address

Address object from the file currently loaded in the host.

None

If the application is not hosted.

Source code in client/bip/sdk/app.py
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
def get_address(self):
    """Returns a pink.Address object.

    If the application is hosted, the Address object inspects the file currently
    loaded in the host, if any, and returns its Bip representation, if the file is a tracked Version.

    !!! info
        See the documentation of `pink.Address` for further information.

    Returns:
        Address: Address object from the file currently loaded in the host.
        None: If the application is not hosted.
    """
    if self.context not in (HOSTED, REMOTE):
        return
    return pink.address.get_from_host(self.host)

get_changelog()

Get the extracted changelog.

If the package root file CHANGELOG.md is correctly formatted, a dict of the changelog for each version is returned.

The dictionary is structured like so:

{"v0.0.1":
    {
        "date": _current_date,
        "url": _current_url,
        "content": content
    },
...
}

Returns:

Name Type Description
dict

Collection of changelog data.

Source code in client/bip/sdk/app.py
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
def get_changelog(self):
    """Get the extracted changelog.

    If the package root file CHANGELOG.md is correctly formatted,
    a dict of the changelog for each version is returned.

    The dictionary is structured like so:
    ```python
    {"v0.0.1":
        {
            "date": _current_date,
            "url": _current_url,
            "content": content
        },
    ...
    }
    ```

    Returns:
        dict: Collection of changelog data.
    """
    file_ = inspect.getfile(self.__class__)
    here = Path(file_).parent
    package_root = here.parent
    path = package_root / "CHANGELOG.md"
    if not path.exists():
        raise ValueError(f"Changelog file {path} cannot be found.")

    return mink.changelog.extract(path)

get_config()

Convenient shortcut to `link.config.get()

Source code in client/bip/sdk/app.py
808
809
810
def get_config(self):
    """Convenient shortcut to `link.config.get()"""
    return link.config.get()

get_projects()

Convenient shortcut to `link.project.get()

Source code in client/bip/sdk/app.py
800
801
802
def get_projects(self):
    """Convenient shortcut to `link.project.get()"""
    return link.project.get()

get_users()

Convenient shortcut to `link.user.get()

Source code in client/bip/sdk/app.py
804
805
806
def get_users(self):
    """Convenient shortcut to `link.user.get()"""
    return link.user.get()

hide()

Hide the window.

Source code in client/bip/sdk/app.py
323
324
325
def hide(self):
    """Hide the window."""
    self.__window.hide()

info_dialog(title, description, details=None, mode=Dialog.SINGLE, choices=None, closable=True, overlay=True, hidden_details=False)

Convenient preset shortcut to App.dialog().

Level is set to Dialog.INFO.

Source code in client/bip/sdk/app.py
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
def info_dialog(
    self,
    title,
    description,
    details=None,
    mode=Dialog.SINGLE,
    choices=None,
    closable=True,
    overlay=True,
    hidden_details=False,
):
    """Convenient preset shortcut to `App.dialog()`.

    Level is set to `Dialog.INFO`.
    """
    return self.dialog(
        title,
        description,
        details,
        INFO,
        mode,
        choices,
        closable,
        overlay,
        hidden_details,
    )

init(callback)

Overridable method for executing operation during initialization.

This is the recommended way to perform startup operation, such as data retrieving. It is particularly encouraged if this operation is time-consuming.

This method is executed at the end of the threaded loading, which means that at this smodele, the application window is shown and the loading overlay is visible, giving the user some visual feedback on what is going on.

The callback can be used to update the text of the loading overlay.

Info

Raising exception is the recommended way to properly interrupt the initialization.

Examples:

def init(self, callback):
    callback("Loading data")
    data = my_api.get()

    callback("Inspect data")
    if not my_api.inspect():
        raise ValueError("The is are not valid")

Parameters:

Name Type Description Default
callback func(`str

Updates the loading overlay with a custom text. The callback is passed to the method by the execution thread.

required
Source code in client/bip/sdk/app.py
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
def init(self, callback):
    """Overridable method for executing operation during initialization.

    This is the recommended way to perform startup operation, such as data retrieving.
    It is particularly encouraged if this operation is time-consuming.

    This method is executed at the end of the threaded loading, which means that at this smodele, the application
    window is shown and the loading overlay is visible, giving the user some visual feedback on
    what is going on.

    The callback can be used to update the text of the loading overlay.

    !!! info
        Raising exception is the recommended way to properly interrupt the initialization.

    Examples:
        ```python
        def init(self, callback):
            callback("Loading data")
            data = my_api.get()

            callback("Inspect data")
            if not my_api.inspect():
                raise ValueError("The is are not valid")
        ```

    Args:
        callback (func(`str)): Updates the loading overlay with a custom text. The callback is passed to the method by the execution thread.

    """
    pass

load()

Overridable method for executing operation after initialization.

This is the recommended way to perform post-initialization operation. This is executed after the init() method, and the main difference with init() is that load() is not threaded.

Tip

The execution of this method is done is the main thread, which means it can be used to update the UI safely.

Source code in client/bip/sdk/app.py
270
271
272
273
274
275
276
277
278
279
280
281
def load(self):
    """Overridable method for executing operation after initialization.

    This is the recommended way to perform post-initialization operation. This is
    executed after the `init()` method, and the main difference with `init()` is
    that `load()` is not threaded.

    !!! tip
        The execution of this method is done is the main thread, which means it can be used to update the UI safely.

    """
    pass

neutral_dialog(title, description, details=None, mode=Dialog.SINGLE, choices=None, closable=True, overlay=True, hidden_details=False)

Convenient preset shortcut to App.dialog().

Level is set to Dialog.NEUTRAL.

Source code in client/bip/sdk/app.py
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
def neutral_dialog(
    self,
    title,
    description,
    details=None,
    mode=Dialog.SINGLE,
    choices=None,
    closable=True,
    overlay=True,
    hidden_details=False,
):
    """Convenient preset shortcut to `App.dialog()`.

    Level is set to `Dialog.NEUTRAL`.
    """
    return self.dialog(
        title,
        description,
        details,
        NEUTRAL,
        mode,
        choices,
        closable,
        overlay,
        hidden_details,
    )

notify(text, subtext=None, level=NEUTRAL, position=BOTTOM, auto_close=5)

Show an overlay notification.

Warning

Experimental feature: does not seem to work in hosted context.

NEUTRAL = NEUTRAL ERROR = ERROR WARNING = WARNING INFO = INFO SUCCESS = SUCCESS

Position

TOP = TOP MIDDLE = MIDDLE BOTTOM = BOTTOM

Parameters:

Name Type Description Default
text str

Text of the notification.

required
subtext str

Additional text.

None
level str

Level of the notification. Accepted values are

NEUTRAL
position str

Vertical alignment. Accepted values are wink.TOP, wink.MIDDLE, wink.BOTTOM.

BOTTOM
auto_close int

Auto-close delay value, in seconds. If set to 0, auto-close is disabled. Defaults to 5.

5
Source code in client/bip/sdk/app.py
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
def notify(self, text, subtext=None, level=NEUTRAL, position=BOTTOM, auto_close=5):
    """Show an overlay notification.

    !!! warning
        **Experimental feature**: does not seem to work in hosted context.

    NEUTRAL = NEUTRAL
    ERROR = ERROR
    WARNING = WARNING
    INFO = INFO
    SUCCESS = SUCCESS

    # Position
    TOP = TOP
    MIDDLE = MIDDLE
    BOTTOM = BOTTOM

    Args:
        text (str): Text of the notification.
        subtext (str, optional): Additional text.
        level (str, optional): Level of the notification. Accepted values are
        `wink.NEUTRAL`, `wink.ERROR`, `wink.WARNING`, `wink.INFO`, `wink.SUCCESS`. Defaults to `NEUTRAL`.
        position (str, optional): Vertical alignment. Accepted values are `wink.TOP`, `wink.MIDDLE`, `wink.BOTTOM`.
        auto_close (int, optional): Auto-close delay value, in seconds. If set to 0, auto-close is disabled. Defaults to 5.
    """
    self.__window.notify(text, subtext, level, position, auto_close)

popup(widget, escape_allowed=True, escape_callback=None, expand=False, margin=None, transparent=False)

Add a popup widget.

A popup widget is a centered overlay on top of the main window. A typical use case is for modal dialogs.

Parameters:

Name Type Description Default
widget QWidget

Widget to place in the overlay.

required
escape_allowed bool

If True, the overlay can be closed by clicking outside. Defaults to True.

True
escape_callback func

If provided and if escape_allowed

None
Source code in client/bip/sdk/app.py
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
def popup(
    self,
    widget,
    escape_allowed=True,
    escape_callback=None,
    expand=False,
    margin=None,
    transparent=False,
):
    """Add a popup widget.

    A popup widget is a centered overlay on top of the main window. A typical use case is for modal dialogs.

    Args:
        widget (QWidget): Widget to place in the overlay.
        escape_allowed (bool, optional): If True, the overlay can be closed by clicking outside. Defaults to `True`.
        escape_callback (func, optional): If provided and if `escape_allowed`
        is True, the callback gets called if the overlay is escaped.
    """
    self.__window.popup(
        widget, escape_allowed, escape_callback, expand, margin, transparent
    )

quit()

Quit the application.

Source code in client/bip/sdk/app.py
369
370
371
372
373
374
375
376
377
def quit(self):
    """Quit the application."""
    try:
        self.close()
    except AttributeError:
        pass

    if not self.context == HOSTED:
        sys.exit()

refresh_active_project()

Force get currently logged-in user's active project.

It can be of use if an application is sleeping in the background and the active project could have changed between two calls.

Source code in client/bip/sdk/app.py
837
838
839
840
841
842
843
844
845
846
def refresh_active_project(self):
    """Force get currently logged-in user's active project.

    It can be of use if an application is sleeping in the
    background and the active project could have changed between two calls.
    """
    try:
        self._get_active_project()
    except ValueError as e:
        self.error_dialog("Active project error", str(e), e)

refresh_current_user()

Force get currently logged-in user.

It can be of use if an application is sleeping in the background and the current user could have changed between two calls.

Source code in client/bip/sdk/app.py
829
830
831
832
833
834
835
def refresh_current_user(self):
    """Force get currently logged-in user.

    It can be of use if an application is sleeping in the
    background and the current user could have changed between two calls.
    """
    self._get_current_user()

remote_order(order)

Overridable method for interpreting remote orders.

If a remote application needs to receive user instructions from the remote host during runtime, those orders, sent with mink.remote.send(), would be sent to this method.

Overriding with a case per order is the recommended way to apply those orders to the application.

Source code in client/bip/sdk/app.py
848
849
850
851
852
853
854
855
856
857
858
def remote_order(self, order):
    """Overridable method for interpreting remote orders.

    If a remote application needs to receive user instructions from the remote host during runtime,
    those orders, sent with `mink.remote.send()`, would be sent to this method.

    Overriding with a case per order is the recommended way to apply those orders to the application.

    """
    if order == QUIT:
        self.quit()

set_title(title)

Set the header title.

Parameters:

Name Type Description Default
title str

Header title.

required
Source code in client/bip/sdk/app.py
302
303
304
305
306
307
308
def set_title(self, title):
    """Set the header title.

    Args:
        title (str): Header title.
    """
    self.__window.set_title(title)

set_widget(widget)

Set the main widget of the window.

Parameters:

Name Type Description Default
widget QWidget

Main widget.

required
Source code in client/bip/sdk/app.py
283
284
285
286
287
288
289
290
def set_widget(self, widget):
    """Set the main widget of the window.

    Args:
        widget (QWidget): Main widget.
    """

    self.__window.set_widget(widget)

set_window_size(height, width, centered=False)

Set the window size.

Parameters:

Name Type Description Default
width int

Width in pixels.

required
height int

Height in pixels.

required
centered bool

If True, the window will be centered relatively to its previous position. Defaults to False.

False
Source code in client/bip/sdk/app.py
292
293
294
295
296
297
298
299
300
def set_window_size(self, height, width, centered=False):
    """Set the window size.

    Args:
        width (int): Width in pixels.
        height (int): Height in pixels.
        centered (bool): If True, the window will be centered relatively to its previous position. Defaults to `False`.
    """
    self.__window.set_window_size(height, width, centered)

set_window_title(title)

Set the window title.

Parameters:

Name Type Description Default
title str

Window title.

required
Source code in client/bip/sdk/app.py
310
311
312
313
314
315
316
def set_window_title(self, title):
    """Set the window title.

    Args:
        title (str): Window title.
    """
    self.__window.set_window_title(title)

show()

Show the window.

Source code in client/bip/sdk/app.py
318
319
320
321
def show(self):
    """Show the window."""
    force_on_top = True if self.context == REMOTE else False
    self.__window.show(force_on_top)

show_changelog()

Show the changelog popup.

Source code in client/bip/sdk/app.py
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
def show_changelog(self):
    """Show the changelog popup."""
    _margin = 54
    _threshold = 400
    _changed = False

    widget = Changelogs(self)
    size = self.__window.frame.size()
    height, width = size.height(), size.width()
    temp_height, temp_width = height, width
    if height <= _threshold:
        temp_height = _threshold
        _changed = True

    if width <= _threshold:
        temp_width = _threshold
        _changed = True

    if _changed:
        self.set_window_size(temp_height, temp_width, centered=True)

    def callback():
        if _changed:
            self.set_window_size(width, height, centered=True)

    self.popup(
        widget=widget,
        expand=True,
        margin=_margin,
        transparent=True,
        escape_callback=callback,
    )

show_loading(title, subtext=None)

Show a loading overlay.

Parameters:

Name Type Description Default
title str

Title of the overlay.

required
subtext str

Subtext (description) of the overlay.

None
Source code in client/bip/sdk/app.py
467
468
469
470
471
472
473
474
def show_loading(self, title, subtext=None):
    """Show a loading overlay.

    Args:
        title (str): Title of the overlay.
        subtext (str, optional): Subtext (description) of the overlay.
    """
    self.__window.show_loading(title, subtext)

success_dialog(title, description, details=None, mode=Dialog.SINGLE, choices=None, closable=True, overlay=True, hidden_details=False)

Convenient preset shortcut to App.dialog().

Level is set to Dialog.SUCCESS.

Source code in client/bip/sdk/app.py
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
def success_dialog(
    self,
    title,
    description,
    details=None,
    mode=Dialog.SINGLE,
    choices=None,
    closable=True,
    overlay=True,
    hidden_details=False,
):
    """Convenient preset shortcut to `App.dialog()`.

    Level is set to `Dialog.SUCCESS`.
    """
    return self.dialog(
        title,
        description,
        details,
        SUCCESS,
        mode,
        choices,
        closable,
        overlay,
        hidden_details,
    )

warning_dialog(title, description, details=None, mode=Dialog.SINGLE, choices=None, closable=True, overlay=True, hidden_details=False)

Convenient preset shortcut to App.dialog().

Level is set to Dialog.WARNING.

Source code in client/bip/sdk/app.py
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
def warning_dialog(
    self,
    title,
    description,
    details=None,
    mode=Dialog.SINGLE,
    choices=None,
    closable=True,
    overlay=True,
    hidden_details=False,
):
    """Convenient preset shortcut to `App.dialog()`.

    Level is set to `Dialog.WARNING`.
    """
    return self.dialog(
        title,
        description,
        details,
        WARNING,
        mode,
        choices,
        closable,
        overlay,
        hidden_details,
    )