--User changes

-Remove Hue as a saved parameter, as well as animation parameters associated with it. It's now a GUI-only field that is never saved.
 -Make histogram, density filter buffer, and all associated fields always float, even when using double. In that case, only the iteration calculations are now double. Suggested by Thomas Ludwig.
 -Print all three kernels in EmberRender when the --dump_kernel option is specified.
 -Apply variations filter to randoms.

--Bug fixes
 -Fix bug where hue was not being preserved when switching controllers and embers. Very hard to repro bug, but mostly overcome by eliminating hue as a saved parameter.

--Code changes
 -De-templatized DEOpenCLKernelCreator and FinalAccumOpenCLKernelCreator. They now just take a bool as a parameter to specify double precision.
 -To accommodate the buffers being float, introduce a new #define types in EmberCL called real4_bucket, and real4reals_bucket.
 -Density and spatial filtering structs now use this type.
 -ConvertDensityFilter() and ConvertSpatialFilter() no longer return a value, they just assign to the member.
This commit is contained in:
mfeemster
2015-08-10 20:10:23 -07:00
parent 6b702334b9
commit eecd3c254f
38 changed files with 695 additions and 771 deletions

View File

@ -92,7 +92,7 @@ template<typename T>
FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderDialog* finalRender)
: FinalRenderEmberControllerBase(finalRender)
{
m_FinalPreviewRenderer = unique_ptr<EmberNs::Renderer<T, T>>(new EmberNs::Renderer<T, T>());
m_FinalPreviewRenderer = unique_ptr<EmberNs::Renderer<T, float>>(new EmberNs::Renderer<T, float>());
m_FinalPreviewRenderer->Callback(nullptr);
m_FinalPreviewRenderer->NumChannels(4);
@ -431,7 +431,7 @@ bool FinalRenderEmberController<T>::CreateRenderer(eRendererType renderType, uin
m_OutputTexID = 0;//Don't care about tex ID when doing final render.
m_Shared = shared;
m_Renderer = unique_ptr<EmberNs::RendererBase>(::CreateRenderer<T, T>(renderType, platform, device, shared, m_OutputTexID, emberReport));
m_Renderer = unique_ptr<EmberNs::RendererBase>(::CreateRenderer<T, float>(renderType, platform, device, shared, m_OutputTexID, emberReport));
errorReport = emberReport.ErrorReport();
if (!errorReport.empty())

View File

@ -138,6 +138,6 @@ protected:
Ember<T> m_PreviewEmber;
EmberFile<T> m_EmberFile;
EmberToXml<T> m_XmlWriter;
unique_ptr<EmberNs::Renderer<T, T>> m_FinalPreviewRenderer;
unique_ptr<EmberNs::Renderer<T, float>> m_FinalPreviewRenderer;
};

View File

@ -117,6 +117,7 @@ Fractorium::Fractorium(QWidget* p)
m_Controller = unique_ptr<FractoriumEmberControllerBase>(new FractoriumEmberController<float>(this));
m_Controller->SetupVariationTree();
m_Controller->FilteredVariations();
if (m_Wrapper.CheckOpenCL() && m_Settings->OpenCL() && m_QualitySpin->value() < 30)
m_QualitySpin->setValue(30);

View File

@ -75,7 +75,7 @@
<x>0</x>
<y>0</y>
<width>1175</width>
<height>861</height>
<height>859</height>
</rect>
</property>
<property name="sizePolicy">
@ -2484,6 +2484,9 @@
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
@ -2596,7 +2599,7 @@
<string/>
</property>
<property name="autoFillBackground">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">QTabWidget::pane
@ -3262,7 +3265,7 @@ SpinBox
<string/>
</property>
<property name="autoFillBackground">
<bool>true</bool>
<bool>false</bool>
</property>
<attribute name="title">
<string>Affine</string>
@ -3289,7 +3292,7 @@ SpinBox
<item>
<widget class="QScrollArea" name="AffineTabScrollArea">
<property name="autoFillBackground">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
@ -3305,8 +3308,8 @@ SpinBox
<rect>
<x>0</x>
<y>0</y>
<width>243</width>
<height>745</height>
<width>118</width>
<height>618</height>
</rect>
</property>
<property name="autoFillBackground">
@ -3349,7 +3352,7 @@ SpinBox
</size>
</property>
<property name="autoFillBackground">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="title">
<string>Pre Affine Transform</string>
@ -3864,7 +3867,7 @@ SpinBox
<item>
<widget class="QGroupBox" name="PreAffineShowGroupBox">
<property name="autoFillBackground">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="title">
<string>Show</string>
@ -3938,7 +3941,7 @@ SpinBox
</size>
</property>
<property name="autoFillBackground">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="title">
<string>Post Affine Transform</string>
@ -4498,7 +4501,7 @@ SpinBox
<bool>true</bool>
</property>
<property name="autoFillBackground">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="title">
<string>Show</string>
@ -4555,7 +4558,7 @@ SpinBox
<item>
<widget class="QGroupBox" name="PivotGroupBox">
<property name="autoFillBackground">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="title">
<string>Pivot</string>
@ -4907,7 +4910,7 @@ SpinBox
</sizepolicy>
</property>
<property name="autoFillBackground">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="title">
<string>Select Xforms</string>
@ -4920,16 +4923,16 @@ SpinBox
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
<number>2</number>
</property>
<property name="topMargin">
<number>0</number>
<number>2</number>
</property>
<property name="rightMargin">
<number>0</number>
<number>2</number>
</property>
<property name="bottomMargin">
<number>0</number>
<number>2</number>
</property>
<item>
<widget class="QScrollArea" name="XformsSelectGroupBoxScrollArea">
@ -4962,8 +4965,8 @@ SpinBox
<rect>
<x>0</x>
<y>0</y>
<width>243</width>
<height>680</height>
<width>133</width>
<height>52</height>
</rect>
</property>
<property name="sizePolicy">
@ -5095,6 +5098,9 @@ SpinBox
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
@ -5119,6 +5125,9 @@ SpinBox
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="tabShape">
<enum>QTabWidget::Triangular</enum>
</property>
@ -5350,12 +5359,12 @@ SpinBox
</attribute>
<column>
<property name="text">
<string/>
<string>Collapse</string>
</property>
</column>
<column>
<property name="text">
<string/>
<string>Expand</string>
</property>
</column>
<item>
@ -6107,7 +6116,7 @@ SpinBox
<x>0</x>
<y>0</y>
<width>256</width>
<height>830</height>
<height>828</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_11">
@ -6585,7 +6594,7 @@ SpinBox
<string>DP</string>
</property>
<property name="toolTip">
<string>Use DP to render</string>
<string>Use double precision to render</string>
</property>
</action>
</widget>

View File

@ -72,11 +72,11 @@ FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium)
{
m_PreviewRun = false;
m_PreviewRunning = false;
m_SheepTools = unique_ptr<SheepTools<T, T>>(new SheepTools<T, T>(
m_SheepTools = unique_ptr<SheepTools<T, float>>(new SheepTools<T, float>(
QString(QApplication::applicationDirPath() + "flam3-palettes.xml").toLocal8Bit().data(),
new EmberNs::Renderer<T, T>()));
new EmberNs::Renderer<T, float>()));
m_GLController = unique_ptr<GLEmberController<T>>(new GLEmberController<T>(fractorium, fractorium->ui.GLDisplay, this));
m_PreviewRenderer = unique_ptr<EmberNs::Renderer<T, T>>(new EmberNs::Renderer<T, T>());
m_PreviewRenderer = unique_ptr<EmberNs::Renderer<T, float>>(new EmberNs::Renderer<T, float>());
//Initial combo change event to fill the palette table will be called automatically later.
if (!InitPaletteList(QCoreApplication::applicationDirPath().toLocal8Bit().data()))

View File

@ -185,6 +185,7 @@ public:
virtual void SetupVariationTree() { }
virtual void ClearVariationsTree() { }
virtual void VariationSpinBoxValueChanged(double d) { }
virtual void FilteredVariations() { }
//Xforms Selection.
@ -230,7 +231,7 @@ protected:
void AddProcessAction(eProcessAction action);
eProcessAction CondenseAndClearProcessActions();
eProcessState ProcessState() { return m_Renderer.get() ? m_Renderer->ProcessState() : NONE; }
//Non-templated members.
bool m_Rendering;
bool m_Shared;
@ -255,6 +256,7 @@ protected:
vector<byte> m_FinalImage[2];
vector<byte> m_PreviewFinalImage;
vector<eProcessAction> m_ProcessActions;
vector<eVariationId> m_FilteredVariations;
unique_ptr<EmberNs::RendererBase> m_Renderer;
QTIsaac<ISAAC_SIZE, ISAAC_INT> m_Rand;
Fractorium* m_Fractorium;
@ -423,6 +425,7 @@ public:
virtual void SetupVariationTree() override;
virtual void ClearVariationsTree() override;
virtual void VariationSpinBoxValueChanged(double d) override;
virtual void FilteredVariations() override;
void FillVariationTreeWithXform(Xform<T>* xform);
//Xforms Xaos.
@ -492,9 +495,9 @@ private:
Palette<T> m_TempPalette;
PaletteList<T> m_PaletteList;
VariationList<T> m_VariationList;
unique_ptr<SheepTools<T, T>> m_SheepTools;
unique_ptr<SheepTools<T, float>> m_SheepTools;
unique_ptr<GLEmberController<T>> m_GLController;
unique_ptr<EmberNs::Renderer<T, T>> m_PreviewRenderer;
unique_ptr<EmberNs::Renderer<T, float>> m_PreviewRenderer;
QFuture<void> m_PreviewResult;
std::function<void (uint, uint)> m_PreviewRenderFunc;
};

