1
0
Fork 0
mirror of https://github.com/EdgeTX/edgetx.git synced 2025-07-24 00:35:14 +03:00

[Companion] MdiChild now use a QTreeWidget instead of a QListWidget (… (#4096)

* [Companion] MdiChild now use a QTreeWidget instead of a QListWidget (for Horus compatibility)

* [Companion] Horus models.txt parsing / writing implemented

* Fix for QT53 (#4109)
This commit is contained in:
Bertrand Songis 2016-12-08 21:26:08 +01:00 committed by GitHub
parent dd77670007
commit ec56d2dbdb
15 changed files with 443 additions and 385 deletions

View file

@ -1079,7 +1079,9 @@ class ModelData {
QVector<const MixData *> mixes(int channel) const;
bool used;
char category[15+1];
char name[15+1];
char filename[16+1];
TimerData timers[CPN_MAX_TIMERS];
bool noGlobalFunctions;
bool thrTrim; // Enable Throttle Trim
@ -1208,7 +1210,8 @@ class GeneralSettings {
int calibMid[CPN_MAX_STICKS+CPN_MAX_POTS+CPN_MAX_MOUSE_ANALOGS];
int calibSpanNeg[CPN_MAX_STICKS+CPN_MAX_POTS+CPN_MAX_MOUSE_ANALOGS];
int calibSpanPos[CPN_MAX_STICKS+CPN_MAX_POTS+CPN_MAX_MOUSE_ANALOGS];
unsigned int currModel; // 0..15
unsigned int currModelIndex;
char currModelFilename[16+1];
unsigned int contrast;
unsigned int vBatWarn;
int txVoltageCalibration;
@ -1321,6 +1324,30 @@ class RadioData {
public:
GeneralSettings generalSettings;
ModelData models[CPN_MAX_MODELS];
void setCurrentModel(unsigned int index)
{
generalSettings.currModelIndex = index;
strcpy(generalSettings.currModelFilename, models[index].filename);
}
QString getNextModelFilename()
{
char filename[sizeof(ModelData::filename)];
int index = 0;
bool found = true;
while (found) {
sprintf(filename, "model%d.bin", ++index);
found = false;
for (int i=0; i<CPN_MAX_MODELS; i++) {
if (strcmp(filename, models[i].filename) == 0) {
found = true;
break;
}
}
}
return filename;
}
};
enum Capability {

View file

@ -87,7 +87,7 @@ Er9xGeneral::operator GeneralSettings ()
result.calibSpanPos[i] = calibSpanPos[i];
}
result.currModel = currModel;
result.currModelIndex = currModel;
result.contrast = contrast;
result.vBatWarn = vBatWarn;
result.txVoltageCalibration = txVoltageCalibration;

View file

@ -99,7 +99,7 @@ Ersky9xGeneral::operator GeneralSettings ()
result.calibSpanPos[i] = calibSpanPos[i];
}
result.currModel = currModel;
result.currModelIndex = currModel;
result.contrast = contrast;
result.vBatWarn = vBatWarn;
result.txVoltageCalibration = txVoltageCalibration;

View file

@ -3394,9 +3394,9 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, BoardEnum board, unsigne
if (IS_HORUS(board)) {
for (int i = 0; i < 5; i++) {
internalField.Append(new CharField<610>(modelData.customScreenData[i], true, "Custom screen blob"));
internalField.Append(new CharField<610>(modelData.customScreenData[i], false, "Custom screen blob"));
}
internalField.Append(new CharField<216>(modelData.topbarData, true, "Top bar blob"));
internalField.Append(new CharField<216>(modelData.topbarData, false, "Top bar blob"));
internalField.Append(new SpareBitsField<8>()); // current view
}
}
@ -3512,7 +3512,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, BoardEnum bo
internalField.Append(new UnsignedField<16>(chkSum));
if (!IS_HORUS(board)) {
internalField.Append(new UnsignedField<8>(generalData.currModel));
internalField.Append(new UnsignedField<8>(generalData.currModelIndex));
internalField.Append(new UnsignedField<8>(generalData.contrast));
}
internalField.Append(new UnsignedField<8>(generalData.vBatWarn));
@ -3711,8 +3711,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, BoardEnum bo
for (int i=0; i<MAX_SLIDERS(board); ++i) {
internalField.Append(new ZCharField<3>(generalData.sliderName[i], "Slider name"));
}
static char modelName[17+1] = "model1.bin\0 ";
internalField.Append(new CharField<17>(modelName, true, "Model name"));
internalField.Append(new CharField<17>(generalData.currModelFilename, true, "Current model filename"));
}
else if (IS_TARANIS(board) && version >= 217) {
for (int i=0; i<MAX_SWITCHES(board, version); i++) {

View file

@ -228,22 +228,33 @@ int OpenTxEepromInterface::loadFile(RadioData & radioData, const QString & filen
storage.read(filename);
// models.txt
QString modelList = QString(storage.modelList);
qDebug() << "Models: size" << modelList.size() << "contents" << modelList;
// radio.bin
// Radio settings
qDebug() << "Radio settings:" << storage.radio.size();
loadFromByteArray<GeneralSettings, OpenTxGeneralData>(radioData.generalSettings, storage.radio);
// all models
QList<QString> models = storage.getModelsFileNames();
qDebug() << "We have" << models.size() << "models:";
int index = 0;
for (QList<ModelFile>::iterator it = storage.models.begin(); it != storage.models.end(); ++it, ++index) {
loadFromByteArray<ModelData, OpenTxModelData>(radioData.models[index], it->data);
radioData.models[index].used = true;
// Models
int modelIndex = 0;
QString modelList = QString(storage.modelList);
QList<QByteArray> lines = storage.modelList.split('\n');
QString category = QObject::tr("Unknown");
foreach (const QByteArray & line, lines) {
if (!line.isEmpty()) {
if (line.startsWith('[') && line.endsWith(']')) {
category = line.mid(1, line.size() - 2);
}
else {
qDebug() << "Loading" << line;
foreach (const ModelFile &model, storage.models) {
if (line == model.filename) {
loadFromByteArray<ModelData, OpenTxModelData>(radioData.models[modelIndex], model.data);
strncpy(radioData.models[modelIndex].filename, line.data(), sizeof(radioData.models[modelIndex].filename));
strncpy(radioData.models[modelIndex].category, category.toStdString().c_str(), sizeof(radioData.models[modelIndex].category));
radioData.models[modelIndex].used = true;
modelIndex++;
}
}
}
}
}
return 0;
@ -255,7 +266,8 @@ int OpenTxEepromInterface::saveFile(const RadioData & radioData, const QString &
uint8_t version = getLastDataVersion(board);
// models.txt
storage.modelList = QByteArray("[Models]\n");
storage.modelList = QByteArray();
QString currentCategory = "";
// radio.bin
saveToByteArray<GeneralSettings, OpenTxGeneralData>(radioData.generalSettings, storage.radio, version);
@ -264,12 +276,17 @@ int OpenTxEepromInterface::saveFile(const RadioData & radioData, const QString &
for (int i=0; i<CPN_MAX_MODELS; i++) {
const ModelData & model = radioData.models[i];
if (!model.isEmpty()) {
QString modelFilename = QString().sprintf("model%d.bin", i+1);
QString modelFilename = model.filename;
QByteArray modelData;
saveToByteArray<ModelData, OpenTxModelData>(model, modelData, version);
ModelFile modelFile = { modelFilename, modelData };
storage.models.append(modelFile);
storage.modelList.append(QString(" ") + modelFilename + "\n");
QString modelCategory = model.category;
if (currentCategory != modelCategory) {
storage.modelList.append(QString().sprintf("[%s]\n", model.category));
currentCategory = modelCategory;
}
storage.modelList.append(modelFilename + "\n");
}
}

View file

@ -813,7 +813,7 @@ void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx)
unsigned int flags = 0;
if (modelIdx >= 0) {
flags |= SIMULATOR_FLAGS_NOTX;
simuData->generalSettings.currModel = modelIdx;
simuData->setCurrentModel(modelIdx);
}
if (radioData.generalSettings.stickMode & 1) {
flags |= SIMULATOR_FLAGS_STICK_MODE_LEFT;

View file

@ -33,8 +33,6 @@
#include "wizarddialog.h"
#include "flashfirmwaredialog.h"
#include "storage_eeprom.h"
#include "storage_sdcard.h"
#include <QFileInfo>
#if defined WIN32 || !defined __GNUC__
#include <windows.h>
@ -45,19 +43,19 @@
MdiChild::MdiChild():
QWidget(),
ui(new Ui::mdiChild),
ui(new Ui::MdiChild),
firmware(GetCurrentFirmware()),
isUntitled(true),
fileChanged(false)
{
ui->setupUi(this);
setWindowIcon(CompanionIcon("open.png"));
ui->SimulateTxButton->setIcon(CompanionIcon("simulate.png"));
ui->simulateButton->setIcon(CompanionIcon("simulate.png"));
setAttribute(Qt::WA_DeleteOnClose);
eepromInterfaceChanged();
if (!(this->isMaximized() || this->isMinimized())) {
if (!(isMaximized() || isMinimized())) {
adjustSize();
}
}
@ -67,27 +65,14 @@ MdiChild::~MdiChild()
delete ui;
}
void MdiChild::qSleep(int ms)
{
if (ms<0)
return;
#if defined WIN32 || !defined __GNUC__
Sleep(uint(ms));
#else
struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
nanosleep(&ts, NULL);
#endif
}
void MdiChild::eepromInterfaceChanged()
{
ui->modelsList->refreshList();
if (GetCurrentFirmware()->getBoard() == BOARD_HORUS && !HORUS_READY_FOR_RELEASE()) {
ui->SimulateTxButton->setEnabled(false);
ui->simulateButton->setEnabled(false);
}
else {
ui->SimulateTxButton->setEnabled(GetCurrentFirmware()->getCapability(Simulation));
ui->simulateButton->setEnabled(GetCurrentFirmware()->getCapability(Simulation));
}
updateTitle();
}
@ -133,7 +118,7 @@ void MdiChild::setModified()
documentWasModified();
}
void MdiChild::on_SimulateTxButton_clicked()
void MdiChild::on_simulateButton_clicked()
{
startSimulation(this, radioData, -1);
}

View file

@ -25,10 +25,10 @@
#include "eeprominterface.h"
namespace Ui {
class mdiChild;
class MdiChild;
}
#define ER9X_EEPROM_FILE_TYPE "ER9X_EEPROM_FILE"
#define ER9X_EEPROM_FILE_TYPE "ER9X_EEPROM_FILE"
#define EEPE_EEPROM_FILE_HEADER "EEPE EEPROM FILE"
#define EEPE_MODEL_FILE_HEADER "EEPE MODEL FILE"
@ -65,8 +65,7 @@ class MdiChild : public QWidget
private slots:
void documentWasModified();
void on_SimulateTxButton_clicked();
void qSleep(int ms);
void on_simulateButton_clicked();
public slots:
void checkAndInitModel(int row);
@ -90,7 +89,7 @@ class MdiChild : public QWidget
QString strippedName(const QString & fullFileName);
bool loadOtxFile(const QString & fileName);
Ui::mdiChild * ui;
Ui::MdiChild * ui;
QString curFile;

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>mdiChild</class>
<widget class="QWidget" name="mdiChild">
<class>MdiChild</class>
<widget class="QWidget" name="MdiChild">
<property name="geometry">
<rect>
<x>0</x>
@ -18,7 +18,7 @@
<widget class="ModelsListWidget" name="modelsList"/>
</item>
<item>
<widget class="QPushButton" name="SimulateTxButton">
<widget class="QPushButton" name="simulateButton">
<property name="text">
<string>Simulate Tx</string>
</property>

View file

@ -356,10 +356,10 @@ void ModulePanel::update()
}
ui->multiSubType->setCurrentIndex(module.subType);
ui->cb_autoBind->setVisible(mask & MASK_MULTIMODULE);
ui->cb_autoBind->setChecked(module.multi.autoBindMode ? Qt::Checked : Qt::Unchecked);
ui->cb_lowPower->setVisible(mask & MASK_MULTIMODULE);
ui->cb_lowPower->setChecked(module.multi.lowPowerMode ? Qt::Checked : Qt::Unchecked);
ui->autoBind->setVisible(mask & MASK_MULTIMODULE);
ui->autoBind->setChecked(module.multi.autoBindMode ? Qt::Checked : Qt::Unchecked);
ui->lowPower->setVisible(mask & MASK_MULTIMODULE);
ui->lowPower->setChecked(module.multi.lowPowerMode ? Qt::Checked : Qt::Unchecked);
if (firmware->getCapability(HasFailsafe)) {

View file

@ -609,14 +609,14 @@
</widget>
</item>
<item row="4" column="4">
<widget class="QCheckBox" name="cb_autoBind">
<widget class="QCheckBox" name="autoBind">
<property name="text">
<string>Bind on startup</string>
</property>
</widget>
</item>
<item row="4" column="5">
<widget class="QCheckBox" name="cb_lowPower">
<widget class="QCheckBox" name="lowPower">
<property name="text">
<string>Low Power</string>
</property>

View file

@ -35,24 +35,42 @@ class DragDropHeader {
};
ModelsListWidget::ModelsListWidget(QWidget * parent):
QListWidget(parent)
QTreeWidget(parent)
{
setFont(QFont("Courier New",12));
radioData = &((MdiChild *)parent)->radioData;
refreshList();
BoardEnum board = GetCurrentFirmware()->getBoard();
QStringList labels;
labels << tr("Index") << tr("Name");
if (!(IS_HORUS(board) || IS_SKY9X(board))) {
labels << tr("Size");
}
setColumnCount(labels.size());
setHeaderLabels(labels);
setColumnWidth(0, 50);
setColumnWidth(2, 100);
connect(this, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OpenEditWindow()));
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(ShowContextMenu(const QPoint&)));
connect(this, SIGNAL(currentRowChanged(int)), this, SLOT(viableModelSelected(int)));
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(onCurrentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
setContextMenuPolicy(Qt::CustomContextMenu);
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::ExtendedSelection);
setDragEnabled(true);
setAcceptDrops(true);
setDragDropOverwriteMode(true);
setDropIndicatorShown(true);
if (!IS_HORUS(board)) {
setIndentation(0);
}
active_highlight_color = palette().color(QPalette::Active, QPalette::Highlight);
radioData = &((MdiChild *)parent)->radioData;
refreshList();
for (int i=0; i<labels.size(); i++) {
resizeColumnToContents(i);
}
}
void ModelsListWidget::ShowContextMenu(const QPoint& pos)
@ -88,6 +106,11 @@ void ModelsListWidget::ShowContextMenu(const QPoint& pos)
contextMenu.exec(globalPos);
}
int ModelsListWidget::currentRow() const
{
return indexOfTopLevelItem(currentItem());
}
void ModelsListWidget::EditModel()
{
((MdiChild *)parent())->modelEdit();
@ -120,30 +143,30 @@ void ModelsListWidget::print()
void ModelsListWidget::setdefault()
{
if (currentRow()==0) return;
if (currentRow() > 0) {
unsigned int currModel = currentRow() - 1;
if (!radioData->models[currModel].isEmpty() && radioData->generalSettings.currModel != currModel) {
radioData->generalSettings.currModel = currModel;
if (!radioData->models[currModel].isEmpty() && radioData->generalSettings.currModelIndex != currModel) {
radioData->setCurrentModel(currModel);
refreshList();
((MdiChild *) parent())->setModified();
}
}
}
void ModelsListWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
dragStartPosition = event->pos();
QListWidget::mousePressEvent(event);
QTreeWidget::mousePressEvent(event);
}
void ModelsListWidget::mouseMoveEvent(QMouseEvent *event)
{
if (!(event->buttons() & Qt::LeftButton))
return;
if ((event->pos() - dragStartPosition).manhattanLength()
< QApplication::startDragDistance())
if ((event->pos() - dragStartPosition).manhattanLength() < QApplication::startDragDistance())
return;
QDrag * drag = new QDrag(this);
@ -156,32 +179,32 @@ void ModelsListWidget::mouseMoveEvent(QMouseEvent *event)
drag->setMimeData(mimeData);
//Qt::DropAction dropAction =
drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
//Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
//if(dropAction==Qt::MoveAction)
// QListWidget::mouseMoveEvent(event);
// QTreeWidget::mouseMoveEvent(event);
}
void ModelsListWidget::saveSelection()
{
currentSelection.current_item = currentItem();
for (int i=0; i<GetEepromInterface()->getMaxModels()+1; ++i)
currentSelection.selected[i] = item(i)->isSelected();
for (int i=0; i<GetEepromInterface()->getMaxModels()+1; ++i) {
currentSelection.selected[i] = selectionModel()->isSelected(model()->index(i, 0));
}
}
void ModelsListWidget::restoreSelection()
{
setCurrentItem(currentSelection.current_item);
for (int i=0; i<GetEepromInterface()->getMaxModels()+1; ++i)
item(i)->setSelected(currentSelection.selected[i]);
for (int i=0; i<GetEepromInterface()->getMaxModels()+1; ++i) {
selectionModel()->select(model()->index(i, 0), currentSelection.selected[i] ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
}
}
void ModelsListWidget::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("application/x-companion"))
{
if (event->mimeData()->hasFormat("application/x-companion")) {
event->acceptProposedAction();
saveSelection();
}
@ -194,19 +217,18 @@ void ModelsListWidget::dragLeaveEvent(QDragLeaveEvent *)
void ModelsListWidget::dragMoveEvent(QDragMoveEvent *event)
{
int row=this->indexAt(event->pos()).row();
int row = indexAt(event->pos()).row();
const QMimeData * mimeData = event->mimeData();
if (mimeData->hasFormat("application/x-companion"))
{
if (mimeData->hasFormat("application/x-companion")) {
QByteArray gmData = mimeData->data("application/x-companion");
event->acceptProposedAction();
clearSelection();
DragDropHeader * header = (DragDropHeader *)gmData.data();
if (row >= 0) {
if (header->general_settings)
item(0)->setSelected(true);
selectionModel()->select(model()->index(0, 0), QItemSelectionModel::Select);
for (int i=row, end=std::min(GetEepromInterface()->getMaxModels()+1, row+header->models_count); i<end; i++)
item(i)->setSelected(true);
selectionModel()->select(model()->index(i, 0), QItemSelectionModel::Select);
}
}
}
@ -220,19 +242,18 @@ void ModelsListWidget::dropEvent(QDropEvent *event)
// QMessageBox::warning(this, tr("Companion"), tr("Index :%1").arg(row));
const QMimeData * mimeData = event->mimeData();
if(mimeData->hasFormat("application/x-companion"))
{
if (mimeData->hasFormat("application/x-companion")) {
QByteArray gmData = mimeData->data("application/x-companion");
if (event->source() && event->dropAction() == Qt::MoveAction)
((ModelsListWidget*)event->source())->doCut(&gmData);
doPaste(&gmData, row);
clearSelection();
setCurrentItem(item(row));
setCurrentItem(topLevelItem(row));
DragDropHeader * header = (DragDropHeader *)gmData.data();
if (header->general_settings)
item(0)->setSelected(true);
selectionModel()->select(model()->index(0, 0), QItemSelectionModel::Select);
for (int i=row, end=std::min(GetEepromInterface()->getMaxModels()+1, row+header->models_count); i<end; i++)
item(i)->setSelected(true);
selectionModel()->select(model()->index(i, 0), QItemSelectionModel::Select);
}
event->acceptProposedAction();
}
@ -240,68 +261,73 @@ void ModelsListWidget::dropEvent(QDropEvent *event)
#ifndef WIN32
void ModelsListWidget::focusInEvent ( QFocusEvent * event )
{
QListWidget::focusInEvent(event);
QTreeWidget::focusInEvent(event);
QPalette palette = this->palette();
palette.setColor(QPalette::Active, QPalette::Highlight, active_highlight_color);
palette.setColor(QPalette::Inactive, QPalette::Highlight, active_highlight_color);
this->setPalette(palette);
setPalette(palette);
}
void ModelsListWidget::focusOutEvent ( QFocusEvent * event )
{
QListWidget::focusOutEvent(event);
QTreeWidget::focusOutEvent(event);
QPalette palette = this->palette();
palette.setColor(QPalette::Active, QPalette::Highlight, palette.color(QPalette::Active, QPalette::Midlight));
palette.setColor(QPalette::Inactive, QPalette::Highlight, palette.color(QPalette::Active, QPalette::Midlight));
this->setPalette(palette);
setPalette(palette);
}
#endif
void ModelsListWidget::refreshList()
{
int current = std::max(0, indexOfTopLevelItem(currentItem()));
clear();
addItem(tr("General Settings"));
QTreeWidgetItem * item = new QTreeWidgetItem();
item->setText(1, tr("General Settings"));
addTopLevelItem(item);
EEPROMInterface * eepromInterface = GetEepromInterface();
BoardEnum board = eepromInterface->getBoard();
// TODO here we calculate the size used by the RLE format, this is clearly not the right place to do that...
int availableEEpromSize = eepromInterface->getEEpromSize() - 64; // let's consider fat
div_t divresult = div(eepromInterface->getSize(radioData->generalSettings), 15);
divresult.quot += (divresult.rem != 0 ? 1 : 0);
availableEEpromSize -= divresult.quot*16;
availableEEpromSize -= 16 * ((eepromInterface->getSize(radioData->generalSettings) + 14) / 15);
for (uint8_t i=0; i<GetEepromInterface()->getMaxModels(); i++) {
QString item = QString().sprintf("%02d: ", i+1);
QTreeWidgetItem * item = new QTreeWidgetItem();
item->setTextAlignment(0, Qt::AlignLeft);
item->setText(0, QString().sprintf("%02d", i+1));
if (!radioData->models[i].isEmpty()) {
QString modelName;
if (strlen(radioData->models[i].name) > 0)
modelName = radioData->models[i].name;
else
modelName = QString().sprintf("Model%02d", i+1);
item += modelName;
item->setText(1, modelName);
if (!IS_SKY9X(board) && !IS_HORUS(board)) {
item += QString(GetCurrentFirmware()->getCapability(ModelName)-modelName.size(), ' ');
int size = eepromInterface->getSize(radioData->models[i]);
item += QString().sprintf("%5d", size);
divresult = div(size, 15);
divresult.quot += (divresult.rem != 0 ? 1 : 0);
availableEEpromSize -= divresult.quot*16;
if (i == radioData->generalSettings.currModel) {
// TODO why?
availableEEpromSize -= divresult.quot*16;
item->setText(2, QString().sprintf("%5d", size));
size = 16 * ((size + 14) / 15);
availableEEpromSize -= size;
if (i == radioData->generalSettings.currModelIndex) {
// Because we need this space for a TEMP model each time we have to write it again
availableEEpromSize -= size;
}
}
if (i == radioData->generalSettings.currModelIndex) {
QFont font = item->font(0);
font.setBold(true);
for (int j=0; j<columnCount(); j++) {
item->setFont(j, font);
}
}
}
addItem(item);
addTopLevelItem(item);
}
if (radioData->generalSettings.currModel < (unsigned int)eepromInterface->getMaxModels()) {
QFont f = QFont("Courier New", 12);
f.setBold(true);
this->item(radioData->generalSettings.currModel+1)->setFont(f);
}
selectionModel()->select(model()->index(current, 0), QItemSelectionModel::Current | QItemSelectionModel::Select | QItemSelectionModel::Rows);
setCurrentItem(topLevelItem(current));
if (!IS_SKY9X(board) && !IS_HORUS(board)) {
((MdiChild*)parent())->setEEpromAvail((availableEEpromSize/16)*15);
@ -314,7 +340,8 @@ void ModelsListWidget::cut()
deleteSelected(false);
}
void ModelsListWidget::confirmDelete() {
void ModelsListWidget::confirmDelete()
{
deleteSelected(true);
}
@ -331,24 +358,27 @@ void ModelsListWidget::deleteSelected(bool ask=true)
selModel=index.row()-1;
}
}
if (isModel==true) {
if (radioData->generalSettings.currModel != selModel) {
if (isModel) {
if (radioData->generalSettings.currModelIndex != selModel) {
ret = QMessageBox::warning(this, "Companion", tr("Delete Selected Models?"), QMessageBox::Yes | QMessageBox::No);
} else {
}
else {
ret = QMessageBox::warning(this, "Companion", tr("Cannot delete default model."), QMessageBox::Ok);
}
}
}
if (ret == QMessageBox::Yes) {
foreach (QModelIndex index, this->selectionModel()->selectedIndexes()) {
if (index.row()>0 && radioData->generalSettings.currModel!=(unsigned int)(index.row()-1)) {
if (index.row() > 0 && radioData->generalSettings.currModelIndex != (unsigned int)(index.row()-1)) {
radioData->models[index.row()-1].clear();
((MdiChild *)parent())->setModified();
} else if (index.row()>0) {
}
else if (index.row()>0) {
if (ask) {
ret = QMessageBox::warning(this, "Companion", tr("Cannot delete default model."), QMessageBox::Ok);
} else {
ret = QMessageBox::warning(this, "Companion", tr("Cannot cut default model."), QMessageBox::Ok);
QMessageBox::warning(this, "Companion", tr("Cannot delete default model."), QMessageBox::Ok);
}
else {
QMessageBox::warning(this, "Companion", tr("Cannot cut default model."), QMessageBox::Ok);
}
}
}
@ -360,7 +390,7 @@ void ModelsListWidget::doCut(QByteArray *gmData)
bool modified = false;
DragDropHeader * header = (DragDropHeader *)gmData->data();
for (int i=0; i<header->models_count; i++) {
if (radioData->generalSettings.currModel != (unsigned int)header->models[i]-1) {
if (radioData->generalSettings.currModelIndex != (unsigned int)header->models[i]-1) {
radioData->models[header->models[i]-1].clear();
modified=true;
}
@ -374,8 +404,10 @@ void ModelsListWidget::doCopy(QByteArray *gmData)
{
DragDropHeader header;
foreach(QModelIndex index, this->selectionModel()->selectedIndexes())
{
qDebug() << selectionModel()->selectedIndexes();
foreach(QModelIndex index, selectionModel()->selectedIndexes()) {
char column = index.column();
if (column == 0) {
char row = index.row();
if (!row) {
header.general_settings = true;
@ -388,6 +420,7 @@ void ModelsListWidget::doCopy(QByteArray *gmData)
gmData->append((char *) &radioData->models[row - 1], sizeof(ModelData));
}
}
}
gmData->prepend((char *)&header, sizeof(header));
}
@ -413,11 +446,13 @@ void ModelsListWidget::doPaste(QByteArray *gmData, int index)
int ret, modified=0;
if(!id) id++;
while((i<gmData->size()) && (id<=GetEepromInterface()->getMaxModels())) {
while (i<gmData->size() && id<=GetEepromInterface()->getMaxModels()) {
qDebug() << i << gmData->size();
char c = *gData;
i++;
gData++;
if(c=='G') { //General settings
if (c == 'G') {
// General settings
ret = QMessageBox::question(this, "Companion", tr("Do you want to overwrite radio general settings?"),
QMessageBox::Yes | QMessageBox::No);
if (ret == QMessageBox::Yes) {
@ -427,12 +462,14 @@ void ModelsListWidget::doPaste(QByteArray *gmData, int index)
gData += sizeof(GeneralSettings);
i += sizeof(GeneralSettings);
}
else { //model data
else {
// Model data
if (!radioData->models[id-1].isEmpty()) {
ret = QMessageBox::question(this, "Companion", tr("You are pasting on an not empty model, are you sure?"),
QMessageBox::Yes | QMessageBox::No);
if (ret == QMessageBox::Yes) {
radioData->models[id-1] = *((ModelData *)gData);
strcpy(radioData->models[id-1].filename, radioData->getNextModelFilename().toStdString().c_str());
gData += sizeof(ModelData);
i += sizeof(ModelData);
id++;
@ -446,6 +483,7 @@ void ModelsListWidget::doPaste(QByteArray *gmData, int index)
}
else {
radioData->models[id-1] = *((ModelData *)gData);
strcpy(radioData->models[id-1].filename, radioData->getNextModelFilename().toStdString().c_str());
gData += sizeof(ModelData);
i += sizeof(ModelData);
id++;
@ -473,19 +511,19 @@ void ModelsListWidget::paste()
const QMimeData * mimeData = clipboard->mimeData();
QByteArray gmData = mimeData->data("application/x-companion");
doPaste(&gmData,this->currentRow());
doPaste(&gmData, currentRow());
}
}
void ModelsListWidget::duplicate()
{
int i = this->currentRow();
if(i && i<GetEepromInterface()->getMaxModels())
{
if (i && i<GetEepromInterface()->getMaxModels()) {
ModelData * model = &radioData->models[i-1];
while (i<GetEepromInterface()->getMaxModels()) {
if (radioData->models[i].isEmpty()) {
radioData->models[i] = *model;
strcpy(radioData->models[i].filename, radioData->getNextModelFilename().toStdString().c_str());
((MdiChild *)parent())->setModified();
break;
}
@ -504,48 +542,41 @@ bool ModelsListWidget::hasSelection()
void ModelsListWidget::keyPressEvent(QKeyEvent *event)
{
if(event->matches(QKeySequence::Delete))
{
if (event->matches(QKeySequence::Delete)) {
deleteSelected();
return;
}
if(event->matches(QKeySequence::Cut))
{
if (event->matches(QKeySequence::Cut)) {
cut();
return;
}
if(event->matches(QKeySequence::Copy))
{
if (event->matches(QKeySequence::Copy)) {
copy();
return;
}
if(event->matches(QKeySequence::Paste))
{
if (event->matches(QKeySequence::Paste)) {
paste();
return;
}
if(event->matches(QKeySequence::Underline))
{
if (event->matches(QKeySequence::Underline)) {
duplicate();
return;
}
QListWidget::keyPressEvent(event);//run the standard event in case we didn't catch an action
QTreeWidget::keyPressEvent(event);//run the standard event in case we didn't catch an action
}
void ModelsListWidget::viableModelSelected(int idx)
void ModelsListWidget::onCurrentItemChanged(QTreeWidgetItem * current, QTreeWidgetItem *)
{
int index = indexOfTopLevelItem(current);
if (!isVisible())
((MdiChild*)parent())->viableModelSelected(false);
else if (idx<1)
else if (index<1)
((MdiChild*)parent())->viableModelSelected(false);
else
((MdiChild*)parent())->viableModelSelected(!radioData->models[currentRow()-1].isEmpty());
}

View file

@ -26,11 +26,11 @@
struct CurrentSelection
{
QListWidgetItem *current_item;
QTreeWidgetItem * current_item;
bool selected[CPN_MAX_MODELS+1];
};
class ModelsListWidget : public QListWidget
class ModelsListWidget : public QTreeWidget
{
Q_OBJECT
@ -40,6 +40,7 @@ public:
bool hasSelection();
void keyPressEvent(QKeyEvent * event);
bool hasPasteData();
int currentRow() const;
protected:
void dropEvent(QDropEvent *event);
@ -69,7 +70,7 @@ public slots:
void setdefault();
void deleteSelected(bool ask);
void confirmDelete();
void viableModelSelected(int idx);
void onCurrentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *);
private:
void doCut(QByteArray *gmData);

View file

@ -72,8 +72,7 @@ int StorageSdcard::readOtx(const QString & path)
// go trough all files in an archive
QRegularExpression regexModel("MODELS/\\w+.bin", QRegularExpression::CaseInsensitiveOption);
for (unsigned int i = 0; i < mz_zip_reader_get_num_files(&zip_archive); i++)
{
for (unsigned int i = 0; i < mz_zip_reader_get_num_files(&zip_archive); i++) {
mz_zip_archive_file_stat file_stat;
if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat)) {
lastErrorMessage = QObject::tr("mz_zip_reader_file_stat() failed!");
@ -117,9 +116,9 @@ int StorageSdcard::readOtx(const QString & path)
else {
qDebug() << "Unknown file " << filename;
}
}
mz_zip_reader_end(&zip_archive);
return 0;
}

View file

@ -70,7 +70,7 @@ void saveRadioSettings(GeneralSettings & settings, global_settings & gs)
Calibration p3Calib(settings.calibMid[6], settings.calibSpanNeg[6], settings.calibSpanPos[6]);
gs.calibration(calibration(rudderCalib, throttleCalib, aileronCalib, elevatorCalib, p1Calib, p2Calib, p3Calib));
// TODO BSS settings.currModel;
// TODO BSS settings.currModelIndex;
gs.contrast(settings.contrast);
gs.battery(battery(settings.txVoltageCalibration, settings.vBatWarn));