Creating a Symbian's like application menu at S60 - qt

I wanted to make an app which is when started it shows a menu. It is just like when you open a Messaging app in S60. Here is a screenshot.
How do I make it? I have tried to make the centralWidget of the QMainWindow as QMenu, and adding QAction to the QMenu. But when I'm running it, the app don't show anything. And I have tried to make the QMenu using QMenuBar. And it is show okay. But I can't use the up/down key to select menu in the device. And when I press the options key (Qt::PositiveSoftKey), the menubar shows up too. And I didn't even add that to menuBar() which is owned by QMainWindow.
Here is my first code:
QAction* act1= new QAction(tr("act1"),this);
QObject::connect(tes,SIGNAL(triggered()),this,SLOT(close()));
QAction* act2= new QAction(tr("act2"),this);
QObject::connect(tes,SIGNAL(triggered()),this,SLOT(close()));
QMenu* menu = new QMenu(this);
menu->addAction(act1);
menu->addAction(act2);
setCentralWidget(menu);
And it shows nothing at the apps.
And here is my second try:
Qt Code: Switch view
QAction* act1= new QAction(tr("act1"),this);
QObject::connect(tes,SIGNAL(triggered()),this,SLOT(close()));
QAction* act2= new QAction(tr("act2"),this);
QObject::connect(tes,SIGNAL(triggered()),this,SLOT(close()));
QMenuBar* menubar = new QMenuBar(this);
QMenu* menu = menubar->addMenu(tr("menu"));
menu->addAction(act1);
menu->addAction(act2);
setCentralWidget(menu);
It shows the menu. But when I deploy to the device, I can't use the keypad to select the menu. And at the simulator, if I click other place than the QAction item, the menu lost.
I am using another approach by using QPushButton with Vertical Layout. Here is the code:
QWidget* centralWidget = new QWidget(this);
QScrollArea* scrollArea = new QScrollArea(this);
scrollArea->setWidget(centralWidget);
scrollArea->setWidgetResizable(true);
setCentralWidget(scrollArea);
QVBoxLayout* centralLayout = new QVBoxLayout(centralWidget);
QPushButton* button1 = new QPushButton(tr("button 1"));
QPushButton* button2 = new QPushButton(tr("button 2"));
centralLayout->addWidget(button1);
centralLayout->addWidget(button2);
centralLayout->setContentsMargins(0,0,0,0);
button1->setFocus();
Here it's look:
Okay, and that's look good enough. But if that's have 8 button. If it is only have 2 button, it looks like this:
looks kind of weird, huh? Any way to prevent this?

For me, the UI that you're trying to replicate is a list of options, so, why don't try to create the UI based on a list widget?
Asumming that you're going to use a list, you have to options from which you have to choose based on your needs and your app requirements:
Qt Widgets: Available in all the Qt supported Plataforms. Created for desktop and works great on it, but in feel strange on mobile devices. Take a look to the QListWidget and QListView.
Qt Quick: It isn't available for S40 phones or S60 3rd edition, not available for non-touch phones, basically. Created for "touch enabled UI's", it doesn't offer a stable set of widgets (buttons, comboboxes) yet, but it offers a set of primitives (like rectangles or images) that gives you a lot of freedom to create your UI's and it looks pretty good. I think that this is what Lucian used to create the UI from his answer.
This examples could be of particular interest: http://doc.qt.io/archives/qt-4.7/all-examples.html
Run the QtDemo to see all the examples live!
Hope it helps!
EDIT: Adding example of QListWidget
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
for(int i=0; i<10; i++) {
QListWidgetItem *item = new QListWidgetItem(QIcon("Qt.png"), QString("Item %1").arg(i));
ui->listWidget->insertItem(i, item);
}
ui->listWidget->setIconSize(QSize(64, 64));
connect(ui->listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(onItemClicked(QListWidgetItem*)));
}
void MainWindow::onItemClicked(QListWidgetItem *item)
{
QMessageBox::information(this, "", QString("%1 pressed").arg(item->text()));
}

You have all the freedom in the world to create your layout the way you like. Want those buttons closer together? Want them centered in the view?
The attached image took me 30 seconds to create and looks already decent (according to my pour designer skills).

Related

QAction doesn't show QMenu

