1 | /***************************************************************************** |
2 | * Copyright (C) 2006-2010 by Peter Penz <peter.penz@gmx.at> * |
3 | * Copyright (C) 2006 by Aaron J. Seigo <aseigo@kde.org> * |
4 | * Copyright (C) 2007 by Kevin Ottens <ervin@kde.org> * |
5 | * Copyright (C) 2007 by Urs Wolfer <uwolfer @ kde.org> * |
6 | * * |
7 | * This library is free software; you can redistribute it and/or * |
8 | * modify it under the terms of the GNU Library General Public * |
9 | * License as published by the Free Software Foundation; either * |
10 | * version 2 of the License, or (at your option) any later version. * |
11 | * * |
12 | * This library is distributed in the hope that it will be useful, * |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * |
15 | * Library General Public License for more details. * |
16 | * * |
17 | * You should have received a copy of the GNU Library General Public License * |
18 | * along with this library; see the file COPYING.LIB. If not, write to * |
19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * |
20 | * Boston, MA 02110-1301, USA. * |
21 | *****************************************************************************/ |
22 | |
23 | #include "kurlnavigator.h" |
24 | |
25 | #include "kurlnavigatorplacesselector_p.h" |
26 | #include "kurlnavigatorprotocolcombo_p.h" |
27 | #include "kurlnavigatordropdownbutton_p.h" |
28 | #include "kurlnavigatorbutton_p.h" |
29 | #include "kurlnavigatortogglebutton_p.h" |
30 | |
31 | #include <kfileitem.h> |
32 | #include <kfileplacesmodel.h> |
33 | #include <kglobalsettings.h> |
34 | #include <kicon.h> |
35 | #include <klocale.h> |
36 | #include <kmenu.h> |
37 | #include <kprotocolinfo.h> |
38 | #include <kurlcombobox.h> |
39 | #include <kurlcompletion.h> |
40 | #include <kurifilter.h> |
41 | |
42 | #include <QtCore/QDir> |
43 | #include <QtCore/QLinkedList> |
44 | #include <QtCore/QTimer> |
45 | #include <QtGui/QApplication> |
46 | #include <QtGui/QBoxLayout> |
47 | #include <QtGui/QClipboard> |
48 | #include <QtGui/QDropEvent> |
49 | #include <QtGui/QKeyEvent> |
50 | #include <QtGui/QLabel> |
51 | #include <QtGui/QPainter> |
52 | #include <QtGui/QStyleOption> |
53 | |
54 | #include <fixx11h.h> |
55 | |
56 | using namespace KDEPrivate; |
57 | |
58 | struct LocationData |
59 | { |
60 | KUrl url; |
61 | #ifndef KDE_NO_DEPRECATED |
62 | KUrl rootUrl; // KDE5: remove after the deprecated methods have been removed |
63 | QPoint pos; // KDE5: remove after the deprecated methods have been removed |
64 | #endif |
65 | QByteArray state; |
66 | }; |
67 | |
68 | class KUrlNavigator::Private |
69 | { |
70 | public: |
71 | Private(KUrlNavigator* q, KFilePlacesModel* placesModel); |
72 | |
73 | void initialize(const KUrl& url); |
74 | |
75 | void slotReturnPressed(); |
76 | void slotProtocolChanged(const QString&); |
77 | void openPathSelectorMenu(); |
78 | |
79 | /** |
80 | * Appends the widget at the end of the URL navigator. It is assured |
81 | * that the filler widget remains as last widget to fill the remaining |
82 | * width. |
83 | */ |
84 | void appendWidget(QWidget* widget, int stretch = 0); |
85 | |
86 | /** |
87 | * Switches the navigation bar between the breadcrumb view and the |
88 | * traditional view (see setUrlEditable()) and is connected to the clicked signal |
89 | * of the navigation bar button. |
90 | */ |
91 | void switchView(); |
92 | |
93 | /** Emits the signal urlsDropped(). */ |
94 | void dropUrls(const KUrl& destination, QDropEvent* event); |
95 | |
96 | /** |
97 | * Is invoked when a navigator button has been clicked. Changes the URL |
98 | * of the navigator if the left mouse button has been used. If the middle |
99 | * mouse button has been used, the signal tabRequested() will be emitted. |
100 | */ |
101 | void slotNavigatorButtonClicked(const KUrl& url, Qt::MouseButton button); |
102 | |
103 | void openContextMenu(); |
104 | |
105 | void slotPathBoxChanged(const QString& text); |
106 | |
107 | void updateContent(); |
108 | |
109 | /** |
110 | * Updates all buttons to have one button for each part of the |
111 | * current URL. Existing buttons, which are available by m_navButtons, |
112 | * are reused if possible. If the URL is longer, new buttons will be |
113 | * created, if the URL is shorter, the remaining buttons will be deleted. |
114 | * @param startIndex Start index of URL part (/), where the buttons |
115 | * should be created for each following part. |
116 | */ |
117 | void updateButtons(int startIndex); |
118 | |
119 | /** |
120 | * Updates the visibility state of all buttons describing the URL. If the |
121 | * width of the URL navigator is too small, the buttons representing the upper |
122 | * paths of the URL will be hidden and moved to a drop down menu. |
123 | */ |
124 | void updateButtonVisibility(); |
125 | |
126 | /** |
127 | * @return Text for the first button of the URL navigator. |
128 | */ |
129 | QString firstButtonText() const; |
130 | |
131 | /** |
132 | * Returns the URL that should be applied for the button with the index \a index. |
133 | */ |
134 | KUrl buttonUrl(int index) const; |
135 | |
136 | void switchToBreadcrumbMode(); |
137 | |
138 | /** |
139 | * Deletes all URL navigator buttons. m_navButtons is |
140 | * empty after this operation. |
141 | */ |
142 | void deleteButtons(); |
143 | |
144 | /** |
145 | * Retrieves the place path for the current path. |
146 | * E. g. for the path "fish://root@192.168.0.2/var/lib" the string |
147 | * "fish://root@192.168.0.2" will be returned, which leads to the |
148 | * navigation indication 'Custom Path > var > lib". For e. g. |
149 | * "settings:///System/" the path "settings://" will be returned. |
150 | */ |
151 | QString retrievePlacePath() const; |
152 | |
153 | /** |
154 | * Returns true, if the MIME type of the path represents a |
155 | * compressed file like TAR or ZIP. |
156 | */ |
157 | bool isCompressedPath(const KUrl& path) const; |
158 | |
159 | void removeTrailingSlash(QString& url) const; |
160 | |
161 | /** |
162 | * Returns the current history index, if \a historyIndex is |
163 | * smaller than 0. If \a historyIndex is greater or equal than |
164 | * the number of available history items, the largest possible |
165 | * history index is returned. For the other cases just \a historyIndex |
166 | * is returned. |
167 | */ |
168 | int adjustedHistoryIndex(int historyIndex) const; |
169 | |
170 | bool m_editable : 1; |
171 | bool m_active : 1; |
172 | bool m_showPlacesSelector : 1; |
173 | bool m_showFullPath : 1; |
174 | int m_historyIndex; |
175 | |
176 | QHBoxLayout* m_layout; |
177 | |
178 | QList<LocationData> m_history; |
179 | KUrlNavigatorPlacesSelector* m_placesSelector; |
180 | KUrlComboBox* m_pathBox; |
181 | KUrlNavigatorProtocolCombo* m_protocols; |
182 | KUrlNavigatorDropDownButton* m_dropDownButton; |
183 | QList<KUrlNavigatorButton*> m_navButtons; |
184 | KUrlNavigatorButtonBase* m_toggleEditableMode; |
185 | KUrl m_homeUrl; |
186 | QStringList m_customProtocols; |
187 | KUrlNavigator* q; |
188 | }; |
189 | |
190 | |
191 | KUrlNavigator::Private::Private(KUrlNavigator* q, KFilePlacesModel* placesModel) : |
192 | m_editable(false), |
193 | m_active(true), |
194 | m_showPlacesSelector(placesModel != 0), |
195 | m_showFullPath(false), |
196 | m_historyIndex(0), |
197 | m_layout(new QHBoxLayout), |
198 | m_placesSelector(0), |
199 | m_pathBox(0), |
200 | m_protocols(0), |
201 | m_dropDownButton(0), |
202 | m_navButtons(), |
203 | m_toggleEditableMode(0), |
204 | m_homeUrl(), |
205 | m_customProtocols(QStringList()), |
206 | q(q) |
207 | { |
208 | m_layout->setSpacing(0); |
209 | m_layout->setMargin(0); |
210 | |
211 | // initialize the places selector |
212 | q->setAutoFillBackground(false); |
213 | |
214 | if (placesModel != 0) { |
215 | m_placesSelector = new KUrlNavigatorPlacesSelector(q, placesModel); |
216 | connect(m_placesSelector, SIGNAL(placeActivated(KUrl)), |
217 | q, SLOT(setLocationUrl(KUrl))); |
218 | |
219 | connect(placesModel, SIGNAL(rowsInserted(QModelIndex,int,int)), |
220 | q, SLOT(updateContent())); |
221 | connect(placesModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), |
222 | q, SLOT(updateContent())); |
223 | connect(placesModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), |
224 | q, SLOT(updateContent())); |
225 | } |
226 | |
227 | // create protocol combo |
228 | m_protocols = new KUrlNavigatorProtocolCombo(QString(), q); |
229 | connect(m_protocols, SIGNAL(activated(QString)), |
230 | q, SLOT(slotProtocolChanged(QString))); |
231 | |
232 | // create drop down button for accessing all paths of the URL |
233 | m_dropDownButton = new KUrlNavigatorDropDownButton(q); |
234 | m_dropDownButton->setForegroundRole(QPalette::WindowText); |
235 | m_dropDownButton->installEventFilter(q); |
236 | connect(m_dropDownButton, SIGNAL(clicked()), |
237 | q, SLOT(openPathSelectorMenu())); |
238 | |
239 | // initialize the path box of the traditional view |
240 | m_pathBox = new KUrlComboBox(KUrlComboBox::Directories, true, q); |
241 | m_pathBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); |
242 | m_pathBox->installEventFilter(q); |
243 | |
244 | KUrlCompletion* kurlCompletion = new KUrlCompletion(KUrlCompletion::DirCompletion); |
245 | m_pathBox->setCompletionObject(kurlCompletion); |
246 | m_pathBox->setAutoDeleteCompletionObject(true); |
247 | |
248 | connect(m_pathBox, SIGNAL(returnPressed()), |
249 | q, SLOT(slotReturnPressed())); |
250 | connect(m_pathBox, SIGNAL(urlActivated(KUrl)), |
251 | q, SLOT(setLocationUrl(KUrl))); |
252 | connect(m_pathBox, SIGNAL(editTextChanged(QString)), |
253 | q, SLOT(slotPathBoxChanged(QString))); |
254 | |
255 | // create toggle button which allows to switch between |
256 | // the breadcrumb and traditional view |
257 | m_toggleEditableMode = new KUrlNavigatorToggleButton(q); |
258 | m_toggleEditableMode->installEventFilter(q); |
259 | m_toggleEditableMode->setMinimumWidth(20); |
260 | connect(m_toggleEditableMode, SIGNAL(clicked()), |
261 | q, SLOT(switchView())); |
262 | |
263 | if (m_placesSelector != 0) { |
264 | m_layout->addWidget(m_placesSelector); |
265 | } |
266 | m_layout->addWidget(m_protocols); |
267 | m_layout->addWidget(m_dropDownButton); |
268 | m_layout->addWidget(m_pathBox, 1); |
269 | m_layout->addWidget(m_toggleEditableMode); |
270 | |
271 | q->setContextMenuPolicy(Qt::CustomContextMenu); |
272 | connect(q, SIGNAL(customContextMenuRequested(QPoint)), |
273 | q, SLOT(openContextMenu())); |
274 | } |
275 | |
276 | void KUrlNavigator::Private::initialize(const KUrl& url) |
277 | { |
278 | LocationData data; |
279 | data.url = url; |
280 | m_history.prepend(data); |
281 | |
282 | q->setLayoutDirection(Qt::LeftToRight); |
283 | |
284 | const int minHeight = m_pathBox->sizeHint().height(); |
285 | q->setMinimumHeight(minHeight); |
286 | |
287 | q->setLayout(m_layout); |
288 | q->setMinimumWidth(100); |
289 | |
290 | updateContent(); |
291 | } |
292 | |
293 | void KUrlNavigator::Private::appendWidget(QWidget* widget, int stretch) |
294 | { |
295 | m_layout->insertWidget(m_layout->count() - 1, widget, stretch); |
296 | } |
297 | |
298 | void KUrlNavigator::Private::slotReturnPressed() |
299 | { |
300 | // Parts of the following code have been taken |
301 | // from the class KateFileSelector located in |
302 | // kate/app/katefileselector.hpp of Kate. |
303 | // Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> |
304 | // Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org> |
305 | // Copyright (C) 2001 Anders Lund <anders.lund@lund.tdcadsl.dk> |
306 | |
307 | const KUrl typedUrl = q->uncommittedUrl(); |
308 | QStringList urls = m_pathBox->urls(); |
309 | urls.removeAll(typedUrl.url()); |
310 | urls.prepend(typedUrl.url()); |
311 | m_pathBox->setUrls(urls, KUrlComboBox::RemoveBottom); |
312 | |
313 | q->setLocationUrl(typedUrl); |
314 | // The URL might have been adjusted by KUrlNavigator::setUrl(), hence |
315 | // synchronize the result in the path box. |
316 | const KUrl currentUrl = q->locationUrl(); |
317 | m_pathBox->setUrl(currentUrl); |
318 | |
319 | emit q->returnPressed(); |
320 | |
321 | if (QApplication::keyboardModifiers() & Qt::ControlModifier) { |
322 | // Pressing Ctrl+Return automatically switches back to the breadcrumb mode. |
323 | // The switch must be done asynchronously, as we are in the context of the |
324 | // editor. |
325 | QMetaObject::invokeMethod(q, "switchToBreadcrumbMode" , Qt::QueuedConnection); |
326 | } |
327 | } |
328 | |
329 | void KUrlNavigator::Private::slotProtocolChanged(const QString& protocol) |
330 | { |
331 | Q_ASSERT(m_editable); |
332 | |
333 | KUrl url; |
334 | url.setProtocol(protocol); |
335 | url.setPath((protocol == QLatin1String("file" )) ? QLatin1String("/" ) : QLatin1String("//" )); |
336 | |
337 | m_pathBox->setEditUrl(url); |
338 | } |
339 | |
340 | void KUrlNavigator::Private::() |
341 | { |
342 | if (m_navButtons.count() <= 0) { |
343 | return; |
344 | } |
345 | |
346 | const KUrl firstVisibleUrl = m_navButtons.first()->url(); |
347 | |
348 | QString spacer; |
349 | QPointer<KMenu> = new KMenu(q); |
350 | popup->setLayoutDirection(Qt::LeftToRight); |
351 | |
352 | const QString placePath = retrievePlacePath(); |
353 | int idx = placePath.count(QLatin1Char('/')); // idx points to the first directory |
354 | // after the place path |
355 | |
356 | const QString path = m_history[m_historyIndex].url.pathOrUrl(); |
357 | QString dirName = path.section(QLatin1Char('/'), idx, idx); |
358 | if (dirName.isEmpty()) { |
359 | dirName = QLatin1Char('/'); |
360 | } |
361 | do { |
362 | const QString text = spacer + dirName; |
363 | |
364 | QAction* action = new QAction(text, popup); |
365 | const KUrl currentUrl = buttonUrl(idx); |
366 | if (currentUrl == firstVisibleUrl) { |
367 | popup->addSeparator(); |
368 | } |
369 | action->setData(QVariant(currentUrl.prettyUrl())); |
370 | popup->addAction(action); |
371 | |
372 | ++idx; |
373 | spacer.append(" " ); |
374 | dirName = path.section('/', idx, idx); |
375 | } while (!dirName.isEmpty()); |
376 | |
377 | const QPoint pos = q->mapToGlobal(m_dropDownButton->geometry().bottomRight()); |
378 | const QAction* activatedAction = popup->exec(pos); |
379 | if (activatedAction != 0) { |
380 | const KUrl url = KUrl(activatedAction->data().toString()); |
381 | q->setLocationUrl(url); |
382 | } |
383 | |
384 | // Delete the menu, unless it has been deleted in its own nested event loop already. |
385 | if (popup) { |
386 | popup->deleteLater(); |
387 | } |
388 | } |
389 | |
390 | void KUrlNavigator::Private::switchView() |
391 | { |
392 | m_toggleEditableMode->setFocus(); |
393 | m_editable = !m_editable; |
394 | m_toggleEditableMode->setChecked(m_editable); |
395 | updateContent(); |
396 | if (q->isUrlEditable()) { |
397 | m_pathBox->setFocus(); |
398 | } |
399 | |
400 | emit q->requestActivation(); |
401 | emit q->editableStateChanged(m_editable); |
402 | } |
403 | |
404 | void KUrlNavigator::Private::dropUrls(const KUrl& destination, QDropEvent* event) |
405 | { |
406 | const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); |
407 | if (!urls.isEmpty()) { |
408 | emit q->urlsDropped(destination, event); |
409 | |
410 | #ifndef KDE_NO_DEPRECATED |
411 | // KDE5: remove, as the signal has been replaced by |
412 | // urlsDropped(const KUrl& destination, QDropEvent* event) |
413 | emit q->urlsDropped(urls, destination); |
414 | #endif |
415 | } |
416 | } |
417 | |
418 | void KUrlNavigator::Private::slotNavigatorButtonClicked(const KUrl& url, Qt::MouseButton button) |
419 | { |
420 | if (button & Qt::LeftButton) { |
421 | q->setLocationUrl(url); |
422 | } else if (button & Qt::MidButton) { |
423 | emit q->tabRequested(url); |
424 | } |
425 | } |
426 | |
427 | void KUrlNavigator::Private::() |
428 | { |
429 | q->setActive(true); |
430 | |
431 | QPointer<KMenu> = new KMenu(q); |
432 | |
433 | // provide 'Copy' action, which copies the current URL of |
434 | // the URL navigator into the clipboard |
435 | QAction* copyAction = popup->addAction(KIcon("edit-copy" ), i18n("Copy" )); |
436 | |
437 | // provide 'Paste' action, which copies the current clipboard text |
438 | // into the URL navigator |
439 | QAction* pasteAction = popup->addAction(KIcon("edit-paste" ), i18n("Paste" )); |
440 | QClipboard* clipboard = QApplication::clipboard(); |
441 | pasteAction->setEnabled(!clipboard->text().isEmpty()); |
442 | |
443 | popup->addSeparator(); |
444 | |
445 | // provide radiobuttons for toggling between the edit and the navigation mode |
446 | QAction* editAction = popup->addAction(i18n("Edit" )); |
447 | editAction->setCheckable(true); |
448 | |
449 | QAction* navigateAction = popup->addAction(i18n("Navigate" )); |
450 | navigateAction->setCheckable(true); |
451 | |
452 | QActionGroup* modeGroup = new QActionGroup(popup); |
453 | modeGroup->addAction(editAction); |
454 | modeGroup->addAction(navigateAction); |
455 | if (q->isUrlEditable()) { |
456 | editAction->setChecked(true); |
457 | } else { |
458 | navigateAction->setChecked(true); |
459 | } |
460 | |
461 | popup->addSeparator(); |
462 | |
463 | // allow showing of the full path |
464 | QAction* showFullPathAction = popup->addAction(i18n("Show Full Path" )); |
465 | showFullPathAction->setCheckable(true); |
466 | showFullPathAction->setChecked(q->showFullPath()); |
467 | |
468 | QAction* activatedAction = popup->exec(QCursor::pos()); |
469 | if (activatedAction == copyAction) { |
470 | QMimeData* mimeData = new QMimeData(); |
471 | mimeData->setText(q->locationUrl().pathOrUrl()); |
472 | clipboard->setMimeData(mimeData); |
473 | } else if (activatedAction == pasteAction) { |
474 | q->setLocationUrl(KUrl(clipboard->text())); |
475 | } else if (activatedAction == editAction) { |
476 | q->setUrlEditable(true); |
477 | } else if (activatedAction == navigateAction) { |
478 | q->setUrlEditable(false); |
479 | } else if (activatedAction == showFullPathAction) { |
480 | q->setShowFullPath(showFullPathAction->isChecked()); |
481 | } |
482 | |
483 | // Delete the menu, unless it has been deleted in its own nested event loop already. |
484 | if (popup) { |
485 | popup->deleteLater(); |
486 | } |
487 | } |
488 | |
489 | void KUrlNavigator::Private::slotPathBoxChanged(const QString& text) |
490 | { |
491 | if (text.isEmpty()) { |
492 | const QString protocol = q->locationUrl().protocol(); |
493 | m_protocols->setProtocol(protocol); |
494 | m_protocols->show(); |
495 | } else { |
496 | m_protocols->hide(); |
497 | } |
498 | } |
499 | |
500 | void KUrlNavigator::Private::updateContent() |
501 | { |
502 | const KUrl currentUrl = q->locationUrl(); |
503 | if (m_placesSelector != 0) { |
504 | m_placesSelector->updateSelection(currentUrl); |
505 | } |
506 | |
507 | if (m_editable) { |
508 | m_protocols->hide(); |
509 | m_dropDownButton->hide(); |
510 | |
511 | deleteButtons(); |
512 | m_toggleEditableMode->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); |
513 | q->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); |
514 | |
515 | m_pathBox->show(); |
516 | m_pathBox->setUrl(currentUrl); |
517 | } else { |
518 | m_pathBox->hide(); |
519 | |
520 | m_protocols->hide(); |
521 | |
522 | m_toggleEditableMode->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); |
523 | q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); |
524 | |
525 | // Calculate the start index for the directories that should be shown as buttons |
526 | // and create the buttons |
527 | KUrl placeUrl; |
528 | if ((m_placesSelector != 0) && !m_showFullPath) { |
529 | placeUrl = m_placesSelector->selectedPlaceUrl(); |
530 | } |
531 | |
532 | QString placePath = placeUrl.isValid() ? placeUrl.pathOrUrl() : retrievePlacePath(); |
533 | removeTrailingSlash(placePath); |
534 | |
535 | const int startIndex = placePath.count('/'); |
536 | updateButtons(startIndex); |
537 | } |
538 | } |
539 | |
540 | void KUrlNavigator::Private::updateButtons(int startIndex) |
541 | { |
542 | KUrl currentUrl = q->locationUrl(); |
543 | |
544 | const QString path = currentUrl.pathOrUrl(); |
545 | |
546 | bool createButton = false; |
547 | const int oldButtonCount = m_navButtons.count(); |
548 | |
549 | int idx = startIndex; |
550 | bool hasNext = true; |
551 | do { |
552 | createButton = (idx - startIndex >= oldButtonCount); |
553 | const bool isFirstButton = (idx == startIndex); |
554 | const QString dirName = path.section(QLatin1Char('/'), idx, idx); |
555 | hasNext = isFirstButton || !dirName.isEmpty(); |
556 | if (hasNext) { |
557 | KUrlNavigatorButton* button = 0; |
558 | if (createButton) { |
559 | button = new KUrlNavigatorButton(buttonUrl(idx), q); |
560 | button->installEventFilter(q); |
561 | button->setForegroundRole(QPalette::WindowText); |
562 | connect(button, SIGNAL(urlsDropped(KUrl,QDropEvent*)), |
563 | q, SLOT(dropUrls(KUrl,QDropEvent*))); |
564 | connect(button, SIGNAL(clicked(KUrl,Qt::MouseButton)), |
565 | q, SLOT(slotNavigatorButtonClicked(KUrl,Qt::MouseButton))); |
566 | connect(button, SIGNAL(finishedTextResolving()), |
567 | q, SLOT(updateButtonVisibility())); |
568 | appendWidget(button); |
569 | } else { |
570 | button = m_navButtons[idx - startIndex]; |
571 | button->setUrl(buttonUrl(idx)); |
572 | } |
573 | |
574 | if (isFirstButton) { |
575 | button->setText(firstButtonText()); |
576 | } |
577 | button->setActive(q->isActive()); |
578 | |
579 | if (createButton) { |
580 | if (!isFirstButton) { |
581 | setTabOrder(m_navButtons.last(), button); |
582 | } |
583 | m_navButtons.append(button); |
584 | } |
585 | |
586 | ++idx; |
587 | button->setActiveSubDirectory(path.section(QLatin1Char('/'), idx, idx)); |
588 | } |
589 | } while (hasNext); |
590 | |
591 | // delete buttons which are not used anymore |
592 | const int newButtonCount = idx - startIndex; |
593 | if (newButtonCount < oldButtonCount) { |
594 | const QList<KUrlNavigatorButton*>::iterator itBegin = m_navButtons.begin() + newButtonCount; |
595 | const QList<KUrlNavigatorButton*>::iterator itEnd = m_navButtons.end(); |
596 | QList<KUrlNavigatorButton*>::iterator it = itBegin; |
597 | while (it != itEnd) { |
598 | (*it)->hide(); |
599 | (*it)->deleteLater(); |
600 | ++it; |
601 | } |
602 | m_navButtons.erase(itBegin, itEnd); |
603 | } |
604 | |
605 | setTabOrder(m_dropDownButton, m_navButtons.first()); |
606 | setTabOrder(m_navButtons.last(), m_toggleEditableMode); |
607 | |
608 | updateButtonVisibility(); |
609 | } |
610 | |
611 | void KUrlNavigator::Private::updateButtonVisibility() |
612 | { |
613 | if (m_editable) { |
614 | return; |
615 | } |
616 | |
617 | const int buttonsCount = m_navButtons.count(); |
618 | if (buttonsCount == 0) { |
619 | m_dropDownButton->hide(); |
620 | return; |
621 | } |
622 | |
623 | // Subtract all widgets from the available width, that must be shown anyway |
624 | int availableWidth = q->width() - m_toggleEditableMode->minimumWidth(); |
625 | |
626 | if ((m_placesSelector != 0) && m_placesSelector->isVisible()) { |
627 | availableWidth -= m_placesSelector->width(); |
628 | } |
629 | |
630 | if ((m_protocols != 0) && m_protocols->isVisible()) { |
631 | availableWidth -= m_protocols->width(); |
632 | } |
633 | |
634 | // Check whether buttons must be hidden at all... |
635 | int requiredButtonWidth = 0; |
636 | foreach (const KUrlNavigatorButton* button, m_navButtons) { |
637 | requiredButtonWidth += button->minimumWidth(); |
638 | } |
639 | |
640 | if (requiredButtonWidth > availableWidth) { |
641 | // At least one button must be hidden. This implies that the |
642 | // drop-down button must get visible, which again decreases the |
643 | // available width. |
644 | availableWidth -= m_dropDownButton->width(); |
645 | } |
646 | |
647 | // Hide buttons... |
648 | QList<KUrlNavigatorButton*>::const_iterator it = m_navButtons.constEnd(); |
649 | const QList<KUrlNavigatorButton*>::const_iterator itBegin = m_navButtons.constBegin(); |
650 | bool isLastButton = true; |
651 | bool hasHiddenButtons = false; |
652 | |
653 | QLinkedList<KUrlNavigatorButton*> buttonsToShow; |
654 | while (it != itBegin) { |
655 | --it; |
656 | KUrlNavigatorButton* button = (*it); |
657 | availableWidth -= button->minimumWidth(); |
658 | if ((availableWidth <= 0) && !isLastButton) { |
659 | button->hide(); |
660 | hasHiddenButtons = true; |
661 | } |
662 | else { |
663 | // Don't show the button immediately, as setActive() |
664 | // might change the size and a relayout gets triggered |
665 | // after showing the button. So the showing of all buttons |
666 | // is postponed until all buttons have the correct |
667 | // activation state. |
668 | buttonsToShow.append(button); |
669 | } |
670 | isLastButton = false; |
671 | } |
672 | |
673 | // All buttons have the correct activation state and |
674 | // can be shown now |
675 | foreach (KUrlNavigatorButton* button, buttonsToShow) { |
676 | button->show(); |
677 | } |
678 | |
679 | if (hasHiddenButtons) { |
680 | m_dropDownButton->show(); |
681 | } else { |
682 | // Check whether going upwards is possible. If this is the case, show the drop-down button. |
683 | KUrl url = m_navButtons.front()->url(); |
684 | url.adjustPath(KUrl::AddTrailingSlash); |
685 | const bool visible = !url.equals(url.upUrl()) && (url.protocol() != "nepomuksearch" ); |
686 | m_dropDownButton->setVisible(visible); |
687 | } |
688 | } |
689 | |
690 | QString KUrlNavigator::Private::firstButtonText() const |
691 | { |
692 | QString text; |
693 | |
694 | // The first URL navigator button should get the name of the |
695 | // place instead of the directory name |
696 | if ((m_placesSelector != 0) && !m_showFullPath) { |
697 | const KUrl placeUrl = m_placesSelector->selectedPlaceUrl(); |
698 | text = m_placesSelector->selectedPlaceText(); |
699 | } |
700 | |
701 | if (text.isEmpty()) { |
702 | const KUrl currentUrl = q->locationUrl(); |
703 | if (currentUrl.isLocalFile()) { |
704 | #ifdef Q_OS_WIN |
705 | text = currentUrl.path().length() > 1 ? currentUrl.path().left(2) : QDir::rootPath(); |
706 | #else |
707 | text = m_showFullPath ? QLatin1String("/" ) : i18n("Custom Path" ); |
708 | #endif |
709 | } else { |
710 | text = currentUrl.protocol() + QLatin1Char(':'); |
711 | if (!currentUrl.host().isEmpty()) { |
712 | text += QLatin1Char(' ') + currentUrl.host(); |
713 | } |
714 | } |
715 | } |
716 | |
717 | return text; |
718 | } |
719 | |
720 | KUrl KUrlNavigator::Private::buttonUrl(int index) const |
721 | { |
722 | if (index < 0) { |
723 | index = 0; |
724 | } |
725 | |
726 | // Keep scheme, hostname etc. as this is needed for e. g. browsing |
727 | // FTP directories |
728 | const KUrl currentUrl = q->locationUrl(); |
729 | KUrl newUrl = currentUrl; |
730 | newUrl.setPath(QString()); |
731 | |
732 | QString pathOrUrl = currentUrl.pathOrUrl(); |
733 | if (!pathOrUrl.isEmpty()) { |
734 | if (index == 0) { |
735 | // prevent the last "/" from being stripped |
736 | // or we end up with an empty path |
737 | #ifdef Q_OS_WIN |
738 | pathOrUrl = pathOrUrl.length() > 1 ? pathOrUrl.left(2) : QDir::rootPath(); |
739 | #else |
740 | pathOrUrl = QLatin1String("/" ); |
741 | #endif |
742 | } else { |
743 | pathOrUrl = pathOrUrl.section('/', 0, index); |
744 | } |
745 | } |
746 | |
747 | newUrl.setPath(KUrl(pathOrUrl).path()); |
748 | return newUrl; |
749 | } |
750 | |
751 | void KUrlNavigator::Private::switchToBreadcrumbMode() |
752 | { |
753 | q->setUrlEditable(false); |
754 | } |
755 | |
756 | void KUrlNavigator::Private::deleteButtons() |
757 | { |
758 | foreach (KUrlNavigatorButton* button, m_navButtons) { |
759 | button->hide(); |
760 | button->deleteLater(); |
761 | } |
762 | m_navButtons.clear(); |
763 | } |
764 | |
765 | QString KUrlNavigator::Private::retrievePlacePath() const |
766 | { |
767 | const KUrl currentUrl = q->locationUrl(); |
768 | const QString path = currentUrl.pathOrUrl(); |
769 | int idx = path.indexOf(QLatin1String("///" )); |
770 | if (idx >= 0) { |
771 | idx += 3; |
772 | } else { |
773 | idx = path.indexOf(QLatin1String("//" )); |
774 | idx = path.indexOf(QLatin1Char('/'), (idx < 0) ? 0 : idx + 2); |
775 | } |
776 | |
777 | QString placePath = (idx < 0) ? path : path.left(idx); |
778 | removeTrailingSlash(placePath); |
779 | return placePath; |
780 | } |
781 | |
782 | bool KUrlNavigator::Private::isCompressedPath(const KUrl& url) const |
783 | { |
784 | const KMimeType::Ptr mime = KMimeType::findByPath(url.path(KUrl::RemoveTrailingSlash)); |
785 | // Note: this list of MIME types depends on the protocols implemented by kio_archive |
786 | return mime->is("application/x-compressed-tar" ) || |
787 | mime->is("application/x-bzip-compressed-tar" ) || |
788 | mime->is("application/x-lzma-compressed-tar" ) || |
789 | mime->is("application/x-xz-compressed-tar" ) || |
790 | mime->is("application/x-tar" ) || |
791 | mime->is("application/x-tarz" ) || |
792 | mime->is("application/x-tzo" ) || // (not sure KTar supports those?) |
793 | mime->is("application/zip" ) || |
794 | mime->is("application/x-archive" ); |
795 | } |
796 | |
797 | void KUrlNavigator::Private::removeTrailingSlash(QString& url) const |
798 | { |
799 | const int length = url.length(); |
800 | if ((length > 0) && (url.at(length - 1) == QChar('/'))) { |
801 | url.remove(length - 1, 1); |
802 | } |
803 | } |
804 | |
805 | int KUrlNavigator::Private::adjustedHistoryIndex(int historyIndex) const |
806 | { |
807 | if (historyIndex < 0) { |
808 | historyIndex = m_historyIndex; |
809 | } else if (historyIndex >= m_history.size()) { |
810 | historyIndex = m_history.size() - 1; |
811 | Q_ASSERT(historyIndex >= 0); // m_history.size() must always be > 0 |
812 | } |
813 | return historyIndex; |
814 | } |
815 | |
816 | // ------------------------------------------------------------------------------------------------ |
817 | |
818 | KUrlNavigator::KUrlNavigator(QWidget* parent) : |
819 | QWidget(parent), |
820 | d(new Private(this, 0)) |
821 | { |
822 | d->initialize(KUrl()); |
823 | } |
824 | |
825 | KUrlNavigator::KUrlNavigator(KFilePlacesModel* placesModel, |
826 | const KUrl& url, |
827 | QWidget* parent) : |
828 | QWidget(parent), |
829 | d(new Private(this, placesModel)) |
830 | { |
831 | d->initialize(url); |
832 | } |
833 | |
834 | KUrlNavigator::~KUrlNavigator() |
835 | { |
836 | delete d; |
837 | } |
838 | |
839 | KUrl KUrlNavigator::locationUrl(int historyIndex) const |
840 | { |
841 | historyIndex = d->adjustedHistoryIndex(historyIndex); |
842 | return d->m_history[historyIndex].url; |
843 | } |
844 | |
845 | void KUrlNavigator::saveLocationState(const QByteArray& state) |
846 | { |
847 | d->m_history[d->m_historyIndex].state = state; |
848 | } |
849 | |
850 | QByteArray KUrlNavigator::locationState(int historyIndex) const |
851 | { |
852 | historyIndex = d->adjustedHistoryIndex(historyIndex); |
853 | return d->m_history[historyIndex].state; |
854 | } |
855 | |
856 | bool KUrlNavigator::goBack() |
857 | { |
858 | const int count = d->m_history.count(); |
859 | if (d->m_historyIndex < count - 1) { |
860 | const KUrl newUrl = locationUrl(d->m_historyIndex + 1); |
861 | emit urlAboutToBeChanged(newUrl); |
862 | |
863 | ++d->m_historyIndex; |
864 | d->updateContent(); |
865 | |
866 | emit historyChanged(); |
867 | emit urlChanged(locationUrl()); |
868 | return true; |
869 | } |
870 | |
871 | return false; |
872 | } |
873 | |
874 | bool KUrlNavigator::goForward() |
875 | { |
876 | if (d->m_historyIndex > 0) { |
877 | const KUrl newUrl = locationUrl(d->m_historyIndex - 1); |
878 | emit urlAboutToBeChanged(newUrl); |
879 | |
880 | --d->m_historyIndex; |
881 | d->updateContent(); |
882 | |
883 | emit historyChanged(); |
884 | emit urlChanged(locationUrl()); |
885 | return true; |
886 | } |
887 | |
888 | return false; |
889 | } |
890 | |
891 | bool KUrlNavigator::goUp() |
892 | { |
893 | const KUrl currentUrl = locationUrl(); |
894 | const KUrl upUrl = currentUrl.upUrl(); |
895 | if (upUrl != currentUrl) { |
896 | setLocationUrl(upUrl); |
897 | return true; |
898 | } |
899 | |
900 | return false; |
901 | } |
902 | |
903 | void KUrlNavigator::goHome() |
904 | { |
905 | if (d->m_homeUrl.isEmpty() || !d->m_homeUrl.isValid()) { |
906 | setLocationUrl(KUrl(QDir::homePath())); |
907 | } else { |
908 | setLocationUrl(d->m_homeUrl); |
909 | } |
910 | } |
911 | |
912 | void KUrlNavigator::setHomeUrl(const KUrl& url) |
913 | { |
914 | d->m_homeUrl = url; |
915 | } |
916 | |
917 | KUrl KUrlNavigator::homeUrl() const |
918 | { |
919 | return d->m_homeUrl; |
920 | } |
921 | |
922 | void KUrlNavigator::setUrlEditable(bool editable) |
923 | { |
924 | if (d->m_editable != editable) { |
925 | d->switchView(); |
926 | } |
927 | } |
928 | |
929 | bool KUrlNavigator::isUrlEditable() const |
930 | { |
931 | return d->m_editable; |
932 | } |
933 | |
934 | void KUrlNavigator::setShowFullPath(bool show) |
935 | { |
936 | if (d->m_showFullPath != show) { |
937 | d->m_showFullPath = show; |
938 | d->updateContent(); |
939 | } |
940 | } |
941 | |
942 | bool KUrlNavigator::showFullPath() const |
943 | { |
944 | return d->m_showFullPath; |
945 | } |
946 | |
947 | |
948 | void KUrlNavigator::setActive(bool active) |
949 | { |
950 | if (active != d->m_active) { |
951 | d->m_active = active; |
952 | |
953 | d->m_dropDownButton->setActive(active); |
954 | foreach(KUrlNavigatorButton* button, d->m_navButtons) { |
955 | button->setActive(active); |
956 | } |
957 | |
958 | update(); |
959 | if (active) { |
960 | emit activated(); |
961 | } |
962 | } |
963 | } |
964 | |
965 | bool KUrlNavigator::isActive() const |
966 | { |
967 | return d->m_active; |
968 | } |
969 | |
970 | void KUrlNavigator::setPlacesSelectorVisible(bool visible) |
971 | { |
972 | if (visible == d->m_showPlacesSelector) { |
973 | return; |
974 | } |
975 | |
976 | if (visible && (d->m_placesSelector == 0)) { |
977 | // the places selector cannot get visible as no |
978 | // places model is available |
979 | return; |
980 | } |
981 | |
982 | d->m_showPlacesSelector = visible; |
983 | d->m_placesSelector->setVisible(visible); |
984 | } |
985 | |
986 | bool KUrlNavigator::isPlacesSelectorVisible() const |
987 | { |
988 | return d->m_showPlacesSelector; |
989 | } |
990 | |
991 | KUrl KUrlNavigator::uncommittedUrl() const |
992 | { |
993 | KUriFilterData filteredData(d->m_pathBox->currentText().trimmed()); |
994 | filteredData.setCheckForExecutables(false); |
995 | if (KUriFilter::self()->filterUri(filteredData, QStringList() << "kshorturifilter" << "kurisearchfilter" )) { |
996 | return filteredData.uri(); |
997 | } |
998 | else { |
999 | return KUrl(filteredData.typedString()); |
1000 | } |
1001 | } |
1002 | |
1003 | void KUrlNavigator::setLocationUrl(const KUrl& newUrl) |
1004 | { |
1005 | if (newUrl == locationUrl()) { |
1006 | return; |
1007 | } |
1008 | |
1009 | KUrl url = newUrl; |
1010 | url.cleanPath(); |
1011 | |
1012 | if ((url.protocol() == QLatin1String("tar" )) || (url.protocol() == QLatin1String("zip" ))) { |
1013 | // The URL represents a tar- or zip-file. Check whether |
1014 | // the URL is really part of the tar- or zip-file, otherwise |
1015 | // replace it by the local path again. |
1016 | bool insideCompressedPath = d->isCompressedPath(url); |
1017 | if (!insideCompressedPath) { |
1018 | KUrl prevUrl = url; |
1019 | KUrl parentUrl = url.upUrl(); |
1020 | while (parentUrl != prevUrl) { |
1021 | if (d->isCompressedPath(parentUrl)) { |
1022 | insideCompressedPath = true; |
1023 | break; |
1024 | } |
1025 | prevUrl = parentUrl; |
1026 | parentUrl = parentUrl.upUrl(); |
1027 | } |
1028 | } |
1029 | if (!insideCompressedPath) { |
1030 | // drop the tar: or zip: protocol since we are not |
1031 | // inside the compressed path |
1032 | url.setProtocol("file" ); |
1033 | } |
1034 | } |
1035 | |
1036 | // Check whether current history element has the same URL. |
1037 | // If this is the case, just ignore setting the URL. |
1038 | const LocationData& data = d->m_history[d->m_historyIndex]; |
1039 | const bool isUrlEqual = url.equals(locationUrl(), KUrl::CompareWithoutTrailingSlash) || |
1040 | (!url.isValid() && url.equals(data.url, KUrl::CompareWithoutTrailingSlash)); |
1041 | if (isUrlEqual) { |
1042 | return; |
1043 | } |
1044 | |
1045 | emit urlAboutToBeChanged(url); |
1046 | |
1047 | if (d->m_historyIndex > 0) { |
1048 | // If an URL is set when the history index is not at the end (= 0), |
1049 | // then clear all previous history elements so that a new history |
1050 | // tree is started from the current position. |
1051 | QList<LocationData>::iterator begin = d->m_history.begin(); |
1052 | QList<LocationData>::iterator end = begin + d->m_historyIndex; |
1053 | d->m_history.erase(begin, end); |
1054 | d->m_historyIndex = 0; |
1055 | } |
1056 | |
1057 | Q_ASSERT(d->m_historyIndex == 0); |
1058 | LocationData newData; |
1059 | newData.url = url; |
1060 | d->m_history.insert(0, newData); |
1061 | |
1062 | // Prevent an endless growing of the history: remembering |
1063 | // the last 100 Urls should be enough... |
1064 | const int historyMax = 100; |
1065 | if (d->m_history.size() > historyMax) { |
1066 | QList<LocationData>::iterator begin = d->m_history.begin() + historyMax; |
1067 | QList<LocationData>::iterator end = d->m_history.end(); |
1068 | d->m_history.erase(begin, end); |
1069 | } |
1070 | |
1071 | emit historyChanged(); |
1072 | emit urlChanged(url); |
1073 | |
1074 | d->updateContent(); |
1075 | |
1076 | requestActivation(); |
1077 | } |
1078 | |
1079 | void KUrlNavigator::requestActivation() |
1080 | { |
1081 | setActive(true); |
1082 | } |
1083 | |
1084 | void KUrlNavigator::setFocus() |
1085 | { |
1086 | if (isUrlEditable()) { |
1087 | d->m_pathBox->setFocus(); |
1088 | } else { |
1089 | QWidget::setFocus(); |
1090 | } |
1091 | } |
1092 | |
1093 | #ifndef KDE_NO_DEPRECATED |
1094 | void KUrlNavigator::setUrl(const KUrl& url) |
1095 | { |
1096 | // deprecated |
1097 | setLocationUrl(url); |
1098 | } |
1099 | #endif |
1100 | |
1101 | #ifndef KDE_NO_DEPRECATED |
1102 | void KUrlNavigator::saveRootUrl(const KUrl& url) |
1103 | { |
1104 | // deprecated |
1105 | d->m_history[d->m_historyIndex].rootUrl = url; |
1106 | } |
1107 | #endif |
1108 | |
1109 | #ifndef KDE_NO_DEPRECATED |
1110 | void KUrlNavigator::savePosition(int x, int y) |
1111 | { |
1112 | // deprecated |
1113 | d->m_history[d->m_historyIndex].pos = QPoint(x, y); |
1114 | } |
1115 | #endif |
1116 | |
1117 | void KUrlNavigator::keyPressEvent(QKeyEvent* event) |
1118 | { |
1119 | if (isUrlEditable() && (event->key() == Qt::Key_Escape)) { |
1120 | setUrlEditable(false); |
1121 | } else { |
1122 | QWidget::keyPressEvent(event); |
1123 | } |
1124 | } |
1125 | |
1126 | void KUrlNavigator::keyReleaseEvent(QKeyEvent* event) |
1127 | { |
1128 | QWidget::keyReleaseEvent(event); |
1129 | } |
1130 | |
1131 | void KUrlNavigator::mouseReleaseEvent(QMouseEvent* event) |
1132 | { |
1133 | if (event->button() == Qt::MidButton) { |
1134 | const QRect bounds = d->m_toggleEditableMode->geometry(); |
1135 | if (bounds.contains(event->pos())) { |
1136 | // The middle mouse button has been clicked above the |
1137 | // toggle-editable-mode-button. Paste the clipboard content |
1138 | // as location URL. |
1139 | QClipboard* clipboard = QApplication::clipboard(); |
1140 | const QMimeData* mimeData = clipboard->mimeData(); |
1141 | if (mimeData->hasText()) { |
1142 | const QString text = mimeData->text(); |
1143 | setLocationUrl(KUrl(text)); |
1144 | } |
1145 | } |
1146 | } |
1147 | QWidget::mouseReleaseEvent(event); |
1148 | } |
1149 | |
1150 | void KUrlNavigator::resizeEvent(QResizeEvent* event) |
1151 | { |
1152 | QTimer::singleShot(0, this, SLOT(updateButtonVisibility())); |
1153 | QWidget::resizeEvent(event); |
1154 | } |
1155 | |
1156 | void KUrlNavigator::wheelEvent(QWheelEvent* event) |
1157 | { |
1158 | setActive(true); |
1159 | QWidget::wheelEvent(event); |
1160 | } |
1161 | |
1162 | bool KUrlNavigator::eventFilter(QObject* watched, QEvent* event) |
1163 | { |
1164 | switch (event->type()) { |
1165 | case QEvent::FocusIn: |
1166 | if (watched == d->m_pathBox) { |
1167 | requestActivation(); |
1168 | setFocus(); |
1169 | } |
1170 | foreach (KUrlNavigatorButton* button, d->m_navButtons) { |
1171 | button->setShowMnemonic(true); |
1172 | } |
1173 | break; |
1174 | |
1175 | case QEvent::FocusOut: |
1176 | foreach (KUrlNavigatorButton* button, d->m_navButtons) { |
1177 | button->setShowMnemonic(false); |
1178 | } |
1179 | break; |
1180 | |
1181 | default: |
1182 | break; |
1183 | } |
1184 | |
1185 | return QWidget::eventFilter(watched, event); |
1186 | } |
1187 | |
1188 | int KUrlNavigator::historySize() const |
1189 | { |
1190 | return d->m_history.count(); |
1191 | } |
1192 | |
1193 | int KUrlNavigator::historyIndex() const |
1194 | { |
1195 | return d->m_historyIndex; |
1196 | } |
1197 | |
1198 | KUrlComboBox* KUrlNavigator::editor() const |
1199 | { |
1200 | return d->m_pathBox; |
1201 | } |
1202 | |
1203 | void KUrlNavigator::setCustomProtocols(const QStringList &protocols) |
1204 | { |
1205 | d->m_customProtocols = protocols; |
1206 | d->m_protocols->setCustomProtocols(d->m_customProtocols); |
1207 | } |
1208 | |
1209 | QStringList KUrlNavigator::customProtocols() const |
1210 | { |
1211 | return d->m_customProtocols; |
1212 | } |
1213 | |
1214 | #ifndef KDE_NO_DEPRECATED |
1215 | const KUrl& KUrlNavigator::url() const |
1216 | { |
1217 | // deprecated |
1218 | |
1219 | // Workaround required because of flawed interface ('const KUrl&' is returned |
1220 | // instead of 'KUrl'): remember the URL to prevent a dangling pointer |
1221 | static KUrl url; |
1222 | url = locationUrl(); |
1223 | return url; |
1224 | } |
1225 | #endif |
1226 | |
1227 | #ifndef KDE_NO_DEPRECATED |
1228 | KUrl KUrlNavigator::url(int index) const |
1229 | { |
1230 | // deprecated |
1231 | return d->buttonUrl(index); |
1232 | } |
1233 | #endif |
1234 | |
1235 | #ifndef KDE_NO_DEPRECATED |
1236 | KUrl KUrlNavigator::historyUrl(int historyIndex) const |
1237 | { |
1238 | // deprecated |
1239 | return locationUrl(historyIndex); |
1240 | } |
1241 | #endif |
1242 | |
1243 | #ifndef KDE_NO_DEPRECATED |
1244 | const KUrl& KUrlNavigator::savedRootUrl() const |
1245 | { |
1246 | // deprecated |
1247 | |
1248 | // Workaround required because of flawed interface ('const KUrl&' is returned |
1249 | // instead of 'KUrl'): remember the root URL to prevent a dangling pointer |
1250 | static KUrl rootUrl; |
1251 | rootUrl = d->m_history[d->m_historyIndex].rootUrl; |
1252 | return rootUrl; |
1253 | } |
1254 | #endif |
1255 | |
1256 | #ifndef KDE_NO_DEPRECATED |
1257 | QPoint KUrlNavigator::savedPosition() const |
1258 | { |
1259 | // deprecated |
1260 | return d->m_history[d->m_historyIndex].pos; |
1261 | } |
1262 | #endif |
1263 | |
1264 | #ifndef KDE_NO_DEPRECATED |
1265 | void KUrlNavigator::setHomeUrl(const QString& homeUrl) |
1266 | { |
1267 | // deprecated |
1268 | setLocationUrl(KUrl(homeUrl)); |
1269 | } |
1270 | #endif |
1271 | |
1272 | #include "kurlnavigator.moc" |
1273 | |