Is there a way to enable qss stylesheets parts per OS? - qt

Is there a way to enable/disable parts of a qss stylesheet per OS (platform). So that I can enable one font for MacOS, another for Windows.
I could set dynamic properties for a particular widget
this->setProperty("qsysKernelType", QSysInfo::kernelType());
this->setProperty("qsysCurrentCpuArchitecture", QSysInfo::currentCpuArchitecture());
this->setProperty("qsysBuildCpuArchitecture", QSysInfo::buildCpuArchitecture());
this->setProperty("qsysProductType", QSysInfo::productType());
but that only works with one widget, not the whole hierarchy.

I don't believe there is a standard simple way for this.
But you always can hold your CSS resources for different platforms in different files, and use ifdefs, to load it, like:
this->setStyleSheet(QFile(
#ifdef Q_OS_WIN
":/style/win.css"
#else // add more, if you need
":/style/mac.css"
#endif
).readAll());
Or simply use two hardcoded strings with ifdefs.

Actually we are now using a combintion of Youw's answer and the approach mentioned in the question.
For conditional qss checks we set the properties for a particular widget or widget tree.
void CStyleSheetUtility::setQSysInfoProperties(QWidget *widget, bool withChildWidgets)
{
Q_ASSERT_X(widget, Q_FUNC_INFO, "Missing widget");
if (!widget->property("qsysKernelType").isValid())
{
widget->setProperty("qsysKernelType", QSysInfo::kernelType());
widget->setProperty("qsysCurrentCpuArchitecture", QSysInfo::currentCpuArchitecture());
widget->setProperty("qsysBuildCpuArchitecture", QSysInfo::buildCpuArchitecture());
widget->setProperty("qsysProductType", QSysInfo::productType());
}
if (withChildWidgets)
{
for (QWidget *w : widget->findChildren<QWidget *>(QString(), Qt::FindDirectChildrenOnly))
{
CStyleSheetUtility::setQSysInfoProperties(w, true);
}
}
}

Related

Which CSS selector is used when a DragOver event is detected?

I am creating a custom RowFactory for my TableView to accept drag-and-drop files. I want to update the style of the specific Row when an acceptable DragOver event is detected.
Using :hover obviously won't work because that would apply even if the user is not dragging anything.
The end goal is simply to make it visually clear which row the user is about to drop the items onto.
Is there a selector I can use in my stylesheet to handle this? I could not find anything in the JavaFX CSS Reference Guide.
I can currently work around this by defining my own StyleClass and adding it in the setOnDragOver() method:
setOnDragOver(event -> {
// Determine if the dragged items are files
if (!this.isEmpty() && event.getDragboard().hasFiles()) {
event.acceptTransferModes(TransferMode.LINK);
this.getStyleClass().add("dragging");
}
});
However, attempting to remove the class when exiting does not seem to work:
setOnDragExited(event -> this.getStyleClass().remove("dragging"));
Edit: I should also clarify that each row may have other styles applied to them (based on several factors) and would want to ADD a style to the row when being dragged over, not replace all the rest)
As mentioned by #kleopatra, working with custom PseudoClass can work for you.
/**
* Interface to keep all custom pseudo classes.
*/
public interface Styles{
/** Dragged pseudo class. */
public static final PseudoClass DRAGGED_PSEUDOCLASS = PseudoClass.getPseudoClass("dragged");
}
In your code:
setOnDragOver(event -> {
if (!this.isEmpty() && event.getDragboard().hasFiles()) {
event.acceptTransferModes(TransferMode.LINK);
this.pseudoClassStateChanged(Styles.DRAGGED_PSEUDOCLASS,true);
}
});
setOnDragExited(event -> this.pseudoClassStateChanged(Styles.DRAGGED_PSEUDOCLASS,false));
In CSS:
.table-row-cell:dragged{
-fx-background-color:$custom-color;
}

Add CSS property in Angualr2 with MetaWidget