View File

@ -253,6 +253,8 @@ void Fractorium::OnEmberTreeItemChanged(QTreeWidgetItem* item, int col) { m_Cont
/// Clears the undo state.
/// Resets the rendering process.
/// Called when the user double clicks on a library tree item.
/// This will get called twice for some reason, and there's no way to prevent it.
/// Doesn't seem to cause any problems.
/// </summary>
/// <param name="item">The item double clicked on</param>
/// <param name="col">The column clicked, ignored.</param>

View File

@ -65,7 +65,7 @@ void FractoriumEmberController<T>::NewFlock(uint count)
for (uint i = 0; i < count; i++)
{
m_SheepTools->Random(ember);
m_SheepTools->Random(ember, m_FilteredVariations, static_cast<int>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand->Frand<T>(-2, 2)), 0);
ParamsToEmber(ember);
ember.m_Index = i;
ember.m_Name = m_EmberFile.m_Filename.toStdString() + "-" + ToString(i + 1).toStdString();
@ -126,7 +126,7 @@ void FractoriumEmberController<T>::NewRandomFlameInCurrentFile()
Ember<T> ember;
StopPreviewRender();
m_SheepTools->Random(ember);
m_SheepTools->Random(ember, m_FilteredVariations, static_cast<int>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand->Frand<T>(-2, 2)), 0);
ParamsToEmber(ember);
ember.m_Name = EmberFile<T>::DefaultEmberName(m_EmberFile.Size() + 1).toStdString();
ember.m_Index = m_EmberFile.Size();

