VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/extensions/QILineEdit.cpp@ 100347

Last change on this file since 100347 was 100075, checked in by vboxsync, 20 months ago

FE/Qt: bugref:10450: Qt6 compatibility bits for QIcon; Good old QIcon::pixmap taking QWindow is deprecated in Qt6; Reworking a lot of calls to use devicePixelRatio acquired beforehand.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.8 KB
Line 
1/* $Id: QILineEdit.cpp 100075 2023-06-05 16:38:02Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - Qt extensions: QILineEdit class implementation.
4 */
5
6/*
7 * Copyright (C) 2008-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QApplication>
30#include <QClipboard>
31#include <QContextMenuEvent>
32#include <QHBoxLayout>
33#include <QLabel>
34#include <QMenu>
35#include <QPalette>
36#include <QStyleOptionFrame>
37#ifdef VBOX_IS_QT6_OR_LATER
38# include <QWindow>
39#endif
40
41/* GUI includes: */
42#include "QILineEdit.h"
43#include "UIIconPool.h"
44
45/* Other VBox includes: */
46#include "iprt/assert.h"
47
48
49QILineEdit::QILineEdit(QWidget *pParent /* = 0 */)
50 : QLineEdit(pParent)
51 , m_fAllowToCopyContentsWhenDisabled(false)
52 , m_pCopyAction(0)
53 , m_pIconLabel(0)
54 , m_fMarkForError(false)
55{
56 prepare();
57}
58
59QILineEdit::QILineEdit(const QString &strText, QWidget *pParent /* = 0 */)
60 : QLineEdit(strText, pParent)
61 , m_fAllowToCopyContentsWhenDisabled(false)
62 , m_pCopyAction(0)
63 , m_pIconLabel(0)
64 , m_fMarkForError(false)
65{
66 prepare();
67}
68
69void QILineEdit::setAllowToCopyContentsWhenDisabled(bool fAllow)
70{
71 m_fAllowToCopyContentsWhenDisabled = fAllow;
72}
73
74void QILineEdit::setMinimumWidthByText(const QString &strText)
75{
76 setMinimumWidth(fitTextWidth(strText).width());
77}
78
79void QILineEdit::setFixedWidthByText(const QString &strText)
80{
81 setFixedWidth(fitTextWidth(strText).width());
82}
83
84void QILineEdit::mark(bool fError, const QString &strErrorMessage /* = QString() */)
85{
86 /* Check if something really changed: */
87 if (fError == m_fMarkForError && m_strErrorMessage == strErrorMessage)
88 return;
89
90 /* Save new values: */
91 m_fMarkForError = fError;
92 m_strErrorMessage = strErrorMessage;
93
94 /* Update accordingly: */
95 if (m_fMarkForError)
96 {
97 /* Create label if absent: */
98 if (!m_pIconLabel)
99 m_pIconLabel = new QLabel(this);
100
101 /* Update label content, visibility & position: */
102 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) * .625;
103 const int iShift = height() > iIconMetric ? (height() - iIconMetric) / 2 : 0;
104#ifndef VBOX_IS_QT6_OR_LATER /* QIcon::pixmap taking QWindow is deprecated in Qt6 */
105 m_pIconLabel->setPixmap(m_markIcon.pixmap(windowHandle(), QSize(iIconMetric, iIconMetric)));
106#else
107 const qreal fDevicePixelRatio = window() && window()->windowHandle() ? window()->windowHandle()->devicePixelRatio() : 1;
108 m_pIconLabel->setPixmap(m_markIcon.pixmap(QSize(iIconMetric, iIconMetric), fDevicePixelRatio));
109#endif
110 m_pIconLabel->setToolTip(m_strErrorMessage);
111 m_pIconLabel->move(width() - iIconMetric - iShift, iShift);
112 m_pIconLabel->show();
113 }
114 else
115 {
116 /* Hide label: */
117 if (m_pIconLabel)
118 m_pIconLabel->hide();
119 }
120}
121
122bool QILineEdit::event(QEvent *pEvent)
123{
124 switch (pEvent->type())
125 {
126 case QEvent::ContextMenu:
127 {
128 /* For disabled widget if requested: */
129 if (!isEnabled() && m_fAllowToCopyContentsWhenDisabled)
130 {
131 /* Create a context menu for the copy to clipboard action: */
132 QContextMenuEvent *pContextMenuEvent = static_cast<QContextMenuEvent*>(pEvent);
133 QMenu menu;
134 m_pCopyAction->setText(tr("&Copy"));
135 menu.addAction(m_pCopyAction);
136 menu.exec(pContextMenuEvent->globalPos());
137 pEvent->accept();
138 }
139 break;
140 }
141 default:
142 break;
143 }
144 return QLineEdit::event(pEvent);
145}
146
147void QILineEdit::resizeEvent(QResizeEvent *pResizeEvent)
148{
149 /* Call to base-class: */
150 QLineEdit::resizeEvent(pResizeEvent);
151
152 /* Update error label position: */
153 if (m_pIconLabel)
154 {
155 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) * .625;
156 const int iShift = height() > iIconMetric ? (height() - iIconMetric) / 2 : 0;
157 m_pIconLabel->move(width() - iIconMetric - iShift, iShift);
158 }
159}
160
161void QILineEdit::copy()
162{
163 /* Copy the current text to the global and selection clipboards: */
164 QApplication::clipboard()->setText(text(), QClipboard::Clipboard);
165 QApplication::clipboard()->setText(text(), QClipboard::Selection);
166}
167
168void QILineEdit::prepare()
169{
170 /* Prepare invisible copy action: */
171 m_pCopyAction = new QAction(this);
172 if (m_pCopyAction)
173 {
174 m_pCopyAction->setShortcut(QKeySequence(QKeySequence::Copy));
175 m_pCopyAction->setShortcutContext(Qt::WidgetShortcut);
176 connect(m_pCopyAction, &QAction::triggered, this, &QILineEdit::copy);
177 addAction(m_pCopyAction);
178 }
179
180 /* Prepare warning icon: */
181 m_markIcon = UIIconPool::iconSet(":/status_error_16px.png");
182}
183
184QSize QILineEdit::fitTextWidth(const QString &strText) const
185{
186 QStyleOptionFrame sof;
187 sof.initFrom(this);
188 sof.rect = contentsRect();
189 sof.lineWidth = hasFrame() ? style()->pixelMetric(QStyle::PM_DefaultFrameWidth) : 0;
190 sof.midLineWidth = 0;
191 sof.state |= QStyle::State_Sunken;
192
193 /** @todo make it wise.. */
194 // WORKAROUND:
195 // The margins are based on qlineedit.cpp of Qt.
196 // Maybe they where changed at some time in the future.
197#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
198 QSize sc(fontMetrics().horizontalAdvance(strText) + 2 * 2,
199 fontMetrics().xHeight() + 2 * 1);
200#else
201 QSize sc(fontMetrics().width(strText) + 2 * 2,
202 fontMetrics().xHeight() + 2 * 1);
203#endif
204 const QSize sa = style()->sizeFromContents(QStyle::CT_LineEdit, &sof, sc, this);
205
206 return sa;
207}
208
209UIMarkableLineEdit::UIMarkableLineEdit(QWidget *pParent /* = 0 */)
210 :QWidget(pParent)
211 , m_pLineEdit(0)
212 , m_pIconLabel(0)
213{
214 prepare();
215}
216
217void UIMarkableLineEdit::setText(const QString &strText)
218{
219 if (m_pLineEdit)
220 m_pLineEdit->setText(strText);
221}
222
223QString UIMarkableLineEdit::text() const
224{
225 if (!m_pLineEdit)
226 return QString();
227 return m_pLineEdit->text();
228}
229
230void UIMarkableLineEdit::setValidator(const QValidator *pValidator)
231{
232 if (m_pLineEdit)
233 m_pLineEdit->setValidator(pValidator);
234}
235
236bool UIMarkableLineEdit::hasAcceptableInput() const
237{
238 if (!m_pLineEdit)
239 return false;
240 return m_pLineEdit->hasAcceptableInput();
241}
242
243void UIMarkableLineEdit::setPlaceholderText(const QString &strText)
244{
245 if (m_pLineEdit)
246 m_pLineEdit->setPlaceholderText(strText);
247}
248
249void UIMarkableLineEdit::mark(bool fError, const QString &strErrorMessage /* = QString() */)
250{
251 m_pIconLabel->setVisible(true);
252 AssertReturnVoid(m_pIconLabel);
253 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
254
255#ifndef VBOX_IS_QT6_OR_LATER /* QIcon::pixmap taking QWindow is deprecated in Qt6 */
256 if (fError)
257 m_pIconLabel->setPixmap(UIIconPool::iconSet(":/status_error_16px.png").pixmap(windowHandle(), QSize(iIconMetric, iIconMetric)));
258 else
259 m_pIconLabel->setPixmap(UIIconPool::iconSet(":/status_check_16px.png").pixmap(windowHandle(), QSize(iIconMetric, iIconMetric)));
260#else
261 const qreal fDevicePixelRatio = window() && window()->windowHandle() ? window()->windowHandle()->devicePixelRatio() : 1;
262 if (fError)
263 m_pIconLabel->setPixmap(UIIconPool::iconSet(":/status_error_16px.png").pixmap(QSize(iIconMetric, iIconMetric), fDevicePixelRatio));
264 else
265 m_pIconLabel->setPixmap(UIIconPool::iconSet(":/status_check_16px.png").pixmap(QSize(iIconMetric, iIconMetric), fDevicePixelRatio));
266#endif
267 m_pIconLabel->setToolTip(strErrorMessage);
268}
269
270void UIMarkableLineEdit::prepare()
271{
272 QHBoxLayout *pMainLayout = new QHBoxLayout(this);
273 AssertReturnVoid(pMainLayout);
274 pMainLayout->setContentsMargins(0, 0, 0, 0);
275 m_pLineEdit = new QILineEdit;
276 AssertReturnVoid(m_pLineEdit);
277 m_pIconLabel = new QLabel;
278 AssertReturnVoid(m_pIconLabel);
279 /* Show the icon label only if line edit is marked for error/no error.*/
280 m_pIconLabel->hide();
281 pMainLayout->addWidget(m_pLineEdit);
282 pMainLayout->addWidget(m_pIconLabel);
283 setFocusProxy(m_pLineEdit);
284 connect(m_pLineEdit, &QILineEdit::textChanged, this, &UIMarkableLineEdit::textChanged);
285}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette