changing/replacing root Object of cascades Application - blackberry-cascades

In my application i need to implement the "first run flow" , so in this case my QML scene will be diffrent. As last thing of this flow i need to run normal flow , so i have to change root Object content.
I don't know how to achieve this.

well
i have changed my class and added two function
Q_INVOKABLE void firstRun();
Q_INVOKABLE void normalRun();
Implementation:
firstrun:
qml->setContextProperty("dateModel" , ModelsFactory::getInstance().weightModel);
qml->setContextProperty("personModel" , ModelsFactory::getInstance().personModel);
qml->setContextProperty("Application", this);
AbstractPane *root = qml->createRootObject<AbstractPane>();
app->setScene(root);
normalRun:
QmlDocument *qml;
qml = QmlDocument::create("asset:///main.qml").parent(this);
qml->setContextProperty("Application", this);
AbstractPane *root = qml->createRootObject<AbstractPane>();
Application::instance()->setScene(root);
as you can see i exposed this reference to qml
and in qml , when the flow is finished , i can call Application.normalRun()
i can do this becouse i have used Q_INVOKEBALE MAKRO in function declaration;
Hope that it will help

Related

How to declare a layout properly so I can use it anywhere in my widget

This might be a simple question for most of your experts but I've been banging my head on this for the last few hours.
I have this layout which I declare in the header file like this:
private:
QVBoxLayout *vlayout;
I then initialize it in the constructor:
QVBoxLayout *vlayout = new QVBoxLayout();
ui->mainscroll_menu->setWidgetResizable(true);
ui->mainscroll_menu->widget()->setLayout(vlayout);
vlayout->setSpacing(1);
vlayout->setAlignment(Qt::AlignTop);
vlayout->setMargin(0);
I then try to use it inside a slot for example:
void MainWidget::on_pushButton_clicked()
{
vlayout->addWidget(menuitem);
}
This will compile ok but it will fail during runtime and crash my application. Upon running the debugging, it shows that it crashes when I try to use vlayout.
If I initialize the layout inside the slot, it will then work without crashing but that comes with other issues as I have to initialize the layout for each and everytime I want to use it.
What am I doing wrong?
The problem is this line in the constructor:
QVBoxLayout *vlayout = new QVBoxLayout();
This is creating a local variable in the constructor that is shadowing the member variable by the same name. When you try to use the member variable in any other method, you end up using an uninitialized value - hence the crash.
The fix is to simply change the line to:
vlayout = new QVBoxLayout();

Open Existing QMainWindow from QMainWindow

I have a little question - I have QMainWindow with button. On click on that button I would like an existing QMainWindow to open (detail: I want open a window with QWT Plot. I mean the refreshtest project example of QWt.)
So I would like to existing Window open on button. As far I was able to open new QMainWindow, but what can I do to see MainWindow from project refreshtest?
void MyWindow::on_pushButton_1_clicked ()
{
QMainWindow *mw = new QMainWindow();
mw->show();
}
With this code, you will get a leaking pointer after leaving the scope of the method.
The reason is that the show() method is not blocking. It will post an event into the event loop queue. It will get processed in an async manner whenever the Qt event loop "gets the capacity for that".
You have several options to address this issue.
1) Qt parent/child relation
QMainWindow *mw = new QMainWindow(this);
^^^^
2) Make "mw" a class member of MyWindow
m_mw.show();
and construct it in the MyWindow constructor.
3) Use a smart pointer
QSharedPointer<QMainWindow> mw = QSharedPointer<QMainWindow>(new QMainWindow());

Working of signals and slots