I am trying to add CSS when clicked on row or column of table, Following is code
private rowClicked(event: Event): void {
event.srcElement.setAttribute("class", "highlighted");
}
But it's not working as accepted. Am I doing in wrong way, Is there any alternate way to add CSS dynamically?
Note-
Is there any way to add CSS using dom element, my table has thousands of data and to create this table, I have used MetaWidget.
The easiest way to your problem is to assign a unique ID to each included element together with employing another variable to hold selected ID. The logic to turn on my-class CSS class will now be based on the selected ID.
Your new HTML template:
<div (click)="rowClicked(1);" [ngClass]="{'my-class': highlightedDiv === 1}">
> I'm a div that gets styled on click
</div>
Your rowClicked function:
highlightedDiv: number;
rowClicked(newValue: number) {
if (this.highlightedDiv === newValue) {
this.highlightedDiv = 0;
}
else {
this.highlightedDiv = newValue;
}
}
A working demo is here.
More can be found here.
You are using MetaWidget, but you are not mentioning what version you are using.
If you want work with Angular2 and MetaWidget, you should have use a compatible version of MetaWidget, which can be found here-
https://github.com/AmitsBizruntime/MetawidetA2
Using this library will be the best solution for you.
Re-
Angular does not work based on DOM, it works based on Component.
If you like to work on DOM, then you should include jQuery in tour angular project from here-
How to use jQuery with Angular2?
But it is not a good practice.

Using variables in qt StyleSheets

Is there any possibility of giving variable name to hex/rgb numbers in .qss file . For eh
myColor = #FFCC08
QPushButton { background-color: myColor;}
So that i can define the variable at the top of the stylesheet and use the variable name whereever required instead of using the hex code. Also if i need to change the color then i have to change in one place and it will be reflected throught the file.
I also searched for Saas but don't know how it can be used in qt.
Thanks :)
You could build your own tiny Sass quite easily:
1.Create a text file with definitions of variables. Use simple format like this:
#myColor = #FFDDEE
#myColor2 = #112233
#myWidth = 20px
2.In qss file use variable names:
QPushButton {
background-color: #myColor;
min-width: #myWidth;
}
3.Open both files and for each variable in definition file change its occurrence in qss file with the value (string) from the definition file. It is a simple string replacement.
4.Apply the preprocessed qss in the app.
This is the simplest solution. You can change both definition file and qss file outside the app and apply it without recompilation of code.
What you're trying to accomplish simply isn't possible using pure Qt style sheets.
You can achieve a similar effect by modifying and reloading your style sheets from within your C++ code, for example:
QString myColor = "#FFCC08";
QString styleSheet = "QPushButton { background-color: %1;}";
...
myWidget->setStyleSheet( styleSheet.arg(myColor) );
Unfortunately this has several drawbacks (inability to preview in designer, changing code rather than a style sheet), but it's about as close as you can get to what you're trying to achieve with Qt.
Another way to accomplish this would be to use Dynamic Properties. This would let you easily assign multiple properties to an object or group of objects, sort of like assigning a css class to an object.
https://wiki.qt.io/Dynamic_Properties_and_Stylesheets
For example, in your UI file, you could add a string dynamic property "colorStyle" with a value of "myStyle1".
Your stylesheet would look like:
QPushButton[colorStyle='myStyle1'] {
background-color: #FFCC08;
... any other style changes...
}
Any QPushButton you assign 'myStyle1' will follow the stylesheet if you set it globally.
Here is a solution using sass. First, install the python bindings:
pip install sass
Then, use it:
import sys
import sass
app = QApplication(sys.argv)
# Create your sass style sheet (you can also write this in a file and load the file)
style = '''
$bg-dark: #292929;
QPushButton {
color: red;
background-color: $bg-dark;
}
'''.encode('utf-8')
# Compile Sass to CSS
style = sass.compile_string(style).decode()
# And set it to your app
app.setStyleSheet(style)
I have similar, but different problem. In my case, I want to connect window size to QCheckBoxIndicator. Code below won't work due to css already use the {}.
self.checkBoxYes.setStyleSheet('''
QCheckBox::indicator {
width: {sz} px;
height: {sz} px;
}
'''.format(sz=rel_sz))
However, workaround can be achieved using old-formatted string below:
def resizeEvent(self, a0) -> None:
rel_wdth = self.width() // 20
rel_hgh = self.height() // 10
rel_sz = str(min(rel_hgh, rel_wdth))
self.checkBoxYes.setStyleSheet('''
QCheckBox::indicator {
width: %s px;
height: %s px;
}
''' %(rel_sz, rel_sz))
return super().resizeEvent(a0)

