From 791c5103ea0c9bdde8b9d89eb46cbf03885f5d7d Mon Sep 17 00:00:00 2001 From: Zachary Hall Date: Mon, 23 Dec 2024 14:06:11 -0800 Subject: [PATCH] Finish cat support --- backends/ui/haiku/image_view.cpp | 6 ++-- backends/ui/haiku/prefs.cpp | 12 ++++++-- backends/ui/qt/main_window.cpp | 16 +++++++--- backends/ui/qt/main_window.h | 3 ++ backends/ui/qt/preferences.cpp | 52 ++++++++++++++++++++------------ backends/ui/qt/preferences.h | 1 + debian/changelog | 5 +++ main.cpp | 2 +- 8 files changed, 66 insertions(+), 31 deletions(-) diff --git a/backends/ui/haiku/image_view.cpp b/backends/ui/haiku/image_view.cpp index f008056..7c07518 100644 --- a/backends/ui/haiku/image_view.cpp +++ b/backends/ui/haiku/image_view.cpp @@ -28,8 +28,8 @@ void LImageView::FrameResized(float newW, float newH) { void LImageView::Draw(BRect updateRect) { AdoptSystemColors(); SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); - SetDrawingMode(B_OP_BLEND); - FillRect(img_bounds); + SetDrawingMode(B_OP_ALPHA); + FillRect(img_bounds, B_SOLID_LOW); if (bitmap == NULL) return; // Handle null image. int x = 0, y = 0; int mw, mh; @@ -80,7 +80,7 @@ void LImageView::Draw(BRect updateRect) { int bottom = updateRect.bottom; int x2 = x + bw; int y2 = y + bh; - FillRect(draw_rect); + FillRect(draw_rect, B_SOLID_LOW); DrawBitmap(bitmap, bitmap_rect, draw_rect); img_bounds = draw_rect; } diff --git a/backends/ui/haiku/prefs.cpp b/backends/ui/haiku/prefs.cpp index b099329..4cd59a6 100644 --- a/backends/ui/haiku/prefs.cpp +++ b/backends/ui/haiku/prefs.cpp @@ -92,8 +92,10 @@ HaikuPrefsWindow::HaikuPrefsWindow(BLooper *next_handler) : BWindow(BRect(100, 1 label_settings_layout->AddView(icons_only); label_settings_layout->AddView(both_labels_icons); BMessage *cat_enable_msg = new BMessage(CMD_SET_SETTING_CHECKBOX); - cat_enable_msg->AddString("pref_path", "ui.cat_enable"); + cat_enable_msg->AddString("pref_path", "ui.enable_cat"); cat_enable = new BCheckBox("Enable Cat", cat_enable_msg); + BGroupView *cat_enable_view = new BGroupView(B_HORIZONTAL); + cat_enable_view->AddChild(cat_enable); BBox *cat_box = new BBox("prefs:cat_options"); cat_box->SetLabel("Cat Options"); BGroupView *cat_group = new BGroupView(B_VERTICAL); @@ -130,7 +132,7 @@ HaikuPrefsWindow::HaikuPrefsWindow(BLooper *next_handler) : BWindow(BRect(100, 1 } root_layout->AddView(box, 3.0); cat_box->AddChild(cat_group); - root_layout->AddView(cat_enable, 1.0); + root_layout->AddView(cat_enable_view, 1.0); root_layout->AddView(cat_box, 3.0); BGroupView *btn_view = new BGroupView(B_HORIZONTAL); BGroupLayout *btn_box = btn_view->GroupLayout(); @@ -182,9 +184,11 @@ void HaikuPrefsWindow::MessageReceived(BMessage *msg) { BMessage *cat_msg = new BMessage(CMD_SET_CAT); if (enable_cat) cat_msg->AddPointer("cat", cats[cat_id]); next_handler->PostMessage(cat_msg); + save_options(); } break; case CMD_REVERT: { - set_options_changed(false); + set_options_changed(false); + load_options(); new_label_setting = get_option("ui.haiku.label_setting", "icons"); new_frontend = get_option("ui.frontend", "haiku"); if (new_frontend != "haiku") restart_warning->Show(); @@ -224,7 +228,9 @@ void HaikuPrefsWindow::MessageReceived(BMessage *msg) { new_label_setting = setting_value; set_options_changed(true); } else if (std::string(setting) == "ui.cat") { + if (cat_btns.contains(cat_id)) cat_btns[cat_id]->SetValue(B_CONTROL_OFF); cat_id = setting_value; + if (cat_btns.contains(cat_id)) cat_btns[cat_id]->SetValue(B_CONTROL_ON); set_options_changed(true); } } diff --git a/backends/ui/qt/main_window.cpp b/backends/ui/qt/main_window.cpp index 5c8e2e7..733e2e1 100644 --- a/backends/ui/qt/main_window.cpp +++ b/backends/ui/qt/main_window.cpp @@ -40,6 +40,9 @@ void LooperWindow::Pulse() { } } } +void LooperWindow::resizeEvent(QResizeEvent *event) { + if (cat_pixmap != NULL) update_cat(*cat_pixmap); +} LooperWindow::LooperWindow(Playback *playback) : QMainWindow() { labels_visible = false; icons_visible = true; @@ -80,10 +83,9 @@ LooperWindow::LooperWindow(Playback *playback) : QMainWindow() { help_menu->addAction(about_item); bar->addMenu(file_menu); bar->addMenu(help_menu); - QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding); - root_layout->addSpacerItem(spacer); cat_disp = new QLabel(); cat_disp->setAlignment(Qt::Alignment::enum_type::AlignRight); + cat_disp->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); root_layout->addWidget(cat_disp); QBoxLayout *top_row = new QBoxLayout(QBoxLayout::LeftToRight, this); pause_resume_btn = new QPushButton("Pause", this); @@ -115,6 +117,7 @@ LooperWindow::LooperWindow(Playback *playback) : QMainWindow() { }); top_row->addWidget(volume_slider); QWidget *top_row_widget = new QWidget(this); + top_row_widget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); top_row_widget->setLayout(top_row); root_layout->addWidget(top_row_widget); QBoxLayout *bottom_row = new QBoxLayout(QBoxLayout::LeftToRight, this); @@ -137,6 +140,7 @@ LooperWindow::LooperWindow(Playback *playback) : QMainWindow() { bottom_row->addWidget(pitch_slider); bottom_row->addWidget(tempo_slider); QWidget *bottom_row_widget = new QWidget(this); + bottom_row_widget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); bottom_row_widget->setLayout(bottom_row); root_layout->addWidget(bottom_row_widget); QTimer *timer = new QTimer(this); @@ -150,6 +154,7 @@ LooperWindow::LooperWindow(Playback *playback) : QMainWindow() { QObject::connect(prefs_window, &PrefsWindow::settings_changed, this, &LooperWindow::update_label_setting); QObject::connect(prefs_window, &PrefsWindow::cat_set, this, &LooperWindow::update_cat); QObject::connect(prefs_window, &PrefsWindow::cat_unset, this, &LooperWindow::clear_cat); + prefs_window->send_cat_signal(); //setLayout(layout); } void LooperWindow::update_label_setting(bool labels_visible, bool icons_visible) { @@ -179,9 +184,10 @@ void LooperWindow::update_label_setting(bool labels_visible, bool icons_visible) } void LooperWindow::clear_cat() { - cat_disp->hide(); + cat_pixmap = NULL; + cat_disp->clear(); } void LooperWindow::update_cat(QPixmap &img) { - cat_disp->setPixmap(img); - cat_disp->show(); + cat_pixmap = &img; + cat_disp->setPixmap(img.scaled(cat_disp->width(), cat_disp->height(), Qt::KeepAspectRatio)); } diff --git a/backends/ui/qt/main_window.h b/backends/ui/qt/main_window.h index 68c5fce..b85e90e 100644 --- a/backends/ui/qt/main_window.h +++ b/backends/ui/qt/main_window.h @@ -23,6 +23,7 @@ class LooperWindow : public QMainWindow { LooperSlider *speed_slider; LooperSlider *tempo_slider; LooperSlider *pitch_slider; + QPixmap *cat_pixmap = NULL; std::thread *update_thread = nullptr; bool done = false; void Pulse(); @@ -45,6 +46,8 @@ class LooperWindow : public QMainWindow { void update_label_setting(bool labels_visible, bool icons_visible); void update_cat(QPixmap &img); void clear_cat(); + protected: + void resizeEvent(QResizeEvent *event) override; public: AboutWindow *about_window; PrefsWindow *prefs_window; diff --git a/backends/ui/qt/preferences.cpp b/backends/ui/qt/preferences.cpp index daf8171..63aca78 100644 --- a/backends/ui/qt/preferences.cpp +++ b/backends/ui/qt/preferences.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -13,17 +15,14 @@ PrefsWindow::PrefsWindow() { for (auto &cat : get_cat_data()) { switch (cat.get_type()) { case CatDataType::Memory: { - QImage image; - QBuffer buffer; - QDataStream in(&buffer); auto mem_cat = cat.get_memory_cat(); - buffer.setData(const_cast((const char*)mem_cat.get_ptr()), mem_cat.get_len()); - in >> image; - cats[cat.get_name()] = QPixmap::fromImage(image); + QPixmap pixmap; + pixmap.loadFromData((const uchar*)mem_cat.get_ptr(), mem_cat.get_len()); + cats[cat.get_name()] = pixmap; } break; case CatDataType::File: { try { - cats[cat.get_name()] = QPixmap(cat.get_path().c_str()); + cats[cat.get_name()] = QPixmap(cat.get_path().c_str()); } catch (std::exception e) { WARNING.writefln("Failed to load cat %s at path %s: %s", cat.get_name().c_str(), cat.get_path().c_str(), e.what()); } @@ -51,8 +50,7 @@ PrefsWindow::PrefsWindow() { } frontend_btn->setMenu(frontend_menu); root_layout->addWidget(frontend_btn); - QFrame *frame = new QFrame(this); - frame->setWindowTitle("Labels and Icons"); + QGroupBox *frame = new QGroupBox("Labels and Icons", this); auto *label_settings_group = new QBoxLayout(QBoxLayout::TopToBottom, this); frame->setLayout(label_settings_group); labels_only = new QRadioButton("Labels Only", frame); @@ -75,27 +73,36 @@ PrefsWindow::PrefsWindow() { label_settings_group->addWidget(both_labels_icons); root_layout->addWidget(frame); cat_enable = new QCheckBox("Enable Cat", this); - QObject::connect(cat_enable, &QCheckBox::pressed, [=,this]() { + QObject::connect(cat_enable, &QCheckBox::toggled, [=,this]() { this->enable_cat = cat_enable->isChecked(); this->set_options_changed(true); }); root_layout->addWidget(cat_enable); - QFrame *catFrame = new QFrame(this); - catFrame->setWindowTitle("Cat Selection"); + QGroupBox *catFrame = new QGroupBox("Cat Selection", this); auto *cat_btns_layout = new QBoxLayout(QBoxLayout::TopToBottom, this); catFrame->setLayout(cat_btns_layout); + QButtonGroup *cat_btn_group = new QButtonGroup(catFrame); + cat_btn_group->setExclusive(true); for (auto &kv : cats) { auto id = kv.first; auto pixmap = kv.second; - QRadioButton *cat_radio = new QRadioButton(id.c_str(), catFrame); + QWidget *cat_view = new QWidget(this); + QBoxLayout *cat_box = new QBoxLayout(QBoxLayout::LeftToRight, this); + QRadioButton *cat_radio = new QRadioButton(id.c_str(), cat_view); + cat_btn_group->addButton(cat_radio); + cat_view->setLayout(cat_box); + cat_box->addWidget(cat_radio); QLabel *cat_img = new QLabel(cat_radio); - cat_img->setPixmap(pixmap); + cat_img->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); + float w = cat_img->width(), h = cat_img->height(); + cat_img->setPixmap(pixmap.scaled(w, h, Qt::KeepAspectRatio)); cat_img->setAlignment(Qt::Alignment::enum_type::AlignRight); + cat_box->addWidget(cat_img); QObject::connect(cat_radio, &QRadioButton::pressed, [=,this]() { this->cat_setting = id; this->set_options_changed(true); }); - cat_btns_layout->addWidget(cat_radio); + cat_btns_layout->addWidget(cat_view); cat_btns[id] = cat_radio; } root_layout->addWidget(catFrame); @@ -108,6 +115,7 @@ PrefsWindow::PrefsWindow() { btn_view->setLayout(btn_box); btn_box->addWidget(revert_btn); btn_box->addWidget(apply_btn); + btn_view->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); root_layout->addWidget(btn_view); revert(); setWindowTitle("Looper Preferences"); @@ -128,6 +136,7 @@ void PrefsWindow::update_label_setting() { } void PrefsWindow::revert() { set_options_changed(false); + load_options(); new_label_setting = get_option("ui.label_setting", "icons"); new_frontend = get_option("ui.frontend", "qt"); if (new_frontend != "qt") restart_warning->show(); @@ -145,11 +154,16 @@ void PrefsWindow::revert() { radio_btn_values[both_labels_icons] = true; } for (auto &kv : radio_btn_values) { - kv.first->setDown(kv.second); + kv.first->setChecked(kv.second); } - if (cat_btns.contains(cat_setting)) cat_btns[cat_setting]->setDown(true); + if (cat_btns.contains(cat_setting)) cat_btns[cat_setting]->setChecked(true); + send_cat_signal(); update_label_setting(); } +void PrefsWindow::send_cat_signal() { + if (enable_cat && cats.contains(cat_setting)) emit(cat_set(cats[cat_setting])); + else emit(cat_unset()); +} void PrefsWindow::apply() { set_options_changed(false); set_option("ui.label_setting", new_label_setting); @@ -160,6 +174,6 @@ void PrefsWindow::apply() { update_label_setting(); set_option("ui.enable_cat", enable_cat); set_option("ui.cat", cat_setting); - if (enable_cat && cats.contains(cat_setting)) emit(cat_set(cats[cat_setting])); - else emit(cat_unset()); + send_cat_signal(); + save_options(); } diff --git a/backends/ui/qt/preferences.h b/backends/ui/qt/preferences.h index cfb6491..e65784f 100644 --- a/backends/ui/qt/preferences.h +++ b/backends/ui/qt/preferences.h @@ -34,6 +34,7 @@ class PrefsWindow : public QWidget { void revert(); void apply(); public: + void send_cat_signal(); PrefsWindow(); Q_SIGNALS: void cat_set(QPixmap &img); diff --git a/debian/changelog b/debian/changelog index 1bb16ff..32f771e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,8 @@ +looper (1.dev4) UNRELEASED; urgency=medium + + * Add cat support + + -- Zachary Hall Mon, 23 Dec 2024 13:15:00 -0800 looper (1.dev3) UNRELEASED; urgency=medium * Set window class in ImGui UI and also only use one StartupWMClass in the diff --git a/main.cpp b/main.cpp index 1ee8985..fa236ea 100644 --- a/main.cpp +++ b/main.cpp @@ -184,7 +184,7 @@ extern "C" int looper_run_as_executable(std::vector args) { auto &cat_data = get_cat_data(); cat_data.push_back(CatData(catoc_data, catoc_size, "Cat OC (Built-In)", "catoc.png")); #ifndef __EMSCRIPTEN__ - fs::path baseDir = get_prefs_path() / fs::path("looper") / fs::path("themes"); + fs::path baseDir = get_prefs_path() / fs::path("looper") / fs::path("cats"); if (!fs::exists(baseDir)) { fs::create_directories(baseDir); }