I'm creating my UI from Qt Designer and it generares this code:
toolBar = new QToolBar(MainWindow);
QIcon icon;
icon.addFile(QStringLiteral(":/main"), QSize(), QIcon::Normal, QIcon::Off);
MainWindow->addToolBar(Qt::TopToolBarArea, toolBar);
actionConvert = new QAction(MainWindow);
actionConvert->setObjectName(QStringLiteral("actionConvert"));
actionConvert->setIcon(icon);
toolBar->addAction(actionConvert);
Now, back in my frame code:
QMenu *menuAdd = new QMenu (this);
menuAdd->addAction (tr("&Files..."));
menuAdd->addAction (tr("&Directory..."));
ui->actionConvert->setMenu (menuAdd);
When I run the application I can see the qaction in the toolbar even the arrow pointing down, which indicates that there is a menu, but when I click it, the menu doesn't appear...any ideas?
There does not seem to be anything wrong with your example code.
It's possible that the reason you aren't seeing the menu is that you need to press and hold the button for a few seconds in order for the menu to appear. A single click will just execute the button's normal action.
See: QToolButton::ToolButtonPopupMode.
You should add menu with menuBar() method as in my case:
void MainWindow::ueInitMenu()
{
this->ueSetCodeRegisterPlacesAction(new QAction(tr("Places"),
this));
this->ueCodeRegisterPlacesAction()->setShortcut(tr("Ctrl+P"));
this->ueCodeRegisterPlacesAction()->setStatusTip(tr("Shows places code register"));
connect(this->ueCodeRegisterPlacesAction(),
SIGNAL(triggered()),
this,
SLOT(ueSlotShowPlacesView()));
this->ueSetCodeRegisterMenu(this->menuBar()->addMenu(tr("Code register")));
this->ueCodeRegisterMenu()->addAction(this->ueCodeRegisterPlacesAction());
} // ueInitMenu
especialy the line:
this->ueSetCodeRegisterMenu(this->menuBar()->addMenu(tr("Code register")));
so in your case:
this->menuBar()->addMenu(tr("System menu");
and then add actions. Also take a look at Menus Example.

How to undock tab with osgViewer from QTabWidget?

I want to undock a QWidget from a QTabWiget (is set as centralWidget). The tab contains some Open Scene Graph content (OpenGL Window). When removing the Tab from the list and putting it into a new Dialog Window (=> undocking from tab) the scene data seems to be corrupt. It works with "standard widgets" but the osg seems to forget the scene.
Surprisingly, undocking works when using a QDockWidget (scene is visible after undocking the window).
Anyone knows how to undock a tab without corrupting the osgViewer?
Code called for to undock from tab and show in new dialog window:
QWidget* gv = // points to an osgViewer in a qt widget
QDialog* dlg = new QDialog(this);
dlg->setWindowTitle("hello earth");
QHBoxLayout* pMainLay = new QHBoxLayout;
gv->setMinimumSize(100,100);
gv->setGeometry(100,100,300,300);
pMainLay->addWidget(gv);
dlg->setLayout(pMainLay);
ui->tabWidget->removeTab(0); // removes the tab at position 0 (docked window)
dlg->show(); // should show the undocked dialog
There is nothing to see in the new dialog. Did I missed something?
How to "copy" the osg view properly into a new widget/dialog? Should I use a composite viewer for this kind of task? It seems there is not even the empty osg view visible (no blue canvas)...
It could be that something's going screwy when you add the osgViewer to another widget before removing it from the QTabWidget. Changing the order might help.
QWidget* gv = // points to an osgViewer in a qt widget
ui->tabWidget->removeTab(0); // removes the tab at position 0 (docked window)
QDialog* dlg = new QDialog(this);
dlg->setWindowTitle("hello earth");
QHBoxLayout* pMainLay = new QHBoxLayout;
pMainLay->addWidget(gv);
dlg->setLayout(pMainLay);
dlg->show(); // should show the undocked dialog

connect from a QTab (in a QTabWidget) back to QMainWindow

The main Part of my Application is a Systray-Menu. For maintenance there should be a normal GUI.
My Problem is that now I have to create two Signal/Slot-Connections back to the MainWindow from each Tab. This is for minimizing the GUI and to update the Menu. I don't know how to do this.
I tried to connect with this->parent->parent from the ManageSession and ui_manag->session_ui->minimizeButton from MainWindow. I have a little knot in my head and am asking for help. Or should I re-think my design? I´m using only QtCreator 2.6.1 with Qt 4.8.4.
Screenshots of the GUI-Elements
This is the mainwindows.cpp:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle(QCoreApplication::applicationName());
QWidget *mainWidget = new QWidget;
QTabWidget *ui_manag = new ManageTab;
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(ui_manag);
mainWidget->setLayout(mainLayout);
setCentralWidget(ui_manag);
ui_manag->setCurrentIndex(0);
//Here comming Code to setup a TrayIcon, the Database and the Menus
}
The Tab is completely generated by the Designer:
ManageTab::ManageTab(QWidget *parent) :
QTabWidget(parent),
tab_ui(new Ui::ManageTab)
{
tab_ui->setupUi(this);
}
For each Setting I use the same GUI with multiple inheritance:
ManageSession::ManageSession(QWidget *parent) :
QWidget(parent),
session_ui(new Ui::ManageWidget)
{
session_ui->setupUi(this);
session_ui->manageLabel->setText(tr("Manage Session"));
connect(session_ui->addButton, SIGNAL(clicked()), this, SLOT(addButton_clicked()));
connect(session_ui->editButton, SIGNAL(clicked()), this, SLOT(editButton_clicked()));
connect(session_ui->deleteButton, SIGNAL(clicked()), this, SLOT(deleteButton_clicked()));
}
//Here follows the Functions for manipulating the TableView
// and emmiting a Signal to Update the Menu
Let's remake it in an answer (so you can accept it, hehe. j/k, to long for a comment):
First. As i said in comment:
You are inheriting without specifying access. So it defaults to private. That's why
ui_manag->session_ui->minimizeButton
wont allow you to access the button.
Second.
parent is a method, so It's: this->parent()->parent() or just parent()->parent() ;)
Again, it probably needs to inherit public. Not sure, tho.
That should work then.

