* Add OrcaCloud sync platform and preset bundle sharing system

  Introduce OrcaCloud, a cloud sync platform for user presets, alongside
  a preset bundle system that enables sharing printer/filament/process
  profiles as local exportable bundles or subscribed cloud bundles.

  OrcaCloud platform:
  - Auth to Orca Cloud
  - Encrypted token storage (file-based or system keychain)
  - User preset sync with
  - Profile migration from default/bambu folders on first login
  - Homepage integration with entrance to cloud.orcaslicer.com

  Preset bundles:
  - Local bundle import/export with bundle_structure.json metadata
  - Subscribed cloud bundles with version-based update checking
  - Thread-safe concurrent bundle access with read-write mutex
  - Canonical bundle preset naming (_local/<id>/... and _subscribed/<id>/...)
  - Bundle presets are read-only; grouped under subheaders in combo boxes
  - PresetBundleDialog with auto-sync toggle, refresh, update notifications
  - Hyperlinked bundle names to cloud bundle pages

  Co-authored-by: Sabriel Koh <sabrielkcr@gmail.com>
  Co-authored-by: Derrick <derrick992110@gmail.com>
  Co-authored-by: Mykola Nahirnyi <mnahirnyi@amcbridge.com>
  Co-authored-by: Ian Chua <iancrb00@gmail.com>
  Co-authored-by: Draginraptor <draginraptor@gmail.com>
  Co-authored-by: ExPikaPaka <112851715+ExPikaPaka@users.noreply.github.com>
  Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
  Co-authored-by: Ocraftyone <Ocraftyone@users.noreply.github.com>
  Co-authored-by: yw4z <ywsyildiz@gmail.com>
  Co-authored-by: peterm-m <101202951+peterm-m@users.noreply.github.com>

* Fixed an issue on Windows it failed to login Orca Cloud with Google account
This commit is contained in:
SoftFever
2026-05-01 18:01:29 +08:00
committed by GitHub
parent e54e7a61c0
commit c04be9ab37
113 changed files with 8691 additions and 3467 deletions

View File

