diff --git a/common/lc_library.cpp b/common/lc_library.cpp index b0d58e45..37ecbe06 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -164,8 +164,15 @@ PieceInfo* lcPiecesLibrary::FindPiece(const char* PieceName, Project* CurrentPro if (PieceIt != mPieces.end()) { PieceInfo* Info = PieceIt->second; + bool HasModel = false; - if ((!CurrentProject || !Info->IsModel() || CurrentProject->GetModels().FindIndex(Info->GetModel()) != -1) && (!ProjectPath.isEmpty() || !Info->IsProject() || Info->IsProjectPiece())) + if (lcGetActiveProject()) + { + const std::vector>& Models = lcGetActiveProject()->GetModels(); + HasModel = std::find_if(Models.begin(), Models.end(), [Model = Info->GetModel()](const std::unique_ptr& CheckModel) { return CheckModel.get() == Model; }) != Models.end(); + } + + if ((!CurrentProject || !Info->IsModel() || HasModel) && (!ProjectPath.isEmpty() || !Info->IsProject() || Info->IsProjectPiece())) return Info; } diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index 877a1d60..fbfdcdd2 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -1070,7 +1070,7 @@ void lcMainWindow::ModelTabChanged(int Index) Project* Project = lcGetActiveProject(); lcModelTabWidget* CurrentTab = (lcModelTabWidget*)mModelTabWidget->widget(Index); - Project->SetActiveModel(Project->GetModels().FindIndex(CurrentTab ? CurrentTab->GetModel() : nullptr)); + Project->SetActiveModel(CurrentTab ? CurrentTab->GetModel() : nullptr); } void lcMainWindow::ClipboardChanged() @@ -2234,24 +2234,29 @@ void lcMainWindow::UpdateSelectionMode() void lcMainWindow::UpdateModels() { - const lcArray& Models = lcGetActiveProject()->GetModels(); + const std::vector>& Models = lcGetActiveProject()->GetModels(); lcModel* CurrentModel = lcGetActiveModel(); - for (int ActionIdx = LC_MODEL_FIRST; ActionIdx <= LC_MODEL_LAST; ActionIdx++) + for (size_t ActionIndex = LC_MODEL_FIRST; ActionIndex <= LC_MODEL_LAST; ActionIndex++) { - QAction* Action = mActions[ActionIdx]; - int ModelIdx = ActionIdx - LC_MODEL_FIRST; + QAction* Action = mActions[ActionIndex]; + size_t ModelIndex = ActionIndex - LC_MODEL_FIRST; - if (ModelIdx < Models.size()) + if (ModelIndex < Models.size()) { - Action->setChecked(CurrentModel == Models[ModelIdx]); - Action->setText(QString::fromLatin1("%1%2 %3").arg(ModelIdx < 9 ? QString("&") : QString(), QString::number(ModelIdx + 1), Models[ModelIdx]->GetProperties().mFileName)); + Action->setChecked(CurrentModel == Models[ModelIndex].get()); + Action->setText(QString::fromLatin1("%1%2 %3").arg(ModelIndex < 9 ? QString("&") : QString(), QString::number(ModelIndex + 1), Models[ModelIndex]->GetProperties().mFileName)); Action->setVisible(true); } else Action->setVisible(false); } + auto HasModel = [&Models](lcModel* Model) + { + return std::find_if(Models.begin(), Models.end(), [Model](const std::unique_ptr& CheckModel) { return CheckModel.get() == Model; }) != Models.end(); + }; + for (int TabIdx = 0; TabIdx < mModelTabWidget->count(); ) { lcModelTabWidget* TabWidget = (lcModelTabWidget*)mModelTabWidget->widget(TabIdx); @@ -2259,7 +2264,7 @@ void lcMainWindow::UpdateModels() if (!Model) TabIdx++; - else if (Models.FindIndex(Model) != -1) + else if (HasModel(Model)) { mModelTabWidget->setTabText(TabIdx, Model->GetProperties().mFileName); TabIdx++; @@ -2271,7 +2276,7 @@ void lcMainWindow::UpdateModels() mPartSelectionWidget->UpdateModels(); if (mCurrentPieceInfo && mCurrentPieceInfo->IsModel()) - if (Models.FindIndex(mCurrentPieceInfo->GetModel()) == -1) + if (!HasModel(mCurrentPieceInfo->GetModel())) SetCurrentPieceInfo(nullptr); } @@ -2395,14 +2400,14 @@ void lcMainWindow::MergeProject() if (NewProject->Load(LoadFileName, true)) { - int NumModels = NewProject->GetModels().size(); + size_t ModelCount = NewProject->GetModels().size(); lcGetActiveProject()->Merge(NewProject); - if (NumModels == 1) + if (ModelCount == 1) QMessageBox::information(this, tr("LeoCAD"), tr("Merged 1 submodel.")); else - QMessageBox::information(this, tr("LeoCAD"), tr("Merged %1 submodels.").arg(NumModels)); + QMessageBox::information(this, tr("LeoCAD"), tr("Merged %1 submodels.").arg(ModelCount)); UpdateModels(); } @@ -2522,7 +2527,7 @@ bool lcMainWindow::SetModelFromFocus() if (Model) { Project* Project = lcGetActiveProject(); - Project->SetActiveModel(Project->GetModels().FindIndex(Model)); + Project->SetActiveModel(Model); return true; } @@ -2539,7 +2544,7 @@ void lcMainWindow::SetModelFromSelection() if (Model) { Project* Project = lcGetActiveProject(); - Project->SetActiveModel(Project->GetModels().FindIndex(Model)); + Project->SetActiveModel(Model); } } diff --git a/common/lc_model.cpp b/common/lc_model.cpp index a3a1b32b..4256dd13 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3250,15 +3250,15 @@ lcModel* lcModel::GetFirstSelectedSubmodel() const return nullptr; } -void lcModel::GetSubModels(lcArray& SubModels) const +void lcModel::GetSubModels(std::set& SubModels) const { for (const lcPiece* Piece : mPieces) { if (Piece->mPieceInfo->IsModel()) { lcModel* SubModel = Piece->mPieceInfo->GetModel(); - if (SubModels.FindIndex(SubModel) == -1) - SubModels.emplace_back(SubModel); + + SubModels.insert(SubModel); } } } diff --git a/common/lc_model.h b/common/lc_model.h index 5b10fbce..17ed5875 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -281,7 +281,7 @@ public: bool AnyPiecesSelected() const; bool AnyObjectsSelected() const; lcModel* GetFirstSelectedSubmodel() const; - void GetSubModels(lcArray& SubModels) const; + void GetSubModels(std::set& SubModels) const; bool GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRotation) const; bool CanRotateSelection() const; bool GetPieceFocusOrSelectionCenter(lcVector3& Center) const; diff --git a/common/lc_modellistdialog.cpp b/common/lc_modellistdialog.cpp index 39b60e2e..650019ad 100644 --- a/common/lc_modellistdialog.cpp +++ b/common/lc_modellistdialog.cpp @@ -11,21 +11,28 @@ enum class lcModelListRole DuplicateModel }; -lcModelListDialog::lcModelListDialog(QWidget* Parent, const lcArray Models) +lcModelListDialog::lcModelListDialog(QWidget* Parent, const std::vector>& Models) : QDialog(Parent), ui(new Ui::lcModelListDialog) { mActiveModelItem = nullptr; ui->setupUi(this); - for (const lcModel* Model : Models) + lcModel* ActiveModel = lcGetActiveProject()->GetActiveModel(); + int ActiveModelIndex = -1; + + for (const std::unique_ptr& Model : Models) { QListWidgetItem* Item = new QListWidgetItem(Model->GetProperties().mFileName); - Item->setData(static_cast(lcModelListRole::ExistingModel), QVariant::fromValue((uintptr_t)Model)); + Item->setData(static_cast(lcModelListRole::ExistingModel), QVariant::fromValue((uintptr_t)Model.get())); ui->ModelList->addItem(Item); + + if (Model.get() == ActiveModel ) + ActiveModelIndex = ui->ModelList->count() - 1; } - ui->ModelList->setCurrentRow(lcGetActiveProject()->GetActiveModelIndex()); + if (ActiveModelIndex != -1) + ui->ModelList->setCurrentRow(ActiveModelIndex); QSettings Settings; ui->SetActiveModel->setChecked(Settings.value("Settings/ModelListSetActive", true).toBool()); diff --git a/common/lc_modellistdialog.h b/common/lc_modellistdialog.h index 1055f3ba..ec2b91cc 100644 --- a/common/lc_modellistdialog.h +++ b/common/lc_modellistdialog.h @@ -19,7 +19,7 @@ class lcModelListDialog : public QDialog Q_OBJECT public: - lcModelListDialog(QWidget* Parent, const lcArray Models); + lcModelListDialog(QWidget* Parent, const std::vector>& Models); ~lcModelListDialog(); int GetActiveModelIndex() const; diff --git a/common/lc_partselectionwidget.cpp b/common/lc_partselectionwidget.cpp index ef27cca0..6200354a 100644 --- a/common/lc_partselectionwidget.cpp +++ b/common/lc_partselectionwidget.cpp @@ -176,16 +176,12 @@ void lcPartSelectionListModel::SetModelsCategory() mParts.clear(); - const lcArray& Models = lcGetActiveProject()->GetModels(); + const std::vector>& Models = lcGetActiveProject()->GetModels(); lcModel* ActiveModel = gMainWindow->GetActiveModel(); - for (int ModelIdx = 0; ModelIdx < Models.size(); ModelIdx++) - { - lcModel* Model = Models[ModelIdx]; - + for (const std::unique_ptr& Model : Models) if (!Model->IncludesModel(ActiveModel)) mParts.emplace_back(std::pair(Model->GetPieceInfo(), QPixmap())); - } auto lcPartSortFunc = [](const std::pair& a, const std::pair& b) { diff --git a/common/project.cpp b/common/project.cpp index 32cff332..504d4f07 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -78,14 +78,13 @@ Project::Project(bool IsPreview) Project::~Project() { - mModels.DeleteAll(); } lcModel* Project::GetModel(const QString& FileName) const { - for (lcModel* Model : mModels) + for (const std::unique_ptr& Model : mModels) if (Model->GetProperties().mFileName == FileName) - return Model; + return Model.get(); return nullptr; } @@ -95,8 +94,8 @@ bool Project::IsModified() const if (mModified) return true; - for (int ModelIdx = 0; ModelIdx < mModels.size(); ModelIdx++) - if (mModels[ModelIdx]->IsModified()) + for (const std::unique_ptr& Model : mModels) + if (Model->IsModified()) return true; return false; @@ -135,21 +134,21 @@ QString Project::GetImageFileName(bool AllowCurrentFolder) const return QDir::toNativeSeparators(FileName) + lcGetProfileString(LC_PROFILE_IMAGE_EXTENSION); } -void Project::SetActiveModel(int ModelIndex) +void Project::SetActiveModel(lcModel* ActiveModel) { - if (ModelIndex < 0 || ModelIndex >= mModels.size()) + if (!ActiveModel) return; - for (int ModelIdx = 0; ModelIdx < mModels.size(); ModelIdx++) - mModels[ModelIdx]->SetActive(ModelIdx == ModelIndex); + for (const std::unique_ptr &Model : mModels) + Model->SetActive(Model.get() == ActiveModel); std::vector UpdatedModels; UpdatedModels.reserve(mModels.size()); - for (int ModelIdx = 0; ModelIdx < mModels.size(); ModelIdx++) - mModels[ModelIdx]->UpdatePieceInfo(UpdatedModels); + for (const std::unique_ptr &Model : mModels) + Model->UpdatePieceInfo(UpdatedModels); - mActiveModel = mModels[ModelIndex]; + mActiveModel = ActiveModel; if (!mIsPreview && gMainWindow) { @@ -158,13 +157,21 @@ void Project::SetActiveModel(int ModelIndex) } } +void Project::SetActiveModel(int ModelIndex) +{ + if (ModelIndex < 0 || ModelIndex >= static_cast(mModels.size())) + return; + + SetActiveModel(mModels[ModelIndex].get()); +} + void Project::SetActiveModel(const QString& FileName) { - for (int ModelIdx = 0; ModelIdx < mModels.size(); ModelIdx++) + for (const std::unique_ptr& Model : mModels) { - if (FileName.compare(mModels[ModelIdx]->GetFileName(), Qt::CaseInsensitive) == 0) + if (FileName.compare(Model->GetFileName(), Qt::CaseInsensitive) == 0) { - SetActiveModel(ModelIdx); + SetActiveModel(Model.get()); return; } } @@ -241,8 +248,8 @@ lcModel* Project::CreateNewModel(bool ShowModel) { QStringList ModelNames; - for (int ModelIdx = 0; ModelIdx < mModels.size(); ModelIdx++) - ModelNames.append(mModels[ModelIdx]->GetProperties().mFileName); + for (const std::unique_ptr &Model : mModels) + ModelNames.append(Model->GetProperties().mFileName); QString Name = GetNewModelName(gMainWindow, tr("New Submodel"), QString(), ModelNames); @@ -257,7 +264,7 @@ lcModel* Project::CreateNewModel(bool ShowModel) if (ShowModel) { - SetActiveModel(mModels.size() - 1); + SetActiveModel(mModels.back().get()); lcView* ActiveView = gMainWindow ? gMainWindow->GetActiveView() : nullptr; if (ActiveView) @@ -266,7 +273,7 @@ lcModel* Project::CreateNewModel(bool ShowModel) gMainWindow->UpdateTitle(); } else - SetActiveModel(mModels.FindIndex(mActiveModel)); + SetActiveModel(mActiveModel); return Model; } @@ -278,7 +285,7 @@ void Project::ShowModelListDialog() if (Dialog.exec() != QDialog::Accepted) return; - lcArray NewModels; + std::vector> NewModels; std::vector Results = Dialog.GetResults(); for (const lcModelListDialogEntry& Entry : Results) @@ -321,7 +328,7 @@ void Project::ShowModelListDialog() Model->SetFileName(Entry.Name); lcGetPiecesLibrary()->RenamePiece(Model->GetPieceInfo(), Entry.Name.toLatin1().constData()); - for (lcModel* CheckModel : mModels) + for (const std::unique_ptr &CheckModel : mModels) CheckModel->RenamePiece(Model->GetPieceInfo()); mModified = true; @@ -330,18 +337,15 @@ void Project::ShowModelListDialog() NewModels.emplace_back(Model); } - for (int ModelIdx = 0; ModelIdx < mModels.size(); ModelIdx++) + for (std::unique_ptr& Model : mModels) { - lcModel* Model = mModels[ModelIdx]; - - if (NewModels.FindIndex(Model) == -1) - { - delete Model; + if (std::find(NewModels.begin(), NewModels.end(), Model) != NewModels.end()) + Model.release(); + else mModified = true; - } } - mModels = NewModels; + mModels = std::move(NewModels); gMainWindow->UpdateTitle(); gMainWindow->UpdateModels(); @@ -380,7 +384,7 @@ bool Project::Load(const QString& FileName, bool ShowErrors) return false; } - mModels.DeleteAll(); + mModels.clear(); SetFileName(FileName); QFileInfo FileInfo(FileName); QString Extension = FileInfo.suffix().toLower(); @@ -461,7 +465,7 @@ bool Project::Load(const QString& FileName, bool ShowErrors) if (mModels.size() == 1) { - lcModel* Model = mModels[0]; + lcModel* Model = mModels.front().get(); if (Model->GetProperties().mFileName.isEmpty()) { @@ -473,7 +477,7 @@ bool Project::Load(const QString& FileName, bool ShowErrors) std::vector UpdatedModels; UpdatedModels.reserve(mModels.size()); - for (lcModel* Model : mModels) + for (const std::unique_ptr& Model : mModels) { Model->UpdateMesh(); Model->UpdatePieceInfo(UpdatedModels); @@ -513,7 +517,7 @@ bool Project::Save(QTextStream& Stream) { bool MPD = mModels.size() > 1; - for (lcModel* Model : mModels) + for (const std::unique_ptr& Model : mModels) { if (MPD) Stream << QLatin1String("0 FILE ") << Model->GetProperties().mFileName << QLatin1String("\r\n"); @@ -530,7 +534,7 @@ bool Project::Save(QTextStream& Stream) void Project::Merge(Project* Other) { - for (lcModel* Model : Other->mModels) + for (std::unique_ptr& Model : Other->mModels) { QString FileName = Model->GetProperties().mFileName; @@ -538,9 +542,9 @@ void Project::Merge(Project* Other) { bool Duplicate = false; - for (int SearchIdx = 0; SearchIdx < mModels.size(); SearchIdx++) + for (const std::unique_ptr& ExistingModel : mModels) { - if (mModels[SearchIdx]->GetProperties().mFileName == FileName) + if (ExistingModel->GetProperties().mFileName == FileName) { Duplicate = true; break; @@ -554,10 +558,10 @@ void Project::Merge(Project* Other) Model->SetFileName(FileName); } - mModels.emplace_back(Model); + mModels.emplace_back(std::move(Model)); } - Other->mModels.RemoveAll(); + Other->mModels.clear(); mModified = true; } @@ -572,29 +576,25 @@ bool Project::ImportLDD(const QString& FileName) if (!ZipFile.ExtractFile("IMAGE100.LXFML", XMLFile)) return false; - mModels.DeleteAll(); QString ModelName = QFileInfo(FileName).completeBaseName(); - lcModel* Model = new lcModel(ModelName, this, false); + std::unique_ptr NewModel(new lcModel(ModelName, this, false)); - if (Model->LoadLDD(QString::fromUtf8((const char*)XMLFile.mBuffer))) - { - mModels.emplace_back(Model); - Model->SetSaved(); - } - else - { - delete Model; + if (!NewModel->LoadLDD(QString::fromUtf8((const char*)XMLFile.mBuffer))) return false; - } - for (int ModelIdx = 0; ModelIdx < mModels.size(); ModelIdx++) - mModels[ModelIdx]->CreatePieceInfo(this); + NewModel->SetSaved(); + + mModels.clear(); + mModels.emplace_back(std::move(NewModel)); + + for (const std::unique_ptr& Model : mModels) + Model->CreatePieceInfo(this); std::vector UpdatedModels; UpdatedModels.reserve(mModels.size()); - for (int ModelIdx = 0; ModelIdx < mModels.size(); ModelIdx++) - mModels[ModelIdx]->UpdatePieceInfo(UpdatedModels); + for (const std::unique_ptr& Model : mModels) + Model->UpdatePieceInfo(UpdatedModels); mModified = false; @@ -606,30 +606,25 @@ bool Project::ImportInventory(const QByteArray& Inventory, const QString& Name, if (Inventory.isEmpty()) return false; - mModels.DeleteAll(); - lcModel* Model = new lcModel(Name, this, false); + std::unique_ptr NewModel(new lcModel(Name, this, false)); - if (Model->LoadInventory(Inventory)) - { - mModels.emplace_back(Model); - Model->SetSaved(); - } - else - { - delete Model; + if (!NewModel->LoadInventory(Inventory)) return false; - } - Model->SetDescription(Description); + NewModel->SetSaved(); + NewModel->SetDescription(Description); - for (int ModelIdx = 0; ModelIdx < mModels.size(); ModelIdx++) - mModels[ModelIdx]->CreatePieceInfo(this); + mModels.clear(); + mModels.emplace_back(std::move(NewModel)); + + for (const std::unique_ptr& Model : mModels) + Model->CreatePieceInfo(this); std::vector UpdatedModels; UpdatedModels.reserve(mModels.size()); - for (int ModelIdx = 0; ModelIdx < mModels.size(); ModelIdx++) - mModels[ModelIdx]->UpdatePieceInfo(UpdatedModels); + for (const std::unique_ptr& Model : mModels) + Model->UpdatePieceInfo(UpdatedModels); mModified = false; @@ -643,12 +638,12 @@ std::vector Project::GetModelParts() if (mModels.empty()) return ModelParts; - for (lcModel* Model : mModels) + for (const std::unique_ptr& Model : mModels) Model->CalculateStep(LC_STEP_MAX); mModels[0]->GetModelParts(lcMatrix44Identity(), gDefaultColor, ModelParts); - SetActiveModel(mModels.FindIndex(mActiveModel)); + SetActiveModel(mActiveModel); return ModelParts; } @@ -671,7 +666,7 @@ bool Project::ExportCurrentStep(const QString& FileName) { Models.append(ModelName); - for (lcModel* Model : mModels) + for (const std::unique_ptr& Model : mModels) { if (Model->GetProperties().mFileName == ModelName) { @@ -724,7 +719,7 @@ bool Project::ExportCurrentStep(const QString& FileName) QTextStream Stream(&File); - for (lcModel* Model : mModels) + for (const std::unique_ptr& Model : mModels) { if (!Models.contains(Model->GetProperties().mFileName)) continue; @@ -1591,17 +1586,20 @@ void Project::ExportHTML(const lcHTMLExportOptions& Options) QDir Dir(Options.PathName); Dir.mkpath(QLatin1String(".")); - lcArray Models; + std::set Models; if (Options.CurrentOnly) - Models.emplace_back(mActiveModel); + Models.insert(mActiveModel); else if (Options.SubModels) { - Models.emplace_back(mActiveModel); + Models.insert(mActiveModel); mActiveModel->GetSubModels(Models); } else - Models = mModels; + { + for (const std::unique_ptr& Model : mModels) + Models.insert(Model.get()); + } QString ProjectTitle = GetTitle(); @@ -1772,9 +1770,8 @@ void Project::ExportHTML(const lcHTMLExportOptions& Options) Stream << QString::fromLatin1("\r\n\r\nInstructions for %1\r\n\r\n
\r\n
\r\n").arg(ProjectTitle); - for (int ModelIdx = 0; ModelIdx < Models.size(); ModelIdx++) + for (const lcModel* Model : Models) { - lcModel* Model = Models[ModelIdx]; BaseName = ProjectTitle.left(ProjectTitle.length() - QFileInfo(ProjectTitle).suffix().length() - 1) + '-' + Model->GetProperties().mFileName; BaseName.replace('#', '_'); diff --git a/common/project.h b/common/project.h index a3b88423..e5193eb2 100644 --- a/common/project.h +++ b/common/project.h @@ -39,7 +39,7 @@ public: Project& operator=(const Project&) = delete; Project& operator=(Project&&) = delete; - const lcArray& GetModels() const + const std::vector>& GetModels() const { return mModels; } @@ -51,14 +51,9 @@ public: return mActiveModel; } - int GetActiveModelIndex() const - { - return mModels.FindIndex(mActiveModel); - } - lcModel* GetMainModel() const { - return !mModels.empty() ? mModels[0] : nullptr; + return !mModels.empty() ? mModels[0].get() : nullptr; } bool IsModified() const; @@ -74,6 +69,7 @@ public: lcInstructions* GetInstructions(); + void SetActiveModel(lcModel* Model); void SetActiveModel(int ModelIndex); void SetActiveModel(const QString& FileName); @@ -112,7 +108,7 @@ protected: QString mFileName; QFileSystemWatcher mFileWatcher; - lcArray mModels; + std::vector> mModels; lcModel* mActiveModel; std::unique_ptr mInstructions;