Added model list dialog.

This commit is contained in:
leo 2014-12-12 23:42:09 +00:00
parent 5037897261
commit b20d52e2f9
10 changed files with 516 additions and 36 deletions

View file

@ -375,10 +375,6 @@ bool lcApplication::Initialize(int argc, char* argv[], const char* LibraryInstal
{ {
return false; return false;
} }
else
{
mProject->NewModel();
}
lcLoadDefaultKeyboardShortcuts(); lcLoadDefaultKeyboardShortcuts();

View file

@ -1127,7 +1127,7 @@ lcCommand gCommands[LC_NUM_COMMANDS] =
// LC_MODEL_LIST // LC_MODEL_LIST
{ {
"Model.List", "Model.List",
QT_TRANSLATE_NOOP("Menu", "List..."), QT_TRANSLATE_NOOP("Menu", "Models..."),
QT_TRANSLATE_NOOP("Status", "Show a list of all models in this project"), QT_TRANSLATE_NOOP("Status", "Show a list of all models in this project"),
QT_TRANSLATE_NOOP("Shortcut", "") QT_TRANSLATE_NOOP("Shortcut", "")
}, },

View file

@ -163,7 +163,6 @@ void lcMainWindow::NewProject()
return; return;
Project* NewProject = new Project(); Project* NewProject = new Project();
NewProject->NewModel();
g_App->SetProject(NewProject); g_App->SetProject(NewProject);
} }
@ -829,6 +828,33 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId)
UpdateAllViews(); UpdateAllViews();
} break; } break;
*/ */
case LC_MODEL_NEW:
lcGetActiveProject()->CreateNewModel();
break;
case LC_MODEL_LIST:
lcGetActiveProject()->ShowModelListDialog();
break;
case LC_MODEL_01:
case LC_MODEL_02:
case LC_MODEL_03:
case LC_MODEL_04:
case LC_MODEL_05:
case LC_MODEL_06:
case LC_MODEL_07:
case LC_MODEL_08:
case LC_MODEL_09:
case LC_MODEL_10:
case LC_MODEL_11:
case LC_MODEL_12:
case LC_MODEL_13:
case LC_MODEL_14:
case LC_MODEL_15:
case LC_MODEL_16:
lcGetActiveProject()->SetActiveModel(CommandId - LC_MODEL_01);
break;
case LC_HELP_HOMEPAGE: case LC_HELP_HOMEPAGE:
g_App->OpenURL("http://www.leocad.org/"); g_App->OpenURL("http://www.leocad.org/");
break; break;

View file

@ -143,6 +143,11 @@ public:
return mProperties; return mProperties;
} }
void SetName(const QString& Name)
{
mProperties.mName = Name;
}
lcStep GetLastStep() const; lcStep GetLastStep() const;
lcStep GetCurrentStep() const lcStep GetCurrentStep() const

View file

