diff --git a/Builds/MSVC/VS2015/Ember.vcxproj b/Builds/MSVC/VS2015/Ember.vcxproj index 759bf99..57afae8 100644 --- a/Builds/MSVC/VS2015/Ember.vcxproj +++ b/Builds/MSVC/VS2015/Ember.vcxproj @@ -70,6 +70,7 @@ true false AnySuitable + true Windows @@ -99,6 +100,7 @@ false false false + true Windows diff --git a/Builds/MSVC/VS2015/EmberAnimate.vcxproj b/Builds/MSVC/VS2015/EmberAnimate.vcxproj index dafb3a7..c7d7152 100644 --- a/Builds/MSVC/VS2015/EmberAnimate.vcxproj +++ b/Builds/MSVC/VS2015/EmberAnimate.vcxproj @@ -67,6 +67,7 @@ true false AnySuitable + true Console @@ -97,6 +98,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)" true false false + true Console diff --git a/Builds/MSVC/VS2015/EmberCL.vcxproj b/Builds/MSVC/VS2015/EmberCL.vcxproj index 51b9935..04229f9 100644 --- a/Builds/MSVC/VS2015/EmberCL.vcxproj +++ b/Builds/MSVC/VS2015/EmberCL.vcxproj @@ -68,6 +68,7 @@ true false AnySuitable + true Windows @@ -96,6 +97,7 @@ false true false + true Windows diff --git a/Builds/MSVC/VS2015/EmberGenome.vcxproj b/Builds/MSVC/VS2015/EmberGenome.vcxproj index cdac5fa..2959f7a 100644 --- a/Builds/MSVC/VS2015/EmberGenome.vcxproj +++ b/Builds/MSVC/VS2015/EmberGenome.vcxproj @@ -67,6 +67,7 @@ true false AnySuitable + true Console @@ -97,6 +98,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)" true false false + true Console diff --git a/Builds/MSVC/VS2015/EmberRender.vcxproj b/Builds/MSVC/VS2015/EmberRender.vcxproj index cef2440..ad01733 100644 --- a/Builds/MSVC/VS2015/EmberRender.vcxproj +++ b/Builds/MSVC/VS2015/EmberRender.vcxproj @@ -67,6 +67,7 @@ true false AnySuitable + true Console @@ -98,6 +99,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)" false true false + true Console diff --git a/Builds/MSVC/VS2015/EmberTester.vcxproj b/Builds/MSVC/VS2015/EmberTester.vcxproj index efe5eb4..7ec4eb5 100644 --- a/Builds/MSVC/VS2015/EmberTester.vcxproj +++ b/Builds/MSVC/VS2015/EmberTester.vcxproj @@ -67,6 +67,7 @@ true false AnySuitable + true Console @@ -97,6 +98,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)" true false false + true Console diff --git a/Builds/MSVC/VS2015/Fractorium.vcxproj b/Builds/MSVC/VS2015/Fractorium.vcxproj index cb1cf69..b463466 100644 --- a/Builds/MSVC/VS2015/Fractorium.vcxproj +++ b/Builds/MSVC/VS2015/Fractorium.vcxproj @@ -49,10 +49,10 @@ $(SolutionDir)Obj\$(TargetName)\$(Platform)\$(Configuration)\ - false + true - false + true @@ -74,6 +74,7 @@ false Level3 AnySuitable + true Windows @@ -114,6 +115,7 @@ xcopy /F /Y /R /D "$(QTDIR)\plugins\platforms\qwindowsd.dll" "$(OutDir)\platform /bigobj -Zm150 %(AdditionalOptions) false Level3 + true Windows diff --git a/archive/Info.plist b/Data/Info.plist similarity index 100% rename from archive/Info.plist rename to Data/Info.plist diff --git a/Source/Fractorium/EmberTreeWidgetItem.h b/Source/Fractorium/EmberTreeWidgetItem.h index b1875a6..2076418 100644 --- a/Source/Fractorium/EmberTreeWidgetItem.h +++ b/Source/Fractorium/EmberTreeWidgetItem.h @@ -34,6 +34,11 @@ public: { } + //~EmberTreeWidgetItemBase() + //{ + // qDebug() << "~EmberTreeWidgetItemBase()"; + //} + /// /// Set the preview image for the tree widget item. /// diff --git a/Source/Fractorium/FractoriumLibrary.cpp b/Source/Fractorium/FractoriumLibrary.cpp index c14abcc..8efe718 100644 --- a/Source/Fractorium/FractoriumLibrary.cpp +++ b/Source/Fractorium/FractoriumLibrary.cpp @@ -283,7 +283,11 @@ void FractoriumEmberController::EmberTreeItemChanged(QTreeWidgetItem* item, i } } -void Fractorium::OnEmberTreeItemChanged(QTreeWidgetItem* item, int col) { m_Controller->EmberTreeItemChanged(item, col); } +void Fractorium::OnEmberTreeItemChanged(QTreeWidgetItem* item, int col) +{ + if (ui.LibraryTree->topLevelItemCount())//This can sometimes be spurriously called even when the tree is empty. + m_Controller->EmberTreeItemChanged(item, col); +} /// /// Set the current ember to the selected item. @@ -301,12 +305,17 @@ void FractoriumEmberController::EmberTreeItemDoubleClicked(QTreeWidgetItem* i SetEmber(m_Fractorium->ui.LibraryTree->currentIndex().row(), false); } -void Fractorium::OnEmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col) { m_Controller->EmberTreeItemDoubleClicked(item, col); } +void Fractorium::OnEmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col) +{ + if (ui.LibraryTree->topLevelItemCount())//This can sometimes be spurriously called even when the tree is empty. + m_Controller->EmberTreeItemDoubleClicked(item, col); +} /// -/// Move a library item at one index to the next index. +/// Move a possibly disjoint selection of library items from their indices, +/// to another index. /// -/// The index of the source item to move +/// The selected list of items to move /// The destination index to move the item to template void FractoriumEmberController::MoveLibraryItems(const QModelIndexList& items, int destRow) @@ -315,17 +324,16 @@ void FractoriumEmberController::MoveLibraryItems(const QModelIndexList& items auto startRow = items[0].row(); auto tree = m_Fractorium->ui.LibraryTree; auto top = tree->topLevelItem(0); - list names; + list names; for (auto& item : items) if (auto temp = m_EmberFile.Get(item.row())) - names.push_back(QString::fromStdString(temp->m_Name)); + names.push_back(temp->m_Name); auto b = m_EmberFile.m_Embers.begin(); auto result = Gather(b, m_EmberFile.m_Embers.end(), Advance(b, destRow), [&](const Ember& ember) { - auto qname = QString::fromStdString(ember.m_Name); - auto position = std::find(names.begin(), names.end(), qname); + auto position = std::find(names.begin(), names.end(), ember.m_Name); if (position != names.end()) { @@ -335,7 +343,9 @@ void FractoriumEmberController::MoveLibraryItems(const QModelIndexList& items return false; }); + tree->update(); SyncLibrary(eLibraryUpdate(eLibraryUpdate::INDEX | eLibraryUpdate::POINTER)); + //SyncLibrary(eLibraryUpdate(eLibraryUpdate::INDEX | eLibraryUpdate::POINTER | eLibraryUpdate::NAME)); } /// @@ -496,7 +506,11 @@ void FractoriumEmberController::SequenceTreeItemChanged(QTreeWidgetItem* item } } -void Fractorium::OnSequenceTreeItemChanged(QTreeWidgetItem* item, int col) { m_Controller->SequenceTreeItemChanged(item, col); } +void Fractorium::OnSequenceTreeItemChanged(QTreeWidgetItem* item, int col) +{ + if (ui.SequenceTree->topLevelItemCount()) + m_Controller->SequenceTreeItemChanged(item, col); +} /// /// Wrapper around calling RenderPreviews with the appropriate values passed in for the previews in the sequence tree. diff --git a/Source/Fractorium/FractoriumRender.cpp b/Source/Fractorium/FractoriumRender.cpp index 2949fab..84d0bc6 100644 --- a/Source/Fractorium/FractoriumRender.cpp +++ b/Source/Fractorium/FractoriumRender.cpp @@ -683,6 +683,7 @@ bool Fractorium::CreateControllerFromOptions() Palette tempPalette; #endif QModelIndex index = ui.LibraryTree->currentIndex(); + ui.LibraryTree->clear();//This must be here before FillLibraryTree() is called below, else a spurious EmberTreeItemChanged event will be called on a deleted object. //First check if a controller has already been created, and if so, save its embers and gracefully shut it down. if (m_Controller.get()) @@ -716,6 +717,12 @@ bool Fractorium::CreateControllerFromOptions() prev->m_Palette = tempPalette; m_Controller->SetEmberFile(efd, true); + //Template specific palette table and variations tree setup in controller constructor, but + //must manually setup the library tree here because it's after the embers were assigned. + //Passing row re-selects the item that was previously selected. + //This will eventually call FillParamTablesAndPalette(), which in addition to filling in various fields, + //will apply the palette adjustments. + m_Controller->FillLibraryTree(index.row()); m_Controller->SetEmber(current, true); m_Controller->LockedScale(scale); //Setting these and updating the GUI overwrites the work of clearing them done in SetEmber() above. @@ -727,12 +734,6 @@ bool Fractorium::CreateControllerFromOptions() m_PaletteBlurSpin->SetValueStealth(blur); m_PaletteFrequencySpin->SetValueStealth(freq); m_Controller->PaletteAdjust();//Applies the adjustments to temp and saves in m_Ember.m_Palette, then fills in the palette preview widget. - //Template specific palette table and variations tree setup in controller constructor, but - //must manually setup the library tree here because it's after the embers were assigned. - //Passing row re-selects the item that was previously selected. - //This will eventually call FillParamTablesAndPalette(), which in addition to filling in various fields, - //will apply the palette adjustments. - m_Controller->FillLibraryTree(index.row()); } } @@ -773,5 +774,5 @@ bool Fractorium::ControllersOk() { return m_Controller.get() && m_Controller->GL template class FractoriumEmberController; #ifdef DO_DOUBLE -template class FractoriumEmberController; + template class FractoriumEmberController; #endif diff --git a/Source/Fractorium/Icons/Function-512.png b/Source/Fractorium/Icons/Function-512.png index a46dd1a..4522c2e 100644 Binary files a/Source/Fractorium/Icons/Function-512.png and b/Source/Fractorium/Icons/Function-512.png differ diff --git a/Source/Fractorium/Icons/grid.png b/Source/Fractorium/Icons/grid.png index fce17c9..5169259 100644 Binary files a/Source/Fractorium/Icons/grid.png and b/Source/Fractorium/Icons/grid.png differ diff --git a/Source/Fractorium/Icons/pic.png b/Source/Fractorium/Icons/pic.png index a5e7bf9..f617f2a 100644 Binary files a/Source/Fractorium/Icons/pic.png and b/Source/Fractorium/Icons/pic.png differ diff --git a/Source/Fractorium/LibraryTreeWidget.cpp b/Source/Fractorium/LibraryTreeWidget.cpp index d081b64..af18cb0 100644 --- a/Source/Fractorium/LibraryTreeWidget.cpp +++ b/Source/Fractorium/LibraryTreeWidget.cpp @@ -27,14 +27,70 @@ void LibraryTreeWidget::dropEvent(QDropEvent* de) } else if (!items.empty())//Actually do the drop and move the item to a new location. { - int row = droppedIndex.row(); + // get the list of the items that are about to be dragged + int i, row = droppedIndex.row(); DropIndicatorPosition dp = dropIndicatorPosition(); + QList dragItems = selectedItems(); if (dp == QAbstractItemView::BelowItem) row++; + auto itemat = this->itemFromIndex(droppedIndex); + QTreeWidget::dropEvent(de);//This internally changes the order of the items. + + //Qt has a long standing major bug that rearranges the order of disjoint selections when + //The drop location is in between the disjoint regions. + //This is an attempt to correct for that bug by removing the dropped items, then re-inserting them + //in the order they were selected. + //This bug remains present as of Qt 5.8: https://bugreports.qt.io/browse/QTBUG-45320 + if (auto top = topLevelItem(0)) + { + if (itemat) + { + auto offsetitem = this->indexFromItem(itemat); + + if (dp == QAbstractItemView::BelowItem) + { + auto itemrow = offsetitem.row() + 1; + + for (i = 0; i < dragItems.size(); i++) + { + if (itemrow < top->childCount()) + top->takeChild(itemrow); + } + + for (i = 0; i < dragItems.size(); i++) + { + auto offset = i + itemrow; + + if (offset <= top->childCount()) + top->insertChild(offset, dragItems[i]); + } + } + else + { + auto itemrow = offsetitem.row();//Will be at least 1 if dropped above it. + auto offset = itemrow; + + for (i = 0; i < dragItems.size(); i++) + { + offset--; + + if (offset < top->childCount()) + top->takeChild(offset); + } + + for (i = 0; i < dragItems.size(); i++) + { + if (offset <= top->childCount()) + top->insertChild(offset, dragItems[i]); + + offset++; + } + } + } + } + QTimer::singleShot(500, [ = ]() { m_Fractorium->m_Controller->MoveLibraryItems(items, row); });//Need to fire this after this event has internally reshuffled the items. } - - QTreeWidget::dropEvent(de); } \ No newline at end of file