@@ -210,9 +210,19 @@ int ComboBox::Append(const wxString &text,
}
int ComboBox::Append(const wxString &text, const wxBitmap &bitmap, const wxString &group, void *clientData, int style)
{
return Append(text, bitmap, group, group, clientData, style);
}
int ComboBox::Append(const wxString &text,
const wxBitmap &bitmap,
const wxString &group_key,
const wxString &group_label,
void *clientData,
int style)
{
auto valid_bit_map = (&bitmap && bitmap.IsOk()) ? bitmap : wxNullBitmap;
Item item{text, wxEmptyString, valid_bit_map, valid_bit_map, clientData, group};
Item item{text, wxEmptyString, valid_bit_map, valid_bit_map, clientData, group_key, group_label};
item.style = style;
items.push_back(item);
SetClientDataType(wxClientData_Void);
@@ -290,6 +300,18 @@ void ComboBox::SetItemTooltip(unsigned int n, wxString const &value) {
if (n == drop.GetSelection()) drop.SetToolTip(value);
}
wxString ComboBox::GetItemAlias(unsigned int n) const
{
if (n >= items.size()) return wxString();
return items[n].alias;
}
void ComboBox::SetItemAlias(unsigned int n, wxString const &value)
{
if (n >= items.size()) return;
items[n].alias = value;
}
wxBitmap ComboBox::GetItemBitmap(unsigned int n) { return items[n].icon; }
void ComboBox::SetItemBitmap(unsigned int n, wxBitmap const &bitmap)

View File

@@ -37,6 +37,12 @@ public:
int Append(const wxString &item, const wxBitmap &bitmap = wxNullBitmap, int item_style = 0);
int Append(const wxString &item, const wxBitmap &bitmap, void *clientData, int item_style = 0);
int Append(const wxString &item, const wxBitmap &bitmap, const wxString &group, void *clientData = nullptr, int item_style = 0);
int Append(const wxString& item,
const wxBitmap& bitmap,
const wxString& group_key,
const wxString& group_label,
void* clientData = nullptr,
int item_style = 0);
int SetItems(const std::vector<DropDown::Item>& the_items);

View File

@@ -340,14 +340,14 @@ void DropDown::render(wxDC &dc)
states2 &= ~StateColor::Enabled;
// Skip by group
if (group.IsEmpty()) {
if (!item.group.IsEmpty()) {
if (groups.find(item.group) != groups.end())
if (!item.group_key.IsEmpty()) {
if (groups.find(item.group_key) != groups.end())
continue;
groups.insert(item.group);
if (!item.group.IsEmpty()) {
groups.insert(item.group_key);
if (!item.group_key.IsEmpty()) {
bool disabled = true;
for (int j = i + 1; j < items.size(); ++j) {
if (items[i].group != item.group && (items[j].style & DD_ITEM_STYLE_DISABLED) == 0) {
if (items[j].group_key == item.group_key && (items[j].style & DD_ITEM_STYLE_DISABLED) == 0) {
disabled = false;
break;
}
@@ -357,7 +357,7 @@ void DropDown::render(wxDC &dc)
}
}
} else {
if (item.group != group)
if (item.group_key != group)
continue;
}
bool is_hover = index == hover_item;
@@ -391,8 +391,8 @@ void DropDown::render(wxDC &dc)
pt.y = rcContent.y;
}
auto text = group.IsEmpty()
? (item.group.IsEmpty() ? item.text : item.group)
: (item.text.StartsWith(group) && !group.EndsWith(' ') ? item.text.substr(group.size()).Trim(false) : item.text);
? (item.group_key.IsEmpty() ? item.text : item.group_label)
: item.text;
if (!text_off && !text.IsEmpty()) {
wxSize tSize = dc.GetMultiLineTextExtent(text);
if (pt.x + tSize.x > rcContent.GetRight()) {
@@ -405,7 +405,7 @@ void DropDown::render(wxDC &dc)
dc.SetFont(GetFont());
dc.SetTextForeground(text_color.colorForStates(states2));
dc.DrawText(text, pt);
if (group.IsEmpty() && !item.group.IsEmpty()) {
if (group.IsEmpty() && !item.group_key.IsEmpty()) {
auto szBmp = arrow_bitmap.GetBmpSize();
pt.x = rcContent.GetRight() - szBmp.x - 5;
pt.y = rcContent.y + (rcContent.height - szBmp.y) / 2;
@@ -430,18 +430,18 @@ int DropDown::hoverIndex()
auto &item = items[i];
// Skip by group
if (group.IsEmpty()) {
if (!item.group.IsEmpty()) {
if (groups.find(item.group) == groups.end())
groups.insert(item.group);
if (!item.group_key.IsEmpty()) {
if (groups.find(item.group_key) == groups.end())
groups.insert(item.group_key);
else
continue;
}
} else {
if (item.group != group)
if (item.group_key != group)
continue;
}
if (++index == hover_item)
return (item.group.IsEmpty() || !group.IsEmpty()) ? i : -i - 2;
return (item.group_key.IsEmpty() || !group.IsEmpty()) ? i : -i - 2;
}
return -1;
}
@@ -455,7 +455,7 @@ int DropDown::selectedItem()
if (count == items.size() && subDropDown == nullptr)
return selection;
auto & sel = items[selection];
if (group.IsEmpty() ? !sel.group.IsEmpty() : sel.group != group)
if (group.IsEmpty() ? !sel.group_key.IsEmpty() : sel.group_key != group)
return -1;
if (selection == 0)
return 0;
@@ -465,14 +465,14 @@ int DropDown::selectedItem()
auto &item = items[i];
// Skip by group
if (group.IsEmpty()) {
if (!item.group.IsEmpty()) {
if (groups.find(item.group) == groups.end())
groups.insert(item.group);
if (!item.group_key.IsEmpty()) {
if (groups.find(item.group_key) == groups.end())
groups.insert(item.group_key);
else
continue;
}
} else {
if (item.group != group)
if (item.group_key != group)
continue;
}
++index;
@@ -493,24 +493,24 @@ void DropDown::messureSize()
auto &item = items[i];
// Skip by group
if (group.IsEmpty()) {
if (!item.group.IsEmpty()) {
if (groups.find(item.group) == groups.end())
groups.insert(item.group);
if (!item.group_key.IsEmpty()) {
if (groups.find(item.group_key) == groups.end())
groups.insert(item.group_key);
else
continue;
}
} else {
if (item.group != group)
if (item.group_key != group)
continue;
}
++count;
wxSize size1;
if (!text_off) {
auto text = group.IsEmpty()
? (item.group.IsEmpty() ? item.text : item.group)
: (item.text.StartsWith(group) && !group.EndsWith(' ') ? item.text.substr(group.size()).Trim(false) : item.text);
? (item.group_key.IsEmpty() ? item.text : item.group_label)
: item.text;
size1 = dc.GetMultiLineTextExtent(text);
if (group.IsEmpty() && !item.group.IsEmpty())
if (group.IsEmpty() && !item.group_key.IsEmpty())
size1.x += 5 + arrow_bitmap.GetBmpWidth();
}
if (item.icon.IsOk()) {
@@ -696,7 +696,7 @@ void DropDown::mouseMove(wxMouseEvent &event)
int index = hoverIndex();
if (index < -1) {
auto & drop = *subDropDown;
drop.group = items[-index - 2].group;
drop.group = items[-index - 2].group_key;
drop.need_sync = true;
drop.messureSize();
drop.autoPosition();

View File

@@ -26,7 +26,8 @@ public:
wxBitmap icon;
wxBitmap icon_textctrl;// display icon for TextInput.eg.PrinterInfoBox
void * data{nullptr};
wxString group{};
wxString group_key{};
wxString group_label{};
wxString alias{};
wxString tip{};
int flag{0};