Exemple #1
0
LabelLayout::LabelLayout(analyzer_header *header, bool enable_reorder, bool enable_drag, FilterTabWidget *filters, QWidget *parent) : QHBoxLayout(parent)
{
    setSizeConstraint(QLayout::SetMinAndMaxSize);

    if(enable_reorder && enable_drag)
    {
        m_spacer_l = new QSpacerItem(20, 40, QSizePolicy::Expanding, QSizePolicy::Expanding);
        addSpacerItem(m_spacer_l);
    }
    else m_spacer_l = NULL;

    m_spacer_r = new QSpacerItem(20, 40, QSizePolicy::Expanding, QSizePolicy::Expanding);
    addSpacerItem(m_spacer_r);

    m_header = header;
    m_enableReorder = enable_reorder;
    m_enableDrag = enable_drag;
    if(m_enableReorder)
        ((QWidget*)parent)->setAcceptDrops(true);

    quint16 len = m_header->hasLen() ? m_header->length : m_header->packet_length;
    lenChanged(len);

    m_filterWidget = filters;

    QTimer *freeTimer = new QTimer(this);
    freeTimer->start(1000);
    connect(freeTimer, SIGNAL(timeout()), SLOT(freeLabels()));
}
Exemple #2
0
 Spacer::Spacer(SizeConstraint* sizeConstraint)
 {
     if(sizeConstraint == NULL)
         throw FCN_EXCEPTION("Spacer cannot have a NULL size constraint!");
     
     setSizeConstraint(sizeConstraint);
 }
SelectionStackWidget::SelectionStackWidget(
        iscore::SelectionStack& s,
        QWidget* parent):
    QWidget{parent},
    m_stack{s}
{
    m_prev = new QToolButton{this};
    m_prev->setArrowType(Qt::LeftArrow);
    m_prev->setEnabled(m_stack.canUnselect());

    m_next = new QToolButton{this};
    m_next->setArrowType(Qt::RightArrow);
    m_next->setEnabled(m_stack.canReselect());

    auto lay = new iscore::MarginLess<QHBoxLayout>{this};
    lay->setSizeConstraint(QLayout::SetMinimumSize);
    lay->addWidget(m_prev);
    lay->addWidget(m_next);
    setLayout(lay);

    connect(m_prev, &QToolButton::pressed,
            [&] () { m_stack.unselect(); });

    connect(m_next, &QToolButton::pressed,
            [&] () { m_stack.reselect(); });

    con(m_stack, &iscore::SelectionStack::currentSelectionChanged,
        this,    &SelectionStackWidget::selectionChanged);
}
/*
// TODO: move all display/formatting stuff to its own module

static const QRegExp AMOUNT_REGEXP("(([1-9]\\d{0,6}|1\\d{7}|20\\d{6}|0|)(\\.\\d{0,8})?|21000000(\\.0{0,8})?)");

// disallow more than 8 decimals and amounts > 21 million
static uint64_t btcStringToSatoshis(const std::string& btcString)
{
    uint32_t whole = 0;
    uint32_t frac = 0;

    unsigned int i = 0;
    bool stateWhole = true;
    for (auto& c: btcString) {
        i++;
        if (stateWhole) {
            if (c == '.') {
                stateWhole = false;
                i = 0;
                continue;
            }
            else if (i > 8 || c < '0' || c > '9') {
                throw std::runtime_error("Invalid amount.");
            }
            whole *= 10;
            whole += (uint32_t)(c - '0');
        }
        else {
            if (i > 8 || c < '0' || c > '9') {
                throw std::runtime_error("Invalid amount.");
            }
            frac *= 10;
            frac += (uint32_t)(c - '0');
        }
    }
    if (frac > 0) {
        while (i < 8) {
            i++;
            frac *= 10;
        }
    }
    uint64_t value = (uint64_t)whole * 100000000ull + frac;
    if (value > 2100000000000000ull) {
        throw std::runtime_error("Invalid amount.");
    }

    return value;
}
*/
TxOutLayout::TxOutLayout(QWidget* parent)
    : QHBoxLayout(parent)
{
    // Base58 version bytes
    base58_versions[0] = getCoinParams().pay_to_pubkey_hash_version();
    base58_versions[1] = getCoinParams().pay_to_script_hash_version();

    QLabel* addressLabel = new QLabel(tr("Address:"));
    addressEdit = new QLineEdit();
    addressEdit->setFixedWidth(300);

    QLabel* amountLabel = new QLabel(tr("Amount:"));
    amountEdit = new QLineEdit();
    amountEdit->setValidator(new QRegExpValidator(AMOUNT_REGEXP, this));

    QLabel* recipientLabel = new QLabel(tr("For:"));
    recipientEdit = new QLineEdit();

    removeButton = new QPushButton(tr("Remove"));

    setSizeConstraint(QLayout::SetFixedSize);
    addWidget(addressLabel);
    addWidget(addressEdit);
    addWidget(amountLabel);
    addWidget(amountEdit);
    addWidget(recipientLabel);
    addWidget(recipientEdit);
    addWidget(removeButton);
}
Exemple #5
0
ItemSync::ItemSync(const QString &label, const QString &icon, ItemWidget *childItem)
    : QWidget( childItem->widget()->parentWidget() )
    , ItemWidgetWrapper(childItem, this)
    , m_label( new QTextEdit(this) )
    , m_icon( new IconWidget(icon, this) )
{
    auto layout = new QVBoxLayout(this);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);
    layout->setSizeConstraint(QLayout::SetMinimumSize);

    auto labelLayout = new QHBoxLayout;
    connect( layout, &QVBoxLayout::destroyed,
             labelLayout, &QHBoxLayout::deleteLater );
    labelLayout->setContentsMargins(0, 0, 0, 0);
    labelLayout->setSpacing(0);

    labelLayout->addWidget(m_icon);
    labelLayout->addWidget(m_label);
    labelLayout->addStretch();

    layout->addLayout(labelLayout);

    QWidget *w = childItem->widget();
    layout->addWidget(w);
    w->setObjectName("item_child");
    w->setParent(this);

    m_label->setObjectName("item_child");

    m_label->document()->setDefaultFont(font());

    QTextOption option = m_label->document()->defaultTextOption();
    option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
    m_label->document()->setDefaultTextOption(option);

    m_label->setReadOnly(true);
    m_label->setUndoRedoEnabled(false);

    m_label->setFocusPolicy(Qt::NoFocus);
    m_label->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_label->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_label->setFrameStyle(QFrame::NoFrame);
    m_label->setContextMenuPolicy(Qt::NoContextMenu);

    m_label->viewport()->installEventFilter(this);

    m_label->setPlainText(label);
}
CameraLayout::CameraLayout( int rows, int columns )
:QGridLayout(), d ( new Private )
{
    d->rows = rows;
    d->columns = columns;
    d->columnCount = 0;
    d->rowCount = 0;
    d->hasSpace = true;
    clear();
    setSizeConstraint( QLayout::SetMaximumSize );
    setSpacing( 2 );
    setMargin( 1 );
    setContentsMargins( 0,0,0,0 );
    fill();
}
Exemple #7
0
//#################################################################################################
//###################         TsupportStandalone       ############################################
//#################################################################################################
TsupportStandalone::TsupportStandalone(QWidget* parent) :
  QDialog(parent)
{
#if defined (Q_OS_ANDROID)
  showMaximized();
#else
  setWindowTitle("Support Nootka");
  auto leftLab = new QLabel(this);
  leftLab->setPixmap(QPixmap(Tpath::img("wizard-left")));
#endif
  QString dontWorry = QApplication::translate("TsupportNootka",
            "Don't worry. This window appears only once per Nootka release.<br>You can find it always in 'About Nootka' dialog");
  auto supportArea = new TsupportNootka(this);
  supportArea->setFrameShape(QFrame::QFrame::StyledPanel);
//   auto neverLab = new TroundedLabel(dontWorry, this);
//     neverLab->setAlignment(Qt::AlignCenter);
//     neverLab->setBackroundColor(palette().base().color());
//     neverLab->setStyleSheet("color: palette(highlightedText)");
//     neverLab->setContentsMargins(5, 5, 5, 5);
  auto thanksButton = new QPushButton(QIcon(Tpath::img("support")), QLatin1String("  Thanks!"), this);
#if defined (Q_OS_ANDROID)
    thanksButton->setIconSize(QSize(Tmtr::fingerPixels(), Tmtr::fingerPixels()));
#else
    thanksButton->setIconSize(QSize(64, 64));
#endif
// Layout
  auto lay = new QHBoxLayout;
#if defined (Q_OS_ANDROID)
    lay->setContentsMargins(0, 0, 0, 0);
#else
    lay->addWidget(leftLab);
    lay->setSizeConstraint(QLayout::SetFixedSize);
#endif
  auto supportLay = new QVBoxLayout();
    supportLay->addWidget(supportArea);
    auto bottomLay = new QHBoxLayout;
//       bottomLay->addWidget(neverLab);
      bottomLay->addWidget(thanksButton, 0, Qt::AlignCenter);
    supportLay->addLayout(bottomLay);
  lay->addLayout(supportLay);
  setLayout(lay);

  connect(thanksButton, SIGNAL(clicked(bool)), this, SLOT(accept()));
}
int QLayout::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = QObject::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    
#ifndef QT_NO_PROPERTIES
     if (_c == QMetaObject::ReadProperty) {
        void *_v = _a[0];
        switch (_id) {
        case 0: *reinterpret_cast< int*>(_v) = margin(); break;
        case 1: *reinterpret_cast< int*>(_v) = spacing(); break;
        case 2: *reinterpret_cast< SizeConstraint*>(_v) = sizeConstraint(); break;
        }
        _id -= 3;
    } else if (_c == QMetaObject::WriteProperty) {
        void *_v = _a[0];
        switch (_id) {
        case 0: setMargin(*reinterpret_cast< int*>(_v)); break;
        case 1: setSpacing(*reinterpret_cast< int*>(_v)); break;
        case 2: setSizeConstraint(*reinterpret_cast< SizeConstraint*>(_v)); break;
        }
        _id -= 3;
    } else if (_c == QMetaObject::ResetProperty) {
        _id -= 3;
    } else if (_c == QMetaObject::QueryPropertyDesignable) {
        _id -= 3;
    } else if (_c == QMetaObject::QueryPropertyScriptable) {
        _id -= 3;
    } else if (_c == QMetaObject::QueryPropertyStored) {
        _id -= 3;
    } else if (_c == QMetaObject::QueryPropertyEditable) {
        _id -= 3;
    } else if (_c == QMetaObject::QueryPropertyUser) {
        _id -= 3;
    }
