2013-08-09 06:57:18 +02:00
|
|
|
#include "lc_global.h"
|
|
|
|
#include "lc_qutils.h"
|
|
|
|
#include "lc_application.h"
|
|
|
|
#include "lc_library.h"
|
2023-12-31 21:55:35 +01:00
|
|
|
#include "lc_model.h"
|
2013-08-09 06:57:18 +02:00
|
|
|
#include "pieceinf.h"
|
|
|
|
|
2017-07-27 02:34:25 +02:00
|
|
|
QString lcFormatValue(float Value, int Precision)
|
2015-01-20 00:48:46 +01:00
|
|
|
{
|
2017-07-27 02:34:25 +02:00
|
|
|
QString String = QString::number(Value, 'f', Precision);
|
2021-11-15 03:34:24 +01:00
|
|
|
const int Dot = String.indexOf('.');
|
2015-01-20 00:48:46 +01:00
|
|
|
|
|
|
|
if (Dot != -1)
|
|
|
|
{
|
|
|
|
while (String.endsWith('0'))
|
|
|
|
String.chop(1);
|
|
|
|
|
|
|
|
if (String.endsWith('.'))
|
|
|
|
String.chop(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return String;
|
|
|
|
}
|
|
|
|
|
2016-06-13 03:46:50 +02:00
|
|
|
QString lcFormatValueLocalized(float Value)
|
|
|
|
{
|
2016-06-14 01:57:31 +02:00
|
|
|
QLocale Locale = QLocale::system();
|
2016-06-14 02:18:24 +02:00
|
|
|
Locale.setNumberOptions(QLocale::OmitGroupSeparator);
|
2021-07-06 02:00:41 +02:00
|
|
|
QString DecimalPoint = Locale.decimalPoint();
|
2017-07-21 02:57:07 +02:00
|
|
|
QString String = Locale.toString(Value, 'f', 4);
|
2016-06-14 01:57:31 +02:00
|
|
|
|
|
|
|
if (String.indexOf(DecimalPoint) != -1)
|
|
|
|
{
|
|
|
|
while (String.endsWith('0'))
|
|
|
|
String.chop(1);
|
|
|
|
|
|
|
|
if (String.endsWith(DecimalPoint))
|
|
|
|
String.chop(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return String;
|
|
|
|
}
|
|
|
|
|
|
|
|
float lcParseValueLocalized(const QString& Value)
|
|
|
|
{
|
|
|
|
return QLocale::system().toFloat(Value);
|
2016-06-13 03:46:50 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
// Resize all columns to content except for one stretching column. (taken from QT creator)
|
|
|
|
lcQTreeWidgetColumnStretcher::lcQTreeWidgetColumnStretcher(QTreeWidget *treeWidget, int columnToStretch)
|
2022-09-08 08:45:17 +02:00
|
|
|
: QObject(treeWidget->header()), m_columnToStretch(columnToStretch), m_interactiveResize(false), m_stretchWidth(0)
|
2013-08-09 06:57:18 +02:00
|
|
|
{
|
|
|
|
parent()->installEventFilter(this);
|
2022-09-07 17:58:26 +02:00
|
|
|
connect(treeWidget->header(), SIGNAL(sectionResized(int, int, int)), SLOT(sectionResized(int, int, int)));
|
2013-08-09 06:57:18 +02:00
|
|
|
QHideEvent fake;
|
|
|
|
lcQTreeWidgetColumnStretcher::eventFilter(parent(), &fake);
|
|
|
|
}
|
|
|
|
|
2022-09-07 17:58:26 +02:00
|
|
|
void lcQTreeWidgetColumnStretcher::sectionResized(int LogicalIndex, int OldSize, int NewSize)
|
|
|
|
{
|
|
|
|
Q_UNUSED(OldSize)
|
|
|
|
|
2022-09-08 08:45:17 +02:00
|
|
|
if (LogicalIndex == m_columnToStretch)
|
|
|
|
{
|
|
|
|
QHeaderView* HeaderView = qobject_cast<QHeaderView*>(parent());
|
|
|
|
|
|
|
|
if (HeaderView->isVisible())
|
|
|
|
m_interactiveResize = true;
|
|
|
|
|
|
|
|
m_stretchWidth = NewSize;
|
|
|
|
}
|
2022-09-07 17:58:26 +02:00
|
|
|
}
|
|
|
|
|
2021-11-15 03:34:24 +01:00
|
|
|
bool lcQTreeWidgetColumnStretcher::eventFilter(QObject* Object, QEvent* Event)
|
2013-08-09 06:57:18 +02:00
|
|
|
{
|
2021-11-15 03:34:24 +01:00
|
|
|
if (Object == parent())
|
2013-08-09 06:57:18 +02:00
|
|
|
{
|
2022-09-07 17:58:26 +02:00
|
|
|
QHeaderView* HeaderView = qobject_cast<QHeaderView*>(Object);
|
|
|
|
|
2021-11-15 03:34:24 +01:00
|
|
|
if (Event->type() == QEvent::Show)
|
2013-08-09 06:57:18 +02:00
|
|
|
{
|
2021-01-08 19:35:52 +01:00
|
|
|
for (int i = 0; i < HeaderView->count(); ++i)
|
|
|
|
HeaderView->setSectionResizeMode(i, QHeaderView::Interactive);
|
2022-09-07 17:58:26 +02:00
|
|
|
|
|
|
|
m_stretchWidth = HeaderView->sectionSize(m_columnToStretch);
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
}
|
2021-11-15 03:34:24 +01:00
|
|
|
else if (Event->type() == QEvent::Hide)
|
2013-08-09 06:57:18 +02:00
|
|
|
{
|
2022-09-08 08:45:17 +02:00
|
|
|
if (!m_interactiveResize)
|
|
|
|
for (int i = 0; i < HeaderView->count(); ++i)
|
|
|
|
HeaderView->setSectionResizeMode(i, i == m_columnToStretch ? QHeaderView::Stretch : QHeaderView::ResizeToContents);
|
2013-08-09 06:57:18 +02:00
|
|
|
}
|
2021-11-15 03:34:24 +01:00
|
|
|
else if (Event->type() == QEvent::Resize)
|
2013-08-09 06:57:18 +02:00
|
|
|
{
|
2022-09-07 17:58:26 +02:00
|
|
|
if (HeaderView->sectionResizeMode(m_columnToStretch) == QHeaderView::Interactive) {
|
|
|
|
|
|
|
|
const int StretchWidth = HeaderView->isVisible() ? m_stretchWidth : 32;
|
2021-01-08 19:35:52 +01:00
|
|
|
|
2022-09-07 17:58:26 +02:00
|
|
|
HeaderView->resizeSection(m_columnToStretch, StretchWidth);
|
2013-08-09 06:57:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2023-12-31 21:55:35 +01:00
|
|
|
|
|
|
|
lcPieceIdStringModel::lcPieceIdStringModel(lcModel* Model, QObject* Parent)
|
|
|
|
: QAbstractListModel(Parent)
|
|
|
|
{
|
|
|
|
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
|
|
|
mSortedPieces.reserve(Library->mPieces.size());
|
|
|
|
|
|
|
|
for (const auto& PartIt : Library->mPieces)
|
|
|
|
{
|
|
|
|
PieceInfo* Info = PartIt.second;
|
|
|
|
|
|
|
|
if (!Info->IsModel() || !Info->GetModel()->IncludesModel(Model))
|
|
|
|
mSortedPieces.push_back(PartIt.second);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto PieceCompare = [](PieceInfo* Info1, PieceInfo* Info2)
|
|
|
|
{
|
|
|
|
return strcmp(Info1->m_strDescription, Info2->m_strDescription) < 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::sort(mSortedPieces.begin(), mSortedPieces.end(), PieceCompare);
|
|
|
|
}
|
|
|
|
|
|
|
|
QModelIndex lcPieceIdStringModel::Index(PieceInfo* Info) const
|
|
|
|
{
|
|
|
|
for (size_t PieceInfoIndex = 0; PieceInfoIndex < mSortedPieces.size(); PieceInfoIndex++)
|
|
|
|
if (mSortedPieces[PieceInfoIndex] == Info)
|
|
|
|
return index(static_cast<int>(PieceInfoIndex), 0);
|
|
|
|
|
|
|
|
return QModelIndex();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<bool> lcPieceIdStringModel::GetFilteredRows(const QString& FilterText) const
|
|
|
|
{
|
|
|
|
const std::string Text = FilterText.toStdString();
|
|
|
|
std::vector<bool> FilteredRows(mSortedPieces.size());
|
|
|
|
|
|
|
|
for (size_t PieceInfoIndex = 0; PieceInfoIndex < mSortedPieces.size(); PieceInfoIndex++)
|
|
|
|
{
|
|
|
|
const PieceInfo* Info = mSortedPieces[PieceInfoIndex];
|
|
|
|
|
|
|
|
FilteredRows[PieceInfoIndex] = (strcasestr(Info->m_strDescription, Text.c_str()) || strcasestr(Info->mFileName, Text.c_str()));
|
|
|
|
}
|
|
|
|
|
|
|
|
return FilteredRows;
|
|
|
|
}
|
|
|
|
|
|
|
|
int lcPieceIdStringModel::rowCount(const QModelIndex& Parent) const
|
|
|
|
{
|
|
|
|
Q_UNUSED(Parent);
|
|
|
|
|
|
|
|
return static_cast<int>(mSortedPieces.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant lcPieceIdStringModel::data(const QModelIndex& Index, int Role) const
|
|
|
|
{
|
|
|
|
if (Index.row() < static_cast<int>(mSortedPieces.size()))
|
|
|
|
{
|
|
|
|
if (Role == Qt::DisplayRole)
|
|
|
|
return QString::fromLatin1(mSortedPieces[Index.row()]->m_strDescription);
|
|
|
|
else if (Role == Qt::UserRole)
|
|
|
|
return QVariant::fromValue(reinterpret_cast<void*>(mSortedPieces[Index.row()]));
|
|
|
|
}
|
|
|
|
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
|
|
|
|
lcPieceIdPickerPopup::lcPieceIdPickerPopup(lcModel* Model, PieceInfo* Current, QWidget* Parent)
|
|
|
|
: QWidget(Parent)
|
|
|
|
{
|
|
|
|
QVBoxLayout* Layout = new QVBoxLayout(this);
|
2024-06-02 02:20:44 +02:00
|
|
|
|
|
|
|
mFilterEdit = new QLineEdit(this);
|
|
|
|
mFilterEdit->setPlaceholderText(tr("Filter"));
|
|
|
|
Layout->addWidget(mFilterEdit);
|
|
|
|
|
|
|
|
connect(mFilterEdit, &QLineEdit::textEdited, this, &lcPieceIdPickerPopup::FilterEdited);
|
2023-12-31 21:55:35 +01:00
|
|
|
|
|
|
|
mListView = new QListView(this);
|
|
|
|
mListView->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
|
|
mListView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
|
|
mListView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
|
|
mListView->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
|
|
mListView->setUniformItemSizes(true);
|
|
|
|
|
|
|
|
mListView->installEventFilter(this);
|
|
|
|
|
|
|
|
lcPieceIdStringModel* StringModel = new lcPieceIdStringModel(Model, mListView);
|
|
|
|
mListView->setModel(StringModel);
|
|
|
|
|
2024-06-02 02:20:44 +02:00
|
|
|
mListView->setMinimumWidth(450);
|
|
|
|
mListView->setTextElideMode(Qt::ElideMiddle);
|
|
|
|
|
2023-12-31 21:55:35 +01:00
|
|
|
if (Current)
|
|
|
|
mListView->setCurrentIndex(StringModel->Index(Current));
|
|
|
|
|
|
|
|
Layout->addWidget(mListView);
|
|
|
|
|
|
|
|
connect(mListView, &QListView::doubleClicked, this, &lcPieceIdPickerPopup::ListViewDoubleClicked);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lcPieceIdPickerPopup::eventFilter(QObject* Object, QEvent* Event)
|
|
|
|
{
|
|
|
|
if (Object == mListView && Event->type() == QEvent::KeyPress)
|
|
|
|
{
|
|
|
|
EmitSelectedEvent(mListView->currentIndex());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return QWidget::eventFilter(Object, Event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcPieceIdPickerPopup::EmitSelectedEvent(const QModelIndex& Index)
|
|
|
|
{
|
|
|
|
if (!Index.isValid())
|
|
|
|
return;
|
|
|
|
|
|
|
|
lcPieceIdStringModel* StringModel = qobject_cast<lcPieceIdStringModel*>(mListView->model());
|
|
|
|
QVariant Variant = StringModel->data(Index, Qt::UserRole);
|
|
|
|
|
|
|
|
if (Variant.isValid())
|
|
|
|
{
|
|
|
|
emit PieceIdSelected(static_cast<PieceInfo*>(Variant.value<void*>()));
|
|
|
|
}
|
|
|
|
|
|
|
|
QMenu* Menu = qobject_cast<QMenu*>(parent());
|
|
|
|
Menu->close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcPieceIdPickerPopup::ListViewDoubleClicked(const QModelIndex& Index)
|
|
|
|
{
|
|
|
|
EmitSelectedEvent(Index);
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcPieceIdPickerPopup::FilterEdited(const QString& Text)
|
|
|
|
{
|
|
|
|
lcPieceIdStringModel* StringModel = qobject_cast<lcPieceIdStringModel*>(mListView->model());
|
|
|
|
std::vector<bool> FilteredRows = StringModel->GetFilteredRows(Text);
|
|
|
|
|
|
|
|
mListView->setUpdatesEnabled(false);
|
|
|
|
|
|
|
|
for (int Row = 0; Row < static_cast<int>(FilteredRows.size()); Row++)
|
|
|
|
mListView->setRowHidden(Row, !FilteredRows[Row]);
|
|
|
|
|
|
|
|
mListView->setUpdatesEnabled(true);
|
|
|
|
}
|