View File

@ -162,11 +162,10 @@ void FractoriumEmberController<T>::ApplyPaletteToEmber()
double sat = double(m_Fractorium->m_PaletteSaturationSpin->value() / 100.0);
double brightness = double(m_Fractorium->m_PaletteBrightnessSpin->value() / 255.0);
double contrast = double(m_Fractorium->m_PaletteContrastSpin->value() > 0 ? (m_Fractorium->m_PaletteContrastSpin->value() * 2) : m_Fractorium->m_PaletteContrastSpin->value()) / 100.0;
m_Ember.m_Hue = double(m_Fractorium->m_PaletteHueSpin->value()) / 360.0;//This is the only palette adjustment value that gets saved with the ember, so just assign it here.
double hue = double(m_Fractorium->m_PaletteHueSpin->value()) / 360.0;
//Use the temp palette as the base and apply the adjustments gotten from the GUI and save the result in the ember palette.
m_TempPalette.MakeAdjustedPalette(m_Ember.m_Palette, 0, m_Ember.m_Hue, sat, brightness, contrast, blur, freq);
m_TempPalette.MakeAdjustedPalette(m_Ember.m_Palette, 0, hue, sat, brightness, contrast, blur, freq);
}
/// <summary>

View File

@ -550,18 +550,28 @@ void FractoriumEmberController<T>::FillParamTablesAndPalette()
FillXaos();
//Palette.
m_Fractorium->ResetPaletteControls();
m_Fractorium->m_PaletteHueSpin->SetValueStealth(NormalizeDeg180<double>(m_Ember.m_Hue * 360.0));//Convert -0.5 to 0.5 range to -180 - 180.
//Use the ember's embedded palette, rather than one from the list, so assign it directly to the controls without applying adjustments.
//Normally, the temp palette is assigned whenever the user clicks on a palette cell. But since that is skipped here, must do it manually.
//The temp palette is assigned the palette read when the file was parsed/saved. The user can apply adjustments on the GUI later.
//These adjustments will be applied to the temp palette, then assigned back to m_Ember.m_Palette.
//Normally, the temp palette is assigned whenever the user clicks on a palette cell. But since this is not
//called in response to that event, it is skipped here so must do it manually.
m_TempPalette = m_Ember.m_Palette;
auto temp = m_Ember.m_Palette.m_Filename;
//Palette controls are reset on each ember load. This means that if the palette was adjusted, saved, the selected ember
//changed to another, then back, the previously adjusted palette will now be considered the base, and all adjustments set to 0.
//To fix this, the caller must preserve the temp palette and the adjustment values and reassign. See Fractorium::CreateControllerFromOptions()
//for an example.
m_Fractorium->ResetPaletteControls();
auto temp = m_Ember.m_Palette.m_Filename;
if (temp.get())
m_Fractorium->SetPaletteFileComboIndex(*temp.get());
UpdateAdjustedPaletteGUI(m_Ember.m_Palette);//Setting the palette will trigger a full render.
//Update the palette preview widget.
//Since the controls were cleared above, the adjusted palette will be identical to the base palette.
//Callers can set, apply and display palette adjustments after this function exits if needed.
UpdateAdjustedPaletteGUI(m_Ember.m_Palette);//Updating the palette GUI will trigger a full render.
}
/// <summary>

