How to get minimize/restore/close rectangle? - qt

I want to draw some text in the end of menu bar like this
But when the child window is maximized in the MDI project it looks like this
I need to fix this output.
I want to check if the active child is maximized and if it is I want to get minimize/restore/close rectangle to get them total width.
How can I get active child window and how can I get it's rectangle of buttons?

// in yourMainWindow.cpp
...
auto child = mdiArea->addSubWindow(yourWidget);
connect(child, &QMdiSubWindow::windowStateChanged, this, &yourMainWindow::yourSlot);
...
void yourMainWindow::yourSlot(Qt::WindowStates oldState, Qt::WindowStates newState)
{
if (newState.testFlag(Qt::WindowMaximized)) {
auto child = qobject_cast<QMdiSubWindow *>(sender());
if (!child)
return;
QStyleOptionComplex opt;
opt.initFrom(child);
auto size = child->style()->sizeFromContents(QStyle::CT_MdiControls, &opt, QSize(100, 20));
qDebug() << size;
}
}

Related

Qt connect QScrollBar with QLineEdit

I would like to "activate" the scrollbar when the lineedit text is too long to display on the window. I have already done it.
I want to move the cursor with the scrollbar. I also want to modify the scroll bar slider length with the increment/decrement of the text length.
.h
private:
Ui::MainWindow *ui;
QLineEdit* LineEdit;
QScrollBar* hScrollBar;
void HDScrollBar();
constructor:
resize(400,100);
LineEdit = new QLineEdit(this);
LineEdit->resize(400,100);
LineEdit->setFont(QFont("Times",20));
hScrollBar = new QScrollBar(Qt::Horizontal, LineEdit);
hScrollBar->resize(400,20);
hScrollBar->move(0,80);
hScrollBar->hide();
connect(LineEdit, &QLineEdit::textChanged, this, &MainWindow::HDScrollBar);
hide/display scrollbar
void MainWindow::HDScrollBar() {
QFont myFont(QFont("Times",20));;
QString str = LineEdit->text();
QFontMetrics fm(myFont);
int width = fm.horizontalAdvance(str);
(width >= 400) ? hScrollBar->show() : hScrollBar->hide();
}
As for the first part, you use can scrollbar's valueChanged signal, e.g. this way:
connect(ui->horizontalScrollBar, &QScrollBar::valueChanged, ui->lineEdit, [&](int v) {
auto scrollbarAt = static_cast<double>(v) / ui->horizontalScrollBar->maximum();
auto cursorTo = std::round(ui->lineEdit->text().length() * scrollbarAt);
ui->lineEdit->setCursorPosition(cursorTo);
});
EDIT:
as for the latter part:
you can either alter the PageStep of the scrollbar, or you can set it to 1 and alter its maximum value, then also the first part should simplify:
ui->horizontalScrollBar->setPageStep(1);
ui->horizontalScrollBar->setMaximum(ui->lineEdit.text().length());
connect(ui->horizontalScrollBar, &QScrollBar::valueChanged,
ui->lineEdit, &QLineEdit::setCursorPosition);
//this can also ben done on textChanged, however for the price
//of more frequent execution...
connect(ui->lineEdit, &QLineEdit::cursorPositionChanged,
ui->horizontalScrollBar, [&](int, int n) {
ui->horizontalScrollBar->setMaximum(ui->lineEdit->text().length());
//...one gets the easy way to track the cursor
//with the slider
ui->horizontalScrollBar->setValue(n);
});

Dragged QGraphicsItem not visible in items() function

