2015-10-27 00:31:35 -04:00
# include "FractoriumPch.h"
# include "QssDialog.h"
# include "ui_QssDialog.h"
# include "qcssscanner.h"
/// <summary>
/// The code in this file did not originate in Fractorium.
/// It was taken either in whole or in part from the source code
/// of Qt Creator. Their license applies.
/// </summary>
/// <summary>
/// Comparison for sorting object names.
/// Strings not starting with the letter 'Q' take precedence.
/// This has the effect of putting custom derived classes first before
/// all Q* classes.
/// </summary>
/// <param name="s1">The first string to compare</param>
/// <param name="s2">The second string to compare</param>
/// <returns>True if s1 < s2 with special rules for 'Q' taken into account.</returns>
bool CaseInsensitiveLessThanQ ( const QString & s1 , const QString & s2 )
{
if ( s1 . length ( ) & & s2 . length ( ) )
{
if ( s1 [ 0 ] = = ' Q ' & & s2 [ 0 ] = = ' Q ' )
return s1 . toLower ( ) < s2 . toLower ( ) ;
else if ( s1 [ 0 ] = = ' Q ' )
return false ;
else if ( s2 [ 0 ] = = ' Q ' )
return true ;
else
return s1 . toLower ( ) < s2 . toLower ( ) ;
}
return false ;
}
/// <summary>
/// Construct a QssDialog.
/// This manually constructs much of the menu GUI via code rather
/// than in the designer.
/// </summary>
/// <param name="parent">The main Fractorium window.</param>
QssDialog : : QssDialog ( Fractorium * parent ) :
QDialog ( parent ) ,
ui ( new Ui : : QssDialog ) ,
2015-11-25 17:32:34 -05:00
m_Parent ( parent ) ,
2015-10-27 00:31:35 -04:00
m_AddColorAction ( new QAction ( tr ( " Add Color " ) , this ) ) ,
m_AddGeomAction ( new QAction ( tr ( " Add Geometry " ) , this ) ) ,
m_AddBorderAction ( new QAction ( tr ( " Add Border " ) , this ) ) ,
m_AddFontAction ( new QAction ( tr ( " Add Font... " ) , this ) ) ,
m_AddStyleAction ( new QAction ( tr ( " Set Theme " ) , this ) )
{
ui - > setupUi ( this ) ;
m_LastStyle = m_Parent - > styleSheet ( ) ;
setWindowTitle ( " QSS Editor - default.qss " ) ;
connect ( ui - > QssEdit , SIGNAL ( textChanged ( ) ) , this , SLOT ( SlotTextChanged ( ) ) ) ;
QToolBar * toolBar = new QToolBar ( this ) ;
QMenu * colorActionMenu = new QMenu ( this ) ;
QMenu * geomActionMenu = new QMenu ( this ) ;
QMenu * borderActionMenu = new QMenu ( this ) ;
QMenu * styleActionMenu = new QMenu ( this ) ;
( m_ColorActionMapper = new QSignalMapper ( this ) ) - > setMapping ( m_AddColorAction , QString ( ) ) ;
( m_GeomActionMapper = new QSignalMapper ( this ) ) - > setMapping ( m_AddGeomAction , QString ( ) ) ;
( m_BorderActionMapper = new QSignalMapper ( this ) ) - > setMapping ( m_AddBorderAction , QString ( ) ) ;
( m_StyleActionMapper = new QSignalMapper ( this ) ) - > setMapping ( m_AddStyleAction , QString ( ) ) ;
connect ( ui - > QssLoadButton , SIGNAL ( clicked ( ) ) , this , SLOT ( LoadButton_clicked ( ) ) , Qt : : QueuedConnection ) ;
connect ( ui - > QssSaveButton , SIGNAL ( clicked ( ) ) , this , SLOT ( SaveButton_clicked ( ) ) , Qt : : QueuedConnection ) ;
connect ( ui - > QssBasicButton , SIGNAL ( clicked ( ) ) , this , SLOT ( BasicButton_clicked ( ) ) , Qt : : QueuedConnection ) ;
connect ( ui - > QssMediumButton , SIGNAL ( clicked ( ) ) , this , SLOT ( MediumButton_clicked ( ) ) , Qt : : QueuedConnection ) ;
connect ( ui - > QssAdvancedButton , SIGNAL ( clicked ( ) ) , this , SLOT ( AdvancedButton_clicked ( ) ) , Qt : : QueuedConnection ) ;
connect ( m_AddFontAction , SIGNAL ( triggered ( ) ) , this , SLOT ( SlotAddFont ( ) ) ) ;
QVector < QPair < QString , QString > > colorVec ;
colorVec . reserve ( 12 ) ;
colorVec . push_back ( QPair < QString , QString > ( " color " , " " ) ) ;
colorVec . push_back ( QPair < QString , QString > ( " background-color " , " " ) ) ;
colorVec . push_back ( QPair < QString , QString > ( " alternate-background-color " , " " ) ) ;
colorVec . push_back ( QPair < QString , QString > ( " border-color " , " " ) ) ;
colorVec . push_back ( QPair < QString , QString > ( " border-top-color " , " " ) ) ;
colorVec . push_back ( QPair < QString , QString > ( " border-right-color " , " " ) ) ;
colorVec . push_back ( QPair < QString , QString > ( " border-bottom-color " , " " ) ) ;
colorVec . push_back ( QPair < QString , QString > ( " border-left-color " , " " ) ) ;
colorVec . push_back ( QPair < QString , QString > ( " gridline-color " , " " ) ) ;
colorVec . push_back ( QPair < QString , QString > ( " selection-color " , " " ) ) ;
colorVec . push_back ( QPair < QString , QString > ( " selection-background-color " , " " ) ) ;
for ( auto & c : colorVec )
{
auto colorAction = colorActionMenu - > addAction ( c . first ) ;
m_ColorMap [ c . first ] = c . second ;
connect ( colorAction , SIGNAL ( triggered ( ) ) , m_ColorActionMapper , SLOT ( map ( ) ) ) ;
m_ColorActionMapper - > setMapping ( colorAction , c . first ) ;
}
QVector < QPair < QString , QString > > geomVec ;
geomVec . reserve ( 12 ) ;
geomVec . push_back ( QPair < QString , QString > ( " width " , " 100px " ) ) ;
geomVec . push_back ( QPair < QString , QString > ( " height " , " 50px " ) ) ;
geomVec . push_back ( QPair < QString , QString > ( " spacing " , " 10 " ) ) ;
geomVec . push_back ( QPair < QString , QString > ( " padding " , " 3px " ) ) ;
geomVec . push_back ( QPair < QString , QString > ( " padding-top " , " 3px " ) ) ;
geomVec . push_back ( QPair < QString , QString > ( " padding-right " , " 3px " ) ) ;
geomVec . push_back ( QPair < QString , QString > ( " padding-bottom " , " 3px " ) ) ;
geomVec . push_back ( QPair < QString , QString > ( " padding-left " , " 3px " ) ) ;
geomVec . push_back ( QPair < QString , QString > ( " margin " , " 3px " ) ) ;
geomVec . push_back ( QPair < QString , QString > ( " margin-top " , " 3px " ) ) ;
geomVec . push_back ( QPair < QString , QString > ( " margin-right " , " 3px " ) ) ;
geomVec . push_back ( QPair < QString , QString > ( " margin-bottom " , " 3px " ) ) ;
geomVec . push_back ( QPair < QString , QString > ( " margin-left " , " 3px " ) ) ;
for ( auto & g : geomVec )
{
auto geomAction = geomActionMenu - > addAction ( g . first ) ;
m_GeomMap [ g . first ] = g . second ;
connect ( geomAction , SIGNAL ( triggered ( ) ) , m_GeomActionMapper , SLOT ( map ( ) ) ) ;
m_GeomActionMapper - > setMapping ( geomAction , g . first ) ;
}
QVector < QPair < QString , QString > > borderVec ;
borderVec . reserve ( 8 ) ;
borderVec . push_back ( QPair < QString , QString > ( " border " , " 1px solid black " ) ) ;
borderVec . push_back ( QPair < QString , QString > ( " border-top " , " 1px inset black " ) ) ;
borderVec . push_back ( QPair < QString , QString > ( " border-right " , " 1px outset black " ) ) ;
borderVec . push_back ( QPair < QString , QString > ( " border-bottom " , " 1px ridge black " ) ) ;
borderVec . push_back ( QPair < QString , QString > ( " border-left " , " 1px groove black " ) ) ;
borderVec . push_back ( QPair < QString , QString > ( " border-style " , " double " ) ) ;
borderVec . push_back ( QPair < QString , QString > ( " border-width " , " 1px " ) ) ;
borderVec . push_back ( QPair < QString , QString > ( " border-radius " , " 10px " ) ) ;
for ( auto & b : borderVec )
{
auto borderAction = borderActionMenu - > addAction ( b . first ) ;
m_BorderMap [ b . first ] = b . second ;
connect ( borderAction , SIGNAL ( triggered ( ) ) , m_BorderActionMapper , SLOT ( map ( ) ) ) ;
m_BorderActionMapper - > setMapping ( borderAction , b . first ) ;
}
auto styles = QStyleFactory : : keys ( ) ;
2016-12-05 22:04:33 -05:00
2015-10-27 00:31:35 -04:00
for ( auto & s : styles )
{
auto styleAction = styleActionMenu - > addAction ( s ) ;
m_StyleMap [ s ] = s ;
connect ( styleAction , SIGNAL ( triggered ( ) ) , m_StyleActionMapper , SLOT ( map ( ) ) ) ;
m_StyleActionMapper - > setMapping ( styleAction , s ) ;
}
connect ( m_ColorActionMapper , SIGNAL ( mapped ( QString ) ) , this , SLOT ( SlotAddColor ( QString ) ) ) ;
connect ( m_GeomActionMapper , SIGNAL ( mapped ( QString ) ) , this , SLOT ( SlotAddGeom ( QString ) ) ) ;
connect ( m_BorderActionMapper , SIGNAL ( mapped ( QString ) ) , this , SLOT ( SlotAddBorder ( QString ) ) ) ;
connect ( m_StyleActionMapper , SIGNAL ( mapped ( QString ) ) , this , SLOT ( SlotSetTheme ( QString ) ) ) ;
m_AddColorAction - > setMenu ( colorActionMenu ) ;
m_AddGeomAction - > setMenu ( geomActionMenu ) ;
m_AddBorderAction - > setMenu ( borderActionMenu ) ;
m_AddStyleAction - > setMenu ( styleActionMenu ) ;
toolBar - > addAction ( m_AddColorAction ) ;
toolBar - > addAction ( m_AddGeomAction ) ;
toolBar - > addAction ( m_AddBorderAction ) ;
toolBar - > addAction ( m_AddFontAction ) ;
toolBar - > addAction ( m_AddStyleAction ) ;
ui - > verticalLayout - > insertWidget ( 0 , toolBar ) ;
ui - > QssEdit - > setFocus ( ) ;
m_ApplyTimer = new QTimer ( this ) ;
m_ApplyTimer - > setSingleShot ( true ) ;
m_ApplyTimer - > setInterval ( 1000 ) ;
connect ( m_ApplyTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( SlotApplyCss ( ) ) ) ;
}
/// <summary>
/// Destructor that stops the apply timer and deletes the ui.
/// </summary>
QssDialog : : ~ QssDialog ( )
{
m_ApplyTimer - > stop ( ) ;
delete ui ;
}
/// <summary>
/// Thin wrapper around getting the text from the main text box as plain text.
/// </summary>
/// <returns>The plain text of the main text box</returns>
QString QssDialog : : Text ( ) const
{
return ui - > QssEdit - > toPlainText ( ) ;
}
/// <summary>
/// Thin wrapper around setting the text of the main text box.
/// </summary>
/// <param name="t">The text to set</param>
void QssDialog : : SetText ( const QString & t )
{
ui - > QssEdit - > setText ( t ) ;
}
/// <summary>
/// Get the class names of all objects in the application.
/// This only makes one entry for each class type.
/// It will also optionally return the object names as well for advanced QSS editing.
/// </summary>
/// <param name="includeObjectNames">Whether to get the individual object names as well</param>
/// <returns>A list of all class names with optional entries for each individual object</returns>
QList < QString > QssDialog : : GetClassNames ( bool includeObjectNames )
{
QSet < QString > classNames ;
QList < QList < QString > > dialogClassNames ;
auto widgetList = m_Parent - > findChildren < QWidget * > ( ) ;
for ( int i = 0 ; i < widgetList . size ( ) ; i + + )
{
auto classAndName = QString ( widgetList [ i ] - > metaObject ( ) - > className ( ) ) ;
if ( ! includeObjectNames )
{
classNames . insert ( classAndName ) ;
}
else
{
auto dlg = qobject_cast < QDialog * > ( widgetList [ i ] ) ;
if ( dlg ) //Dialogs only nest one level deep, so no need for generalized recursion.
{
QSet < QString > dlgSet ;
auto dlgWidgetList = dlg - > findChildren < QWidget * > ( ) ; //Find all children of the dialog.
dlgSet . insert ( classAndName ) ; //Add the basic dialog class name, opening curly brace will be added later.
classAndName + = " " ;
for ( int i = 0 ; i < dlgWidgetList . size ( ) ; i + + )
{
auto dlgClassAndName = classAndName + QString ( dlgWidgetList [ i ] - > metaObject ( ) - > className ( ) ) ;
dlgSet . insert ( dlgClassAndName ) ;
if ( ! dlgWidgetList [ i ] - > objectName ( ) . isEmpty ( ) ) //Add the class with object name for individual control customization.
{
dlgClassAndName + = " # " + dlgWidgetList [ i ] - > objectName ( ) ;
dlgSet . insert ( dlgClassAndName ) ;
}
}
auto dlgList = dlgSet . toList ( ) ; //Convert set to list and sort.
qSort ( dlgList . begin ( ) , dlgList . end ( ) , CaseInsensitiveLessThanQ ) ;
dialogClassNames . push_back ( dlgList ) ; //Add this to the full list after sorting at the end.
}
else if ( GetAllParents < QDialog * > ( widgetList [ i ] ) . empty ( ) ) //Skip widgets on dialogs, they are added above.
{
classNames . insert ( classAndName ) ; //Add the basic class name.
if ( ! widgetList [ i ] - > objectName ( ) . isEmpty ( ) ) //Add the class with object name for individual control customization.
{
classAndName + = " # " + widgetList [ i ] - > objectName ( ) ;
classNames . insert ( classAndName ) ;
}
}
}
}
auto l = classNames . toList ( ) ;
qSort ( l . begin ( ) , l . end ( ) , CaseInsensitiveLessThanQ ) ;
for ( auto & d : dialogClassNames )
l . append ( d ) ;
return l ;
}
/// <summary>
/// Determines whether the passed in stylesheet text is valid.
/// If the initial parse fails, a second attempt is made by wrapping the entire
/// text in curly braces.
/// </summary>
/// <param name="styleSheet">The stylesheet text to analyze.</param>
/// <returns>True if valid, else false.</returns>
bool QssDialog : : IsStyleSheetValid ( const QString & styleSheet )
{
QCss : : Parser parser ( styleSheet ) ;
QCss : : StyleSheet sheet ;
2016-12-05 22:04:33 -05:00
2015-10-27 00:31:35 -04:00
if ( parser . parse ( & sheet ) )
return true ;
2016-12-05 22:04:33 -05:00
2015-10-27 00:31:35 -04:00
QString fullSheet = QStringLiteral ( " * { " ) ;
fullSheet + = styleSheet ;
fullSheet + = QLatin1Char ( ' } ' ) ;
QCss : : Parser parser2 ( fullSheet ) ;
return parser2 . parse ( & sheet ) ;
}
/// <summary>
/// Save the current stylesheet text to default.qss.
/// Also save the selected theme to the settings.
/// Called when the user clicks ok.
/// Not called if cancelled or closed with the X.
/// </summary>
void QssDialog : : accept ( )
{
if ( m_Theme )
m_Parent - > m_Settings - > Theme ( m_Theme - > objectName ( ) ) ;
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
SaveAsDefault ( ) ;
2015-10-27 00:31:35 -04:00
QDialog : : accept ( ) ;
}
/// <summary>
/// Restore the stylesheet and theme to what it was when the dialog was opened.
/// Called when the user clicks cancel or closes with the X.
/// </summary>
void QssDialog : : reject ( )
{
if ( ! m_LastStyle . isEmpty ( ) )
m_Parent - > setStyleSheet ( m_LastStyle ) ;
if ( m_LastTheme )
{
m_Parent - > setStyle ( m_LastTheme ) ;
m_Parent - > m_Settings - > Theme ( m_LastTheme - > objectName ( ) ) ;
}
2018-07-31 00:39:41 -04:00
m_Parent - > m_Controller - > FillVariationTreeWithCurrentXform ( ) ;
2015-10-27 00:31:35 -04:00
QDialog : : reject ( ) ;
}
/// <summary>
/// Shows the event.
/// </summary>
/// <param name="e">The e.</param>
void QssDialog : : showEvent ( QShowEvent * e )
{
if ( m_Parent )
{
m_LastStyle = m_Parent - > styleSheet ( ) ;
m_LastTheme = m_Parent - > m_Theme ; //The style() member cannot be relied upon, it is *not* the same object passed to setStyle();
SetText ( m_LastStyle ) ;
}
2016-12-05 22:04:33 -05:00
2015-10-27 00:31:35 -04:00
QDialog : : showEvent ( e ) ;
}
/// <summary>
/// Start the timer which will analyze and apply the current stylesheet text.
/// Each successive keystroke will reset the timer if it has not timed out yet.
/// This is only called when the dialog is visible because it seems to be spurriously
/// called on startup.
/// Called when the user changes the text in main text box.
/// </summary>
void QssDialog : : SlotTextChanged ( )
{
if ( isVisible ( ) ) //Sometimes this fires even though the window is not shown yet.
m_ApplyTimer - > start ( ) ;
}
/// <summary>
/// Add a color string to the stylesheet text.
/// Called when the user clicks the add color menu.
/// </summary>
/// <param name="s">The color string selector to add</param>
void QssDialog : : SlotAddColor ( const QString & s )
{
const QColor color = QColorDialog : : getColor ( 0xffffffff , this , QString ( ) , QColorDialog : : ShowAlphaChannel ) ;
if ( ! color . isValid ( ) )
return ;
QString colorStr ;
if ( color . alpha ( ) = = 255 )
{
colorStr = QString ( QStringLiteral ( " rgb(%1, %2, %3) " ) ) . arg (
2016-12-05 22:04:33 -05:00
color . red ( ) ) . arg ( color . green ( ) ) . arg ( color . blue ( ) ) ;
2015-10-27 00:31:35 -04:00
}
else
{
colorStr = QString ( QStringLiteral ( " rgba(%1, %2, %3, %4) " ) ) . arg (
2016-12-05 22:04:33 -05:00
color . red ( ) ) . arg ( color . green ( ) ) . arg ( color . blue ( ) ) . arg ( color . alpha ( ) ) ;
2015-10-27 00:31:35 -04:00
}
InsertCssProperty ( s , colorStr ) ;
}
/// <summary>
/// Adds a geometry string to the stylesheet text.
/// </summary>
/// <param name="s">The geometry string to add</param>
void QssDialog : : SlotAddGeom ( const QString & s )
{
auto val = m_GeomMap [ s ] ;
InsertCssProperty ( s , val ) ;
}
/// <summary>
/// Adds a border string to the stylesheet text.
/// </summary>
/// <param name="s">The border string to add</param>
void QssDialog : : SlotAddBorder ( const QString & s )
{
auto val = m_BorderMap [ s ] ;
InsertCssProperty ( s , val ) ;
}
/// <summary>
/// Set the theme to the user selection.
/// Called when the user selects an item on the theme combo box.
/// </summary>
/// <param name="s">The s.</param>
void QssDialog : : SlotSetTheme ( const QString & s )
{
if ( auto theme = QStyleFactory : : create ( s ) )
{
m_Theme = theme ;
m_Parent - > setStyle ( m_Theme ) ;
}
}
/// <summary>
/// Add a font string.
/// Called when the user clicks the add font menu button.
/// </summary>
void QssDialog : : SlotAddFont ( )
{
bool ok ;
auto font = QFontDialog : : getFont ( & ok , this ) ;
if ( ok )
{
QString fontStr ;
if ( font . weight ( ) ! = QFont : : Normal )
{
fontStr + = QString : : number ( font . weight ( ) ) ;
fontStr + = QLatin1Char ( ' ' ) ;
}
switch ( font . style ( ) )
{
2016-12-05 22:04:33 -05:00
case QFont : : StyleItalic :
fontStr + = QStringLiteral ( " italic " ) ;
break ;
case QFont : : StyleOblique :
fontStr + = QStringLiteral ( " oblique " ) ;
break ;
default :
break ;
2015-10-27 00:31:35 -04:00
}
fontStr + = QString : : number ( font . pointSize ( ) ) ;
fontStr + = QStringLiteral ( " pt \" " ) ;
fontStr + = font . family ( ) ;
fontStr + = QLatin1Char ( ' " ' ) ;
InsertCssProperty ( QStringLiteral ( " font " ) , fontStr ) ;
}
}
/// <summary>
/// Check if the current stylesheet is valid and apply it if so.
/// Also indicate via label whether it was valid.
/// </summary>
void QssDialog : : SlotApplyCss ( )
{
auto label = ui - > QssValidityLabel ;
auto style = Text ( ) ;
const bool valid = IsStyleSheetValid ( style ) ;
ui - > QssButtonBox - > button ( QDialogButtonBox : : Ok ) - > setEnabled ( valid ) ;
if ( valid )
{
label - > setText ( tr ( " Valid Style Sheet " ) ) ;
label - > setStyleSheet ( QStringLiteral ( " color: green " ) ) ;
m_Parent - > setStyleSheet ( style ) ;
2018-07-31 00:39:41 -04:00
m_Parent - > m_Controller - > FillVariationTreeWithCurrentXform ( ) ;
2015-10-27 00:31:35 -04:00
}
else
{
label - > setText ( tr ( " Invalid Style Sheet " ) ) ;
label - > setStyleSheet ( QStringLiteral ( " color: red " ) ) ;
}
}
/// <summary>
/// Load a stylesheet from disk.
/// Called when the user clicks the load button.
/// </summary>
void QssDialog : : LoadButton_clicked ( )
{
string s ;
auto f = OpenFile ( ) ;
if ( ! f . isEmpty ( ) & & ReadFile ( f . toStdString ( ) . c_str ( ) , s ) & & ! s . empty ( ) )
SetText ( QString : : fromStdString ( s ) ) ;
setWindowTitle ( " QSS Editor - " + f ) ;
}
/// <summary>
/// Save the stylesheet to disk.
/// Called when the user clicks the save button.
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
/// The user cannot save to default.qss, as it's a special placeholder.
/// When they exit the dialog by clicking OK, the currently displayed stylesheet
/// will be saved to default.qss.
2015-10-27 00:31:35 -04:00
/// </summary>
void QssDialog : : SaveButton_clicked ( )
{
auto path = SaveFile ( ) ;
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
if ( path . toLower ( ) . endsWith ( " default.qss " ) )
{
QMessageBox : : critical ( this , " File save error " , " Stylesheet cannot be saved to default.qss. Save it to a different file name, then exit the dialog by clicking OK which will set it as the default. " ) ;
return ;
}
2015-10-27 00:31:35 -04:00
if ( ! path . isEmpty ( ) )
{
ofstream of ( path . toStdString ( ) ) ;
string s = Text ( ) . toStdString ( ) ;
if ( of . is_open ( ) )
of < < s ;
else
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
QMessageBox : : critical ( this , " File save error " , " Failed to save " + path + " , style will not be set as default " ) ;
2015-10-27 00:31:35 -04:00
}
}
/// <summary>
/// Save the stylesheet to the default.qss on disk.
/// This will be loaded the next time Fractorium runs.
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
/// Called when the user clicks ok.
2015-10-27 00:31:35 -04:00
/// </summary>
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
void QssDialog : : SaveAsDefault ( )
2015-10-27 00:31:35 -04:00
{
auto path = m_Parent - > m_SettingsPath + " /default.qss " ;
ofstream of ( path . toStdString ( ) ) ;
auto s = Text ( ) . toStdString ( ) ;
if ( of . is_open ( ) )
of < < s ;
else
--User changes
-Add new variations: bubbleT3D, crob, hexaplay3D, hexcrop, hexes, hexnix3D, loonie2, loonie3, nBlur, octapol and synth.
-Allow for pre/post versions of dc_bubble, dc_cylinder and dc_linear whereas before they were omitted.
-When saving a file with multiple embers in it, detect if time values are all the same and if so, start them at zero and increment by 1 for each ember.
-Allow for numerous quality increases to be coalesced into one. It will pick up at the end of the current render.
-Show selection highlight on variations tree in response to mouse hover. This makes it easier to see for which variation or param the current mouse wheel action will apply.
-Make default temporal samples be 100, whereas before it was 1000 which was overkill.
-Require the shift key to be held with delete for deleting an ember to prevent it from triggering when the user enters delete in the edit box.
-This wasn't otherwise fixable without writing a lot more code.
--Bug fixes
-EmberGenome was crashing when generating a sequence from a source file with more than 2 embers in it.
-EmberGenome was improperly handling the first frame of a merge after the last frame of the loop.
-These bugs were due to a previous commit. Revert parts of that commit.
-Prevent a zoom value of less than 0 when reading from xml.
-Slight optimization of the crescents, and mask variations, if the compiler wasn't doing it already.
-Unique file naming was broken because it was looking for _# and the default names ended with -#.
-Disallow renaming of an ember in the library tree to an empty string.
-Severe bug that prevented some variations from being read correctly from params generated outside this program.
-Severe OpenCL randomization bug. The first x coordinates of the first points in the first kernel call of the first ember of a render since the OpenCL renderer object was created were not random and were mostly -1.
-Severe bug when populating xform selection distributions that could sometimes cause a crash due to roundoff error. Fix by using double.
-Limit the max number of variations in a random ember to MAX_CL_VARS, which is 8. This ensures they'll look the same on CPU and GPU.
-Prevent user from saving stylesheet to default.qss, it's a special reserved filename.
--Code changes
-Generalize using the running sum output point inside of a variation for all cases: pre, reg and post.
-Allow for array variables in variations where the address of each element is stored in m_Params.
-Qualify all math functions with std::
-No longer use our own Clamp() in OpenCL, instead use the standard clamp().
-Redesign how functions are used in the variations OpenCL code.
-Add tests to EmberTester to verify some of the new functionality.
-Place more const and override qualifiers on functions where appropriate.
-Add a global rand with a lock to be used very sparingly.
-Use a map instead of a vector for bad param names in Xml parsing.
-Prefix affine interpolation mode defines with "AFFINE_" to make their purpose more clear.
-Allow for variations that change state during iteration by sending a separate copy of the ember to each rendering thread.
-Implement this same functionality with a local struct in OpenCL. It's members are the total of all variables that need to change state within an ember.
-Add Contains() function to Utils.h.
-EmberRender: print names of kernels being printed with --dump_kernel option.
-Clean up EmberTester to handle some of the recent changes.
-Fix various casts.
-Replace % 2 with & 1, even though the compiler was likely doing this already.
-Add new file Variations06.h to accommodate new variations.
-General cleanup.
2015-11-22 17:15:07 -05:00
QMessageBox : : critical ( this , " File save error " , " Failed to save " + path + " , style will not be set as default " ) ;
2015-10-27 00:31:35 -04:00
}
/// <summary>
/// Fill the main text box with the most basic style.
/// Called when the Basic button is clicked.
/// </summary>
void QssDialog : : BasicButton_clicked ( )
{
SetText ( BaseStyle ( ) ) ;
setWindowTitle ( " QSS Editor " ) ;
}
/// <summary>
/// Fill the main text box with a medium specificity style.
/// This will expose all control types in the application.
/// Called when the Medium button is clicked.
/// </summary>
void QssDialog : : MediumButton_clicked ( )
{
QString str = BaseStyle ( ) ;
auto names = GetClassNames ( false ) ;
for ( auto & it : names )
str + = it + QString ( " \n { \n \t \n } \n \n " ) ;
SetText ( str ) ;
setWindowTitle ( " QSS Editor " ) ;
}
/// <summary>
/// Fill the main text box with the most advanced style.
/// This will expose all control types in the application as well as their named instances.
/// Called when the Advanced button is clicked.
/// </summary>
void QssDialog : : AdvancedButton_clicked ( )
{
QString str = BaseStyle ( ) ;
auto names = GetClassNames ( true ) ;
for ( auto & it : names )
str + = it + QString ( " \n { \n \t \n } \n \n " ) ;
SetText ( str ) ;
setWindowTitle ( " QSS Editor " ) ;
}
/// <summary>
/// Insert a CSS property.
/// This is called whenever the user inserts a value via the menus.
/// </summary>
/// <param name="name">The name of the property to insert</param>
/// <param name="value">The value of the property to insert</param>
void QssDialog : : InsertCssProperty ( const QString & name , const QString & value )
{
auto editor = ui - > QssEdit ;
auto cursor = editor - > textCursor ( ) ;
if ( ! name . isEmpty ( ) )
{
cursor . beginEditBlock ( ) ;
cursor . removeSelectedText ( ) ;
cursor . movePosition ( QTextCursor : : EndOfLine ) ;
//Simple check to see if we're in a selector scope.
const QTextDocument * doc = editor - > document ( ) ;
const QTextCursor closing = doc - > find ( QStringLiteral ( " } " ) , cursor , QTextDocument : : FindBackward ) ;
const QTextCursor opening = doc - > find ( QStringLiteral ( " { " ) , cursor , QTextDocument : : FindBackward ) ;
const bool inSelector = ! opening . isNull ( ) & & ( closing . isNull ( ) | |
2016-12-05 22:04:33 -05:00
closing . position ( ) < opening . position ( ) ) ;
2015-10-27 00:31:35 -04:00
QString insertion ;
//Reasonable attempt at positioning things correctly. This can and often is wrong, but is sufficient for our purposes.
if ( editor - > textCursor ( ) . block ( ) . length ( ) ! = 1 & & ! editor - > textCursor ( ) . block ( ) . text ( ) . isEmpty ( ) )
insertion + = QLatin1Char ( ' \n ' ) ;
if ( inSelector & & editor - > textCursor ( ) . block ( ) . text ( ) ! = " \t " )
insertion + = QLatin1Char ( ' \t ' ) ;
insertion + = name ;
insertion + = QStringLiteral ( " : " ) ;
insertion + = value ;
insertion + = QLatin1Char ( ' ; ' ) ;
cursor . insertText ( insertion ) ;
cursor . endEditBlock ( ) ;
}
else
{
cursor . insertText ( value ) ;
}
}
/// <summary>
/// Initial file dialog creation.
/// This will perform lazy instantiation since it takes a long time.
/// </summary>
void QssDialog : : SetupFileDialog ( )
{
2017-04-04 19:21:58 -04:00
# ifndef __APPLE__
2015-10-27 00:31:35 -04:00
if ( ! m_FileDialog )
{
m_FileDialog = new QFileDialog ( this ) ;
m_FileDialog - > setViewMode ( QFileDialog : : List ) ;
2018-09-30 17:20:02 -04:00
m_FileDialog - > setDirectory ( m_Parent - > m_SettingsPath ) ;
m_FileDialog - > setOption ( QFileDialog : : DontUseNativeDialog , true ) ;
2015-10-27 00:31:35 -04:00
}
2017-04-04 19:21:58 -04:00
# endif
2015-10-27 00:31:35 -04:00
}
/// <summary>
/// Present a file open dialog and retun the file selected.
/// </summary>
/// <returns>The file selected if any, else empty string.</returns>
QString QssDialog : : OpenFile ( )
{
2017-04-04 19:21:58 -04:00
# ifndef __APPLE__
2015-10-27 00:31:35 -04:00
QStringList filenames ;
SetupFileDialog ( ) ;
m_FileDialog - > setFileMode ( QFileDialog : : ExistingFile ) ;
m_FileDialog - > setAcceptMode ( QFileDialog : : AcceptOpen ) ;
m_FileDialog - > setNameFilter ( " Qss (*.qss) " ) ;
m_FileDialog - > setWindowTitle ( " Open Stylesheet " ) ;
m_FileDialog - > selectNameFilter ( " *.qss " ) ;
if ( m_FileDialog - > exec ( ) = = QDialog : : Accepted )
filenames = m_FileDialog - > selectedFiles ( ) ;
return ! filenames . empty ( ) ? filenames [ 0 ] : " " ;
2017-04-04 19:21:58 -04:00
# else
auto filename = QFileDialog : : getOpenFileName ( this , tr ( " Open Stylesheet " ) , m_Parent - > m_SettingsPath , tr ( " Qss (*.qss) " ) ) ;
return filename . size ( ) > 0 ? filename : " " ;
# endif
2015-10-27 00:31:35 -04:00
}
/// <summary>
/// Present a file save dialog and retun the file selected.
/// </summary>
/// <returns>The file selected for saving if any, else empty string.</returns>
QString QssDialog : : SaveFile ( )
{
2017-04-04 19:21:58 -04:00
# ifndef __APPLE__
2015-10-27 00:31:35 -04:00
QStringList filenames ;
SetupFileDialog ( ) ;
m_FileDialog - > setFileMode ( QFileDialog : : AnyFile ) ;
m_FileDialog - > setAcceptMode ( QFileDialog : : AcceptSave ) ;
m_FileDialog - > setNameFilter ( " Qss (*.qss) " ) ;
m_FileDialog - > setWindowTitle ( " Save Stylesheet " ) ;
m_FileDialog - > selectNameFilter ( " *.qss " ) ;
if ( m_FileDialog - > exec ( ) = = QDialog : : Accepted )
filenames = m_FileDialog - > selectedFiles ( ) ;
return ! filenames . empty ( ) ? filenames [ 0 ] : " " ;
2017-04-04 19:21:58 -04:00
# else
auto filename = QFileDialog : : getSaveFileName ( this , tr ( " Save Stylesheet " ) , m_Parent - > m_SettingsPath , tr ( " Qss (*.qss) " ) ) ;
return filename . size ( ) > 0 ? filename : " " ;
# endif
2015-10-27 00:31:35 -04:00
}