View File

@ -277,7 +277,7 @@ bool FractoriumEmberController<T>::SyncSizes()
{
bool changed = false;
GLWidget* gl = m_Fractorium->ui.GLDisplay;
RendererCL<T>* rendererCL = nullptr;
RendererCL<T, float>* rendererCL = nullptr;
if (!m_GLController->SizesMatch())
{
@ -286,7 +286,7 @@ bool FractoriumEmberController<T>::SyncSizes()
gl->Allocate();
gl->SetViewport();
if (m_Renderer->RendererType() == OPENCL_RENDERER && (rendererCL = dynamic_cast<RendererCL<T>*>(m_Renderer.get())))
if (m_Renderer->RendererType() == OPENCL_RENDERER && (rendererCL = dynamic_cast<RendererCL<T, float>*>(m_Renderer.get())))
rendererCL->SetOutputTexture(gl->OutputTexID());
m_Fractorium->CenterScrollbars();
@ -308,11 +308,11 @@ bool FractoriumEmberController<T>::Render()
bool success = true;
GLWidget* gl = m_Fractorium->ui.GLDisplay;
RendererCL<T>* rendererCL = nullptr;
RendererCL<T, float>* rendererCL = nullptr;
eProcessAction action = CondenseAndClearProcessActions();
if (m_Renderer->RendererType() == OPENCL_RENDERER)
rendererCL = dynamic_cast<RendererCL<T>*>(m_Renderer.get());
rendererCL = dynamic_cast<RendererCL<T, float>*>(m_Renderer.get());
//Force temporal samples to always be 1. Perhaps change later when animation is implemented.
m_Ember.m_TemporalSamples = 1;
@ -524,7 +524,7 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, uint
DeleteRenderer();//Delete the renderer and refresh the textures.
//Before starting, must take care of allocations.
gl->Allocate(true);//Forcing a realloc of the texture is necessary on AMD, but not on nVidia.
m_Renderer = unique_ptr<EmberNs::RendererBase>(::CreateRenderer<T, T>(renderType, platform, device, shared, gl->OutputTexID(), emberReport));
m_Renderer = unique_ptr<EmberNs::RendererBase>(::CreateRenderer<T, float>(renderType, platform, device, shared, gl->OutputTexID(), emberReport));//Always make bucket type float.
errorReport = emberReport.ErrorReport();
if (errorReport.empty())
@ -699,20 +699,26 @@ bool Fractorium::CreateControllerFromOptions()
//Restore the ember and ember file.
if (m_Controller.get())
{
m_Controller->SetEmber(ed);//Convert float to double or set double verbatim;
ed.m_Palette = tempPalette;//Restore base temp palette. Adjustments will be then be applied and stored back in in m_Ember.m_Palette below.
m_Controller->SetEmber(ed);//Convert float to double or set double verbatim. This will assign m_Ember.m_Palette (which was just tempPalette) to m_TempPalette.
m_Controller->SetEmberFile(efd);
//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.
m_Controller->FillLibraryTree(index.row());//Passing row re-selects the item that was previously selected.
m_Controller->SetTempPalette(tempPalette);//Restore palette.
//Setting these and updating the GUI overwrites the work of clearing them done in SetEmber() above.
//It's a corner case, but doesn't seem to matter.
m_PaletteHueSpin->SetValueStealth(hue);
m_PaletteSaturationSpin->SetValueStealth(sat);
m_PaletteBrightnessSpin->SetValueStealth(bright);
m_PaletteContrastSpin->SetValueStealth(con);
m_PaletteBlurSpin->SetValueStealth(blur);
m_PaletteFrequencySpin->SetValueStealth(freq);
m_Controller->PaletteAdjust();//Fills in the palette.
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());
}
}

