How to set .qss Style Sheet dynamically to my App - qt

I would like to apply a .qss Style Sheet to my application dynamically : there would be an option in my toolbar to select the .qss file to apply directly, .qss files already exist, and load, without closing the App, the new style.
I don't know how to manage it since :
there is no setStyleSheet in QMainWindow
it seems there is no good way to get the QApplication instance from QMainWindow (by the way, is it so silly to conceive : access of app instance from mainWindow ? it is an innocent question)
So I have this code, I don't know where to put :
if( !QFile::exists(fileName) )
return;
QFile styleFile(fileName);
if( !styleFile.open(QFile::ReadOnly))
return;
QString style( styleFile.readAll() );

As it said on comment of my question, qApp is the answer.
(A global pointer referring to the unique application object.)

Related

Qt shortcut for custom context menu

I have been reading though a couple of examples and post but I just cannot figure out how to add a shortcut to my custom context menu. My GUI has several elements. One of them is a treeView. For the elements in my treeView I would like to have a custom context menu.
My first approach was according to this tutorial here. The context menu itself worked but the shortcuts cannot work if you create the actin within the show function.
So my second approach was according to this tutorial. But still my shortcuts do not work and if I use the context menu all actions are called twice...
Since I did not find a tutorial or code example, which matches my case, I hope that someone here can explain to me how this is correctly done in theory. Adding a shortcut to an action for a custom context menu.
Where do I have to declare my action?
What needs to be the parent of the action?
On which widget do I need to call addAction?
Thanks for any hints.
Another way is to add your action also to the parent widget (or main window widget). As mentioned in this reply, adding the same action to multiple widgets is fine and it's the way QActions are supposed to be used.
Example with custom HtmlBrowser class deriving from QTextBrowser:
Ctrl+U shortcut works for this code:
HtmlBrowser::HtmlBrowser(QWidget * parent) : QTextBrowser(parent)
{
viewSourceAct = new QAction(tr("View/hide HTML so&urce"), this);
viewSourceAct->setShortcut(tr("Ctrl+U"));
viewSourceAct->setCheckable(true);
parent->addAction(viewSourceAct);
connect(viewSourceAct, &QAction::triggered, this, &HtmlBrowser::viewSourceToggle);
}
and Ctrl+U shortcut does not work with this code (same as above, but without parent->AddAction(...)):
HtmlBrowser::HtmlBrowser(QWidget * parent) : QTextBrowser(parent)
{
viewSourceAct = new QAction(tr("View/hide HTML so&urce"), this);
viewSourceAct->setShortcut(tr("Ctrl+U"));
viewSourceAct->setCheckable(true);
connect(viewSourceAct, &QAction::triggered, this, &HtmlBrowser::viewSourceToggle);
}
Curiously, parent in this case is another widget (tab widget), not MainWindow. Still, adding parent->addAction() helps. And, unlike your suggested answer, it works even when connecting action to simple methods, without slots. Works for me in Qt 5.15.0. Not quite sure why it works, though. Perhaps, the widget the action is added to must be permanent for shortcuts to work? Looks like a bug in Qt.
Thanks to Scheff's hint I got it working. I do not now if this is really the correct way but this works for me.
The action needs to be declared in the constructor of your GUI class (e.g. MainWindow):
actionDel = new QAction(tr("delete"), this);
actionDel->setShortcut(QKeySequence(Qt::Key_Delete));
connect(actionDel, SIGNAL(triggered()), this, SLOT(actionDel_triggered()));
The triggered signal needs to be connected to a slot. Hint: if you create the slot do not use on_ACTIONNAME_triggered, this will interfere with the designer and cause a connection error.
Next add the action to a custom menu
fileContextMenu = new QMenu(this);
fileContextMenu->addAction(actionDel);
And to the widget
ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->treeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showDirContextMenu(QPoint)));
ui->treeView->addAction(actionDel);
All in the constructor of your GUI class.
To show the context menu use the following code in slot used in the above connect:
QModelIndex index=ui->treeView->indexAt(pos);
// Here you can modify the menu e.g. disabling certain actions
QAction* selectedItem = fileContextMenu->exec(ui->treeView->viewport()->mapToGlobal(pos));
If you do not have a slot for an action, the action can be also handled in the context menu slot, but this does not work with shortcuts!
if(selectedItem == actionOpen){
on_treeView_doubleClicked(index);
}

How to access the set qt stylesheet properties (css like grammar), or is there an css to xml converter?

