leocad/common/lc_partselectionwidget.cpp

1406 lines
40 KiB
C++
Raw Normal View History

#include "lc_global.h"
#include "lc_partselectionwidget.h"
2019-12-16 04:01:55 +01:00
#include "lc_partpalettedialog.h"
#include "lc_profile.h"
#include "lc_application.h"
#include "lc_mainwindow.h"
#include "lc_library.h"
2024-07-12 00:04:07 +02:00
#include "lc_thumbnailmanager.h"
2016-12-19 03:53:25 +01:00
#include "project.h"
#include "pieceinf.h"
#include "lc_glextensions.h"
2020-12-24 03:16:00 +01:00
#include "lc_category.h"
2020-12-24 03:16:00 +01:00
Q_DECLARE_METATYPE(QList<int>)
void lcPartSelectionItemDelegate::paint(QPainter* Painter, const QStyleOptionViewItem& Option, const QModelIndex& Index) const
{
2024-07-12 00:04:07 +02:00
mListModel->RequestThumbnail(Index.row());
QStyledItemDelegate::paint(Painter, Option, Index);
}
QSize lcPartSelectionItemDelegate::sizeHint(const QStyleOptionViewItem& Option, const QModelIndex& Index) const
{
QSize Size = QStyledItemDelegate::sizeHint(Option, Index);
int IconSize = mListModel->GetIconSize();
if (IconSize)
{
QWidget* Widget = (QWidget*)parent();
const int PixmapMargin = Widget->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &Option, Widget) + 1;
int PixmapWidth = IconSize + 2 * PixmapMargin;
Size.setWidth(qMin(PixmapWidth, Size.width()));
}
return Size;
}
lcPartSelectionListModel::lcPartSelectionListModel(QObject* Parent)
: QAbstractListModel(Parent)
{
2017-01-11 02:48:05 +01:00
mListView = (lcPartSelectionListView*)Parent;
mIconSize = 0;
2017-01-28 03:20:44 +01:00
mShowPartNames = lcGetProfileInt(LC_PROFILE_PARTS_LIST_NAMES);
mListMode = lcGetProfileInt(LC_PROFILE_PARTS_LIST_LISTMODE);
2017-07-12 03:09:15 +02:00
mShowDecoratedParts = lcGetProfileInt(LC_PROFILE_PARTS_LIST_DECORATED);
mShowPartAliases = lcGetProfileInt(LC_PROFILE_PARTS_LIST_ALIASES);
2024-11-12 09:04:39 +01:00
mCaseSensitiveFilter = lcGetProfileInt(LC_PROFILE_PARTS_LIST_CASE_SENSITIVE_FILTER);
mFileNameFilter = lcGetProfileInt(LC_PROFILE_PARTS_LIST_FILE_NAME_FILTER);
mPartDescriptionFilter = lcGetProfileInt(LC_PROFILE_PARTS_LIST_PART_DESCRIPTION_FILTER);
mPartFilterType = static_cast<lcPartFilterType>(lcGetProfileInt(LC_PROFILE_PARTS_LIST_PART_FILTER));
2017-01-23 04:28:05 +01:00
int ColorCode = lcGetProfileInt(LC_PROFILE_PARTS_LIST_COLOR);
if (ColorCode == -1)
2017-02-05 04:37:40 +01:00
{
mColorIndex = gMainWindow->mColorIndex;
mColorLocked = false;
2017-02-05 04:37:40 +01:00
}
else
{
mColorIndex = lcGetColorIndex(ColorCode);
mColorLocked = true;
}
2024-07-12 00:04:07 +02:00
connect(lcGetPiecesLibrary()->GetThumbnailManager(), &lcThumbnailManager::ThumbnailReady, this, &lcPartSelectionListModel::ThumbnailReady);
2017-01-23 04:28:05 +01:00
}
lcPartSelectionListModel::~lcPartSelectionListModel()
{
2024-07-12 00:04:07 +02:00
ReleaseThumbnails();
}
2024-07-12 00:04:07 +02:00
void lcPartSelectionListModel::UpdateThumbnails()
2016-12-29 16:28:53 +01:00
{
beginResetModel();
2024-07-12 00:04:07 +02:00
ReleaseThumbnails();
2016-12-29 16:28:53 +01:00
endResetModel();
SetFilter(mFilter);
2016-12-29 16:28:53 +01:00
}
void lcPartSelectionListModel::SetColorIndex(int ColorIndex)
{
if (mColorLocked || ColorIndex == mColorIndex)
return;
2024-07-12 00:04:07 +02:00
UpdateThumbnails();
mColorIndex = ColorIndex;
}
void lcPartSelectionListModel::ToggleColorLocked()
{
mColorLocked = !mColorLocked;
SetColorIndex(gMainWindow->mColorIndex);
lcSetProfileInt(LC_PROFILE_PARTS_LIST_COLOR, mColorLocked ? lcGetColorCode(mColorIndex) : -1);
}
void lcPartSelectionListModel::ToggleListMode()
{
mListMode = !mListMode;
mListView->UpdateViewMode();
lcSetProfileInt(LC_PROFILE_PARTS_LIST_LISTMODE, mListMode);
}
void lcPartSelectionListModel::SetCategory(int CategoryIndex)
{
beginResetModel();
2024-07-12 00:04:07 +02:00
ReleaseThumbnails();
lcPiecesLibrary* Library = lcGetPiecesLibrary();
2024-05-25 04:26:01 +02:00
std::vector<PieceInfo*> SingleParts, GroupedParts;
2017-02-01 06:12:30 +01:00
if (CategoryIndex != -1)
Library->GetCategoryEntries(CategoryIndex, false, SingleParts, GroupedParts);
else
{
2017-02-01 06:12:30 +01:00
Library->GetParts(SingleParts);
lcModel* ActiveModel = gMainWindow->GetActiveModel();
2024-05-25 04:26:01 +02:00
for (size_t PartIndex = 0; PartIndex < SingleParts.size(); )
{
2024-05-25 04:26:01 +02:00
PieceInfo* Info = SingleParts[PartIndex];
if (!Info->IsModel() || !Info->GetModel()->IncludesModel(ActiveModel))
2024-05-25 04:26:01 +02:00
PartIndex++;
else
2024-05-25 04:26:01 +02:00
SingleParts.erase(SingleParts.begin() + PartIndex);
}
}
2019-11-23 19:46:18 +01:00
auto lcPartSortFunc=[](const PieceInfo* a, const PieceInfo* b)
2017-07-12 03:09:15 +02:00
{
2019-11-23 19:46:18 +01:00
return strcmp(a->m_strDescription, b->m_strDescription) < 0;
2017-07-12 03:09:15 +02:00
};
2019-11-23 19:46:18 +01:00
std::sort(SingleParts.begin(), SingleParts.end(), lcPartSortFunc);
2024-05-25 04:26:01 +02:00
mParts.resize(SingleParts.size());
2024-07-12 00:04:07 +02:00
for (size_t PartIndex = 0; PartIndex < SingleParts.size(); PartIndex++)
mParts[PartIndex].Info = SingleParts[PartIndex];
2016-12-19 03:53:25 +01:00
endResetModel();
2017-07-12 03:09:15 +02:00
SetFilter(mFilter);
2016-12-19 03:53:25 +01:00
}
void lcPartSelectionListModel::SetModelsCategory()
{
beginResetModel();
2024-07-12 00:04:07 +02:00
ReleaseThumbnails();
2016-12-19 03:53:25 +01:00
mParts.clear();
2024-06-17 02:43:02 +02:00
const std::vector<std::unique_ptr<lcModel>>& Models = lcGetActiveProject()->GetModels();
lcModel* ActiveModel = gMainWindow->GetActiveModel();
2016-12-19 03:53:25 +01:00
2024-06-17 02:43:02 +02:00
for (const std::unique_ptr<lcModel>& Model : Models)
if (!Model->IncludesModel(ActiveModel))
2024-07-12 00:04:07 +02:00
mParts.emplace_back().Info = Model->GetPieceInfo();
2024-07-12 00:04:07 +02:00
auto lcPartSortFunc = [](const lcPartSelectionListModelEntry& a, const lcPartSelectionListModelEntry& b)
{
2024-07-12 00:04:07 +02:00
return strcmp(a.Info->m_strDescription, b.Info->m_strDescription) < 0;
};
std::sort(mParts.begin(), mParts.end(), lcPartSortFunc);
endResetModel();
2017-07-12 03:09:15 +02:00
SetFilter(mFilter);
}
2019-12-09 04:19:02 +01:00
void lcPartSelectionListModel::SetPaletteCategory(int SetIndex)
2019-12-07 18:52:46 +01:00
{
beginResetModel();
2024-07-12 00:04:07 +02:00
ReleaseThumbnails();
2019-12-07 18:52:46 +01:00
mParts.clear();
2019-12-09 01:54:12 +01:00
lcPartSelectionWidget* PartSelectionWidget = mListView->GetPartSelectionWidget();
2019-12-09 04:19:02 +01:00
const std::vector<lcPartPalette>& Palettes = PartSelectionWidget->GetPartPalettes();
std::vector<PieceInfo*> PartsList = lcGetPiecesLibrary()->GetPartsFromSet(Palettes[SetIndex].Parts);
2019-12-07 18:52:46 +01:00
2019-12-07 20:23:50 +01:00
auto lcPartSortFunc = [](const PieceInfo* a, const PieceInfo* b)
{
return strcmp(a->m_strDescription, b->m_strDescription) < 0;
};
2019-12-09 01:54:12 +01:00
std::sort(PartsList.begin(), PartsList.end(), lcPartSortFunc);
2019-12-07 20:23:50 +01:00
2019-12-09 01:54:12 +01:00
mParts.reserve(PartsList.size());
2019-12-07 18:52:46 +01:00
2024-07-12 00:04:07 +02:00
for (PieceInfo* Info : PartsList)
mParts.emplace_back().Info = Info;
2019-12-07 18:52:46 +01:00
endResetModel();
SetFilter(mFilter);
}
void lcPartSelectionListModel::SetCurrentModelCategory()
{
beginResetModel();
2024-07-12 00:04:07 +02:00
ReleaseThumbnails();
mParts.clear();
lcModel* ActiveModel = gMainWindow->GetActiveModel();
lcPartsList PartsList;
2021-03-11 01:10:24 +01:00
if (ActiveModel)
ActiveModel->GetPartsList(gDefaultColor, true, true, PartsList);
for (const auto& PartIt : PartsList)
2024-07-12 00:04:07 +02:00
mParts.emplace_back().Info = (PieceInfo*)PartIt.first;
2024-07-12 00:04:07 +02:00
auto lcPartSortFunc = [](const lcPartSelectionListModelEntry& a, const lcPartSelectionListModelEntry& b)
{
2024-07-12 00:04:07 +02:00
return strcmp(a.Info->m_strDescription, b.Info->m_strDescription) < 0;
};
std::sort(mParts.begin(), mParts.end(), lcPartSortFunc);
endResetModel();
2017-07-12 03:09:15 +02:00
SetFilter(mFilter);
}
void lcPartSelectionListModel::SetCustomParts(const std::vector<PieceInfo*>& Parts)
{
beginResetModel();
ReleaseThumbnails();
mParts.clear();
for (PieceInfo* Part : Parts)
mParts.emplace_back().Info = Part;
auto lcPartSortFunc = [](const lcPartSelectionListModelEntry& a, const lcPartSelectionListModelEntry& b)
{
return strcmp(a.Info->m_strDescription, b.Info->m_strDescription) < 0;
};
std::sort(mParts.begin(), mParts.end(), lcPartSortFunc);
endResetModel();
SetFilter(mFilter);
}
2017-07-12 03:09:15 +02:00
void lcPartSelectionListModel::SetFilter(const QString& Filter)
{
mFilter = Filter.toLatin1();
2024-11-12 09:04:39 +01:00
bool DefaultFilter = mFileNameFilter && mPartDescriptionFilter;
bool WildcardFilter = mPartFilterType == lcPartFilterType::Wildcard;
bool FixedStringFilter = mPartFilterType == lcPartFilterType::FixedString;
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
const QString Pattern = WildcardFilter ? QRegularExpression::wildcardToRegularExpression(mFilter) : mFilter;
QRegularExpression::PatternOption PatternOptions = mCaseSensitiveFilter ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption;
QRegularExpression FilterRx = QRegularExpression(Pattern, PatternOptions);
#else
Qt::CaseSensitivity CaseSensitive = mCaseSensitiveFilter ? Qt::CaseSensitive : Qt::CaseInsensitive;
QRegExp::PatternSyntax PatternSyntax = WildcardFilter ? QRegExp::Wildcard : QRegExp::RegExp2;
QRegExp FilterRx(mFilter, CaseSensitive, PatternSyntax);
#endif
2019-05-28 20:10:21 +02:00
for (size_t PartIdx = 0; PartIdx < mParts.size(); PartIdx++)
2017-07-12 03:09:15 +02:00
{
2024-07-12 00:04:07 +02:00
PieceInfo* Info = mParts[PartIdx].Info;
2024-11-12 09:04:39 +01:00
bool Visible = true;
2017-07-12 03:09:15 +02:00
2022-07-06 16:23:31 +02:00
if (!mShowDecoratedParts && Info->IsPatterned() && !Info->IsProjectPiece())
2017-07-12 03:09:15 +02:00
Visible = false;
else if (!mShowPartAliases && Info->m_strDescription[0] == '=')
Visible = false;
2024-11-12 09:04:39 +01:00
else if (!mFilter.isEmpty())
2017-07-12 03:09:15 +02:00
{
char Description[sizeof(Info->m_strDescription)];
char* Src = Info->m_strDescription;
char* Dst = Description;
for (;;)
{
*Dst = *Src;
if (*Src == ' ' && *(Src + 1) == ' ')
Src++;
else if (*Src == 0)
break;
Src++;
Dst++;
}
2024-11-12 09:04:39 +01:00
if (FixedStringFilter)
{
if (DefaultFilter)
if (mCaseSensitiveFilter)
Visible = strstr(Description, mFilter) || strstr(Info->mFileName, mFilter);
else
Visible = strcasestr(Description, mFilter) || strcasestr(Info->mFileName, mFilter);
else if (mFileNameFilter)
Visible = mCaseSensitiveFilter ? strstr(Info->mFileName, mFilter) : strcasestr(Info->mFileName, mFilter);
else if (mPartDescriptionFilter)
Visible = mCaseSensitiveFilter ? strstr(Description, mFilter) : strcasestr(Description, mFilter);
}
else
{
if (DefaultFilter)
Visible = QString(Description).contains(FilterRx) || QString(Info->mFileName).contains(FilterRx);
else if (mFileNameFilter)
Visible = QString(Info->mFileName).contains(FilterRx);
else if (mPartDescriptionFilter)
Visible = QString(Description).contains(FilterRx);
}
2017-07-12 03:09:15 +02:00
}
mListView->setRowHidden((int)PartIdx, !Visible);
2017-07-12 03:09:15 +02:00
}
}
int lcPartSelectionListModel::rowCount(const QModelIndex& Parent) const
{
Q_UNUSED(Parent);
2016-12-19 03:53:25 +01:00
2019-05-28 01:22:49 +02:00
return (int)mParts.size();
}
QVariant lcPartSelectionListModel::data(const QModelIndex& Index, int Role) const
{
2019-05-28 20:10:21 +02:00
size_t InfoIndex = Index.row();
if (Index.isValid() && InfoIndex < mParts.size())
{
2024-07-12 00:04:07 +02:00
PieceInfo* Info = mParts[InfoIndex].Info;
switch (Role)
2016-12-16 21:52:36 +01:00
{
case Qt::DisplayRole:
if (!mIconSize || mShowPartNames || mListMode)
return QVariant(QString::fromLatin1(Info->m_strDescription));
break;
case Qt::ToolTipRole:
return QVariant(QString("%1 (%2)").arg(QString::fromLatin1(Info->m_strDescription), QString::fromLatin1(Info->mFileName)));
case Qt::DecorationRole:
2024-07-12 00:04:07 +02:00
if (mIconSize && !mParts[InfoIndex].Pixmap.isNull())
return QVariant(mParts[InfoIndex].Pixmap);
else
return QVariant(QColor(0, 0, 0, 0));
default:
break;
}
}
return QVariant();
}
QVariant lcPartSelectionListModel::headerData(int Section, Qt::Orientation Orientation, int Role) const
{
Q_UNUSED(Section);
Q_UNUSED(Orientation);
2016-12-19 03:53:25 +01:00
2016-12-19 23:23:26 +01:00
return Role == Qt::DisplayRole ? QVariant(QLatin1String("Image")) : QVariant();
}
Qt::ItemFlags lcPartSelectionListModel::flags(const QModelIndex& Index) const
{
Qt::ItemFlags DefaultFlags = QAbstractListModel::flags(Index);
if (Index.isValid())
return Qt::ItemIsDragEnabled | DefaultFlags;
else
return DefaultFlags;
}
QModelIndex lcPartSelectionListModel::GetPieceInfoIndex(PieceInfo* Info) const
{
if (Info)
{
for (int PartIndex = 0; PartIndex < static_cast<int>(mParts.size()); PartIndex++)
if (mParts[PartIndex].Info == Info)
return index(PartIndex, 0);
}
return QModelIndex();
}
2024-07-12 00:04:07 +02:00
void lcPartSelectionListModel::ReleaseThumbnails()
{
2024-07-12 00:04:07 +02:00
lcThumbnailManager* ThumbnailManager = lcGetPiecesLibrary()->GetThumbnailManager();
2017-01-23 04:28:05 +01:00
2024-07-12 00:04:07 +02:00
for (lcPartSelectionListModelEntry& Part : mParts)
{
2024-07-12 00:04:07 +02:00
ThumbnailManager->ReleaseThumbnail(Part.ThumbnailId);
Part.ThumbnailId = lcPartThumbnailId::Invalid;
Part.Pixmap = QPixmap();
}
2017-01-23 04:28:05 +01:00
}
2024-07-12 00:04:07 +02:00
void lcPartSelectionListModel::RequestThumbnail(int PartIndex)
2017-01-23 04:28:05 +01:00
{
2024-07-12 00:04:07 +02:00
if (!mIconSize || !mParts[PartIndex].Pixmap.isNull() || mParts[PartIndex].ThumbnailId != lcPartThumbnailId::Invalid)
return;
2024-07-12 00:04:07 +02:00
PieceInfo* Info = mParts[PartIndex].Info;
auto [ThumbnailId, Thumbnail] = lcGetPiecesLibrary()->GetThumbnailManager()->RequestThumbnail(Info, mColorIndex, mIconSize);
2024-07-12 00:04:07 +02:00
mParts[PartIndex].ThumbnailId = ThumbnailId;
2024-07-12 00:04:07 +02:00
if (!Thumbnail.isNull())
{
mParts[PartIndex].Pixmap = Thumbnail;
2024-07-12 00:04:07 +02:00
emit dataChanged(index(PartIndex, 0), index(PartIndex, 0), { Qt::DecorationRole });
}
2024-07-12 00:04:07 +02:00
}
2024-07-12 00:04:07 +02:00
void lcPartSelectionListModel::ThumbnailReady(lcPartThumbnailId ThumbnailId, QPixmap Pixmap)
{
for (int PartIndex = 0; PartIndex < static_cast<int>(mParts.size()); PartIndex++)
{
2024-07-12 00:04:07 +02:00
if (mParts[PartIndex].ThumbnailId == ThumbnailId)
2021-03-21 21:43:07 +01:00
{
2024-07-12 00:04:07 +02:00
mParts[PartIndex].Pixmap = Pixmap;
2021-03-21 21:43:07 +01:00
2024-07-12 00:04:07 +02:00
emit dataChanged(index(PartIndex, 0), index(PartIndex, 0), { Qt::DecorationRole });
2021-03-21 21:43:07 +01:00
2024-07-12 00:04:07 +02:00
break;
}
}
}
2017-07-12 03:09:15 +02:00
void lcPartSelectionListModel::SetShowDecoratedParts(bool Show)
{
if (Show == mShowDecoratedParts)
return;
mShowDecoratedParts = Show;
SetFilter(mFilter);
}
void lcPartSelectionListModel::SetShowPartAliases(bool Show)
{
if (Show == mShowPartAliases)
return;
mShowPartAliases = Show;
SetFilter(mFilter);
}
2024-11-12 09:04:39 +01:00
void lcPartSelectionListModel::SetPartFilterType(lcPartFilterType Option)
{
if (Option == mPartFilterType)
return;
mPartFilterType = Option;
SetFilter(mFilter);
}
void lcPartSelectionListModel::SetCaseSensitiveFilter(bool Option)
{
if (Option == mCaseSensitiveFilter)
return;
mCaseSensitiveFilter = Option;
SetFilter(mFilter);
}
void lcPartSelectionListModel::SetFileNameFilter(bool Option)
{
if (Option == mFileNameFilter)
return;
mFileNameFilter = Option;
SetFilter(mFilter);
}
void lcPartSelectionListModel::SetPartDescriptionFilter(bool Option)
{
if (Option == mPartDescriptionFilter)
return;
mPartDescriptionFilter = Option;
SetFilter(mFilter);
}
void lcPartSelectionListModel::SetIconSize(int Size)
{
if (Size == mIconSize)
return;
mIconSize = Size;
beginResetModel();
2024-07-12 00:04:07 +02:00
ReleaseThumbnails();
endResetModel();
SetFilter(mFilter);
}
2017-01-28 03:20:44 +01:00
void lcPartSelectionListModel::SetShowPartNames(bool Show)
{
if (Show == mShowPartNames)
return;
mShowPartNames = Show;
beginResetModel();
endResetModel();
SetFilter(mFilter);
2017-01-28 03:20:44 +01:00
}
2019-12-09 01:54:12 +01:00
lcPartSelectionListView::lcPartSelectionListView(QWidget* Parent, lcPartSelectionWidget* PartSelectionWidget)
: QListView(Parent), mPartSelectionWidget(PartSelectionWidget)
{
setUniformItemSizes(true);
setResizeMode(QListView::Adjust);
setWordWrap(false);
setDragEnabled(true);
setContextMenuPolicy(Qt::CustomContextMenu);
setAutoScroll(false);
mListModel = new lcPartSelectionListModel(this);
2017-07-12 03:09:15 +02:00
setModel(mListModel);
lcPartSelectionItemDelegate* ItemDelegate = new lcPartSelectionItemDelegate(this, mListModel);
setItemDelegate(ItemDelegate);
connect(this, SIGNAL(customContextMenuRequested(QPoint)), SLOT(CustomContextMenuRequested(QPoint)));
SetIconSize(lcGetProfileInt(LC_PROFILE_PARTS_LIST_ICONS));
}
void lcPartSelectionListView::CustomContextMenuRequested(QPoint Pos)
{
if (!mPartSelectionWidget)
return;
QMenu* Menu = new QMenu(this);
2019-12-07 18:52:46 +01:00
QModelIndex Index = indexAt(Pos);
2019-12-09 01:54:12 +01:00
mContextInfo = Index.isValid() ? mListModel->GetPieceInfo(Index.row()) : nullptr;
2019-12-07 20:23:50 +01:00
2019-12-09 04:19:02 +01:00
QMenu* SetMenu = Menu->addMenu(tr("Add to Palette"));
2019-12-07 18:52:46 +01:00
2019-12-09 04:19:02 +01:00
const std::vector<lcPartPalette>& Palettes = mPartSelectionWidget->GetPartPalettes();
2019-12-07 18:52:46 +01:00
2019-12-09 04:19:02 +01:00
if (!Palettes.empty())
{
2019-12-09 04:19:02 +01:00
for (const lcPartPalette& Palette : Palettes)
SetMenu->addAction(Palette.Name, mPartSelectionWidget, SLOT(AddToPalette()));
}
2019-12-09 01:54:12 +01:00
else
2017-01-28 03:20:44 +01:00
{
2019-12-09 01:54:12 +01:00
QAction* Action = SetMenu->addAction(tr("None"));
Action->setEnabled(false);
2017-01-28 03:20:44 +01:00
}
2019-12-09 04:19:02 +01:00
QAction* RemoveAction = Menu->addAction(tr("Remove from Palette"), mPartSelectionWidget, SLOT(RemoveFromPalette()));
RemoveAction->setEnabled(mCategoryType == lcPartCategoryType::Palette);
2019-12-09 01:54:12 +01:00
Menu->exec(viewport()->mapToGlobal(Pos));
delete Menu;
}
2019-12-09 01:54:12 +01:00
void lcPartSelectionListView::SetCategory(lcPartCategoryType Type, int Index)
{
QModelIndex CurrentIndex = currentIndex();
if (CurrentIndex.isValid())
mLastCategoryRow[{mCategoryType, mCategoryIndex}] = CurrentIndex.row();
2019-12-09 01:54:12 +01:00
mCategoryType = Type;
mCategoryIndex = Index;
2019-12-09 01:54:12 +01:00
switch (Type)
{
case lcPartCategoryType::AllParts:
mListModel->SetCategory(-1);
break;
case lcPartCategoryType::PartsInUse:
mListModel->SetCurrentModelCategory();
break;
case lcPartCategoryType::Submodels:
mListModel->SetModelsCategory();
break;
2019-12-09 04:19:02 +01:00
case lcPartCategoryType::Palette:
mListModel->SetPaletteCategory(Index);
2019-12-09 01:54:12 +01:00
break;
case lcPartCategoryType::Category:
mListModel->SetCategory(Index);
break;
case lcPartCategoryType::Custom:
case lcPartCategoryType::Count:
break;
}
auto CurrentIt = mLastCategoryRow.find({mCategoryType, mCategoryIndex});
bool ScrollToTop = true;
if (CurrentIt != mLastCategoryRow.end())
{
CurrentIndex = mListModel->index(CurrentIt->second, 0);
if (!isRowHidden(CurrentIndex.row()))
{
scrollTo(CurrentIndex);
setCurrentIndex(CurrentIndex);
ScrollToTop = false;
}
}
if (ScrollToTop)
{
scrollToTop();
setCurrentIndex(indexAt(QPoint(0, 0)));
}
}
void lcPartSelectionListView::SetCustomParts(const std::vector<PieceInfo*>& Parts)
{
mCategoryType = lcPartCategoryType::Custom;
mListModel->SetCustomParts(Parts);
setCurrentIndex(mListModel->index(0, 0));
}
void lcPartSelectionListView::SetCurrentPart(PieceInfo* Info)
{
QModelIndex Index = mListModel->GetPieceInfoIndex(Info);
if (Index.isValid())
{
setCurrentIndex(Index);
scrollTo(Index, QAbstractItemView::EnsureVisible);
}
}
2017-01-28 03:20:44 +01:00
void lcPartSelectionListView::SetNoIcons()
{
SetIconSize(0);
}
void lcPartSelectionListView::SetSmallIcons()
{
SetIconSize(32);
}
void lcPartSelectionListView::SetMediumIcons()
{
SetIconSize(64);
}
void lcPartSelectionListView::SetLargeIcons()
{
SetIconSize(96);
}
void lcPartSelectionListView::SetExtraLargeIcons()
{
SetIconSize(192);
}
2017-01-28 03:20:44 +01:00
void lcPartSelectionListView::TogglePartNames()
{
2017-01-28 03:20:44 +01:00
bool Show = !mListModel->GetShowPartNames();
mListModel->SetShowPartNames(Show);
lcSetProfileInt(LC_PROFILE_PARTS_LIST_NAMES, Show);
}
void lcPartSelectionListView::ToggleDecoratedParts()
{
2017-07-12 03:09:15 +02:00
bool Show = !mListModel->GetShowDecoratedParts();
mListModel->SetShowDecoratedParts(Show);
lcSetProfileInt(LC_PROFILE_PARTS_LIST_DECORATED, Show);
}
void lcPartSelectionListView::TogglePartAliases()
{
bool Show = !mListModel->GetShowPartAliases();
mListModel->SetShowPartAliases(Show);
lcSetProfileInt(LC_PROFILE_PARTS_LIST_ALIASES, Show);
}
2024-11-12 09:04:39 +01:00
void lcPartSelectionListView::SetFixedStringFilter()
{
SetPartFilterType(lcPartFilterType::FixedString);
}
void lcPartSelectionListView::SetWildcardFilter()
{
SetPartFilterType(lcPartFilterType::Wildcard);
}
void lcPartSelectionListView::SetRegularExpressionFilter()
{
SetPartFilterType(lcPartFilterType::RegularExpression);
}
void lcPartSelectionListView::ToggleCaseSensitiveFilter()
{
bool Option = !mListModel->GetCaseSensitiveFilter();
mListModel->SetCaseSensitiveFilter(Option);
lcSetProfileInt(LC_PROFILE_PARTS_LIST_CASE_SENSITIVE_FILTER, Option);
}
void lcPartSelectionListView::ToggleFileNameFilter()
{
bool Option = !mListModel->GetFileNameFilter();
mListModel->SetFileNameFilter(Option);
lcSetProfileInt(LC_PROFILE_PARTS_LIST_FILE_NAME_FILTER, Option);
}
void lcPartSelectionListView::TogglePartDescriptionFilter()
{
bool Option = !mListModel->GetPartDescriptionFilter();
mListModel->SetPartDescriptionFilter(Option);
lcSetProfileInt(LC_PROFILE_PARTS_LIST_PART_DESCRIPTION_FILTER, Option);
}
void lcPartSelectionListView::SetPartFilterType(lcPartFilterType Option)
{
mListModel->SetPartFilterType(Option);
lcSetProfileInt(LC_PROFILE_PARTS_LIST_PART_FILTER, static_cast<int>(Option));
}
void lcPartSelectionListView::ToggleListMode()
{
mListModel->ToggleListMode();
}
void lcPartSelectionListView::ToggleFixedColor()
2017-01-28 03:20:44 +01:00
{
mListModel->ToggleColorLocked();
}
void lcPartSelectionListView::UpdateInUseCategory()
{
if (mCategoryType == lcPartCategoryType::PartsInUse)
mListModel->SetCurrentModelCategory();
}
void lcPartSelectionListView::UpdateViewMode()
{
setViewMode(mListModel->GetIconSize() && !mListModel->IsListMode() ? QListView::IconMode : QListView::ListMode);
setWordWrap(mListModel->IsListMode());
setDragEnabled(true);
}
void lcPartSelectionListView::SetIconSize(int Size)
{
setIconSize(QSize(Size, Size));
lcSetProfileInt(LC_PROFILE_PARTS_LIST_ICONS, Size);
mListModel->SetIconSize(Size);
UpdateViewMode();
2019-05-12 01:07:27 +02:00
int Width = Size + 2 * frameWidth() + 6;
if (verticalScrollBar())
Width += verticalScrollBar()->sizeHint().width();
int Height = Size + 2 * frameWidth() + 2;
if (horizontalScrollBar())
Height += horizontalScrollBar()->sizeHint().height();
setMinimumSize(Width, Height);
}
void lcPartSelectionListView::startDrag(Qt::DropActions SupportedActions)
{
Q_UNUSED(SupportedActions);
PieceInfo* Info = GetCurrentPart();
if (!Info)
return;
QByteArray ItemData;
QDataStream DataStream(&ItemData, QIODevice::WriteOnly);
DataStream << QString(Info->mFileName);
QMimeData* MimeData = new QMimeData;
MimeData->setData("application/vnd.leocad-part", ItemData);
QDrag* Drag = new QDrag(this);
Drag->setMimeData(MimeData);
Drag->exec(Qt::CopyAction);
}
lcPartSelectionWidget::lcPartSelectionWidget(QWidget* Parent)
: QWidget(Parent)
{
mSplitter = new QSplitter(this);
2017-02-06 18:06:52 +01:00
mSplitter->setOrientation(Qt::Vertical);
mSplitter->setChildrenCollapsible(false);
2023-04-18 00:59:12 +02:00
QWidget* CategoriesGroupWidget = new QWidget(mSplitter);
QVBoxLayout* CategoriesLayout = new QVBoxLayout();
CategoriesLayout->setContentsMargins(0, 0, 0, 0);
CategoriesGroupWidget->setLayout(CategoriesLayout);
QHBoxLayout* FilterCategoriesLayout = new QHBoxLayout();
2023-04-19 13:07:46 +02:00
FilterCategoriesLayout->setContentsMargins(0, 0, 0, 0);
2023-04-18 00:59:12 +02:00
CategoriesLayout->addLayout(FilterCategoriesLayout);
mFilterCategoriesWidget = new QLineEdit(CategoriesGroupWidget);
mFilterCategoriesWidget->setPlaceholderText(tr("Filter Categories"));
FilterCategoriesLayout->addWidget(mFilterCategoriesWidget);
2023-04-19 13:07:46 +02:00
mFilterCaseAction = new QAction();
mFilterCaseAction->setIcon(QIcon(":/resources/case.png"));
mFilterCaseAction->setToolTip(tr("Match Case"));
mFilterCaseAction->setCheckable(true);
mFilterCaseAction->setChecked(false);
connect(mFilterCaseAction, SIGNAL(triggered()), this, SLOT(FilterCaseTriggered()));
QToolButton* FilterCaseButton = new QToolButton();
FilterCaseButton->setDefaultAction(mFilterCaseAction);
FilterCategoriesLayout->addWidget(FilterCaseButton);
mCategoriesWidget = new QTreeWidget(mSplitter);
mCategoriesWidget->setHeaderHidden(true);
mCategoriesWidget->setUniformRowHeights(true);
mCategoriesWidget->setRootIsDecorated(false);
2023-04-18 00:59:12 +02:00
CategoriesLayout->addWidget(mCategoriesWidget);
QWidget* PartsGroupWidget = new QWidget(mSplitter);
QVBoxLayout* PartsLayout = new QVBoxLayout();
PartsLayout->setContentsMargins(0, 0, 0, 0);
PartsGroupWidget->setLayout(PartsLayout);
2019-12-09 01:54:12 +01:00
QHBoxLayout* SearchLayout = new QHBoxLayout();
SearchLayout->setContentsMargins(0, 0, 0, 0);
PartsLayout->addLayout(SearchLayout);
mFilterWidget = new QLineEdit(PartsGroupWidget);
mFilterWidget->setPlaceholderText(tr("Filter Parts"));
2019-12-09 01:54:12 +01:00
SearchLayout->addWidget(mFilterWidget);
QToolButton* OptionsButton = new QToolButton();
2019-12-12 02:26:18 +01:00
OptionsButton->setIcon(QIcon(":/resources/gear_in.png"));
OptionsButton->setToolTip(tr("Options"));
2019-12-09 01:54:12 +01:00
OptionsButton->setPopupMode(QToolButton::InstantPopup);
SearchLayout->addWidget(OptionsButton);
2019-12-09 01:54:12 +01:00
QMenu* OptionsMenu = new QMenu(this);
OptionsButton->setMenu(OptionsMenu);
connect(OptionsMenu, SIGNAL(aboutToShow()), this, SLOT(OptionsMenuAboutToShow()));
mPartsWidget = new lcPartSelectionListView(PartsGroupWidget, this);
PartsLayout->addWidget(mPartsWidget);
QHBoxLayout* Layout = new QHBoxLayout(this);
Layout->setContentsMargins(0, 0, 0, 0);
Layout->addWidget(mSplitter);
setLayout(Layout);
connect(mPartsWidget, &QListView::doubleClicked, this, &lcPartSelectionWidget::PartViewDoubleClicked);
connect(mPartsWidget->selectionModel(), &QItemSelectionModel::currentChanged, this, &lcPartSelectionWidget::PartViewSelectionChanged);
connect(mFilterWidget, &QLineEdit::textChanged, this, &lcPartSelectionWidget::FilterChanged);
connect(mCategoriesWidget, &QTreeWidget::currentItemChanged, this, &lcPartSelectionWidget::CategoryChanged);
connect(mFilterCategoriesWidget, &QLineEdit::textChanged, this, &lcPartSelectionWidget::FilterCategoriesChanged);
2016-12-19 03:53:25 +01:00
2019-12-09 04:19:02 +01:00
LoadPartPalettes();
2016-12-19 03:53:25 +01:00
UpdateCategories();
2017-02-06 18:06:52 +01:00
mSplitter->setStretchFactor(0, 0);
mSplitter->setStretchFactor(1, 1);
}
bool lcPartSelectionWidget::event(QEvent* Event)
{
if (Event->type() == QEvent::ShortcutOverride)
{
QKeyEvent* KeyEvent = (QKeyEvent*)Event;
int Key = KeyEvent->key();
if (KeyEvent->modifiers() == Qt::NoModifier && Key >= Qt::Key_A && Key <= Qt::Key_Z)
Event->accept();
switch (Key)
{
case Qt::Key_Down:
case Qt::Key_Up:
case Qt::Key_Left:
case Qt::Key_Right:
case Qt::Key_Home:
case Qt::Key_End:
case Qt::Key_PageUp:
case Qt::Key_PageDown:
case Qt::Key_Asterisk:
case Qt::Key_Plus:
case Qt::Key_Minus:
Event->accept();
break;
}
}
return QWidget::event(Event);
}
2017-02-06 18:06:52 +01:00
void lcPartSelectionWidget::LoadState(QSettings& Settings)
{
2017-02-06 18:06:52 +01:00
QList<int> Sizes = Settings.value("PartSelectionSplitter").value<QList<int>>();
if (Sizes.size() != 2)
{
int Length = mSplitter->orientation() == Qt::Horizontal ? mSplitter->width() : mSplitter->height();
Sizes = { Length / 3, 2 * Length / 3 };
2017-02-06 18:06:52 +01:00
}
mSplitter->setSizes(Sizes);
}
void lcPartSelectionWidget::SaveState(QSettings& Settings)
{
QList<int> Sizes = mSplitter->sizes();
Settings.setValue("PartSelectionSplitter", QVariant::fromValue(Sizes));
}
void lcPartSelectionWidget::DisableIconMode()
{
mPartsWidget->SetNoIcons();
}
void lcPartSelectionWidget::SetCurrentPart(PieceInfo* Info)
{
mCategoriesWidget->setCurrentItem(mAllPartsCategoryItem);
mPartsWidget->SetCurrentPart(Info);
2024-07-26 02:56:29 +02:00
mPartsWidget->setFocus();
}
void lcPartSelectionWidget::SetOrientation(Qt::Orientation Orientation)
{
mSplitter->setOrientation(Orientation);
int Length = mSplitter->orientation() == Qt::Horizontal ? mSplitter->width() : mSplitter->height();
QList<int> Sizes = { Length / 3, 2 * Length / 3 };
mSplitter->setSizes(Sizes);
}
2017-02-06 18:06:52 +01:00
void lcPartSelectionWidget::DockLocationChanged(Qt::DockWidgetArea Area)
{
if (Area == Qt::LeftDockWidgetArea || Area == Qt::RightDockWidgetArea)
mSplitter->setOrientation(Qt::Vertical);
2017-02-06 18:06:52 +01:00
else
mSplitter->setOrientation(Qt::Horizontal);
}
void lcPartSelectionWidget::resizeEvent(QResizeEvent* Event)
{
QDockWidget* DockWidget = qobject_cast<QDockWidget*>(parent());
if (DockWidget && DockWidget->isFloating())
2017-02-06 18:06:52 +01:00
{
if (Event->size().width() > Event->size().height())
mSplitter->setOrientation(Qt::Horizontal);
else
mSplitter->setOrientation(Qt::Vertical);
}
QWidget::resizeEvent(Event);
}
2023-04-18 00:59:12 +02:00
void lcPartSelectionWidget::FilterCategoriesChanged(const QString& Text)
{
if (mFilterCategoriesAction)
{
if (Text.isEmpty())
{
delete mFilterCategoriesAction;
mFilterCategoriesAction = nullptr;
}
}
else
{
if (!Text.isEmpty())
{
mFilterCategoriesAction = mFilterCategoriesWidget->addAction(QIcon(":/stylesheet/close.svg"), QLineEdit::TrailingPosition);
connect(mFilterCategoriesAction, &QAction::triggered, this, &lcPartSelectionWidget::FilterCategoriesTriggered);
}
2023-04-18 00:59:12 +02:00
}
bool Hide = true;
2023-04-19 13:07:46 +02:00
Qt::CaseSensitivity MatchCase = mFilterCaseAction->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive;
2023-04-18 00:59:12 +02:00
mCategoriesWidget->setUpdatesEnabled(false);
for (int CategoryIdx = 0; CategoryIdx < mCategoriesWidget->topLevelItemCount(); CategoryIdx++)
{
QTreeWidgetItem* CategoryItem = mCategoriesWidget->topLevelItem(CategoryIdx);
Hide = false;
2023-04-19 13:07:46 +02:00
if (!CategoryItem->text(0).contains(Text, MatchCase))
2023-04-18 00:59:12 +02:00
Hide = true;
CategoryItem->setHidden(Hide);
}
mCategoriesWidget->setUpdatesEnabled(true);
mCategoriesWidget->update();
}
void lcPartSelectionWidget::FilterChanged(const QString& Text)
{
2017-02-01 06:12:30 +01:00
if (mFilterAction)
{
if (Text.isEmpty())
{
delete mFilterAction;
mFilterAction = nullptr;
}
}
else
{
if (!Text.isEmpty())
{
mFilterAction = mFilterWidget->addAction(QIcon(":/stylesheet/close.svg"), QLineEdit::TrailingPosition);
connect(mFilterAction, &QAction::triggered, this, &lcPartSelectionWidget::FilterTriggered);
}
2017-02-01 06:12:30 +01:00
}
2017-07-12 03:09:15 +02:00
mPartsWidget->GetListModel()->SetFilter(Text);
}
2023-04-18 00:59:12 +02:00
void lcPartSelectionWidget::FilterCategoriesTriggered()
{
mFilterCategoriesWidget->clear();
}
2023-04-19 13:07:46 +02:00
void lcPartSelectionWidget::FilterCaseTriggered()
{
if (!mFilterCategoriesWidget->text().isEmpty())
FilterCategoriesChanged(mFilterCategoriesWidget->text());
}
2017-02-01 06:12:30 +01:00
void lcPartSelectionWidget::FilterTriggered()
{
mFilterWidget->clear();
}
void lcPartSelectionWidget::CategoryChanged(QTreeWidgetItem* Current, QTreeWidgetItem* Previous)
{
Q_UNUSED(Previous);
2016-12-19 03:53:25 +01:00
2019-12-09 01:54:12 +01:00
if (!Current)
return;
int Type = Current->data(0, static_cast<int>(lcPartCategoryRole::Type)).toInt();
int Index = Current->data(0, static_cast<int>(lcPartCategoryRole::Index)).toInt();
2016-12-19 03:53:25 +01:00
2019-12-09 01:54:12 +01:00
mPartsWidget->SetCategory(static_cast<lcPartCategoryType>(Type), Index);
}
void lcPartSelectionWidget::PartViewSelectionChanged(const QModelIndex& Current, const QModelIndex& Previous)
{
2016-12-19 03:53:25 +01:00
Q_UNUSED(Current);
Q_UNUSED(Previous);
2024-07-26 02:56:29 +02:00
emit CurrentPartChanged(mPartsWidget->GetCurrentPart());
}
void lcPartSelectionWidget::PartViewDoubleClicked(const QModelIndex& Index)
{
PieceInfo* Info = mPartsWidget->GetListModel()->GetPieceInfo(Index.row());
if (Info)
2024-07-26 02:56:29 +02:00
emit PartPicked(Info);
2016-12-16 21:52:36 +01:00
}
2016-12-19 03:53:25 +01:00
2019-12-09 01:54:12 +01:00
void lcPartSelectionWidget::OptionsMenuAboutToShow()
2019-12-07 18:52:46 +01:00
{
2019-12-09 01:54:12 +01:00
QMenu* Menu = (QMenu*)sender();
Menu->clear();
2022-05-16 21:36:52 +02:00
Menu->addAction(tr("Edit Palettes..."), this, SLOT(EditPartPalettes()));
2019-12-09 04:19:02 +01:00
Menu->addSeparator();
2019-12-09 01:54:12 +01:00
lcPartSelectionListModel* ListModel = mPartsWidget->GetListModel();
if (ListModel->GetIconSize() != 0 && !ListModel->IsListMode())
{
QAction* PartNames = Menu->addAction(tr("Show Part Names"), mPartsWidget, &lcPartSelectionListView::TogglePartNames);
PartNames->setCheckable(true);
PartNames->setChecked(ListModel->GetShowPartNames());
}
QAction* DecoratedParts = Menu->addAction(tr("Show Decorated Parts"), mPartsWidget, &lcPartSelectionListView::ToggleDecoratedParts);
DecoratedParts->setCheckable(true);
DecoratedParts->setChecked(ListModel->GetShowDecoratedParts());
QAction* PartAliases = Menu->addAction(tr("Show Part Aliases"), mPartsWidget, &lcPartSelectionListView::TogglePartAliases);
PartAliases->setCheckable(true);
PartAliases->setChecked(ListModel->GetShowPartAliases());
Menu->addSeparator();
2020-12-27 22:05:55 +01:00
if (gSupportsFramebufferObject)
2019-12-09 01:54:12 +01:00
{
QMenu* IconMenu = Menu->addMenu(tr("Icons"));
2019-12-09 01:54:12 +01:00
QActionGroup* IconGroup = new QActionGroup(Menu);
QAction* NoIcons = IconMenu->addAction(tr("No Icons"), mPartsWidget, &lcPartSelectionListView::SetNoIcons);
2019-12-09 01:54:12 +01:00
NoIcons->setCheckable(true);
NoIcons->setChecked(ListModel->GetIconSize() == 0);
IconGroup->addAction(NoIcons);
QAction* SmallIcons = IconMenu->addAction(tr("Small Icons"), mPartsWidget, &lcPartSelectionListView::SetSmallIcons);
2019-12-09 01:54:12 +01:00
SmallIcons->setCheckable(true);
SmallIcons->setChecked(ListModel->GetIconSize() == 32);
IconGroup->addAction(SmallIcons);
QAction* MediumIcons = IconMenu->addAction(tr("Medium Icons"), mPartsWidget, &lcPartSelectionListView::SetMediumIcons);
2019-12-09 01:54:12 +01:00
MediumIcons->setCheckable(true);
MediumIcons->setChecked(ListModel->GetIconSize() == 64);
IconGroup->addAction(MediumIcons);
QAction* LargeIcons = IconMenu->addAction(tr("Large Icons"), mPartsWidget, &lcPartSelectionListView::SetLargeIcons);
2019-12-09 01:54:12 +01:00
LargeIcons->setCheckable(true);
LargeIcons->setChecked(ListModel->GetIconSize() == 96);
IconGroup->addAction(LargeIcons);
QAction* ExtraLargeIcons = IconMenu->addAction(tr("Extra Large Icons"), mPartsWidget, &lcPartSelectionListView::SetExtraLargeIcons);
2019-12-09 01:54:12 +01:00
ExtraLargeIcons->setCheckable(true);
ExtraLargeIcons->setChecked(ListModel->GetIconSize() == 192);
IconGroup->addAction(ExtraLargeIcons);
if (ListModel->GetIconSize() != 0)
{
IconMenu->addSeparator();
2019-12-09 01:54:12 +01:00
QAction* ListMode = IconMenu->addAction(tr("List Mode"), mPartsWidget, &lcPartSelectionListView::ToggleListMode);
ListMode->setCheckable(true);
ListMode->setChecked(ListModel->IsListMode());
2019-12-09 01:54:12 +01:00
QAction* FixedColor = IconMenu->addAction(tr("Lock Color"), mPartsWidget, &lcPartSelectionListView::ToggleFixedColor);
FixedColor->setCheckable(true);
FixedColor->setChecked(ListModel->IsColorLocked());
}
2019-12-09 01:54:12 +01:00
}
2024-11-12 09:04:39 +01:00
QMenu* FilterMenu = Menu->addMenu(tr("Filter"));
2024-11-12 09:04:39 +01:00
QActionGroup* FilterGroup = new QActionGroup(Menu);
QAction* PartFilterType = FilterMenu->addAction(tr("Fixed String"), mPartsWidget, &lcPartSelectionListView::SetFixedStringFilter);
2024-11-12 09:04:39 +01:00
PartFilterType->setCheckable(true);
PartFilterType->setChecked(ListModel->GetPartFilterType() == lcPartFilterType::FixedString);
FilterGroup->addAction(PartFilterType);
QAction* WildcardFilter = FilterMenu->addAction(tr("Wildcard"), mPartsWidget, &lcPartSelectionListView::SetWildcardFilter);
2024-11-12 09:04:39 +01:00
WildcardFilter->setCheckable(true);
WildcardFilter->setChecked(ListModel->GetPartFilterType() == lcPartFilterType::Wildcard);
FilterGroup->addAction(WildcardFilter);
QAction* RegularExpressionFilter = FilterMenu->addAction(tr("Regular Expression"), mPartsWidget, &lcPartSelectionListView::SetRegularExpressionFilter);
2024-11-12 09:04:39 +01:00
RegularExpressionFilter->setCheckable(true);
RegularExpressionFilter->setChecked(ListModel->GetPartFilterType() == lcPartFilterType::RegularExpression);
FilterGroup->addAction(RegularExpressionFilter);
FilterMenu->addSeparator();
QAction* CaseSensitiveFilter = FilterMenu->addAction(tr("Match Case"), mPartsWidget, &lcPartSelectionListView::ToggleCaseSensitiveFilter);
2024-11-12 09:04:39 +01:00
CaseSensitiveFilter->setCheckable(true);
CaseSensitiveFilter->setChecked(ListModel->GetCaseSensitiveFilter());
QAction* FileNameFilter = FilterMenu->addAction(tr("Part ID"), mPartsWidget, &lcPartSelectionListView::ToggleFileNameFilter);
2024-11-12 09:04:39 +01:00
FileNameFilter->setCheckable(true);
FileNameFilter->setChecked(ListModel->GetFileNameFilter());
FileNameFilter->setEnabled(ListModel->GetPartDescriptionFilter());
2024-11-12 09:04:39 +01:00
QAction* PartDescriptionFilter = FilterMenu->addAction(tr("Part Description"), mPartsWidget, &lcPartSelectionListView::TogglePartDescriptionFilter);
2024-11-12 09:04:39 +01:00
PartDescriptionFilter->setCheckable(true);
PartDescriptionFilter->setChecked(ListModel->GetPartDescriptionFilter());
PartDescriptionFilter->setEnabled(ListModel->GetFileNameFilter());
2019-12-07 18:52:46 +01:00
}
2019-12-16 04:01:55 +01:00
void lcPartSelectionWidget::EditPartPalettes()
2019-12-09 04:19:02 +01:00
{
2019-12-16 04:01:55 +01:00
lcPartPaletteDialog Dialog(this, mPartPalettes);
2019-12-09 04:19:02 +01:00
2019-12-16 04:01:55 +01:00
if (Dialog.exec() != QDialog::Accepted)
return;
SavePartPalettes();
UpdateCategories();
2019-12-09 04:19:02 +01:00
}
2024-07-12 00:04:07 +02:00
void lcPartSelectionWidget::UpdateThumbnails()
2016-12-28 22:30:31 +01:00
{
2024-07-12 00:04:07 +02:00
mPartsWidget->GetListModel()->UpdateThumbnails();
2016-12-28 22:30:31 +01:00
}
void lcPartSelectionWidget::SetDefaultPart()
{
for (int CategoryIdx = 0; CategoryIdx < mCategoriesWidget->topLevelItemCount(); CategoryIdx++)
{
QTreeWidgetItem* CategoryItem = mCategoriesWidget->topLevelItem(CategoryIdx);
if (CategoryItem->text(0) == "Brick")
{
mCategoriesWidget->setCurrentItem(CategoryItem);
break;
}
}
}
2019-12-09 04:19:02 +01:00
void lcPartSelectionWidget::LoadPartPalettes()
2019-12-09 01:54:12 +01:00
{
2019-12-09 04:19:02 +01:00
QByteArray Buffer = lcGetProfileBuffer(LC_PROFILE_PART_PALETTES);
2019-12-09 01:54:12 +01:00
QJsonDocument Document = QJsonDocument::fromJson(Buffer);
if (Document.isNull())
2019-12-09 04:19:02 +01:00
Document = QJsonDocument::fromJson((QString("{ \"Version\":1, \"Palettes\": { \"%1\": [] } }").arg(tr("Favorites"))).toUtf8());
2019-12-09 01:54:12 +01:00
QJsonObject RootObject = Document.object();
2019-12-09 04:19:02 +01:00
mPartPalettes.clear();
2019-12-09 01:54:12 +01:00
int Version = RootObject["Version"].toInt(0);
if (Version != 1)
return;
2019-12-09 04:19:02 +01:00
QJsonObject PalettesObject = RootObject["Palettes"].toObject();
2019-12-09 01:54:12 +01:00
2019-12-09 04:19:02 +01:00
for (QJsonObject::const_iterator ElementIt = PalettesObject.constBegin(); ElementIt != PalettesObject.constEnd(); ElementIt++)
2019-12-09 01:54:12 +01:00
{
if (!ElementIt.value().isArray())
continue;
2019-12-09 04:19:02 +01:00
lcPartPalette Palette;
Palette.Name = ElementIt.key();
2019-12-09 01:54:12 +01:00
QJsonArray Parts = ElementIt.value().toArray();
for (const QJsonValue& Part : Parts)
2019-12-09 04:19:02 +01:00
Palette.Parts.emplace_back(Part.toString().toStdString());
2019-12-09 01:54:12 +01:00
2019-12-09 04:19:02 +01:00
mPartPalettes.emplace_back(std::move(Palette));
2019-12-09 01:54:12 +01:00
}
}
2019-12-09 04:19:02 +01:00
void lcPartSelectionWidget::SavePartPalettes()
2019-12-09 01:54:12 +01:00
{
QJsonObject RootObject;
RootObject["Version"] = 1;
2019-12-09 04:19:02 +01:00
QJsonObject PalettesObject;
2019-12-09 01:54:12 +01:00
2019-12-09 04:19:02 +01:00
for (const lcPartPalette& Palette : mPartPalettes)
2019-12-09 01:54:12 +01:00
{
QJsonArray Parts;
2019-12-09 04:19:02 +01:00
for (const std::string& PartId : Palette.Parts)
2019-12-09 01:54:12 +01:00
Parts.append(QString::fromStdString(PartId));
2019-12-09 04:19:02 +01:00
PalettesObject[Palette.Name] = Parts;
2019-12-09 01:54:12 +01:00
}
2019-12-09 04:19:02 +01:00
RootObject["Palettes"] = PalettesObject;
2019-12-09 01:54:12 +01:00
QByteArray Buffer = QJsonDocument(RootObject).toJson();
2019-12-09 04:19:02 +01:00
lcSetProfileBuffer(LC_PROFILE_PART_PALETTES, Buffer);
2019-12-09 01:54:12 +01:00
}
2019-12-09 04:19:02 +01:00
void lcPartSelectionWidget::AddToPalette()
2019-12-09 01:54:12 +01:00
{
PieceInfo* Info = mPartsWidget->GetContextInfo();
if (!Info)
return;
QString SetName = ((QAction*)sender())->text();
2019-12-09 04:19:02 +01:00
std::vector<lcPartPalette>::iterator SetIt = std::find_if(mPartPalettes.begin(), mPartPalettes.end(), [&SetName](const lcPartPalette& Set)
2019-12-09 01:54:12 +01:00
{
return Set.Name == SetName;
});
2019-12-09 04:19:02 +01:00
if (SetIt == mPartPalettes.end())
2019-12-09 01:54:12 +01:00
return;
std::string PartId = lcGetPiecesLibrary()->GetPartId(Info);
2019-12-09 04:19:02 +01:00
std::vector<std::string>& Parts = SetIt->Parts;
2019-12-09 01:54:12 +01:00
2019-12-09 04:19:02 +01:00
if (std::find(Parts.begin(), Parts.end(), PartId) == Parts.end())
2019-12-09 01:54:12 +01:00
{
2019-12-09 04:19:02 +01:00
Parts.emplace_back(PartId);
SavePartPalettes();
2019-12-09 01:54:12 +01:00
}
}
2019-12-09 04:19:02 +01:00
void lcPartSelectionWidget::RemoveFromPalette()
2019-12-09 01:54:12 +01:00
{
PieceInfo* Info = mPartsWidget->GetContextInfo();
if (!Info)
return;
QTreeWidgetItem* CurrentItem = mCategoriesWidget->currentItem();
2019-12-09 04:19:02 +01:00
if (!CurrentItem || CurrentItem->data(0, static_cast<int>(lcPartCategoryRole::Type)) != static_cast<int>(lcPartCategoryType::Palette))
2019-12-09 01:54:12 +01:00
return;
int SetIndex = CurrentItem->data(0, static_cast<int>(lcPartCategoryRole::Index)).toInt();
2019-12-09 04:19:02 +01:00
lcPartPalette& Palette = mPartPalettes[SetIndex];
2019-12-09 01:54:12 +01:00
std::string PartId = lcGetPiecesLibrary()->GetPartId(Info);
2019-12-09 04:19:02 +01:00
std::vector<std::string>::iterator PartIt = std::find(Palette.Parts.begin(), Palette.Parts.end(), PartId);
2019-12-09 01:54:12 +01:00
2019-12-09 04:19:02 +01:00
if (PartIt != Palette.Parts.end())
2019-12-09 01:54:12 +01:00
{
2019-12-09 04:19:02 +01:00
Palette.Parts.erase(PartIt);
mPartsWidget->SetCategory(lcPartCategoryType::Palette, SetIndex);
SavePartPalettes();
2019-12-09 01:54:12 +01:00
}
}
void lcPartSelectionWidget::UpdateInUseCategory()
{
mPartsWidget->UpdateInUseCategory();
2019-12-09 01:54:12 +01:00
}
2016-12-19 03:53:25 +01:00
void lcPartSelectionWidget::UpdateCategories()
{
2019-12-16 04:01:55 +01:00
QTreeWidgetItem* CurrentItem = mCategoriesWidget->currentItem();
lcPartCategoryType CurrentType = lcPartCategoryType::Count;
int CurrentIndex = -1;
if (CurrentItem)
{
CurrentType = static_cast<lcPartCategoryType>(CurrentItem->data(0, static_cast<int>(lcPartCategoryRole::Type)).toInt());
CurrentIndex = CurrentItem->data(0, static_cast<int>(lcPartCategoryRole::Index)).toInt();
CurrentItem = nullptr;
}
2016-12-19 03:53:25 +01:00
mCategoriesWidget->clear();
mAllPartsCategoryItem = new QTreeWidgetItem(mCategoriesWidget, QStringList(tr("All Parts")));
mAllPartsCategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Type), static_cast<int>(lcPartCategoryType::AllParts));
2017-02-01 06:12:30 +01:00
2019-12-16 04:01:55 +01:00
if (CurrentType == lcPartCategoryType::AllParts && CurrentIndex == 0)
CurrentItem = mAllPartsCategoryItem;
2019-12-16 04:01:55 +01:00
QTreeWidgetItem* CurrentModelCategoryItem = new QTreeWidgetItem(mCategoriesWidget, QStringList(tr("In Use")));
2019-12-09 01:54:12 +01:00
CurrentModelCategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Type), static_cast<int>(lcPartCategoryType::PartsInUse));
2016-12-19 03:53:25 +01:00
2019-12-16 04:01:55 +01:00
if (CurrentType == lcPartCategoryType::PartsInUse && CurrentIndex == 0)
CurrentItem = CurrentModelCategoryItem;
2019-12-16 04:01:55 +01:00
2019-12-09 01:54:12 +01:00
QTreeWidgetItem* SubmodelsCategoryItem = new QTreeWidgetItem(mCategoriesWidget, QStringList(tr("Submodels")));
SubmodelsCategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Type), static_cast<int>(lcPartCategoryType::Submodels));
2019-12-16 04:01:55 +01:00
if (CurrentType == lcPartCategoryType::Submodels && CurrentIndex == 0)
CurrentItem = SubmodelsCategoryItem;
2019-12-16 04:01:55 +01:00
for (int PaletteIdx = 0; PaletteIdx < static_cast<int>(mPartPalettes.size()); PaletteIdx++)
2019-12-09 01:54:12 +01:00
{
2019-12-16 04:01:55 +01:00
const lcPartPalette& Set = mPartPalettes[PaletteIdx];
QTreeWidgetItem* PaletteCategoryItem = new QTreeWidgetItem(mCategoriesWidget, QStringList(Set.Name));
PaletteCategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Type), static_cast<int>(lcPartCategoryType::Palette));
PaletteCategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Index), PaletteIdx);
if (CurrentType == lcPartCategoryType::Palette && CurrentIndex == PaletteIdx)
CurrentItem = PaletteCategoryItem;
2019-12-09 01:54:12 +01:00
}
2020-01-11 02:40:14 +01:00
for (int CategoryIdx = 0; CategoryIdx < static_cast<int>(gCategories.size()); CategoryIdx++)
2019-12-09 01:54:12 +01:00
{
QTreeWidgetItem* CategoryItem = new QTreeWidgetItem(mCategoriesWidget, QStringList(gCategories[CategoryIdx].Name));
CategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Type), static_cast<int>(lcPartCategoryType::Category));
CategoryItem->setData(0, static_cast<int>(lcPartCategoryRole::Index), CategoryIdx);
2019-12-16 04:01:55 +01:00
if (CurrentType == lcPartCategoryType::Category && CurrentIndex == CategoryIdx)
CurrentItem = CategoryItem;
2019-12-09 01:54:12 +01:00
}
2019-12-16 04:01:55 +01:00
if (CurrentItem)
mCategoriesWidget->setCurrentItem(CurrentItem);
2016-12-19 03:53:25 +01:00
}
void lcPartSelectionWidget::UpdateModels()
{
2019-12-09 01:54:12 +01:00
QTreeWidgetItem* CurrentItem = mCategoriesWidget->currentItem();
if (CurrentItem && CurrentItem->data(0, static_cast<int>(lcPartCategoryRole::Type)) == static_cast<int>(lcPartCategoryType::Submodels))
mPartsWidget->SetCategory(lcPartCategoryType::Submodels, 0);
2016-12-19 03:53:25 +01:00
}