diff --git a/__main__.py b/__main__.py
index cef8a9c..5eca83d 100644
--- a/__main__.py
+++ b/__main__.py
@@ -1,6 +1,22 @@
+from wx import App, Locale
+
+
+class StandAloneApp(App):
+ def __init__(
+ self, redirect=False, filename=None, useBestVisual=False, clearSigInt=True
+ ):
+ super().__init__(redirect, filename, useBestVisual, clearSigInt)
+
+ def OnInit(self):
+ from kicad_amf_plugin.settings.setting_manager import SETTING_MANAGER
+
+ self.locale = Locale(SETTING_MANAGER.get_language())
+ return True
+
+
if __name__ == "__main__":
from kicad_amf_plugin.plugin._main import _main
- from wx import App
- app = App()
+
+ app = StandAloneApp()
_main()
app.MainLoop()
diff --git a/docs/place_order_new.gif b/docs/place_order_new.gif
new file mode 100644
index 0000000..9a321aa
Binary files /dev/null and b/docs/place_order_new.gif differ
diff --git a/kicad_amf_plugin/gui/app_base.py b/kicad_amf_plugin/gui/app_base.py
index a048b6a..fa30dfa 100644
--- a/kicad_amf_plugin/gui/app_base.py
+++ b/kicad_amf_plugin/gui/app_base.py
@@ -1,13 +1,12 @@
-from kicad_amf_plugin.language.lang_const import get_supported_language
from kicad_amf_plugin.language.lang_const import LANG_DOMAIN
from kicad_amf_plugin.settings.supported_layer_count import AVAILABLE_LAYER_COUNTS
import builtins
import sys
import os
from kicad_amf_plugin import PLUGIN_ROOT
-from kicad_amf_plugin.gui.event.pcb_fabrication_evt_list import EVT_LOCALE_CHANGE
from kicad_amf_plugin.kicad.board_manager import load_board_manager
from kicad_amf_plugin.utils.combo_box_ignore_wheel import ComboBoxIgnoreWheel
+from kicad_amf_plugin.icon import GetImagePath
import wx
# add translation macro to builtin similar to what gettext does
@@ -23,17 +22,17 @@ def _displayHook(obj):
class BaseApp(wx.EvtHandler):
def __init__(self):
super().__init__()
- self.Bind(EVT_LOCALE_CHANGE, self.on_locale_changed)
- # work around for Python stealing "_"
sys.displayhook = _displayHook
- self.locale = None
wx.Locale.AddCatalogLookupPathPrefix(
os.path.join(PLUGIN_ROOT, "language", "locale")
)
+ existing_locale = wx.GetLocale()
+ if existing_locale is not None:
+ existing_locale.AddCatalog(LANG_DOMAIN)
def load_success(self):
from kicad_amf_plugin.settings.setting_manager import SETTING_MANAGER
- self.update_language(SETTING_MANAGER.language)
+
SETTING_MANAGER.register_app(self)
self.board_manager = load_board_manager()
if self.board_manager.board.GetCopperLayerCount() not in AVAILABLE_LAYER_COUNTS:
@@ -41,40 +40,6 @@ def load_success(self):
return False
return True
- def on_locale_changed(self, evt):
- self.update_language(evt.GetInt())
- info = wx.MessageDialog(
- self.main_wind,
- _(
- "Restart the plugin to apply the new locale ?\nFor full translation(including the options), restarting KiCad is required"
- ),
- _("Tip"),
- wx.YES | wx.ICON_QUESTION | wx.NO,
- )
- res = info.ShowModal()
- info.Destroy()
- if res == wx.ID_YES:
- if self.main_wind:
- self.main_wind.Destroy()
- self.startup_dialog()
-
- def update_language(self, lang: int):
- if lang in get_supported_language():
- selLang = lang
- else:
- wx.MessageBox(f"Unexpected language id {lang}")
- selLang = wx.LANGUAGE_ENGLISH
- if self.locale:
- assert sys.getrefcount(self.locale) <= 2
- del self.locale
-
- self.locale = wx.Locale(selLang)
- if self.locale.IsOk():
- self.locale.AddCatalog(LANG_DOMAIN)
- else:
- wx.MessageBox(self.locale.GetLocale() + _(" is not supported"))
- self.locale = None
-
def startup_dialog(self):
from kicad_amf_plugin.gui.main_frame import MainFrame
from kicad_amf_plugin.settings.setting_manager import SETTING_MANAGER
@@ -82,4 +47,5 @@ def startup_dialog(self):
self.main_wind = MainFrame(
self.board_manager, SETTING_MANAGER.get_window_size()
)
+ self.main_wind.SetIcon(wx.Icon(GetImagePath("Huaqiu.ico")))
self.main_wind.Show()
diff --git a/kicad_amf_plugin/gui/main_frame.py b/kicad_amf_plugin/gui/main_frame.py
index 4841cf6..7d38cde 100644
--- a/kicad_amf_plugin/gui/main_frame.py
+++ b/kicad_amf_plugin/gui/main_frame.py
@@ -1,5 +1,10 @@
from kicad_amf_plugin.gui.summary.price_summary_model import PriceCategory
from kicad_amf_plugin.kicad.board_manager import BoardManager
+from kicad_amf_plugin.kicad.fabrication_data_generator_evt import (
+ EVT_BUTTON_FABRICATION_DATA_GEN_RES,
+ FabricationDataGenEvent,
+ GenerateStatus,
+)
from kicad_amf_plugin.order.supported_region import SupportedRegion
from kicad_amf_plugin.pcb_fabrication.base.base_info_view import BaseInfoView
from kicad_amf_plugin.pcb_fabrication.process.process_info_view import ProcessInfoView
@@ -37,6 +42,7 @@
import webbrowser
import json
from kicad_amf_plugin.order.order_region import OrderRegion, URL_KIND
+from kicad_amf_plugin.kicad.fabrication_data_generator_thread import DataGenThread
from enum import Enum
@@ -79,16 +85,33 @@ def __init__(self, board_manager: BoardManager, size, parent=None):
)
self._board_manager = board_manager
self._fabrication_data_gen = None
+ self._fabrication_data_gen_thread = None
self._pcb_form_parts: "dict[PCBFormPart, FormPanelBase]" = {}
+ self._data_gen_progress: wx.ProgressDialog = None
+ self._dataGenThread: DataGenThread = None
SINGLE_PLUGIN.register_main_wind(self)
self.init_ui()
+ def show_data_gen_progress_dialog(self):
+ if self._data_gen_progress is not None:
+ self._data_gen_progress.Destroy()
+ self._data_gen_progress = None
+ self._data_gen_progress = wx.ProgressDialog(
+ _("Preparing for your order"),
+ _("The browser will be launched automatically while ready"),
+ maximum=GenerateStatus.MAX_PROGRESS,
+ parent=self,
+ style=0 | wx.PD_APP_MODAL,
+ )
+
def init_ui(self):
self.SetSizeHints(wx.DefaultSize, wx.DefaultSize)
- main_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ left_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.main_splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
+ self.left_panel_container = wx.Panel(self.main_splitter)
pcb_fab_scroll_wind = wx.ScrolledWindow(
- self,
+ self.left_panel_container,
wx.ID_ANY,
wx.DefaultPosition,
wx.Size(-1, -1),
@@ -104,9 +127,14 @@ def init_ui(self):
pcb_fab_scroll_wind.SetSizer(lay_pcb_fab_panel)
pcb_fab_scroll_wind.Layout()
- self.summary_view = SummaryPanel(self)
- main_sizer.Add(pcb_fab_scroll_wind, 1, wx.EXPAND, 8)
- main_sizer.Add(self.summary_view, 0, wx.EXPAND, 8)
+ self.summary_view = SummaryPanel(self.main_splitter)
+ left_sizer.Add(pcb_fab_scroll_wind, 1, wx.EXPAND, 8)
+ self.left_panel_container.SetSizer(left_sizer)
+ self.left_panel_container.Layout()
+ left_sizer.Fit(self.left_panel_container)
+ self.main_splitter.SplitVertically(
+ self.left_panel_container, self.summary_view, 400
+ )
self.Bind(
EVT_LAYER_COUNT_CHANGE,
@@ -121,15 +149,49 @@ def init_ui(self):
self.Bind(EVT_ORDER_REGION_CHANGED, self.on_order_region_changed)
self.Bind(wx.EVT_SIZE, self.OnSize, self)
self.Bind(wx.EVT_CLOSE, self.OnClose, self)
+ self.Bind(
+ wx.EVT_SPLITTER_SASH_POS_CHANGED,
+ self.on_sash_pos_changed,
+ self.main_splitter,
+ )
+
+ self.main_splitter.Bind(wx.EVT_IDLE, self.main_splitter_on_idle)
+
+ self.Bind(
+ EVT_BUTTON_FABRICATION_DATA_GEN_RES, self.on_fabrication_data_gen_progress
+ )
for i in self._pcb_form_parts.values():
i.init()
i.on_region_changed()
+ main_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ main_sizer.Add(self.main_splitter, 1, wx.EXPAND, 5)
self.SetSizer(main_sizer)
self.Layout()
self.Centre(wx.BOTH)
+ def on_fabrication_data_gen_progress(self, evt: FabricationDataGenEvent):
+ if self._data_gen_progress is not None:
+ res = evt.get_status()
+ if GenerateStatus.RUNNING == res.get_status():
+ self._data_gen_progress.Update(res.get_progress(), res.get_message())
+ else:
+ self._data_gen_progress.Destroy()
+ self._data_gen_progress = None
+ if GenerateStatus.FAILED == res.get_status():
+ wx.MessageBox(f"{res.get_message()}")
+
+ def on_sash_pos_changed(self, evt):
+ sash_pos = evt.GetSashPosition()
+ SETTING_MANAGER.set_mainwindow_sash_pos(sash_pos)
+
+ def main_splitter_on_idle(self, evt):
+ self.main_splitter.SetSashPosition(
+ SETTING_MANAGER.get_mainwindow_sash_position()
+ )
+ self.main_splitter.Unbind(wx.EVT_IDLE)
+
@property
def fabrication_data_generator(self):
if self._fabrication_data_gen is None:
@@ -242,35 +304,24 @@ def on_update_price(self, evt):
raise e # TODO remove me
def on_place_order(self, evt):
+ self.show_data_gen_progress_dialog()
if not self.form_is_valid():
return
- try:
- url = OrderRegion.get_url(
- SETTING_MANAGER.order_region, URL_KIND.PLACE_ORDER
- )
- if url is None:
- wx.MessageBox(_("No available url for placing order in current region"))
- return
- with self.fabrication_data_generator.create_kicad_pcb_file() as zipfile:
- rsp = requests.post(
- url,
- files={"file": open(zipfile, "rb")},
- data=self.get_place_order_form(),
- )
- urls = json.loads(rsp.content)
- for key in "url", "redirect":
- if key in urls:
- uat_url = str(urls[key])
- webbrowser.open(uat_url)
- return
- raise Exception("No available order url in the response")
- except Exception as e:
- wx.MessageBox(str(e))
- raise e # TODO remove me
+ url = OrderRegion.get_url(SETTING_MANAGER.order_region, URL_KIND.PLACE_ORDER)
+ if url is None:
+ wx.MessageBox(_("No available url for placing order in current region"))
+ return
+ if self._dataGenThread is not None:
+ self._dataGenThread.join()
+ self._dataGenThread = None
+ self._dataGenThread = DataGenThread(
+ self, self.fabrication_data_generator, self.get_place_order_form(), url
+ )
def adjust_size(self):
for i in self._pcb_form_parts.values():
i.Layout()
+ self.left_panel_container.Layout()
self.Layout()
def on_order_region_changed(self, ev):
diff --git a/kicad_amf_plugin/gui/summary/price_model_base.py b/kicad_amf_plugin/gui/summary/price_model_base.py
index 16dc56e..bd747e6 100644
--- a/kicad_amf_plugin/gui/summary/price_model_base.py
+++ b/kicad_amf_plugin/gui/summary/price_model_base.py
@@ -1,10 +1,9 @@
from dataclasses import dataclass
-from enum import Enum
import abc
import json
-class PriceModelCol(Enum):
+class PriceModelCol:
DESC = 0
VALUE = DESC + 1
COL_COUNT = VALUE + 1
diff --git a/kicad_amf_plugin/gui/summary/summary_panel.py b/kicad_amf_plugin/gui/summary/summary_panel.py
index a30eb87..7eac478 100644
--- a/kicad_amf_plugin/gui/summary/summary_panel.py
+++ b/kicad_amf_plugin/gui/summary/summary_panel.py
@@ -2,9 +2,8 @@
from kicad_amf_plugin.utils.roles import EditDisplayRole
from .ui_summary_panel import UiSummaryPanel
from kicad_amf_plugin.icon import GetImagePath
-from kicad_amf_plugin.language.lang_setting_pop_menu import LangSettingPopMenu
import wx
-from .order_summary_model import OrderSummary, OrderSummaryModel
+from .order_summary_model import OrderSummaryModel
from .price_summary_model import PriceSummaryModel
@@ -18,9 +17,9 @@
OrderRegionSettings = (
- EditDisplayRole(SupportedRegion.CHINA_MAINLAND, _("CN")),
- EditDisplayRole(SupportedRegion.JAPAN, _("JP")),
- EditDisplayRole(SupportedRegion.EUROPE_USA, _("EU/USA")),
+ EditDisplayRole(SupportedRegion.CHINA_MAINLAND, _("Mainland China")),
+ EditDisplayRole(SupportedRegion.EUROPE_USA, _("Worldwide (English)")),
+ EditDisplayRole(SupportedRegion.JAPAN, _("Worldwide (Japanese)")),
)
@@ -29,10 +28,14 @@ def __init__(self, *args, **kw):
super().__init__(*args, **kw)
self.init_ui()
- self.btn_set_language.Bind(wx.EVT_BUTTON, self.on_set_lang_clicked)
self.btn_update_price.Bind(wx.EVT_BUTTON, self.on_update_price_clicked)
self.btn_place_order.Bind(wx.EVT_BUTTON, self.on_place_order_clicked)
self.choice_order_region.Bind(wx.EVT_CHOICE, self.on_region_changed)
+ self.Bind(
+ wx.EVT_SPLITTER_SASH_POS_CHANGED,
+ self.on_sash_changed,
+ self.splitter_detail_summary,
+ )
def init_ui(self):
self.list_order_summary.AppendTextColumn(
@@ -95,6 +98,12 @@ def init_ui(self):
self.SetMinSize(wx.Size(max_width + 30, -1))
+ def splitter_detail_summaryOnIdle(self, event):
+ self.splitter_detail_summary.SetSashPosition(
+ SETTING_MANAGER.get_summary_detail_sash_pos()
+ )
+ self.splitter_detail_summary.Unbind(wx.EVT_IDLE)
+
def update_price_detail(self, price: "dict"):
self.model_price_summary.update_price(price)
@@ -113,6 +122,10 @@ def on_place_order_clicked(self, ev):
evt = PlaceOrder(id=-1)
wx.PostEvent(self.Parent, evt)
+ def on_sash_changed(self, evt):
+ sash_pos = evt.GetSashPosition()
+ SETTING_MANAGER.set_summary_detail_sash_pos(sash_pos)
+
def GetImagePath(self, bitmap_path):
return GetImagePath(bitmap_path)
@@ -123,11 +136,6 @@ def GetLineHeight(parent):
line.Destroy()
return height
- def on_set_lang_clicked(self, evt):
- menu = LangSettingPopMenu(SETTING_MANAGER.language)
- self.PopupMenu(menu)
- menu.Destroy()
-
def clear_content(self):
for i in self.model_order_summary, self.model_price_summary:
i.clear_content()
diff --git a/kicad_amf_plugin/gui/summary/ui_summary_panel.fbp b/kicad_amf_plugin/gui/summary/ui_summary_panel.fbp
index 95f2989..5bdf485 100644
--- a/kicad_amf_plugin/gui/summary/ui_summary_panel.fbp
+++ b/kicad_amf_plugin/gui/summary/ui_summary_panel.fbp
@@ -78,11 +78,11 @@
wxHORIZONTAL
1
none
-