View File

@ -15,7 +15,7 @@ void Fractorium::InitToolbarUI()
spGroup->addAction(ui.ActionDP);
SyncOptionsToToolbar();
connect(ui.ActionCpu, SIGNAL(triggered(bool)), this, SLOT(OnActionCpu(bool)), Qt::QueuedConnection);//Need to sync these with options dialog.//TODO
connect(ui.ActionCpu, SIGNAL(triggered(bool)), this, SLOT(OnActionCpu(bool)), Qt::QueuedConnection);
connect(ui.ActionCL, SIGNAL(triggered(bool)), this, SLOT(OnActionCL(bool)), Qt::QueuedConnection);
connect(ui.ActionSP, SIGNAL(triggered(bool)), this, SLOT(OnActionSP(bool)), Qt::QueuedConnection);
connect(ui.ActionDP, SIGNAL(triggered(bool)), this, SLOT(OnActionDP(bool)), Qt::QueuedConnection);

View File

@ -27,7 +27,10 @@ void Fractorium::InitXformsVariationsUI()
void Fractorium::OnActionVariationsDialog(bool checked)
{
if (m_VarDialog->exec())
{
m_Controller->FilteredVariations();
Filter();
}
}
/// <summary>
@ -77,6 +80,20 @@ void Fractorium::Filter()
m_Controller->Filter(ui.VariationsFilterLineEdit->text());
}
template <typename T>
void FractoriumEmberController<T>::FilteredVariations()
{
auto& map = m_Fractorium->m_VarDialog->Map();
m_FilteredVariations.clear();
m_FilteredVariations.reserve(map.size());
for (auto i = 0; i < m_VariationList.Size(); i++)
if (auto var = m_VariationList.GetVariation(i))
if (map.contains(var->Name().c_str()) && map[var->Name().c_str()].toBool())
m_FilteredVariations.push_back(var->VariationId());
}
/// <summary>
/// Dynamically populate the variation tree widget with VariationTreeWidgetItem and VariationTreeDoubleSpinBox
/// templated with the correct type.
@ -222,6 +239,7 @@ void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would
if (xformVar)
xform->DeleteVariationById(var->VariationId());
//widgetItem->setBackgroundColor(0, Qt::darkGray);//Ensure background is always white if weight goes to zero.
widgetItem->setBackgroundColor(0, QColor(255, 255, 255));//Ensure background is always white if weight goes to zero.
}
else
@ -238,6 +256,7 @@ void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would
newVar->m_Weight = d;
xform->AddVariation(newVar);
//widgetItem->setBackgroundColor(0, Qt::darkGray);//Set background to gray when a variation has non-zero weight in this xform.
widgetItem->setBackgroundColor(0, QColor(200, 200, 200));//Set background to gray when a variation has non-zero weight in this xform.
//If they've added a new parametric variation, then grab the values currently in the spinners
@ -295,6 +314,7 @@ void FractoriumEmberController<T>::FillVariationTreeWithXform(Xform<T>* xform)
item->setHidden(false);
spinBox->SetValueStealth(var ? var->m_Weight : 0);//If the variation was present, set the spin box to its weight, else zero.
//item->setBackgroundColor(0, var ? Qt::darkGray : Qt::lightGray);//Ensure background is always white if the value goes to zero, else gray if var present.
item->setBackgroundColor(0, var ? QColor(200, 200, 200) : QColor(255, 255, 255));//Ensure background is always white if the value goes to zero, else gray if var present.
for (uint j = 0; j < item->childCount(); j++)//Iterate through all of the children, which will be the params if it was a parametric variation.

