VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIFileTableNavigationWidget.cpp

Last change on this file was 104585, checked in by vboxsync, 4 months ago

FE/Qt: bugref:10450: Get rid of pre-5.11 code related to QFontMetrics.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.9 KB
Line 
1/* $Id: UIFileTableNavigationWidget.cpp 104585 2024-05-13 11:37:59Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIFileTableNavigationWidget class definitions.
4 */
5
6/*
7 * Copyright (C) 2009-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 <QComboBox>
31#include <QDir>
32#include <QFont>
33#include <QHBoxLayout>
34#include <QLabel>
35#include <QLineEdit>
36#include <QStackedWidget>
37#include <QToolButton>
38
39/* GUI includes: */
40#include "UIFileTableNavigationWidget.h"
41#include "UIPathOperations.h"
42
43
44/*********************************************************************************************************************************
45* UIFileManagerHistoryComboBox definition. *
46*********************************************************************************************************************************/
47/** A QCombo extension used as location history list in the UIFileTableNavigationWidget. */
48class UIFileManagerHistoryComboBox : public QComboBox
49{
50 Q_OBJECT;
51
52signals:
53
54 void sigHidePopup();
55
56public:
57
58 UIFileManagerHistoryComboBox(QWidget *pParent = 0);
59 /** Emit sigHidePopup as the popup is hidded. */
60 virtual void hidePopup() RT_OVERRIDE;
61};
62
63
64/*********************************************************************************************************************************
65* UIFileManagerBreadCrumbs definition. *
66*********************************************************************************************************************************/
67/** A QLabel extension. It shows the current path as text and hightligts the folder name
68 * as the mouse hovers over it. Clicking on the highlighted folder name make the file table to
69 * navigate to that folder. */
70class UIFileManagerBreadCrumbs : public QLabel
71{
72 Q_OBJECT;
73
74public:
75
76 UIFileManagerBreadCrumbs(QWidget *pParent = 0);
77 void setPath(const QString &strPath);
78 void setPathSeparator(const QChar &separator);
79
80protected:
81
82 virtual void resizeEvent(QResizeEvent *pEvent) RT_OVERRIDE;
83
84private:
85
86 QString m_strPath;
87 QChar m_pathSeparator;
88};
89
90
91/*********************************************************************************************************************************
92* UIFileManagerHistoryComboBox implementation. *
93*********************************************************************************************************************************/
94
95UIFileManagerHistoryComboBox::UIFileManagerHistoryComboBox(QWidget *pParent /* = 0 */)
96 :QComboBox(pParent)
97{
98
99}
100
101void UIFileManagerHistoryComboBox::hidePopup()
102{
103 QComboBox::hidePopup();
104 emit sigHidePopup();
105}
106
107
108/*********************************************************************************************************************************
109* UIFileManagerBreadCrumbs implementation. *
110*********************************************************************************************************************************/
111
112UIFileManagerBreadCrumbs::UIFileManagerBreadCrumbs(QWidget *pParent /* = 0 */)
113 :QLabel(pParent)
114 , m_pathSeparator(UIPathOperations::delimiter)
115{
116 float fFontMult = 1.f;
117 QFont mFont = font();
118 if (mFont.pixelSize() == -1)
119 mFont.setPointSize(fFontMult * mFont.pointSize());
120 else
121 mFont.setPixelSize(fFontMult * mFont.pixelSize());
122 setFont(mFont);
123
124 setFrameShape(QFrame::Box);
125 setLineWidth(1);
126 setAutoFillBackground(true);
127 QPalette pal = QApplication::palette();
128 pal.setColor(QPalette::Active, QPalette::Window, pal.color(QPalette::Active, QPalette::Base));
129 setPalette(pal);
130 /* Allow the label become smaller than the current text. calling setpath in resizeEvent truncated the text anyway: */
131 setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
132}
133
134void UIFileManagerBreadCrumbs::setPath(const QString &strPath)
135{
136 m_strPath = strPath;
137
138 const QChar separator(UIPathOperations::delimiter);
139 clear();
140
141 if (strPath.isEmpty())
142 return;
143
144 QStringList folderList = UIPathOperations::pathTrail(strPath);
145 if (!strPath.isEmpty() && strPath.at(0) == UIPathOperations::delimiter)
146 folderList.push_front(separator);
147
148 QString strLabelText;
149 QVector<QString> strPathUpto;
150 strPathUpto.resize(folderList.size());
151
152 for (int i = 0; i < folderList.size(); ++i)
153 {
154 QString strFolder = folderList.at(i);
155 if (i != 0)
156 strPathUpto[i] = strPathUpto[i - 1];
157 strPathUpto[i].append(QString("%1%2").arg(strFolder).arg(separator));
158 }
159
160 int iWidth = 0;
161 for (int i = folderList.size() - 1; i >= 0; --i)
162 {
163 QString strFolder = UIPathOperations::removeTrailingDelimiters(folderList.at(i)).replace(UIPathOperations::delimiter, m_pathSeparator);
164 QString strWord = QString("<a href=\"%1\" style=\"color:black;text-decoration:none;\">%2</a>").arg(strPathUpto[i]).arg(strFolder);
165
166 if (i < folderList.size() - 1)
167 {
168 iWidth += fontMetrics().horizontalAdvance(" > ");
169 strWord.append("<b> > </b>");
170 }
171 iWidth += fontMetrics().horizontalAdvance(strFolder);
172
173 if (iWidth < width())
174 strLabelText.prepend(strWord);
175 }
176 setText(strLabelText);
177}
178
179void UIFileManagerBreadCrumbs::setPathSeparator(const QChar &separator)
180{
181 m_pathSeparator = separator;
182}
183
184void UIFileManagerBreadCrumbs::resizeEvent(QResizeEvent *pEvent)
185{
186 /* Truncate the text the way we want: */
187 setPath(m_strPath);
188 QLabel::resizeEvent(pEvent);
189}
190
191
192/*********************************************************************************************************************************
193* UIFileTableNavigationWidget implementation. *
194*********************************************************************************************************************************/
195
196UIFileTableNavigationWidget::UIFileTableNavigationWidget(QWidget *pParent /* = 0 */)
197 :QWidget(pParent)
198 , m_pContainer(0)
199 , m_pBreadCrumbs(0)
200 , m_pHistoryComboBox(0)
201 , m_pAddressLineEdit(0)
202 , m_pSwitchButton(0)
203 , m_pathSeparator(UIPathOperations::delimiter)
204{
205 prepare();
206}
207
208void UIFileTableNavigationWidget::setPath(const QString &strLocation)
209{
210 if (m_strCurrentPath == QDir::fromNativeSeparators(strLocation))
211 return;
212
213 m_strCurrentPath = QDir::fromNativeSeparators(strLocation);
214
215 if (m_pBreadCrumbs)
216 m_pBreadCrumbs->setPath(strLocation);
217
218 if (m_pHistoryComboBox)
219 {
220 QString strNativeLocation(strLocation);
221 strNativeLocation.replace(UIPathOperations::delimiter, m_pathSeparator);
222 int itemIndex = m_pHistoryComboBox->findText(strNativeLocation,
223 Qt::MatchExactly | Qt::MatchCaseSensitive);
224 if (itemIndex == -1)
225 {
226 m_pHistoryComboBox->insertItem(m_pHistoryComboBox->count(), strNativeLocation);
227 itemIndex = m_pHistoryComboBox->count() - 1;
228 }
229 m_pHistoryComboBox->setCurrentIndex(itemIndex);
230 emit sigHistoryListChanged();
231 }
232}
233
234void UIFileTableNavigationWidget::reset()
235{
236 if (m_pHistoryComboBox)
237 {
238 m_pHistoryComboBox->blockSignals(true);
239 m_pHistoryComboBox->clear();
240 m_pHistoryComboBox->blockSignals(false);
241 emit sigHistoryListChanged();
242 }
243
244 if (m_pBreadCrumbs)
245 m_pBreadCrumbs->setPath(QString());
246}
247
248void UIFileTableNavigationWidget::setPathSeparator(const QChar &separator)
249{
250 m_pathSeparator = separator;
251 if (m_pBreadCrumbs)
252 m_pBreadCrumbs->setPathSeparator(m_pathSeparator);
253}
254
255bool UIFileTableNavigationWidget::canGoForward() const
256{
257 if (!m_pHistoryComboBox)
258 return false;
259 return (m_pHistoryComboBox->currentIndex() < m_pHistoryComboBox->count() - 1);
260}
261
262bool UIFileTableNavigationWidget::canGoBackward() const
263{
264 if (!m_pHistoryComboBox)
265 return false;
266 return (m_pHistoryComboBox->currentIndex() > 0);
267}
268
269
270void UIFileTableNavigationWidget::goForwardInHistory()
271{
272 if (!m_pHistoryComboBox || m_pHistoryComboBox->currentIndex() >= m_pHistoryComboBox->count() - 1)
273 return;
274 m_pHistoryComboBox->setCurrentIndex(m_pHistoryComboBox->currentIndex() + 1);
275}
276
277void UIFileTableNavigationWidget::goBackwardInHistory()
278{
279 if (!m_pHistoryComboBox || m_pHistoryComboBox->currentIndex() <= 0)
280 return;
281 m_pHistoryComboBox->setCurrentIndex(m_pHistoryComboBox->currentIndex() - 1);
282}
283
284void UIFileTableNavigationWidget::prepare()
285{
286 QHBoxLayout *pLayout = new QHBoxLayout;
287 if (!pLayout)
288 return;
289 pLayout->setSpacing(0);
290 pLayout->setContentsMargins(0, 0, 0, 0);
291
292 m_pContainer = new QStackedWidget;
293 if (m_pContainer)
294 {
295 m_pBreadCrumbs = new UIFileManagerBreadCrumbs;
296 m_pHistoryComboBox = new UIFileManagerHistoryComboBox;
297 m_pAddressLineEdit = new QLineEdit;
298 if (m_pBreadCrumbs && m_pHistoryComboBox)
299 {
300 m_pBreadCrumbs->setIndent(0.5 * qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin));
301 m_pBreadCrumbs->installEventFilter(this);
302 m_pAddressLineEdit->installEventFilter(this);
303 connect(m_pBreadCrumbs, &UIFileManagerBreadCrumbs::linkActivated,
304 this, &UIFileTableNavigationWidget::sltHandlePathChange);
305 connect(m_pHistoryComboBox, &UIFileManagerHistoryComboBox::sigHidePopup,
306 this, &UIFileTableNavigationWidget::sltHandleHidePopup);
307 connect(m_pHistoryComboBox, &UIFileManagerHistoryComboBox::currentTextChanged,
308 this, &UIFileTableNavigationWidget::sltHandlePathChange);
309 connect(m_pAddressLineEdit, &QLineEdit::returnPressed,
310 this, &UIFileTableNavigationWidget::sltAddressLineEdited);
311 m_pContainer->insertWidget(StackedWidgets_BreadCrumbs, m_pBreadCrumbs);
312 m_pContainer->insertWidget(StackedWidgets_History, m_pHistoryComboBox);
313 m_pContainer->insertWidget(StackedWidgets_AddressLine, m_pAddressLineEdit);
314 m_pContainer->setCurrentIndex(StackedWidgets_BreadCrumbs);
315 }
316 pLayout->addWidget(m_pContainer);
317 }
318
319 m_pSwitchButton = new QToolButton;
320 if (m_pSwitchButton)
321 {
322 QStyle *pStyle = QApplication::style();
323 QIcon buttonIcon;
324 if (pStyle)
325 {
326 buttonIcon = pStyle->standardIcon(QStyle::SP_TitleBarUnshadeButton);
327 m_pSwitchButton->setIcon(buttonIcon);
328 }
329 pLayout->addWidget(m_pSwitchButton);
330 connect(m_pSwitchButton, &QToolButton::clicked,
331 this, &UIFileTableNavigationWidget::sltHandleSwitch);
332 }
333 setLayout(pLayout);
334}
335
336bool UIFileTableNavigationWidget::eventFilter(QObject *pObject, QEvent *pEvent)
337{
338 if (pObject == m_pBreadCrumbs && pEvent && pEvent->type() == QEvent::MouseButtonDblClick)
339 {
340 m_pContainer->setCurrentIndex(StackedWidgets_AddressLine);
341 m_pAddressLineEdit->setText(QDir::toNativeSeparators(m_strCurrentPath));
342 m_pAddressLineEdit->setFocus();
343
344 }
345 else if(pObject == m_pAddressLineEdit && pEvent && pEvent->type() == QEvent::FocusOut)
346 m_pContainer->setCurrentIndex(StackedWidgets_BreadCrumbs);
347
348 return QWidget::eventFilter(pObject, pEvent);
349}
350
351void UIFileTableNavigationWidget::sltHandleHidePopup()
352{
353 m_pContainer->setCurrentIndex(StackedWidgets_BreadCrumbs);
354}
355
356void UIFileTableNavigationWidget::sltHandlePathChange(const QString &strPath)
357{
358 emit sigPathChanged(UIPathOperations::replaceDosDelimeter(strPath));
359}
360
361void UIFileTableNavigationWidget::sltHandleSwitch()
362{
363 if (m_pContainer->currentIndex() == StackedWidgets_BreadCrumbs)
364 {
365 m_pContainer->setCurrentIndex(StackedWidgets_History);
366 m_pHistoryComboBox->showPopup();
367 }
368 else
369 {
370 m_pContainer->setCurrentIndex(StackedWidgets_BreadCrumbs);
371 m_pHistoryComboBox->hidePopup();
372 }
373}
374
375void UIFileTableNavigationWidget::sltAddressLineEdited()
376{
377 sigPathChanged(QDir::fromNativeSeparators(m_pAddressLineEdit->text()));
378}
379
380#include "UIFileTableNavigationWidget.moc"
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle
ContactPrivacy/Do Not Sell My InfoTerms of Use