From eb1bc1cd315a04d87e7f734dc2d5a4c20949a0be Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Fri, 16 Dec 2016 09:14:19 -0800 Subject: [PATCH] First pass of the new parts list widget. --- common/lc_context.cpp | 30 ++-- common/lc_context.h | 1 + common/lc_library.cpp | 3 +- common/lc_mainwindow.cpp | 32 +++- common/lc_mainwindow.h | 10 ++ common/lc_model.cpp | 6 +- common/lc_partselectionwidget.cpp | 283 ++++++++++++++++++++++++++++++ common/lc_partselectionwidget.h | 122 +++++++++++++ common/preview.cpp | 15 +- common/preview.h | 7 - common/view.cpp | 9 +- leocad.pro | 2 + leocad.qrc | 1 + resources/parts_search.png | Bin 0 -> 1912 bytes 14 files changed, 484 insertions(+), 37 deletions(-) create mode 100644 common/lc_partselectionwidget.cpp create mode 100644 common/lc_partselectionwidget.h create mode 100644 resources/parts_search.png diff --git a/common/lc_context.cpp b/common/lc_context.cpp index 894ca143..2a679580 100644 --- a/common/lc_context.cpp +++ b/common/lc_context.cpp @@ -466,24 +466,25 @@ void lcContext::EndRenderToTexture() } } -bool lcContext::SaveRenderToTextureImage(const QString& FileName, int Width, int Height) +QImage lcContext::GetRenderToTextureImage(int Width, int Height) { - lcuint8* Buffer = (lcuint8*)malloc(Width * Height * 4); + QImage Image(Width, Height, QImage::Format_ARGB32); + quint8* Buffer = Image.bits(); glFinish(); glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, Buffer); for (int y = 0; y < (Height + 1) / 2; y++) { - lcuint8* Top = Buffer + ((Height - y - 1) * Width * 4); - lcuint8* Bottom = Buffer + y * Width * 4; + quint8* Top = Buffer + ((Height - y - 1) * Width * 4); + quint8* Bottom = Buffer + y * Width * 4; for (int x = 0; x < Width; x++) { - lcuint8 Red = Top[0]; - lcuint8 Green = Top[1]; - lcuint8 Blue = Top[2]; - lcuint8 Alpha = Top[3]; + quint8 Red = Top[0]; + quint8 Green = Top[1]; + quint8 Blue = Top[2]; + quint8 Alpha = Top[3]; Top[0] = Bottom[2]; Top[1] = Bottom[1]; @@ -496,18 +497,23 @@ bool lcContext::SaveRenderToTextureImage(const QString& FileName, int Width, int Bottom[3] = Alpha; Top += 4; - Bottom +=4; + Bottom += 4; } } + return Image; +} + +bool lcContext::SaveRenderToTextureImage(const QString& FileName, int Width, int Height) +{ + QImage Image = GetRenderToTextureImage(Width, Height); QImageWriter Writer(FileName); - bool Result = Writer.write(QImage(Buffer, Width, Height, QImage::Format_ARGB32)); + + bool Result = Writer.write(Image); if (!Result) QMessageBox::information(gMainWindow, tr("Error"), tr("Error writing to file '%1':\n%2").arg(FileName, Writer.errorString())); - free(Buffer); - return Result; } diff --git a/common/lc_context.h b/common/lc_context.h index 3204946a..35815c05 100644 --- a/common/lc_context.h +++ b/common/lc_context.h @@ -141,6 +141,7 @@ public: bool BeginRenderToTexture(int Width, int Height); void EndRenderToTexture(); + QImage GetRenderToTextureImage(int Width, int Height); bool SaveRenderToTextureImage(const QString& FileName, int Width, int Height); lcVertexBuffer CreateVertexBuffer(int Size, const void* Data); diff --git a/common/lc_library.cpp b/common/lc_library.cpp index 70a2e8de..1962d8a6 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -2320,7 +2320,8 @@ bool lcPiecesLibrary::PieceInCategory(PieceInfo* Info, const String& CategoryKey void lcPiecesLibrary::GetCategoryEntries(int CategoryIndex, bool GroupPieces, lcArray& SinglePieces, lcArray& GroupedPieces) { - GetCategoryEntries(gCategories[CategoryIndex].Keywords, GroupPieces, SinglePieces, GroupedPieces); + if (CategoryIndex >= 0 && CategoryIndex < gCategories.GetSize()) + GetCategoryEntries(gCategories[CategoryIndex].Keywords, GroupPieces, SinglePieces, GroupedPieces); } void lcPiecesLibrary::GetCategoryEntries(const String& CategoryKeywords, bool GroupPieces, lcArray& SinglePieces, lcArray& GroupedPieces) diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index bb7cd6b9..2dd7a916 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -2,6 +2,7 @@ #include "lc_mainwindow.h" #include #include +#include "lc_partselectionwidget.h" #include "lc_timelinewidget.h" #include "lc_qglwidget.h" #include "lc_qpartstree.h" @@ -41,6 +42,7 @@ lcMainWindow::lcMainWindow() mLockY = false; mLockZ = false; mRelativeTransform = true; + mCurrentPieceInfo = NULL; memset(&mSearchOptions, 0, sizeof(mSearchOptions)); @@ -52,6 +54,12 @@ lcMainWindow::lcMainWindow() lcMainWindow::~lcMainWindow() { + if (mCurrentPieceInfo) + { + mCurrentPieceInfo->Release(); + mCurrentPieceInfo = NULL; + } + for (int FileIdx = 0; FileIdx < LC_MAX_RECENT_FILES; FileIdx++) lcSetProfileString((LC_PROFILE_KEY)(LC_PROFILE_RECENT_FILE1 + FileIdx), mRecentFiles[FileIdx]); @@ -400,6 +408,7 @@ void lcMainWindow::CreateMenus() ViewMenu->addAction(mActions[LC_VIEW_RESET_VIEWS]); ViewMenu->addSeparator(); QMenu* ToolBarsMenu = ViewMenu->addMenu(tr("T&oolbars")); + ToolBarsMenu->addAction(mPartSelectionToolBar->toggleViewAction()); ToolBarsMenu->addAction(mPartsToolBar->toggleViewAction()); ToolBarsMenu->addAction(mPropertiesToolBar->toggleViewAction()); ToolBarsMenu->addAction(mTimelineToolBar->toggleViewAction()); @@ -569,6 +578,12 @@ void lcMainWindow::CreateToolBars() mTimeToolBar->addAction(mActions[LC_VIEW_TIME_ADD_KEYS]); // TODO: add missing menu items + mPartSelectionToolBar = new QDockWidget(tr("Parts"), this); + mPartSelectionToolBar->setObjectName("PartSelectionToolbar"); + mPartSelectionWidget = new lcPartSelectionWidget(this); + mPartSelectionToolBar->setWidget(mPartSelectionWidget); + addDockWidget(Qt::RightDockWidgetArea, mPartSelectionToolBar); + mPartsToolBar = new QDockWidget(tr("Parts"), this); mPartsToolBar->setObjectName("PartsToolbar"); mPartsToolBar->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); @@ -1346,6 +1361,19 @@ void lcMainWindow::SetTransformType(lcTransformType TransformType) } } +void lcMainWindow::SetCurrentPieceInfo(PieceInfo* Info) +{ + mPreviewWidget->MakeCurrent(); + + if (mCurrentPieceInfo) + mCurrentPieceInfo->Release(); + + mCurrentPieceInfo = Info; + + if (mCurrentPieceInfo) + mCurrentPieceInfo->AddRef(); +} + lcVector3 lcMainWindow::GetTransformAmount() { lcVector3 Transform; @@ -1771,8 +1799,8 @@ void lcMainWindow::UpdateModels() mPartsTree->UpdateModels(); - PieceInfo* CurPiece = mPreviewWidget->GetCurrentPiece(); - if (CurPiece->GetModel() == CurrentModel) + PieceInfo* CurPiece = GetCurrentPieceInfo(); + if (CurPiece && CurPiece->GetModel() == CurrentModel) mPreviewWidget->SetDefaultPiece(); } diff --git a/common/lc_mainwindow.h b/common/lc_mainwindow.h index bead1aa3..f49e7d0f 100644 --- a/common/lc_mainwindow.h +++ b/common/lc_mainwindow.h @@ -7,6 +7,7 @@ #include "lc_model.h" class View; +class lcPartSelectionWidget; class PiecePreview; class lcQGLWidget; class lcQPartsTree; @@ -156,6 +157,11 @@ public: return mRelativeTransform; } + PieceInfo* lcMainWindow::GetCurrentPieceInfo() const + { + return mCurrentPieceInfo; + } + View* GetActiveView() const { lcModelTabWidget* CurrentTab = (lcModelTabWidget*)mModelTabWidget->currentWidget(); @@ -214,6 +220,7 @@ public: void SetLockY(bool LockY); void SetLockZ(bool LockZ); void SetRelativeTransform(bool RelativeTransform); + void SetCurrentPieceInfo(PieceInfo* Info); void NewProject(); bool OpenProject(const QString& FileName); @@ -313,6 +320,7 @@ protected: bool mLockY; bool mLockZ; bool mRelativeTransform; + PieceInfo* mCurrentPieceInfo; QAction* mActionFileRecentSeparator; @@ -320,10 +328,12 @@ protected: QToolBar* mStandardToolBar; QToolBar* mToolsToolBar; QToolBar* mTimeToolBar; + QDockWidget* mPartSelectionToolBar; QDockWidget* mPartsToolBar; QDockWidget* mPropertiesToolBar; QDockWidget* mTimelineToolBar; + lcPartSelectionWidget* mPartSelectionWidget; lcQGLWidget* mPiecePreviewWidget; lcQPartsTree* mPartsTree; QLineEdit* mPartSearchEdit; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index debc74ce..fbb6c998 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -164,7 +164,7 @@ lcModel::~lcModel() { if (mPieceInfo) { - if (gMainWindow && gMainWindow->mPreviewWidget->GetCurrentPiece() == mPieceInfo) + if (gMainWindow && gMainWindow->GetCurrentPieceInfo() == mPieceInfo) gMainWindow->mPreviewWidget->SetDefaultPiece(); if (mPieceInfo->GetModel() == this) @@ -1922,7 +1922,7 @@ lcMatrix33 lcModel::GetRelativeRotation() const void lcModel::AddPiece() { - PieceInfo* CurPiece = gMainWindow->mPreviewWidget->GetCurrentPiece(); + PieceInfo* CurPiece = gMainWindow->GetCurrentPieceInfo(); if (!CurPiece) return; @@ -3545,7 +3545,7 @@ void lcModel::EndMouseTool(lcTool Tool, bool Accept) void lcModel::InsertPieceToolClicked(const lcMatrix44& WorldMatrix) { - lcPiece* Piece = new lcPiece(gMainWindow->mPreviewWidget->GetCurrentPiece()); + lcPiece* Piece = new lcPiece(gMainWindow->GetCurrentPieceInfo()); Piece->Initialize(WorldMatrix, mCurrentStep); Piece->SetColorIndex(gMainWindow->mColorIndex); Piece->UpdatePosition(mCurrentStep); diff --git a/common/lc_partselectionwidget.cpp b/common/lc_partselectionwidget.cpp new file mode 100644 index 00000000..d6cff56c --- /dev/null +++ b/common/lc_partselectionwidget.cpp @@ -0,0 +1,283 @@ +#include "lc_global.h" +#include "lc_partselectionwidget.h" +#include "lc_application.h" +#include "lc_library.h" +#include "pieceinf.h" + +static const int gIconSize = 64; + +static int lcPartSortFunc(PieceInfo* const& a, PieceInfo* const& b) +{ + return strcmp(a->m_strDescription, b->m_strDescription); +} + +lcPartSelectionFilterModel::lcPartSelectionFilterModel(QObject* Parent) + : QSortFilterProxyModel(Parent) +{ +} + +void lcPartSelectionFilterModel::SetFilter(const QString& Filter) +{ + mFilter = Filter.toLatin1(); + invalidateFilter(); +} + +bool lcPartSelectionFilterModel::filterAcceptsRow(int SourceRow, const QModelIndex& SourceParent) const +{ + if (mFilter.isEmpty()) + return true; + + lcPartSelectionListModel* SourceModel = (lcPartSelectionListModel*)sourceModel(); + PieceInfo* Info = SourceModel->GetPieceInfo(SourceRow); + + return strstr(Info->m_strDescription, mFilter); +} + +void lcPartSelectionItemDelegate::paint(QPainter* Painter, const QStyleOptionViewItem& Option, const QModelIndex& Index) const +{ + mListModel->RequestPreview(mFilterModel->mapToSource(Index).row()); + QStyledItemDelegate::paint(Painter, Option, Index); +} + +QSize lcPartSelectionItemDelegate::sizeHint(const QStyleOptionViewItem& Option, const QModelIndex& Index) const +{ + return QStyledItemDelegate::sizeHint(Option, Index); +} + +lcPartSelectionListModel::lcPartSelectionListModel(QObject* Parent) + : QAbstractListModel(Parent) +{ +} + +lcPartSelectionListModel::~lcPartSelectionListModel() +{ +} + +void lcPartSelectionListModel::SetCategory(int CategoryIndex) +{ + beginResetModel(); + + lcPiecesLibrary* Library = lcGetPiecesLibrary(); + lcArray SingleParts, GroupedParts; + + Library->GetCategoryEntries(CategoryIndex, false, SingleParts, GroupedParts); + + SingleParts.Sort(lcPartSortFunc); + mParts.resize(SingleParts.GetSize()); + + for (int PartIdx = 0; PartIdx < SingleParts.GetSize(); PartIdx++) + mParts[PartIdx] = (QPair(SingleParts[PartIdx], QPixmap())); + + endResetModel(); +} + +int lcPartSelectionListModel::rowCount(const QModelIndex& Parent) const +{ + Q_UNUSED(Parent); + return mParts.size(); +} + +QVariant lcPartSelectionListModel::data(const QModelIndex& Index, int Role) const +{ + int InfoIndex = Index.row(); + + if (Index.isValid() && InfoIndex < mParts.size()) + { + if (Role == Qt::ToolTipRole) + return QVariant(QString::fromLatin1(mParts[InfoIndex].first->m_strDescription)); + else if (Role == Qt::DecorationRole) + { + if (!mParts[InfoIndex].second.isNull()) + return QVariant(mParts[InfoIndex].second); + else + return QVariant(QColor(0, 0, 0, 0)); + } + } + + return QVariant(); +} + +QVariant lcPartSelectionListModel::headerData(int Section, Qt::Orientation Orientation, int Role) const +{ + Q_UNUSED(Section); + Q_UNUSED(Orientation); + return Role == Qt::DisplayRole ? QVariant(QStringLiteral("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; +} + + +#include "lc_mainwindow.h" +#include "preview.h" + +void lcPartSelectionListModel::RequestPreview(int InfoIndex) +{ + if (mParts[InfoIndex].second.isNull()) + { + gMainWindow->mPreviewWidget->MakeCurrent(); + lcContext* Context = gMainWindow->mPreviewWidget->mContext; + int Width = gIconSize; + int Height = gIconSize; + + if (!Context->BeginRenderToTexture(Width, Height)) + return; + + float aspect = (float)Width / (float)Height; + Context->SetViewport(0, 0, Width, Height); + + lcMatrix44 ProjectionMatrix = lcMatrix44Perspective(30.0f, aspect, 1.0f, 2500.0f); + lcMatrix44 ViewMatrix; + + Context->SetDefaultState(); + Context->SetProjectionMatrix(ProjectionMatrix); + Context->SetProgram(LC_PROGRAM_SIMPLE); + + PieceInfo* Info = mParts[InfoIndex].first; + Info->AddRef(); + + glClearColor(1.0f, 1.0f, 1.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + lcVector3 CameraPosition(-100.0f, -100.0f, 75.0f); + Info->ZoomExtents(ProjectionMatrix, ViewMatrix, CameraPosition); + + lcScene Scene; + Scene.Begin(ViewMatrix); + + Info->AddRenderMeshes(Scene, lcMatrix44Identity(), gDefaultColor, false, false); + + Scene.End(); + + Context->SetViewMatrix(ViewMatrix); + Context->DrawOpaqueMeshes(Scene.mOpaqueMeshes); + Context->DrawTranslucentMeshes(Scene.mTranslucentMeshes); + + Context->UnbindMesh(); // context remove + + Info->Release(); + + mParts[InfoIndex].second = QPixmap::fromImage(Context->GetRenderToTextureImage(Width, Height)); + + Context->EndRenderToTexture(); + + emit dataChanged(index(InfoIndex, 0), index(InfoIndex, 0), QVector() << Qt::DecorationRole); + } +} + +lcPartSelectionListView::lcPartSelectionListView(QWidget* Parent) + : QListView(Parent) +{ + setUniformItemSizes(true); + setViewMode(QListView::IconMode); + setIconSize(QSize(gIconSize, gIconSize)); + setResizeMode(QListView::Adjust); + setDragEnabled(true); + + mListModel = new lcPartSelectionListModel(this); + mFilterModel = new lcPartSelectionFilterModel(this); + mFilterModel->setSourceModel(mListModel); + setModel(mFilterModel); + lcPartSelectionItemDelegate* ItemDelegate = new lcPartSelectionItemDelegate(this, mListModel, mFilterModel); + setItemDelegate(ItemDelegate); +} + +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->m_strName); + + 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); + + mCategoriesWidget = new QTreeWidget(mSplitter); + mCategoriesWidget->setHeaderHidden(true); + mCategoriesWidget->setUniformRowHeights(true); + mCategoriesWidget->setRootIsDecorated(false); + + for (int CategoryIdx = 0; CategoryIdx < gCategories.GetSize(); CategoryIdx++) + { + QTreeWidgetItem* CategoryItem = new QTreeWidgetItem(mCategoriesWidget, QStringList((const char*)gCategories[CategoryIdx].Name)); +// CategoryItem->setCheckState(0, Qt::Unchecked); + } + + QWidget* PartsGroupWidget = new QWidget(mSplitter); + + QVBoxLayout* PartsLayout = new QVBoxLayout(); + PartsLayout->setContentsMargins(0, 0, 0, 0); + PartsGroupWidget->setLayout(PartsLayout); + + mFilterWidget = new QLineEdit(PartsGroupWidget); + mFilterWidget->setPlaceholderText(tr("Search Parts")); + mFilterWidget->addAction(QIcon(":/resources/parts_search.png"), QLineEdit::TrailingPosition); + PartsLayout->addWidget(mFilterWidget); + + mPartsWidget = new lcPartSelectionListView(PartsGroupWidget); + PartsLayout->addWidget(mPartsWidget); + + QHBoxLayout* Layout = new QHBoxLayout(this); + Layout->setContentsMargins(0, 0, 0, 0); + Layout->addWidget(mSplitter); + setLayout(Layout); + + connect(mPartsWidget->selectionModel(), &QItemSelectionModel::currentChanged, this, &lcPartSelectionWidget::PartChanged); + connect(mFilterWidget, &QLineEdit::textEdited, this, &lcPartSelectionWidget::FilterChanged); + connect(mCategoriesWidget, &QTreeWidget::currentItemChanged, this, &lcPartSelectionWidget::CategoryChanged); +} + +lcPartSelectionWidget::~lcPartSelectionWidget() +{ +} + +void lcPartSelectionWidget::resizeEvent(QResizeEvent* Event) +{ + if (width() > height()) + mSplitter->setOrientation(Qt::Horizontal); + else + mSplitter->setOrientation(Qt::Vertical); + + QWidget::resizeEvent(Event); +} + +void lcPartSelectionWidget::FilterChanged(const QString& Text) +{ + mPartsWidget->GetFilterModel()->SetFilter(Text); +} + +void lcPartSelectionWidget::CategoryChanged(QTreeWidgetItem* Current, QTreeWidgetItem* Previous) +{ + Q_UNUSED(Previous); + mPartsWidget->GetListModel()->SetCategory(mCategoriesWidget->indexOfTopLevelItem(Current)); + mPartsWidget->setCurrentIndex(mPartsWidget->GetFilterModel()->index(0, 0)); +} + +void lcPartSelectionWidget::PartChanged(const QModelIndex& Current, const QModelIndex& Previous) +{ + gMainWindow->SetCurrentPieceInfo(mPartsWidget->GetCurrentPart()); +} \ No newline at end of file diff --git a/common/lc_partselectionwidget.h b/common/lc_partselectionwidget.h new file mode 100644 index 00000000..6e6469c6 --- /dev/null +++ b/common/lc_partselectionwidget.h @@ -0,0 +1,122 @@ +#ifndef _LC_PARTSELECTIONWIDGET_H_ +#define _LC_PARTSELECTIONWIDGET_H_ + +class lcPartSelectionListModel; + +class lcPartSelectionFilterModel : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + lcPartSelectionFilterModel(QObject* Parent); + + void SetFilter(const QString& Filter); + +protected: + virtual bool filterAcceptsRow(int SourceRow, const QModelIndex& SourceParent) const; + + QByteArray mFilter; +}; + +class lcPartSelectionItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + lcPartSelectionItemDelegate(QObject* Parent, lcPartSelectionListModel* ListModel, lcPartSelectionFilterModel* FilterModel) + : QStyledItemDelegate(Parent), mListModel(ListModel), mFilterModel(FilterModel) + { + } + + virtual void paint(QPainter* Painter, const QStyleOptionViewItem& Option, const QModelIndex& Index) const; + virtual QSize sizeHint(const QStyleOptionViewItem& Option, const QModelIndex& Index) const; + +protected: + lcPartSelectionListModel* mListModel; + lcPartSelectionFilterModel* mFilterModel; +}; + +class lcPartSelectionListModel : public QAbstractListModel +{ + Q_OBJECT + +public: + lcPartSelectionListModel(QObject* Parent); + ~lcPartSelectionListModel(); + + virtual int rowCount(const QModelIndex& Parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex& Index, int Role = Qt::DisplayRole) const; + virtual QVariant headerData(int Section, Qt::Orientation Orientation, int Role = Qt::DisplayRole) const; + virtual Qt::ItemFlags flags(const QModelIndex& Index) const; + + PieceInfo* GetPieceInfo(QModelIndex Index) const + { + return Index.isValid() ? mParts[Index.row()].first : NULL; + } + + PieceInfo* GetPieceInfo(int Row) const + { + return mParts[Row].first; + } + + void SetCategory(int CategoryIndex); + void RequestPreview(int InfoIndex); + +protected: + QVector> mParts; +}; + +class lcPartSelectionListView : public QListView +{ + Q_OBJECT + +public: + lcPartSelectionListView(QWidget* Parent); + + virtual void startDrag(Qt::DropActions SupportedActions); + + PieceInfo* GetCurrentPart() const + { + return mListModel->GetPieceInfo(mFilterModel->mapToSource(currentIndex())); + } + + lcPartSelectionListModel* GetListModel() const + { + return mListModel; + } + + lcPartSelectionFilterModel* GetFilterModel() const + { + return mFilterModel; + } + +protected: + lcPartSelectionListModel* mListModel; + lcPartSelectionFilterModel* mFilterModel; + +// QSize sizeHint() const; +}; + +class lcPartSelectionWidget : public QWidget +{ + Q_OBJECT + +public: + lcPartSelectionWidget(QWidget* Parent); + ~lcPartSelectionWidget(); + +protected slots: + void FilterChanged(const QString& Text); + void CategoryChanged(QTreeWidgetItem* Current, QTreeWidgetItem* Previous); + void PartChanged(const QModelIndex& Current, const QModelIndex& Previous); + +protected: + virtual void resizeEvent(QResizeEvent* Event); + + QTreeWidget* mCategoriesWidget; + QLineEdit* mFilterWidget; + lcPartSelectionListView* mPartsWidget; + QSplitter* mSplitter; +}; + +#endif // _LC_PARTSELECTIONWIDGET_H_ diff --git a/common/preview.cpp b/common/preview.cpp index c315ec97..9acf4f96 100644 --- a/common/preview.cpp +++ b/common/preview.cpp @@ -9,7 +9,6 @@ PiecePreview::PiecePreview() { - m_PieceInfo = NULL; m_RotateX = 60.0f; m_RotateZ = 225.0f; m_Distance = 10.0f; @@ -19,13 +18,13 @@ PiecePreview::PiecePreview() PiecePreview::~PiecePreview() { - if (m_PieceInfo) - m_PieceInfo->Release(); } void PiecePreview::OnDraw() { - if (m_PieceInfo == NULL) + PieceInfo* Info = gMainWindow->GetCurrentPieceInfo(); + + if (Info == NULL) return; mContext->SetDefaultState(); @@ -45,13 +44,13 @@ void PiecePreview::OnDraw() lcMatrix44 ProjectionMatrix = lcMatrix44Perspective(30.0f, aspect, 1.0f, 2500.0f); lcMatrix44 ViewMatrix; - const lcBoundingBox& BoundingBox = m_PieceInfo->GetBoundingBox(); + const lcBoundingBox& BoundingBox = Info->GetBoundingBox(); lcVector3 Center = (BoundingBox.Min + BoundingBox.Max) / 2.0f; if (m_AutoZoom) { Eye = Eye * 100.0f; - m_PieceInfo->ZoomExtents(ProjectionMatrix, ViewMatrix, Eye); + Info->ZoomExtents(ProjectionMatrix, ViewMatrix, Eye); // Update the new camera distance. lcVector3 d = Eye - Center; @@ -69,7 +68,7 @@ void PiecePreview::OnDraw() lcScene Scene; Scene.Begin(ViewMatrix); - m_PieceInfo->AddRenderMeshes(Scene, lcMatrix44Identity(), gMainWindow->mColorIndex, false, false); + Info->AddRenderMeshes(Scene, lcMatrix44Identity(), gMainWindow->mColorIndex, false, false); Scene.End(); @@ -81,6 +80,7 @@ void PiecePreview::OnDraw() void PiecePreview::SetCurrentPiece(PieceInfo *pInfo) { + /* MakeCurrent(); if (m_PieceInfo != NULL) @@ -93,6 +93,7 @@ void PiecePreview::SetCurrentPiece(PieceInfo *pInfo) m_PieceInfo->AddRef(); Redraw(); } + */ } void PiecePreview::SetDefaultPiece() diff --git a/common/preview.h b/common/preview.h index a799049d..9e6cba2a 100644 --- a/common/preview.h +++ b/common/preview.h @@ -19,17 +19,10 @@ public: void OnRightButtonUp(); void OnMouseMove(); - PieceInfo* GetCurrentPiece() const - { - return m_PieceInfo; - } - void SetCurrentPiece(PieceInfo* Info); void SetDefaultPiece(); protected: - PieceInfo* m_PieceInfo; - // Mouse tracking. int m_Tracking; int m_DownX; diff --git a/common/view.cpp b/common/view.cpp index a57c293f..4d526600 100644 --- a/common/view.cpp +++ b/common/view.cpp @@ -7,7 +7,6 @@ #include "tr.h" #include "texfont.h" #include "lc_texture.h" -#include "preview.h" #include "piece.h" #include "pieceinf.h" #include "lc_synth.h" @@ -419,7 +418,7 @@ lcVector3 View::GetMoveDirection(const lcVector3& Direction) const lcMatrix44 View::GetPieceInsertPosition() const { - PieceInfo* CurPiece = gMainWindow->mPreviewWidget->GetCurrentPiece(); + PieceInfo* CurPiece = gMainWindow->GetCurrentPieceInfo(); lcPiece* HitPiece = (lcPiece*)FindObjectUnderPointer(true).Object; if (HitPiece) @@ -554,7 +553,7 @@ void View::OnDraw() if (DrawInterface && mTrackTool == LC_TRACKTOOL_INSERT) { - PieceInfo* Info = gMainWindow->mPreviewWidget->GetCurrentPiece(); + PieceInfo* Info = gMainWindow->GetCurrentPieceInfo(); if (Info) Info->AddRenderMeshes(mScene, GetPieceInsertPosition(), gMainWindow->mColorIndex, true, true); @@ -1307,7 +1306,7 @@ void View::DrawGrid() if (mTrackTool == LC_TRACKTOOL_INSERT) { - PieceInfo* CurPiece = gMainWindow->mPreviewWidget->GetCurrentPiece(); + PieceInfo* CurPiece = gMainWindow->GetCurrentPieceInfo(); if (CurPiece) { @@ -2380,7 +2379,7 @@ void View::OnButtonDown(lcTrackButton TrackButton) case LC_TRACKTOOL_INSERT: { - PieceInfo* CurPiece = gMainWindow->mPreviewWidget->GetCurrentPiece(); + PieceInfo* CurPiece = gMainWindow->GetCurrentPieceInfo(); if (!CurPiece) break; diff --git a/leocad.pro b/leocad.pro index a3bd691c..f1bcc053 100644 --- a/leocad.pro +++ b/leocad.pro @@ -173,6 +173,7 @@ SOURCES += common/view.cpp \ qt/lc_qcolorlist.cpp \ qt/lc_qfinddialog.cpp \ qt/lc_qmodellistdialog.cpp \ + common/lc_partselectionwidget.cpp \ common/lc_timelinewidget.cpp HEADERS += \ common/view.h \ @@ -234,6 +235,7 @@ HEADERS += \ qt/lc_qcolorlist.h \ qt/lc_qfinddialog.h \ qt/lc_qmodellistdialog.h \ + common/lc_partselectionwidget.h \ common/lc_timelinewidget.h FORMS += \ qt/lc_qpovraydialog.ui \ diff --git a/leocad.qrc b/leocad.qrc index 2a914ca4..623d53ab 100644 --- a/leocad.qrc +++ b/leocad.qrc @@ -88,6 +88,7 @@ resources/piece_show_earlier.png resources/piece_show_later.png resources/time_add_keys.png + resources/parts_search.png resources/library.zip resources/minifig.ini resources/leocad_fr.qm diff --git a/resources/parts_search.png b/resources/parts_search.png new file mode 100644 index 0000000000000000000000000000000000000000..9cbc3618f5ad94df90ca1cc1d726a76c87687874 GIT binary patch literal 1912 zcmV-;2Z#8HP)RhC_%=of2~iV`G2#OyRH72DiQe4g{&Ce1iA4XnF?W*F$L##h`JC_X{LY!>48y?x^Wv`d z+4}Yk3+d(?}b7ky!ZZQjEx2F{nw_A+cSlj0Jv-U-9^nUt^OxhuR?x) z0m9=kJiB=h&W1JQ7nQ)BTLeMmV6$-q!b1*?;Ns9Z%y4q}@9L#+=VT!m9K{Elx1hJ@ zTTkcCFGn%~5Uk%~!@T)DOIn-F;A0UP5B~crIP%KSx}Y3OYFwx)ln{z*7*FV?4F;V! zQ!yQ92G8MvcXr~lHFuh8nGac(dkCPO{3fRYurU=LeeCf%uh;wf1NYy@1jaKT_90;} z!gI@R#636VL8PolV=BUmhDd@Sk~+ZCLY{}1;|3?#(RJuF+7?uzq@)zzA3f$NEb@GI z;)mn@sQ`GULU~2Srp1dEQfv*okDbK@nZwOB<(OOQ#E6{4sG^!dqnd#j#a2u+pinK? z?Hnq+r5H6tbR9iw`e448&q)ej6~H0bY`0aEmC<4qT|fHa%JraimK#BqHD#=*6pVt$ zsjL#rs2Jm9y1)|vnaHEkTZXQal(43P`C>kq?@RzBs%poy;$ni=aB^6IBP$zK1#Hh% zL@9WTg0rmSlY+;o5VIs30oWiCK=JefS{oxDDokJGllji12zf)-q0vJ60ZDS0l^&*o zlM|`nEU+0IDS#xM9fyNY9ZA{>UDKgz9KkrC(H1ZW=F>`W>QlhxfzB4tVo|h{e4JTq zvZ|Yzr)5uPFG)Ojo7EEtP*pjW2CWrM6?INWrZZ-uNZ1067TYKb>hqMnj+mN~J{6eG z6y+n4+#<;?2q}Q1s$1{2#c@M%mg$4}Vm>nk(4*tyeZDh;AT_b5R0L-e2tdK`coG4U zAWVC}Up6%iOEpHz6dMjCu(-@l0KmZDAms7LK2w$q01~H8{j{aO{}2q$h6ay;>28Vk z-v+;|(h<~2U?Wv*X2BUqQcp-wZ%9y~YV`T<7Ztb&VxEU0(&^Z@?*P8-?tU8?sK5Y} zu5Z5HAMghT4jwuT)!^}XO`Igoh6<7DLN}{iqrfZ}3!bFA<$`ASvdx`#9?S8fX~0^KwH}i?#9{m&wstE^DSDTO$ER%Eh@{&Y-je6 z-ygW$J98%T2x6`)3>QtnsP4pY+>K}=3z3)uLD`OcL&XAj7nCWK zdoymmbt$r(E>zbwtlzzB`=+Zwq>mw+T7g}=IyBx|}HLoMFmZ zpETmBDrm1cUVtG;IDF(gba(gQ`s-_{jk_R6W2mmFg$IYx^zP#LEo%<2j+mJ8g@i1d zYivE{emi#_M~)nU5>M!*Wu-iOi4m!j z@`4k~TIL|n{u^*=E&BEXO)qp`5rVtI|Ez}>lFgVktG2eWspTn`%Qc_%^~nIN!XuH$ z;qE=V-}CtfMqgRGuCu(V3WAi2o227dZ2uT&`4rSF2;v2T(60#bXK%%#r3QO1D?412jAkAq!fyblr<;--8$!r z_3SjVs%>xF)?4d7kBU5#P0d-Y2V#^JY0?8u!2}jOX<|JlAfSH>i&bqRtbe}`~LK(=5g(=35bWn;Om`>=suej!G989GDHbk yPWo#l*?CK)#6Jy?hRC*hOS0a=M00RJDa7Sg}Qvxjj0000