@ -17,11 +17,13 @@
#include "lc_application.h" #include "lc_application.h"
#include "lc_profile.h" #include "lc_profile.h"
#include "preview.h" #include "preview.h"
#include "lc_qmodellistdialog.h"
Project::Project() Project::Project()
{ {
mModified = false; mModified = false;
mActiveModel = NULL; mActiveModel = new lcModel(tr("Model #1"));
mModels.Add(mActiveModel);
} }
Project::~Project() Project::~Project()
@ -29,11 +31,148 @@ Project::~Project()
mModels.DeleteAll(); mModels.DeleteAll();
} }
void Project::NewModel() bool Project::IsModified() const
{ {
//todo: add dialog to get the model name and check if the name is unique if (mModified)
mActiveModel = new lcModel(tr("Model%1").arg(QString::number(mModels.GetSize() + 1))); return true;
mModels.Add(mActiveModel);
for (int ModelIdx = 0; ModelIdx < mModels.GetSize(); ModelIdx++)
if (mModels[ModelIdx]->IsModified())
return true;
return false;
}
QString Project::GetTitle() const
{
return mFileName.isEmpty() ? tr("New Project.ldr") : QFileInfo(mFileName).fileName();
}
void Project::SetActiveModel(int ModelIndex)
{
if (ModelIndex < 0 || ModelIndex >= mModels.GetSize())
return;
mActiveModel = mModels[ModelIndex];
mActiveModel->UpdateInterface();
gMainWindow->UpdateModels();
const lcArray<View*>& Views = gMainWindow->GetViews();
for (int ViewIdx = 0; ViewIdx < Views.GetSize(); ViewIdx++)
Views[ViewIdx]->SetModel(lcGetActiveModel());
}
bool Project::IsModelNameValid(const QString& Name) const
{
if (Name.isEmpty())
return false;
for (int ModelIdx = 0; ModelIdx < mModels.GetSize(); ModelIdx++)
if (mModels[ModelIdx]->GetProperties().mName == Name)
return false;
return true;
}
void Project::CreateNewModel()
{
const QString Prefix = tr("Model #");
int Max = 0;
for (int ModelIdx = 0; ModelIdx < mModels.GetSize(); ModelIdx++)
{
QString Name = mModels[ModelIdx]->GetProperties().mName;
if (Name.startsWith(Prefix))
{
QString NumberString = Name.mid(Prefix.length());
QTextStream Stream(&NumberString);
int Number;
Stream >> Number;
Max = qMax(Max, Number);
}
}
QString Name = Prefix + QString::number(Max + 1);
for (;;)
{
bool Ok = false;
Name = QInputDialog::getText(gMainWindow->mHandle, tr("New Model"), tr("Name:"), QLineEdit::Normal, Name, &Ok);
if (!Ok)
return;
if (IsModelNameValid(Name))
break;
if (Name.isEmpty())
QMessageBox::information(gMainWindow->mHandle, tr("Empty Name"), tr("The model name cannot be empty."));
else
QMessageBox::information(gMainWindow->mHandle, tr("Duplicate Model"), tr("A model named '%1' already exists in this project, please enter an unique name.").arg(Name));
}
if (!Name.isEmpty())
{
mModified = true;
mModels.Add(new lcModel(Name));
SetActiveModel(mModels.GetSize() - 1);
gMainWindow->UpdateTitle();
}
}
void Project::ShowModelListDialog()
{
QList<QPair<QString, lcModel*>> Models;
Models.reserve(mModels.GetSize());
for (int ModelIdx = 0; ModelIdx < mModels.GetSize(); ModelIdx++)
{
lcModel* Model = mModels[ModelIdx];
Models.append(QPair<QString, lcModel*>(Model->GetProperties().mName, Model));
}
lcQModelListDialog Dialog(gMainWindow->mHandle, Models);
if (Dialog.exec() != QDialog::Accepted || Models.isEmpty())
return;
lcArray<lcModel*> NewModels;
for (QList<QPair<QString, lcModel*>>::iterator it = Models.begin(); it != Models.end(); it++)
{
lcModel* Model = it->second;
if (!Model)
{
Model = new lcModel(it->first);
mModified = true;
}
else if (Model->GetProperties().mName != it->first)
{
Model->SetName(it->first);
mModified = true;
}
NewModels.Add(Model);
}
for (int ModelIdx = 0; ModelIdx < mModels.GetSize(); ModelIdx++)
{
lcModel* Model = mModels[ModelIdx];
if (NewModels.FindIndex(Model) == -1)
{
delete Model;
mModified = true;
}
}
mModels = NewModels;
SetActiveModel(Dialog.mActiveModel);
gMainWindow->UpdateTitle();
} }
bool Project::Load(const QString& FileName) bool Project::Load(const QString& FileName)
@ -46,6 +185,7 @@ bool Project::Load(const QString& FileName)
return false; return false;
} }
mModels.DeleteAll();
QString Extension = QFileInfo(FileName).suffix().toLower(); QString Extension = QFileInfo(FileName).suffix().toLower();
if (Extension == QLatin1String("dat") || Extension == QLatin1String("ldr") || Extension == QLatin1String("mpd")) if (Extension == QLatin1String("dat") || Extension == QLatin1String("ldr") || Extension == QLatin1String("mpd"))
@ -75,6 +215,8 @@ bool Project::Load(const QString& FileName)
delete Model; delete Model;
} }
// todo: validate model names
if (mModels.IsEmpty()) if (mModels.IsEmpty())
return false; return false;
@ -132,6 +274,7 @@ bool Project::Load(const QString& FileName)
*/ */
mFileName = FileName; mFileName = FileName;
mModified = false;
return true; return true;
} }
@ -169,17 +312,6 @@ bool Project::Save(const QString& FileName)
return true; return true;
} }
bool Project::IsModified() const
{
if (mModified)
return true;
for (int ModelIdx = 0; ModelIdx < mModels.GetSize(); ModelIdx++)
if (mModels[ModelIdx]->IsModified())
return true;
return false;
}
/* /*
void Project::LoadDefaults() // todo: Change the interface in SetProject() instead void Project::LoadDefaults() // todo: Change the interface in SetProject() instead
{ {
@ -205,10 +337,6 @@ void Project::LoadDefaults() // todo: Change the interface in SetProject() inste
gMainWindow->UpdateFocusObject(NULL); gMainWindow->UpdateFocusObject(NULL);
} }
*/ */
QString Project::GetTitle() const
{
return mFileName.isEmpty() ? tr("New Project.ldr") : QFileInfo(mFileName).fileName();
}
void Project::SaveImage() void Project::SaveImage()
{ {

View file

@ -2,11 +2,7 @@
#define _PROJECT_H_ #define _PROJECT_H_
#include "object.h" #include "object.h"
#include "opengl.h"
#include "lc_array.h" #include "lc_array.h"
#include "lc_math.h"
#include "lc_commands.h"
#include "str.h"
#include "lc_application.h" #include "lc_application.h"
#define LC_SCENE_FOG 0x004 // Enable fog #define LC_SCENE_FOG 0x004 // Enable fog
@ -50,18 +46,22 @@ public:
return mActiveModel; return mActiveModel;
} }
bool IsModified() const;
QString GetTitle() const; QString GetTitle() const;
QString GetFileName() const QString GetFileName() const
{ {
return mFileName; return mFileName;
} }
void NewModel(); void SetActiveModel(int ModelIndex);
bool IsModelNameValid(const QString& Name) const;
void CreateNewModel();
void ShowModelListDialog();
bool Load(const QString& FileName); bool Load(const QString& FileName);
bool Save(const QString& FileName); bool Save(const QString& FileName);
bool IsModified() const;
protected: protected:
bool mModified; bool mModified;
QString mFileName; QString mFileName;