I have created a QGraphicsScene scene and added some graphcis items (lines, rectangles) etc to the scene.
I can loop through them using this list :
QList<QGraphicsItem*> all = items();
I enabled movement for these items and I am able to drag them by click selecting them. But after an element has been dragged, it stops showing up in the call to items() function of the QGraphicsScene.
QList<QGraphicsItem*> all = items();
None of the dragged items show up in the above list, while non-dragged ones do show up.
Does dragging the QGraphicScene elements change their parent ? or any other reason somebody could suggest for such an issue ?
{P.S. Code is too very big to share}
Edit 1 :
I am using the flags QGraphicsItem::ItemIsSelectable and QGraphicsItem::ItemIsMovable for making the items movable.
foreach(QGraphicsItem* itemInVisualScene, items())
{
itemInVisualScene->setFlag(QGraphicsItem::ItemIsSelectable, itemsMovable);
itemInVisualScene->setFlag(QGraphicsItem::ItemIsMovable, itemsMovable);
}
By default I add few rectangle to the scene. Then in the 'move mode' I drag them around. Then in the 'add mode' I click on screen to add new rectangles. I have written a logic to check if I am clicking on any existing drawn rectangle :
void Scene::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
if(eDrawLines == sceneMode)
{
dragBeginPoint = event->scenePos();
dragEndPoint = dragBeginPoint;
QList<QGraphicsItem*> all = items();
for (int i = 0; i < all.size(); i++)
{
QGraphicsItem *gi = all[i];
// Clicked point lies inside existing rect
if( QGraphicsRectItem::Type == gi->type() && gi->contains(dragBeginPoint))
{
std::cout << "Pressed inside existing rect" << std::endl;
return;
}
}
std::cout << "Point not found, add new rectangle" << std::endl;
}
QGraphicsScene::mousePressEvent(event);
}
This adding of rectangles work fine for rects which were not dragged in the 'move mode'. But rects which were moved do not seem to recognize the click anymore. My control comes out of the loop even when I click on an existing rectangle which was dragged earlier.
QGraphicsItem's transform is changed after dragging and therefore need to transform the point to item's local coordinates.
gi->contains(gi->mapFromScene(dragBeginPoint))
To convert or get item's position in scene coordinates, use
gi->mapToScene(0,0) or gi->scenePos()

Qt: Visibility state of the QWidget when used stylesheet