CSS selector for custom Qt class

I created a "Slider" subclass of QWidget and would like to be able to style it with Qt's stylesheets. Is there a way to declare the widget to Qt application so that this setting in the application stylesheet is applied to all sliders ?
Slider { background-color:blue; }
Or if this is not possible, can I use a class like this ?
QWidget.slider { background-color:blue; }
The widgets have a "className()" method that is accessible via the meta object. In my case this is:
slider.metaObject()->className();
// ==> mimas::Slider
Since the "Slider" class is in a namespace, you have to use the fully qualified name for styling (replacing '::' with '--'):
mimas--Slider { background-color:blue; }
Another solution is to define a class property and use it with a leading dot:
.slider { background-color:blue; }
C++ Slider class:
Q_PROPERTY(QString class READ cssClass)
...
QString cssClass() { return QString("slider"); }
While on the subject, to draw the slider with colors and styles defined in CSS, this is how you get them (link text):
// background-color:
palette.color(QPalette::Window)
// color:
palette.color(QPalette::WindowText)
// border-width:
// not possible (too bad...). To make it work, you would need to copy paste
// some headers defined in qstylesheetstyle.cpp for QRenderRule class inside,
// get the private headers for QStyleSheetStyle and change them so you can call
// renderRule and then you could use the rule to get the width borders. But your
// code won't link because the symbol for QStyleSheetStyle are local in QtGui.
// The official and supported solution is to use property:
// qproperty-border:
border_width_ // or whatever stores the Q_PROPERTY border
And finally, a note on QPalette values from CSS:
color = QPalette::WindowText
background = QPalette::Window
alternate-background-color = QPalette::AlternateBase
selection-background-color = QPalette::Highlighted
selection-color = QPalette::HighlightedText

Addressing in CSS in Flex: Buttons in RichTextEditor only?

I want to change the font characteristics for buttons in the toolbar of the RichTextEditor, but I want them to be different than other buttons in my application. Is there any way to do this with just CSS? I know that I can do it with setStyle if necessary...
One way to do it, since the RichTextEditor's sub-components are declared in MXML and are therefore publicly accessible, is to assign their styleName properties individually at runtime (after the container's creationComplete event fires, to be sure the editor and all its children have been created), like so:
<mx:Style>
.myRTECombo
{
color: #FF0000;
}
</mx:Style>
<mx:Script>
<![CDATA[
private function creationCompleteHandler(event:Event):void
{
rte.fontFamilyCombo.styleName = "myRTECombo";
rte.fontSizeCombo.styleName = "myRTECombo";
}
]]>
</mx:Script>
<mx:RichTextEditor id="rte" />
The Flex docs don't call out the subcomponents ("boldButton", "fontSizeCombo", et al) by ID, but the component's source is available for viewing, so you should be able to get all the info you need from the source code itself. Since I use FlexBuilder, I usually use the Eclipse Ctrl+click shortcut, on the tag/class name, to jump into the associated class-definition file, but you can also open the source file directly at [installDir]/sdks/[version]/frameworks/src/mx/RichTextEditor.mxml to have a look for yourself.
I'm sure there are other approaches (setStyle being one, although its explicit use is generally discouraged for performance reasons), but this ought to work out for you. One thing to note, though, as you'll see when you dig into the component's source, is that many of the buttons in the default button set actually use PNGs (e.g., icon_style_bold.png), not text, which is why my example includes a reference to the ComboBox instead, so you can see how the color changes apply; if you want to change the look of the buttons, be aware they're using the styleable icon property, not font-style settings, for their look and feel.
Hope it helps!
Thanks #Christian Nunciato! This is my final code, in my component that is a RichTextEditor (extends it). In the creationComplete, I call this
private function setUpStyleNames():void {
setUpStyleNamesInner(toolbar.getChildren());
setUpStyleNamesInner(toolBar2.getChildren());
}
private function setUpStyleNamesInner(children:Array):void {
for each (var child:DisplayObject in children) {
if (child is UIComponent) {
UIComponent(child).styleName = "rteInnards";
}
}
}
and then in my styleSheet, I have this
.rteInnards {
color: #FF0000;
fontSize: 25px;
}
Awesome. Thanks again!

Resources