How to know that widget is currently is running in Qt Designer - qt

How can I in code of the custom Qt widget know that it is currently instantiated in Qt designer?
Use case:
I build a complex custom widget that has several child widgets like QPushButton, QLabel etc.
As application logic require, when widget is created most of those sub component are not visible but in design time when I put it on a form I would like to see them.
To be able to play with style sheet at design time.
Currently what I get is a empty is only a result of constructor - minimal view (actually empty in my case).
What I am looking for is to be able to do something like
MyQWidget::(QWidget *parent)
{
....
if(isRunningInDesigner())
{
myChildWidget1->setVisible(true);
myChildWidget2->setVisible(true);
myChildWidget3->setVisible(true);
}
else
{
myChildWidget1->setVisible(false);
myChildWidget2->setVisible(false);
myChildWidget3->setVisible(false);
}
....
}
So what should I put in to this bool isRunningInDesigner() ?

From the Qt Designer manual:
To give custom widgets special behavior in Qt Designer, provide an implementation of the initialize() function to configure the widget construction process for Qt Designer specific behavior. This function will be called for the first time before any calls to createWidget() and could perhaps set an internal flag that can be tested later when Qt Designer calls the plugin’s createWidget() function.
Those are methods from the QDesignerCustomWidgetInterface plugin interface. In short: you tell the widget to behave differently when Qt Designer asks your plugin to create instances of your custom widget.

Related

Qt5 dynamic translation issues for C++ defined properties

I am currently working on somebody else code and I need to fix a bug linked with dynamic translation.
When the language is changed, the Loader is reloaded, it works but it generates unwanted effects (including the bug mentioned above).
So I tried to look for a way to dynamically change the translation without reloading everything.
I added m_engine->retranslate() in my switchLanguage function and this works perfectly, but only for texts directly defined in QML files. The thing is there is also a lot of text defined with setContextProperty in the C++ main controller class, and for them, it doesn't work at all (which seems pretty normal since m_engine is a QQmlApplicationEngine).
I don't see how I can simply force these texts to retranslate too. I have them in pretty much every controller function and they are used by different QML files. I am afraid that there will be no other choice but to change completely the way translation is managed. I hope advanced programmers can help me with this.
Other information:
I work with 5.13.0 version of Qt.
I don't use Designer and cannot use ui.retranslateUi().
It's hard to tell how your main controller class looks like, so here is a short general answer.
You can install an eventFilter and listen for LanguageChange.
In constructor of "main controller class", add this:
auto *core = QCoreApplication::instance();
if(core != nullptr)
{
core->installEventFilter(this);
}
Then add a function to your class:
bool MainControllerClass::eventFilter(QObject *watched, QEvent *event)
{
Q_UNUSED(watched);
if(event->type() == QEvent::LanguageChange)
{
//set properties again or emit property changed signals
}
}

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);
}

Best way to propagate variables from QWizard to the pages

Iam looking for a good and easy way to propagate a variable, in my case a string from QWizard on to the pages. I have tried to use fields but without registering it this won't work.
So on the third page of my wizard I need a path to a folder where some data can be found, this is used to init a QFileDialog. This QString is not directly coupled to a QWidget. So I can not call registerField on it.
pseudo code:
// setup wizard:
QMyWizard wiz;
QString s = "c:\\";
wiz.SetFolder(s);
I can of course in the Wizard SetFolder function access the page by looking it up and casting but I find this quite ugly. So Is there a good solution to pass on global variable without registering to widgets?
Thanks!
I'll answer my own question.. I did not find handy functionality in the wizard code itself. Now I am using the ability of any derived class from QObject to hold properties in a map from string to QVariant. In the wizard pages you can acces the properties of the parent now.
http://qt-project.org/doc/qt-4.8/qobject.html#setProperty

Qt Form and main.cpp communication

i have a Qt project with mainwindow (GUI Application)
how can i communicate with my main via my form?
for example
increase variable (which there's in my main) while button a click in my form
i have make a project in C which its in console application. works fine, and now i make another project which contains ui form with same code. and i want to make communication between form and main function
You can use the Qt signal/slot functionality.
Example:
// on mainwindow.cpp. Delcare onButtonClicked as a slot() on the header
void onButtonClicked()
{
++myVar;
}
connect(myButton, SIGNAL(clicked()), this, SLOT(onButtonClicked());
Reference docs.

global event catch for QEventfilter class

I want to add a help webpage for my Qt Application. The user can use the Qt::WhatsThis "tooltip" to have a explanation about the topic and a URL to a webpage. I edit the WhatsthisTooltips with the Qt Designer and have it language indepentend.
Now I create a "LinkFilter" class for filtering, install it in the viewclass and react on the QEvent::WhatsThisClicked event. This works fine.
Now i would catch every QEvent::WhatsThisClicked in my application, but i looks really messy to install it on really every dialog/view/action/widget. This there some kind of global eventHandler, were I can install my "LinkEvent"class? There must be a nice Qt style way for solving this.
For installing the EventFilter I strongly followed this video-tutorial http://youtu.be/DHgbYxpZkbg
http://qt-project.org/doc/qt-4.8/qapplication.html#notify
Essentially you need to subclass QApplication and override this function. Then you can check if it's the type of event you're looking for and act accordingly.

Resources