Companion update model references from enhanced context menus (#7325)
Companion update model references from enhanced context menus
This commit is contained in:
@@ -49,7 +49,7 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
|
||||
}
|
||||
else {
|
||||
ui->name->setMaxLength(length);
|
||||
ui->name->setText(timer.name);
|
||||
//ui->name->setText(timer.name);
|
||||
}
|
||||
|
||||
// Mode
|
||||
@@ -85,6 +85,7 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
|
||||
QWidget::setTabOrder(ui->countdownBeep, ui->minuteBeep);
|
||||
QWidget::setTabOrder(ui->minuteBeep, ui->persistent);
|
||||
|
||||
update();
|
||||
lock = false;
|
||||
}
|
||||
|
||||
@@ -95,6 +96,9 @@ TimerPanel::~TimerPanel()
|
||||
|
||||
void TimerPanel::update()
|
||||
{
|
||||
lock = true;
|
||||
ui->name->setText(timer.name);
|
||||
|
||||
int hour = timer.val / 3600;
|
||||
int min = (timer.val - (hour * 3600)) / 60;
|
||||
int sec = (timer.val - (hour * 3600)) % 60;
|
||||
@@ -116,7 +120,10 @@ void TimerPanel::update()
|
||||
ui->persistentValue->setText(QString(" %1(%2:%3:%4)").arg(sign<0 ? "-" :" ").arg(hours, 2, 10, QLatin1Char('0')).arg(minutes, 2, 10, QLatin1Char('0')).arg(seconds, 2, 10, QLatin1Char('0')));
|
||||
}
|
||||
|
||||
ui->countdownBeep->updateValue();
|
||||
ui->minuteBeep->setChecked(timer.minuteBeep);
|
||||
ui->persistent->updateValue();
|
||||
lock = false;
|
||||
}
|
||||
|
||||
QWidget * TimerPanel::getLastFocus()
|
||||
@@ -126,38 +133,43 @@ QWidget * TimerPanel::getLastFocus()
|
||||
|
||||
void TimerPanel::on_value_editingFinished()
|
||||
{
|
||||
unsigned val = ui->value->time().hour()*3600 + ui->value->time().minute()*60 + ui->value->time().second();
|
||||
if (timer.val != val) {
|
||||
timer.val = val;
|
||||
emit modified();
|
||||
if (!lock) {
|
||||
unsigned val = ui->value->time().hour()*3600 + ui->value->time().minute()*60 + ui->value->time().second();
|
||||
if (timer.val != val) {
|
||||
timer.val = val;
|
||||
emit modified();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimerPanel::onModeChanged(int index)
|
||||
{
|
||||
if (lock)
|
||||
return;
|
||||
|
||||
bool ok;
|
||||
const RawSwitch rs(ui->mode->itemData(index).toInt(&ok));
|
||||
if (ok && timer.mode.toValue() != rs.toValue()) {
|
||||
timer.mode = rs;
|
||||
emit modified();
|
||||
if (!lock) {
|
||||
bool ok;
|
||||
const RawSwitch rs(ui->mode->itemData(index).toInt(&ok));
|
||||
if (ok && timer.mode.toValue() != rs.toValue()) {
|
||||
timer.mode = rs;
|
||||
emit modified();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimerPanel::on_minuteBeep_toggled(bool checked)
|
||||
{
|
||||
timer.minuteBeep = checked;
|
||||
emit modified();
|
||||
if (!lock) {
|
||||
timer.minuteBeep = checked;
|
||||
emit modified();
|
||||
}
|
||||
}
|
||||
|
||||
void TimerPanel::on_name_editingFinished()
|
||||
{
|
||||
if (QString(timer.name) != ui->name->text()) {
|
||||
int length = ui->name->maxLength();
|
||||
strncpy(timer.name, ui->name->text().toLatin1(), length);
|
||||
emit modified();
|
||||
if (!lock) {
|
||||
if (QString(timer.name) != ui->name->text()) {
|
||||
int length = ui->name->maxLength();
|
||||
strncpy(timer.name, ui->name->text().toLatin1(), length);
|
||||
emit modified();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,27 +285,12 @@ ModulePanel::~ModulePanel()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool ModulePanel::moduleHasFailsafes()
|
||||
{
|
||||
return firmware->getCapability(HasFailsafe) && (
|
||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCESS_ISRM ||
|
||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCST_ISRM_D16 ||
|
||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_PXX_XJT_X16 ||
|
||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_PXX_R9M ||
|
||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCESS_R9M ||
|
||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCESS_R9M_LITE ||
|
||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_ACCESS_R9M_LITE_PRO ||
|
||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_XJT_LITE_X16 ||
|
||||
(PulsesProtocol)module.protocol == PulsesProtocol::PULSES_MULTIMODULE
|
||||
);
|
||||
}
|
||||
|
||||
void ModulePanel::setupFailsafes()
|
||||
{
|
||||
ChannelFailsafeWidgetsGroup grp;
|
||||
const int start = module.channelsStart;
|
||||
const int end = start + module.channelsCount;
|
||||
const bool hasFailsafe = moduleHasFailsafes();
|
||||
const bool hasFailsafe = module.hasFailsafes(firmware);
|
||||
|
||||
lock = true;
|
||||
|
||||
@@ -382,48 +379,6 @@ void ModulePanel::setupFailsafes()
|
||||
lock = false;
|
||||
}
|
||||
|
||||
int ModulePanel::getMaxChannelCount()
|
||||
{
|
||||
const PulsesProtocol protocol = (PulsesProtocol)module.protocol;
|
||||
switch (protocol) {
|
||||
case PULSES_ACCESS_ISRM:
|
||||
return 24;
|
||||
case PULSES_PXX_R9M:
|
||||
case PULSES_ACCESS_R9M:
|
||||
case PULSES_ACCESS_R9M_LITE:
|
||||
case PULSES_ACCESS_R9M_LITE_PRO:
|
||||
case PULSES_ACCST_ISRM_D16:
|
||||
case PULSES_XJT_LITE_X16:
|
||||
case PULSES_PXX_XJT_X16:
|
||||
case PULSES_CROSSFIRE:
|
||||
case PULSES_SBUS:
|
||||
case PULSES_PPM:
|
||||
return 16;
|
||||
case PULSES_XJT_LITE_LR12:
|
||||
case PULSES_PXX_XJT_LR12:
|
||||
return 12;
|
||||
case PULSES_PXX_DJT:
|
||||
case PULSES_XJT_LITE_D8:
|
||||
case PULSES_PXX_XJT_D8:
|
||||
return 8;
|
||||
case PULSES_LP45:
|
||||
case PULSES_DSM2:
|
||||
case PULSES_DSMX:
|
||||
return 6;
|
||||
case PULSES_MULTIMODULE:
|
||||
if (module.multi.rfProtocol == MODULE_SUBTYPE_MULTI_DSM2)
|
||||
return 12;
|
||||
else
|
||||
return 16;
|
||||
break;
|
||||
case PULSES_OFF:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 8;
|
||||
}
|
||||
|
||||
void ModulePanel::update()
|
||||
{
|
||||
const PulsesProtocol protocol = (PulsesProtocol)module.protocol;
|
||||
@@ -510,7 +465,7 @@ void ModulePanel::update()
|
||||
mask |= MASK_PPM_FIELDS | MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
|
||||
}
|
||||
|
||||
if (moduleHasFailsafes()) {
|
||||
if (module.hasFailsafes(firmware)) {
|
||||
mask |= MASK_FAILSAFES;
|
||||
}
|
||||
|
||||
@@ -527,7 +482,7 @@ void ModulePanel::update()
|
||||
ui->label_channelsCount->setVisible(mask & MASK_CHANNELS_RANGE);
|
||||
ui->channelsCount->setVisible(mask & MASK_CHANNELS_RANGE);
|
||||
ui->channelsCount->setEnabled(mask & MASK_CHANNELS_COUNT);
|
||||
ui->channelsCount->setMaximum(getMaxChannelCount());
|
||||
ui->channelsCount->setMaximum(module.getMaxChannelCount());
|
||||
ui->channelsCount->setValue(module.channelsCount);
|
||||
ui->channelsCount->setSingleStep(firmware->getCapability(HasPPMStart) ? 1 : 2);
|
||||
|
||||
@@ -695,7 +650,7 @@ void ModulePanel::onProtocolChanged(int index)
|
||||
{
|
||||
if (!lock && module.protocol != ui->protocol->itemData(index).toUInt()) {
|
||||
module.protocol = ui->protocol->itemData(index).toInt();
|
||||
module.channelsCount = getMaxChannelCount();
|
||||
module.channelsCount = module.getMaxChannelCount();
|
||||
update();
|
||||
emit modified();
|
||||
}
|
||||
@@ -790,7 +745,7 @@ void ModulePanel::onMultiProtocolChanged(int index)
|
||||
if (rfProtocol > MODULE_SUBTYPE_MULTI_LAST)
|
||||
maxSubTypes=8;
|
||||
module.subType = std::min(module.subType, maxSubTypes -1);
|
||||
module.channelsCount = getMaxChannelCount();
|
||||
module.channelsCount = module.getMaxChannelCount();
|
||||
update();
|
||||
emit modified();
|
||||
lock = false;
|
||||
@@ -1064,16 +1019,28 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
|
||||
RawSwitchFilterItemModel * swModel = new RawSwitchFilterItemModel(&generalSettings, &model, RawSwitch::TimersContext, this);
|
||||
connect(this, &SetupPanel::updated, swModel, &RawSwitchFilterItemModel::update);
|
||||
|
||||
for (int i=0; i<CPN_MAX_TIMERS; i++) {
|
||||
if (i<firmware->getCapability(Timers)) {
|
||||
timersCount = firmware->getCapability(Timers);
|
||||
|
||||
for (int i = 0; i < CPN_MAX_TIMERS; i++) {
|
||||
if (i < timersCount) {
|
||||
timers[i] = new TimerPanel(this, model, model.timers[i], generalSettings, firmware, prevFocus, swModel);
|
||||
ui->gridLayout->addWidget(timers[i], 1+i, 1);
|
||||
connect(timers[i], &TimerPanel::modified, this, &SetupPanel::modified);
|
||||
connect(this, &SetupPanel::updated, timers[i], &TimerPanel::update);
|
||||
connect(this, &SetupPanel::timerUpdated, timers[i], &TimerPanel::update);
|
||||
prevFocus = timers[i]->getLastFocus();
|
||||
// TODO more reliable method required
|
||||
QLabel *label = findChild<QLabel *>(QString("label_timer%1").arg(i + 1));
|
||||
if (label) { // to stop crashing if not found
|
||||
label->setProperty("index", i);
|
||||
label->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
label->setToolTip(tr("Popup menu available"));
|
||||
label->setMouseTracking(true);
|
||||
connect(label, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onTimerCustomContextMenuRequested(QPoint)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
foreach(QLabel *label, findChildren<QLabel *>(QRegularExpression(QString("label_timer%1").arg(i+1)))) {
|
||||
foreach(QLabel *label, findChildren<QLabel *>(QRegularExpression(QString("label_timer%1").arg(i + 1 )))) { //TODO more reliable method required
|
||||
label->hide();
|
||||
}
|
||||
}
|
||||
@@ -1081,9 +1048,9 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
|
||||
|
||||
if (firmware->getCapability(HasTopLcd)) {
|
||||
ui->toplcdTimer->setField(model.toplcdTimer, this);
|
||||
for (int i=0; i<CPN_MAX_TIMERS; i++) {
|
||||
if (i<firmware->getCapability(Timers)) {
|
||||
ui->toplcdTimer->addItem(tr("Timer %1").arg(i+1), i);
|
||||
for (int i = 0; i < CPN_MAX_TIMERS; i++) {
|
||||
if (i<timersCount) {
|
||||
ui->toplcdTimer->addItem(tr("Timer %1").arg(i + 1), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1528,3 +1495,155 @@ void SetupPanel::on_editText_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
void SetupPanel::onTimerCustomContextMenuRequested(QPoint pos)
|
||||
{
|
||||
QLabel *label = (QLabel *)sender();
|
||||
selectedTimerIndex = label->property("index").toInt();
|
||||
QPoint globalPos = label->mapToGlobal(pos);
|
||||
|
||||
QMenu contextMenu;
|
||||
contextMenu.addAction(CompanionIcon("copy.png"), tr("Copy"), this, SLOT(cmTimerCopy()));
|
||||
contextMenu.addAction(CompanionIcon("cut.png"), tr("Cut"), this, SLOT(cmTimerCut()));
|
||||
contextMenu.addAction(CompanionIcon("paste.png"), tr("Paste"), this, SLOT(cmTimerPaste()))->setEnabled(hasTimerClipboardData());
|
||||
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear"), this, SLOT(cmTimerClear()));
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addAction(CompanionIcon("arrow-right.png"), tr("Insert"), this, SLOT(cmTimerInsert()))->setEnabled(insertTimerAllowed());
|
||||
contextMenu.addAction(CompanionIcon("arrow-left.png"), tr("Delete"), this, SLOT(cmTimerDelete()));
|
||||
contextMenu.addAction(CompanionIcon("moveup.png"), tr("Move Up"), this, SLOT(cmTimerMoveUp()))->setEnabled(moveTimerUpAllowed());
|
||||
contextMenu.addAction(CompanionIcon("movedown.png"), tr("Move Down"), this, SLOT(cmTimerMoveDown()))->setEnabled(moveTimerDownAllowed());
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addAction(CompanionIcon("clear.png"), tr("Clear All"), this, SLOT(cmTimerClearAll()));
|
||||
|
||||
contextMenu.exec(globalPos);
|
||||
}
|
||||
|
||||
bool SetupPanel::hasTimerClipboardData(QByteArray * data) const
|
||||
{
|
||||
const QClipboard * clipboard = QApplication::clipboard();
|
||||
const QMimeData * mimeData = clipboard->mimeData();
|
||||
if (mimeData->hasFormat(MIMETYPE_TIMER)) {
|
||||
if (data)
|
||||
data->append(mimeData->data(MIMETYPE_TIMER));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SetupPanel::insertTimerAllowed() const
|
||||
{
|
||||
return ((selectedTimerIndex < timersCount - 1) && (model->timers[timersCount - 1].isEmpty()));
|
||||
}
|
||||
|
||||
bool SetupPanel::moveTimerDownAllowed() const
|
||||
{
|
||||
return selectedTimerIndex < timersCount - 1;
|
||||
}
|
||||
|
||||
bool SetupPanel::moveTimerUpAllowed() const
|
||||
{
|
||||
return selectedTimerIndex > 0;
|
||||
}
|
||||
|
||||
void SetupPanel::cmTimerClear()
|
||||
{
|
||||
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear Timer. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||
return;
|
||||
|
||||
model->timers[selectedTimerIndex].clear();
|
||||
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_CLEAR, selectedTimerIndex);
|
||||
emit timerUpdated();
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void SetupPanel::cmTimerClearAll()
|
||||
{
|
||||
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear all Timers. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < timersCount; i++) {
|
||||
model->timers[i].clear();
|
||||
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_CLEAR, i);
|
||||
}
|
||||
emit timerUpdated();
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void SetupPanel::cmTimerCopy()
|
||||
{
|
||||
QByteArray data;
|
||||
data.append((char*)&model->timers[selectedTimerIndex], sizeof(TimerData));
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
mimeData->setData(MIMETYPE_TIMER, data);
|
||||
QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
|
||||
}
|
||||
|
||||
void SetupPanel::cmTimerCut()
|
||||
{
|
||||
cmTimerCopy();
|
||||
cmTimerClear();
|
||||
}
|
||||
|
||||
void SetupPanel::cmTimerDelete()
|
||||
{
|
||||
if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Delete Timer. Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||
return;
|
||||
|
||||
int maxidx = timersCount - 1;
|
||||
for (int i = selectedTimerIndex; i < maxidx; i++) {
|
||||
if (!model->timers[i].isEmpty() || !model->timers[i + 1].isEmpty()) {
|
||||
memcpy(&model->timers[i], &model->timers[i+1], sizeof(TimerData));
|
||||
}
|
||||
}
|
||||
model->timers[maxidx].clear();
|
||||
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SHIFT, selectedTimerIndex, 0, -1);
|
||||
emit timerUpdated();
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void SetupPanel::cmTimerInsert()
|
||||
{
|
||||
for (int i = (timersCount - 1); i > selectedTimerIndex; i--) {
|
||||
if (!model->timers[i].isEmpty() || !model->timers[i-1].isEmpty()) {
|
||||
memcpy(&model->timers[i], &model->timers[i-1], sizeof(TimerData));
|
||||
}
|
||||
}
|
||||
model->timers[selectedTimerIndex].clear();
|
||||
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SHIFT, selectedTimerIndex, 0, 1);
|
||||
emit timerUpdated();
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void SetupPanel::cmTimerMoveDown()
|
||||
{
|
||||
swapTimerData(selectedTimerIndex, selectedTimerIndex + 1);
|
||||
}
|
||||
|
||||
void SetupPanel::cmTimerMoveUp()
|
||||
{
|
||||
swapTimerData(selectedTimerIndex, selectedTimerIndex - 1);
|
||||
}
|
||||
|
||||
void SetupPanel::cmTimerPaste()
|
||||
{
|
||||
QByteArray data;
|
||||
if (hasTimerClipboardData(&data)) {
|
||||
TimerData *td = &model->timers[selectedTimerIndex];
|
||||
memcpy(td, data.constData(), sizeof(TimerData));
|
||||
emit timerUpdated();
|
||||
emit modified();
|
||||
}
|
||||
}
|
||||
|
||||
void SetupPanel::swapTimerData(int idx1, int idx2)
|
||||
{
|
||||
if ((idx1 != idx2) && (!model->timers[idx1].isEmpty() || !model->timers[idx2].isEmpty())) {
|
||||
TimerData tdtmp = model->timers[idx2];
|
||||
TimerData *td1 = &model->timers[idx1];
|
||||
TimerData *td2 = &model->timers[idx2];
|
||||
memcpy(td2, td1, sizeof(TimerData));
|
||||
memcpy(td1, &tdtmp, sizeof(TimerData));
|
||||
model->updateAllReferences(ModelData::REF_UPD_TYPE_TIMER, ModelData::REF_UPD_ACT_SWAP, idx1, idx2);
|
||||
emit timerUpdated();
|
||||
emit modified();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user