View file

@ -160,7 +160,8 @@ SOURCES += common/view.cpp \
qt/lc_qimage.cpp \ qt/lc_qimage.cpp \
qt/lc_qglwidget.cpp \ qt/lc_qglwidget.cpp \
qt/lc_qcolorlist.cpp \ qt/lc_qcolorlist.cpp \
qt/lc_qfinddialog.cpp qt/lc_qfinddialog.cpp \
qt/lc_qmodellistdialog.cpp
HEADERS += \ HEADERS += \
common/view.h \ common/view.h \
common/tr.h \ common/tr.h \
@ -219,7 +220,8 @@ HEADERS += \
qt/lc_qcolorpicker.h \ qt/lc_qcolorpicker.h \
qt/lc_qglwidget.h \ qt/lc_qglwidget.h \
qt/lc_qcolorlist.h \ qt/lc_qcolorlist.h \
qt/lc_qfinddialog.h qt/lc_qfinddialog.h \
qt/lc_qmodellistdialog.h
FORMS += \ FORMS += \
qt/lc_qpovraydialog.ui \ qt/lc_qpovraydialog.ui \
qt/lc_qarraydialog.ui \ qt/lc_qarraydialog.ui \
@ -234,7 +236,8 @@ FORMS += \
qt/lc_qcategorydialog.ui \ qt/lc_qcategorydialog.ui \
qt/lc_qimagedialog.ui \ qt/lc_qimagedialog.ui \
qt/lc_qupdatedialog.ui \ qt/lc_qupdatedialog.ui \
qt/lc_qfinddialog.ui qt/lc_qfinddialog.ui \
qt/lc_qmodellistdialog.ui
OTHER_FILES += OTHER_FILES +=
RESOURCES += leocad.qrc RESOURCES += leocad.qrc

147
qt/lc_qmodellistdialog.cpp Normal file
View file

