VirtualBox

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

Last change on this file since 103977 was 103711, checked in by vboxsync, 9 months ago

FE/Qt: Get rid of even more iprt includes, s.a. r162071 and r162072.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.1 KB
Line 
1/* $Id: UIFileTableNavigationWidget.cpp 103711 2024-03-06 17:44:24Z 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#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
169 iWidth += fontMetrics().horizontalAdvance(" > ");
170#else
171 iWidth += fontMetrics().width(" > ");
172#endif
173 strWord.append("<b> > </b>");
174 }
175#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
176 iWidth += fontMetrics().horizontalAdvance(strFolder);
177#else
178 iWidth += fontMetrics().width(strFolder);
179#endif
180
181 if (iWidth < width())
182 strLabelText.prepend(strWord);
183 }
184 setText(strLabelText);
185}
186
187void UIFileManagerBreadCrumbs::setPathSeparator(const QChar &separator)
188{
189 m_pathSeparator = separator;
190}
191
192void UIFileManagerBreadCrumbs::resizeEvent(QResizeEvent *pEvent)
193{
194 /* Truncate the text the way we want: */
195 setPath(m_strPath);
196 QLabel::resizeEvent(pEvent);
197}
198
199
200/*********************************************************************************************************************************
201* UIFileTableNavigationWidget implementation. *
202*********************************************************************************************************************************/
203
204UIFileTableNavigationWidget::UIFileTableNavigationWidget(QWidget *pParent /* = 0 */)
205 :QWidget(pParent)
206 , m_pContainer(0)
207 , m_pBreadCrumbs(0)
208 , m_pHistoryComboBox(0)
209 , m_pAddressLineEdit(0)
210 , m_pSwitchButton(0)
211 , m_pathSeparator(UIPathOperations::delimiter)
212{
213 prepare();
214}
215
216void UIFileTableNavigationWidget::setPath(const QString &strLocation)
217{
218 if (m_strCurrentPath == QDir::fromNativeSeparators(strLocation))
219 return;
220
221 m_strCurrentPath = QDir::fromNativeSeparators(strLocation);
222
223 if (m_pBreadCrumbs)
224 m_pBreadCrumbs->setPath(strLocation);
225
226 if (m_pHistoryComboBox)
227 {
228 QString strNativeLocation(strLocation);
229 strNativeLocation.replace(UIPathOperations::delimiter, m_pathSeparator);
230 int itemIndex = m_pHistoryComboBox->findText(strNativeLocation,
231 Qt::MatchExactly | Qt::MatchCaseSensitive);
232 if (itemIndex == -1)
233 {
234 m_pHistoryComboBox->insertItem(m_pHistoryComboBox->count(), strNativeLocation);
235 itemIndex = m_pHistoryComboBox->count() - 1;
236 }
237 m_pHistoryComboBox->setCurrentIndex(itemIndex);
238 emit sigHistoryListChanged();
239 }
240}
241
242void UIFileTableNavigationWidget::reset()
243{
244 if (m_pHistoryComboBox)
245 {
246 m_pHistoryComboBox->blockSignals(true);
247 m_pHistoryComboBox->clear();
248 m_pHistoryComboBox->blockSignals(false);
249 emit sigHistoryListChanged();
250 }
251
252 if (m_pBreadCrumbs)
253 m_pBreadCrumbs->setPath(QString());
254}
255
256void UIFileTableNavigationWidget::setPathSeparator(const QChar &separator)
257{
258 m_pathSeparator = separator;
259 if (m_pBreadCrumbs)
260 m_pBreadCrumbs->setPathSeparator(m_pathSeparator);
261}
262
263bool UIFileTableNavigationWidget::canGoForward() const
264{
265 if (!m_pHistoryComboBox)
266 return false;
267 return (m_pHistoryComboBox->currentIndex() < m_pHistoryComboBox->count() - 1);
268}
269
270bool UIFileTableNavigationWidget::canGoBackward() const
271{
272 if (!m_pHistoryComboBox)
273 return false;
274 return (m_pHistoryComboBox->currentIndex() > 0);
275}
276
277
278void UIFileTableNavigationWidget::goForwardInHistory()
279{
280 if (!m_pHistoryComboBox || m_pHistoryComboBox->currentIndex() >= m_pHistoryComboBox->count() - 1)
281 return;
282 m_pHistoryComboBox->setCurrentIndex(m_pHistoryComboBox->currentIndex() + 1);
283}
284
285void UIFileTableNavigationWidget::goBackwardInHistory()
286{
287 if (!m_pHistoryComboBox || m_pHistoryComboBox->currentIndex() <= 0)
288 return;
289 m_pHistoryComboBox->setCurrentIndex(m_pHistoryComboBox->currentIndex() - 1);
290}
291
292void UIFileTableNavigationWidget::prepare()
293{
294 QHBoxLayout *pLayout = new QHBoxLayout;
295 if (!pLayout)
296 return;
297 pLayout->setSpacing(0);
298 pLayout->setContentsMargins(0, 0, 0, 0);
299
300 m_pContainer = new QStackedWidget;
301 if (m_pContainer)
302 {
303 m_pBreadCrumbs = new UIFileManagerBreadCrumbs;
304 m_pHistoryComboBox = new UIFileManagerHistoryComboBox;
305 m_pAddressLineEdit = new QLineEdit;
306 if (m_pBreadCrumbs && m_pHistoryComboBox)
307 {
308 m_pBreadCrumbs->setIndent(0.5 * qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin));
309 m_pBreadCrumbs->installEventFilter(this);
310 m_pAddressLineEdit->installEventFilter(this);
311 connect(m_pBreadCrumbs, &UIFileManagerBreadCrumbs::linkActivated,
312 this, &UIFileTableNavigationWidget::sltHandlePathChange);
313 connect(m_pHistoryComboBox, &UIFileManagerHistoryComboBox::sigHidePopup,
314 this, &UIFileTableNavigationWidget::sltHandleHidePopup);
315 connect(m_pHistoryComboBox, &UIFileManagerHistoryComboBox::currentTextChanged,
316 this, &UIFileTableNavigationWidget::sltHandlePathChange);
317 connect(m_pAddressLineEdit, &QLineEdit::returnPressed,
318 this, &UIFileTableNavigationWidget::sltAddressLineEdited);
319 m_pContainer->insertWidget(StackedWidgets_BreadCrumbs, m_pBreadCrumbs);
320 m_pContainer->insertWidget(StackedWidgets_History, m_pHistoryComboBox);
321 m_pContainer->insertWidget(StackedWidgets_AddressLine, m_pAddressLineEdit);
322 m_pContainer->setCurrentIndex(StackedWidgets_BreadCrumbs);
323 }
324 pLayout->addWidget(m_pContainer);
325 }
326
327 m_pSwitchButton = new QToolButton;
328 if (m_pSwitchButton)
329 {
330 QStyle *pStyle = QApplication::style();
331 QIcon buttonIcon;
332 if (pStyle)
333 {
334 buttonIcon = pStyle->standardIcon(QStyle::SP_TitleBarUnshadeButton);
335 m_pSwitchButton->setIcon(buttonIcon);
336 }
337 pLayout->addWidget(m_pSwitchButton);
338 connect(m_pSwitchButton, &QToolButton::clicked,
339 this, &UIFileTableNavigationWidget::sltHandleSwitch);
340 }
341 setLayout(pLayout);
342}
343
344bool UIFileTableNavigationWidget::eventFilter(QObject *pObject, QEvent *pEvent)
345{
346 if (pObject == m_pBreadCrumbs && pEvent && pEvent->type() == QEvent::MouseButtonDblClick)
347 {
348 m_pContainer->setCurrentIndex(StackedWidgets_AddressLine);
349 m_pAddressLineEdit->setText(QDir::toNativeSeparators(m_strCurrentPath));
350 m_pAddressLineEdit->setFocus();
351
352 }
353 else if(pObject == m_pAddressLineEdit && pEvent && pEvent->type() == QEvent::FocusOut)
354 m_pContainer->setCurrentIndex(StackedWidgets_BreadCrumbs);
355
356 return QWidget::eventFilter(pObject, pEvent);
357}
358
359void UIFileTableNavigationWidget::sltHandleHidePopup()
360{
361 m_pContainer->setCurrentIndex(StackedWidgets_BreadCrumbs);
362}
363
364void UIFileTableNavigationWidget::sltHandlePathChange(const QString &strPath)
365{
366 emit sigPathChanged(UIPathOperations::replaceDosDelimeter(strPath));
367}
368
369void UIFileTableNavigationWidget::sltHandleSwitch()
370{
371 if (m_pContainer->currentIndex() == StackedWidgets_BreadCrumbs)
372 {
373 m_pContainer->setCurrentIndex(StackedWidgets_History);
374 m_pHistoryComboBox->showPopup();
375 }
376 else
377 {
378 m_pContainer->setCurrentIndex(StackedWidgets_BreadCrumbs);
379 m_pHistoryComboBox->hidePopup();
380 }
381}
382
383void UIFileTableNavigationWidget::sltAddressLineEdited()
384{
385 sigPathChanged(QDir::fromNativeSeparators(m_pAddressLineEdit->text()));
386}
387
388#include "UIFileTableNavigationWidget.moc"
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