Hy,
i m working on a qt application styled by a stylesheet, set like
QApplication qApplication(argc, argv);
QFile styleFile("myStyleFile.stylesheet");
bool check = styleFile.open(QFile::ReadOnly);
qApplication.setStyleSheet(styleFile.readAll());
the important window of this application uses a QGraphicsScene (which items are not styleable with stylesheets).
But i wannt a unique look.
So the questions are:
1.) Is there a way to access the set stylesheet properties ( like getProperty("QMenu::item:selected") )?
2.) or does anyone know a css-syntax to xml-file tool? (than one could access the set properties with the qt xml/dom support)
I know that some special properties can be accessed like
QColor mainWindowbackgroundColor =
palette().color( QWidget::backgroundRole() );//Get the backgroundcolor set by stylesheet.
but i am searching for a way to access ALL set properties.
Thank you!
I think you will need to use private Qt classes to do this. This is generally not a good idea as the interfaces are internal and subject to change.
In the Qt (4.8.4) sources \src\gui\text\qcssparser_p.h header the QCss namespace is declared.
Whilst I haven't tried this, it looks like you will need to create a QCss::Parser, call parse to get a QCss::StyleSheet. This object contains the parsed data including a vector of QCss::StyleRule which matches QCss::Selector and QCss::Declaration together, have a look at the comment above the QCss::Declaration to see how it is all broken down.
Final Warning: Using Qt private interfaces is liable to cause maintenance problems - don't do it without a very good reason.

I want to handle the link clicked in a QWebView

so this is my problem : I would like to handle a clicked link in a QWebView. There is the signal
void QWebView::linkClicked ( const QUrl & url )
that is emitted when the user clicks on a link, so I could use that for my purposes, but it depends of the value of linkDelegationPolicy property that is set by default to not delegate links
but I can't change this because it's a function of QWebPage and I have a QWebView and QWebView doesn't inherit from QWebPage...so I'm really confused
Any help please! Thanks!
The QWebView has an underlying QWepPage. You can get a pointer to it using the method QWebView::page().

cannot connect to parents slot

I thought I was beginning to understand this but it seems not.
I am trying to connect together a stacked widget so that the children can send a message to the parent to tell it to change the view. The QStackedWidget is a child of the main window and its pages are promoted fomrs that I created myself. I think that's the right way to do it?
So within one of the children forms I tried the following:
// Set up a mapping between the buttons and the pages
QSignalMapper *mapper = new QSignalMapper(this);
mapper->setMapping(ui->automatedButton, 1); // Value of the index
connect(ui->automatedButton, SIGNAL(clicked()), mapper, SLOT(map()));
connect(mapper, SIGNAL(mapped(int)), ((QStackedWidget*)parentWidget()), SLOT(setCurrentIndex(int)));
But that doesn't seem to work. I click the button and nothing changes. However if i do this:
void MySelectionForm::on_automatedButton_clicked()
{
((QStackedWidget*)parentWidget())->setCurrentIndex(1);
}
Which I thought was the same as what I was doing before?
I do see on message when running which I guess is associated:
QObject::connect: Cannot connect QSignalMapper::mapped(int) to (null)::setCurrentIndex(int)
Have you checked that parentItem() is not returning NULL when you call QObject::connect()? It sounds like maybe the parent item is being set after the constructor, which would mean that parentItem() would indeed return NULL. I suspect that might be how Qt Designer rolls. If so, you would need to connect the signal/slot outside of the constructor, either in another method (one that is not called inside the constructor), or outside of the child altogether.
According to the message,
((QStackedWidget*)parentWidget()), SLOT(setCurrentIndex(int)));
leads to
(null)::setCurrentIndex(int)
which means parentWidget() is NULL.
This basically means that the forms are not a child of the QStackedWidget.
If you create your forms manually, you have to do something like this
MyForm *form = new MyForm( ui->stackedWidget );

QWebView doesn't open links in new window and not start external application for handling pdf

I am using a QWebView in this way:
QWebView *window = new QWebView();
window->setUrl(QString("my url"));
window->show();
And it works. I can see the html page I want.
The problem is this. By default if I "right click" on a link the action "Open in new window" is shown but if I click on it, nothing happens. If I "left click" on the same link it works.
So the problem is that no new windows are open by QWebView. Does anyone know why?
I have another problem. Some links are pdf file so I expect that QWebView ask me to download it or to run an application to open it. But nothing happens instead. I think the problem is related to the fact that no new windows are allowed to be opened by QWebView and not on the pdf.
Obviously I tested the page with a web browser and everything work well, so the problem is in some settings of QWebView.
Does anyone know how to make QWebView open new windows when required?
Notes:
all links are local resources.
The html links use this syntax (and they works):
Some link
The link to pdfs use this syntax (nothing happens when I click):
Some pdf
Try to handle cicks by yourself. Here is an example that can guide you. I have not compiled it though .
QWebView *window = new QWebView();
window->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);//Handle link clicks by yourself
window->page()->setContextMenuPolicy(Qt::NoContextMenu); //No context menu is allowed if you don't need it
connect( window, SIGNAL( linkClicked( QUrl ) ),
this, SLOT( linkClickedSlot( QUrl ) ) );
window->setUrl(QString("my url"));
window->show();
//This slot handles all clicks
void MyWindow::linkClickedSlot( QUrl url )
{
if (url.ishtml()//isHtml does not exist actually you need to write something like it by yourself
window->load (url);
else//non html (pdf) pages will be opened with default application
QDesktopServices::openUrl( url );
}
Note that if the HTML you are displaying may containing relative/internal links to other parts of itself, then you should use QWebPage::DelegateExternalLinks instead of QWebPage::DelegateAllLinks.
The above answer is informative but might be overwhelmed for this question.
Connecting signals to QWebPage::action(OpenLinkInNewWindow) or overriding QWebPage::triggerAction should solve this problem.

Resources