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 <QDebug> | ||||
ngraham: Don't want this in production code | |||||
54 | #include <QMimeData> | 55 | #include <QMimeData> | ||
56 | #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 | 57 | | |||
56 | using namespace KDEPrivate; | 58 | using namespace KDEPrivate; | ||
57 | 59 | | |||
58 | struct LocationData { | 60 | struct LocationData { | ||
59 | QUrl url; | 61 | QUrl url; | ||
60 | #ifndef KIOFILEWIDGETS_NO_DEPRECATED | 62 | #ifndef KIOFILEWIDGETS_NO_DEPRECATED | ||
61 | QUrl rootUrl; // KDE5: remove after the deprecated methods have been removed | 63 | QUrl rootUrl; // KDE5: remove after the deprecated methods have been removed | ||
62 | QPoint pos; // KDE5: remove after the deprecated methods have been removed | 64 | QPoint pos; // KDE5: remove after the deprecated methods have been removed | ||
Show All 9 Lines | 71 | public: | |||
72 | void initialize(const QUrl &url); | 74 | void initialize(const QUrl &url); | ||
73 | 75 | | |||
74 | /** Applies the edited URL in m_pathBox to the URL navigator */ | 76 | /** Applies the edited URL in m_pathBox to the URL navigator */ | ||
75 | void applyUncommittedUrl(); | 77 | void applyUncommittedUrl(); | ||
76 | 78 | | |||
77 | void slotReturnPressed(); | 79 | void slotReturnPressed(); | ||
78 | void slotProtocolChanged(const QString &); | 80 | void slotProtocolChanged(const QString &); | ||
79 | void openPathSelectorMenu(); | 81 | void openPathSelectorMenu(); | ||
82 | void openHierarchyMenu(); | ||||
83 | QString parentDirectory(const QString ¤tPath) const; | ||||
80 | 84 | | |||
81 | /** | 85 | /** | ||
82 | * Appends the widget at the end of the URL navigator. It is assured | 86 | * 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 | 87 | * that the filler widget remains as last widget to fill the remaining | ||
84 | * width. | 88 | * width. | ||
85 | */ | 89 | */ | ||
86 | void appendWidget(QWidget *widget, int stretch = 0); | 90 | void appendWidget(QWidget *widget, int stretch = 0); | ||
87 | 91 | | |||
Show All 14 Lines | |||||
102 | 106 | | |||
103 | /** | 107 | /** | ||
104 | * Is invoked when a navigator button has been clicked. Changes the URL | 108 | * 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 | 109 | * 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. | 110 | * mouse button has been used, the signal tabRequested() will be emitted. | ||
107 | */ | 111 | */ | ||
108 | void slotNavigatorButtonClicked(const QUrl &url, Qt::MouseButton button, Qt::KeyboardModifiers modifiers); | 112 | void slotNavigatorButtonClicked(const QUrl &url, Qt::MouseButton button, Qt::KeyboardModifiers modifiers); | ||
109 | 113 | | |||
114 | void slotKeyUpPressed(); | ||||
115 | void keyUpPressed(); | ||||
116 | void keyDownPressed(); | ||||
117 | | ||||
110 | void openContextMenu(const QPoint &p); | 118 | void openContextMenu(const QPoint &p); | ||
111 | 119 | | |||
112 | void slotPathBoxChanged(const QString &text); | 120 | void slotPathBoxChanged(const QString &text); | ||
113 | 121 | | |||
114 | void updateContent(); | 122 | void updateContent(); | ||
115 | 123 | | |||
124 | | ||||
ngraham: Unrelated whitespace change | |||||
116 | /** | 125 | /** | ||
117 | * Updates all buttons to have one button for each part of the | 126 | * Updates all buttons to have one button for each part of the | ||
118 | * current URL. Existing buttons, which are available by m_navButtons, | 127 | * current URL. Existing buttons, which are available by m_navButtons, | ||
119 | * are reused if possible. If the URL is longer, new buttons will be | 128 | * 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. | 129 | * created, if the URL is shorter, the remaining buttons will be deleted. | ||
121 | * @param startIndex Start index of URL part (/), where the buttons | 130 | * @param startIndex Start index of URL part (/), where the buttons | ||
122 | * should be created for each following part. | 131 | * should be created for each following part. | ||
123 | */ | 132 | */ | ||
▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Line(s) | 224 | { | |||
276 | m_layout->addWidget(m_protocols); | 285 | m_layout->addWidget(m_protocols); | ||
277 | m_layout->addWidget(m_dropDownButton); | 286 | m_layout->addWidget(m_dropDownButton); | ||
278 | m_layout->addWidget(m_pathBox, 1); | 287 | m_layout->addWidget(m_pathBox, 1); | ||
279 | m_layout->addWidget(m_toggleEditableMode); | 288 | m_layout->addWidget(m_toggleEditableMode); | ||
280 | 289 | | |||
281 | q->setContextMenuPolicy(Qt::CustomContextMenu); | 290 | q->setContextMenuPolicy(Qt::CustomContextMenu); | ||
282 | connect(q, SIGNAL(customContextMenuRequested(QPoint)), | 291 | connect(q, SIGNAL(customContextMenuRequested(QPoint)), | ||
283 | q, SLOT(openContextMenu(QPoint))); | 292 | q, SLOT(openContextMenu(QPoint))); | ||
293 | connect(q, SIGNAL(keyUpPressed()), q, SLOT(slotKeyUpPressed())); | ||||
294 | connect(q, SIGNAL(keyDownPressed()), | ||||
295 | q, SLOT(openHierarchyMenu())); | ||||
284 | } | 296 | } | ||
285 | 297 | | |||
286 | void KUrlNavigator::Private::initialize(const QUrl &url) | 298 | void KUrlNavigator::Private::initialize(const QUrl &url) | ||
287 | { | 299 | { | ||
288 | LocationData data; | 300 | LocationData data; | ||
289 | data.url = url.adjusted(QUrl::NormalizePathSegments); | 301 | data.url = url.adjusted(QUrl::NormalizePathSegments); | ||
290 | m_history.prepend(data); | 302 | m_history.prepend(data); | ||
291 | 303 | | |||
Show All 30 Lines | 321 | { | |||
322 | 334 | | |||
323 | q->setLocationUrl(typedUrl); | 335 | q->setLocationUrl(typedUrl); | ||
324 | // The URL might have been adjusted by KUrlNavigator::setUrl(), hence | 336 | // The URL might have been adjusted by KUrlNavigator::setUrl(), hence | ||
325 | // synchronize the result in the path box. | 337 | // synchronize the result in the path box. | ||
326 | const QUrl currentUrl = q->locationUrl(); | 338 | const QUrl currentUrl = q->locationUrl(); | ||
327 | m_pathBox->setUrl(currentUrl); | 339 | m_pathBox->setUrl(currentUrl); | ||
328 | } | 340 | } | ||
329 | 341 | | |||
342 | void KUrlNavigator::Private::slotKeyUpPressed() | ||||
343 | { | ||||
344 | emit q->goUp(); | ||||
345 | /* | ||||
346 | * Ugly hack to get focus back | ||||
347 | */ | ||||
348 | slotToggleEditableButtonPressed(); | ||||
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. | |||||
349 | QTimer::singleShot(10, q->editor()->lineEdit(), SLOT(setFocus())); | ||||
350 | } | ||||
351 | | ||||
330 | void KUrlNavigator::Private::slotReturnPressed() | 352 | void KUrlNavigator::Private::slotReturnPressed() | ||
331 | { | 353 | { | ||
332 | applyUncommittedUrl(); | 354 | applyUncommittedUrl(); | ||
333 | 355 | | |||
334 | emit q->returnPressed(); | 356 | emit q->returnPressed(); | ||
335 | 357 | | |||
336 | if (QApplication::keyboardModifiers() & Qt::ControlModifier) { | 358 | if (QApplication::keyboardModifiers() & Qt::ControlModifier) { | ||
337 | // Pressing Ctrl+Return automatically switches back to the breadcrumb mode. | 359 | // Pressing Ctrl+Return automatically switches back to the breadcrumb mode. | ||
Show All 15 Lines | 374 | } else { | |||
353 | // With no authority set we'll get e.g. "ftp:" instead of "ftp://". | 375 | // 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. | 376 | // We want the latter, so let's set an empty authority. | ||
355 | url.setAuthority(QString()); | 377 | url.setAuthority(QString()); | ||
356 | } | 378 | } | ||
357 | 379 | | |||
358 | m_pathBox->setEditUrl(url); | 380 | m_pathBox->setEditUrl(url); | ||
359 | } | 381 | } | ||
360 | 382 | | |||
383 | QString KUrlNavigator::Private::parentDirectory(const QString ¤tPath) const | ||||
384 | { | ||||
385 | const int slash = currentPath.lastIndexOf(QLatin1Char('/')); | ||||
386 | if (slash == -1) | ||||
387 | return QString(); | ||||
ngraham: Coding style: don't omit braces for single-line conditionals | |||||
388 | else if (slash == 0) | ||||
389 | return QString(QLatin1Char('/')); | ||||
390 | else if (slash == currentPath.length()-1) | ||||
391 | return parentDirectory(currentPath.left(slash)); | ||||
392 | return currentPath.left(slash); | ||||
393 | } | ||||
394 | | ||||
395 | void KUrlNavigator::Private::openHierarchyMenu() { | ||||
396 | QUrl currentDirectory = q->locationUrl(); | ||||
397 | QStringList urlList = QStringList(); | ||||
398 | bool hasParent = true; | ||||
399 | while (hasParent) { | ||||
400 | urlList.append(currentDirectory.path()); | ||||
ngraham: Use `toLocalFile()` instead of `path()`, otherwise it breaks on Windows | |||||
401 | hasParent = (currentDirectory != QUrl(parentDirectory(currentDirectory.path()))); | ||||
402 | qInfo() << currentDirectory.path(); | ||||
ngraham: Don't want this in production code | |||||
403 | currentDirectory = QUrl(parentDirectory(currentDirectory.path())); | ||||
404 | } | ||||
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… | |||||
405 | m_pathBox->setUrls(urlList, false); | ||||
406 | m_pathBox->showPopup(); | ||||
krutovmikhail: Is QMenu a proper widget for dropdown list here? | |||||
407 | } | ||||
408 | | ||||
361 | void KUrlNavigator::Private::openPathSelectorMenu() | 409 | void KUrlNavigator::Private::openPathSelectorMenu() | ||
362 | { | 410 | { | ||
363 | if (m_navButtons.count() <= 0) { | 411 | if (m_navButtons.count() <= 0) { | ||
364 | return; | 412 | return; | ||
365 | } | 413 | } | ||
366 | 414 | | |||
367 | const QUrl firstVisibleUrl = m_navButtons.first()->url(); | 415 | const QUrl firstVisibleUrl = m_navButtons.first()->url(); | ||
368 | 416 | | |||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Line(s) | 463 | if (popup) { | |||
416 | popup->deleteLater(); | 464 | popup->deleteLater(); | ||
417 | } | 465 | } | ||
418 | } | 466 | } | ||
419 | 467 | | |||
420 | void KUrlNavigator::Private::slotToggleEditableButtonPressed() | 468 | void KUrlNavigator::Private::slotToggleEditableButtonPressed() | ||
421 | { | 469 | { | ||
422 | if (m_editable) { | 470 | if (m_editable) { | ||
423 | applyUncommittedUrl(); | 471 | applyUncommittedUrl(); | ||
472 | m_pathBox->removeEventFilter(q); | ||||
473 | } else { | ||||
474 | m_pathBox->installEventFilter(q); | ||||
ngraham: This feels like a hack | |||||
424 | } | 475 | } | ||
425 | | ||||
ngraham: Unrelated whitespace change | |||||
426 | switchView(); | 476 | switchView(); | ||
427 | } | 477 | } | ||
428 | 478 | | |||
429 | void KUrlNavigator::Private::switchView() | 479 | void KUrlNavigator::Private::switchView() | ||
430 | { | 480 | { | ||
431 | m_toggleEditableMode->setFocus(); | 481 | m_toggleEditableMode->setFocus(); | ||
432 | m_editable = !m_editable; | 482 | m_editable = !m_editable; | ||
433 | m_toggleEditableMode->setChecked(m_editable); | 483 | m_toggleEditableMode->setChecked(m_editable); | ||
▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Line(s) | 598 | { | |||
553 | 603 | | |||
554 | if (m_editable) { | 604 | if (m_editable) { | ||
555 | m_protocols->hide(); | 605 | m_protocols->hide(); | ||
556 | m_dropDownButton->hide(); | 606 | m_dropDownButton->hide(); | ||
557 | 607 | | |||
558 | deleteButtons(); | 608 | deleteButtons(); | ||
559 | m_toggleEditableMode->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); | 609 | m_toggleEditableMode->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); | ||
560 | q->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); | 610 | q->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); | ||
561 | | ||||
ngraham: Unrelated whitespace change | |||||
562 | m_pathBox->show(); | 611 | m_pathBox->show(); | ||
563 | m_pathBox->setUrl(currentUrl); | 612 | m_pathBox->setUrl(currentUrl); | ||
564 | } else { | 613 | } else { | ||
565 | m_pathBox->hide(); | 614 | m_pathBox->hide(); | ||
566 | 615 | | |||
567 | m_protocols->hide(); | 616 | m_protocols->hide(); | ||
568 | 617 | | |||
569 | m_toggleEditableMode->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); | 618 | m_toggleEditableMode->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); | ||
▲ Show 20 Lines • Show All 655 Lines • ▼ Show 20 Line(s) | 1267 | case QEvent::FocusIn: | |||
1225 | } | 1274 | } | ||
1226 | break; | 1275 | break; | ||
1227 | 1276 | | |||
1228 | case QEvent::FocusOut: | 1277 | case QEvent::FocusOut: | ||
1229 | foreach (KUrlNavigatorButton *button, d->m_navButtons) { | 1278 | foreach (KUrlNavigatorButton *button, d->m_navButtons) { | ||
1230 | button->setShowMnemonic(false); | 1279 | button->setShowMnemonic(false); | ||
1231 | } | 1280 | } | ||
1232 | break; | 1281 | break; | ||
1233 | 1282 | case QEvent::KeyRelease: | |||
1283 | { | ||||
1284 | QKeyEvent *actualEvent = static_cast<QKeyEvent *>(event); | ||||
1285 | if (actualEvent->key() == Qt::Key_Up) { | ||||
1286 | emit keyUpPressed(); | ||||
1287 | return true; | ||||
ngraham: You could remove the `true` from these | |||||
1288 | } else if (actualEvent->key() == Qt::Key_Down) { | ||||
1289 | emit keyDownPressed(); | ||||
1290 | return true; | ||||
1291 | } | ||||
1292 | break; | ||||
1293 | } | ||||
1234 | default: | 1294 | default: | ||
1235 | break; | 1295 | break; | ||
1236 | } | 1296 | } | ||
1237 | 1297 | | |||
1238 | return QWidget::eventFilter(watched, event); | 1298 | return QWidget::eventFilter(watched, event); | ||
1239 | } | 1299 | } | ||
1240 | 1300 | | |||
1241 | int KUrlNavigator::historySize() const | 1301 | int KUrlNavigator::historySize() const | ||
▲ Show 20 Lines • Show All 89 Lines • Show Last 20 Lines |
Don't want this in production code