@ -0,0 +1,147 @@
#include "lc_qmodellistdialog.h"
#include "ui_lc_qmodellistdialog.h"
#include "project.h"
lcQModelListDialog::lcQModelListDialog(QWidget* Parent, QList<QPair<QString, lcModel*>>& Models)
: QDialog(Parent), mModels(Models), ui(new Ui::lcQModelListDialog)
{
ui->setupUi(this);
for (QList<QPair<QString, lcModel*>>::iterator it = Models.begin(); it != Models.end(); it++)
{
QListWidgetItem* Item = new QListWidgetItem(it->first);
Item->setData(Qt::UserRole, qVariantFromValue<uintptr_t>((uintptr_t)it->second));
ui->ModelList->addItem(Item);
}
ui->ModelList->setCurrentRow(0);
}
lcQModelListDialog::~lcQModelListDialog()
{
delete ui;
}
void lcQModelListDialog::accept()
{
mActiveModel = ui->ModelList->currentRow();
if (mActiveModel < 0)
mActiveModel = 0;
QDialog::accept();
}
void lcQModelListDialog::on_NewModel_clicked()
{
const QString Prefix = tr("Model #");
int Max = 0;
for (int ItemIdx = 0; ItemIdx < ui->ModelList->count(); ItemIdx++)
{
QString Name = ui->ModelList->item(ItemIdx)->text();
if (Name.startsWith(Prefix))
{
QString NumberString = Name.mid(Prefix.length());
QTextStream Stream(&NumberString);
int Number;
Stream >> Number;
Max = qMax(Max, Number);
}
}
QString Name = Prefix + QString::number(Max + 1);
if (Name.isEmpty())
return;
QListWidgetItem* Item = new QListWidgetItem(Name);
Item->setData(Qt::UserRole, qVariantFromValue<uintptr_t>(0));
ui->ModelList->addItem(Item);
}
void lcQModelListDialog::on_DeleteModel_clicked()
{
if (ui->ModelList->count() == 1)
{
QMessageBox::information(this, tr("Error"), tr("The project must have at least 1 model."));
return;
}
QList<QListWidgetItem*> SelectedItems = ui->ModelList->selectedItems();
if (SelectedItems.isEmpty())
return;
QString Prompt = tr("Are you sure you want to delete the model '%1'?").arg(SelectedItems[0]->text());
if (QMessageBox::question(this, tr("Delete Model"), Prompt, QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
return;
delete SelectedItems[0];
}
void lcQModelListDialog::on_RenameModel_clicked()
{
QList<QListWidgetItem*> SelectedItems = ui->ModelList->selectedItems();
if (SelectedItems.isEmpty())
return;
QString Name = SelectedItems[0]->text();
bool Ok = false;
for (;;)
{
Name = QInputDialog::getText(this, tr("Rename Model"), tr("Name:"), QLineEdit::Normal, Name, &Ok);
if (!Ok)
return;
if (Name.isEmpty())
{
QMessageBox::information(this, tr("Empty Name"), tr("The model name cannot be empty."));
continue;
}
QList<QListWidgetItem*> MatchedItems = ui->ModelList->findItems(Name, Qt::MatchFixedString);
if (MatchedItems.isEmpty() || (MatchedItems.size() == 1 && MatchedItems[0] == SelectedItems[0]))
break;
QMessageBox::information(this, tr("Duplicate Model"), tr("A model named '%1' already exists in this project, please enter an unique name.").arg(Name));
}
SelectedItems[0]->setText(Name);
}
void lcQModelListDialog::on_MoveUp_clicked()
{
QList<QListWidgetItem*> SelectedItems = ui->ModelList->selectedItems();
if (SelectedItems.isEmpty())
return;
QListWidgetItem* Item = SelectedItems[0];
int Row = ui->ModelList->row(Item);
if (Row == 0)
return;
ui->ModelList->takeItem(Row);
ui->ModelList->insertItem(Row - 1, Item);
ui->ModelList->setCurrentItem(Item);
}
void lcQModelListDialog::on_MoveDown_clicked()
{
QList<QListWidgetItem*> SelectedItems = ui->ModelList->selectedItems();
if (SelectedItems.isEmpty())
return;
QListWidgetItem* Item = SelectedItems[0];
int Row = ui->ModelList->row(Item);
ui->ModelList->takeItem(Row);
ui->ModelList->insertItem(Row + 1, Item);
ui->ModelList->setCurrentItem(Item);
}

33
qt/lc_qmodellistdialog.h Normal file
View file

@ -0,0 +1,33 @@
#ifndef _LC_QMODELLISTDIALOG_H_
#define _LC_QMODELLISTDIALOG_H_
#include <QDialog>
namespace Ui {
class lcQModelListDialog;
}
class lcQModelListDialog : public QDialog
{
Q_OBJECT
public:
lcQModelListDialog(QWidget* Parent, QList<QPair<QString, lcModel*>>& Models);
~lcQModelListDialog();
int mActiveModel;
QList<QPair<QString, lcModel*>>& mModels;
public slots:
void accept();
void on_NewModel_clicked();
void on_DeleteModel_clicked();
void on_RenameModel_clicked();
void on_MoveUp_clicked();
void on_MoveDown_clicked();
private:
Ui::lcQModelListDialog* ui;
};
#endif // _LC_QMODELLISTDIALOG_H_

142
qt/lc_qmodellistdialog.ui Normal file
View file

@ -0,0 +1,142 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>lcQModelListDialog</class>
<widget class="QDialog" name="lcQModelListDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Models</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QListWidget" name="ModelList"/>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="NewModel">
<property name="text">
<string>New...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="DeleteModel">
<property name="text">
<string>Delete...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="RenameModel">
<property name="text">
<string>Rename...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="MoveUp">
<property name="text">
<string>Move Up</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="MoveDown">
<property name="text">
<string>Move Down</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>ModelList</tabstop>
<tabstop>NewModel</tabstop>
<tabstop>DeleteModel</tabstop>
<tabstop>RenameModel</tabstop>
<tabstop>MoveUp</tabstop>
<tabstop>MoveDown</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>lcQModelListDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>lcQModelListDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>