#endif // QT_NO_PROPERTIES
    return _id;
}
KitOptionsPageWidget::KitOptionsPageWidget()
    : m_model(0), m_selectionModel(0), m_currentWidget(0)
{
    m_kitsView = new QTreeView(this);
    m_kitsView->setUniformRowHeights(true);
    m_kitsView->header()->setStretchLastSection(true);
    m_kitsView->setSizePolicy(m_kitsView->sizePolicy().horizontalPolicy(),
                              QSizePolicy::Ignored);

    m_addButton = new QPushButton(KitOptionsPage::tr("Add"), this);
    m_cloneButton = new QPushButton(KitOptionsPage::tr("Clone"), this);
    m_delButton = new QPushButton(KitOptionsPage::tr("Remove"), this);
    m_makeDefaultButton = new QPushButton(KitOptionsPage::tr("Make Default"), this);

    auto buttonLayout = new QVBoxLayout;
    buttonLayout->setSpacing(6);
    buttonLayout->setContentsMargins(0, 0, 0, 0);
    buttonLayout->addWidget(m_addButton);
    buttonLayout->addWidget(m_cloneButton);
    buttonLayout->addWidget(m_delButton);
    buttonLayout->addWidget(m_makeDefaultButton);
    buttonLayout->addStretch();

    auto horizontalLayout = new QHBoxLayout;
    horizontalLayout->addWidget(m_kitsView);
    horizontalLayout->addLayout(buttonLayout);

    auto verticalLayout = new QVBoxLayout(this);
    verticalLayout->setSizeConstraint(QLayout::SetMinimumSize);
    verticalLayout->addLayout(horizontalLayout);

    m_model = new Internal::KitModel(verticalLayout, this);
    connect(m_model, &Internal::KitModel::kitStateChanged,
            this, &KitOptionsPageWidget::updateState);
    verticalLayout->setStretch(0, 1);
    verticalLayout->setStretch(1, 0);

    m_kitsView->setModel(m_model);
    m_kitsView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
    m_kitsView->expandAll();

    m_selectionModel = m_kitsView->selectionModel();
    connect(m_selectionModel, &QItemSelectionModel::selectionChanged,
            this, &KitOptionsPageWidget::kitSelectionChanged);
    connect(KitManager::instance(), &KitManager::kitAdded,
            this, &KitOptionsPageWidget::kitSelectionChanged);
    connect(KitManager::instance(), &KitManager::kitRemoved,
            this, &KitOptionsPageWidget::kitSelectionChanged);
    connect(KitManager::instance(), &KitManager::kitUpdated,
            this, &KitOptionsPageWidget::kitSelectionChanged);

    // Set up add menu:
    connect(m_addButton, &QAbstractButton::clicked,
            this, &KitOptionsPageWidget::addNewKit);
    connect(m_cloneButton, &QAbstractButton::clicked,
            this, &KitOptionsPageWidget::cloneKit);
    connect(m_delButton, &QAbstractButton::clicked,
            this, &KitOptionsPageWidget::removeKit);
    connect(m_makeDefaultButton, &QAbstractButton::clicked,
            this, &KitOptionsPageWidget::makeDefaultKit);

    updateState();
}
GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent) :
	QGridLayout(parent),
	v4l2(fd),
	m_row(0),
	m_col(0),
	m_cols(n),
	m_audioInput(NULL),
	m_tvStandard(NULL),
	m_videoPreset(NULL),
	m_freq(NULL),
	m_vidCapFormats(NULL),
	m_frameSize(NULL),
	m_vidOutFormats(NULL)
{
	setSpacing(3);

	setSizeConstraint(QLayout::SetMinimumSize);

	if (querycap(m_querycap)) {
		addLabel("Device:");
		addLabel(device + (useWrapper() ? " (wrapped)" : ""), Qt::AlignLeft);

		addLabel("Driver:");
		addLabel((char *)m_querycap.driver, Qt::AlignLeft);

		addLabel("Card:");
		addLabel((char *)m_querycap.card, Qt::AlignLeft);

		addLabel("Bus:");
		addLabel((char *)m_querycap.bus_info, Qt::AlignLeft);
	}

	g_tuner(m_tuner);

	v4l2_standard vs;
	if (enum_std(vs, true)) {
		addLabel("TV Standard");
		m_tvStandard = new QComboBox(parent);
		do {
			m_tvStandard->addItem((char *)vs.name);
		} while (enum_std(vs));
		addWidget(m_tvStandard);
		connect(m_tvStandard, SIGNAL(activated(int)), SLOT(standardChanged(int)));
		updateStandard();
	}

	v4l2_dv_enum_preset preset;
	if (enum_dv_preset(preset, true)) {
		addLabel("Video Preset");
		m_videoPreset = new QComboBox(parent);
		do {
			m_videoPreset->addItem((char *)preset.name);
		} while (enum_dv_preset(preset));
		addWidget(m_videoPreset);
		connect(m_videoPreset, SIGNAL(activated(int)), SLOT(presetChanged(int)));
		updatePreset();
	}

	v4l2_input vin;
	if (enum_input(vin, true)) {
		addLabel("Input");
		m_videoInput = new QComboBox(parent);
		do {
			m_videoInput->addItem((char *)vin.name);
		} while (enum_input(vin));
		addWidget(m_videoInput);
		connect(m_videoInput, SIGNAL(activated(int)), SLOT(inputChanged(int)));
		updateVideoInput();
	}

	v4l2_output vout;
	if (enum_output(vout, true)) {
		addLabel("Output");
		m_videoOutput = new QComboBox(parent);
		do {
			m_videoOutput->addItem((char *)vout.name);
		} while (enum_output(vout));
		addWidget(m_videoOutput);
		connect(m_videoOutput, SIGNAL(activated(int)), SLOT(outputChanged(int)));
		updateVideoOutput();
	}

	v4l2_audio vaudio;
	if (enum_audio(vaudio, true)) {
		addLabel("Input Audio");
		m_audioInput = new QComboBox(parent);
		do {
			m_audioInput->addItem((char *)vaudio.name);
		} while (enum_audio(vaudio));
		addWidget(m_audioInput);
		connect(m_audioInput, SIGNAL(activated(int)), SLOT(inputAudioChanged(int)));
		updateAudioInput();
	}

	v4l2_audioout vaudout;
	if (enum_audout(vaudout, true)) {
		addLabel("Output Audio");
		m_audioOutput = new QComboBox(parent);
		do {
			m_audioOutput->addItem((char *)vaudout.name);
		} while (enum_audout(vaudout));
		addWidget(m_audioOutput);
		connect(m_audioOutput, SIGNAL(activated(int)), SLOT(outputAudioChanged(int)));
		updateAudioOutput();
	}

	if (m_tuner.type) {
		m_freq = new QSpinBox(parent);
		m_freq->setMinimum(m_tuner.rangelow);
		m_freq->setMaximum(m_tuner.rangehigh);
		m_freq->setWhatsThis(QString("Frequency\nLow: %1\nHigh: %2")
				.arg(m_tuner.rangelow).arg(m_tuner.rangehigh));
		connect(m_freq, SIGNAL(valueChanged(int)), SLOT(freqChanged(int)));
		updateFreq();
		addLabel("Frequency");
		addWidget(m_freq);

		addLabel("Frequency Table");
		m_freqTable = new QComboBox(parent);
		for (int i = 0; v4l2_channel_lists[i].name; i++) {
			m_freqTable->addItem(v4l2_channel_lists[i].name);
		}
		addWidget(m_freqTable);
		connect(m_freqTable, SIGNAL(activated(int)), SLOT(freqTableChanged(int)));

		addLabel("Channels");
		m_freqChannel = new QComboBox(parent);
		m_freqChannel->setSizeAdjustPolicy(QComboBox::AdjustToContents);
		addWidget(m_freqChannel);
		connect(m_freqChannel, SIGNAL(activated(int)), SLOT(freqChannelChanged(int)));
		updateFreqChannel();
	}

	v4l2_fmtdesc fmt;
	addLabel("Capture Image Formats");
	m_vidCapFormats = new QComboBox(parent);
	if (enum_fmt_cap(fmt, true)) {
		do {
			m_vidCapFormats->addItem(pixfmt2s(fmt.pixelformat) +
					" - " + (const char *)fmt.description);
		} while (enum_fmt_cap(fmt));
	}
	addWidget(m_vidCapFormats);
	connect(m_vidCapFormats, SIGNAL(activated(int)), SLOT(vidCapFormatChanged(int)));

	addLabel("Frame Width");
	m_frameWidth = new QSpinBox(parent);
	addWidget(m_frameWidth);
	connect(m_frameWidth, SIGNAL(editingFinished()), SLOT(frameWidthChanged()));
	addLabel("Frame Height");
	m_frameHeight = new QSpinBox(parent);
	addWidget(m_frameHeight);
	connect(m_frameHeight, SIGNAL(editingFinished()), SLOT(frameHeightChanged()));

	addLabel("Frame Size");
	m_frameSize = new QComboBox(parent);
	m_frameSize->setSizeAdjustPolicy(QComboBox::AdjustToContents);
	addWidget(m_frameSize);
	connect(m_frameSize, SIGNAL(activated(int)), SLOT(frameSizeChanged(int)));

	addLabel("Frame Interval");
	m_frameInterval = new QComboBox(parent);
	m_frameInterval->setSizeAdjustPolicy(QComboBox::AdjustToContents);
	addWidget(m_frameInterval);
	connect(m_frameInterval, SIGNAL(activated(int)), SLOT(frameIntervalChanged(int)));

	updateVidCapFormat();

	if (caps() & V4L2_CAP_VIDEO_OUTPUT) {
		addLabel("Output Image Formats");
		m_vidOutFormats = new QComboBox(parent);
		if (enum_fmt_out(fmt, true)) {
			do {
				m_vidOutFormats->addItem(pixfmt2s(fmt.pixelformat) +
						" - " + (const char *)fmt.description);
			} while (enum_fmt_out(fmt));
		}
		addWidget(m_vidOutFormats);
		connect(m_vidOutFormats, SIGNAL(activated(int)), SLOT(vidOutFormatChanged(int)));
	}

	addLabel("Capture Method");
	m_capMethods = new QComboBox(parent);
	if (m_querycap.capabilities & V4L2_CAP_STREAMING) {
		v4l2_requestbuffers reqbuf;

		// Yuck. The videobuf framework does not accept a count of 0.
		// This is out-of-spec, but it means that the only way to test which
		// method is supported is to give it a non-zero count. But non-videobuf
		// drivers like uvc do not allow e.g. S_FMT calls after a REQBUFS call
		// with non-zero counts unless there is a REQBUFS call with count == 0
		// in between. This is actual proper behavior, although somewhat
		// unexpected. So the only way at the moment to do this that works
		// everywhere is to call REQBUFS with a count of 1, and then again with
		// a count of 0.
		if (reqbufs_user_cap(reqbuf, 1)) {
			m_capMethods->addItem("User pointer I/O", QVariant(methodUser));
			reqbufs_user_cap(reqbuf, 0);
		}
		if (reqbufs_mmap_cap(reqbuf, 1)) {
			m_capMethods->addItem("Memory mapped I/O", QVariant(methodMmap));
			reqbufs_mmap_cap(reqbuf, 0);
		}
	}
	if (m_querycap.capabilities & V4L2_CAP_READWRITE) {
		m_capMethods->addItem("read()", QVariant(methodRead));
	}
	addWidget(m_capMethods);

	QGridLayout::addWidget(new QWidget(parent), rowCount(), 0, 1, n);
	setRowStretch(rowCount() - 1, 1);
}
Exemple #11
0
DlInstrTab::DlInstrTab(QWidget *parent, DlProject *dlProject) :
    QWidget(parent),
    dlProject_(dlProject)
{
    DEBUG_FUNC_NAME

    anemView_ = new AnemView(this);
    anemModel_ = new AnemModel(anemView_, dlProject_->anems());
    anemDelegate_ = new AnemDelegate(anemView_);

    // NOTE: test if delegate clipping is necessary
    anemDelegate_->setClipping(false);
    anemView_->setModel(anemModel_);
    anemView_->setItemDelegate(anemDelegate_);
    anemView_->setSelectionMode(QAbstractItemView::SingleSelection);
    anemView_->setSelectionBehavior(QAbstractItemView::SelectColumns);
    anemView_->setCornerButtonEnabled(false);
    anemView_->setWordWrap(false);


    anemView_->horizontalHeader()->setDefaultSectionSize(130);
    anemView_->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
    anemView_->horizontalHeader()->setSectionsClickable(true);
    anemView_->horizontalHeader()->setHighlightSections(true);
    anemView_->horizontalHeader()->setSectionsMovable(false);
    anemView_->resizeRowsToContents();
    anemView_->resizeColumnsToContents();

    for (int i = 0; i < anemModel_->rowCount(); i++)
    {
        anemView_->verticalHeader()->resizeSection(i, 20);
    }

    auto addAnemButton = new QToolButton;
    addAnemButton->setObjectName(QStringLiteral("plusButton"));
    addAnemButton->setToolTip(tr("<b>+</b> Add a new anemometer."));

    auto removeAnemButton = new QToolButton;
    removeAnemButton->setObjectName(QStringLiteral("minusButton"));
    removeAnemButton->setToolTip(tr("<b>-</b> Remove the currently selected anemometer."));

    auto anemButtonsLayout = new QVBoxLayout;
    anemButtonsLayout->addWidget(addAnemButton);
    anemButtonsLayout->addWidget(removeAnemButton);
    anemButtonsLayout->addStretch();

    auto anemLayout = new QHBoxLayout;
    anemLayout->addWidget(anemView_);
    anemLayout->addLayout(anemButtonsLayout);
    anemLayout->setSizeConstraint(QLayout::SetNoConstraint);

    auto anemGroup = new QGroupBox(tr("Anemometers Info"));
    anemGroup->setObjectName(QStringLiteral("simpleGroupBox"));
    anemGroup->setFlat(true);
    anemGroup->setToolTip(tr("<b>Anemometers info:</b> Describe anemometers used at the flux station to collect data you want to process."));
    anemGroup->setLayout(anemLayout);
    anemGroup->setMinimumHeight(378);

    irgaView_ = new IrgaView(this);
    irgaModel_ = new IrgaModel(irgaView_, dlProject_->irgas());
    irgaDelegate_ = new IrgaDelegate(irgaView_);
    irgaView_->setModel(irgaModel_);
    irgaView_->setItemDelegate(irgaDelegate_);

    irgaView_->setSelectionMode(QAbstractItemView::SingleSelection);
    irgaView_->setSelectionBehavior(QAbstractItemView::SelectColumns);
    irgaView_->setCornerButtonEnabled(false);
    irgaView_->setWordWrap(false);

    irgaView_->horizontalHeader()->setDefaultSectionSize(145);
    irgaView_->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
    irgaView_->horizontalHeader()->setSectionsClickable(true);
    irgaView_->horizontalHeader()->setHighlightSections(true);
    irgaView_->horizontalHeader()->setSectionsMovable(false);
    irgaView_->setMinimumWidth(320);
    irgaView_->resizeRowsToContents();
    irgaView_->resizeColumnsToContents();
    irgaView_->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);

    for (int i = 0; i < irgaModel_->rowCount(); i++)
    {
        irgaView_->verticalHeader()->resizeSection(i, 20);
    }

    auto addIrgaButton = new QToolButton;
    addIrgaButton->setObjectName(QStringLiteral("plusButton"));
    addIrgaButton->setToolTip(tr("<b>+</b> Add a new gas analyzer."));

    auto removeIrgaButton = new QToolButton;
    removeIrgaButton->setObjectName(QStringLiteral("minusButton"));
    removeIrgaButton->setToolTip(tr("<b>-</b>Remove the currently selected gas analyzer."));

    auto irgaButtonsLayout = new QVBoxLayout;
    irgaButtonsLayout->addWidget(addIrgaButton);
    irgaButtonsLayout->addWidget(removeIrgaButton);
    irgaButtonsLayout->addStretch();

    auto irgaLayout = new QHBoxLayout;
    irgaLayout->addWidget(irgaView_);
    irgaLayout->addLayout(irgaButtonsLayout);
    irgaLayout->setSizeConstraint(QLayout::SetNoConstraint);

    auto irgaGroup = new QGroupBox(tr("Gas Analyzers Info"));
    irgaGroup->setObjectName(QStringLiteral("simpleGroupBox"));
    irgaGroup->setFlat(true);
    irgaGroup->setToolTip(tr("<b>Gas analyzers info:</b> Describe gas analyzers used to collect the data you want to process."));
    irgaGroup->setMinimumHeight(378);
    irgaGroup->setLayout(irgaLayout);

    auto instrLayout = new QHBoxLayout;
    instrLayout->addWidget(anemGroup);
    instrLayout->addWidget(irgaGroup);
    instrLayout->setSpacing(0);
    instrLayout->setContentsMargins(0, 0, 0, 0);

    auto instrContainer = new QFrame;
    instrContainer->setFrameStyle(QFrame::NoFrame);
    instrContainer->setObjectName(QStringLiteral("instrContainer"));
    instrContainer->setLayout(instrLayout);

    auto instrumentScrollArea = new QScrollArea;
    instrumentScrollArea->setWidget(instrContainer);
    instrumentScrollArea->setWidgetResizable(true);

    auto mainlayout = new QHBoxLayout(this);
    mainlayout->addWidget(instrumentScrollArea);
    mainlayout->setSizeConstraint(QLayout::SetNoConstraint);
    setLayout(mainlayout);

    connect(anemModel_, &AnemModel::modified, [=]()
            { dlProject_->setModified(true); });
    connect(addAnemButton, &QToolButton::clicked,
            anemView_, &AnemView::addAnem);
    connect(removeAnemButton, &QToolButton::clicked,
            anemView_, &AnemView::removeAnem);

    connect(irgaModel_, &IrgaModel::modified, [=]()
            { dlProject_->setModified(true); });
    connect(addIrgaButton, &QToolButton::clicked,
            irgaView_, &IrgaView::addIrga);
    connect(addIrgaButton, &QToolButton::clicked,
            this, &DlInstrTab::updateScrollBars);
    connect(removeIrgaButton, &QToolButton::clicked,
            irgaView_, &IrgaView::removeIrga);

    // NOTE: to trigger table editing with single click without altering the
    // editTriggers property, because that way the column selection
    // clicking on the header triggers the first cell editor
    connect(anemView_, SIGNAL(clicked(const QModelIndex &)),
            anemView_, SLOT(edit(const QModelIndex &)));
    connect(irgaView_, SIGNAL(clicked(const QModelIndex &)),
            irgaView_, SLOT(edit(const QModelIndex &)));
}
TimeLagSettingsDialog::TimeLagSettingsDialog(QWidget *parent, EcProject *ecProject, ConfigState* config) :
    QDialog(parent),
    ecProject_(ecProject),
    configState_(config)
{
    setWindowModality(Qt::WindowModal);
    setWindowTitle(tr("Time Lag Optimization Settings"));
    WidgetUtils::removeContextHelpButton(this);

    auto groupTitle = new QLabel;
    groupTitle->setText(tr("Configure smart time lag detection, "
                           "providing quality selection criteria and initial "
                           "time lag windows"));

    auto hrLabel = new QLabel;
    hrLabel->setObjectName(QStringLiteral("hrLabel"));

    existingRadio = new QRadioButton(tr("Time lag file available : "));
    existingRadio->setToolTip(tr("<b>Time lag file available:</b> If you have a satisfactory time lag assessment from a previous run and it applies to the current dataset, you can use it by providing the path to the file 'eddypro_timelag_opt_ID.txt' that was generated by EddyPro in the previous run and contains the results of the assessment. This will shorten program execution time and assure full comparability between the current and previous results."));

    nonExistingRadio = new QRadioButton(tr("Time lag file not available :"));
    nonExistingRadio->setToolTip(tr("<b>Time lag file not available:</b> Choose this option and provide the following information if you need to optimize time lags for your dataset. EddyPro will complete the time lag optimization first and then complete the raw data processing and flux computation procedures."));

    subsetCheckBox = new QCheckBox;
    subsetCheckBox->setProperty("subperiod", true);
    subsetCheckBox->setText(tr("Select a different period"));
    subsetCheckBox->setToolTip(tr("<b>Select a different period:</b> Select this option and set the corresponding dates, to identify the time period EddyPro will use for the Time lag optimization. This subperiod must fall within the time period defined by the available raw data."));

    startDateLabel = new ClickLabel(this);
    startDateLabel->setText(tr("Start :"));
    startDateLabel->setToolTip(tr("<b>Start:</b> Starting date of the time period to be used for time lag optimization. This time should not be shorter than about 1-2 months. As a general recommendation, select a time period during which the instrument setup did not undergo major modifications. Results obtained using a given time period (e.g., 2 months) can be used for processing a longer time period, in which major modifications did not occur in the setup. The stricter the threshold setup in this dialogue, the longer the period should be in order to get robust results."));
    startDateEdit = new QDateEdit;
    startDateEdit->setToolTip(startDateLabel->toolTip());
    startDateEdit->setCalendarPopup(true);
    WidgetUtils::customizeCalendar(startDateEdit->calendarWidget());

    startTimeEdit = new QTimeEdit;
    startTimeEdit->setDisplayFormat(QStringLiteral("hh:mm"));
    startTimeEdit->setAccelerated(true);

    lockedIcon = new QLabel;
    auto pixmap = QPixmap(QStringLiteral(":/icons/vlink-locked"));
#if defined(Q_OS_MAC)
    pixmap.setDevicePixelRatio(2.0);
#endif
    lockedIcon->setPixmap(pixmap);

    endDateLabel = new ClickLabel(this);
    endDateLabel->setText(tr("End :"));
    endDateLabel->setToolTip(tr("<b>End:</b> End date of the time period to be used for time lag optimization. This time should not be shorter than about 1-2 months As a general recommendation, select a time period during which the instrumental setup did not undergo major modifications. Results obtained using a given time period (e.g., 2 months) can be used for processing a longer time period, in which major modifications did not occur in the setup. The stricter the threshold setup in this dialogue, the longer the period should be in order to get robust results."));
    endDateEdit = new QDateEdit;
    endDateEdit->setToolTip(endDateLabel->toolTip());
    endDateEdit->setCalendarPopup(true);
    WidgetUtils::customizeCalendar(endDateEdit->calendarWidget());

    endTimeEdit = new QTimeEdit;
    endTimeEdit->setDisplayFormat(QStringLiteral("hh:mm"));
    endTimeEdit->setAccelerated(true);

    auto dateTimeContainer = new QGridLayout;
    dateTimeContainer->addWidget(startDateEdit, 0, 1);
    dateTimeContainer->addWidget(startTimeEdit, 0, 2);
    dateTimeContainer->addWidget(lockedIcon, 0, 0, 2, 1);
    dateTimeContainer->addWidget(endDateEdit, 1, 1);
    dateTimeContainer->addWidget(endTimeEdit, 1, 2);
    dateTimeContainer->setColumnStretch(1, 1);
    dateTimeContainer->setColumnStretch(2, 1);
    dateTimeContainer->setColumnStretch(3, 2);
    dateTimeContainer->setContentsMargins(0, 0, 0, 0);
    dateTimeContainer->setVerticalSpacing(3);

    fileBrowse = new FileBrowseWidget;
    fileBrowse->setToolTip(tr("<b>Load:</b> Load an existing time lag file"));
    fileBrowse->setDialogTitle(tr("Select the Time Lag Optimization File"));
    fileBrowse->setDialogWorkingDir(WidgetUtils::getSearchPathHint());
    fileBrowse->setDialogFilter(tr("All Files (*.*)"));

    auto existingFileLayout = new QHBoxLayout;
    existingFileLayout->addWidget(existingRadio);
    existingFileLayout->addWidget(fileBrowse);
    existingFileLayout->setStretch(2, 1);
    existingFileLayout->setContentsMargins(0, 0, 0, 0);
    existingFileLayout->setSpacing(0);

    radioGroup = new QButtonGroup(this);
    radioGroup->addButton(existingRadio, 0);
    radioGroup->addButton(nonExistingRadio, 1);

    h2oTitleLabel = WidgetUtils::createBlueLabel(this, tr("Water vapor time lag as a function of relative humidity"));

    pgRangeLabel = new ClickLabel(tr("Plausibility range around median value :"));
    pgRangeLabel->setToolTip(tr("<b>Plausibility range around median value:</b> The plausibility range is defined as the median time lag, %1 <i>n</i> times the MAD (median of the absolute deviations from the median time lag). Specify <i>n</i> here. The value of 1.5 was heuristically found to be optimal.").arg(Defs::PLUSMINUS));
    pgRangeSpin = new QDoubleSpinBox;
    pgRangeSpin->setDecimals(1);
    pgRangeSpin->setRange(0.1, 100.0);
    pgRangeSpin->setSingleStep(0.1);
    pgRangeSpin->setAccelerated(true);
    pgRangeSpin->setSuffix(tr("  [mad]"));
    pgRangeSpin->setToolTip(pgRangeLabel->toolTip());
    pgRangeLabel_2 = new QLabel(tr("(<tt>%1%2n%3mad</tt>, where you set <tt>n</tt>)").arg(Defs::MICRO, Defs::PLUSMINUS, Defs::MID_DOT));

    rhClassLabel = new ClickLabel(tr("Number of RH classes :"));
    rhClassLabel->setToolTip(tr("<b>Number of RH classes:</b> Select the number or relative humidity classes, to assess water vapor time lag as a function of RH. The whole range or RH variation (0-100%) will be evenly divided according to the selected number of classes. For example, selecting 10 classes causes EddyPro to assess water vapor time lags for the classes 0-10%, 10-20%,..., 90-100%. Selecting 1 class, the label <b><i>Do not sort in RH classes</i></b> appears and will cause EddyPro to treat water vapor exactly like other passive gases. This option is only suitable for open path systems, or closed path systems with short and heated sampling lines."));

    rhClassSpin = new QSpinBox;
    rhClassSpin->setRange(1, 20);
    rhClassSpin->setSingleStep(1);
    rhClassSpin->setAccelerated(true);
    rhClassSpin->setSpecialValueText(tr("Do not sort in RH classes"));
    rhClassSpin->setToolTip(rhClassLabel->toolTip());

    gasTitleLabel = WidgetUtils::createBlueLabel(this, tr("Passive gases"));

    co2MinFluxLabel = new ClickLabel(tr("Minimum (absolute) %1 flux :").arg(Defs::CO2_STRING));
    co2MinFluxLabel->setToolTip(tr("<b>Minimum (absolute) %1 flux:</b> %1 time lags corresponding to fluxes smaller (in module) than this value will not be considered in the time lag optimization. Selecting high-enough fluxes assures that well developed turbulent conditions are met and the correlation function is well characterized.").arg(Defs::CO2_STRING));
    co2MinFluxSpin = new QDoubleSpinBox;
    co2MinFluxSpin->setDecimals(3);
    co2MinFluxSpin->setRange(0.0, 100.0);
    co2MinFluxSpin->setSingleStep(0.001);
    co2MinFluxSpin->setAccelerated(true);
    co2MinFluxSpin->setSuffix(tr("  [%1]").arg(Defs::UMOL_M2S_STRING));
    co2MinFluxSpin->setToolTip(co2MinFluxLabel->toolTip());

    ch4MinFluxLabel = new ClickLabel(tr("Minimum (absolute) %1 flux :").arg(Defs::CH4_STRING));
    ch4MinFluxLabel->setToolTip(tr("<b>Minimum (absolute) %1 flux:</b> %1 time lags corresponding to fluxes smaller (in module) than this value will not be considered in the time lag optimization. Selecting high-enough fluxes assures that well developed turbulent conditions are met and the correlation function is well characterized.").arg(Defs::CH4_STRING));
    ch4MinFluxSpin = new QDoubleSpinBox;
    ch4MinFluxSpin->setDecimals(3);
    ch4MinFluxSpin->setRange(0.0, 100.0);
    ch4MinFluxSpin->setSingleStep(0.001);
    ch4MinFluxSpin->setAccelerated(true);
    ch4MinFluxSpin->setSuffix(tr("  [%1]").arg(Defs::UMOL_M2S_STRING));
    ch4MinFluxSpin->setToolTip(ch4MinFluxLabel->toolTip());

    gas4MinFluxLabel = new ClickLabel(tr("Minimum (absolute) %1 gas flux :").arg(Defs::GAS4_STRING));
    gas4MinFluxLabel->setToolTip(tr("<b>Minimum (absolute) %1 gas flux:</b> %1 gas time lags corresponding to fluxes smaller (in module) than this value will not be considered in the time lag optimization. Selecting high-enough fluxes assures that well developed turbulent conditions are met and the correlation function is well characterized.").arg(Defs::GAS4_STRING));
    gas4MinFluxSpin = new QDoubleSpinBox;
    gas4MinFluxSpin->setDecimals(3);
    gas4MinFluxSpin->setRange(0.0, 100.0);
    gas4MinFluxSpin->setSingleStep(0.001);
    gas4MinFluxSpin->setAccelerated(true);
    gas4MinFluxSpin->setSuffix(tr("  [%1]").arg(Defs::UMOL_M2S_STRING));
    gas4MinFluxSpin->setToolTip(gas4MinFluxLabel->toolTip());

    leMinFluxLabel = new ClickLabel(tr("Minimum latent heat flux :"));
    leMinFluxLabel->setToolTip(tr("<b>Minimum latent heat flux:</b> Minimum latent heat flux: H<sub>2</sub>O time lags corresponding to latent heat fluxes smaller than this value will not be considered in the time lag optimization. Selecting high-enough fluxes assures that well developed turbulent conditions are met and the correlation function is well characterized."));
    leMinFluxSpin = new QDoubleSpinBox;
    leMinFluxSpin->setDecimals(1);
    leMinFluxSpin->setRange(0.0, 1000.0);
    leMinFluxSpin->setSingleStep(0.1);
    leMinFluxSpin->setAccelerated(true);
    leMinFluxSpin->setSuffix(tr("  [%1]").arg(Defs::W_M2_STRING));
    leMinFluxSpin->setToolTip(leMinFluxLabel->toolTip());

    searchWindowLabel = WidgetUtils::createBlueLabel(this, tr("Time lag searching windows"));

    minLabel = WidgetUtils::createBlueLabel(this, tr("Minimum"));
    minLabel->setToolTip(tr("<b>Minimum:</b> Minimum time lag for each gas, for initializing the time lag optimization procedure. The searching window defined by Minimum and Maximum should be large enough to accommodate all possible time lags. Leave as <i>Not set</i> if in doubt, EddyPro will initialize it automatically."));

    maxLabel = WidgetUtils::createBlueLabel(this, tr("Maximum"));
    maxLabel->setToolTip(tr("<b>Maximum:</b> Maximum time lag for each gas, for initializing the time lag optimization procedure. The searching window defined by Minimum and Maximum should be large enough to accommodate all possible time lags. In particular, maximum time lags of water vapor in closed path systems can up to ten times higher than its nominal value, or even higher. Leave as <i>Not set</i> if in doubt, EddyPro will initialize it automatically."));

    co2Label = new ClickLabel(tr("%1 :").arg(Defs::CO2_STRING));

    minCo2TlSpin = new QDoubleSpinBox;
    minCo2TlSpin->setDecimals(1);
    minCo2TlSpin->setRange(-1000.1, 1000.0);
    minCo2TlSpin->setSingleStep(0.1);
    minCo2TlSpin->setSpecialValueText(tr("Detect automatically"));
    minCo2TlSpin->setAccelerated(true);
    minCo2TlSpin->setSuffix(tr("  [s]"));
    minCo2TlSpin->setToolTip(minLabel->toolTip());

    maxCo2TlSpin = new QDoubleSpinBox;
    maxCo2TlSpin->setDecimals(1);
    maxCo2TlSpin->setRange(-1000.1, 1000.0);
    maxCo2TlSpin->setSingleStep(0.1);
    maxCo2TlSpin->setSpecialValueText(tr("Detect automatically"));
    maxCo2TlSpin->setAccelerated(true);
    maxCo2TlSpin->setSuffix(tr("  [s]"));
    maxCo2TlSpin->setToolTip(maxLabel->toolTip());

    h2oLabel = new ClickLabel(tr("%1 :").arg(Defs::H2O_STRING));

    minH2oTlSpin = new QDoubleSpinBox;
    minH2oTlSpin->setDecimals(1);
    minH2oTlSpin->setRange(-1000.1, 1000.0);
    minH2oTlSpin->setSingleStep(0.1);
    minH2oTlSpin->setSpecialValueText(tr("Detect automatically"));
    minH2oTlSpin->setAccelerated(true);
    minH2oTlSpin->setSuffix(tr("  [s]"));
    minH2oTlSpin->setToolTip(minLabel->toolTip());

    maxH2oTlSpin = new QDoubleSpinBox;
    maxH2oTlSpin->setDecimals(1);
    maxH2oTlSpin->setRange(-1000.1, 1000.0);
    maxH2oTlSpin->setSingleStep(0.1);
    maxH2oTlSpin->setSpecialValueText(tr("Detect automatically"));
    maxH2oTlSpin->setAccelerated(true);
    maxH2oTlSpin->setSuffix(tr("  [s]"));
    maxH2oTlSpin->setToolTip(maxLabel->toolTip());

    ch4Label = new ClickLabel(tr("%1 :").arg(Defs::CH4_STRING));

    minCh4TlSpin = new QDoubleSpinBox;
    minCh4TlSpin->setDecimals(1);
    minCh4TlSpin->setRange(-1000.1, 1000.0);
    minCh4TlSpin->setSingleStep(0.1);
    minCh4TlSpin->setSpecialValueText(tr("Detect automatically"));
    minCh4TlSpin->setAccelerated(true);
    minCh4TlSpin->setSuffix(tr("  [s]"));
    minCh4TlSpin->setToolTip(minLabel->toolTip());

    maxCh4TlSpin = new QDoubleSpinBox;
    maxCh4TlSpin->setDecimals(1);
    maxCh4TlSpin->setRange(-1000.1, 1000.0);
    maxCh4TlSpin->setSingleStep(0.1);
    maxCh4TlSpin->setSpecialValueText(tr("Detect automatically"));
    maxCh4TlSpin->setAccelerated(true);
    maxCh4TlSpin->setSuffix(tr("  [s]"));
    maxCh4TlSpin->setToolTip(maxLabel->toolTip());

    gas4Label = new ClickLabel(tr("%1 gas :").arg(Defs::GAS4_STRING));

    minGas4TlSpin = new QDoubleSpinBox;
    minGas4TlSpin->setDecimals(1);
    minGas4TlSpin->setRange(-1000.1, 1000.0);
    minGas4TlSpin->setSingleStep(0.1);
    minGas4TlSpin->setSpecialValueText(tr("Detect automatically"));
    minGas4TlSpin->setAccelerated(true);
    minGas4TlSpin->setSuffix(tr("  [s]"));
    minGas4TlSpin->setToolTip(minLabel->toolTip());

    maxGas4TlSpin = new QDoubleSpinBox;
    maxGas4TlSpin->setDecimals(1);
    maxGas4TlSpin->setRange(-1000.1, 1000.0);
    maxGas4TlSpin->setSingleStep(0.1);
    maxGas4TlSpin->setSpecialValueText(tr("Detect automatically"));
    maxGas4TlSpin->setAccelerated(true);
    maxGas4TlSpin->setSuffix(tr("  [s]"));
    maxGas4TlSpin->setToolTip(maxLabel->toolTip());

    auto propertiesLayout = new QGridLayout;
    propertiesLayout->addLayout(existingFileLayout, 0, 0, 1, -1);
    propertiesLayout->addWidget(nonExistingRadio, 1, 0);
    propertiesLayout->addWidget(subsetCheckBox, 1, 1, 1, 1, Qt::AlignLeft);
    propertiesLayout->addWidget(startDateLabel, 1, 1, Qt::AlignRight);
    propertiesLayout->addLayout(dateTimeContainer, 1, 2, 2, 1);
    propertiesLayout->addWidget(endDateLabel, 2, 1, Qt::AlignRight);
    propertiesLayout->addWidget(pgRangeLabel, 3, 1, 1, 1, Qt::AlignRight);
    propertiesLayout->addWidget(pgRangeSpin, 3, 2);
    propertiesLayout->addWidget(pgRangeLabel_2, 3, 3);

    propertiesLayout->addWidget(h2oTitleLabel, 4, 0, 1, 2);

    propertiesLayout->addWidget(rhClassLabel, 5, 1, Qt::AlignRight);
    propertiesLayout->addWidget(rhClassSpin, 5, 2);
    propertiesLayout->addWidget(leMinFluxLabel, 6, 1, Qt::AlignRight);
    propertiesLayout->addWidget(leMinFluxSpin, 6, 2);

    propertiesLayout->addWidget(gasTitleLabel, 7, 0);

    propertiesLayout->addWidget(co2MinFluxLabel, 8, 1, Qt::AlignRight);
    propertiesLayout->addWidget(co2MinFluxSpin, 8, 2);
    propertiesLayout->addWidget(ch4MinFluxLabel, 9, 1, Qt::AlignRight);
    propertiesLayout->addWidget(ch4MinFluxSpin, 9, 2);
    propertiesLayout->addWidget(gas4MinFluxLabel, 10, 1, Qt::AlignRight);
    propertiesLayout->addWidget(gas4MinFluxSpin, 10, 2);

    propertiesLayout->addWidget(searchWindowLabel, 11, 0);
    propertiesLayout->addWidget(minLabel, 12, 1);
    propertiesLayout->addWidget(maxLabel, 12, 2);
    propertiesLayout->addWidget(co2Label, 13, 0, Qt::AlignRight);
    propertiesLayout->addWidget(minCo2TlSpin, 13, 1);
    propertiesLayout->addWidget(maxCo2TlSpin, 13, 2);
    propertiesLayout->addWidget(h2oLabel, 14, 0, Qt::AlignRight);
    propertiesLayout->addWidget(minH2oTlSpin, 14, 1);
    propertiesLayout->addWidget(maxH2oTlSpin, 14, 2);
    propertiesLayout->addWidget(ch4Label, 15, 0, Qt::AlignRight);
    propertiesLayout->addWidget(minCh4TlSpin, 15, 1);
    propertiesLayout->addWidget(maxCh4TlSpin, 15, 2);
    propertiesLayout->addWidget(gas4Label, 16, 0, Qt::AlignRight);
    propertiesLayout->addWidget(minGas4TlSpin, 16, 1);
    propertiesLayout->addWidget(maxGas4TlSpin, 16, 2);
    propertiesLayout->setVerticalSpacing(3);
    propertiesLayout->setRowMinimumHeight(2, 10);
    propertiesLayout->setContentsMargins(3, 3, 3, 3);

    auto propertiesFrame = new QWidget;
    propertiesFrame->setLayout(propertiesLayout);
    propertiesFrame->setMinimumWidth(propertiesFrame->sizeHint().width());

    auto okButton = WidgetUtils::createCommonButton(this, tr("Ok"));

    auto mainLayout = new QGridLayout(this);
    mainLayout->addWidget(groupTitle, 0, 0);
    mainLayout->addWidget(hrLabel, 1, 0);
    mainLayout->addWidget(propertiesFrame, 2, 0);
    mainLayout->addWidget(okButton, 3, 0, 1, 1, Qt::AlignCenter);
    mainLayout->setVerticalSpacing(10);
    mainLayout->setContentsMargins(30, 30, 30, 30);
    mainLayout->setSizeConstraint(QLayout::SetFixedSize);
    setLayout(mainLayout);

    connect(radioGroup, SIGNAL(buttonClicked(int)),
            this, SLOT(updateTlMode(int)));

    connect(radioGroup, SIGNAL(buttonClicked(int)),
            this, SLOT(radioClicked(int)));

    connect(fileBrowse, &FileBrowseWidget::pathChanged,
            this, &TimeLagSettingsDialog::updateFile);
    connect(fileBrowse, &FileBrowseWidget::pathSelected,
        this, &TimeLagSettingsDialog::testSelectedFile);

    connect(subsetCheckBox, &QCheckBox::toggled,
            this, &TimeLagSettingsDialog::updateSubsetSelection);

    connect(startDateLabel, &ClickLabel::clicked,
            this, &TimeLagSettingsDialog::onStartDateLabelClicked);
    connect(startDateEdit, &QDateEdit::dateChanged,
            this, &TimeLagSettingsDialog::updateStartDate);
    connect(startTimeEdit, &QTimeEdit::timeChanged,
            this, &TimeLagSettingsDialog::updateStartTime);

    connect(endDateLabel, &ClickLabel::clicked,
            this, &TimeLagSettingsDialog::onEndDateLabelClicked);
    connect(endDateEdit, &QDateEdit::dateChanged,
            this, &TimeLagSettingsDialog::updateEndDate);
    connect(endTimeEdit, &QTimeEdit::timeChanged,
            this, &TimeLagSettingsDialog::updateEndTime);

    connect(rhClassLabel, &ClickLabel::clicked,
            this, &TimeLagSettingsDialog::onRhClassClicked);
    connect(rhClassSpin, SIGNAL(valueChanged(int)),
            this, SLOT(updateRhClass(int)));

    connect(co2MinFluxLabel, &ClickLabel::clicked,
            this, &TimeLagSettingsDialog::onCo2MinFluxClicked);
    connect(co2MinFluxSpin, SIGNAL(valueChanged(double)),
            this, SLOT(updateCo2MinFlux(double)));

    connect(ch4MinFluxLabel, &ClickLabel::clicked,
            this, &TimeLagSettingsDialog::onCh4MinFluxClicked);
    connect(ch4MinFluxSpin, SIGNAL(valueChanged(double)),
            this, SLOT(updateCh4MinFlux(double)));

    connect(gas4MinFluxLabel, &ClickLabel::clicked,
            this, &TimeLagSettingsDialog::onGas4MinFluxClicked);
    connect(gas4MinFluxSpin, SIGNAL(valueChanged(double)),
            this, SLOT(updateGas4MinFlux(double)));

    connect(leMinFluxLabel, &ClickLabel::clicked,
            this, &TimeLagSettingsDialog::onLeMinFluxClicked);
    connect(leMinFluxSpin, SIGNAL(valueChanged(double)),
            this, SLOT(updateLeMinFlux(double)));

    connect(pgRangeLabel, &ClickLabel::clicked,
            this, &TimeLagSettingsDialog::onPgRangeLabelClicked);
    connect(pgRangeSpin, SIGNAL(valueChanged(double)),
            this, SLOT(updatePgRange(double)));

    connect(co2Label, &ClickLabel::clicked,
            this, &TimeLagSettingsDialog::onCo2LabelClicked);
    connect(minCo2TlSpin, SIGNAL(valueChanged(double)),
            this, SLOT(updateMinCo2Tl(double)));
    connect(maxCo2TlSpin, SIGNAL(valueChanged(double)),
            this, SLOT(updateMaxCo2Tl(double)));

    connect(h2oLabel, &ClickLabel::clicked,
            this, &TimeLagSettingsDialog::onH2oLabelClicked);
    connect(minH2oTlSpin, SIGNAL(valueChanged(double)),
            this, SLOT(updateMinH2oTl(double)));
    connect(maxH2oTlSpin, SIGNAL(valueChanged(double)),
            this, SLOT(updateMaxH2oTl(double)));

    connect(ch4Label, &ClickLabel::clicked,
            this, &TimeLagSettingsDialog::onCh4LabelClicked);
    connect(minCh4TlSpin, SIGNAL(valueChanged(double)),
            this, SLOT(updateMinCh4Tl(double)));
    connect(maxCh4TlSpin, SIGNAL(valueChanged(double)),
            this, SLOT(updateMaxCh4Tl(double)));

    connect(gas4Label, &ClickLabel::clicked,
            this, &TimeLagSettingsDialog::onGas4LabelClicked);
    connect(minGas4TlSpin, SIGNAL(valueChanged(double)),
            this, SLOT(updateMinGas4Tl(double)));
    connect(maxGas4TlSpin, SIGNAL(valueChanged(double)),
            this, SLOT(updateMaxGas4Tl(double)));

    connect(okButton, &QPushButton::clicked,
            this, &TimeLagSettingsDialog::close);

    // init
    forceEndDatePolicy();
    forceEndTimePolicy();
}
MainWindow::MainWindow(Settings& settings, Model& model, QWidget* parent)
    : QMainWindow(parent)
    , m_settings(settings)
    , m_model(model)
{
    m_tableView = new QTableView(this);
    m_tableView->setModel(&m_model);
    setCentralWidget(m_tableView);

    m_tableView->setAlternatingRowColors(true);
    m_tableView->sortByColumn(0, Qt::AscendingOrder);
    m_tableView->setSortingEnabled(true);
    m_tableView->setSelectionMode(QAbstractItemView::SingleSelection);
    m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    m_tableView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
    m_tableView->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);

    m_tableView->verticalHeader()->setVisible(false);
    m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
    m_tableView->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch);

    connect(m_tableView, &QTableView::activated, this, &MainWindow::activated);
    connect(m_tableView->selectionModel(), &QItemSelectionModel::currentChanged, this, &MainWindow::currentChanged);

    const auto searchDock = new QDockWidget(tr("Search"), this);
    searchDock->setObjectName(QStringLiteral("searchDock"));
    addDockWidget(Qt::BottomDockWidgetArea, searchDock);

    const auto searchWidget = new QWidget(searchDock);
    searchDock->setWidget(searchWidget);

    const auto searchLayout = new QFormLayout(searchWidget);
    searchWidget->setLayout(searchLayout);

    m_searchTimer = new QTimer(this);
    m_searchTimer->setInterval(searchTimeout);

    m_channelBox = new QComboBox(searchWidget);
    m_channelBox->setModel(m_model.channels());
    m_channelBox->setEditable(true);
    m_channelBox->setMinimumContentsLength(minimumChannelLength);
    m_channelBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
    searchLayout->addRow(tr("Channel"), m_channelBox);

    m_topicBox = new QComboBox(searchWidget);
    m_topicBox->setModel(m_model.topics());
    m_topicBox->setEditable(true);
    m_topicBox->setMinimumContentsLength(minimumTopicLength);
    m_topicBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
    searchLayout->addRow(tr("Topic"), m_topicBox);

    m_titleEdit = new QLineEdit(searchWidget);
    m_titleEdit->setFocus();
    searchLayout->addRow(tr("Title"), m_titleEdit);

    connect(m_searchTimer, &QTimer::timeout, this, &MainWindow::timeout);

    constexpr auto startTimer = static_cast< void (QTimer::*)() >(&QTimer::start);
    connect(m_channelBox, &QComboBox::currentTextChanged, m_searchTimer, startTimer);
    connect(m_topicBox, &QComboBox::currentTextChanged, m_searchTimer, startTimer);
    connect(m_titleEdit, &QLineEdit::textChanged, m_searchTimer, startTimer);

    const auto buttonsWidget = new QWidget(searchWidget);
    searchLayout->addWidget(buttonsWidget);
    searchLayout->setAlignment(buttonsWidget, Qt::AlignRight);

    const auto buttonsLayout = new QBoxLayout(QBoxLayout::LeftToRight, buttonsWidget);
    buttonsWidget->setLayout(buttonsLayout);
    buttonsLayout->setSizeConstraint(QLayout::SetFixedSize);

    const auto resetFilterButton = new QPushButton(QIcon::fromTheme(QStringLiteral("edit-clear")), QString(), buttonsWidget);
    buttonsLayout->addWidget(resetFilterButton);

    const auto updateDatabaseButton = new QPushButton(QIcon::fromTheme(QStringLiteral("view-refresh")), QString(), buttonsWidget);
    buttonsLayout->addWidget(updateDatabaseButton);

    const auto editSettingsButton = new QPushButton(QIcon::fromTheme(QStringLiteral("preferences-system")), QString(), buttonsWidget);
    buttonsLayout->addWidget(editSettingsButton);

    connect(resetFilterButton, &QPushButton::pressed, this, &MainWindow::resetFilterPressed);
    connect(updateDatabaseButton, &QPushButton::pressed, this, &MainWindow::updateDatabasePressed);
    connect(editSettingsButton, &QPushButton::pressed, this, &MainWindow::editSettingsPressed);

    const auto detailsDock = new QDockWidget(tr("Details"), this);
    detailsDock->setObjectName(QStringLiteral("detailsDock"));
    addDockWidget(Qt::BottomDockWidgetArea, detailsDock);

    const auto detailsWidget = new QWidget(detailsDock);
    detailsDock->setWidget(detailsWidget);

    const auto detailsLayout = new QGridLayout(detailsWidget);
    detailsWidget->setLayout(detailsLayout);

    detailsLayout->setRowStretch(2, 1);
    detailsLayout->setColumnStretch(1, 1);

    m_descriptionEdit = new QTextEdit(detailsWidget);
    m_descriptionEdit->setReadOnly(true);
    m_descriptionEdit->setLineWrapMode(QTextEdit::WidgetWidth);
    detailsLayout->addWidget(m_descriptionEdit, 0, 1, 3, 1);

    m_websiteLabel = new QLabel(detailsWidget);
    detailsLayout->addWidget(m_websiteLabel, 3, 1);

    connect(m_websiteLabel, &QLabel::linkActivated, QDesktopServices::openUrl);

    const auto playButton = new QPushButton(QIcon::fromTheme(QStringLiteral("media-playback-start")), QString(), detailsWidget);
    detailsLayout->addWidget(playButton, 0, 0);

    const auto downloadButton = new QPushButton(QIcon::fromTheme(QStringLiteral("media-record")), QString(), detailsWidget);
    detailsLayout->addWidget(downloadButton, 1, 0);

    connect(playButton, &QPushButton::pressed, this, &MainWindow::playPressed);
    connect(downloadButton, &QPushButton::pressed, this, &MainWindow::downloadPressed);

    const auto quitShortcut = new QShortcut(QKeySequence::Quit, this);
    connect(quitShortcut, &QShortcut::activated, this, &MainWindow::close);

    restoreGeometry(m_settings.mainWindowGeometry());
    restoreState(m_settings.mainWindowState());

    statusBar()->showMessage(tr("Ready"), messageTimeout);
}
DlRawfileDescTab::DlRawfileDescTab(QWidget* parent, DlProject* dlProject) :
    QWidget(parent),
    dlProject_(dlProject),
    rawSettingsDialog(nullptr),
    fieldSepTOB1Flag_(false)
{
    DEBUG_FUNC_NAME

    variableView_ = new VariableView(this);
    variableModel_ = new VariableModel(variableView_, dlProject_->variables());
    variableDelegate_ = new VariableDelegate(variableView_);

    variableView_->setModel(variableModel_);
    variableView_->setItemDelegate(variableDelegate_);
    variableView_->setSelectionMode(QAbstractItemView::SingleSelection);
    variableView_->setSelectionBehavior(QAbstractItemView::SelectColumns);
    variableView_->setCornerButtonEnabled(false);
    variableView_->setWordWrap(false);

    QHeaderView *hHeaderView = variableView_->horizontalHeader();
    hHeaderView->setDefaultSectionSize(175);
    hHeaderView->setSectionResizeMode(QHeaderView::Fixed);
    hHeaderView->setSectionsClickable(true);
    hHeaderView->setHighlightSections(true);
    hHeaderView->setSectionsMovable(false);

    variableView_->setMinimumHeight(298);
    variableView_->resizeRowsToContents();
    variableView_->resizeColumnsToContents();
    for (int i = 0; i < variableModel_->rowCount(); i++)
    {
        variableView_->verticalHeader()->resizeSection(i, 20);
    }

    auto addButton = new QToolButton;
    addButton->setObjectName(QStringLiteral("plusButton"));
    addButton->setToolTip(tr("<b>+</b> Add a variable."));

    auto removeButton = new QToolButton;
    removeButton->setObjectName(QStringLiteral("minusButton"));
    removeButton->setToolTip(tr("<b>-</b> Remove a variable."));

    auto buttonsLayout = new QVBoxLayout;
    buttonsLayout->addWidget(addButton);
    buttonsLayout->addWidget(removeButton);
    buttonsLayout->addStretch();

    rawSettingsButton = new QPushButton(tr("Raw File Settings..."));
    rawSettingsButton->setProperty("mdButton", true);
    rawSettingsButton->setStyleSheet(QStringLiteral("QPushButton {margin-top: 15px}"));

    clearCustomVarsButton = new QPushButton(tr("Clear Custom Variables"));
    clearCustomVarsButton->setProperty("mdButton", true);
    clearCustomVarsButton->setStyleSheet(QStringLiteral("QPushButton {margin-top: 15px}"));

    auto varLayout = new QGridLayout;
    varLayout->addWidget(variableView_, 0, 0, -1, 1);
    varLayout->addLayout(buttonsLayout, 0, 1, 1, 1);
    varLayout->setColumnStretch(0, 1);
    varLayout->setColumnStretch(1, 0);
    varLayout->setRowStretch(2, 0);
    varLayout->setSizeConstraint(QLayout::SetNoConstraint);

    auto varGroup = new QGroupBox(tr("Data Columns Info"));
    varGroup->setObjectName(QStringLiteral("simpleGroupBox"));
    varGroup->setFlat(true);
    varGroup->setLayout(varLayout);

    auto varScrollArea = new QScrollArea;
    varScrollArea->setWidget(varGroup);
    varScrollArea->setWidgetResizable(true);

    auto mainlayout = new QGridLayout(this);
    mainlayout->setRowMinimumHeight(0, 18);
    mainlayout->addWidget(rawSettingsButton, 1, 0, 1, 1, Qt::AlignTop);
    mainlayout->addWidget(clearCustomVarsButton, 2, 0, 1, 1, Qt::AlignTop);
    mainlayout->addWidget(varScrollArea, 0, 1, -1, -1);
    mainlayout->setRowStretch(3, 1);
    mainlayout->setColumnStretch(1, 1);
    mainlayout->setSizeConstraint(QLayout::SetNoConstraint);
    setLayout(mainlayout);

    connect(variableModel_, &VariableModel::modified, [=]()
            { dlProject_->setModified(true); });

    connect(dlProject, &DlProject::projectModified,
            this, &DlRawfileDescTab::updateModels);

    connect(dlProject, &DlProject::projectChanged,
            this, &DlRawfileDescTab::updateModels);

    connect(addButton, &QToolButton::clicked,
            variableView_, &VariableView::addVar);
    connect(removeButton, &QToolButton::clicked,
            variableView_, &VariableView::removeVar);

    connect(rawSettingsButton, &QPushButton::clicked,
            this, &DlRawfileDescTab::showRawSettingsDialog);

    connect(clearCustomVarsButton, &QPushButton::clicked,[=]()
            { variableDelegate_->clearCustomVariableBuffer(); });

    // to trigger table editing with single click without altering the
    // editTriggers property, because that way the column selection
    // clicking on the header trigger the first cell editor
    connect(variableView_, SIGNAL(clicked(const QModelIndex &)),
            variableView_, SLOT(edit(const QModelIndex &)));
}
BinarySettingsDialog::BinarySettingsDialog(QWidget* parent, EcProject *ecProject)
    : QDialog(parent),
    ecProject_(ecProject)
{
    setWindowModality(Qt::WindowModal);
    setWindowTitle(tr("Generic Binary File Settings"));
    WidgetUtils::removeContextHelpButton(this);

    auto groupTitle = new QLabel;
    groupTitle->setText(tr("Please provide details of your binary format."));

    auto hrLabel = new QLabel;
    hrLabel->setObjectName(QStringLiteral("hrLabel"));

    binaryHLinesLabel = new ClickLabel(tr("Number of ASCII header lines :"));
    binaryHLinesLabel->setToolTip(tr("<b>Number of ASCII header lines:</b> Enter the number of ASCII (readable text) header lines present at the beginning of your binary files. Enter 0 if there is no ASCII header."));
    binaryHLinesSpin = new QSpinBox(this);
    binaryHLinesSpin->setRange(-1, 100);
    binaryHLinesSpin->setSingleStep(1);
    binaryHLinesSpin->setSpecialValueText(tr("Not set"));
    binaryHLinesSpin->setAccelerated(true);
    binaryHLinesSpin->setToolTip(binaryHLinesLabel->toolTip());

    qDebug() << "binaryHLinesSpin 1" << binaryHLinesSpin->focusPolicy();

    binaryEolLabel = new ClickLabel(tr("ASCII header end of line :"));
    binaryEolLabel->setToolTip(tr("<b>ASCII header end of line:</b> If an ASCII header is present in the files, specify the line terminator. Typically, Windows OS uses <i>CR+LF</i> (0x0D+0x0A), Linux OS and Mac OS X use <i>LF</i> (0x0A), while Mac OS up to version 9 and OS-9 use <i>CR</i> (0x0D)."));
    binaryEolCombo = new QComboBox;
    binaryEolCombo->addItem(tr("CR+LF"));
    binaryEolCombo->addItem(tr("CR"));
    binaryEolCombo->addItem(tr("LF"));
    binaryEolCombo->setToolTip(binaryEolLabel->toolTip());

    binaryNBytesLabel = new ClickLabel(tr("Number of bytes per variable :"));
    binaryNBytesLabel->setToolTip(tr("<b>Number of bytes per variable:</b> Specify the number of bytes reserved for each variable stored as a single precision number. Typically 2 bytes are reserved for each number."));
    binaryNBytesSpin = new QSpinBox(this);
    binaryNBytesSpin->setRange(0, 8);
    binaryNBytesSpin->setSingleStep(1);
    binaryNBytesSpin->setSpecialValueText(tr("Not set"));
    binaryNBytesSpin->setAccelerated(true);
    binaryNBytesSpin->setToolTip(binaryNBytesLabel->toolTip());

    binaryEndianessLabel = new ClickLabel(tr("Endianess :"));
    binaryEndianessLabel->setToolTip(tr("<b>Endianess:</b> In a multi-bytes binary word, <i>Little endian</i> means that the most significant byte is the last byte (highest address); <i>Big endian</i> means that the most significant byte is the first byte (lowest address)."));
    binaryEndianessCombo = new QComboBox;
    binaryEndianessCombo->addItem(tr("Big endian"));
    binaryEndianessCombo->addItem(tr("Little endian"));
    binaryEndianessCombo->setMinimumWidth(10);
    binaryEndianessCombo->setToolTip(binaryEndianessLabel->toolTip());

    auto binPropertiesLayout = new QGridLayout;
    binPropertiesLayout->addWidget(binaryHLinesLabel, 0, 0, 1, 1, Qt::AlignRight);
    binPropertiesLayout->addWidget(binaryHLinesSpin, 0, 1);
    binPropertiesLayout->addWidget(binaryEolLabel, 1, 0, 1, 1, Qt::AlignRight);
    binPropertiesLayout->addWidget(binaryEolCombo, 1, 1);
    binPropertiesLayout->addWidget(binaryNBytesLabel, 2, 0, 1, 1, Qt::AlignRight);
    binPropertiesLayout->addWidget(binaryNBytesSpin, 2, 1);
    binPropertiesLayout->addWidget(binaryEndianessLabel, 3, 0, 1, 1, Qt::AlignRight);
    binPropertiesLayout->addWidget(binaryEndianessCombo, 3, 1);
    binPropertiesLayout->setVerticalSpacing(3);
    binPropertiesLayout->setContentsMargins(3, 3, 3, 3);

    auto binPropertiesWidget = new QWidget;
    binPropertiesWidget->setLayout(binPropertiesLayout);

    auto okButton = WidgetUtils::createCommonButton(this, tr("Ok"));

    auto mainLayout = new QGridLayout(this);
    mainLayout->addWidget(groupTitle, 0, 0);
    mainLayout->addWidget(hrLabel, 1, 0);
    mainLayout->addWidget(binPropertiesWidget, 2, 0);
    mainLayout->addWidget(okButton, 3, 0, 1, 1, Qt::AlignCenter);
    mainLayout->setVerticalSpacing(10);
    mainLayout->setContentsMargins(30, 30, 30, 30);
    mainLayout->setSizeConstraint(QLayout::SetFixedSize);
    setLayout(mainLayout);

    connect(binaryHLinesLabel, &ClickLabel::clicked,
            this, &BinarySettingsDialog::onBinaryHLinesLabelClicked);
    connect(binaryHLinesSpin, SIGNAL(valueChanged(int)),
            this, SLOT(updateBinaryHLine(int)));

    connect(binaryEolLabel, &ClickLabel::clicked,
            this, &BinarySettingsDialog::onBinaryClickEolLabel);
    connect(binaryEolCombo, SIGNAL(currentIndexChanged(int)),
            this, SLOT(updateBinaryEol(int)));

    connect(binaryNBytesLabel, &ClickLabel::clicked,
            this, &BinarySettingsDialog::onBinaryNBytesLabelClicked);
    connect(binaryNBytesSpin, SIGNAL(valueChanged(int)),
            this, SLOT(updateBinaryNBytes(int)));

    connect(binaryEndianessLabel, &ClickLabel::clicked,
            this, &BinarySettingsDialog::onBinaryClickEndianessLabel);
    connect(binaryEndianessCombo, SIGNAL(currentIndexChanged(int)),
            this, SLOT(updateBinaryEndianess(int)));

    connect(okButton, &QPushButton::clicked,
            this, &BinarySettingsDialog::close);
}
DummyLayout::DummyLayout()
{
	setSizeConstraint(QLayout::SetNoConstraint);
}