How to get selected QTextEdit using on-screen keyboard? - qt

I have to make a GUI for a touch screen software. It's on the same window as the QTextEdit. I was thinking of something simple with a limited set of characters (I also have to make PIN Pads for other windows later).
The approach I'm thinking of is hard-coding the text modifications done by each button. The problem I'm facing getting the QTextEdit that actually has the focus (is selected by the user's cursor).
So I would like to know how I could find out if a certain QTextEdit currently has focus or not ?
Also if there are better ways to do this whole thing ?
Here is my new code, what's wrong with it ?
#include "settings2.h"
#include "ui_settings2.h"
Settings2::Settings2(QWidget *parent) :
QWidget(parent),
ui(new Ui::Settings2)
{
ui->setupUi(this);
}
Settings2::~Settings2()
{
delete ui;
}
void Settings2::on_q_btn_clicked()
{
QTextEdit *textedit = qobject_cast<QTextEdit*>(QApplication::focusWidget());
if(textedit){
textedit->setText("aze");}
}

The way you are trying to get the QTextEdit in focus is wrong. Moreover as soon as you click on a button on your on-screen keyboard, the focus will move to the key and will not stay on the QTextEdit.
I would suggest using a pointer to hold address of modified QTextEdit as soon as one comes to focus. Thus you will always know which was the last text edit in focus and keep appending the new text to that.
You will have to write your own class inheriting QTextEdit and implement the QTextEdit::focusInEvent where you will be pointing the above mentioned pointer to the this pointer.

Per #thuga's comment QApplication::focusWidget.
If you want to be sure the focused widget is a certain category of widget you can use qobject_cast, which will only return a non-null pointer if that cast is valid:
QLineEdit *lineedit = qobject_cast<QLineEdit*>(widget);
QTextEdit *textedit = qobject_cast<QTextEdit*>(widget);
...
if (lineedit) {
// do QLineEdit stuff with lineedit
...
}
if (textedit) {
// do QTextEdit stuff with textedit
...
}
...

Related

How to override all widgit tooltips to have them displayed in a single QTextBrowser widget?

I am new to Qt and therefore do not know all the in's and out's and would therefore like to know how, when you hover your mouse over a checkbox or other field that contains a tooltip, to get that tooltip text and have it applied/displayed in a QTextBrowser widget??
Thanks for any help on this issue.
Each QWidget has a "toolTip" property. To get it you can simply call:
QString toolTip = desiredWidget->toolTip();
Also, as you see, to get a toolTip as a string you don't have to wait until your mouse will hover over the desired widget. After that you can use this toolTip as you want (e.g. display it in QTextBrowser as you wrote in your question).
If you try to dynamically display tooltip of the widget under cursor, try to track mouse movement.
class MyWidget: public SuperclassWidget
{...};
void MyWidget::mouseMoveEvent(QMouseEvent *event)
{
const QWidget *widget = childAt(event->pos());
if (widget != NULL)
_textBrowser->setHtml(widget->toolTip());
SuperclassWidget::mouseMoveEvent(event);
}
There may be more clever things to prevent too frequent setting of the same tooltip, e.g. remembering the last widget.

How to delete objects inside Widget in Qt

I have MainWindow form which has Widget inside. And I have another Widget class (promoted to MainWindow) which has only DockWidget inside. In MainWindow I am opening new one and placing into Widget. However when I close DockWidget from close(cross"X") button. Inside my MainWindow it is not cleaning..
Sorry for my bad english better to paste my code here:
qDebug() << ui->widget->layout()->count();
QueryWidget *lQueryWidget = new QueryWidget(this);
ui->widget->layout()->addWidget(lQueryWidget);
So in everytime although I close DockWindow(lQueryWidget), layout()->count() never decrease. I tried to delete everything inside layout like ;
QList<QObject*> child = ui->widget->layout()->children();
foreach (QObject *var, child)
{
delete var;
}
But it never enters foreach loop.. If you check image below you will see that there is something above DockWidget, but it is not visible.. Could you please help me how can I solve this issue ?
To make dockable widget you should use
QDockWidget::setWidget(QWidget * widget)
The widget will be deleted when the dock widget is deleted.
You should not manipulate the dock widget layout.

Qt Menu with QLinEdit action

I want to have a line edit field in a popup menu I've got. I'm basically letting the user pick from one of several common sizes for something, but I want them to be able to enter a custom size as the last entry in the menu.
So I've got something like this (snipped from larger code, new_menu is the menu of interest):
QWidget *widget = new QWidget(new_menu);
QHBoxLayout *layout = new QHBoxLayout;
QLineEdit* le = new QLineEdit;
le->setPlaceholderText("Custom");
le->setFixedWidth(100);
ayout->addWidget(le);
widget->setLayout(layout);
QWidgetAction* wa = new QWidgetAction(new_menu);
wa->setActionGroup(group);
wa->setDefaultWidget(widget);
new_menu->addAction(wa);
connect(le, SIGNAL(returnPressed()), this, SLOT(leslot()));
Which works great, the LineEdit shows up nice and centered in the menu, it's got the placeholder text, I can click it and edit, everything. However, when I hit enter on the textBox, it emits the returnPressed signal and the menu emits a triggered signal with one of the other actions on the list, so at best I'm changing my configuration twice and at worst things break.
Additionally, when I click off the edge of the LineEdit (still in the menu though, but not in the editable area), the menu emits a triggered signal with the QWidgetAction associated with it, which isn't what I want.
So two questions:
1) Can I get the return to work the way I want. It's fine if the menu closes when it's hit, but it can't emit another action too.
2) Can I get it to not emit an action at all when the lineEdit is clicked?
Here's what I ended up doing for anyone that follows. I subclassed QLineEdit thusly:
class EnterLineEdit : public QLineEdit {
Q_OBJECT
public:
void keyPressEvent(QKeyEvent *evt) {
if (evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Return) {
emit returnPressed();
} else {
QLineEdit::keyPressEvent(evt);
}
}
};
This lets me manually emit the returnPressed signal when enter/return is hit and not pass it up the widget hierarchy, so the menu never sees it when enter is hit over the lineedit. I connected the returnPressed signal to the hide() slot of the menu so that the menu will still close, but without triggering an action.

