From 487c0de90fa4faef91eb46629c5f73d5ffe04e7b Mon Sep 17 00:00:00 2001 From: Max Paperno Date: Sun, 3 Jun 2018 17:16:20 -0400 Subject: [PATCH] [Companion][InputsPanel] Fix "ghost" input names being left over when moving items (closes #5740); Cut/paste and drag-move will now also copy the input name if destination input is nameless and source input becomes empty (will not duplicate names); Clean up/simplify some code. (#5942) --- companion/src/firmwares/modeldata.cpp | 13 +- companion/src/firmwares/modeldata.h | 2 +- companion/src/modeledit/inputs.cpp | 213 +++++++++++++------------- companion/src/modeledit/inputs.h | 10 +- 4 files changed, 113 insertions(+), 125 deletions(-) diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index bb8e7ce1a..c2c69ee16 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -151,7 +151,7 @@ QVector ModelData::mixes(int channel) const return result; } -void ModelData::removeInput(const int idx) +void ModelData::removeInput(const int idx, bool clearName) { unsigned int chn = expoData[idx].chn; @@ -159,15 +159,8 @@ void ModelData::removeInput(const int idx) expoData[CPN_MAX_EXPOS-1].clear(); //also remove input name if removing last line for this input - bool found = false; - for (int i=0; i destination channel - // i -> mixer number - QByteArray qba; ExposlistWidget->clear(); - int curDest = -1; - - for (int i=0; iexpoData[i]; - - if (!md->mode) - break; - - while (curDest < (int)md->chn-1) { - curDest++; - AddInputLine(-curDest-1); + for (int i=0; i < inputsCount; ++i) { + bool filled = false; + for (uint j=0; j < CPN_MAX_EXPOS; ++j) { + const ExpoData & ed = model->expoData[j]; + if ((int)ed.chn == i && ed.mode) { + AddInputLine(j); + filled = true; + } } - if (AddInputLine(i)) { - curDest++; + if (!filled) { + AddInputLine(-i-1); } } - - while (curDest < inputsCount-1) { - curDest++; - AddInputLine(-curDest-1); - } - lock = false; } @@ -109,65 +96,52 @@ void InputsPanel::update() @param[in] dest defines which input line to create. If dest < 0 then create empty input slot for input -dest ( dest=-6 -> Input05) if dest >=0 then create used input based on model input data from slot dest (dest=4 -> model expoData[4]) - - @retval true created input number is different from the previous list item - false created input number is the same as previous list item */ -bool InputsPanel::AddInputLine(int dest) +void InputsPanel::AddInputLine(int dest) { - bool new_ch; - QString str = getInputText(dest, &new_ch); - QListWidgetItem *itm = new QListWidgetItem(str); QByteArray qba(1, (quint8)dest); unsigned destId = abs(dest); + bool newChan = false; bool hasSibs = false; - if (dest >= 0) { + if (dest >= 0 && dest < CPN_MAX_EXPOS) { //add input data - ExpoData *md = &model->expoData[dest]; - qba.append((const char*)md, sizeof(ExpoData)); - destId = md->chn + 1; - hasSibs = (dest < CPN_MAX_EXPOS && model->expoData[dest+1].chn == md->chn); + const ExpoData &md = model->expoData[dest]; + qba.append((const char*)&md, sizeof(ExpoData)); + destId = md.chn + 1; + const QVector expos = model->expos(md.chn); + newChan = (expos.constFirst() == &md); + hasSibs = (expos.constLast() != &md); } + QListWidgetItem *itm = new QListWidgetItem(getInputText(dest, newChan)); itm->setData(Qt::UserRole, qba); - ExposlistWidget->addItem(itm, destId, new_ch, hasSibs); - //qDebug() << "InputsPanel::AddInputLine(): dest" << dest << "text" << str; - return new_ch; + ExposlistWidget->addItem(itm, destId, newChan, hasSibs); } /** @brief Returns HTML formated input representation - @param[in] dest defines which input line to create. + @param dest defines which input line to create. If dest < 0 then create empty input slot for input -dest ( dest=-6 -> Input05) if dest >=0 then create used input based on model input data from slot dest (dest=4 -> model expoData[4]) + @param newChan If true, prints the full channel name in leading column, otherwise pads the column with spaces. Assumed true if @a dest < 0. + @retval string input line in HTML */ -QString InputsPanel::getInputText(int dest, bool * new_ch) +QString InputsPanel::getInputText(int dest, bool newChan) { QString str; - - if (new_ch) - *new_ch = false; - if (dest < 0) { str = modelPrinter.printInputName(-dest-1); - if (new_ch) - *new_ch = true; } else { - ExpoData & input = model->expoData[dest]; - int nameChars = (firmware->getCapability(VirtualInputs) ? 10 : 4); - - if ((dest == 0) || (model->expoData[dest-1].chn != input.chn)) { - if (new_ch) - *new_ch = true; + const ExpoData & input = model->expoData[dest]; + const int nameChars = (firmware->getCapability(VirtualInputs) ? 10 : 4); + if (newChan) str = QString("%1").arg(modelPrinter.printInputName(input.chn), -nameChars, QChar(' ')); - } - else { + else str = QString(nameChars, QChar(' ')); - } str.replace(" ", " "); str += modelPrinter.printInputLine(input); } @@ -191,9 +165,9 @@ bool InputsPanel::gm_insertExpo(int idx) return true; } -void InputsPanel::gm_deleteExpo(int index) +void InputsPanel::gm_deleteExpo(int index, bool clearName) { - model->removeInput(index); + model->removeInput(index, clearName); } void InputsPanel::gm_openExpo(int index) @@ -266,7 +240,7 @@ void InputsPanel::exposDelete(bool ask) if ((ret == QMessageBox::Yes) || (!ask)) { - exposDeleteList(list); + exposDeleteList(list, ask); emit modified(); update(); } @@ -300,7 +274,7 @@ void InputsPanel::mimeExpoDropped(int index, const QMimeData *data, Qt::DropActi } else if (action==Qt::MoveAction) { QList list = createExpoListFromSelected(); - exposDeleteList(list); + exposDeleteList(list, false); foreach (const int del, list) { if (del < idx) --idx; @@ -332,7 +306,9 @@ void InputsPanel::pasteExpoMimeData(const QMimeData * mimeData, int destIdx) break; ExpoData *md = &model->expoData[idx]; memcpy(md, mxData.mid(i, sizeof(ExpoData)).constData(), sizeof(ExpoData)); + const int oldChan = md->chn; md->chn = dch; + maybeCopyInputName(oldChan, md->chn); i += sizeof(ExpoData); } @@ -354,8 +330,8 @@ void InputsPanel::exposPaste() void InputsPanel::exposDuplicate() { - exposCopy(); - exposPaste(); + exposCopy(); + exposPaste(); } @@ -394,7 +370,6 @@ void InputsPanel::expoAdd() gm_openExpo(index); } - void InputsPanel::expolistWidget_customContextMenuRequested(QPoint pos) { QPoint globalPos = ExposlistWidget->mapToGlobal(pos); @@ -438,80 +413,81 @@ void InputsPanel::expolistWidget_KeyPress(QKeyEvent *event) ExposlistWidget->setCurrentRow(ExposlistWidget->currentRow()-1); } - int InputsPanel::gm_moveExpo(int idx, bool dir) //true=inc=down false=dec=up { + if (idx >= CPN_MAX_EXPOS || idx < 0 || (dir && idx >= CPN_MAX_EXPOS - 1) || (!dir && !idx)) + return -1; - if(idx>CPN_MAX_EXPOS || (idx==CPN_MAX_EXPOS && dir)) return idx; + const int tdx = dir ? idx+1 : idx-1; + ExpoData temp; + ExpoData &src = model->expoData[idx]; + ExpoData &tgt = model->expoData[tdx]; - int tdx = dir ? idx+1 : idx-1; - ExpoData temp; - temp.clear(); - ExpoData &src=model->expoData[idx]; - ExpoData &tgt=model->expoData[tdx]; - if (!dir && tdx<0 && src.chn>0) { + if (memcmp(&src, &temp, sizeof(ExpoData)) == 0) { + // src expo is empty + return -1; + } + + bool tgtempty = (memcmp(&tgt, &temp, sizeof(ExpoData)) == 0); + + if (tgt.chn != src.chn || tgtempty) { + const int oldChan = src.chn; + if (dir && src.chn < unsigned(inputsCount-1)) + src.chn++; + else if (!dir && src.chn > 0) src.chn--; - return idx; - } - else if (!dir && tdx<0) { - return idx; - } + maybeCopyInputName(oldChan, src.chn); + return idx; + } - if (memcmp(&src, &temp, sizeof(ExpoData)) == 0) { - return idx; + // flip between src and tgt + memcpy(&temp, &src, sizeof(ExpoData)); + memcpy(&src, &tgt, sizeof(ExpoData)); + memcpy(&tgt, &temp, sizeof(ExpoData)); + return tdx; +} + +void InputsPanel::moveExpoList(bool down) +{ + QList list = createExpoListFromSelected(); + QList highlightList; + bool mod = false; + foreach(int idx, list) { + const int newIdx = gm_moveExpo(idx, down); + if (newIdx > -1) { + highlightList << newIdx; + mod = true; } - - bool tgtempty = (memcmp(&tgt, &temp, sizeof(ExpoData)) == 0); - - if (tgt.chn!=src.chn || tgtempty) { - if ((dir) && (src.chn0)) src.chn--; - return idx; - } - - // flip between idx and tgt - memcpy(&temp, &src, sizeof(ExpoData)); - memcpy(&src, &tgt, sizeof(ExpoData)); - memcpy(&tgt, &temp, sizeof(ExpoData)); - return tdx; + } + if (mod) { + emit modified(); + update(); + } + setSelectedByExpoList(highlightList); } void InputsPanel::moveExpoUp() { - QList list = createExpoListFromSelected(); - QList highlightList; - foreach(int idx, list) { - highlightList << gm_moveExpo(idx, false); - } - emit modified(); - update(); - setSelectedByExpoList(highlightList); + moveExpoList(false); } void InputsPanel::moveExpoDown() { - QList list = createExpoListFromSelected(); - QList highlightList; - foreach(int idx, list) { - highlightList << gm_moveExpo(idx, true); - } - emit modified(); - update(); - setSelectedByExpoList(highlightList); + moveExpoList(true); } void InputsPanel::expolistWidget_doubleClicked(QModelIndex index) { - expoOpen(ExposlistWidget->item(index.row())); + expoOpen(ExposlistWidget->item(index.row())); } -void InputsPanel::exposDeleteList(QList list) +void InputsPanel::exposDeleteList(QList list, bool clearName) { qSort(list.begin(), list.end()); int iDec = 0; foreach(int idx, list) { - gm_deleteExpo(idx-iDec); + gm_deleteExpo(idx-iDec, clearName); iDec++; } } @@ -524,3 +500,20 @@ void InputsPanel::clearExpos() update(); } } + +void InputsPanel::maybeCopyInputName(int srcChan, int destChan) +{ + if (srcChan == destChan) + return; + + // check to see if source input channel is now empty + const bool srcEmpty = (model->expos(srcChan).size() == 0); + + if (srcEmpty) { + // if destination input name is empty, copy it from source expo input + if (!strlen(model->inputNames[destChan])) + strncpy(model->inputNames[destChan], model->inputNames[srcChan], 5); + // clear the emptry source channel name + model->inputNames[srcChan][0] = 0; + } +} diff --git a/companion/src/modeledit/inputs.h b/companion/src/modeledit/inputs.h index 963c73544..939d0a647 100644 --- a/companion/src/modeledit/inputs.h +++ b/companion/src/modeledit/inputs.h @@ -37,6 +37,7 @@ class InputsPanel : public ModelPanel private slots: void clearExpos(); + void moveExpoList(bool down); void moveExpoUp(); void moveExpoDown(); void mimeExpoDropped(int index, const QMimeData *data, Qt::DropAction action); @@ -50,6 +51,7 @@ class InputsPanel : public ModelPanel void exposDuplicate(); void expoOpen(QListWidgetItem *item = NULL); void expoAdd(); + void maybeCopyInputName(int srcChan, int destChan); private: bool expoInserted; @@ -59,15 +61,15 @@ class InputsPanel : public ModelPanel int getExpoIndex(unsigned int dch); bool gm_insertExpo(int idx); - void gm_deleteExpo(int index); + void gm_deleteExpo(int index, bool clearName = true); void gm_openExpo(int index); int gm_moveExpo(int idx, bool dir); - void exposDeleteList(QList list); + void exposDeleteList(QList list, bool clearName = true); QList createExpoListFromSelected(); void setSelectedByExpoList(QList list); void pasteExpoMimeData(const QMimeData * mimeData, int destIdx); - bool AddInputLine(int dest); - QString getInputText(int dest, bool * new_ch); + void AddInputLine(int dest); + QString getInputText(int dest, bool newChan); };