|
63 | 63 | from datalab.gui.h5io import H5InputOutput |
64 | 64 | from datalab.gui.panel import base, image, macro, signal |
65 | 65 | from datalab.gui.settings import edit_settings |
66 | | -from datalab.plugins import PluginRegistry, discover_plugins |
| 66 | +from datalab.plugins import PluginRegistry, discover_plugins, discover_v020_plugins |
67 | 67 | from datalab.utils import dephash |
68 | 68 | from datalab.utils import qthelpers as qth |
69 | 69 | from datalab.utils.qthelpers import ( |
@@ -651,10 +651,64 @@ def check_for_previous_crash(self) -> None: # pragma: no cover |
651 | 651 | if choice == QW.QMessageBox.StandardButton.Yes: |
652 | 652 | self.__show_logviewer() |
653 | 653 |
|
| 654 | + def check_for_v020_plugins(self) -> None: # pragma: no cover |
| 655 | + """Check for v0.20 plugins and warn user if any are found""" |
| 656 | + if Conf.main.v020_plugins_warning_ignore.get(False): |
| 657 | + return |
| 658 | + |
| 659 | + v020_plugins = discover_v020_plugins() |
| 660 | + if execenv.unattended or not v020_plugins: |
| 661 | + return |
| 662 | + |
| 663 | + # Build plugin list with clickable directory paths |
| 664 | + plugin_items = [] |
| 665 | + for name, directory_path in v020_plugins: |
| 666 | + if directory_path: |
| 667 | + # Create clickable file:// link to directory |
| 668 | + dir_url = QC.QUrl.fromLocalFile(directory_path).toString() |
| 669 | + plugin_items.append( |
| 670 | + f'<li>{name} (<a href="{dir_url}">{directory_path}</a>)</li>' |
| 671 | + ) |
| 672 | + else: |
| 673 | + plugin_items.append(f"<li>{name}</li>") |
| 674 | + plugin_list = "<ul>" + "".join(plugin_items) + "</ul>" |
| 675 | + |
| 676 | + txtlist = [ |
| 677 | + "<b>" + _("DataLab v0.20 plugins detected") + "</b>", |
| 678 | + "", |
| 679 | + _("The following plugins are using the old DataLab v0.20 format:"), |
| 680 | + plugin_list, |
| 681 | + _( |
| 682 | + "These plugins will <b>not be loaded</b> in DataLab v1.0 because " |
| 683 | + "they are not compatible with the new architecture." |
| 684 | + ), |
| 685 | + "", |
| 686 | + _( |
| 687 | + "To use these plugins with DataLab v1.0, you need to update them. " |
| 688 | + "Please refer to the migration guide on the DataLab website " |
| 689 | + ) |
| 690 | + + '(<a href="https://datalab-platform.com/en/features/advanced/' |
| 691 | + 'migration_v020_to_v100.html">Migration guide</a>)' |
| 692 | + + _(" or in the PDF documentation."), |
| 693 | + "", |
| 694 | + _("Choosing to ignore this message will prevent it from appearing again."), |
| 695 | + ] |
| 696 | + |
| 697 | + answer = QW.QMessageBox.question( |
| 698 | + self, |
| 699 | + APP_NAME, |
| 700 | + "<br>".join(txtlist), |
| 701 | + QW.QMessageBox.Ok | QW.QMessageBox.Ignore, |
| 702 | + ) |
| 703 | + |
| 704 | + if answer == QW.QMessageBox.Ignore: |
| 705 | + Conf.main.v020_plugins_warning_ignore.set(True) |
| 706 | + |
654 | 707 | def execute_post_show_actions(self) -> None: |
655 | 708 | """Execute post-show actions""" |
656 | 709 | self.check_stable_release() |
657 | 710 | self.check_for_previous_crash() |
| 711 | + self.check_for_v020_plugins() |
658 | 712 | tour = Conf.main.tour_enabled.get() |
659 | 713 | if tour: |
660 | 714 | Conf.main.tour_enabled.set(False) |
@@ -895,7 +949,7 @@ def __setup_global_actions(self) -> None: |
895 | 949 | _("Auto-refresh"), |
896 | 950 | icon=get_icon("refresh-auto.svg"), |
897 | 951 | tip=_("Auto-refresh plot when object is modified, added or removed"), |
898 | | - toggled=self.toggle_auto_refresh, |
| 952 | + toggled=self.handle_autorefresh_action, |
899 | 953 | ) |
900 | 954 | self.showfirstonly_action = create_action( |
901 | 955 | self, |
@@ -1385,6 +1439,48 @@ def toggle_show_titles(self, state: bool) -> None: |
1385 | 1439 | obj.set_metadata_option("showlabel", state) |
1386 | 1440 | datapanel.refresh_plot("selected", True, False) |
1387 | 1441 |
|
| 1442 | + def handle_autorefresh_action(self, state: bool) -> None: |
| 1443 | + """Handle auto-refresh action from UI (with confirmation dialog) |
| 1444 | +
|
| 1445 | + Args: |
| 1446 | + state: desired state |
| 1447 | + """ |
| 1448 | + # If disabling auto-refresh, show confirmation dialog |
| 1449 | + if not state: |
| 1450 | + txtlist = [ |
| 1451 | + "<b>" + _("Disable auto-refresh?") + "</b>", |
| 1452 | + "", |
| 1453 | + _( |
| 1454 | + "When auto-refresh is disabled, the plot view will not " |
| 1455 | + "automatically update when objects are modified, added or removed." |
| 1456 | + ), |
| 1457 | + "", |
| 1458 | + _( |
| 1459 | + "You will need to manually click the refresh button to update " |
| 1460 | + "the view." |
| 1461 | + ), |
| 1462 | + "", |
| 1463 | + _("Are you sure you want to disable auto-refresh?"), |
| 1464 | + ] |
| 1465 | + |
| 1466 | + answer = QW.QMessageBox.question( |
| 1467 | + self, |
| 1468 | + APP_NAME, |
| 1469 | + "<br>".join(txtlist), |
| 1470 | + QW.QMessageBox.Yes | QW.QMessageBox.No, |
| 1471 | + QW.QMessageBox.No, |
| 1472 | + ) |
| 1473 | + |
| 1474 | + if answer == QW.QMessageBox.No: |
| 1475 | + # User cancelled, restore the action's checked state |
| 1476 | + self.autorefresh_action.blockSignals(True) |
| 1477 | + self.autorefresh_action.setChecked(True) |
| 1478 | + self.autorefresh_action.blockSignals(False) |
| 1479 | + return |
| 1480 | + |
| 1481 | + # Apply the change |
| 1482 | + self.toggle_auto_refresh(state) |
| 1483 | + |
1388 | 1484 | @remote_controlled |
1389 | 1485 | def toggle_auto_refresh(self, state: bool) -> None: |
1390 | 1486 | """Toggle auto refresh option |
|
0 commit comments