Allow selection of segments within Zone box

This commit is contained in:
Adam Honse 2023-01-15 01:23:28 -06:00
parent 447e936464
commit 72d8e66c91
3 changed files with 457 additions and 94 deletions

View file

@ -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<int> 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())

View file

@ -69,6 +69,7 @@ signals:
public slots:
bool selectLed(int);
bool selectLeds(QVector<int>);
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);

View file

@ -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);