I have customized QWidget named "MainWidget" and a customized QWidget named "ChildWidget".
MainWidget is the parent of ChildWidget and these child widgets are created dynamically and inserted into the MainWidget's stack of widgets.
I have used style sheet to set the background color of the both MainWidget and ChildWidget in their respective .ui (form) file.
Select the widget ->Right Click on Widget-> Change stylesheet -> select background color-> apply -> save the .ui file
"background-color: ;"
Each ChidlWidget has its own unique size (width & height) such that when they have stacked on MainWidget's stack of widgets, there may be chances of one widget overlapping other widget, some widgets are completely obscured and some widgets are partially visible.
I am trying to find the visibility state of all types of widgets ( obscured, completely visible , partially visible) .
I am using following code snippet.
void MainWidget::printVisibilityState()
{
QList<ChildWidget *> childWidgetsList = findChildren<ChildWidget *>();
for (register int i = 0; i < childWidgetsList.size(); i++)
{
ChildWidget* pWidget = childWidgetsList.at(i);
QRegion visibleRegion = pWidget->visibleRegion();
QRect visibleRegionBoundingRect = visibleRegion.boundingRect();
int visibleRegionRectsCount = visibleRegion.rects().count();
QRect widgetRect = pWidget->rect();
if (visibleRegion.isEmpty()) {
qDebug() <<pWidget->getName()<< "is OBSCURED";
}
else {
if (
(visibleRegionBoundingRect == widgetRect) &&
(1 == visibleRegionRectsCount))
{
qDebug() <<pWidget->getName()<< "is VISIBLE";
}
else
{
qDebug() <<pWidget->getName()<< "is PARTIALLY VISIBLE";
}
}
}
}
and I have implemented painEvent in both MainWidget and ChildWidget with the following code snippet.
void ChildWidget::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
void MainWidget::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
This code prints the visibility state for all child widgets as VISIBLE always.
Note: Instead of setting the background-color using style sheet, if I use the setAutoFillBackground(true) for both MainWidget and ChildWidget then I am getting the proper visibility state.
Could you please guide me why it doesn't get me the proper visibility state when used style sheet?
Am I missing something in calculating the visibility state?
Are there any other way to get the visibility state info?
The QWidget document (http://qt-project.org/doc/qt-4.8/qwidget.html#visible-prop) says that, "A widget that happens to be obscured by other windows on the screen is considered to be visible."
If this is the case How do we determine the visibility state for the partially visible widgets? ( For example an error popup on other window, so error popup is completely visible and window is partially visible)
Please help me
Regards
SRaju

QGraphicsItem doesn't detect its own boundingRect change

// QT 4.8
I've implemented a resizable QGraphicsItem, which works pretty fine.
However, now, I need to include child items in this resizable item.
Child items size/position will obviously depend on parent one.
My problem is to notify childs when parent one is resized.
But so far, the parent itself doesn't detect its own size change (whereas on the scene, everything behave as expected!)
In the parent item (= the resizable one) item I've tried to override
QVariant itemChange(QGraphicsItemChange, QVariant)
in order to dump change events. I can see all events, but itemChange method never get called when item is (being) resized.
Any help greatly appreciated.
NB:
In my resizable QGraphicsItem constructor, I've enabled the flag QGraphicsItem::ItemSendGeometryChange
ResizableGraphicsItem::ResizableGraphicsItem(QGraphicsItem *p_parent,
qreal p_initialWidth,
qreal p_initialHeight)
: QGraphicsItem(p_parent), _width(p_initialWidth),
_height(p_initialHeight), _resized(true)
{
setFlag(ItemSendsGeometryChanges);
...
}
The resize method looks like the following:
void ResizableGraphicsItem::setSize(qreal p_width, qreal p_height)
{
prepareGeometryChange();
if ((_width != p_width) ||
(_height != p_height))
{
_width = p_width;
_height = p_height;
_resized = true;
}
}
with:
QRectF ResizableGraphicsItem::boundingRect() const
{
return QRectF(0, 0, _width, _height);
}

Displaying image as background of QGraphicsScene

I try to use QGraphicsView to display a map with some QGraphicItem-subclass showing region centers of the map. Conceptually, I organize the map as follow:
QGraphicsView
QGraphicsScene
QGraphicsPixmapItem : background image, fixed until next call of loadSetting
QGraphicsRectItem : legend, position relative to bg is fixed throughout app
QGraphicsEllipseItem : region centers
I want the map to behave as follow:
no scrollbars to be displayed, and the background image fillup all the visible area of the view/scene.
when the widget is re-sized, the QGraphics*Items will re-size themselves accordingly (as if the view is zoomed)
relative positions of QGraphicsEllipseItems, remain fixed until next call of loadSetting()
Now I have problem in getting the background image displayed properly.
Constructor [I'm adding this view to a QTabWidget directly: myTab->addTab("name", my_view_); ]
MyView::MyView(QWidget *parent) : QGraphicsView(parent) {
bg_pixmap_ = new QGraphicsPixmapItem();
legend_ = new MapLegend();
setScene(new QGraphicsScene(this));
scene()->addItem(bg_pixmap_);
scene()->addItem(legend_);
}
Load map setting (during program execution, this method may be invoked multiple times)
void MyView::loadSetting(Config* cfg) {
if (!cfg) return;
/* (a) */
scene()->clearFocus();
scene()->clearSelection();
for (int i = 0; i < symbols_.size(); i++)
scene()->removeItem(symbols_[i]);
qDeleteAll(symbols_);
symbols_.clear();
/* (a) */
/* (b) */
background_ = QPixmap(QString::fromStdString(cfg->district_map));
bg_pixmap_->setPixmap(background_);
for (size_t i = 0; i < cfg->centers.size(); i++) {
qreal x = cfg->centers[i].first * background_.width();
qreal y = cfg->centers[i].second * background_.height();
MapSymbol* item = new MapSymbol(x, y, 10);
symbols_.append(item);
scene()->addItem(item);
}
/* (b) */
update();
}
Questions
Now all items except the 'bg_pixmap_' got displayed, and I checked the 'background_' variable that it loads the image correctly. Is there anything I missed?
How do I implement the resizeEvent of MyView to cope with the desired 'resize-strategy'?

Resources