I have a basic doubt about how signals and slots actually work. Here's my code segment.
finddialog.cpp :
#include "finddialog.h"
#include <QtGui>
#include <QHBoxLayout>
#include <QVBoxLayout>
FindDialog::FindDialog(QWidget *parent) : QDialog(parent) {
//VAR INITIALIZATIONS
label = new QLabel(tr("Find &what:"));
lineEdit = new QLineEdit;
label->setBuddy(lineEdit);
caseCheckBox = new QCheckBox(tr("Match &case"));
backwardCheckBox = new QCheckBox(tr("Search &backward"));
findButton = new QPushButton("&Find");
findButton->setDefault(true);
findButton->setEnabled(false);
closeButton = new QPushButton(tr("&Quit"));
//SIGNALS & SLOTS
connect (lineEdit, SIGNAL(textChanged(const QString&)),this, SLOT(enableFindButton(const QString&)));
connect (findButton, SIGNAL(clicked()), this, SLOT(findClicked()));
connect (closeButton,SIGNAL(clicked()), this, SLOT(close()));
//Layout
QHBoxLayout *topLeftLayout = new QHBoxLayout;
topLeftLayout->addWidget(label);
topLeftLayout->addWidget(lineEdit);
QVBoxLayout *leftLayout = new QVBoxLayout;
leftLayout->addLayout(topLeftLayout);
leftLayout->addWidget(caseCheckBox);
leftLayout->addWidget(backwardCheckBox);
QVBoxLayout *rightLayout = new QVBoxLayout;
rightLayout->addWidget(findButton);
rightLayout->addWidget(closeButton);
rightLayout->addStretch();
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addLayout(leftLayout);
mainLayout->addLayout(rightLayout);
//Complete window settings
setLayout(mainLayout);
setWindowTitle(tr("Find"));
setFixedHeight(sizeHint().height());
}
//Function Definition
void FindDialog::findClicked() {
QString text = lineEdit->text();
Qt::CaseSensitivity cs = caseCheckBox->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive;
if(backwardCheckBox->isChecked())
emit findPrevious(text, cs);
else
emit findNext(text,cs);
}
void FindDialog::enableFindButton(const QString &text1) {
findButton->setEnabled(!text1.isEmpty());
}
With this code, how does the compiler know what is passed to enableFindButton(QString &) function. There are no function calls to enableFindButton(). In the connect statement there is a reference to enableFindButton() but isn't that more like a prototype because we are not providing the name of the variables to work with in its arguments?
connect (lineEdit, SIGNAL(textChanged(const QString&)),this, SLOT(enableFindButton(const QString&)));
Here only (const QString &) is the argument and a variable is not given. How does the application know what its argument is without passing it explicitly?
void FindDialog::enableFindButton(const QString &text1) {
findButton->setEnabled(!text1.isEmpty());
}
Here also &text1 is a reference argument. But to what ? I don't understand anything now after typing this all!
:-|
Qt is generating the code that makes it work when you build the project.
SIGNAL, SLOT, etc are preprocessor macros defined in qobjectdefs.h
These are then picked up by moc in QT when you build your project, and all the code required is generated, then compiled.
A decent page that explains this in more detail can be found here
C++ source code is processed by Qt meta object compiler (moc). It generates 'signatures' strings for QObject slots. Signatures contain method name and arguments (types, arguments' names do not matter in signatures). Whenever signal is emitted a signature match is performed directly (in case of direct connections) or in the event loop (for queued connections), and corresponding method is called. Moc compiler generates all necessary code that will match signatures and call the methods. If interested, look inside of one of those *.cxx files generated.

Qt - Connected but doesn't work

I have problem with one class in my project, after click appears new window with QTableWidget and QPushButton, after clicking the button I should have "test" on stdout, but nothing shows, here are parts of this code:
Header:
class ClientsSelector : public QWidget {
Q_OBJECT
public:
ClientsSelector(InvoiceTab* parent);
QWidget *window;
private:
QPushButton *accept;
public slots:
void loadData();
Constructor:
window = new QWidget();
layout = new QGridLayout();
layout->addWidget(table, 0, 0);
/*code*/
accept = new QPushButton(QString::fromUtf8("Load data"));
connect(accept, SIGNAL(clicked()), this, SLOT(loadData()));
layout->addWidget(accept, 0, 1);
/*code*/
window->setLayout(layout);
window->show();
Method:
void ClientsSelector::loadData() {
QTextStream std(stdout);
std << "test" << endl;
}
I have not even one warning nor error. I have nothing on stdout, it looks like button was connected to wrong object(?)
How do you instantiate ClientsSelector? Isn't it a singleton or global variable by chance? Try moving the connect call to a separate init function which is called after the ClientsSelector constructor. It helped me in similar WTF situations. It has something to do with the fact that each QObject inheritor has a static metadata member and you can't be sure about when it is fully initialized until the constructor finishes. connect won't work without that metadata.
See for example here: http://www.qtcentre.org/threads/9479-connect-in-constructor
If still lost, go through this checklist. Qt signals are so easy to use, everybody sometimes forgets it also has some requirements.
Seems like you forgot a closing " on the test printout.
Try using
qDebug() << "test";
instead of QTextstream
You can do following to make sure that the connection was made and slot is called.
connect function returns status of connection. Check if the connection was made properly.
put a breakpoint and see if the loadData() is called when button is pressed.
This might help to find the cause.

how to translate string added dynamicaly in Qapp with Qtranslator?

i trying to created a Qt application multilanguage with Qt linguist.
I place this code in an function of my MainWindow :
translator.load(":/lang/English");
qApp->installTranslator(&translator);
ui->retranslateUi(this);
With the QTranslator declare in my MainWindow.h and all my string i want translate enclose by tr() . But with that, all QObject added dynamicaly by the code of my MainWindow.cpp, for example the title of a QTableWidget, are not translated.
If i place an other translator in my main.cpp, all my string are translate but i must created language button in my application and so i can't place translator in main.cpp.
Do you have an idea to help me?
Thx for your answers.
Gat
When you add a translation in your application using qApp->installTranslator(& aTranslator) then all the following calls to QObject::tr() (and similar functions) will look up in the translator for a translated text. So you should call retranslateUi() after qApp->installTranslator(). Actually you might event not call it there, you may reimplement QWidget::changeEvent() and intercept any QEvent::LanguageChange event.
void MainWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
// Someone called qApp->installTranslator() with a new translation.
// Let's update the user visible strings.
// This function was created by uic from the Designer form.
// It translates all user visible texts in the form.
ui->retranslateUi(this);
// This function must be written by you. It translates other user visible
// texts that are not in the form. See down for an example.
this->retranslateUi();
break;
default:
break;
}
}
ui->retranslateUi() just calls QObject::tr() for each user visible string in the ui. It is called automatically at the end of setupUi() and populates the form's widgets with translated text (have a look, it is defined by uic in ui_MainWindow.h file). You may want to take a similar approach with other user visible texts, like the title of a QTableWidget. All the strings are set in a function (named perhaps retranslateUi() for consistency) which is called at application starts (or, better, after the relevant widgets are created) and every time a new translations is loaded.
MainWindow::MainWindow(QWidget * parent)
: QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Creates other widgets, but do not set their user visible texts.
tableWidget = new QTableWidget(this);
...
someControl = new QLineEdit(this);
someOtherControl = new QSpinBox(this);
someModel = new MyModel(this);
...
// Ok, *now* we set their texts.
this->retranslateUi();
}
...
void MainWindow::retranslateUi()
{
// This function will be called (either manually or automatically by
// `changeEvent()`) when a new translator has installed, hence all the `tr()`
// calls will return the right translation for the last installed language.
QStringList labels;
labels.append(tr("First column"));
labels.append(tr("Second column"));
labels.append(tr("Third column"));
tableWidget->setHorizontalHeaderLabels(labels);
someControl->setText(tr("Control name"));
someOtherControl->setText(tr("Other control name"));
// Perhaps you have a model that need to be retranslated too
// (you need to write its `retranslateUi()` function):
someModel->retranslateUi();
...
}
Also, please note that if you are doing something like
void MainWindow::someFunction()
{
...
QTranslator translator;
translator.load(":/lang/English");
qApp->installTranslator(& translator);
...
}
as soon as that function returns the variable translator gets destroyed, so next time QObject::tr() is called the address stored with qApp->installTranslator(& translator) will be invalid. So you must allocate translator on the heap with new (and possibly deleting it with delete when you do not need it anymore). An exception is if you are doing that in main() before calling QCoreApplication::exec() since that function is blocking and will not return until application is closed.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
...
QTranslator translator;
translator.load(":/lang/English");
app.installTranslator(& translator);
...
app.exec(); // This function will return only on application's exit.
// Hence `translator` will outlive the application, there is
// no need to worry about it.
}

Resources