ORE Studio 0.0.4
Loading...
Searching...
No Matches
WidgetUtils.hpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 *
3 * Copyright (C) 2026 Marco Craveiro <marco.craveiro@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 3 of the License, or (at your option) any later
8 * version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 * details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 51
17 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20#ifndef ORES_QT_WIDGET_UTILS_HPP
21#define ORES_QT_WIDGET_UTILS_HPP
22
23#include <QApplication>
24#include <QComboBox>
25#include <QListView>
26#include <QPointer>
27#include <QScreen>
28#include <QShowEvent>
29#include <QSize>
30#include <QTimer>
31#include <QWidget>
32
33namespace ores::qt {
34
46class BoundedListView : public QListView {
47public:
48 static constexpr int max_popup_height = 250;
49
50 explicit BoundedListView(QComboBox* combo)
51 : QListView(combo), combo_(combo) {}
52
53 QSize sizeHint() const override {
54 const auto s = QListView::sizeHint();
55 return { s.width(), std::min(s.height(), max_popup_height) };
56 }
57
58protected:
59 void showEvent(QShowEvent* event) override {
60 QListView::showEvent(event);
61 // Post so this runs after QComboBox::showPopup() finishes sizing and
62 // positioning. We then correct both if needed.
63 QTimer::singleShot(0, this, [this]() {
64 QWidget* popup = parentWidget();
65 if (!popup || !combo_ || popup->height() <= max_popup_height)
66 return;
67
68 // Determine where the combo box is on screen.
69 const QPoint comboPos = combo_->mapToGlobal(QPoint(0, 0));
70 const QRect comboRect(comboPos, combo_->size());
71
72 // Get the available screen geometry.
73 const QScreen* screen = QApplication::screenAt(comboPos);
74 const QRect screenRect = screen
75 ? screen->availableGeometry()
76 : QRect(0, 0, 9999, 9999);
77
78 // Resize first, then reposition: prefer opening below the combo,
79 // fall back to above if there is not enough room.
80 popup->resize(popup->width(), max_popup_height);
81 int y = comboRect.bottom() + 1;
82 if (y + max_popup_height > screenRect.bottom())
83 y = comboRect.top() - max_popup_height;
84 popup->move(popup->x(), y);
85 });
86 }
87
88private:
89 QPointer<QComboBox> combo_;
90};
91
96
106 static void setupComboBoxes(QWidget* parent) {
107 for (auto* combo : parent->findChildren<QComboBox*>()) {
108 combo->setMaxVisibleItems(10);
109 combo->setView(new BoundedListView(combo));
110 }
111 }
112};
113
114}
115
116#endif
Qt-based graphical user interface for ORE Studio.
Definition AboutDialog.hpp:29
A QListView that caps the combo box popup height and repositions it.
Definition WidgetUtils.hpp:46
Utility functions for common widget configuration.
Definition WidgetUtils.hpp:95
static void setupComboBoxes(QWidget *parent)
Apply standard configuration to all combo boxes in a widget.
Definition WidgetUtils.hpp:106