Changeset View
Changeset View
Standalone View
Standalone View
src/filewidgets/kurlnavigator.cpp
Show First 20 Lines • Show All 45 Lines • ▼ Show 20 Line(s) | |||||
46 | #include <QClipboard> | 46 | #include <QClipboard> | ||
47 | #include <QDropEvent> | 47 | #include <QDropEvent> | ||
48 | #include <QKeyEvent> | 48 | #include <QKeyEvent> | ||
49 | #include <QLabel> | 49 | #include <QLabel> | ||
50 | #include <QMenu> | 50 | #include <QMenu> | ||
51 | #include <QPainter> | 51 | #include <QPainter> | ||
52 | #include <QStyleOption> | 52 | #include <QStyleOption> | ||
53 | #include <qmimedatabase.h> | 53 | #include <qmimedatabase.h> | ||
54 | #include <QMimeData> | 54 | #include <QMimeData> | ||
ngraham: Don't want this in production code | |||||
55 | #include <QLineEdit> | ||||
The existing list is not 100% sorted alphabetically, but let's assume alphabetical sorting for new entries, so this should go right below #include <QLabel> ngraham: The existing list is not 100% sorted alphabetically, but let's assume alphabetical sorting for… | |||||
55 | 56 | | |||
56 | using namespace KDEPrivate; | 57 | using namespace KDEPrivate; | ||
57 | 58 | | |||
58 | struct LocationData { | 59 | struct LocationData { | ||
59 | QUrl url; | 60 | QUrl url; | ||
60 | #ifndef KIOFILEWIDGETS_NO_DEPRECATED | 61 | #ifndef KIOFILEWIDGETS_NO_DEPRECATED | ||
61 | QUrl rootUrl; // KDE5: remove after the deprecated methods have been removed | 62 | QUrl rootUrl; // KDE5: remove after the deprecated methods have been removed | ||
62 | QPoint pos; // KDE5: remove after the deprecated methods have been removed | 63 | QPoint pos; // KDE5: remove after the deprecated methods have been removed | ||
Show All 9 Lines | 70 | public: | |||
72 | void initialize(const QUrl &url); | 73 | void initialize(const QUrl &url); | ||
73 | 74 | | |||
74 | /** Applies the edited URL in m_pathBox to the URL navigator */ | 75 | /** Applies the edited URL in m_pathBox to the URL navigator */ | ||
75 | void applyUncommittedUrl(); | 76 | void applyUncommittedUrl(); | ||
76 | 77 | | |||
77 | void slotReturnPressed(); | 78 | void slotReturnPressed(); | ||
78 | void slotProtocolChanged(const QString &); | 79 | void slotProtocolChanged(const QString &); | ||
79 | void openPathSelectorMenu(); | 80 | void openPathSelectorMenu(); | ||
81 | void openHierarchyMenu(); | ||||
82 | QString parentDirectory(const QString ¤tPath) const; | ||||
80 | 83 | | |||
81 | /** | 84 | /** | ||
82 | * Appends the widget at the end of the URL navigator. It is assured | 85 | * Appends the widget at the end of the URL navigator. It is assured | ||
83 | * that the filler widget remains as last widget to fill the remaining | 86 | * that the filler widget remains as last widget to fill the remaining | ||
84 | * width. | 87 | * width. | ||
85 | */ | 88 | */ | ||
86 | void appendWidget(QWidget *widget, int stretch = 0); | 89 | void appendWidget(QWidget *widget, int stretch = 0); | ||
87 | 90 | | |||
Show All 14 Lines | |||||
102 | 105 | | |||
103 | /** | 106 | /** | ||
104 | * Is invoked when a navigator button has been clicked. Changes the URL | 107 | * Is invoked when a navigator button has been clicked. Changes the URL | ||
105 | * of the navigator if the left mouse button has been used. If the middle | 108 | * of the navigator if the left mouse button has been used. If the middle | ||
106 | * mouse button has been used, the signal tabRequested() will be emitted. | 109 | * mouse button has been used, the signal tabRequested() will be emitted. | ||
107 | */ | 110 | */ | ||
108 | void slotNavigatorButtonClicked(const QUrl &url, Qt::MouseButton button, Qt::KeyboardModifiers modifiers); | 111 | void slotNavigatorButtonClicked(const QUrl &url, Qt::MouseButton button, Qt::KeyboardModifiers modifiers); | ||
109 | 112 | | |||
113 | void slotKeyUpPressed(); | ||||
114 | void keyUpPressed(); | ||||
115 | void keyDownPressed(); | ||||
116 | | ||||
110 | void openContextMenu(const QPoint &p); | 117 | void openContextMenu(const QPoint &p); | ||
111 | 118 | | |||
112 | void slotPathBoxChanged(const QString &text); | 119 | void slotPathBoxChanged(const QString &text); | ||
113 | 120 | | |||
114 | void updateContent(); | 121 | void updateContent(); | ||
115 | 122 | | |||
ngraham: Unrelated whitespace change | |||||
116 | /** | 123 | /** | ||
117 | * Updates all buttons to have one button for each part of the | 124 | * Updates all buttons to have one button for each part of the | ||
118 | * current URL. Existing buttons, which are available by m_navButtons, | 125 | * current URL. Existing buttons, which are available by m_navButtons, | ||
119 | * are reused if possible. If the URL is longer, new buttons will be | 126 | * are reused if possible. If the URL is longer, new buttons will be | ||
120 | * created, if the URL is shorter, the remaining buttons will be deleted. | 127 | * created, if the URL is shorter, the remaining buttons will be deleted. | ||
121 | * @param startIndex Start index of URL part (/), where the buttons | 128 | * @param startIndex Start index of URL part (/), where the buttons | ||
122 | * should be created for each following part. | 129 | * should be created for each following part. | ||
123 | */ | 130 | */ | ||
▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Line(s) | 222 | { | |||
272 | 279 | | |||
273 | if (m_placesSelector != nullptr) { | 280 | if (m_placesSelector != nullptr) { | ||
274 | m_layout->addWidget(m_placesSelector); | 281 | m_layout->addWidget(m_placesSelector); | ||
275 | } | 282 | } | ||
276 | m_layout->addWidget(m_protocols); | 283 | m_layout->addWidget(m_protocols); | ||
277 | m_layout->addWidget(m_dropDownButton); | 284 | m_layout->addWidget(m_dropDownButton); | ||
278 | m_layout->addWidget(m_pathBox, 1); | 285 | m_layout->addWidget(m_pathBox, 1); | ||
279 | m_layout->addWidget(m_toggleEditableMode); | 286 | m_layout->addWidget(m_toggleEditableMode); | ||
287 | m_pathBox->installEventFilter(q); | ||||
280 | 288 | | |||
281 | q->setContextMenuPolicy(Qt::CustomContextMenu); | 289 | q->setContextMenuPolicy(Qt::CustomContextMenu); | ||
282 | connect(q, SIGNAL(customContextMenuRequested(QPoint)), | 290 | connect(q, SIGNAL(customContextMenuRequested(QPoint)), | ||
283 | q, SLOT(openContextMenu(QPoint))); | 291 | q, SLOT(openContextMenu(QPoint))); | ||
292 | connect(q, SIGNAL(keyUpPressed()), q, SLOT(slotKeyUpPressed())); | ||||
293 | connect(q, SIGNAL(keyDownPressed()), | ||||
294 | q, SLOT(openHierarchyMenu())); | ||||
284 | } | 295 | } | ||
285 | 296 | | |||
286 | void KUrlNavigator::Private::initialize(const QUrl &url) | 297 | void KUrlNavigator::Private::initialize(const QUrl &url) | ||
287 | { | 298 | { | ||
288 | LocationData data; | 299 | LocationData data; | ||
289 | data.url = url.adjusted(QUrl::NormalizePathSegments); | 300 | data.url = url.adjusted(QUrl::NormalizePathSegments); | ||
290 | m_history.prepend(data); | 301 | m_history.prepend(data); | ||
291 | 302 | | |||
Show All 30 Lines | 320 | { | |||
322 | 333 | | |||
323 | q->setLocationUrl(typedUrl); | 334 | q->setLocationUrl(typedUrl); | ||
324 | // The URL might have been adjusted by KUrlNavigator::setUrl(), hence | 335 | // The URL might have been adjusted by KUrlNavigator::setUrl(), hence | ||
325 | // synchronize the result in the path box. | 336 | // synchronize the result in the path box. | ||
326 | const QUrl currentUrl = q->locationUrl(); | 337 | const QUrl currentUrl = q->locationUrl(); | ||
327 | m_pathBox->setUrl(currentUrl); | 338 | m_pathBox->setUrl(currentUrl); | ||
328 | } | 339 | } | ||
329 | 340 | | |||
341 | void KUrlNavigator::Private::slotKeyUpPressed() | ||||
342 | { | ||||
343 | emit q->goUp(); | ||||
344 | } | ||||
345 | | ||||
330 | void KUrlNavigator::Private::slotReturnPressed() | 346 | void KUrlNavigator::Private::slotReturnPressed() | ||
331 | { | 347 | { | ||
This works in Dolphin, but causes the navigator to switch back to breadcrumbs mode in Gwenview. I think we need to instead fix whatever bug is causing the desire for thus ugly hack. :) ngraham: This works in Dolphin, but causes the navigator to switch back to breadcrumbs mode in Gwenview. | |||||
332 | applyUncommittedUrl(); | 348 | applyUncommittedUrl(); | ||
333 | 349 | | |||
334 | emit q->returnPressed(); | 350 | emit q->returnPressed(); | ||
335 | 351 | | |||
336 | if (QApplication::keyboardModifiers() & Qt::ControlModifier) { | 352 | if (QApplication::keyboardModifiers() & Qt::ControlModifier) { | ||
337 | // Pressing Ctrl+Return automatically switches back to the breadcrumb mode. | 353 | // Pressing Ctrl+Return automatically switches back to the breadcrumb mode. | ||
338 | // The switch must be done asynchronously, as we are in the context of the | 354 | // The switch must be done asynchronously, as we are in the context of the | ||
339 | // editor. | 355 | // editor. | ||
Show All 13 Lines | 368 | } else { | |||
353 | // With no authority set we'll get e.g. "ftp:" instead of "ftp://". | 369 | // With no authority set we'll get e.g. "ftp:" instead of "ftp://". | ||
354 | // We want the latter, so let's set an empty authority. | 370 | // We want the latter, so let's set an empty authority. | ||
355 | url.setAuthority(QString()); | 371 | url.setAuthority(QString()); | ||
356 | } | 372 | } | ||
357 | 373 | | |||
358 | m_pathBox->setEditUrl(url); | 374 | m_pathBox->setEditUrl(url); | ||
359 | } | 375 | } | ||
360 | 376 | | |||
377 | QString KUrlNavigator::Private::parentDirectory(const QString ¤tPath) const | ||||
378 | { | ||||
379 | const int slash = currentPath.lastIndexOf(QLatin1Char('/')); | ||||
380 | if (slash == -1) { | ||||
381 | return QString(); | ||||
ngraham: Coding style: don't omit braces for single-line conditionals | |||||
382 | } | ||||
383 | else if (slash == 0) { | ||||
384 | return QString(QLatin1Char('/')); | ||||
385 | } | ||||
386 | else if (slash == currentPath.length()-1) { | ||||
387 | return parentDirectory(currentPath.left(slash)); | ||||
388 | } | ||||
389 | return currentPath.left(slash); | ||||
390 | } | ||||
391 | | ||||
392 | void KUrlNavigator::Private::openHierarchyMenu() { | ||||
393 | QUrl currentDirectory = q->locationUrl(); | ||||
394 | QStringList urlList = QStringList(); | ||||
ngraham: Use `toLocalFile()` instead of `path()`, otherwise it breaks on Windows | |||||
395 | bool hasParent = true; | ||||
396 | while (hasParent) { | ||||
ngraham: Don't want this in production code | |||||
397 | urlList.append(currentDirectory.toLocalFile()); | ||||
398 | hasParent = (currentDirectory != QUrl(parentDirectory(currentDirectory.path()))); | ||||
QUrl(currentDirectory.resolved(levelUp)) for some reason results in missed 1st level directory, eg list for /home/neko would be: /home/neko / Is this a proper approach or should I do it somehow differently? krutovmikhail: QUrl(currentDirectory.resolved(levelUp)) for some reason results in missed 1st level directory… | |||||
399 | currentDirectory = QUrl(parentDirectory(currentDirectory.path())); | ||||
400 | } | ||||
krutovmikhail: Is QMenu a proper widget for dropdown list here? | |||||
401 | m_pathBox->setUrls(urlList, KUrlComboBox::KeepOld); | ||||
402 | m_pathBox->showPopup(); | ||||
403 | } | ||||
404 | | ||||
361 | void KUrlNavigator::Private::openPathSelectorMenu() | 405 | void KUrlNavigator::Private::openPathSelectorMenu() | ||
362 | { | 406 | { | ||
363 | if (m_navButtons.count() <= 0) { | 407 | if (m_navButtons.count() <= 0) { | ||
364 | return; | 408 | return; | ||
365 | } | 409 | } | ||
366 | 410 | | |||
367 | const QUrl firstVisibleUrl = m_navButtons.first()->url(); | 411 | const QUrl firstVisibleUrl = m_navButtons.first()->url(); | ||
368 | 412 | | |||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Line(s) | |||||
417 | } | 461 | } | ||
418 | } | 462 | } | ||
419 | 463 | | |||
420 | void KUrlNavigator::Private::slotToggleEditableButtonPressed() | 464 | void KUrlNavigator::Private::slotToggleEditableButtonPressed() | ||
421 | { | 465 | { | ||
422 | if (m_editable) { | 466 | if (m_editable) { | ||
423 | applyUncommittedUrl(); | 467 | applyUncommittedUrl(); | ||
424 | } | 468 | } | ||
425 | 469 | | |||
ngraham: Unrelated whitespace change | |||||
426 | switchView(); | 470 | switchView(); | ||
ngraham: This feels like a hack | |||||
427 | } | 471 | } | ||
428 | 472 | | |||
429 | void KUrlNavigator::Private::switchView() | 473 | void KUrlNavigator::Private::switchView() | ||
430 | { | 474 | { | ||
431 | m_toggleEditableMode->setFocus(); | 475 | m_toggleEditableMode->setFocus(); | ||
432 | m_editable = !m_editable; | 476 | m_editable = !m_editable; | ||
433 | m_toggleEditableMode->setChecked(m_editable); | 477 | m_toggleEditableMode->setChecked(m_editable); | ||
434 | updateContent(); | 478 | updateContent(); | ||
▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Line(s) | 592 | { | |||
553 | 597 | | |||
554 | if (m_editable) { | 598 | if (m_editable) { | ||
555 | m_protocols->hide(); | 599 | m_protocols->hide(); | ||
556 | m_dropDownButton->hide(); | 600 | m_dropDownButton->hide(); | ||
557 | 601 | | |||
558 | deleteButtons(); | 602 | deleteButtons(); | ||
559 | m_toggleEditableMode->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); | 603 | m_toggleEditableMode->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); | ||
560 | q->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); | 604 | q->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); | ||
561 | 605 | | |||
ngraham: Unrelated whitespace change | |||||
562 | m_pathBox->show(); | 606 | m_pathBox->show(); | ||
563 | m_pathBox->setUrl(currentUrl); | 607 | m_pathBox->setUrl(currentUrl); | ||
564 | } else { | 608 | } else { | ||
565 | m_pathBox->hide(); | 609 | m_pathBox->hide(); | ||
566 | 610 | | |||
567 | m_protocols->hide(); | 611 | m_protocols->hide(); | ||
568 | 612 | | |||
569 | m_toggleEditableMode->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); | 613 | m_toggleEditableMode->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); | ||
▲ Show 20 Lines • Show All 655 Lines • ▼ Show 20 Line(s) | 1262 | case QEvent::FocusIn: | |||
1225 | } | 1269 | } | ||
1226 | break; | 1270 | break; | ||
1227 | 1271 | | |||
1228 | case QEvent::FocusOut: | 1272 | case QEvent::FocusOut: | ||
1229 | foreach (KUrlNavigatorButton *button, d->m_navButtons) { | 1273 | foreach (KUrlNavigatorButton *button, d->m_navButtons) { | ||
1230 | button->setShowMnemonic(false); | 1274 | button->setShowMnemonic(false); | ||
1231 | } | 1275 | } | ||
1232 | break; | 1276 | break; | ||
1233 | 1277 | case QEvent::KeyRelease: | |||
1278 | { | ||||
1279 | QKeyEvent *actualEvent = static_cast<QKeyEvent *>(event); | ||||
1280 | if (actualEvent->key() == Qt::Key_Up) { | ||||
1281 | emit keyUpPressed(); | ||||
1282 | } else if (actualEvent->key() == Qt::Key_Down) { | ||||
ngraham: You could remove the `true` from these | |||||
1283 | emit keyDownPressed(); | ||||
1284 | } | ||||
1285 | break; | ||||
1286 | } | ||||
1234 | default: | 1287 | default: | ||
1235 | break; | 1288 | break; | ||
1236 | } | 1289 | } | ||
1237 | 1290 | | |||
1238 | return QWidget::eventFilter(watched, event); | 1291 | return QWidget::eventFilter(watched, event); | ||
1239 | } | 1292 | } | ||
1240 | 1293 | | |||
1241 | int KUrlNavigator::historySize() const | 1294 | int KUrlNavigator::historySize() const | ||
▲ Show 20 Lines • Show All 89 Lines • Show Last 20 Lines |
Don't want this in production code