1 #include "lc_global.h"
2 #include "lc_partselectionwidget.h"
3 #include "lc_partpalettedialog.h"
4 #include "lc_profile.h"
5 #include "lc_application.h"
6 #include "lc_mainwindow.h"
7 #include "lc_library.h"
8 #include "lc_model.h"
9 #include "project.h"
10 #include "pieceinf.h"
11 #include "camera.h"
12 #include "lc_scene.h"
13 #include "lc_view.h"
14 #include "lc_glextensions.h"
15 #include "lc_category.h"
16 
Q_DECLARE_METATYPE(QList<int>)17 Q_DECLARE_METATYPE(QList<int>)
18 
19 void lcPartSelectionItemDelegate::paint(QPainter* Painter, const QStyleOptionViewItem& Option, const QModelIndex& Index) const
20 {
21 	mListModel->RequestPreview(Index.row());
22 	QStyledItemDelegate::paint(Painter, Option, Index);
23 }
24 
sizeHint(const QStyleOptionViewItem & Option,const QModelIndex & Index) const25 QSize lcPartSelectionItemDelegate::sizeHint(const QStyleOptionViewItem& Option, const QModelIndex& Index) const
26 {
27 	QSize Size = QStyledItemDelegate::sizeHint(Option, Index);
28 	int IconSize = mListModel->GetIconSize();
29 
30 	if (IconSize)
31 	{
32 		QWidget* Widget = (QWidget*)parent();
33 		const int PixmapMargin = Widget->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &Option, Widget) + 1;
34 		int PixmapWidth = IconSize + 2 * PixmapMargin;
35 		Size.setWidth(qMin(PixmapWidth, Size.width()));
36 	}
37 
38 	return Size;
39 }
40 
lcPartSelectionListModel(QObject * Parent)41 lcPartSelectionListModel::lcPartSelectionListModel(QObject* Parent)
42 	: QAbstractListModel(Parent)
43 {
44 	mListView = (lcPartSelectionListView*)Parent;
45 	mIconSize = 0;
46 	mShowPartNames = lcGetProfileInt(LC_PROFILE_PARTS_LIST_NAMES);
47 	mListMode = lcGetProfileInt(LC_PROFILE_PARTS_LIST_LISTMODE);
48 	mShowDecoratedParts = lcGetProfileInt(LC_PROFILE_PARTS_LIST_DECORATED);
49 	mShowPartAliases = lcGetProfileInt(LC_PROFILE_PARTS_LIST_ALIASES);
50 
51 	int ColorCode = lcGetProfileInt(LC_PROFILE_PARTS_LIST_COLOR);
52 	if (ColorCode == -1)
53 	{
54 		mColorIndex = gMainWindow->mColorIndex;
55 		mColorLocked = false;
56 	}
57 	else
58 	{
59 		mColorIndex = lcGetColorIndex(ColorCode);
60 		mColorLocked = true;
61 	}
62 
63 	connect(lcGetPiecesLibrary(), SIGNAL(PartLoaded(PieceInfo*)), this, SLOT(PartLoaded(PieceInfo*)));
64 }
65 
~lcPartSelectionListModel()66 lcPartSelectionListModel::~lcPartSelectionListModel()
67 {
68 	ClearRequests();
69 
70 	mView.reset();
71 	mModel.reset();
72 }
73 
ClearRequests()74 void lcPartSelectionListModel::ClearRequests()
75 {
76 	lcPiecesLibrary* Library = lcGetPiecesLibrary();
77 
78 	for (int RequestIdx : mRequestedPreviews)
79 	{
80 		PieceInfo* Info = mParts[RequestIdx].first;
81 		Library->ReleasePieceInfo(Info);
82 	}
83 
84 	mRequestedPreviews.clear();
85 }
86 
Redraw()87 void lcPartSelectionListModel::Redraw()
88 {
89 	ClearRequests();
90 
91 	beginResetModel();
92 
93 	for (size_t PartIdx = 0; PartIdx < mParts.size(); PartIdx++)
94 		mParts[PartIdx].second = QPixmap();
95 
96 	endResetModel();
97 
98 	SetFilter(mFilter);
99 }
100 
SetColorIndex(int ColorIndex)101 void lcPartSelectionListModel::SetColorIndex(int ColorIndex)
102 {
103 	if (mColorLocked || ColorIndex == mColorIndex)
104 		return;
105 
106 	mColorIndex = ColorIndex;
107 	Redraw();
108 }
109 
ToggleColorLocked()110 void lcPartSelectionListModel::ToggleColorLocked()
111 {
112 	mColorLocked = !mColorLocked;
113 
114 	SetColorIndex(gMainWindow->mColorIndex);
115 	lcSetProfileInt(LC_PROFILE_PARTS_LIST_COLOR, mColorLocked ? lcGetColorCode(mColorIndex) : -1);
116 }
117 
ToggleListMode()118 void lcPartSelectionListModel::ToggleListMode()
119 {
120 	mListMode = !mListMode;
121 
122 	mListView->UpdateViewMode();
123 	lcSetProfileInt(LC_PROFILE_PARTS_LIST_LISTMODE, mListMode);
124 }
125 
SetCategory(int CategoryIndex)126 void lcPartSelectionListModel::SetCategory(int CategoryIndex)
127 {
128 	ClearRequests();
129 
130 	beginResetModel();
131 
132 	lcPiecesLibrary* Library = lcGetPiecesLibrary();
133 	lcArray<PieceInfo*> SingleParts, GroupedParts;
134 
135 	if (CategoryIndex != -1)
136 		Library->GetCategoryEntries(CategoryIndex, false, SingleParts, GroupedParts);
137 	else
138 	{
139 		Library->GetParts(SingleParts);
140 
141 		lcModel* ActiveModel = gMainWindow->GetActiveModel();
142 
143 		for (int PartIdx = 0; PartIdx < SingleParts.GetSize(); )
144 		{
145 			PieceInfo* Info = SingleParts[PartIdx];
146 
147 			if (!Info->IsModel() || !Info->GetModel()->IncludesModel(ActiveModel))
148 				PartIdx++;
149 			else
150 				SingleParts.RemoveIndex(PartIdx);
151 		}
152 	}
153 
154 	auto lcPartSortFunc=[](const PieceInfo* a, const PieceInfo* b)
155 	{
156 		return strcmp(a->m_strDescription, b->m_strDescription) < 0;
157 	};
158 
159 	std::sort(SingleParts.begin(), SingleParts.end(), lcPartSortFunc);
160 
161 	mParts.resize(SingleParts.GetSize());
162 
163 	for (int PartIdx = 0; PartIdx < SingleParts.GetSize(); PartIdx++)
164 		mParts[PartIdx] = std::pair<PieceInfo*, QPixmap>(SingleParts[PartIdx], QPixmap());
165 
166 	endResetModel();
167 
168 	SetFilter(mFilter);
169 }
170 
SetModelsCategory()171 void lcPartSelectionListModel::SetModelsCategory()
172 {
173 	ClearRequests();
174 
175 	beginResetModel();
176 
177 	mParts.clear();
178 
179 	const lcArray<lcModel*>& Models = lcGetActiveProject()->GetModels();
180 	lcModel* ActiveModel = gMainWindow->GetActiveModel();
181 
182 	for (int ModelIdx = 0; ModelIdx < Models.GetSize(); ModelIdx++)
183 	{
184 		lcModel* Model = Models[ModelIdx];
185 
186 		if (!Model->IncludesModel(ActiveModel))
187 			mParts.emplace_back(std::pair<PieceInfo*, QPixmap>(Model->GetPieceInfo(), QPixmap()));
188 	}
189 
190 	auto lcPartSortFunc = [](const std::pair<PieceInfo*, QPixmap>& a, const std::pair<PieceInfo*, QPixmap>& b)
191 	{
192 		return strcmp(a.first->m_strDescription, b.first->m_strDescription) < 0;
193 	};
194 
195 	std::sort(mParts.begin(), mParts.end(), lcPartSortFunc);
196 
197 	endResetModel();
198 
199 	SetFilter(mFilter);
200 }
201 
SetPaletteCategory(int SetIndex)202 void lcPartSelectionListModel::SetPaletteCategory(int SetIndex)
203 {
204 	ClearRequests();
205 
206 	beginResetModel();
207 
208 	mParts.clear();
209 
210 	lcPartSelectionWidget* PartSelectionWidget = mListView->GetPartSelectionWidget();
211 	const std::vector<lcPartPalette>& Palettes = PartSelectionWidget->GetPartPalettes();
212 	std::vector<PieceInfo*> PartsList = lcGetPiecesLibrary()->GetPartsFromSet(Palettes[SetIndex].Parts);
213 
214 	auto lcPartSortFunc = [](const PieceInfo* a, const PieceInfo* b)
215 	{
216 		return strcmp(a->m_strDescription, b->m_strDescription) < 0;
217 	};
218 
219 	std::sort(PartsList.begin(), PartsList.end(), lcPartSortFunc);
220 
221 	mParts.reserve(PartsList.size());
222 
223 	for (PieceInfo* Favorite : PartsList)
224 		mParts.emplace_back(std::pair<PieceInfo*, QPixmap>(Favorite, QPixmap()));
225 
226 	endResetModel();
227 
228 	SetFilter(mFilter);
229 }
230 
SetCurrentModelCategory()231 void lcPartSelectionListModel::SetCurrentModelCategory()
232 {
233 	ClearRequests();
234 
235 	beginResetModel();
236 
237 	mParts.clear();
238 
239 	lcModel* ActiveModel = gMainWindow->GetActiveModel();
240 	lcPartsList PartsList;
241 
242 	if (ActiveModel)
243 		ActiveModel->GetPartsList(gDefaultColor, true, true, PartsList);
244 
245 	for (const auto& PartIt : PartsList)
246 		mParts.emplace_back(std::pair<PieceInfo*, QPixmap>((PieceInfo*)PartIt.first, QPixmap()));
247 
248 	auto lcPartSortFunc = [](const std::pair<PieceInfo*, QPixmap>& a, const std::pair<PieceInfo*, QPixmap>& b)
249 	{
250 		return strcmp(a.first->m_strDescription, b.first->m_strDescription) < 0;
251 	};
252 
253 	std::sort(mParts.begin(), mParts.end(), lcPartSortFunc);
254 
255 	endResetModel();
256 
257 	SetFilter(mFilter);
258 }
259 
SetFilter(const QString & Filter)260 void lcPartSelectionListModel::SetFilter(const QString& Filter)
261 {
262 	mFilter = Filter.toLatin1();
263 
264 	for (size_t PartIdx = 0; PartIdx < mParts.size(); PartIdx++)
265 	{
266 		PieceInfo* Info = mParts[PartIdx].first;
267 		bool Visible;
268 
269 		if (!mShowDecoratedParts && Info->IsPatterned())
270 			Visible = false;
271 		else if (!mShowPartAliases && Info->m_strDescription[0] == '=')
272 			Visible = false;
273 		else if (mFilter.isEmpty())
274 			Visible = true;
275 		else
276 		{
277 			char Description[sizeof(Info->m_strDescription)];
278 			char* Src = Info->m_strDescription;
279 			char* Dst = Description;
280 
281 			for (;;)
282 			{
283 				*Dst = *Src;
284 
285 				if (*Src == ' ' && *(Src + 1) == ' ')
286 					Src++;
287 				else if (*Src == 0)
288 					break;
289 
290 				Src++;
291 				Dst++;
292 			}
293 
294 			Visible = strcasestr(Description, mFilter) || strcasestr(Info->mFileName, mFilter);
295 		}
296 
297 		mListView->setRowHidden((int)PartIdx, !Visible);
298 	}
299 }
300 
rowCount(const QModelIndex & Parent) const301 int lcPartSelectionListModel::rowCount(const QModelIndex& Parent) const
302 {
303 	Q_UNUSED(Parent);
304 
305 	return (int)mParts.size();
306 }
307 
data(const QModelIndex & Index,int Role) const308 QVariant lcPartSelectionListModel::data(const QModelIndex& Index, int Role) const
309 {
310 	size_t InfoIndex = Index.row();
311 
312 	if (Index.isValid() && InfoIndex < mParts.size())
313 	{
314 		PieceInfo* Info = mParts[InfoIndex].first;
315 
316 		switch (Role)
317 		{
318 		case Qt::DisplayRole:
319 			if (!mIconSize || mShowPartNames || mListMode)
320 				return QVariant(QString::fromLatin1(Info->m_strDescription));
321 			break;
322 
323 		case Qt::ToolTipRole:
324 			return QVariant(QString("%1 (%2)").arg(QString::fromLatin1(Info->m_strDescription), QString::fromLatin1(Info->mFileName)));
325 
326 		case Qt::DecorationRole:
327 			if (!mParts[InfoIndex].second.isNull() && mIconSize)
328 				return QVariant(mParts[InfoIndex].second);
329 			else
330 				return QVariant(QColor(0, 0, 0, 0));
331 
332 		default:
333 			break;
334 		}
335 	}
336 
337 	return QVariant();
338 }
339 
headerData(int Section,Qt::Orientation Orientation,int Role) const340 QVariant lcPartSelectionListModel::headerData(int Section, Qt::Orientation Orientation, int Role) const
341 {
342 	Q_UNUSED(Section);
343 	Q_UNUSED(Orientation);
344 
345 	return Role == Qt::DisplayRole ? QVariant(QLatin1String("Image")) : QVariant();
346 }
347 
flags(const QModelIndex & Index) const348 Qt::ItemFlags lcPartSelectionListModel::flags(const QModelIndex& Index) const
349 {
350 	Qt::ItemFlags DefaultFlags = QAbstractListModel::flags(Index);
351 
352 	if (Index.isValid())
353 		return Qt::ItemIsDragEnabled | DefaultFlags;
354 	else
355 		return DefaultFlags;
356 }
357 
RequestPreview(int InfoIndex)358 void lcPartSelectionListModel::RequestPreview(int InfoIndex)
359 {
360 	if (!mIconSize || !mParts[InfoIndex].second.isNull())
361 		return;
362 
363 	if (std::find(mRequestedPreviews.begin(), mRequestedPreviews.end(), InfoIndex) != mRequestedPreviews.end())
364 		return;
365 
366 	PieceInfo* Info = mParts[InfoIndex].first;
367 	lcGetPiecesLibrary()->LoadPieceInfo(Info, false, false);
368 
369 	if (Info->mState == LC_PIECEINFO_LOADED)
370 		DrawPreview(InfoIndex);
371 	else
372 		mRequestedPreviews.push_back(InfoIndex);
373 }
374 
PartLoaded(PieceInfo * Info)375 void lcPartSelectionListModel::PartLoaded(PieceInfo* Info)
376 {
377 	for (size_t PartIdx = 0; PartIdx < mParts.size(); PartIdx++)
378 	{
379 		if (mParts[PartIdx].first == Info)
380 		{
381 			auto PreviewIt = std::find(mRequestedPreviews.begin(), mRequestedPreviews.end(), static_cast<int>(PartIdx));
382 			if (PreviewIt != mRequestedPreviews.end())
383 			{
384 				mRequestedPreviews.erase(PreviewIt);
385 				DrawPreview((int)PartIdx);
386 			}
387 			break;
388 		}
389 	}
390 }
391 
DrawPreview(int InfoIndex)392 void lcPartSelectionListModel::DrawPreview(int InfoIndex)
393 {
394 	const int Width = mIconSize * 2;
395 	const int Height = mIconSize * 2;
396 
397 	if (mView && (mView->GetWidth() != Width || mView->GetHeight() != Height))
398 		mView.reset();
399 
400 	if (!mView)
401 	{
402 		if (!mModel)
403 			mModel = std::unique_ptr<lcModel>(new lcModel(QString(), nullptr, true));
404 		mView = std::unique_ptr<lcView>(new lcView(lcViewType::PartsList, mModel.get()));
405 
406 		mView->SetOffscreenContext();
407 		mView->MakeCurrent();
408 		mView->SetSize(Width, Height);
409 
410 		if (!mView->BeginRenderToImage(Width, Height))
411 		{
412 			mView.reset();
413 			return;
414 		}
415 	}
416 
417 	mView->MakeCurrent();
418 	mView->BindRenderFramebuffer();
419 
420 	const uint BackgroundColor = mListView->palette().color(QPalette::Base).rgba();
421 	mView->SetBackgroundColorOverride(LC_RGBA(qRed(BackgroundColor), qGreen(BackgroundColor), qBlue(BackgroundColor), 0));
422 
423 	PieceInfo* Info = mParts[InfoIndex].first;
424 	mModel->SetPreviewPieceInfo(Info, mColorIndex);
425 
426 	const lcVector3 Center = (Info->GetBoundingBox().Min + Info->GetBoundingBox().Max) / 2.0f;
427 	const lcVector3 Position = Center + lcVector3(100.0f, -100.0f, 75.0f);
428 
429 	mView->GetCamera()->SetViewpoint(Position, Center, lcVector3(0, 0, 1));
430 	mView->GetCamera()->m_fovy = 20.0f;
431 	mView->ZoomExtents();
432 
433 	mView->OnDraw();
434 
435 	mView->UnbindRenderFramebuffer();
436 
437 	QImage Image = mView->GetRenderFramebufferImage().convertToFormat(QImage::Format_ARGB32);
438 
439 	if (Info->GetSynthInfo())
440 	{
441 		QPainter Painter(&Image);
442 		QImage Icon = QImage(":/resources/flexible.png");
443 		uchar* ImageBits = Icon.bits();
444 		QRgb TextColor = mListView->palette().color(QPalette::WindowText).rgba();
445 		int Red = qRed(TextColor);
446 		int Green = qGreen(TextColor);
447 		int Blue = qBlue(TextColor);
448 
449 		for (int y = 0; y < Icon.height(); y++)
450 		{
451 			for (int x = 0; x < Icon.width(); x++)
452 			{
453 				QRgb& Pixel = ((QRgb*)ImageBits)[x];
454 				Pixel = qRgba(Red, Green, Blue, qAlpha(Pixel));
455 			}
456 
457 			ImageBits += Icon.bytesPerLine();
458 		}
459 
460 		Painter.drawImage(QPoint(0, 0), Icon);
461 		Painter.end();
462 	}
463 
464 	mParts[InfoIndex].second = QPixmap::fromImage(Image).scaled(mIconSize, mIconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
465 
466 	lcGetPiecesLibrary()->ReleasePieceInfo(Info);
467 
468 	emit dataChanged(index(InfoIndex, 0), index(InfoIndex, 0), QVector<int>() << Qt::DecorationRole);
469 }
470 
SetShowDecoratedParts(bool Show)471 void lcPartSelectionListModel::SetShowDecoratedParts(bool Show)
472 {
473 	if (Show == mShowDecoratedParts)
474 		return;
475 
476 	mShowDecoratedParts = Show;
477 
478 	SetFilter(mFilter);
479 }
480 
SetShowPartAliases(bool Show)481 void lcPartSelectionListModel::SetShowPartAliases(bool Show)
482 {
483 	if (Show == mShowPartAliases)
484 		return;
485 
486 	mShowPartAliases = Show;
487 
488 	SetFilter(mFilter);
489 }
490 
SetIconSize(int Size)491 void lcPartSelectionListModel::SetIconSize(int Size)
492 {
493 	if (Size == mIconSize)
494 		return;
495 
496 	mIconSize = Size;
497 
498 	beginResetModel();
499 
500 	for (size_t PartIdx = 0; PartIdx < mParts.size(); PartIdx++)
501 		mParts[PartIdx].second = QPixmap();
502 
503 	endResetModel();
504 
505 	SetFilter(mFilter);
506 }
507 
SetShowPartNames(bool Show)508 void lcPartSelectionListModel::SetShowPartNames(bool Show)
509 {
510 	if (Show == mShowPartNames)
511 		return;
512 
513 	mShowPartNames = Show;
514 
515 	beginResetModel();
516 	endResetModel();
517 
518 	SetFilter(mFilter);
519 }
520 
lcPartSelectionListView(QWidget * Parent,lcPartSelectionWidget * PartSelectionWidget)521 lcPartSelectionListView::lcPartSelectionListView(QWidget* Parent, lcPartSelectionWidget* PartSelectionWidget)
522 	: QListView(Parent)
523 {
524 	mPartSelectionWidget = PartSelectionWidget;
525 	mCategoryType = lcPartCategoryType::AllParts;
526 	mCategoryIndex = 0;
527 
528 	setUniformItemSizes(true);
529 	setResizeMode(QListView::Adjust);
530 	setWordWrap(false);
531 	setDragEnabled(true);
532 	setContextMenuPolicy(Qt::CustomContextMenu);
533 
534 	mListModel = new lcPartSelectionListModel(this);
535 	setModel(mListModel);
536 	lcPartSelectionItemDelegate* ItemDelegate = new lcPartSelectionItemDelegate(this, mListModel);
537 	setItemDelegate(ItemDelegate);
538 
539 	connect(this, SIGNAL(customContextMenuRequested(QPoint)), SLOT(CustomContextMenuRequested(QPoint)));
540 
541 	SetIconSize(lcGetProfileInt(LC_PROFILE_PARTS_LIST_ICONS));
542 }
543 
CustomContextMenuRequested(QPoint Pos)544 void lcPartSelectionListView::CustomContextMenuRequested(QPoint Pos)
545 {
546 	QMenu* Menu = new QMenu(this);
547 
548 	QModelIndex Index = indexAt(Pos);
549 	mContextInfo = Index.isValid() ? mListModel->GetPieceInfo(Index.row()) : nullptr;
550 
551 	QMenu* SetMenu = Menu->addMenu(tr("Add to Palette"));
552 
553 	const std::vector<lcPartPalette>& Palettes = mPartSelectionWidget->GetPartPalettes();
554 
555 	if (!Palettes.empty())
556 	{
557 		for (const lcPartPalette& Palette : Palettes)
558 			SetMenu->addAction(Palette.Name, mPartSelectionWidget, SLOT(AddToPalette()));
559 	}
560 	else
561 	{
562 		QAction* Action = SetMenu->addAction(tr("None"));
563 		Action->setEnabled(false);
564 	}
565 
566 	QAction* RemoveAction = Menu->addAction(tr("Remove from Palette"), mPartSelectionWidget, SLOT(RemoveFromPalette()));
567 	RemoveAction->setEnabled(mCategoryType == lcPartCategoryType::Palette);
568 
569 	Menu->exec(viewport()->mapToGlobal(Pos));
570 	delete Menu;
571 }
572 
SetCategory(lcPartCategoryType Type,int Index)573 void lcPartSelectionListView::SetCategory(lcPartCategoryType Type, int Index)
574 {
575 	mCategoryType = Type;
576 	mCategoryIndex = Index;
577 
578 	switch (Type)
579 	{
580 	case lcPartCategoryType::AllParts:
581 		mListModel->SetCategory(-1);
582 		break;
583 	case lcPartCategoryType::PartsInUse:
584 		mListModel->SetCurrentModelCategory();
585 		break;
586 	case lcPartCategoryType::Submodels:
587 		mListModel->SetModelsCategory();
588 		break;
589 	case lcPartCategoryType::Palette:
590 		mListModel->SetPaletteCategory(Index);
591 		break;
592 	case lcPartCategoryType::Category:
593 		mListModel->SetCategory(Index);
594 		break;
595 	case lcPartCategoryType::Count:
596 		break;
597 	}
598 
599 	setCurrentIndex(mListModel->index(0, 0));
600 }
601 
SetNoIcons()602 void lcPartSelectionListView::SetNoIcons()
603 {
604 	SetIconSize(0);
605 }
606 
SetSmallIcons()607 void lcPartSelectionListView::SetSmallIcons()
608 {
609 	SetIconSize(32);
610 }
611 
SetMediumIcons()612 void lcPartSelectionListView::SetMediumIcons()
613 {
614 	SetIconSize(64);
615 }
616 
SetLargeIcons()617 void lcPartSelectionListView::SetLargeIcons()
618 {
619 	SetIconSize(96);
620 }
621 
SetExtraLargeIcons()622 void lcPartSelectionListView::SetExtraLargeIcons()
623 {
624 	SetIconSize(192);
625 }
626 
TogglePartNames()627 void lcPartSelectionListView::TogglePartNames()
628 {
629 	bool Show = !mListModel->GetShowPartNames();
630 	mListModel->SetShowPartNames(Show);
631 	lcSetProfileInt(LC_PROFILE_PARTS_LIST_NAMES, Show);
632 }
633 
ToggleDecoratedParts()634 void lcPartSelectionListView::ToggleDecoratedParts()
635 {
636 	bool Show = !mListModel->GetShowDecoratedParts();
637 	mListModel->SetShowDecoratedParts(Show);
638 	lcSetProfileInt(LC_PROFILE_PARTS_LIST_DECORATED, Show);
639 }
640 
TogglePartAliases()641 void lcPartSelectionListView::TogglePartAliases()
642 {
643 	bool Show = !mListModel->GetShowPartAliases();
644 	mListModel->SetShowPartAliases(Show);
645 	lcSetProfileInt(LC_PROFILE_PARTS_LIST_ALIASES, Show);
646 }
647 
ToggleListMode()648 void lcPartSelectionListView::ToggleListMode()
649 {
650 	mListModel->ToggleListMode();
651 }
652 
ToggleFixedColor()653 void lcPartSelectionListView::ToggleFixedColor()
654 {
655 	mListModel->ToggleColorLocked();
656 }
657 
UpdateViewMode()658 void lcPartSelectionListView::UpdateViewMode()
659 {
660 	setViewMode(mListModel->GetIconSize() && !mListModel->IsListMode() ? QListView::IconMode : QListView::ListMode);
661 	setWordWrap(mListModel->IsListMode());
662 	setDragEnabled(true);
663 }
664 
SetIconSize(int Size)665 void lcPartSelectionListView::SetIconSize(int Size)
666 {
667 	setIconSize(QSize(Size, Size));
668 	lcSetProfileInt(LC_PROFILE_PARTS_LIST_ICONS, Size);
669 	mListModel->SetIconSize(Size);
670 	UpdateViewMode();
671 
672 	int Width = Size + 2 * frameWidth() + 6;
673 	if (verticalScrollBar())
674 		Width += verticalScrollBar()->sizeHint().width();
675 	int Height = Size + 2 * frameWidth() + 2;
676 	if (horizontalScrollBar())
677 		Height += horizontalScrollBar()->sizeHint().height();
678 	setMinimumSize(Width, Height);
679 }
680 
startDrag(Qt::DropActions SupportedActions)681 void lcPartSelectionListView::startDrag(Qt::DropActions SupportedActions)
682 {
683 	Q_UNUSED(SupportedActions);
684 
685 	PieceInfo* Info = GetCurrentPart();
686 
687 	if (!Info)
688 		return;
689 
690 	QByteArray ItemData;
691 	QDataStream DataStream(&ItemData, QIODevice::WriteOnly);
692 	DataStream << QString(Info->mFileName);
693 
694 	QMimeData* MimeData = new QMimeData;
695 	MimeData->setData("application/vnd.leocad-part", ItemData);
696 
697 	QDrag* Drag = new QDrag(this);
698 	Drag->setMimeData(MimeData);
699 
700 	Drag->exec(Qt::CopyAction);
701 }
702 
mouseDoubleClickEvent(QMouseEvent * MouseEvent)703 void lcPartSelectionListView::mouseDoubleClickEvent(QMouseEvent* MouseEvent)
704 {
705 	if (MouseEvent->button() == Qt::LeftButton )
706 		PreviewSelection(currentIndex().row());
707 
708 	QListView::mouseDoubleClickEvent(MouseEvent);
709 }
710 
PreviewSelection(int InfoIndex)711 void lcPartSelectionListView::PreviewSelection(int InfoIndex)
712 {
713 	PieceInfo* Info = mListModel->GetPieceInfo(InfoIndex);
714 
715 	if (!Info)
716 		return;
717 
718 	quint32 ColorCode = lcGetColorCode(mListModel->GetColorIndex());
719 
720 	gMainWindow->PreviewPiece(Info->mFileName, ColorCode, true);
721 }
722 
lcPartSelectionWidget(QWidget * Parent)723 lcPartSelectionWidget::lcPartSelectionWidget(QWidget* Parent)
724 	: QWidget(Parent), mFilterAction(nullptr)
725 {
726 	mSplitter = new QSplitter(this);
727 	mSplitter->setOrientation(Qt::Vertical);
728 	mSplitter->setChildrenCollapsible(false);
729 
730 	mCategoriesWidget = new QTreeWidget(mSplitter);
731 	mCategoriesWidget->setHeaderHidden(true);
732 	mCategoriesWidget->setUniformRowHeights(true);
733 	mCategoriesWidget->setRootIsDecorated(false);
734 
735 	QWidget* PartsGroupWidget = new QWidget(mSplitter);
736 
737 	QVBoxLayout* PartsLayout = new QVBoxLayout();
738 	PartsLayout->setContentsMargins(0, 0, 0, 0);
739 	PartsGroupWidget->setLayout(PartsLayout);
740 
741 	QHBoxLayout* SearchLayout = new QHBoxLayout();
742 	SearchLayout->setContentsMargins(0, 0, 0, 0);
743 	PartsLayout->addLayout(SearchLayout);
744 
745 	mFilterWidget = new QLineEdit(PartsGroupWidget);
746 	mFilterWidget->setPlaceholderText(tr("Search Parts"));
747 	mFilterAction = mFilterWidget->addAction(QIcon(":/resources/parts_search.png"), QLineEdit::TrailingPosition);
748 	connect(mFilterAction, SIGNAL(triggered()), this, SLOT(FilterTriggered()));
749 	SearchLayout->addWidget(mFilterWidget);
750 
751 	QToolButton* OptionsButton = new QToolButton();
752 	OptionsButton->setIcon(QIcon(":/resources/gear_in.png"));
753 	OptionsButton->setToolTip(tr("Options"));
754 	OptionsButton->setPopupMode(QToolButton::InstantPopup);
755 	SearchLayout->addWidget(OptionsButton);
756 
757 	QMenu* OptionsMenu = new QMenu(this);
758 	OptionsButton->setMenu(OptionsMenu);
759 	connect(OptionsMenu, SIGNAL(aboutToShow()), this, SLOT(OptionsMenuAboutToShow()));
760 
761 	mPartsWidget = new lcPartSelectionListView(PartsGroupWidget, this);
762 	PartsLayout->addWidget(mPartsWidget);
763 
764 	QHBoxLayout* Layout = new QHBoxLayout(this);
765 	Layout->setContentsMargins(0, 0, 0, 0);
766 	Layout->addWidget(mSplitter);
767 	setLayout(Layout);
768 
769 	connect(mPartsWidget->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(PartChanged(const QModelIndex&, const QModelIndex&)));
770 	connect(mFilterWidget, SIGNAL(textChanged(const QString&)), this, SLOT(FilterChanged(const QString&)));
771 	connect(mCategoriesWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(CategoryChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
772 
773 	LoadPartPalettes();
774 	UpdateCategories();
775 
776 	mSplitter->setStretchFactor(0, 0);
777 	mSplitter->setStretchFactor(1, 1);
778 
779 	connect(Parent, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(DockLocationChanged(Qt::DockWidgetArea)));
780 }
781 
event(QEvent * Event)782 bool lcPartSelectionWidget::event(QEvent* Event)
783 {
784 	if (Event->type() == QEvent::ShortcutOverride)
785 	{
786 		QKeyEvent* KeyEvent = (QKeyEvent*)Event;
787 		int Key = KeyEvent->key();
788 
789 		if (KeyEvent->modifiers() == Qt::NoModifier && Key >= Qt::Key_A && Key <= Qt::Key_Z)
790 			Event->accept();
791 
792 		switch (Key)
793 		{
794 		case Qt::Key_Down:
795 		case Qt::Key_Up:
796 		case Qt::Key_Left:
797 		case Qt::Key_Right:
798 		case Qt::Key_Home:
799 		case Qt::Key_End:
800 		case Qt::Key_PageUp:
801 		case Qt::Key_PageDown:
802 		case Qt::Key_Asterisk:
803 		case Qt::Key_Plus:
804 		case Qt::Key_Minus:
805 			Event->accept();
806 			break;
807 		}
808 	}
809 
810 	return QWidget::event(Event);
811 }
812 
LoadState(QSettings & Settings)813 void lcPartSelectionWidget::LoadState(QSettings& Settings)
814 {
815 	QList<int> Sizes = Settings.value("PartSelectionSplitter").value<QList<int>>();
816 
817 	if (Sizes.size() != 2)
818 	{
819 		int Length = mSplitter->orientation() == Qt::Horizontal ? mSplitter->width() : mSplitter->height();
820 		Sizes << Length / 3 << 2 * Length / 3;
821 	}
822 
823 	mSplitter->setSizes(Sizes);
824 }
825 
SaveState(QSettings & Settings)826 void lcPartSelectionWidget::SaveState(QSettings& Settings)
827 {
828 	QList<int> Sizes = mSplitter->sizes();
829 	Settings.setValue("PartSelectionSplitter", QVariant::fromValue(Sizes));
830 }
831 
DisableIconMode()832 void lcPartSelectionWidget::DisableIconMode()
833 {
834 	mPartsWidget->SetNoIcons();
835 }
836 
DockLocationChanged(Qt::DockWidgetArea Area)837 void lcPartSelectionWidget::DockLocationChanged(Qt::DockWidgetArea Area)
838 {
839 	if (Area == Qt::LeftDockWidgetArea || Area == Qt::RightDockWidgetArea)
840 		mSplitter->setOrientation(Qt::Vertical);
841 	else
842 		mSplitter->setOrientation(Qt::Horizontal);
843 }
844 
resizeEvent(QResizeEvent * Event)845 void lcPartSelectionWidget::resizeEvent(QResizeEvent* Event)
846 {
847 	if (((QDockWidget*)parent())->isFloating())
848 	{
849 		if (Event->size().width() > Event->size().height())
850 			mSplitter->setOrientation(Qt::Horizontal);
851 		else
852 			mSplitter->setOrientation(Qt::Vertical);
853 	}
854 
855 	QWidget::resizeEvent(Event);
856 }
857 
FilterChanged(const QString & Text)858 void lcPartSelectionWidget::FilterChanged(const QString& Text)
859 {
860 	if (mFilterAction)
861 	{
862 		if (Text.isEmpty())
863 			mFilterAction->setIcon(QIcon(":/resources/parts_search.png"));
864 		else
865 			mFilterAction->setIcon(QIcon(":/resources/parts_cancel.png"));
866 	}
867 
868 	mPartsWidget->GetListModel()->SetFilter(Text);
869 }
870 
FilterTriggered()871 void lcPartSelectionWidget::FilterTriggered()
872 {
873 	mFilterWidget->clear();
874 }
875 
CategoryChanged(QTreeWidgetItem * Current,QTreeWidgetItem * Previous)876 void lcPartSelectionWidget::CategoryChanged(QTreeWidgetItem* Current, QTreeWidgetItem* Previous)
877 {
878 	Q_UNUSED(Previous);
879 
880 	if (!Current)
881 		return;
882 
883 	int Type = Current->data(0, static_cast<int>(lcPartCategoryRole::Type)).toInt();
884 	int Index = Current->data(0, static_cast<int>(lcPartCategoryRole::Index)).toInt();
885 
886 	mPartsWidget->SetCategory(static_cast<lcPartCategoryType>(Type), Index);
887 }
888 
PartChanged(const QModelIndex & Current,const QModelIndex & Previous)889 void lcPartSelectionWidget::PartChanged(const QModelIndex& Current, const QModelIndex& Previous)
890 {
891 	Q_UNUSED(Current);
892 	Q_UNUSED(Previous);
893 
894 	gMainWindow->SetCurrentPieceInfo(mPartsWidget->GetCurrentPart());
895 }
896 
OptionsMenuAboutToShow()897 void lcPartSelectionWidget::OptionsMenuAboutToShow()
898 {
899 	QMenu* Menu = (QMenu*)sender();
900 	Menu->clear();
901 
902 	Menu->addAction("Edit Palettes...", this, SLOT(EditPartPalettes()));
903 	Menu->addSeparator();
904 
905 	lcPartSelectionListModel* ListModel = mPartsWidget->GetListModel();
906 
907 	if (gSupportsFramebufferObject)
908 	{
909 		QActionGroup* IconGroup = new QActionGroup(Menu);
910 
911 		QAction* NoIcons = Menu->addAction(tr("No Icons"), mPartsWidget, SLOT(SetNoIcons()));
912 		NoIcons->setCheckable(true);
913 		NoIcons->setChecked(ListModel->GetIconSize() == 0);
914 		IconGroup->addAction(NoIcons);
915 
916 		QAction* SmallIcons = Menu->addAction(tr("Small Icons"), mPartsWidget, SLOT(SetSmallIcons()));
917 		SmallIcons->setCheckable(true);
918 		SmallIcons->setChecked(ListModel->GetIconSize() == 32);
919 		IconGroup->addAction(SmallIcons);
920 
921 		QAction* MediumIcons = Menu->addAction(tr("Medium Icons"), mPartsWidget, SLOT(SetMediumIcons()));
922 		MediumIcons->setCheckable(true);
923 		MediumIcons->setChecked(ListModel->GetIconSize() == 64);
924 		IconGroup->addAction(MediumIcons);
925 
926 		QAction* LargeIcons = Menu->addAction(tr("Large Icons"), mPartsWidget, SLOT(SetLargeIcons()));
927 		LargeIcons->setCheckable(true);
928 		LargeIcons->setChecked(ListModel->GetIconSize() == 96);
929 		IconGroup->addAction(LargeIcons);
930 
931 		QAction* ExtraLargeIcons = Menu->addAction(tr("Extra Large Icons"), mPartsWidget, SLOT(SetExtraLargeIcons()));
932 		ExtraLargeIcons->setCheckable(true);
933 		ExtraLargeIcons->setChecked(ListModel->GetIconSize() == 192);
934 		IconGroup->addAction(ExtraLargeIcons);
935 
936 		Menu->addSeparator();
937 	}
938 
939 	if (ListModel->GetIconSize() != 0 && !ListModel->IsListMode())
940 	{
941 		QAction* PartNames = Menu->addAction(tr("Show Part Names"), mPartsWidget, SLOT(TogglePartNames()));
942 		PartNames->setCheckable(true);
943 		PartNames->setChecked(ListModel->GetShowPartNames());
944 	}
945 
946 	QAction* DecoratedParts = Menu->addAction(tr("Show Decorated Parts"), mPartsWidget, SLOT(ToggleDecoratedParts()));
947 	DecoratedParts->setCheckable(true);
948 	DecoratedParts->setChecked(ListModel->GetShowDecoratedParts());
949 
950 	QAction* PartAliases = Menu->addAction(tr("Show Part Aliases"), mPartsWidget, SLOT(TogglePartAliases()));
951 	PartAliases->setCheckable(true);
952 	PartAliases->setChecked(ListModel->GetShowPartAliases());
953 
954 	if (ListModel->GetIconSize() != 0)
955 	{
956 		QAction* ListMode = Menu->addAction(tr("List Mode"), mPartsWidget, SLOT(ToggleListMode()));
957 		ListMode->setCheckable(true);
958 		ListMode->setChecked(ListModel->IsListMode());
959 
960 		QAction* FixedColor = Menu->addAction(tr("Lock Preview Color"), mPartsWidget, SLOT(ToggleFixedColor()));
961 		FixedColor->setCheckable(true);
962 		FixedColor->setChecked(ListModel->IsColorLocked());
963 	}
964 }
965 
EditPartPalettes()966 void lcPartSelectionWidget::EditPartPalettes()
967 {
968 	lcPartPaletteDialog Dialog(this, mPartPalettes);
969 
970 	if (Dialog.exec() != QDialog::Accepted)
971 		return;
972 
973 	SavePartPalettes();
974 	UpdateCategories();
975 }
976 
Redraw()977 void lcPartSelectionWidget::Redraw()
978 {
979 	mPartsWidget->GetListModel()->Redraw();
980 }
981 
SetDefaultPart()982 void lcPartSelectionWidget::SetDefaultPart()
983 {
984 	for (int CategoryIdx = 0; CategoryIdx < mCategoriesWidget->topLevelItemCount(); CategoryIdx++)
985 	{
986 		QTreeWidgetItem* CategoryItem = mCategoriesWidget->topLevelItem(CategoryIdx);
987 
988 		if (CategoryItem->text(0) == "Brick")
989 		{
990 			mCategoriesWidget->setCurrentItem(CategoryItem);
991 			break;
992 		}
993 	}
994 }
995 
LoadPartPalettes()996 void lcPartSelectionWidget::LoadPartPalettes()
997 {
998 	QByteArray Buffer = lcGetProfileBuffer(LC_PROFILE_PART_PALETTES);
999 	QJsonDocument Document = QJsonDocument::fromJson(Buffer);
1000 
1001 	if (Document.isNull())
1002 		Document = QJsonDocument::fromJson((QString("{ \"Version\":1, \"Palettes\": { \"%1\": [] } }").arg(tr("Favorites"))).toUtf8());
1003 
1004 	QJsonObject RootObject = Document.object();
1005 	mPartPalettes.clear();
1006 
1007 	int Version = RootObject["Version"].toInt(0);
1008 	if (Version != 1)
1009 		return;
1010 
1011 	QJsonObject PalettesObject = RootObject["Palettes"].toObject();
1012 
1013 	for (QJsonObject::const_iterator ElementIt = PalettesObject.constBegin(); ElementIt != PalettesObject.constEnd(); ElementIt++)
1014 	{
1015 		if (!ElementIt.value().isArray())
1016 			continue;
1017 
1018 		lcPartPalette Palette;
1019 		Palette.Name = ElementIt.key();
1020 
1021 		QJsonArray Parts = ElementIt.value().toArray();
1022 
1023 		for (const QJsonValue& Part : Parts)
1024 			Palette.Parts.emplace_back(Part.toString().toStdString());
1025 
1026 		mPartPalettes.emplace_back(std::move(Palette));
1027 	}
1028 }
1029 
SavePartPalettes()1030 void lcPartSelectionWidget::SavePartPalettes()
1031 {
1032 	QJsonObject RootObject;
1033 
1034 	RootObject["Version"] = 1;
1035 	QJsonObject PalettesObject;
1036 
1037 	for (const lcPartPalette& Palette : mPartPalettes)
1038 	{
1039 		QJsonArray Parts;
1040 
1041 		for (const std::string& PartId : Palette.Parts)
1042 			Parts.append(QString::fromStdString(PartId));
1043 
1044 		PalettesObject[Palette.Name] = Parts;
1045 	}
1046 
1047 	RootObject["Palettes"] = PalettesObject;
1048 
1049 	QByteArray Buffer = QJsonDocument(RootObject).toJson();
1050 	lcSetProfileBuffer(LC_PROFILE_PART_PALETTES, Buffer);
1051 }
1052 
AddToPalette()1053 void lcPartSelectionWidget::AddToPalette()
1054 {
1055 	PieceInfo* Info = mPartsWidget->GetContextInfo();
1056 	if (!Info)
1057 		return;
1058 
1059 	QString SetName = ((QAction*)sender())->text();
1060 
1061 	std::vector<lcPartPalette>::iterator SetIt = std::find_if(mPartPalettes.begin(), mPartPalettes.end(), [&SetName](const lcPartPalette& Set)
1062 	{
1063 		return Set.Name == SetName;
1064 	});
1065 
1066 	if (SetIt == mPartPalettes.end())
1067 		return;
1068 
1069 	std::string PartId = lcGetPiecesLibrary()->GetPartId(Info);
1070 	std::vector<std::string>& Parts = SetIt->Parts;
1071 
1072 	if (std::find(Parts.begin(), Parts.end(), PartId) == Parts.end())
1073 	{
1074 		Parts.emplace_back(PartId);
1075 		SavePartPalettes();
1076 	}
1077 }
1078 
RemoveFromPalette()1079 void lcPartSelectionWidget::RemoveFromPalette()
1080 {
1081 	PieceInfo* Info = mPartsWidget->GetContextInfo();
1082 	if (!Info)
1083 		return;
1084 
1085 	QTreeWidgetItem* CurrentItem = mCategoriesWidget->currentItem();
1086 	if (!CurrentItem || CurrentItem->data(0, static_cast<int>(lcPartCategoryRole::Type)) != static_cast<int>(lcPartCategoryType::Palette))
1087 		return;
1088 
1089 	int SetIndex = CurrentItem->data(0, static_cast<int>(lcPartCategoryRole::Index)).toInt();
1090 	lcPartPalette& Palette = mPartPalettes[SetIndex];
1091 
1092 	std::string PartId = lcGetPiecesLibrary()->GetPartId(Info);
1093 	std::vector<std::string>::iterator PartIt = std::find(Palette.Parts.begin(), Palette.Parts.end(), PartId);
1094 
1095 	if (PartIt != Palette.Parts.end())
1096 	{
1097 		Palette.Parts.erase(PartIt);
1098 		mPartsWidget->SetCategory(lcPartCategoryType::Palette, SetIndex);
1099 		SavePartPalettes();
1100 	}
1101 }
1102 
UpdateCategories()1103 void lcPartSelectionWidget::UpdateCategories()
1104 {
1105 	QTreeWidgetItem* CurrentItem = mCategoriesWidget->currentItem();
1106 	lcPartCategoryType CurrentType = lcPartCategoryType::Count;
1107 	int CurrentIndex = -1;
1108 
1109 	if (CurrentItem)
1110 	{
1111 		CurrentType = static_cast<lcPartCategoryType>(CurrentItem->data(0, static_cast<int>(lcPartCategoryRole::Type)).toInt());
1112 		CurrentIndex = CurrentItem->data(0, static_cast<int>(lcPartCategoryRole::Index)).toInt();
1113 		CurrentItem = nullptr;
1114 	}
1115 
1116 	mCategoriesWidget->clear();
1117 
1118 	QTreeWidgetItem* AllPartsCategoryItem = new QTreeWidgetItem(mCategoriesWidget, QStringList(tr("All Parts")));
1119 	AllPartsCategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Type), static_cast<int>(lcPartCategoryType::AllParts));
1120 
1121 	if (CurrentType == lcPartCategoryType::AllParts && CurrentIndex == 0)
1122 		CurrentItem = AllPartsCategoryItem;
1123 
1124 	QTreeWidgetItem* CurrentModelCategoryItem = new QTreeWidgetItem(mCategoriesWidget, QStringList(tr("In Use")));
1125 	CurrentModelCategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Type), static_cast<int>(lcPartCategoryType::PartsInUse));
1126 
1127 	if (CurrentType == lcPartCategoryType::PartsInUse && CurrentIndex == 0)
1128 		CurrentItem = CurrentModelCategoryItem;
1129 
1130 	QTreeWidgetItem* SubmodelsCategoryItem = new QTreeWidgetItem(mCategoriesWidget, QStringList(tr("Submodels")));
1131 	SubmodelsCategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Type), static_cast<int>(lcPartCategoryType::Submodels));
1132 
1133 	if (CurrentType == lcPartCategoryType::Submodels && CurrentIndex == 0)
1134 		CurrentItem = SubmodelsCategoryItem;
1135 
1136 	for (int PaletteIdx = 0; PaletteIdx < static_cast<int>(mPartPalettes.size()); PaletteIdx++)
1137 	{
1138 		const lcPartPalette& Set = mPartPalettes[PaletteIdx];
1139 		QTreeWidgetItem* PaletteCategoryItem = new QTreeWidgetItem(mCategoriesWidget, QStringList(Set.Name));
1140 		PaletteCategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Type), static_cast<int>(lcPartCategoryType::Palette));
1141 		PaletteCategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Index), PaletteIdx);
1142 
1143 		if (CurrentType == lcPartCategoryType::Palette && CurrentIndex == PaletteIdx)
1144 			CurrentItem = PaletteCategoryItem;
1145 	}
1146 
1147 	for (int CategoryIdx = 0; CategoryIdx < static_cast<int>(gCategories.size()); CategoryIdx++)
1148 	{
1149 		QTreeWidgetItem* CategoryItem = new QTreeWidgetItem(mCategoriesWidget, QStringList(gCategories[CategoryIdx].Name));
1150 		CategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Type), static_cast<int>(lcPartCategoryType::Category));
1151 		CategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Index), CategoryIdx);
1152 
1153 		if (CurrentType == lcPartCategoryType::Category && CurrentIndex == CategoryIdx)
1154 			CurrentItem = CategoryItem;
1155 	}
1156 
1157 	if (CurrentItem)
1158 		mCategoriesWidget->setCurrentItem(CurrentItem);
1159 }
1160 
UpdateModels()1161 void lcPartSelectionWidget::UpdateModels()
1162 {
1163 	QTreeWidgetItem* CurrentItem = mCategoriesWidget->currentItem();
1164 
1165 	if (CurrentItem && CurrentItem->data(0, static_cast<int>(lcPartCategoryRole::Type)) == static_cast<int>(lcPartCategoryType::Submodels))
1166 		mPartsWidget->SetCategory(lcPartCategoryType::Submodels, 0);
1167 }
1168