diff --git a/common/lc_instructions.cpp b/common/lc_instructions.cpp index 2c05e06e..a7256628 100644 --- a/common/lc_instructions.cpp +++ b/common/lc_instructions.cpp @@ -24,6 +24,28 @@ lcInstructions::lcInstructions(Project* Project) CreatePages(); } +lcInstructionsStepProperties lcInstructions::GetStepProperties(lcModel* Model, lcStep Step) const +{ + lcInstructionsStepProperties StepProperties = mStepProperties; + + std::map::const_iterator ModelIt = mModels.find(Model); + + if (ModelIt == mModels.end()) + return StepProperties; + + const lcInstructionsModel& InstructionModel = ModelIt->second; + + for (lcStep StepIndex = 0; StepIndex <= Step; StepIndex++) + { + const lcInstructionsStepProperties& Properties = InstructionModel.StepProperties[StepIndex]; + + if (Properties.BackgroundColorMode == lcInstructionsPropertyMode::Set || (Properties.BackgroundColorMode == lcInstructionsPropertyMode::StepOnly && Step == StepIndex)) + StepProperties.BackgroundColor = Properties.BackgroundColor; + } + + return StepProperties; +} + void lcInstructions::SetDefaultPageSettings(const lcInstructionsPageSettings& PageSettings) { mPageSettings = PageSettings; @@ -31,6 +53,17 @@ void lcInstructions::SetDefaultPageSettings(const lcInstructionsPageSettings& Pa CreatePages(); } +void lcInstructions::SetDefaultStepBackgroundColor(quint32 Color) +{ + if (mStepProperties.BackgroundColor == Color) + return; + + mStepProperties.BackgroundColor = Color; + + for (size_t PageIndex = 0; PageIndex < mPages.size(); PageIndex++) + emit PageInvalid(static_cast(PageIndex)); // todo: invalidate steps, not pages +} + void lcInstructions::CreatePages() { mPages.clear(); @@ -57,6 +90,10 @@ void lcInstructions::AddDefaultPages(lcModel* Model, std::vector lcInstructionsPage Page; int Row = 0, Column = 0; + lcInstructionsModel InstructionModel; + InstructionModel.StepProperties.resize(LastStep + 1); + mModels.emplace(Model, std::move(InstructionModel)); + for (lcStep Step = 1; Step <= LastStep; Step++) { std::set StepSubModels; diff --git a/common/lc_instructions.h b/common/lc_instructions.h index 57662421..9290162e 100644 --- a/common/lc_instructions.h +++ b/common/lc_instructions.h @@ -1,5 +1,7 @@ #pragma once +#include "lc_math.h" + struct lcInstructionsPageSetup { float Width; @@ -23,11 +25,26 @@ struct lcInstructionsPageSettings lcInstructionsDirection Direction; }; +enum class lcInstructionsPropertyMode +{ + NotSet, + Set, + StepOnly +}; + +struct lcInstructionsStepProperties +{ + lcInstructionsPropertyMode BackgroundColorMode = lcInstructionsPropertyMode::NotSet; + quint32 BackgroundColor = LC_RGBA(255, 255, 255, 0); +}; + struct lcInstructionsStep { QRectF Rect; lcModel* Model; lcStep Step; + + lcInstructionsStepProperties Properties; }; struct lcInstructionsPage @@ -36,16 +53,31 @@ struct lcInstructionsPage std::vector Steps; }; -class lcInstructions +struct lcInstructionsModel { + std::vector StepProperties; +}; + +class lcInstructions : public QObject +{ + Q_OBJECT + public: lcInstructions(Project* Project = nullptr); + lcInstructionsStepProperties GetStepProperties(lcModel* Model, lcStep Step) const; void SetDefaultPageSettings(const lcInstructionsPageSettings& PageSettings); + void SetDefaultStepBackgroundColor(quint32 Color); std::vector mPages; lcInstructionsPageSettings mPageSettings; lcInstructionsPageSetup mPageSetup; + lcInstructionsStepProperties mStepProperties; + + std::map mModels; + +signals: + void PageInvalid(int PageIndex); protected: void CreatePages(); diff --git a/common/lc_instructionsdialog.cpp b/common/lc_instructionsdialog.cpp index fe4495ae..13eab9e0 100644 --- a/common/lc_instructionsdialog.cpp +++ b/common/lc_instructionsdialog.cpp @@ -4,13 +4,33 @@ #include "project.h" #include "lc_model.h" #include "lc_view.h" +#include "lc_collapsiblewidget.h" + +lcInstructionsStepItem::lcInstructionsStepItem(const QPixmap& Pixmap, QGraphicsItem* Parent, lcInstructionsPropertiesWidget* PropertiesWidget) + : QGraphicsPixmapItem(Pixmap, Parent), mPropertiesWidget(PropertiesWidget) +{ +} + +void lcInstructionsStepItem::focusInEvent(QFocusEvent* FocusEvent) +{ + mPropertiesWidget->StepItemFocusIn(this); + + QGraphicsPixmapItem::focusInEvent(FocusEvent); +} + +void lcInstructionsStepItem::focusOutEvent(QFocusEvent* FocusEvent) +{ + mPropertiesWidget->ItemFocusOut(this); + + QGraphicsPixmapItem::focusOutEvent(FocusEvent); +} lcInstructionsPageWidget::lcInstructionsPageWidget(QWidget* Parent, lcInstructions* Instructions) : QGraphicsView(Parent), mInstructions(Instructions) { } -void lcInstructionsPageWidget::SetCurrentPage(const lcInstructionsPage* Page) +void lcInstructionsPageWidget::SetCurrentPage(const lcInstructionsPage* Page, lcInstructionsPropertiesWidget* PropertiesWidget) { QGraphicsScene* Scene = new QGraphicsScene(); setScene(Scene); @@ -30,12 +50,13 @@ void lcInstructionsPageWidget::SetCurrentPage(const lcInstructionsPage* Page) { const float StepWidth = MarginsRect.width() * Step.Rect.width(); const float StepHeight = MarginsRect.height() * Step.Rect.height(); + const lcInstructionsStepProperties StepProperties = mInstructions->GetStepProperties(Step.Model, Step.Step); lcView View(lcViewType::View, Step.Model); View.SetOffscreenContext(); View.MakeCurrent(); -// View.SetBackgroundColorOverride(LC_RGBA(255, 255, 0, 255)); + View.SetBackgroundColorOverride(StepProperties.BackgroundColor); View.SetSize(StepWidth, StepHeight); std::vector Images = View.GetStepImages(Step.Step, Step.Step); @@ -45,7 +66,7 @@ void lcInstructionsPageWidget::SetCurrentPage(const lcInstructionsPage* Page) QImage& StepImage = Images.front(); - QGraphicsPixmapItem* StepImageItem = new QGraphicsPixmapItem(QPixmap::fromImage(StepImage), PageItem); + lcInstructionsStepItem* StepImageItem = new lcInstructionsStepItem(QPixmap::fromImage(StepImage), PageItem, PropertiesWidget); StepImageItem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable); StepImageItem->setPos(MarginsRect.left() + MarginsRect.width() * Step.Rect.x(), MarginsRect.top() + MarginsRect.height() * Step.Rect.y()); @@ -175,6 +196,79 @@ void lcInstructionsPageListWidget::ShowPageSetupDialog() return; } +lcInstructionsPropertiesWidget::lcInstructionsPropertiesWidget(QWidget* Parent, lcInstructions* Instructions) + : QDockWidget(Parent), mInstructions(Instructions) +{ + QWidget* CentralWidget = new QWidget(this); + setWidget(CentralWidget); + setWindowTitle(tr("Properties")); + + QGridLayout* Layout = new QGridLayout(CentralWidget); + Layout->setContentsMargins(0, 0, 0, 0); + + QComboBox* ScopeComboBox = new QComboBox(CentralWidget); + ScopeComboBox->addItems(QStringList() << tr("Default") << tr("Current Model") << tr("Current Step Only") << tr("Current Step Forward")); + + Layout->addWidget(new QLabel(tr("Scope:")), 0, 0); + Layout->addWidget(ScopeComboBox, 0, 1); + + QComboBox* PresetComboBox = new QComboBox(CentralWidget); + + Layout->addWidget(new QLabel(tr("Preset:")), 1, 0); + Layout->addWidget(PresetComboBox, 1, 1); + + Layout->setRowStretch(3, 1); +} + +void lcInstructionsPropertiesWidget::ColorButtonClicked() +{ +// const lcInstructionsStepProperties StepProperties = mInstructions->GetStepProperties(Step.Model, Step.Step); + + QColor Color = QColorDialog::getColor(); + + if (!Color.isValid()) + return; + + mInstructions->SetDefaultStepBackgroundColor(LC_RGBA(Color.red(), Color.green(), Color.blue(), Color.alpha())); + +// mPageListWidget->mThumbnailsWidget->setCurrentRow(0); +} + +void lcInstructionsPropertiesWidget::StepItemFocusIn(lcInstructionsStepItem* StepItem) +{ + if (mFocusItem == StepItem) + return; + + mFocusItem = StepItem; + + delete mWidget; + mWidget = new lcCollapsibleWidget(tr("Step Properties")); // todo: disable collapse + + QGridLayout* WidgetLayout = qobject_cast(widget()->layout()); + WidgetLayout->addWidget(mWidget, 2, 0, 1, -1); + + QGridLayout* Layout = new QGridLayout(); + mWidget->SetChildLayout(Layout); + + QToolButton* ColorButton = new QToolButton(); + ColorButton->setText("background"); + + Layout->addWidget(ColorButton); + + connect(ColorButton, &QToolButton::clicked, this, &lcInstructionsPropertiesWidget::ColorButtonClicked); +} + +void lcInstructionsPropertiesWidget::ItemFocusOut(QGraphicsItem* Item) +{ + if (mFocusItem != Item) + return; + + mFocusItem = nullptr; + + delete mWidget; + mWidget = nullptr; +} + lcInstructionsDialog::lcInstructionsDialog(QWidget* Parent, Project* Project) : QMainWindow(Parent), mProject(Project) { @@ -182,13 +276,17 @@ lcInstructionsDialog::lcInstructionsDialog(QWidget* Parent, Project* Project) mInstructions = mProject->GetInstructions(); - mPageWidget = new lcInstructionsPageWidget(this, &mInstructions); + mPageWidget = new lcInstructionsPageWidget(this, mInstructions); setCentralWidget(mPageWidget); - mPageListWidget = new lcInstructionsPageListWidget(this, &mInstructions); - mPageListWidget->setObjectName("PageList"); + mPageListWidget = new lcInstructionsPageListWidget(this, mInstructions); + mPageListWidget->setObjectName("InstructionsPageList"); addDockWidget(Qt::LeftDockWidgetArea, mPageListWidget); + mPropertiesWidget = new lcInstructionsPropertiesWidget(this, mInstructions); + mPropertiesWidget->setObjectName("InstructionsProperties"); + addDockWidget(Qt::RightDockWidgetArea, mPropertiesWidget); + mPageSettingsToolBar = addToolBar(tr("Page Settings")); mPageSettingsToolBar->setObjectName("PageSettings"); mPageSettingsToolBar->setFloatable(false); @@ -209,12 +307,13 @@ lcInstructionsDialog::lcInstructionsDialog(QWidget* Parent, Project* Project) PageDirectionGroup->addAction(mVerticalPageAction); PageDirectionGroup->addAction(mHorizontalPageAction); - for (size_t PageNumber = 0; PageNumber < mInstructions.mPages.size(); PageNumber++) + for (size_t PageNumber = 0; PageNumber < mInstructions->mPages.size(); PageNumber++) mPageListWidget->mThumbnailsWidget->addItem(QString("Page %1").arg(PageNumber + 1)); connect(mPageListWidget->mThumbnailsWidget, SIGNAL(currentRowChanged(int)), this, SLOT(CurrentThumbnailChanged(int))); mPageListWidget->mThumbnailsWidget->setCurrentRow(0); + connect(mInstructions, &lcInstructions::PageInvalid, this, &lcInstructionsDialog::PageInvalid); connect(mVerticalPageAction, SIGNAL(toggled(bool)), this, SLOT(UpdatePageSettings())); connect(mHorizontalPageAction, SIGNAL(toggled(bool)), this, SLOT(UpdatePageSettings())); connect(mRowsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(UpdatePageSettings())); @@ -233,11 +332,11 @@ void lcInstructionsDialog::UpdatePageSettings() else PageSettings.Direction = lcInstructionsDirection::Vertical; - mInstructions.SetDefaultPageSettings(PageSettings); + mInstructions->SetDefaultPageSettings(PageSettings); // lcInstructionsPage* Page = &mInstructions.mPages[mThumbnailsWidget->currentIndex().row()]; mPageListWidget->mThumbnailsWidget->clear(); - for (size_t PageNumber = 0; PageNumber < mInstructions.mPages.size(); PageNumber++) + for (size_t PageNumber = 0; PageNumber < mInstructions->mPages.size(); PageNumber++) mPageListWidget->mThumbnailsWidget->addItem(QString("Page %1").arg(PageNumber + 1)); // mThumbnailsWidget->setCurrentRow(0); @@ -247,17 +346,17 @@ void lcInstructionsDialog::UpdatePageSettings() void lcInstructionsDialog::CurrentThumbnailChanged(int Index) { - if (Index < 0 || Index >= static_cast(mInstructions.mPages.size())) + if (Index < 0 || Index >= static_cast(mInstructions->mPages.size())) { - mPageWidget->SetCurrentPage(nullptr); + mPageWidget->SetCurrentPage(nullptr, mPropertiesWidget); return; } - const lcInstructionsPage* Page = &mInstructions.mPages[Index]; + const lcInstructionsPage* Page = &mInstructions->mPages[Index]; // const lcInstructionsPageSettings& PageSettings = Page->Settings; - const lcInstructionsPageSettings& PageSettings = mInstructions.mPageSettings; + const lcInstructionsPageSettings& PageSettings = mInstructions->mPageSettings; - mPageWidget->SetCurrentPage(Page); + mPageWidget->SetCurrentPage(Page, mPropertiesWidget); if (PageSettings.Direction == lcInstructionsDirection::Horizontal) { @@ -280,3 +379,12 @@ void lcInstructionsDialog::CurrentThumbnailChanged(int Index) mColumnsSpinBox->setValue(PageSettings.Columns); mColumnsSpinBox->blockSignals(false); } + +void lcInstructionsDialog::PageInvalid(int PageIndex) +{ + if (mPageListWidget->mThumbnailsWidget->currentRow() == PageIndex) + { + const lcInstructionsPage* Page = &mInstructions->mPages[PageIndex]; + mPageWidget->SetCurrentPage(Page, mPropertiesWidget); + } +} diff --git a/common/lc_instructionsdialog.h b/common/lc_instructionsdialog.h index 735d7e15..ddbfb174 100644 --- a/common/lc_instructionsdialog.h +++ b/common/lc_instructionsdialog.h @@ -2,6 +2,20 @@ #include "lc_instructions.h" +class lcInstructionsPropertiesWidget; + +class lcInstructionsStepItem : public QGraphicsPixmapItem +{ +public: + lcInstructionsStepItem(const QPixmap& Pixmap, QGraphicsItem* Parent, lcInstructionsPropertiesWidget* PropertiesWidget); + +protected: + void focusInEvent(QFocusEvent* FocusEvent) override; + void focusOutEvent(QFocusEvent* FocusEvent) override; + + lcInstructionsPropertiesWidget* mPropertiesWidget = nullptr; +}; + class lcInstructionsPageWidget : public QGraphicsView { Q_OBJECT @@ -9,7 +23,7 @@ class lcInstructionsPageWidget : public QGraphicsView public: lcInstructionsPageWidget(QWidget* Parent, lcInstructions* Instructions); - void SetCurrentPage(const lcInstructionsPage* Page); + void SetCurrentPage(const lcInstructionsPage* Page, lcInstructionsPropertiesWidget* PropertiesWidget); protected: lcInstructions* mInstructions; @@ -47,6 +61,25 @@ protected: lcInstructions* mInstructions; }; +class lcInstructionsPropertiesWidget : public QDockWidget +{ + Q_OBJECT + +public: + lcInstructionsPropertiesWidget(QWidget* Parent, lcInstructions* Instructions); + + void StepItemFocusIn(lcInstructionsStepItem* StepItem); + void ItemFocusOut(QGraphicsItem* Item); + +protected slots: + void ColorButtonClicked(); + +protected: + lcCollapsibleWidget* mWidget = nullptr; + lcInstructions* mInstructions = nullptr; + QGraphicsItem* mFocusItem = nullptr; +}; + class lcInstructionsDialog : public QMainWindow { Q_OBJECT @@ -57,15 +90,17 @@ public: protected slots: void UpdatePageSettings(); void CurrentThumbnailChanged(int Index); + void PageInvalid(int PageIndex); protected: Project* mProject = nullptr; int mCurrentPageNumber; - lcInstructions mInstructions; + lcInstructions* mInstructions; lcInstructionsPageWidget* mPageWidget = nullptr; lcInstructionsPageListWidget* mPageListWidget = nullptr; + lcInstructionsPropertiesWidget* mPropertiesWidget = nullptr; QToolBar* mPageSettingsToolBar = nullptr; QAction* mVerticalPageAction = nullptr; diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index 07284500..75b25475 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -1127,8 +1127,8 @@ void lcMainWindow::Print(QPrinter* Printer) int DocCopies; int PageCopies; - lcInstructions Instructions = lcGetActiveProject()->GetInstructions(); - const int PageCount = static_cast(Instructions.mPages.size()); + lcInstructions* Instructions = lcGetActiveProject()->GetInstructions(); + const int PageCount = static_cast(Instructions->mPages.size()); if (Printer->collateCopies()) { @@ -1193,7 +1193,7 @@ void lcMainWindow::Print(QPrinter* Printer) int StepWidth = MarginRect.width(); int StepHeight = MarginRect.height(); - const lcInstructionsPage& PageLayout = Instructions.mPages[Page - 1]; + const lcInstructionsPage& PageLayout = Instructions->mPages[Page - 1]; lcModel* Model = PageLayout.Steps[0].Model; lcStep Step = PageLayout.Steps[0].Step; QImage Image = Model->GetStepImage(false, StepWidth, StepHeight, Step); @@ -1299,7 +1299,7 @@ void lcMainWindow::ShowInstructionsDialog() void lcMainWindow::ShowPrintDialog() { #ifndef QT_NO_PRINTER - int PageCount = static_cast(lcGetActiveProject()->GetInstructions().mPages.size()); + int PageCount = static_cast(lcGetActiveProject()->GetInstructions()->mPages.size()); QPrinter Printer(QPrinter::HighResolution); Printer.setFromTo(1, PageCount + 1); @@ -1923,7 +1923,7 @@ void lcMainWindow::TogglePrintPreview() #ifndef QT_NO_PRINTER // todo: print preview inside main window - int PageCount = static_cast(lcGetActiveProject()->GetInstructions().mPages.size()); + int PageCount = static_cast(lcGetActiveProject()->GetInstructions()->mPages.size()); QPrinter Printer(QPrinter::ScreenResolution); Printer.setFromTo(1, PageCount + 1); diff --git a/common/project.cpp b/common/project.cpp index 0b3ff62d..5c22a042 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -1504,9 +1504,12 @@ void Project::ExportCSV() } } -lcInstructions Project::GetInstructions() +lcInstructions* Project::GetInstructions() { - return lcInstructions(this); + mInstructions.reset(); + mInstructions = std::unique_ptr(new lcInstructions(this)); + + return mInstructions.get(); } void Project::ExportHTML(const lcHTMLExportOptions& Options) diff --git a/common/project.h b/common/project.h index e91b4ce1..938e0091 100644 --- a/common/project.h +++ b/common/project.h @@ -70,7 +70,7 @@ public: QString GetImageFileName(bool AllowCurrentFolder) const; - lcInstructions GetInstructions(); + lcInstructions* GetInstructions(); void SetActiveModel(int ModelIndex); void SetActiveModel(const QString& FileName); @@ -110,6 +110,7 @@ protected: lcArray mModels; lcModel* mActiveModel; + std::unique_ptr mInstructions; Q_DECLARE_TR_FUNCTIONS(Project); };