Simple way to get all visible items in the QListView

I am trying to develop an image gallery application using Qt Framework. The application loads all the images from the selected folder and those images are displayed using QListView control.
But now i want to reduce the memory consumption by loading only the images that are visible to user. Since there is no direct function to get all the visible items in the view, i am not able to achieve this.
You can get the visible items of a list view using the indexAt function. For more details and an example you can check the following article:
http://qt-project.org/faq/answer/how_can_i_get_hold_of_all_of_the_visible_items_in_my_qlistview
I found it! You have to connect the vertical scrollbar of the listwidget to a signal:
connect(ui->listWidget->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(launch_timer()));
Every time the user scrolls, the valuechanged(int) signal is being omitted! The thing is that you shouldn't run the code provided by webclectic in this question every time the value of the vertical scrollbar of the listwidget changes, because the program will be unresponsive with so much code to run in so little time.
So, you have to have a singleshot timer and point it to the function that webclectic posted above. When launch_timer() is called, you do something like this:
if(timer->isActive()){
timer->stop();
timer->start(300);
}
else
timer->start(300);
and the timeout() signal of timer will be connected to the slot webclectic talked about. This way, if the user scrolls quickly all the way down only the last items will be updated. Generally, it will be updated anything visible for more than 300 milliseconds!
I think what you need is to implement your own model (take a look to the QAbstractListModel documentation) so that way you could decide when you have to load more images to show and maybe free some of the images that became non-visible.
although this is not so simple in Qt 4 but
it is always simple to copy below:
#include <private/qlistview_p.h>
class QListViewHelper : public QListView
{
typedef QListView super;
inline QListViewHelper() {} //not intended to be constructed
public:
inline static QVector<QModelIndex> indexFromRect(const QListView *view,
const QRect &rect)
{
const QListViewPrivate *d = static_cast<const QListViewPrivate *>(QObjectPrivate::get(view)); //to access "QListViewPrivate::intersectingSet(...)"
const QListViewHelper *helper = static_cast<const QListViewHelper *>(view); //to access "QListView::horizontalOffset()"
return d->intersectingSet(rect.translated(helper->horizontalOffset(), helper->verticalOffset()), false);
}
inline static QVector<QModelIndex> visibleItems(const QListView *view)
{ return indexFromRect(view, view->rect()); }
inline static QModelIndex firstVisible(const QListView *view)
{ return visibleItems(view).value(0); }
inline static QModelIndex lastVisible(const QListView *view) {
const QVector<QModelIndex> &items = visibleItems(view);
return items.value(items.count() - 1);
}
};
void ourTest(const QListView *view) {
QModelIndex &index = QListViewHelper::firstVisible(view);
qDebug("QListViewHelper: first visible row is %d", index.row());
index = QListViewHelper::lastVisible(view);
qDebug("QListViewHelper: last visible row is %d", index.row());
}
usage:
QModelIndex &index =
QListViewHelper::firstVisible(listViewPointerHere)
note: since it does use Qt 4.8 private-headers it may no longer work in latter versions and will need some changes.
You can keep track of all the elements that are drawn per paint event. I used a delegate and overloaded the paint event.
I also overloaded the paint event in the view. During this call, all the visible delegates will get a paint event.
If you just need to know if an item is visible, you can increment a frame count in view->paintEvent and set that number in the delegate item. The item is visible of the item matches the current frame number.
If you need a list of all visible items, clear the visible item list in view->paintEvent and add each item in the int the delegate->paintEvent to the visible items list.

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.

Resources