5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
25 #elif defined __GNUC__
32 #include "simulatorinterface.h"
33 #include "simulatormainwindow.h"
34 #include "storage/sdcard.h"
37 #include <QMessageBox>
39 using namespace Helpers
;
41 Stopwatch
gStopwatch("global");
43 const QColor colors
[CPN_MAX_CURVES
] = {
82 GVarGroup::GVarGroup(QCheckBox
* weightGV
, QAbstractSpinBox
* weightSB
, QComboBox
* weightCB
, int & weight
, const ModelData
& model
, const int deflt
, const int mini
, const int maxi
, const double step
, bool allowGvars
):
86 sb(dynamic_cast<QSpinBox
*>(weightSB
)),
87 dsb(dynamic_cast<QDoubleSpinBox
*>(weightSB
)),
93 if (allowGvars
&& getCurrentFirmware()->getCapability(Gvars
)) {
94 Helpers::populateGVCB(*weightCB
, weight
, model
);
95 connect(weightGV
, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int)));
96 connect(weightCB
, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged()));
100 if (weight
> maxi
|| weight
< mini
) {
107 if (weight
>maxi
|| weight
<mini
) {
109 weightGV
->setChecked(true);
115 weightGV
->setChecked(false);
121 sb
->setMinimum(mini
);
122 sb
->setMaximum(maxi
);
126 dsb
->setMinimum(mini
*step
);
127 dsb
->setMaximum(maxi
*step
);
128 dsb
->setValue(val
*step
);
131 connect(weightSB
, SIGNAL(editingFinished()), this, SLOT(valuesChanged()));
136 void GVarGroup::gvarCBChanged(int state
)
138 weightCB
->setVisible(state
);
140 weightSB
->setVisible(!state
);
142 weightSB
->setVisible(!state
);
146 void GVarGroup::valuesChanged()
149 if (weightGV
->isChecked())
150 weight
= weightCB
->itemData(weightCB
->currentIndex()).toInt();
152 weight
= sb
->value();
154 weight
= round(dsb
->value()/step
);
164 CurveGroup::CurveGroup(QComboBox
* curveTypeCB
, QCheckBox
* curveGVarCB
, QComboBox
* curveValueCB
, QSpinBox
* curveValueSB
, CurveReference
& curve
, const ModelData
& model
, unsigned int flags
):
166 curveTypeCB(curveTypeCB
),
167 curveGVarCB(curveGVarCB
),
168 curveValueCB(curveValueCB
),
169 curveValueSB(curveValueSB
),
176 if (!(flags
& HIDE_DIFF
)) curveTypeCB
->addItem(tr("Diff"), 0);
177 if (!(flags
& HIDE_EXPO
)) curveTypeCB
->addItem(tr("Expo"), 1);
178 curveTypeCB
->addItem(tr("Func"), 2);
179 curveTypeCB
->addItem(tr("Curve"), 3);
181 curveValueCB
->setMaxVisibleItems(10);
183 connect(curveTypeCB
, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int)));
184 connect(curveGVarCB
, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int)));
185 connect(curveValueCB
, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged()));
186 connect(curveValueSB
, SIGNAL(editingFinished()), this, SLOT(valuesChanged()));
191 void CurveGroup::update()
195 int found
= curveTypeCB
->findData(curve
.type
);
196 if (found
< 0) found
= 0;
197 curveTypeCB
->setCurrentIndex(found
);
199 if (curve
.type
== CurveReference::CURVE_REF_DIFF
|| curve
.type
== CurveReference::CURVE_REF_EXPO
) {
200 curveGVarCB
->setVisible(getCurrentFirmware()->getCapability(Gvars
));
201 if (curve
.value
> 100 || curve
.value
< -100) {
202 curveGVarCB
->setChecked(true);
203 if (lastType
!= CurveReference::CURVE_REF_DIFF
&& lastType
!= CurveReference::CURVE_REF_EXPO
) {
204 lastType
= curve
.type
;
205 Helpers::populateGVCB(*curveValueCB
, curve
.value
, model
);
207 curveValueCB
->show();
208 curveValueSB
->hide();
211 curveGVarCB
->setChecked(false);
212 curveValueSB
->setMinimum(-100);
213 curveValueSB
->setMaximum(100);
214 curveValueSB
->setValue(curve
.value
);
215 curveValueSB
->show();
216 curveValueCB
->hide();
221 curveValueSB
->hide();
222 curveValueCB
->show();
223 switch (curve
.type
) {
224 case CurveReference::CURVE_REF_FUNC
:
225 if (lastType
!= curve
.type
) {
226 lastType
= curve
.type
;
227 curveValueCB
->clear();
228 for (int i
=0; i
<=6/*TODO constant*/; i
++) {
229 curveValueCB
->addItem(CurveReference(CurveReference::CURVE_REF_FUNC
, i
).toString(&model
, false));
232 curveValueCB
->setCurrentIndex(curve
.value
);
234 case CurveReference::CURVE_REF_CUSTOM
:
236 int numcurves
= getCurrentFirmware()->getCapability(NumCurves
);
237 if (lastType
!= curve
.type
) {
238 lastType
= curve
.type
;
239 curveValueCB
->clear();
240 for (int i
= ((flags
& HIDE_NEGATIVE_CURVES
) ? 0 : -numcurves
); i
<=numcurves
; i
++) {
241 curveValueCB
->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM
, i
).toString(&model
, false), i
);
242 if (i
== curve
.value
) {
243 curveValueCB
->setCurrentIndex(curveValueCB
->count() - 1);
257 void CurveGroup::gvarCBChanged(int state
)
261 curve
.value
= 10000+1; // TODO constant in EEpromInterface ...
262 lastType
= -1; // quickfix for issue #3518: force refresh of curveValueCB at next update() to set current index to GV1
265 curve
.value
= 0; // TODO could be better
272 void CurveGroup::typeChanged(int value
)
275 int type
= curveTypeCB
->itemData(curveTypeCB
->currentIndex()).toInt();
278 curve
= CurveReference(CurveReference::CURVE_REF_DIFF
, 0);
281 curve
= CurveReference(CurveReference::CURVE_REF_EXPO
, 0);
284 curve
= CurveReference(CurveReference::CURVE_REF_FUNC
, 0);
287 curve
= CurveReference(CurveReference::CURVE_REF_CUSTOM
, 0);
295 void CurveGroup::valuesChanged()
298 switch (curveTypeCB
->itemData(curveTypeCB
->currentIndex()).toInt()) {
303 if (curveGVarCB
->isChecked())
304 value
= curveValueCB
->itemData(curveValueCB
->currentIndex()).toInt();
306 value
= curveValueSB
->value();
307 curve
= CurveReference(curveTypeCB
->itemData(curveTypeCB
->currentIndex()).toInt() == 0 ? CurveReference::CURVE_REF_DIFF
: CurveReference::CURVE_REF_EXPO
, value
);
311 curve
= CurveReference(CurveReference::CURVE_REF_FUNC
, curveValueCB
->currentIndex());
314 curve
= CurveReference(CurveReference::CURVE_REF_CUSTOM
, curveValueCB
->itemData(curveValueCB
->currentIndex()).toInt());
323 * Helpers namespace functions
326 void Helpers::populateGVCB(QComboBox
& b
, int value
, const ModelData
& model
)
328 int count
= getCurrentFirmware()->getCapability(Gvars
);
332 for (int i
=-count
; i
<=-1; i
++) {
333 int16_t gval
= (int16_t)(-10000+i
);
334 b
.addItem("-" + RawSource(SOURCE_TYPE_GVAR
, abs(i
)-1).toString(&model
), gval
);
337 for (int i
=1; i
<=count
; i
++) {
338 int16_t gval
= (int16_t)(10000+i
);
339 b
.addItem(RawSource(SOURCE_TYPE_GVAR
, i
-1).toString(&model
), gval
);
342 b
.setCurrentIndex(b
.findData(value
));
343 if (b
.currentIndex() == -1)
344 b
.setCurrentIndex(count
);
347 // Returns Diff/Expo/Weight/Offset adjustment value as either a percentage or a global variable name.
348 QString
Helpers::getAdjustmentString(int16_t val
, const ModelData
* model
, bool sign
)
351 if (val
>= -10000 && val
<= 10000) {
358 ret
= RawSource(SOURCE_TYPE_GVAR
, abs(val
) - 10001).toString(model
);
367 // TODO: Move lookup to GVarData class (w/out combobox)
368 void Helpers::populateGvarUseCB(QComboBox
* b
, unsigned int phase
)
370 b
->addItem(QCoreApplication::translate("GVarData", "Own value"));
371 for (int i
=0; i
<getCurrentFirmware()->getCapability(FlightModes
); i
++) {
372 if (i
!= (int)phase
) {
373 b
->addItem(QCoreApplication::translate("GVarData", "Flight mode %1 value").arg(i
));
378 void Helpers::populateFileComboBox(QComboBox
* b
, const QSet
<QString
> & set
, const QString
& current
)
384 // Convert set into list and sort it alphabetically case insensitive
385 QStringList list
= QStringList::fromSet(set
);
386 qSort(list
.begin(), list
.end(), caseInsensitiveLessThan
);
387 foreach (QString entry
, list
) {
389 if (entry
== current
) {
390 b
->setCurrentIndex(b
->count()-1);
395 if (!added
&& !current
.isEmpty()) {
397 b
->setCurrentIndex(b
->count()-1);
401 void Helpers::getFileComboBoxValue(QComboBox
* b
, char * dest
, int length
)
403 memset(dest
, 0, length
+1);
404 if (b
->currentText() != "----") {
405 strncpy(dest
, b
->currentText().toLatin1(), length
);
409 void Helpers::addRawSourceItems(QStandardItemModel
* itemModel
, const RawSourceType
& type
, int count
, const GeneralSettings
* const generalSettings
,
410 const ModelData
* const model
, const int start
)
412 for (int i
= start
; i
< start
+ count
; i
++) {
413 RawSource src
= RawSource(type
, i
);
414 if (!src
.isAvailable(model
, generalSettings
, getCurrentBoard()))
417 QStandardItem
* modelItem
= new QStandardItem(src
.toString(model
, generalSettings
));
418 modelItem
->setData(src
.toValue(), Qt::UserRole
);
419 itemModel
->appendRow(modelItem
);
423 QStandardItemModel
* Helpers::getRawSourceItemModel(const GeneralSettings
* const generalSettings
, const ModelData
* const model
, unsigned int flags
)
425 QStandardItemModel
* itemModel
= new QStandardItemModel();
426 Boards board
= Boards(getCurrentBoard());
427 Firmware
* fw
= getCurrentFirmware();
429 if (flags
& POPULATE_NONE
) {
430 addRawSourceItems(itemModel
, SOURCE_TYPE_NONE
, 1, generalSettings
, model
);
433 if (flags
& POPULATE_SCRIPT_OUTPUTS
) {
434 for (int i
=0; i
< getCurrentFirmware()->getCapability(LuaScripts
); i
++) {
435 addRawSourceItems(itemModel
, SOURCE_TYPE_LUA_OUTPUT
, fw
->getCapability(LuaOutputsPerScript
), generalSettings
, model
, i
* 16);
439 if (model
&& (flags
& POPULATE_VIRTUAL_INPUTS
)) {
440 addRawSourceItems(itemModel
, SOURCE_TYPE_VIRTUAL_INPUT
, fw
->getCapability(VirtualInputs
), generalSettings
, model
);
443 if (flags
& POPULATE_SOURCES
) {
444 int totalSources
= CPN_MAX_STICKS
+ board
.getCapability(Board::Pots
) + board
.getCapability(Board::Sliders
) + board
.getCapability(Board::MouseAnalogs
);
445 addRawSourceItems(itemModel
, SOURCE_TYPE_STICK
, totalSources
, generalSettings
, model
);
446 addRawSourceItems(itemModel
, SOURCE_TYPE_ROTARY_ENCODER
, fw
->getCapability(RotaryEncoders
), generalSettings
, model
);
449 if (flags
& POPULATE_TRIMS
) {
450 addRawSourceItems(itemModel
, SOURCE_TYPE_TRIM
, board
.getCapability(Board::NumTrims
), generalSettings
, model
);
453 if (flags
& POPULATE_SOURCES
) {
454 addRawSourceItems(itemModel
, SOURCE_TYPE_MAX
, 1, generalSettings
, model
);
457 if (flags
& POPULATE_SWITCHES
) {
458 addRawSourceItems(itemModel
, SOURCE_TYPE_SWITCH
, board
.getCapability(Board::Switches
), generalSettings
, model
);
459 addRawSourceItems(itemModel
, SOURCE_TYPE_CUSTOM_SWITCH
, fw
->getCapability(LogicalSwitches
), generalSettings
, model
);
462 if (flags
& POPULATE_SOURCES
) {
463 addRawSourceItems(itemModel
, SOURCE_TYPE_CYC
, CPN_MAX_CYC
, generalSettings
, model
);
464 addRawSourceItems(itemModel
, SOURCE_TYPE_PPM
, fw
->getCapability(TrainerInputs
), generalSettings
, model
);
465 addRawSourceItems(itemModel
, SOURCE_TYPE_CH
, fw
->getCapability(Outputs
), generalSettings
, model
);
468 if (flags
& POPULATE_TELEMETRY
) {
470 if (IS_ARM(board
.getBoardType())) {
471 addRawSourceItems(itemModel
, SOURCE_TYPE_SPECIAL
, 5, generalSettings
, model
);
472 count
= CPN_MAX_SENSORS
* 3;
475 count
= ((flags
& POPULATE_TELEMETRYEXT
) ? TELEMETRY_SOURCES_STATUS_COUNT
: TELEMETRY_SOURCES_COUNT
);
478 addRawSourceItems(itemModel
, SOURCE_TYPE_TELEMETRY
, count
, generalSettings
, model
);
481 if (flags
& POPULATE_GVARS
) {
482 addRawSourceItems(itemModel
, SOURCE_TYPE_GVAR
, fw
->getCapability(Gvars
), generalSettings
, model
);
488 QString
image2qstring(QImage image
)
493 image
.save(&buffer
, "PNG");
496 int size
=buffer
.data().size();
497 for (int j
= 0; j
< size
; j
++) {
498 b
=buffer
.data().at(j
);
499 ImageStr
+= QString("%1").arg(b
&0xff, 2, 16, QChar('0'));
504 int findmult(float value
, float base
)
506 int vvalue
= value
*10;
511 for (int i
=8; i
>=0; i
--) {
512 if (vvalue
/vbase
>= (1<<i
)) {
521 // TODO: Move to FrSkyAlarmData
522 QString
getFrSkyAlarmType(int alarm
)
526 return QCoreApplication::translate("FrSkyAlarmData", "Yellow");
528 return QCoreApplication::translate("FrSkyAlarmData", "Orange");
530 return QCoreApplication::translate("FrSkyAlarmData", "Red");
536 // TODO: move to FrSkyChannelData
537 QString
getFrSkyUnits(int units
)
541 return QCoreApplication::translate("FrSkyChannelData", "---");
543 return QCoreApplication::translate("FrSkyChannelData", "V");
549 int theme_set
= g
.theme();
571 CompanionIcon::CompanionIcon(const QString
&baseimage
)
573 static QString theme
= getTheme();
574 addFile(":/themes/"+theme
+"/16/"+baseimage
, QSize(16,16));
575 addFile(":/themes/"+theme
+"/24/"+baseimage
, QSize(24,24));
576 addFile(":/themes/"+theme
+"/32/"+baseimage
, QSize(32,32));
577 addFile(":/themes/"+theme
+"/48/"+baseimage
, QSize(48,48));
580 void startSimulation(QWidget
* parent
, RadioData
& radioData
, int modelIdx
)
582 QString fwId
= SimulatorLoader::findSimulatorByFirmwareName(getCurrentFirmware()->getId());
583 if (fwId
.isEmpty()) {
584 QMessageBox::warning(NULL
,
586 QCoreApplication::translate("Companion", "Simulator for this firmware is not yet available"));
590 RadioData
* simuData
= new RadioData(radioData
);
591 unsigned int flags
= 0;
594 flags
|= SIMULATOR_FLAGS_NOTX
;
595 simuData
->setCurrentModel(modelIdx
);
598 SimulatorMainWindow
* dialog
= new SimulatorMainWindow(parent
, fwId
, flags
);
599 dialog
->setWindowModality(Qt::ApplicationModal
);
600 dialog
->setAttribute(Qt::WA_DeleteOnClose
);
602 QObject::connect(dialog
, &SimulatorMainWindow::destroyed
, [simuData
] (void) {
603 // TODO simuData and Horus tmp directory is deleted on simulator close OR we could use it to get back data from the simulation
608 if (dialog
->getExitStatus(&resultMsg
)) {
609 if (resultMsg
.isEmpty())
610 resultMsg
= QCoreApplication::translate("Companion", "Uknown error during Simulator startup.");
611 QMessageBox::critical(NULL
, QCoreApplication::translate("Companion", "Simulator Error"), resultMsg
);
612 dialog
->deleteLater();
614 else if (dialog
->setRadioData(simuData
)) {
618 QMessageBox::critical(NULL
, QCoreApplication::translate("Companion", "Data Load Error"), QCoreApplication::translate("Companion", "Error occurred while starting simulator."));
619 dialog
->deleteLater();
623 QPixmap
makePixMap(const QImage
& image
)
625 Firmware
* firmware
= getCurrentFirmware();
626 QImage result
= image
.scaled(firmware
->getCapability(LcdWidth
), firmware
->getCapability(LcdHeight
));
627 if (firmware
->getCapability(LcdDepth
) == 4) {
628 result
= result
.convertToFormat(QImage::Format_RGB32
);
629 for (int i
= 0; i
< result
.width(); ++i
) {
630 for (int j
= 0; j
< result
.height(); ++j
) {
631 QRgb col
= result
.pixel(i
, j
);
632 int gray
= qGray(col
);
633 result
.setPixel(i
, j
, qRgb(gray
, gray
, gray
));
638 result
= result
.convertToFormat(QImage::Format_Mono
);
641 return QPixmap::fromImage(result
);
645 int version2index(const QString
& version
)
649 QString mainVersion
= version
;
650 if (version
.contains("RC")) {
651 parts
= version
.split("RC");
652 result
= parts
[1].toInt() + 900; // RC0 = 900; RC1=901,..
653 mainVersion
= parts
[0];
655 else if (version
.contains("N")) {
656 parts
= version
.split("N");
657 result
= parts
[1].toInt(); // nightly build up to 899
658 mainVersion
= parts
[0];
660 parts
= mainVersion
.split('.');
661 if (parts
.size() > 2)
662 result
+= 1000 * parts
[2].toInt();
663 if (parts
.size() > 1)
664 result
+= 100000 * parts
[1].toInt();
665 if (parts
.size() > 0)
666 result
+= 10000000 * parts
[0].toInt();
670 const QString
index2version(int index
)
673 QString
templt("%1.%2.%3");
674 if (index
>= 19900000) {
675 int nightly
= index
% 1000;
677 int revision
= index
% 100;
679 int minor
= index
% 100;
680 int major
= index
/ 100;
681 result
= templt
.arg(major
).arg(minor
).arg(revision
);
682 if (nightly
> 0 && nightly
< 900) {
683 result
+= "N" + QString::number(nightly
);
685 else if (nightly
>= 900 && nightly
< 1000) {
686 result
+= "RC" + QString::number(nightly
-900);
689 else if (index
>= 19900) {
690 int revision
= index
% 100;
692 int minor
= index
% 100;
693 int major
= index
/ 100;
694 result
= templt
.arg(major
).arg(minor
).arg(revision
);
699 bool qunlink(const QString
& fileName
)
701 return QFile::remove(fileName
);
704 QString
generateProcessUniqueTempFileName(const QString
& fileName
)
706 QString sanitizedFileName
= fileName
;
707 sanitizedFileName
.remove('/');
708 return QDir::tempPath() + QString("/%1-").arg(QCoreApplication::applicationPid()) + sanitizedFileName
;
711 bool isTempFileName(const QString
& fileName
)
713 return fileName
.startsWith(QDir::tempPath());
716 QString
getSoundsPath(const GeneralSettings
&generalSettings
)
718 QString path
= g
.profile
[g
.id()].sdPath() + "/SOUNDS/";
719 QString lang
= generalSettings
.ttsLanguage
;
726 QSet
<QString
> getFilesSet(const QString
&path
, const QStringList
&filter
, int maxLen
)
728 QSet
<QString
> result
;
731 foreach (QString filename
, dir
.entryList(filter
, QDir::Files
)) {
732 QFileInfo
file(filename
);
733 QString name
= file
.completeBaseName();
734 if (name
.length() <= maxLen
) {
742 bool caseInsensitiveLessThan(const QString
&s1
, const QString
&s2
)
744 return s1
.toLower() < s2
.toLower();
747 bool GpsGlitchFilter::isGlitch(GpsCoord coord
)
749 if ((fabs(coord
.latitude
) < 0.1) && (fabs(coord
.longitude
) < 0.1)) {
754 if (fabs(coord
.latitude
- lastLat
) > 0.01) {
755 // qDebug() << "GpsGlitchFilter(): latitude glitch " << coord.latitude << lastLat;
756 if ( ++glitchCount
< 10) {
760 if (fabs(coord
.longitude
- lastLon
) > 0.01) {
761 // qDebug() << "GpsGlitchFilter(): longitude glitch " << coord.longitude << lastLon;
762 if ( ++glitchCount
< 10) {
767 lastLat
= coord
.latitude
;
768 lastLon
= coord
.longitude
;
774 bool GpsLatLonFilter::isValid(GpsCoord coord
)
776 if (lastLat
== coord
.latitude
) {
779 if (lastLon
== coord
.longitude
) {
782 lastLat
= coord
.latitude
;
783 lastLon
= coord
.longitude
;
787 double toDecimalCoordinate(const QString
& value
)
789 if (value
.isEmpty()) return 0.0;
790 double temp
= int(value
.left(value
.length()-1).toDouble() / 100);
791 double result
= temp
+ (value
.left(value
.length() - 1).toDouble() - temp
* 100) / 60.0;
792 QChar direction
= value
.at(value
.size()-1);
793 if ((direction
== 'S') || (direction
== 'W')) {
799 GpsCoord
extractGpsCoordinates(const QString
& position
)
802 QStringList parts
= position
.split(' ');
803 if (parts
.size() == 2) {
804 QString value
= parts
.at(0).trimmed();
805 QChar direction
= value
.at(value
.size()-1);
806 if (direction
== 'E' || direction
== 'W') {
807 // OpenTX 2.1 format: "NNN.MMM[E|W] NNN.MMM[N|S]" <longitude> <latitude>
808 result
.latitude
= toDecimalCoordinate(parts
.at(1).trimmed());
809 result
.longitude
= toDecimalCoordinate(parts
.at(0).trimmed());
812 // OpenTX 2.2 format: "DD.DDDDDD DD.DDDDDD" <latitude> <longitude> both in Signed degrees format (DDD.dddd)
813 // Precede South latitudes and West longitudes with a minus sign.
814 // Latitudes range from -90 to 90.
815 // Longitudes range from -180 to 180.
816 result
.latitude
= parts
.at(0).trimmed().toDouble();
817 result
.longitude
= parts
.at(1).trimmed().toDouble();
823 TableLayout::TableLayout(QWidget
* parent
, int rowCount
, const QStringList
& headerLabels
)
825 #if defined(TABLE_LAYOUT)
826 tableWidget
= new QTableWidget(parent
);
827 QVBoxLayout
* layout
= new QVBoxLayout();
828 layout
->addWidget(tableWidget
);
829 layout
->setContentsMargins(0, 0, 0, 0);
830 parent
->setLayout(layout
);
832 tableWidget
->setRowCount(rowCount
);
833 tableWidget
->setColumnCount(headerLabels
.size());
834 tableWidget
->setShowGrid(false);
835 tableWidget
->verticalHeader()->setVisible(false);
836 tableWidget
->setSelectionBehavior(QAbstractItemView::SelectRows
);
837 tableWidget
->setSelectionMode(QAbstractItemView::NoSelection
);
838 tableWidget
->setFrameStyle(QFrame::NoFrame
| QFrame::Plain
);
839 tableWidget
->setStyleSheet("QTableWidget {background-color: transparent;}");
840 tableWidget
->setHorizontalHeaderLabels(headerLabels
);
842 gridWidget
= new QGridLayout(parent
);
845 foreach(QString text
, headerLabels
) {
846 QLabel
*label
= new QLabel();
847 label
->setFrameShape(QFrame::Panel
);
848 label
->setFrameShadow(QFrame::Raised
);
849 label
->setMidLineWidth(0);
850 label
->setAlignment(Qt::AlignCenter
);
852 label
->setText(text
);
854 // label->setMinimumWidth(100);
855 gridWidget
->addWidget(label
, 0, col
++);
860 void TableLayout::addWidget(int row
, int column
, QWidget
* widget
)
862 #if defined(TABLE_LAYOUT)
863 QHBoxLayout
* layout
= new QHBoxLayout(tableWidget
);
864 layout
->addWidget(widget
);
865 addLayout(row
, column
, layout
);
867 gridWidget
->addWidget(widget
, row
+ 1, column
);
871 void TableLayout::addLayout(int row
, int column
, QLayout
* layout
)
873 #if defined(TABLE_LAYOUT)
874 layout
->setContentsMargins(1, 3, 1, 3);
875 QWidget
* containerWidget
= new QWidget(tableWidget
);
876 containerWidget
->setLayout(layout
);
877 tableWidget
->setCellWidget(row
, column
, containerWidget
);
879 gridWidget
->addLayout(layout
, row
+ 1, column
);
883 void TableLayout::resizeColumnsToContents()
885 #if defined(TABLE_LAYOUT)
886 tableWidget
->resizeColumnsToContents();
891 void TableLayout::setColumnWidth(int col
, int width
)
893 #if defined(TABLE_LAYOUT)
894 tableWidget
->setColumnWidth(col
, width
);
899 void TableLayout::pushRowsUp(int row
)
901 #if defined(TABLE_LAYOUT)
904 QSpacerItem
* spacer
= new QSpacerItem(0, 0, QSizePolicy::Minimum
, QSizePolicy::Expanding
);
905 gridWidget
->addItem(spacer
, row
, 0);
908 // addDoubleSpring(gridLayout, 5, num_fsw+1);