- added svg icon handling
- began ui update to manage apps from ui - force utf8 only mode - new about dialog
This commit is contained in:
parent
90607d2f5d
commit
563080643f
|
@ -89,4 +89,4 @@ An example on how to add custom apps to the config can be found [here](./setting
|
||||||
This repository is open for contributions. You can view the current roadmap [here](https://github.com/EinTim23/PlayerLink/projects) or implement your own features and then open a pull request. Please keep your code as consistent and clean as possible.
|
This repository is open for contributions. You can view the current roadmap [here](https://github.com/EinTim23/PlayerLink/projects) or implement your own features and then open a pull request. Please keep your code as consistent and clean as possible.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
This project was heavily inspired by [Alexandra Aurora's MusicRPC](https://github.com/AlexandraAurora/MusicRPC) and her project may provide a better experience when being on Mac OS only.
|
This project was heavily inspired by [Alexandra Göttlicher's MusicRPC](https://github.com/kaethchen/MusicRPC) and her project may provide a better experience when being on Mac OS only.
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-6">
|
||||||
|
<path d="M21.731 2.269a2.625 2.625 0 0 0-3.712 0l-1.157 1.157 3.712 3.712 1.157-1.157a2.625 2.625 0 0 0 0-3.712ZM19.513 8.199l-3.712-3.712-12.15 12.15a5.25 5.25 0 0 0-1.32 2.214l-.8 2.685a.75.75 0 0 0 .933.933l2.685-.8a5.25 5.25 0 0 0 2.214-1.32L19.513 8.2Z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 367 B |
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-6">
|
||||||
|
<path fill-rule="evenodd" d="M14 3a2 2 0 1 0-4 0v7H3a2 2 0 1 0 0 4h7v7a2 2 0 1 0 4 0v-7h7a2 2 0 1 0 0-4h-7V3z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 239 B |
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-6">
|
||||||
|
<path fill-rule="evenodd" d="M16.5 4.478v.227a48.816 48.816 0 0 1 3.878.512.75.75 0 1 1-.256 1.478l-.209-.035-1.005 13.07a3 3 0 0 1-2.991 2.77H8.084a3 3 0 0 1-2.991-2.77L4.087 6.66l-.209.035a.75.75 0 0 1-.256-1.478A48.567 48.567 0 0 1 7.5 4.705v-.227c0-1.564 1.213-2.9 2.816-2.951a52.662 52.662 0 0 1 3.369 0c1.603.051 2.815 1.387 2.815 2.951Zm-6.136-1.452a51.196 51.196 0 0 1 3.273 0C14.39 3.05 15 3.684 15 4.478v.113a49.488 49.488 0 0 0-6 0v-.113c0-.794.609-1.428 1.364-1.452Zm-.355 5.945a.75.75 0 1 0-1.5.058l.347 9a.75.75 0 1 0 1.499-.058l-.346-9Zm5.48.058a.75.75 0 1 0-1.498-.058l-.347 9a.75.75 0 0 0 1.5.058l.345-9Z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 751 B |
135
src/main.cpp
135
src/main.cpp
|
@ -3,6 +3,7 @@
|
||||||
#include <wx/mstream.h>
|
#include <wx/mstream.h>
|
||||||
#include <wx/statline.h>
|
#include <wx/statline.h>
|
||||||
#include <wx/taskbar.h>
|
#include <wx/taskbar.h>
|
||||||
|
#include <wx/hyperlink.h>
|
||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
@ -151,9 +152,43 @@ void handleMediaTasks() {
|
||||||
Discord_UpdatePresence(&activity);
|
Discord_UpdatePresence(&activity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AboutDialog : public wxDialog {
|
||||||
|
public:
|
||||||
|
AboutDialog(wxWindow* parent)
|
||||||
|
: wxDialog(parent, wxID_ANY, _("About PlayerLink"), wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxDEFAULT_DIALOG_STYLE & ~wxRESIZE_BORDER) {
|
||||||
|
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
wxStaticText* label = new wxStaticText(this, wxID_ANY, _("Made with <3 by EinTim"));
|
||||||
|
label->Wrap(300);
|
||||||
|
mainSizer->Add(label, 0, wxALL | wxALIGN_CENTER, 10);
|
||||||
|
|
||||||
|
wxStaticText* copyrightText = new wxStaticText(this, wxID_ANY, "© 2024-2025 EinTim. All rights reserved.");
|
||||||
|
copyrightText->Wrap(300);
|
||||||
|
mainSizer->Add(copyrightText, 0, wxALL | wxALIGN_CENTER, 10);
|
||||||
|
|
||||||
|
wxStaticText* creditsText =
|
||||||
|
new wxStaticText(this, wxID_ANY,
|
||||||
|
_("Credits:\n- Developer: EinTim\n- Inspiration: Alexandra Göttlicher\n- Icons from: "
|
||||||
|
"heroicons.com\n- Open source "
|
||||||
|
"projects used in this:\n wxWidgets, libcurl, libdbus, mbedtls, nlohmann-json."));
|
||||||
|
creditsText->Wrap(300);
|
||||||
|
mainSizer->Add(creditsText, 0, wxALL | wxALIGN_CENTER, 10);
|
||||||
|
|
||||||
|
wxHyperlinkCtrl* link = new wxHyperlinkCtrl(this, wxID_ANY, _("Visit my website"), _("https://eintim.dev"));
|
||||||
|
mainSizer->Add(link, 0, wxALL | wxALIGN_CENTER, 10);
|
||||||
|
|
||||||
|
wxButton* okButton = new wxButton(this, wxID_OK, _("OK"));
|
||||||
|
mainSizer->Add(okButton, 0, wxALL | wxALIGN_CENTER, 10);
|
||||||
|
|
||||||
|
this->SetSizerAndFit(mainSizer);
|
||||||
|
this->CentreOnScreen();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class PlayerLinkIcon : public wxTaskBarIcon {
|
class PlayerLinkIcon : public wxTaskBarIcon {
|
||||||
public:
|
public:
|
||||||
PlayerLinkIcon(wxFrame* s) : settingsFrame(s) {}
|
PlayerLinkIcon(wxFrame* s) : settingsFrame(s), aboutDlg(nullptr) {}
|
||||||
|
|
||||||
void OnMenuOpen(wxCommandEvent& evt) {
|
void OnMenuOpen(wxCommandEvent& evt) {
|
||||||
settingsFrame->Show(true);
|
settingsFrame->Show(true);
|
||||||
|
@ -165,13 +200,14 @@ public:
|
||||||
void OnMenuExit(wxCommandEvent& evt) { settingsFrame->Close(true); }
|
void OnMenuExit(wxCommandEvent& evt) { settingsFrame->Close(true); }
|
||||||
|
|
||||||
void OnMenuAbout(wxCommandEvent& evt) {
|
void OnMenuAbout(wxCommandEvent& evt) {
|
||||||
wxMessageBox(_("Made with <3 by EinTim"), _("PlayerLink"), wxOK | wxICON_INFORMATION);
|
aboutDlg.Show(true);
|
||||||
|
aboutDlg.Raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual wxMenu* CreatePopupMenu() override {
|
virtual wxMenu* CreatePopupMenu() override {
|
||||||
wxMenu* menu = new wxMenu;
|
wxMenu* menu = new wxMenu;
|
||||||
menu->Append(10004, currentSongTitle == "" ? _("Not Playing") : wxString::FromUTF8(currentSongTitle));
|
menu->Append(10004, currentSongTitle == "" ? _("Not Playing") : currentSongTitle);
|
||||||
menu->Enable(10004, false);
|
menu->Enable(10004, false);
|
||||||
menu->AppendSeparator();
|
menu->AppendSeparator();
|
||||||
menu->Append(10005, _("Copy Odesli URL"));
|
menu->Append(10005, _("Copy Odesli URL"));
|
||||||
|
@ -190,6 +226,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxFrame* settingsFrame;
|
wxFrame* settingsFrame;
|
||||||
|
AboutDialog aboutDlg;
|
||||||
};
|
};
|
||||||
|
|
||||||
class wxTextCtrlWithPlaceholder : public wxTextCtrl {
|
class wxTextCtrlWithPlaceholder : public wxTextCtrl {
|
||||||
|
@ -258,31 +295,49 @@ public:
|
||||||
this->SetIcon(icon);
|
this->SetIcon(icon);
|
||||||
|
|
||||||
auto mainContainer = new wxBoxSizer(wxVERTICAL);
|
auto mainContainer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
wxPanel* panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||||
|
panel->SetSizer(mainContainer);
|
||||||
// header start
|
// header start
|
||||||
auto settingsText = new wxStaticText(this, wxID_ANY, _("Settings"), wxDefaultPosition, wxDefaultSize, 0);
|
auto settingsText = new wxStaticText(panel, wxID_ANY, _("Settings"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
settingsText->Wrap(-1);
|
settingsText->Wrap(-1);
|
||||||
mainContainer->Add(settingsText, 0, wxALIGN_CENTER | wxALL, 5);
|
mainContainer->Add(settingsText, 0, wxALIGN_CENTER | wxALL, 5);
|
||||||
// header end
|
// header end
|
||||||
|
|
||||||
// enabled apps start
|
// enabled apps start
|
||||||
auto settingsDivider = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
|
auto settingsDivider = new wxStaticLine(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
|
||||||
mainContainer->Add(settingsDivider, 0, wxEXPAND | wxALL, 5);
|
mainContainer->Add(settingsDivider, 0, wxEXPAND | wxALL, 5);
|
||||||
|
|
||||||
wxBoxSizer* enabledAppsContainer;
|
wxBoxSizer* enabledAppsContainer;
|
||||||
enabledAppsContainer = new wxBoxSizer(wxHORIZONTAL);
|
enabledAppsContainer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
|
||||||
auto enabledAppsText =
|
auto enabledAppsText =
|
||||||
new wxStaticText(this, wxID_ANY, _("Enabled Apps:"), wxDefaultPosition, wxDefaultSize, 0);
|
new wxStaticText(panel, wxID_ANY, _("Enabled Apps:"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
enabledAppsText->Wrap(-1);
|
enabledAppsText->Wrap(-1);
|
||||||
enabledAppsContainer->Add(enabledAppsText, 0, wxALL, 5);
|
enabledAppsContainer->Add(enabledAppsText, 0, wxALL, 5);
|
||||||
|
|
||||||
wxBoxSizer* appCheckboxContainer;
|
const auto edit_button_texture = utils::loadSettingsIcon(pencil_svg, pencil_svg_size);
|
||||||
appCheckboxContainer = new wxBoxSizer(wxVERTICAL);
|
const auto delete_button_texture = utils::loadSettingsIcon(trash_svg, trash_svg_size);
|
||||||
|
const auto add_button_texture = utils::loadSettingsIcon(plus_svg, plus_svg_size);
|
||||||
|
|
||||||
|
wxBoxSizer* appCheckboxContainer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
|
||||||
|
wxBoxSizer* rowSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
|
||||||
|
wxBitmapButton* addButton = new wxBitmapButton(panel, wxID_ANY, add_button_texture);
|
||||||
|
addButton->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) {
|
||||||
|
|
||||||
|
});
|
||||||
|
rowSizer->Add(addButton, 0, wxALL | wxALIGN_CENTER_VERTICAL);
|
||||||
|
|
||||||
|
wxBoxSizer* vSizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
vSizer->Add(rowSizer, 0, wxALL, 5);
|
||||||
|
enabledAppsContainer->Add(vSizer, 0, wxEXPAND);
|
||||||
auto settings = utils::getSettings();
|
auto settings = utils::getSettings();
|
||||||
|
|
||||||
for (auto app : settings.apps) {
|
for (auto app : settings.apps) {
|
||||||
auto checkbox = new wxCheckBox(this, wxID_ANY, app.appName, wxDefaultPosition, wxDefaultSize, 0);
|
wxBoxSizer* checkboxRowSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
|
||||||
|
auto checkbox = new wxCheckBox(panel, wxID_ANY, app.appName, wxDefaultPosition, wxDefaultSize, 0);
|
||||||
checkbox->SetValue(app.enabled);
|
checkbox->SetValue(app.enabled);
|
||||||
checkbox->SetClientData(new utils::App(app));
|
checkbox->SetClientData(new utils::App(app));
|
||||||
checkbox->Bind(wxEVT_CHECKBOX, [checkbox](wxCommandEvent& event) {
|
checkbox->Bind(wxEVT_CHECKBOX, [checkbox](wxCommandEvent& event) {
|
||||||
|
@ -294,10 +349,35 @@ public:
|
||||||
checkbox->Bind(wxEVT_DESTROY, [checkbox](wxWindowDestroyEvent&) {
|
checkbox->Bind(wxEVT_DESTROY, [checkbox](wxWindowDestroyEvent&) {
|
||||||
delete static_cast<utils::App*>(checkbox->GetClientData());
|
delete static_cast<utils::App*>(checkbox->GetClientData());
|
||||||
});
|
});
|
||||||
appCheckboxContainer->Add(checkbox, 0, wxALL, 5);
|
|
||||||
|
wxBitmapButton* editButton = new wxBitmapButton(panel, wxID_ANY, edit_button_texture);
|
||||||
|
editButton->Bind(wxEVT_BUTTON, [checkbox](wxCommandEvent& event) {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
wxBitmapButton* deleteButton = new wxBitmapButton(panel, wxID_ANY, delete_button_texture);
|
||||||
|
deleteButton->Bind(wxEVT_BUTTON, [this, checkbox, editButton, deleteButton, checkboxRowSizer,
|
||||||
|
appCheckboxContainer](wxCommandEvent& event) {
|
||||||
|
utils::App* appData = static_cast<utils::App*>(checkbox->GetClientData());
|
||||||
|
auto settings = utils::getSettings();
|
||||||
|
settings.apps.erase(std::find(settings.apps.begin(), settings.apps.end(), *appData));
|
||||||
|
utils::saveSettings(settings);
|
||||||
|
appCheckboxContainer->Detach(checkboxRowSizer);
|
||||||
|
|
||||||
|
this->CallAfter([this, checkboxRowSizer]() {
|
||||||
|
checkboxRowSizer->Clear(true);
|
||||||
|
this->Layout();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
checkboxRowSizer->Add(checkbox, 1, wxALL | wxALIGN_CENTER_VERTICAL);
|
||||||
|
checkboxRowSizer->Add(editButton, 0, wxALL | wxALIGN_CENTER_VERTICAL);
|
||||||
|
checkboxRowSizer->Add(deleteButton, 0, wxALL | wxALIGN_CENTER_VERTICAL);
|
||||||
|
|
||||||
|
appCheckboxContainer->Add(checkboxRowSizer, 0, wxALL, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto anyOtherCheckbox = new wxCheckBox(this, wxID_ANY, _("Any other"), wxDefaultPosition, wxDefaultSize, 0);
|
auto anyOtherCheckbox = new wxCheckBox(panel, wxID_ANY, _("Any other"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
anyOtherCheckbox->SetValue(settings.anyOtherEnabled);
|
anyOtherCheckbox->SetValue(settings.anyOtherEnabled);
|
||||||
anyOtherCheckbox->Bind(wxEVT_CHECKBOX, [](wxCommandEvent& event) {
|
anyOtherCheckbox->Bind(wxEVT_CHECKBOX, [](wxCommandEvent& event) {
|
||||||
bool isChecked = event.IsChecked();
|
bool isChecked = event.IsChecked();
|
||||||
|
@ -308,26 +388,26 @@ public:
|
||||||
|
|
||||||
appCheckboxContainer->Add(anyOtherCheckbox, 0, wxALL, 5);
|
appCheckboxContainer->Add(anyOtherCheckbox, 0, wxALL, 5);
|
||||||
|
|
||||||
enabledAppsContainer->Add(appCheckboxContainer, 1, wxEXPAND, 5);
|
vSizer->Add(appCheckboxContainer, 1, wxEXPAND, 5);
|
||||||
|
|
||||||
mainContainer->Add(enabledAppsContainer, 0, 0, 5);
|
mainContainer->Add(enabledAppsContainer, 0, 0, 5);
|
||||||
// enabled apps end
|
// enabled apps end
|
||||||
|
|
||||||
// LastFM start
|
// LastFM start
|
||||||
auto lastfmDivider = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
|
auto lastfmDivider = new wxStaticLine(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
|
||||||
mainContainer->Add(lastfmDivider, 0, wxEXPAND | wxALL, 5);
|
mainContainer->Add(lastfmDivider, 0, wxEXPAND | wxALL, 5);
|
||||||
|
|
||||||
wxBoxSizer* lastFMContainer;
|
wxBoxSizer* lastFMContainer;
|
||||||
lastFMContainer = new wxBoxSizer(wxHORIZONTAL);
|
lastFMContainer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
|
||||||
auto lastfmText = new wxStaticText(this, wxID_ANY, _("LastFM:"), wxDefaultPosition, wxDefaultSize, 0);
|
auto lastfmText = new wxStaticText(panel, wxID_ANY, _("LastFM:"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
lastfmText->Wrap(-1);
|
lastfmText->Wrap(-1);
|
||||||
lastFMContainer->Add(lastfmText, 0, wxALL, 5);
|
lastFMContainer->Add(lastfmText, 0, wxALL, 5);
|
||||||
|
|
||||||
wxBoxSizer* lastfmSettingsContainer;
|
wxBoxSizer* lastfmSettingsContainer;
|
||||||
lastfmSettingsContainer = new wxBoxSizer(wxVERTICAL);
|
lastfmSettingsContainer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
|
||||||
auto lastfmEnabledCheckbox = new wxCheckBox(this, wxID_ANY, _("Enabled"), wxDefaultPosition, wxDefaultSize, 0);
|
auto lastfmEnabledCheckbox = new wxCheckBox(panel, wxID_ANY, _("Enabled"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
lastfmEnabledCheckbox->SetValue(settings.lastfm.enabled);
|
lastfmEnabledCheckbox->SetValue(settings.lastfm.enabled);
|
||||||
lastfmEnabledCheckbox->Bind(wxEVT_CHECKBOX, [](wxCommandEvent& event) {
|
lastfmEnabledCheckbox->Bind(wxEVT_CHECKBOX, [](wxCommandEvent& event) {
|
||||||
bool isChecked = event.IsChecked();
|
bool isChecked = event.IsChecked();
|
||||||
|
@ -339,7 +419,7 @@ public:
|
||||||
lastFMContainer->Add(lastfmSettingsContainer, 1, wxEXPAND, 5);
|
lastFMContainer->Add(lastfmSettingsContainer, 1, wxEXPAND, 5);
|
||||||
|
|
||||||
auto usernameInput =
|
auto usernameInput =
|
||||||
new wxTextCtrlWithPlaceholder(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
|
new wxTextCtrlWithPlaceholder(panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
|
||||||
usernameInput->SetPlaceholderText(_("Username"));
|
usernameInput->SetPlaceholderText(_("Username"));
|
||||||
usernameInput->SetValue(settings.lastfm.username);
|
usernameInput->SetValue(settings.lastfm.username);
|
||||||
usernameInput->Bind(wxEVT_TEXT, [this](wxCommandEvent& event) {
|
usernameInput->Bind(wxEVT_TEXT, [this](wxCommandEvent& event) {
|
||||||
|
@ -348,7 +428,7 @@ public:
|
||||||
settings.lastfm.username = data;
|
settings.lastfm.username = data;
|
||||||
utils::saveSettings(settings);
|
utils::saveSettings(settings);
|
||||||
});
|
});
|
||||||
auto passwordInput = new wxTextCtrlWithPlaceholder(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
auto passwordInput = new wxTextCtrlWithPlaceholder(panel, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||||
wxDefaultSize, wxTE_PASSWORD);
|
wxDefaultSize, wxTE_PASSWORD);
|
||||||
passwordInput->SetPlaceholderText(_("Password"));
|
passwordInput->SetPlaceholderText(_("Password"));
|
||||||
passwordInput->SetValue(settings.lastfm.password);
|
passwordInput->SetValue(settings.lastfm.password);
|
||||||
|
@ -359,7 +439,7 @@ public:
|
||||||
utils::saveSettings(settings);
|
utils::saveSettings(settings);
|
||||||
});
|
});
|
||||||
auto apikeyInput =
|
auto apikeyInput =
|
||||||
new wxTextCtrlWithPlaceholder(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
|
new wxTextCtrlWithPlaceholder(panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
|
||||||
apikeyInput->SetPlaceholderText(_("API-Key"));
|
apikeyInput->SetPlaceholderText(_("API-Key"));
|
||||||
apikeyInput->SetValue(settings.lastfm.api_key);
|
apikeyInput->SetValue(settings.lastfm.api_key);
|
||||||
apikeyInput->Bind(wxEVT_TEXT, [this](wxCommandEvent& event) {
|
apikeyInput->Bind(wxEVT_TEXT, [this](wxCommandEvent& event) {
|
||||||
|
@ -368,7 +448,7 @@ public:
|
||||||
settings.lastfm.api_key = data;
|
settings.lastfm.api_key = data;
|
||||||
utils::saveSettings(settings);
|
utils::saveSettings(settings);
|
||||||
});
|
});
|
||||||
auto apisecretInput = new wxTextCtrlWithPlaceholder(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
auto apisecretInput = new wxTextCtrlWithPlaceholder(panel, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||||
wxDefaultSize, wxTE_PASSWORD);
|
wxDefaultSize, wxTE_PASSWORD);
|
||||||
apisecretInput->SetPlaceholderText(_("API-Secret"));
|
apisecretInput->SetPlaceholderText(_("API-Secret"));
|
||||||
apisecretInput->SetValue(settings.lastfm.api_secret);
|
apisecretInput->SetValue(settings.lastfm.api_secret);
|
||||||
|
@ -379,7 +459,7 @@ public:
|
||||||
utils::saveSettings(settings);
|
utils::saveSettings(settings);
|
||||||
});
|
});
|
||||||
|
|
||||||
auto checkButton = new wxButton(this, wxID_ANY, _("Check credentials"));
|
auto checkButton = new wxButton(panel, wxID_ANY, _("Check credentials"));
|
||||||
checkButton->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) { initLastFM(true); });
|
checkButton->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) { initLastFM(true); });
|
||||||
mainContainer->Add(lastFMContainer, 0, 0, 5);
|
mainContainer->Add(lastFMContainer, 0, 0, 5);
|
||||||
|
|
||||||
|
@ -392,7 +472,7 @@ public:
|
||||||
// Last FM End
|
// Last FM End
|
||||||
|
|
||||||
// settings start
|
// settings start
|
||||||
auto appsDivider = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
|
auto appsDivider = new wxStaticLine(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
|
||||||
mainContainer->Add(appsDivider, 0, wxEXPAND | wxALL, 5);
|
mainContainer->Add(appsDivider, 0, wxEXPAND | wxALL, 5);
|
||||||
|
|
||||||
wxBoxSizer* settingsContainer;
|
wxBoxSizer* settingsContainer;
|
||||||
|
@ -401,12 +481,12 @@ public:
|
||||||
wxBoxSizer* startupContainer;
|
wxBoxSizer* startupContainer;
|
||||||
startupContainer = new wxBoxSizer(wxHORIZONTAL);
|
startupContainer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
|
||||||
auto startupText = new wxStaticText(this, wxID_ANY, _("Startup:"), wxDefaultPosition, wxDefaultSize, 0);
|
auto startupText = new wxStaticText(panel, wxID_ANY, _("Startup:"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
startupText->Wrap(-1);
|
startupText->Wrap(-1);
|
||||||
startupContainer->Add(startupText, 0, wxALL, 5);
|
startupContainer->Add(startupText, 0, wxALL, 5);
|
||||||
|
|
||||||
auto autostartCheckbox =
|
auto autostartCheckbox =
|
||||||
new wxCheckBox(this, wxID_ANY, _("Launch at login"), wxDefaultPosition, wxDefaultSize, 0);
|
new wxCheckBox(panel, wxID_ANY, _("Launch at login"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
autostartCheckbox->SetValue(settings.autoStart);
|
autostartCheckbox->SetValue(settings.autoStart);
|
||||||
autostartCheckbox->Bind(wxEVT_CHECKBOX, [](wxCommandEvent& event) {
|
autostartCheckbox->Bind(wxEVT_CHECKBOX, [](wxCommandEvent& event) {
|
||||||
bool isChecked = event.IsChecked();
|
bool isChecked = event.IsChecked();
|
||||||
|
@ -417,7 +497,7 @@ public:
|
||||||
});
|
});
|
||||||
|
|
||||||
auto odesliCheckbox =
|
auto odesliCheckbox =
|
||||||
new wxCheckBox(this, wxID_ANY, _("Odesli integration"), wxDefaultPosition, wxDefaultSize, 0);
|
new wxCheckBox(panel, wxID_ANY, _("Odesli integration"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
odesliCheckbox->SetValue(settings.odesli);
|
odesliCheckbox->SetValue(settings.odesli);
|
||||||
odesliCheckbox->Bind(wxEVT_CHECKBOX, [](wxCommandEvent& event) {
|
odesliCheckbox->Bind(wxEVT_CHECKBOX, [](wxCommandEvent& event) {
|
||||||
bool isChecked = event.IsChecked();
|
bool isChecked = event.IsChecked();
|
||||||
|
@ -430,17 +510,20 @@ public:
|
||||||
settingsContainer->Add(odesliCheckbox, 0, wxALL, 5);
|
settingsContainer->Add(odesliCheckbox, 0, wxALL, 5);
|
||||||
startupContainer->Add(settingsContainer);
|
startupContainer->Add(settingsContainer);
|
||||||
mainContainer->Add(startupContainer, 0, wxEXPAND, 5);
|
mainContainer->Add(startupContainer, 0, wxEXPAND, 5);
|
||||||
|
|
||||||
// settings end
|
// settings end
|
||||||
this->SetSizerAndFit(mainContainer);
|
|
||||||
|
|
||||||
|
wxBoxSizer* frameSizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
frameSizer->Add(panel, 1, wxEXPAND);
|
||||||
|
this->SetSizerAndFit(frameSizer);
|
||||||
wxSize currentSize = this->GetSize();
|
wxSize currentSize = this->GetSize();
|
||||||
this->SetSize(size.GetWidth(), currentSize.GetHeight());
|
this->SetSize(size.GetWidth(), currentSize.GetHeight());
|
||||||
this->Layout();
|
this->Layout();
|
||||||
|
|
||||||
this->Centre(wxBOTH);
|
this->Centre(wxBOTH);
|
||||||
|
panel->SetFocus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlayerLink : public wxApp {
|
class PlayerLink : public wxApp {
|
||||||
public:
|
public:
|
||||||
virtual bool OnInit() override {
|
virtual bool OnInit() override {
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <wx/mstream.h>
|
#include <wx/mstream.h>
|
||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
#include <wx/clipbrd.h>
|
#include <wx/clipbrd.h>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <nlohmann-json/single_include/nlohmann/json.hpp>
|
#include <nlohmann-json/single_include/nlohmann/json.hpp>
|
||||||
|
@ -26,6 +25,9 @@ namespace utils {
|
||||||
std::string clientId;
|
std::string clientId;
|
||||||
std::string searchEndpoint;
|
std::string searchEndpoint;
|
||||||
std::vector<std::string> processNames;
|
std::vector<std::string> processNames;
|
||||||
|
bool operator==(const App& other) const {
|
||||||
|
return appName == other.appName && clientId == other.clientId && type == other.type;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LastFMSettings {
|
struct LastFMSettings {
|
||||||
|
@ -57,16 +59,46 @@ namespace utils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline wxIcon loadIconFromMemory(const unsigned char* data, size_t size) {
|
inline wxBitmap loadImageFromMemory(const unsigned char* data, size_t size, int width = 0, int height = 0) {
|
||||||
wxMemoryInputStream stream(data, size);
|
wxMemoryInputStream stream(data, size);
|
||||||
wxImage img(stream, wxBITMAP_TYPE_PNG);
|
wxImage img(stream, wxBITMAP_TYPE_PNG);
|
||||||
if (img.IsOk()) {
|
if (img.IsOk()) {
|
||||||
|
if (width != 0 || height != 0)
|
||||||
|
img.Rescale(width, height, wxIMAGE_QUALITY_HIGH);
|
||||||
wxBitmap bmp(img);
|
wxBitmap bmp(img);
|
||||||
wxIcon icon;
|
return bmp;
|
||||||
icon.CopyFromBitmap(bmp);
|
|
||||||
return icon;
|
|
||||||
}
|
}
|
||||||
return wxNullIcon;
|
return wxNullBitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline wxIcon loadIconFromMemory(const unsigned char* data, size_t size, int width = 0, int height = 0) {
|
||||||
|
wxIcon icn{};
|
||||||
|
icn.CopyFromBitmap(loadImageFromMemory(data, size, width, height));
|
||||||
|
return icn;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline wxBitmap loadColoredSVG(const unsigned char* svg, const unsigned int svg_size, const wxSize& size,
|
||||||
|
const wxColour& color) {
|
||||||
|
const std::string defaultColor = "currentColor";
|
||||||
|
std::string svg_data = std::string((const char*)svg, svg_size);
|
||||||
|
size_t start_pos = svg_data.find(defaultColor);
|
||||||
|
if (start_pos != std::string::npos)
|
||||||
|
svg_data.replace(start_pos, defaultColor.length(), color.GetAsString(wxC2S_HTML_SYNTAX));
|
||||||
|
|
||||||
|
wxBitmapBundle bundle = wxBitmapBundle::FromSVG(svg_data.c_str(), size);
|
||||||
|
if (!bundle.IsOk())
|
||||||
|
return wxNullBitmap;
|
||||||
|
wxBitmap bmp = bundle.GetBitmap(size);
|
||||||
|
if (!bmp.IsOk())
|
||||||
|
return wxNullBitmap;
|
||||||
|
return bmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline wxBitmap loadSettingsIcon(const unsigned char* svg, const unsigned int svg_size,
|
||||||
|
const wxSize& size = wxSize(16, 16)) {
|
||||||
|
return loadColoredSVG(
|
||||||
|
svg, svg_size, size,
|
||||||
|
wxSystemSettings::GetAppearance().IsSystemDark() ? wxColor(255, 255, 255, 255) : wxColor(0, 0, 0, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string toLower(const std::string& str) {
|
inline std::string toLower(const std::string& str) {
|
||||||
|
|
|
@ -19,6 +19,8 @@ set(wxBUILD_SHARED OFF)
|
||||||
set(wxBUILD_MONOLITHIC ON)
|
set(wxBUILD_MONOLITHIC ON)
|
||||||
set(wxUSE_GUI ON)
|
set(wxUSE_GUI ON)
|
||||||
set(wxUSE_WEBVIEW OFF)
|
set(wxUSE_WEBVIEW OFF)
|
||||||
|
set(wxUSE_UNICODE_UTF8 ON)
|
||||||
|
set(wxUSE_UTF8_LOCALE_ONLY ON)
|
||||||
add_subdirectory("wxWidgets")
|
add_subdirectory("wxWidgets")
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
add_subdirectory("dbus")
|
add_subdirectory("dbus")
|
||||||
|
|
Loading…
Reference in New Issue