diff --git a/qt/DeviceView.cpp b/qt/DeviceView.cpp index 9ccd6bcb..b774a010 100644 --- a/qt/DeviceView.cpp +++ b/qt/DeviceView.cpp @@ -402,7 +402,7 @@ void DeviceView::InitDeviceView() | Calculate LED box positions for segmented zones | \*-----------------------------------------------------*/ unsigned int leds_count = controller->zones[zone_idx].segments[segment_idx].leds_count; - + for(unsigned int led_idx = 0; led_idx < leds_count; led_idx++) { unsigned int led_pos_idx = controller->zones[zone_idx].start_idx + controller->zones[zone_idx].segments[segment_idx].start_idx + led_idx; @@ -760,7 +760,7 @@ void DeviceView::paintEvent(QPaintEvent* /* event */) { painter.setPen(palette().windowText().color()); } - painter.drawText(posx, posy + posh, QString(controller->zones[zone_idx].segments[segment_idx].name.c_str())); + painter.drawText(posx, posy + posh, QString(controller->zones[zone_idx].segments[segment_idx].name.c_str())); } } @@ -891,6 +891,47 @@ bool DeviceView::selectLeds(QVector target) return true; } +bool DeviceView::selectSegment(int zone, int segment, bool add) +{ + if(zone < 0 || size_t(zone) >= controller->zones.size()) + { + return false; + } + + if(segment < 0 || size_t(segment) >= controller->zones[zone].segments.size()) + { + return false; + } + + if(!add) + { + selectedLeds.clear(); + selectionFlags.clear(); + selectionFlags.resize(controller->leds.size()); + } + + int zoneStart = controller->zones[zone].start_idx; + int segStart = controller->zones[zone].segments[segment].start_idx; + + for(std::size_t led_idx = 0; led_idx < controller->zones[zone].segments[segment].leds_count; ++led_idx) + { + if(!selectionFlags[zoneStart + segStart + led_idx]) + { + selectedLeds.push_back(zoneStart + segStart + led_idx); + selectionFlags[zoneStart + segStart + led_idx] = 1; + } + } + + update(); + + /*-----------------------------------------------------*\ + | Send selection changed signal | + \*-----------------------------------------------------*/ + emit selectionChanged(selectedLeds); + + return true; +} + bool DeviceView::selectZone(int zone, bool add) { if(zone < 0 || size_t(zone) >= controller->zones.size()) diff --git a/qt/DeviceView.h b/qt/DeviceView.h index ff8d754d..6f775d92 100644 --- a/qt/DeviceView.h +++ b/qt/DeviceView.h @@ -69,6 +69,7 @@ signals: public slots: bool selectLed(int); bool selectLeds(QVector); + bool selectSegment(int zone, int segment, bool add = false); bool selectZone(int zone, bool add = false); void clearSelection(); // Same as selecting the entire device void setSelectionColor(RGBColor); diff --git a/qt/OpenRGBDevicePage.cpp b/qt/OpenRGBDevicePage.cpp index 26cc35b7..e08c375e 100644 --- a/qt/OpenRGBDevicePage.cpp +++ b/qt/OpenRGBDevicePage.cpp @@ -146,63 +146,147 @@ RGBController* Ui::OpenRGBDevicePage::GetController() return device; } -void Ui::OpenRGBDevicePage::on_ZoneBox_currentIndexChanged(int /*index*/) +void Ui::OpenRGBDevicePage::on_ZoneBox_currentIndexChanged(int index) { /*-----------------------------------------------------*\ | Read selected mode | \*-----------------------------------------------------*/ unsigned int selected_mode = (unsigned int)ui->ModeBox->currentIndex(); + /*-----------------------------------------------------*\ + | Process zone box change based on color mode | + \*-----------------------------------------------------*/ switch(device->modes[selected_mode].color_mode) { case MODE_COLORS_PER_LED: { - int selected_zone = ui->ZoneBox->currentIndex(); + /*-----------------------------------------*\ + | Initialize both selected zone and segment | + | to -1 to indicate there is no selection | + \*-----------------------------------------*/ + unsigned int current_index = 0; + bool selected_all_zones = false; + int selected_zone = -1; + int selected_segment = -1; - QString msLine; - if(MultipleSelected) + /*-----------------------------------------*\ + | Handle condition where device has more | + | than one zone, which adds an "All Zones" | + | entry to the Zone menu in the first index | + \*-----------------------------------------*/ + if(device->zones.size() > 1) { - msLine = ui->LEDBox->itemText(ui->LEDBox->count() - 1); + if(index == current_index) + { + selected_all_zones = true; + } + + current_index++; } + + /*-----------------------------------------*\ + | Determine selected zone and optionally | + | selected segment based on index if "All | + | Zones" is not the selected index | + \*-----------------------------------------*/ + if(!selected_all_zones) + { + for(std::size_t zone_idx = 0; zone_idx < device->zones.size(); zone_idx++) + { + if(index == current_index) + { + selected_zone = zone_idx; + break; + } + + current_index++; + + for(std::size_t segment_idx = 0; segment_idx < device->zones[zone_idx].segments.size(); segment_idx++) + { + if(index == current_index) + { + selected_zone = zone_idx; + selected_segment = segment_idx; + break; + } + + current_index++; + } + + if(selected_segment != -1) + { + break; + } + } + } + + /*-----------------------------------------*\ + | Clear LED box | + \*-----------------------------------------*/ ui->LEDBox->blockSignals(true); ui->LEDBox->clear(); - if(device->zones.size() > 1) - { - if(selected_zone == 0) - { - if(device->leds.size() > 1) - { - ui->LEDBox->addItem(tr("Entire Device")); - ui->LEDBox->setEnabled(1); - } - else - { - ui->LEDBox->setDisabled(1); - } - for (std::size_t i = 0; i < device->leds.size(); i++) - { - ui->LEDBox->addItem(device->leds[i].name.c_str()); - } - if(MultipleSelected) // Preserve the multiple() option - { - ui->LEDBox->addItem(msLine); - ui->LEDBox->setCurrentIndex((int)device->leds.size()); - } + /*-----------------------------------------*\ + | Clear multiple selected flag | + \*-----------------------------------------*/ + MultipleSelected = false; - ui->ResizeButton->setEnabled(false); - if(!ui->ZoneBox->signalsBlocked()) - { - ui->DeviceViewBox->blockSignals(true); - ui->DeviceViewBox->clearSelection(); - ui->DeviceViewBox->blockSignals(false); - } - } - selected_zone = selected_zone - 1; - } - if(device->zones.size() == 1 || selected_zone != -1) + /*-----------------------------------------*\ + | Handle "All Zones" selected condition or | + | multiple selection condition | + \*-----------------------------------------*/ + if(selected_all_zones) { - // Disable led box if there's only one LED anyway + /*-------------------------------------*\ + | If there are multiple LEDs, add the | + | "Entire Device" option to the LED box | + | and enable it, otherwise there is | + | only one LED so disable it | + \*-------------------------------------*/ + if(device->leds.size() > 1) + { + ui->LEDBox->addItem(tr("Entire Device")); + ui->LEDBox->setEnabled(1); + } + else + { + ui->LEDBox->setDisabled(1); + } + + /*-------------------------------------*\ + | Fill in the LED list with all LEDs in | + | the device | + \*-------------------------------------*/ + for(std::size_t i = 0; i < device->leds.size(); i++) + { + ui->LEDBox->addItem(device->leds[i].name.c_str()); + } + + /*-------------------------------------*\ + | Resizing is not allowed when all | + | zones are selected at once | + \*-------------------------------------*/ + ui->ResizeButton->setEnabled(false); + + if(!ui->ZoneBox->signalsBlocked()) + { + ui->DeviceViewBox->blockSignals(true); + ui->DeviceViewBox->clearSelection(); + ui->DeviceViewBox->blockSignals(false); + } + } + + /*-----------------------------------------*\ + | Handle a zone selected condition | + \*-----------------------------------------*/ + else if(selected_zone != -1 && selected_segment == -1) + { + /*-------------------------------------*\ + | If there are multiple LEDs, add the | + | "Entire Zone" option to the LED box | + | and enable it, otherwise there is | + | only one LED so disable it | + \*-------------------------------------*/ if(device->zones[selected_zone].leds_count > 1) { ui->LEDBox->addItem(tr("Entire Zone")); @@ -212,11 +296,20 @@ void Ui::OpenRGBDevicePage::on_ZoneBox_currentIndexChanged(int /*index*/) { ui->LEDBox->setDisabled(1); } - for (std::size_t led_idx = 0; led_idx < device->zones[selected_zone].leds_count; led_idx++) + + /*-------------------------------------*\ + | Fill in the LED list with all LEDs in | + | the zone | + \*-------------------------------------*/ + for(std::size_t led_idx = 0; led_idx < device->zones[selected_zone].leds_count; led_idx++) { ui->LEDBox->addItem(device->zones[selected_zone].leds[led_idx].name.c_str()); } + /*-------------------------------------*\ + | Enable resizing if zone has variable | + | LED count (min != max) | + \*-------------------------------------*/ if(device->zones[selected_zone].leds_min == device->zones[selected_zone].leds_max) { ui->ResizeButton->setEnabled(false); @@ -225,6 +318,7 @@ void Ui::OpenRGBDevicePage::on_ZoneBox_currentIndexChanged(int /*index*/) { ui->ResizeButton->setEnabled(true); } + if(!ui->ZoneBox->signalsBlocked()) { ui->DeviceViewBox->blockSignals(true); @@ -233,6 +327,50 @@ void Ui::OpenRGBDevicePage::on_ZoneBox_currentIndexChanged(int /*index*/) } } + /*-----------------------------------------*\ + | Handle a segment selected condition | + \*-----------------------------------------*/ + else if(selected_zone != -1 && selected_segment != -1) + { + /*-------------------------------------*\ + | If there are multiple LEDs, add the | + | "Entire Segment" option to the LED | + | box and enable it, otherwise there is | + | only one LED so disable it | + \*-------------------------------------*/ + if(device->zones[selected_zone].segments[selected_segment].leds_count > 1) + { + ui->LEDBox->addItem(tr("Entire Segment")); + ui->LEDBox->setEnabled(1); + } + else + { + ui->LEDBox->setDisabled(1); + } + + /*-------------------------------------*\ + | Fill in the LED list with all LEDs in | + | the segment | + \*-------------------------------------*/ + for(std::size_t led_idx = 0; led_idx < device->zones[selected_zone].segments[selected_segment].leds_count; led_idx++) + { + ui->LEDBox->addItem(device->zones[selected_zone].leds[led_idx + device->zones[selected_zone].segments[selected_segment].start_idx].name.c_str()); + } + + /*-------------------------------------*\ + | Resizing is not allowed when a | + | segment is selected | + \*-------------------------------------*/ + ui->ResizeButton->setEnabled(false); + + if(!ui->ZoneBox->signalsBlocked()) + { + ui->DeviceViewBox->blockSignals(true); + ui->DeviceViewBox->selectSegment(selected_zone, selected_segment); + ui->DeviceViewBox->blockSignals(false); + } + } + ui->LEDBox->setCurrentIndex(0); on_LEDBox_currentIndexChanged(0); ui->LEDBox->blockSignals(false); @@ -243,84 +381,258 @@ void Ui::OpenRGBDevicePage::on_ZoneBox_currentIndexChanged(int /*index*/) void Ui::OpenRGBDevicePage::on_LEDBox_currentIndexChanged(int index) { - if(index < 0) - { - return; - } - /*-----------------------------------------------------*\ | Read selected mode | \*-----------------------------------------------------*/ unsigned int selected_mode = (unsigned int)ui->ModeBox->currentIndex(); + /*-----------------------------------------------------*\ + | Process zone box change based on color mode | + \*-----------------------------------------------------*/ switch(device->modes[selected_mode].color_mode) { case MODE_COLORS_PER_LED: { - int selected_zone = ui->ZoneBox->currentIndex(); - bool multiple = (std::size_t(index) == (device->leds.size() + 1)); - - RGBColor color = 0x00000000; - bool updateColor = 0; + /*-----------------------------------------*\ + | Initialize both selected zone and segment | + | to -1 to indicate there is no selection | + \*-----------------------------------------*/ + unsigned int current_index = 0; + bool selected_all_zones = false; + bool selected_all_leds = false; + int selected_led = -1; + int selected_zone = -1; + int selected_segment = -1; + /*-----------------------------------------*\ + | Handle condition where device has more | + | than one zone, which adds an "All Zones" | + | entry to the Zone menu in the first index | + \*-----------------------------------------*/ if(device->zones.size() > 1) { - if(selected_zone == 0) // All zones + if(ui->ZoneBox->currentIndex() == current_index) { - if(device->leds.size() > 1) - { - if(index == 0) // All LEDs on the entire device - { - if(!ui->LEDBox->signalsBlocked()) - { - ui->DeviceViewBox->blockSignals(true); - ui->DeviceViewBox->clearSelection(); - ui->DeviceViewBox->blockSignals(false); - } - } - index = index - 1; - } - if((device->leds.size() == 1 || index != -1) && !multiple) - { - if(MultipleSelected) - { - ui->LEDBox->removeItem((int)(device->leds.size() + 1)); - } - MultipleSelected = 0; - color = device->GetLED(index); // One LED, proceed - updateColor = 1; - if(!ui->LEDBox->signalsBlocked()) - { - ui->DeviceViewBox->blockSignals(true); - ui->DeviceViewBox->selectLed(index); - ui->DeviceViewBox->blockSignals(false); - } - } + selected_all_zones = true; } - selected_zone = selected_zone - 1; + + current_index++; } - if(device->zones.size() == 1 || selected_zone != -1) // A specific zone is selected + + /*-----------------------------------------*\ + | Determine selected zone and optionally | + | selected segment based on index if "All | + | Zones" is not the selected index | + \*-----------------------------------------*/ + if(!selected_all_zones) { - if(device->zones[selected_zone].leds_count > 1) + for(std::size_t zone_idx = 0; zone_idx < device->zones.size(); zone_idx++) { - if(index == 0) // Entire zone + if(ui->ZoneBox->currentIndex() == current_index) { + selected_zone = zone_idx; + break; + } + + current_index++; + + for(std::size_t segment_idx = 0; segment_idx < device->zones[zone_idx].segments.size(); segment_idx++) + { + if(ui->ZoneBox->currentIndex() == current_index) + { + selected_zone = zone_idx; + selected_segment = segment_idx; + break; + } + + current_index++; + } + + if(selected_segment != -1) + { + break; + } + } + } + + /*-----------------------------------------*\ + | Handle selection of "Entire Device/Zone/ | + | Segment" index is selected | + | | + | There should always be an Entire index as | + | long as the LED box is enabled | + \*-----------------------------------------*/ + if(index == 0) + { + selected_all_leds = true; + } + /*-----------------------------------------*\ + | Determine selected LED if "Entire Device/ | + | Zone/Segment" is not selected | + \*-----------------------------------------*/ + else + { + selected_led = index - 1; + } + + /*-----------------------------------------*\ + | Initialize variables | + \*-----------------------------------------*/ + bool multiple = (std::size_t(selected_led) == (device->leds.size() + 1)); + RGBColor color = 0x00000000; + bool updateColor = false; + + /*-----------------------------------------*\ + | Remove multiple selection | + \*-----------------------------------------*/ + if(MultipleSelected) + { + ui->LEDBox->removeItem((int)(device->leds.size() + 1)); + } + + MultipleSelected = false; + + /*-----------------------------------------*\ + | Handle "All Zones" selected condition | + \*-----------------------------------------*/ + if(selected_all_zones) + { + /*-------------------------------------*\ + | Handle Entire Device selection | + \*-------------------------------------*/ + if(selected_all_leds) + { + if(!ui->LEDBox->signalsBlocked()) + { + ui->DeviceViewBox->blockSignals(true); + ui->DeviceViewBox->clearSelection(); + ui->DeviceViewBox->blockSignals(false); + } + } + + /*-------------------------------------*\ + | Handle single selected LED | + \*-------------------------------------*/ + if((device->leds.size() == 1 || selected_led != -1) && !multiple) + { + /*---------------------------------*\ + | Get selected LED's current color | + \*---------------------------------*/ + color = device->GetLED(selected_led); + + /*---------------------------------*\ + | Set update color flag | + \*---------------------------------*/ + updateColor = true; + + /*---------------------------------*\ + | Select LED in device view | + \*---------------------------------*/ + if(!ui->LEDBox->signalsBlocked()) + { + ui->DeviceViewBox->blockSignals(true); + ui->DeviceViewBox->selectLed(selected_led); + ui->DeviceViewBox->blockSignals(false); + } + } + } + /*-----------------------------------------*\ + | Handle a zone selected condition | + \*-----------------------------------------*/ + else if(selected_zone != -1 && selected_segment == -1) + { + /*-------------------------------------*\ + | Handle Entire Zone selection | + \*-------------------------------------*/ + if(selected_all_leds) + { + if(!ui->LEDBox->signalsBlocked()) + { + ui->DeviceViewBox->blockSignals(true); + ui->DeviceViewBox->selectZone(selected_zone); + ui->DeviceViewBox->blockSignals(false); + } + } + + /*-------------------------------------*\ + | Handle single selected LED | + \*-------------------------------------*/ + if(device->zones[selected_zone].leds_count == 1 || selected_led != -1) + { + if((unsigned int)selected_led < device->zones[selected_zone].leds_count) + { + /*-----------------------------*\ + | Get selected LED's current | + | color | + \*-----------------------------*/ + color = device->zones[selected_zone].colors[selected_led]; + + /*-----------------------------*\ + | Set update color flag | + \*-----------------------------*/ + updateColor = 1; + + /*-----------------------------*\ + | Set global index | + \*-----------------------------*/ + int globalIndex = device->zones[selected_zone].leds - &(device->leds[0]) + selected_led; + + /*-----------------------------*\ + | Select LED in device view | + \*-----------------------------*/ if(!ui->LEDBox->signalsBlocked()) { ui->DeviceViewBox->blockSignals(true); - ui->DeviceViewBox->selectZone(selected_zone); + ui->DeviceViewBox->selectLed(globalIndex); ui->DeviceViewBox->blockSignals(false); } } - index = index - 1; } - if(device->zones[selected_zone].leds_count == 1 || index != -1) + } + /*-----------------------------------------*\ + | Handle a segment selected condition | + \*-----------------------------------------*/ + else if(selected_zone != -1 && selected_segment != -1) + { + /*-------------------------------------*\ + | Handle Entire Zone selection | + \*-------------------------------------*/ + if(selected_all_leds) { - if((unsigned int)index < device->zones[selected_zone].leds_count) + if(!ui->LEDBox->signalsBlocked()) { - color = device->zones[selected_zone].colors[index]; + ui->DeviceViewBox->blockSignals(true); + ui->DeviceViewBox->selectSegment(selected_zone, selected_segment); + ui->DeviceViewBox->blockSignals(false); + } + } + + /*-------------------------------------*\ + | Handle single selected LED | + \*-------------------------------------*/ + if(device->zones[selected_zone].segments[selected_segment].leds_count == 1 || selected_led != -1) + { + if((unsigned int)selected_led < device->zones[selected_zone].segments[selected_segment].leds_count) + { + /*-----------------------------*\ + | Get selected LED's current | + | color | + \*-----------------------------*/ + color = device->zones[selected_zone].colors[selected_led + device->zones[selected_zone].segments[selected_segment].start_idx]; + + /*-----------------------------*\ + | Set update color flag | + \*-----------------------------*/ updateColor = 1; - int globalIndex = device->zones[selected_zone].leds - &(device->leds[0]) + index; + + /*-----------------------------*\ + | Set global index | + \*-----------------------------*/ + int globalIndex = device->zones[selected_zone].leds - &(device->leds[0]) + selected_led + device->zones[selected_zone].segments[selected_segment].start_idx; + + /*-----------------------------*\ + | Select LED in device view | + \*-----------------------------*/ if(!ui->LEDBox->signalsBlocked()) { ui->DeviceViewBox->blockSignals(true); @@ -700,15 +1012,24 @@ void Ui::OpenRGBDevicePage::UpdateModeUi() ui->ZoneBox->setEnabled(1); ui->ZoneBox->addItem(tr("All Zones")); } + else if(device->zones.size() == 1 && device->zones[0].segments.size() > 1) + { + ui->ZoneBox->setEnabled(1); + } else { ui->ZoneBox->setDisabled(1); ui->ResizeButton->setEnabled(false); } - for (std::size_t i = 0; i < device->zones.size(); i++) + for(std::size_t zone_idx = 0; zone_idx < device->zones.size(); zone_idx++) { - ui->ZoneBox->addItem(device->zones[i].name.c_str()); + ui->ZoneBox->addItem(device->zones[zone_idx].name.c_str()); + + for(std::size_t segment_idx = 0; segment_idx < device->zones[zone_idx].segments.size(); segment_idx++) + { + ui->ZoneBox->addItem((" " + device->zones[zone_idx].segments[segment_idx].name).c_str()); + } } ui->ZoneBox->setCurrentIndex(0);