View File

@ -48,11 +48,50 @@ int main(int argc, char *argv[])
try
{
//a.setStyle(QStyleFactory::create("Fusion"));
//QPalette darkPalette;
/*darkPalette.setColor(QPalette::Window, QColor(53, 53, 53));
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, QColor(25, 25, 25));
darkPalette.setColor(QPalette::AlternateBase, QColor(53, 53, 53));
darkPalette.setColor(QPalette::ToolTipBase, Qt::white);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, QColor(53, 53, 53));
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::BrightText, Qt::red);
darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
darkPalette.setColor(QPalette::HighlightedText, Qt::black);;*/
//darkPalette.setColor(QPalette::, Qt::lightGray);
//darkPalette.setColor(QPalette::Window, Qt::darkGray);
//darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, Qt::red);
//darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, Qt::blue);//Works for disabled buttons, but not for disabled menus.
//a.setPalette(darkPalette);
//a.setStyleSheet("QToolTip { color: #ffffff; background-color: darkgray; border: 1px solid white; }");
//a.setStyleSheet("QTableWidget { border-color: darkgray; }")
//QString s;
//s = "QTableView, QSpinBox, QDoubleSpinBox, QGroupBox, QTreeWidget { background-color: darkGray; } ";
//s += "QComboBox, QTextEdit, QLineEdit { background - color: lightGray; } ";
//s += "QTabWidget { window-color: darkGray; } ";
//a.setStyleSheet("{ color: rgb(85, 170, 0); }");
//a.setStyleSheet("GLWidget { background-color: darkgray; }");
//a.setStyleSheet("QTableView, QDoubleSpinBox { background-color: darkgray; }");//Works!
//a.setStyleSheet(s);//Works!
//a.setStyleSheet("QTableView, QSpinBox, QDoubleSpinBox, QTreeWidget, QTreeWidgetItem { background-color: darkgray; }");//QTreeWidgetItem not needed.
//a.setStyleSheet("QTableView, DoubleSpinBox { background-color: darkgray; }");//Works!
Fractorium w;
w.show();
a.installEventFilter(&w);
rv = a.exec();
} catch (const char *e) {
}
catch (const char* e)
{
QMessageBox::critical(0, "Fatal Error", e);
}