|
6 | 6 | from crystal.app_preferences import app_prefs |
7 | 7 | from crystal.browser.entitytree import EntityTree |
8 | 8 | from crystal.browser.icons import TREE_NODE_ICONS |
| 9 | +from crystal.browser.new_alias import NewAliasDialog |
9 | 10 | from crystal.browser.new_group import NewGroupDialog |
10 | 11 | from crystal.browser.new_root_url import ChangePrefixCommand, NewRootUrlDialog |
11 | 12 | from crystal.browser.preferences import PreferencesDialog |
@@ -316,6 +317,11 @@ def _create_actions(self) -> None: |
316 | 317 | enabled=(not self._readonly), |
317 | 318 | button_bitmap=dict(DEFAULT_FOLDER_ICON_SET())[wx.TreeItemIcon_Normal], |
318 | 319 | button_label='New &Group...') |
| 320 | + self._new_alias_action = Action(wx.ID_ANY, |
| 321 | + 'New &Alias...', |
| 322 | + wx.AcceleratorEntry(wx.ACCEL_CTRL | wx.ACCEL_SHIFT, ord('A')), |
| 323 | + self._on_new_alias, |
| 324 | + enabled=(not self._readonly)) |
319 | 325 | self._edit_action = Action(wx.ID_ANY, |
320 | 326 | self._EDIT_ACTION_LABEL if not self._readonly else self._GET_INFO_ACTION_LABEL, |
321 | 327 | accel=wx.AcceleratorEntry(wx.ACCEL_NORMAL, wx.WXK_RETURN), |
@@ -438,6 +444,7 @@ def _create_menu_bar(self, raw_frame: wx.Frame) -> wx.MenuBar: |
438 | 444 | entity_menu.AppendSeparator() |
439 | 445 | self._new_root_url_action.append_menuitem_to(entity_menu) |
440 | 446 | self._new_group_action.append_menuitem_to(entity_menu) |
| 447 | + self._new_alias_action.append_menuitem_to(entity_menu) |
441 | 448 | self._edit_action.append_menuitem_to(entity_menu) |
442 | 449 | self._forget_action.append_menuitem_to(entity_menu) |
443 | 450 | entity_menu.AppendSeparator() |
@@ -1413,16 +1420,56 @@ def _on_edit_group_dialog_ok(self, |
1413 | 1420 |
|
1414 | 1421 | assert download_immediately == False |
1415 | 1422 |
|
1416 | | - def _saving_source_would_create_cycle(self, rg: ResourceGroup, source: ResourceGroupSource) -> bool: |
1417 | | - ancestor_source = source # type: ResourceGroupSource |
1418 | | - while ancestor_source is not None: |
1419 | | - if ancestor_source == rg: |
1420 | | - return True |
1421 | | - if isinstance(ancestor_source, ResourceGroup): |
1422 | | - ancestor_source = ancestor_source.source # reinterpret |
1423 | | - else: |
1424 | | - ancestor_source = None |
1425 | | - return False |
| 1423 | + # === Entity Pane: New/Edit Alias === |
| 1424 | + |
| 1425 | + def _on_new_alias(self, event: wx.CommandEvent) -> None: |
| 1426 | + restore_menuitems = self._disable_menus_during_showwindowmodal() |
| 1427 | + NewAliasDialog( |
| 1428 | + self._frame, |
| 1429 | + self._on_new_alias_dialog_ok, |
| 1430 | + alias_exists_func=self._alias_exists, |
| 1431 | + on_close=restore_menuitems, |
| 1432 | + ) |
| 1433 | + |
| 1434 | + def _alias_exists(self, source_url_prefix: str) -> bool: |
| 1435 | + return self.project.get_alias(source_url_prefix) is not None |
| 1436 | + |
| 1437 | + @fg_affinity |
| 1438 | + def _on_new_alias_dialog_ok(self, |
| 1439 | + source_url_prefix: str, |
| 1440 | + target_url_prefix: str, |
| 1441 | + target_is_external: bool, |
| 1442 | + ) -> None: |
| 1443 | + if source_url_prefix == '': |
| 1444 | + raise ValueError('Invalid blank source URL prefix') |
| 1445 | + if target_url_prefix == '': |
| 1446 | + raise ValueError('Invalid blank target URL prefix') |
| 1447 | + |
| 1448 | + try: |
| 1449 | + alias = Alias(self.project, source_url_prefix, target_url_prefix, |
| 1450 | + target_is_external=target_is_external) |
| 1451 | + except Alias.AlreadyExists: |
| 1452 | + raise ValueError('Invalid duplicate source URL prefix') |
| 1453 | + |
| 1454 | + @fg_affinity |
| 1455 | + def _on_edit_alias_dialog_ok(self, |
| 1456 | + alias: Alias, |
| 1457 | + source_url_prefix: str, |
| 1458 | + target_url_prefix: str, |
| 1459 | + target_is_external: bool, |
| 1460 | + ) -> None: |
| 1461 | + if source_url_prefix != alias.source_url_prefix: |
| 1462 | + raise ValueError( |
| 1463 | + 'Attempted to change source_url_prefix of existing Alias. ' |
| 1464 | + 'Source URL prefix cannot be changed after alias is created.' |
| 1465 | + ) |
| 1466 | + |
| 1467 | + if target_url_prefix == '': |
| 1468 | + raise ValueError('Invalid blank target URL prefix') |
| 1469 | + |
| 1470 | + # NOTE: Entity tree update will be triggered by property setters |
| 1471 | + alias.target_url_prefix = target_url_prefix |
| 1472 | + alias.target_is_external = target_is_external |
1426 | 1473 |
|
1427 | 1474 | # === Entity Pane: Other Commands === |
1428 | 1475 |
|
@@ -1487,9 +1534,38 @@ def _on_edit_entity(self, event) -> None: |
1487 | 1534 | raise |
1488 | 1535 | except CancelLoadUrls: |
1489 | 1536 | pass |
| 1537 | + elif isinstance(selected_entity, Alias): |
| 1538 | + alias = selected_entity |
| 1539 | + restore_menuitems = self._disable_menus_during_showwindowmodal() |
| 1540 | + try: |
| 1541 | + NewAliasDialog( |
| 1542 | + self._frame, |
| 1543 | + partial(self._on_edit_alias_dialog_ok, alias), |
| 1544 | + alias_exists_func=self._alias_exists, |
| 1545 | + initial_source_url_prefix=alias.source_url_prefix, |
| 1546 | + initial_target_url_prefix=alias.target_url_prefix, |
| 1547 | + initial_target_is_external=alias.target_is_external, |
| 1548 | + is_edit=True, |
| 1549 | + readonly=self._readonly, |
| 1550 | + on_close=restore_menuitems, |
| 1551 | + ) |
| 1552 | + except: |
| 1553 | + restore_menuitems() |
| 1554 | + raise |
1490 | 1555 | else: |
1491 | 1556 | raise AssertionError() |
1492 | 1557 |
|
| 1558 | + def _saving_source_would_create_cycle(self, rg: ResourceGroup, source: ResourceGroupSource) -> bool: |
| 1559 | + ancestor_source = source # type: ResourceGroupSource |
| 1560 | + while ancestor_source is not None: |
| 1561 | + if ancestor_source == rg: |
| 1562 | + return True |
| 1563 | + if isinstance(ancestor_source, ResourceGroup): |
| 1564 | + ancestor_source = ancestor_source.source # reinterpret |
| 1565 | + else: |
| 1566 | + ancestor_source = None |
| 1567 | + return False |
| 1568 | + |
1493 | 1569 | def _on_forget_entity(self, event) -> None: |
1494 | 1570 | selected_entity = self.entity_tree.selected_entity |
1495 | 1571 | assert selected_entity is not None |
|
0 commit comments