How can I add another tab that looks exactly like the first one (like in a browser)?

I have a browser made in Qt and a I have a tabwidget with one tab (which has a label, lineedit and a webview). I want to add others that look like the first one (have label, lineedit and webview).
How can I do this?
I don't know of any way to "clone" or duplicate an existing tab or widget, so I believe you'll need to code the tab contents yourself (i.e. not through the designer).
If all you need are a QLabel, a QLineEdit and a QWebView, that's not very complex. The idea would be to:
create a custom widget (inheriting from QWidget directly, or from QFrame)
lay out the contained widgets in the fashion you want in its constructor
add as many tabs as you want, when you want them, via the QTabWidget.addTab function.
The Tab Dialog example has everything you need - it's actually more complex than what you need because it uses different widgets for each tab. You can get away with a single widget.
If you wonder how to do the layout, and you're satisfied with what you got from the designer, you can inspect the generated (.moc) files. You'll see what layouts it uses, and you can replicate that in your own code.
Skeleton widget:
class BrowserTab : public QWidet
{
Q_OBJECT
public:
BrowserTab(QUrl const& home, QWidget *parent = 0);
void setUrl(QUrl const& url);
private:
QWebView *web;
QLabel *title;
QLineEdit *urlEdit;
};
BrowserTab::BrowserTab(QUrl const& home, QWidget *parent)
: QWidget(parent)
{
urlEdit = new QLineEdit(this);
title = new QLabel(this);
web = new QWebView(this);
QVBoxLayout *vl = new QVBoxLayout;
vl->addLayout(title);
vl->addLayout(urlEdit);
vl->addLayout(web);
setLayout(vl);
setUrl(home);
}
void BrowserTab::setUrl(QUrl const& url)
{
web->load(url);
// update label & urlEdit here
}
You'll need to do a bit more to make it a proper browser (setUrl should probably be a slot too), but this should get you started.

Qt - Symbian Mobile - Soft key menus not displaying correctly

I create and show a QWebView with soft key options at the bottom. When I click "Options", a menu shows up, but it's tiny, black, and in the upper left hand corner (it should look like the standard blue soft keys and be directly above them). I followed this example.
//create webview
webView = new QWebView;
webView->setUrl(QString(":html/internal.html"));
//create menu
QAction *option1 = new QAction(tr("Back"), webView);
option1->setSoftKeyRole(QAction::PositiveSoftKey);
connect(option1, SIGNAL(triggered()), this, SLOT(deleteView()));
//create right softkey action to launch the "options" menu
QAction *option2 = new QAction(tr("Options"), webView);
option2->setSoftKeyRole(QAction::NegativeSoftKey);
connect(option2, SIGNAL(triggered(), this, SLOT(showMenu()));
QMenu *menuOptions = new QMenu(webView);
menuOptions->addAction(tr("Sub Menu 1"), this, SLOT(aboutView()));
menuOptions->addAction(tr("Sub Menu 2"), this, SLOT(aboutView()));
option2->setMenu(menuOptions);
//add softkey menus
QList < QAction* > softKeys;
softKeys.append(option1);
softKeys.append(option2);
webView->addActions(softKeys);
webView->show();
This example works well on simulator and also in phone. It is included in the QTDIR/examples/widgets folder since Qt 4.6.x

Resources