00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "kurlnavigator.h"
00023
00024 #include "kfileplacesselector_p.h"
00025 #include "kprotocolcombo_p.h"
00026 #include "kurldropdownbutton_p.h"
00027 #include "kurlnavigatorbutton_p.h"
00028 #include "kurltogglebutton_p.h"
00029
00030 #include <kfileitem.h>
00031 #include <kfileplacesmodel.h>
00032 #include <kglobalsettings.h>
00033 #include <kicon.h>
00034 #include <klineedit.h>
00035 #include <klocale.h>
00036 #include <kmenu.h>
00037 #include <kprotocolinfo.h>
00038 #include <kurlcombobox.h>
00039 #include <kurlcompletion.h>
00040
00041 #include <QtCore/QDir>
00042 #include <QtCore/QLinkedList>
00043 #include <QtCore/QTimer>
00044 #include <QtGui/QApplication>
00045 #include <QtGui/QClipboard>
00046 #include <QtGui/QDropEvent>
00047 #include <QtGui/QKeyEvent>
00048 #include <QtGui/QBoxLayout>
00049 #include <QtGui/QLabel>
00050
00057 class HistoryElem
00058 {
00059 public:
00060 HistoryElem();
00061 HistoryElem(const KUrl& url);
00062 ~HistoryElem();
00063
00064 const KUrl& url() const;
00065
00066 void setRootUrl(const KUrl& url);
00067 const KUrl& rootUrl() const;
00068
00069 void setContentsX(int x);
00070 int contentsX() const;
00071
00072 void setContentsY(int y);
00073 int contentsY() const;
00074
00075 private:
00076 KUrl m_url;
00077 KUrl m_rootUrl;
00078 int m_contentsX;
00079 int m_contentsY;
00080 };
00081
00082 HistoryElem::HistoryElem() :
00083 m_url(),
00084 m_rootUrl(),
00085 m_contentsX(0),
00086 m_contentsY(0)
00087 {
00088 }
00089
00090 HistoryElem::HistoryElem(const KUrl& url) :
00091 m_url(url),
00092 m_rootUrl(),
00093 m_contentsX(0),
00094 m_contentsY(0)
00095 {
00096 }
00097
00098 HistoryElem::~HistoryElem()
00099 {
00100 }
00101
00102 inline const KUrl& HistoryElem::url() const
00103 {
00104 return m_url;
00105 }
00106
00107 inline void HistoryElem::setRootUrl(const KUrl& url)
00108 {
00109 m_rootUrl = url;
00110 }
00111
00112 inline const KUrl& HistoryElem::rootUrl() const
00113 {
00114 return m_rootUrl;
00115 }
00116
00117 inline void HistoryElem::setContentsX(int x)
00118 {
00119 m_contentsX = x;
00120 }
00121
00122 inline int HistoryElem::contentsX() const
00123 {
00124 return m_contentsX;
00125 }
00126
00127 inline void HistoryElem::setContentsY(int y)
00128 {
00129 m_contentsY = y;
00130 }
00131
00132 inline int HistoryElem::contentsY() const
00133 {
00134 return m_contentsY;
00135 }
00136
00138
00139 class KUrlNavigator::Private
00140 {
00141 public:
00142 Private(KUrlNavigator* q, KFilePlacesModel* placesModel);
00143
00144 void slotReturnPressed(const QString&);
00145 void slotReturnPressed();
00146 void slotRemoteHostActivated();
00147 void slotProtocolChanged(const QString&);
00148 void openPathSelectorMenu();
00149
00155 void appendWidget(QWidget* widget, int stretch = 0);
00156
00162 void switchView();
00163
00165 void dropUrls(const KUrl& destination, QDropEvent* event);
00166
00167 void updateContent();
00168
00177 void updateButtons(const QString& path, int startIndex);
00178
00184 void updateButtonVisibility();
00185
00186 void switchToBreadcrumbMode();
00187
00192 void deleteButtons();
00193
00201 QString retrievePlacePath(const QString& path) const;
00202
00207 bool isCompressedPath(const KUrl& path) const;
00208
00209 void removeTrailingSlash(QString& url);
00210
00211 bool m_editable : 1;
00212 bool m_active : 1;
00213 bool m_showPlacesSelector : 1;
00214 bool m_showFullPath : 1;
00215 int m_historyIndex;
00216
00217 QHBoxLayout* m_layout;
00218
00219 QList<HistoryElem> m_history;
00220 KFilePlacesSelector* m_placesSelector;
00221 KUrlComboBox* m_pathBox;
00222 KProtocolCombo* m_protocols;
00223 KLineEdit* m_host;
00224 KUrlDropDownButton* m_dropDownButton;
00225 QLinkedList<KUrlNavigatorButton*> m_navButtons;
00226 KUrlButton* m_toggleEditableMode;
00227 QString m_homeUrl;
00228 QStringList m_customProtocols;
00229 KUrlNavigator* q;
00230 };
00231
00232
00233 KUrlNavigator::Private::Private(KUrlNavigator* q, KFilePlacesModel* placesModel) :
00234 m_editable(false),
00235 m_active(true),
00236 m_showPlacesSelector(placesModel != 0),
00237 m_showFullPath(false),
00238 m_historyIndex(0),
00239 m_layout(new QHBoxLayout),
00240 m_placesSelector(0),
00241 m_pathBox(0),
00242 m_protocols(0),
00243 m_host(0),
00244 m_dropDownButton(0),
00245 m_toggleEditableMode(0),
00246 m_customProtocols(QStringList()),
00247 q(q)
00248 {
00249 m_layout->setSpacing(0);
00250 m_layout->setMargin(0);
00251
00252
00253 q->setAutoFillBackground(false);
00254
00255 if (placesModel != 0) {
00256 m_placesSelector = new KFilePlacesSelector(q, placesModel);
00257 connect(m_placesSelector, SIGNAL(placeActivated(const KUrl&)),
00258 q, SLOT(setUrl(const KUrl&)));
00259
00260 connect(placesModel, SIGNAL(rowsInserted(QModelIndex, int, int)),
00261 q, SLOT(updateContent()));
00262 connect(placesModel, SIGNAL(rowsRemoved(QModelIndex, int, int)),
00263 q, SLOT(updateContent()));
00264 connect(placesModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)),
00265 q, SLOT(updateContent()));
00266 }
00267
00268
00269 m_protocols = new KProtocolCombo(QString(), q);
00270 connect(m_protocols, SIGNAL(activated(QString)),
00271 q, SLOT(slotProtocolChanged(QString)));
00272
00273
00274 m_host = new KLineEdit(QString(), q);
00275 m_host->setClearButtonShown(true);
00276 connect(m_host, SIGNAL(editingFinished()),
00277 q, SLOT(slotRemoteHostActivated()));
00278 connect(m_host, SIGNAL(returnPressed()),
00279 q, SIGNAL(returnPressed()));
00280
00281
00282 m_dropDownButton = new KUrlDropDownButton(q);
00283 connect(m_dropDownButton, SIGNAL(clicked()),
00284 q, SLOT(openPathSelectorMenu()));
00285
00286
00287 m_pathBox = new KUrlComboBox(KUrlComboBox::Both, true, q);
00288 m_pathBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
00289 m_pathBox->installEventFilter(q);
00290
00291 KUrlCompletion* kurlCompletion = new KUrlCompletion(KUrlCompletion::DirCompletion);
00292 kurlCompletion->setIgnoreCase(true);
00293 m_pathBox->setCompletionObject(kurlCompletion);
00294 m_pathBox->setAutoDeleteCompletionObject(true);
00295
00296 connect(m_pathBox, SIGNAL(returnPressed(QString)),
00297 q, SLOT(slotReturnPressed(QString)));
00298 connect(m_pathBox, SIGNAL(returnPressed()),
00299 q, SLOT(slotReturnPressed()));
00300 connect(m_pathBox, SIGNAL(urlActivated(KUrl)),
00301 q, SLOT(setUrl(KUrl)));
00302
00303 m_toggleEditableMode = new KUrlToggleButton(q);
00304 m_toggleEditableMode->setMinimumWidth(20);
00305 connect(m_toggleEditableMode, SIGNAL(clicked()),
00306 q, SLOT(switchView()));
00307
00308 if (m_placesSelector != 0) {
00309 m_layout->addWidget(m_placesSelector);
00310 }
00311 m_layout->addWidget(m_protocols);
00312 m_layout->addWidget(m_dropDownButton);
00313 m_layout->addWidget(m_host);
00314 m_layout->setStretchFactor(m_host, 1);
00315 m_layout->addWidget(m_pathBox, 1);
00316 m_layout->addWidget(m_toggleEditableMode);
00317 }
00318
00319 void KUrlNavigator::Private::appendWidget(QWidget* widget, int stretch)
00320 {
00321 m_layout->insertWidget(m_layout->count() - 1, widget, stretch);
00322 }
00323
00324 void KUrlNavigator::Private::slotReturnPressed(const QString& text)
00325 {
00326
00327
00328
00329
00330
00331
00332
00333 KUrl typedUrl(text);
00334 if (typedUrl.hasPass()) {
00335 typedUrl.setPass(QString());
00336 }
00337
00338 QStringList urls = m_pathBox->urls();
00339 urls.removeAll(typedUrl.url());
00340 urls.prepend(typedUrl.url());
00341 m_pathBox->setUrls(urls, KUrlComboBox::RemoveBottom);
00342
00343 q->setUrl(typedUrl);
00344
00345
00346 m_pathBox->setUrl(q->url());
00347
00348 emit q->returnPressed();
00349
00350 if (QApplication::keyboardModifiers() & Qt::ControlModifier) {
00351
00352
00353
00354 QMetaObject::invokeMethod(q, "switchToBreadcrumbMode", Qt::QueuedConnection);
00355 }
00356 }
00357
00358 void KUrlNavigator::Private::slotReturnPressed()
00359 {
00360 const QString text = q->uncommittedUrl().prettyUrl();
00361 slotReturnPressed(text);
00362 }
00363
00364 void KUrlNavigator::Private::slotRemoteHostActivated()
00365 {
00366 KUrl u = q->url();
00367
00368 KUrl n(m_protocols->currentProtocol() + "://" + m_host->text());
00369
00370 if (n.scheme() != u.scheme() ||
00371 n.host() != u.host() ||
00372 n.user() != u.user() ||
00373 n.port() != u.port()) {
00374 u.setScheme(n.scheme());
00375 u.setHost(n.host());
00376 u.setUser(n.user());
00377 u.setPort(n.port());
00378
00379
00380 if (u.scheme() == "file") {
00381 u.setHost("");
00382 if (u.path().isEmpty()) {
00383 u.setPath("/");
00384 }
00385 }
00386
00387 q->setUrl(u);
00388 }
00389 }
00390
00391 void KUrlNavigator::Private::slotProtocolChanged(const QString& protocol)
00392 {
00393 KUrl url;
00394 url.setScheme(protocol);
00395 url.setPath("/");
00396 QLinkedList<KUrlNavigatorButton*>::const_iterator it = m_navButtons.begin();
00397 const QLinkedList<KUrlNavigatorButton*>::const_iterator itEnd = m_navButtons.end();
00398 while (it != itEnd) {
00399 (*it)->hide();
00400 (*it)->deleteLater();
00401 ++it;
00402 }
00403 m_navButtons.clear();
00404
00405 if (KProtocolInfo::protocolClass(protocol) == ":local") {
00406 q->setUrl(url);
00407 } else {
00408 m_host->setText(QString());
00409 m_host->show();
00410 m_host->setFocus();
00411 }
00412 }
00413
00414 void KUrlNavigator::Private::openPathSelectorMenu()
00415 {
00416 if (m_navButtons.count() <= 0) {
00417 return;
00418 }
00419
00420 const KUrl firstVisibleUrl = q->url(m_navButtons.first()->index());
00421
00422 QString spacer;
00423 KMenu* popup = new KMenu(q);
00424 popup->setLayoutDirection(Qt::LeftToRight);
00425
00426 const QString path = q->url().pathOrUrl();
00427 QString placePath = retrievePlacePath(path);
00428 removeTrailingSlash(placePath);
00429 int idx = placePath.count('/');
00430
00431
00432 QString dirName = path.section('/', idx, idx);
00433 if (dirName.isEmpty()) {
00434 dirName = QChar('/');
00435 }
00436 do {
00437 const QString text = spacer + dirName;
00438
00439 QAction* action = new QAction(text, popup);
00440 const KUrl currentUrl = q->url(idx);
00441 if (currentUrl == firstVisibleUrl) {
00442 popup->addSeparator();
00443 }
00444 action->setData(QVariant(currentUrl.prettyUrl()));
00445 popup->addAction(action);
00446
00447 ++idx;
00448 spacer.append(" ");
00449 dirName = path.section('/', idx, idx);
00450 } while (!dirName.isEmpty());
00451
00452 const QPoint pos = q->mapToGlobal(m_dropDownButton->geometry().bottomRight());
00453 const QAction* activatedAction = popup->exec(pos);
00454 if (activatedAction != 0) {
00455 const KUrl url = KUrl(activatedAction->data().toString());
00456 q->setUrl(url);
00457 }
00458
00459 popup->deleteLater();
00460 }
00461
00462 void KUrlNavigator::Private::switchView()
00463 {
00464 m_toggleEditableMode->setFocus();
00465 m_editable = !m_editable;
00466 m_toggleEditableMode->setChecked(m_editable);
00467 updateContent();
00468 if (q->isUrlEditable()) {
00469 m_pathBox->setFocus();
00470 }
00471
00472 emit q->requestActivation();
00473 emit q->editableStateChanged(m_editable);
00474 }
00475
00476 void KUrlNavigator::Private::dropUrls(const KUrl& destination, QDropEvent* event)
00477 {
00478 const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
00479 if (!urls.isEmpty()) {
00480 emit q->urlsDropped(destination, event);
00481
00482
00483
00484 emit q->urlsDropped(urls, destination);
00485 }
00486 }
00487
00488 void KUrlNavigator::Private::updateContent()
00489 {
00490 if (m_placesSelector != 0) {
00491 m_placesSelector->updateSelection(q->url());
00492 }
00493
00494 if (m_editable) {
00495 m_protocols->hide();
00496 m_host->hide();
00497 m_dropDownButton->hide();
00498
00499 deleteButtons();
00500 m_toggleEditableMode->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
00501 q->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
00502
00503 m_pathBox->show();
00504 m_pathBox->setUrl(q->url());
00505 } else {
00506 m_dropDownButton->setVisible(!m_showFullPath);
00507 m_pathBox->hide();
00508
00509 QString path = q->url().pathOrUrl();
00510 removeTrailingSlash(path);
00511
00512 m_toggleEditableMode->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
00513 q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
00514
00515
00516 KUrl placeUrl;
00517 if ((m_placesSelector != 0) && !m_showFullPath) {
00518 placeUrl = m_placesSelector->selectedPlaceUrl();
00519 }
00520
00521 QString placePath = placeUrl.isValid() ? placeUrl.pathOrUrl() : retrievePlacePath(path);
00522 removeTrailingSlash(placePath);
00523
00524
00525
00526 const int slashCount = placePath.count('/');
00527
00528 const KUrl currentUrl = q->url();
00529 if (currentUrl.isLocalFile() || placeUrl.isValid()) {
00530 m_protocols->hide();
00531 m_host->hide();
00532 } else {
00533
00534
00535 const QString protocol = currentUrl.scheme();
00536 m_protocols->setProtocol(protocol);
00537 m_protocols->show();
00538
00539
00540 QString hostText = currentUrl.host();
00541 if (!currentUrl.user().isEmpty()) {
00542 hostText = currentUrl.user() + '@' + hostText;
00543 }
00544 if (currentUrl.port() != -1) {
00545 hostText = hostText + ':' + QString::number(currentUrl.port());
00546 }
00547 m_host->setText(hostText);
00548 m_host->setVisible((placePath == path) &&
00549 (KProtocolInfo::protocolClass(protocol) != ":local"));
00550 }
00551
00552 updateButtons(path, slashCount);
00553 }
00554 }
00555
00556 void KUrlNavigator::Private::updateButtons(const QString& path, int startIndex)
00557 {
00558 QLinkedList<KUrlNavigatorButton*>::iterator it = m_navButtons.begin();
00559 const QLinkedList<KUrlNavigatorButton*>::const_iterator itEnd = m_navButtons.end();
00560 bool createButton = false;
00561 const KUrl currentUrl = q->url();
00562
00563 int idx = startIndex;
00564 bool hasNext = true;
00565 do {
00566 createButton = (it == itEnd);
00567
00568 const QString dirName = path.section('/', idx, idx);
00569 const bool isFirstButton = (idx == startIndex);
00570 hasNext = isFirstButton || !dirName.isEmpty();
00571 if (hasNext) {
00572 QString text;
00573 if (isFirstButton) {
00574
00575
00576 if ((m_placesSelector != 0) && !m_showFullPath) {
00577 const KUrl placeUrl = m_placesSelector->selectedPlaceUrl();
00578 text = m_placesSelector->selectedPlaceText();
00579 }
00580 if (text.isEmpty()) {
00581 if (currentUrl.isLocalFile()) {
00582 text = m_showFullPath ? "/" : i18n("Custom Path");
00583 } else if (!m_host->isVisible() && !m_host->text().isEmpty()) {
00584 text = m_host->text();
00585 } else {
00586
00587
00588 ++idx;
00589 continue;
00590 }
00591 }
00592 }
00593
00594 KUrlNavigatorButton* button = 0;
00595 if (createButton) {
00596 button = new KUrlNavigatorButton(idx, q);
00597 connect(button, SIGNAL(urlsDropped(const KUrl&, QDropEvent*)),
00598 q, SLOT(dropUrls(const KUrl&, QDropEvent*)));
00599 appendWidget(button);
00600 } else {
00601 button = *it;
00602 button->setIndex(idx);
00603 }
00604
00605 if (isFirstButton) {
00606 button->setText(text);
00607 }
00608
00609 if (createButton) {
00610 m_navButtons.append(button);
00611 } else {
00612 ++it;
00613 }
00614 ++idx;
00615 }
00616 } while (hasNext);
00617
00618
00619 QLinkedList<KUrlNavigatorButton*>::iterator itBegin = it;
00620 while (it != itEnd) {
00621 (*it)->hide();
00622 (*it)->deleteLater();
00623 ++it;
00624 }
00625 m_navButtons.erase(itBegin, m_navButtons.end());
00626
00627 updateButtonVisibility();
00628 }
00629
00630 void KUrlNavigator::Private::updateButtonVisibility()
00631 {
00632 if (m_editable) {
00633 return;
00634 }
00635
00636 const int buttonsCount = m_navButtons.count();
00637 if (buttonsCount == 0) {
00638 m_dropDownButton->hide();
00639 return;
00640 }
00641
00642
00643 int availableWidth = q->width() - m_toggleEditableMode->minimumWidth();
00644
00645 if ((m_placesSelector != 0) && m_placesSelector->isVisible()) {
00646 availableWidth -= m_placesSelector->width();
00647 }
00648
00649 if ((m_protocols != 0) && m_protocols->isVisible()) {
00650 availableWidth -= m_protocols->width();
00651 }
00652
00653 if (m_host->isVisible()) {
00654 availableWidth -= m_host->width();
00655 }
00656
00657
00658 int requiredButtonWidth = 0;
00659 foreach (KUrlNavigatorButton* button, m_navButtons) {
00660 requiredButtonWidth += button->minimumWidth();
00661 }
00662 if (requiredButtonWidth > availableWidth) {
00663
00664
00665
00666 availableWidth -= m_dropDownButton->width();
00667 }
00668
00669
00670 QLinkedList<KUrlNavigatorButton*>::iterator it = m_navButtons.end();
00671 const QLinkedList<KUrlNavigatorButton*>::const_iterator itBegin = m_navButtons.begin();
00672 bool isLastButton = true;
00673 bool hasHiddenButtons = false;
00674
00675 QLinkedList<KUrlNavigatorButton*> buttonsToShow;
00676 while (it != itBegin) {
00677 --it;
00678 KUrlNavigatorButton* button = (*it);
00679 availableWidth -= button->minimumWidth();
00680 if ((availableWidth <= 0) && !isLastButton) {
00681 button->hide();
00682 hasHiddenButtons = true;
00683 }
00684 else {
00685 button->setActive(isLastButton);
00686
00687
00688
00689
00690
00691 buttonsToShow.append(button);
00692 }
00693 isLastButton = false;
00694 }
00695
00696
00697
00698 foreach (KUrlNavigatorButton* button, buttonsToShow) {
00699 button->show();
00700 }
00701
00702 if (m_showFullPath) {
00703 m_dropDownButton->setVisible(hasHiddenButtons);
00704 }
00705 }
00706
00707 void KUrlNavigator::Private::switchToBreadcrumbMode()
00708 {
00709 q->setUrlEditable(false);
00710 }
00711
00712 void KUrlNavigator::Private::deleteButtons()
00713 {
00714 foreach (KUrlNavigatorButton* button, m_navButtons) {
00715 button->hide();
00716 button->deleteLater();
00717 }
00718 m_navButtons.clear();
00719 }
00720
00721 QString KUrlNavigator::Private::retrievePlacePath(const QString& path) const
00722 {
00723 int idx = path.indexOf(QLatin1String("///"));
00724 if (idx >= 0) {
00725 idx += 3;
00726 } else {
00727 idx = path.indexOf(QLatin1String("//"));
00728 idx = path.indexOf(QLatin1Char('/'), (idx < 0) ? 0 : idx + 2);
00729 }
00730 return (idx < 0) ? path : path.left(idx);
00731 }
00732
00733 bool KUrlNavigator::Private::isCompressedPath(const KUrl& url) const
00734 {
00735 const KMimeType::Ptr mime = KMimeType::findByPath(url.path(KUrl::RemoveTrailingSlash));
00736
00737 return mime->is("application/x-compressed-tar") ||
00738 mime->is("application/x-bzip-compressed-tar") ||
00739 mime->is("application/x-tar") ||
00740 mime->is("application/x-tarz") ||
00741 mime->is("application/x-tzo") ||
00742 mime->is("application/zip") ||
00743 mime->is("application/x-archive");
00744 }
00745
00746 void KUrlNavigator::Private::removeTrailingSlash(QString& url)
00747 {
00748 const int length = url.length();
00749 if ((length > 0) && (url.at(length - 1) == QChar('/'))) {
00750 url.remove(length -1, 1);
00751 }
00752 }
00753
00755
00756 KUrlNavigator::KUrlNavigator(KFilePlacesModel* placesModel,
00757 const KUrl& url,
00758 QWidget* parent) :
00759 QWidget(parent),
00760 d(new Private(this, placesModel))
00761 {
00762 d->m_history.prepend(HistoryElem(url));
00763 setLayoutDirection(Qt::LeftToRight);
00764
00765 const QFont font = KGlobalSettings::generalFont();
00766 setFont(font);
00767
00768 const int minHeight = d->m_pathBox->sizeHint().height();
00769 setMinimumHeight(minHeight);
00770
00771 setLayout(d->m_layout);
00772 setMinimumWidth(100);
00773
00774 d->updateContent();
00775 }
00776
00777 KUrlNavigator::~KUrlNavigator()
00778 {
00779 delete d;
00780 }
00781
00782 const KUrl& KUrlNavigator::url() const
00783 {
00784 Q_ASSERT(!d->m_history.empty());
00785 return d->m_history[d->m_historyIndex].url();
00786 }
00787
00788 KUrl KUrlNavigator::uncommittedUrl() const
00789 {
00790 if (isUrlEditable()) {
00791 return KUrl(d->m_pathBox->currentText());
00792 } else {
00793 return KUrl(d->m_protocols->currentProtocol() + "://" + d->m_host->text());
00794 }
00795 }
00796
00797 KUrl KUrlNavigator::url(int index) const
00798 {
00799 if (index < 0) {
00800 index = 0;
00801 }
00802
00803
00804
00805 KUrl newUrl = url();
00806 newUrl.setPath(QString());
00807
00808 QString pathOrUrl = url().pathOrUrl();
00809 if (!pathOrUrl.isEmpty()) {
00810 if (index == 0) {
00811
00812
00813 #ifdef Q_OS_WIN
00814 pathOrUrl = pathOrUrl.length() > 2 ? pathOrUrl.left(3) : QDir::rootPath();
00815 #else
00816 pathOrUrl = QLatin1String("/");
00817 #endif
00818 } else {
00819 pathOrUrl = pathOrUrl.section('/', 0, index);
00820 }
00821 }
00822
00823 newUrl.setPath(KUrl(pathOrUrl).path());
00824 return newUrl;
00825 }
00826
00827 bool KUrlNavigator::goBack()
00828 {
00829 const int count = d->m_history.count();
00830 if (d->m_historyIndex < count - 1) {
00831 ++d->m_historyIndex;
00832 d->updateContent();
00833 emit historyChanged();
00834 emit urlChanged(url());
00835 return true;
00836 }
00837
00838 return false;
00839 }
00840
00841 bool KUrlNavigator::goForward()
00842 {
00843 if (d->m_historyIndex > 0) {
00844 --d->m_historyIndex;
00845 d->updateContent();
00846 emit historyChanged();
00847 emit urlChanged(url());
00848 return true;
00849 }
00850
00851 return false;
00852 }
00853
00854 bool KUrlNavigator::goUp()
00855 {
00856 const KUrl& currentUrl = url();
00857 const KUrl upUrl = currentUrl.upUrl();
00858 if (upUrl != currentUrl) {
00859 setUrl(upUrl);
00860 return true;
00861 }
00862
00863 return false;
00864 }
00865
00866 void KUrlNavigator::goHome()
00867 {
00868 if (d->m_homeUrl.isEmpty()) {
00869 setUrl(QDir::homePath());
00870 } else {
00871 setUrl(d->m_homeUrl);
00872 }
00873 }
00874
00875 void KUrlNavigator::setHomeUrl(const QString& homeUrl)
00876 {
00877 d->m_homeUrl = homeUrl;
00878 }
00879
00880 void KUrlNavigator::setUrlEditable(bool editable)
00881 {
00882 if (d->m_editable != editable) {
00883 d->switchView();
00884 }
00885 }
00886
00887 bool KUrlNavigator::isUrlEditable() const
00888 {
00889 return d->m_editable;
00890 }
00891
00892 void KUrlNavigator::setShowFullPath(bool show)
00893 {
00894 if (d->m_showFullPath != show) {
00895 d->m_showFullPath = show;
00896 d->updateContent();
00897 }
00898 }
00899
00900 bool KUrlNavigator::showFullPath() const
00901 {
00902 return d->m_showFullPath;
00903 }
00904
00905
00906 void KUrlNavigator::setActive(bool active)
00907 {
00908 if (active != d->m_active) {
00909 d->m_active = active;
00910 update();
00911 if (active) {
00912 emit activated();
00913 }
00914 }
00915 }
00916
00917 bool KUrlNavigator::isActive() const
00918 {
00919 return d->m_active;
00920 }
00921
00922 void KUrlNavigator::setPlacesSelectorVisible(bool visible)
00923 {
00924 if (visible == d->m_showPlacesSelector) {
00925 return;
00926 }
00927
00928 if (visible && (d->m_placesSelector == 0)) {
00929
00930
00931 return;
00932 }
00933
00934 d->m_showPlacesSelector = visible;
00935 d->m_placesSelector->setVisible(visible);
00936 }
00937
00938 bool KUrlNavigator::isPlacesSelectorVisible() const
00939 {
00940 return d->m_showPlacesSelector;
00941 }
00942
00943 void KUrlNavigator::setUrl(const KUrl& url)
00944 {
00945 QString urlStr(KUrlCompletion::replacedPath(url.pathOrUrl(), true, true));
00946
00947 if (urlStr.length() > 0 && urlStr.at(0) == '~') {
00948
00949 urlStr.remove(0, 1);
00950 urlStr.insert(0, QDir::homePath());
00951 }
00952
00953 if ((url.protocol() == "tar") || (url.protocol() == "zip")) {
00954
00955
00956
00957 bool insideCompressedPath = d->isCompressedPath(url);
00958 if (!insideCompressedPath) {
00959 KUrl prevUrl = url;
00960 KUrl parentUrl = url.upUrl();
00961 while (parentUrl != prevUrl) {
00962 if (d->isCompressedPath(parentUrl)) {
00963 insideCompressedPath = true;
00964 break;
00965 }
00966 prevUrl = parentUrl;
00967 parentUrl = parentUrl.upUrl();
00968 }
00969 }
00970 if (!insideCompressedPath) {
00971
00972
00973 urlStr = url.path();
00974 }
00975 }
00976
00977 const KUrl transformedUrl(urlStr);
00978
00979
00980
00981 const HistoryElem& historyElem = d->m_history[d->m_historyIndex];
00982 const bool isUrlEqual = transformedUrl.equals(historyElem.url(), KUrl::CompareWithoutTrailingSlash) ||
00983 (!transformedUrl.isValid() && (urlStr == historyElem.url().url()));
00984 if (isUrlEqual) {
00985 return;
00986 }
00987
00988 if (d->m_historyIndex > 0) {
00989
00990
00991
00992 QList<HistoryElem>::iterator begin = d->m_history.begin();
00993 QList<HistoryElem>::iterator end = begin + d->m_historyIndex;
00994 d->m_history.erase(begin, end);
00995 d->m_historyIndex = 0;
00996 }
00997
00998 Q_ASSERT(d->m_historyIndex == 0);
00999 d->m_history.insert(0, HistoryElem(transformedUrl));
01000
01001
01002
01003 const int historyMax = 100;
01004 if (d->m_history.size() > historyMax) {
01005 QList<HistoryElem>::iterator begin = d->m_history.begin() + historyMax;
01006 QList<HistoryElem>::iterator end = d->m_history.end();
01007 d->m_history.erase(begin, end);
01008 }
01009
01010 emit historyChanged();
01011 emit urlChanged(transformedUrl);
01012
01013 d->updateContent();
01014
01015 requestActivation();
01016 }
01017
01018 void KUrlNavigator::requestActivation()
01019 {
01020 setActive(true);
01021 }
01022
01023 void KUrlNavigator::saveRootUrl(const KUrl& url)
01024 {
01025 HistoryElem& hist = d->m_history[d->m_historyIndex];
01026 hist.setRootUrl(url);
01027 }
01028
01029 void KUrlNavigator::savePosition(int x, int y)
01030 {
01031 HistoryElem& hist = d->m_history[d->m_historyIndex];
01032 hist.setContentsX(x);
01033 hist.setContentsY(y);
01034 }
01035
01036 void KUrlNavigator::keyReleaseEvent(QKeyEvent* event)
01037 {
01038 QWidget::keyReleaseEvent(event);
01039 if (isUrlEditable() && (event->key() == Qt::Key_Escape)) {
01040 setUrlEditable(false);
01041 }
01042 }
01043
01044 void KUrlNavigator::mouseReleaseEvent(QMouseEvent* event)
01045 {
01046 if (event->button() == Qt::MidButton) {
01047 QClipboard* clipboard = QApplication::clipboard();
01048 const QMimeData* mimeData = clipboard->mimeData();
01049 if (mimeData->hasText()) {
01050 const QString text = mimeData->text();
01051 setUrl(KUrl(text));
01052 }
01053 }
01054 QWidget::mouseReleaseEvent(event);
01055 }
01056
01057 void KUrlNavigator::resizeEvent(QResizeEvent* event)
01058 {
01059 QTimer::singleShot(0, this, SLOT(updateButtonVisibility()));
01060 QWidget::resizeEvent(event);
01061 }
01062
01063 bool KUrlNavigator::eventFilter(QObject* watched, QEvent* event)
01064 {
01065 if ((watched == d->m_pathBox) && (event->type() == QEvent::FocusIn)) {
01066 requestActivation();
01067 setFocus();
01068 }
01069
01070 return QWidget::eventFilter(watched, event);
01071 }
01072
01073 int KUrlNavigator::historySize() const
01074 {
01075 return d->m_history.count();
01076 }
01077
01078 int KUrlNavigator::historyIndex() const
01079 {
01080 return d->m_historyIndex;
01081 }
01082
01083 const KUrl& KUrlNavigator::savedRootUrl() const
01084 {
01085 const HistoryElem& histElem = d->m_history[d->m_historyIndex];
01086 return histElem.rootUrl();
01087 }
01088
01089 QPoint KUrlNavigator::savedPosition() const
01090 {
01091 const HistoryElem& histElem = d->m_history[d->m_historyIndex];
01092 return QPoint(histElem.contentsX(), histElem.contentsY());
01093 }
01094
01095 KUrlComboBox* KUrlNavigator::editor() const
01096 {
01097 return d->m_pathBox;
01098 }
01099
01100 void