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>
56 using namespace KDEPrivate;
61 #ifndef KDE_NO_DEPRECATED
68 class KUrlNavigator::Private
73 void initialize(
const KUrl& url);
75 void slotReturnPressed();
76 void slotProtocolChanged(
const QString&);
77 void openPathSelectorMenu();
84 void appendWidget(
QWidget* widget,
int stretch = 0);
101 void slotNavigatorButtonClicked(
const KUrl& url, Qt::MouseButton button);
103 void openContextMenu();
105 void slotPathBoxChanged(
const QString& text);
107 void updateContent();
117 void updateButtons(
int startIndex);
124 void updateButtonVisibility();
129 QString firstButtonText()
const;
134 KUrl buttonUrl(
int index)
const;
136 void switchToBreadcrumbMode();
142 void deleteButtons();
151 QString retrievePlacePath()
const;
157 bool isCompressedPath(
const KUrl& path)
const;
159 void removeTrailingSlash(
QString& url)
const;
168 int adjustedHistoryIndex(
int historyIndex)
const;
172 bool m_showPlacesSelector : 1;
173 bool m_showFullPath : 1;
194 m_showPlacesSelector(placesModel != 0),
195 m_showFullPath(false),
203 m_toggleEditableMode(0),
208 m_layout->setSpacing(0);
209 m_layout->setMargin(0);
214 if (placesModel != 0) {
216 connect(m_placesSelector, SIGNAL(placeActivated(
KUrl)),
217 q, SLOT(setLocationUrl(
KUrl)));
220 q, SLOT(updateContent()));
222 q, SLOT(updateContent()));
224 q, SLOT(updateContent()));
230 q, SLOT(slotProtocolChanged(
QString)));
234 m_dropDownButton->setForegroundRole(QPalette::WindowText);
235 m_dropDownButton->installEventFilter(q);
236 connect(m_dropDownButton, SIGNAL(clicked()),
237 q, SLOT(openPathSelectorMenu()));
241 m_pathBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
242 m_pathBox->installEventFilter(q);
245 m_pathBox->setCompletionObject(kurlCompletion);
246 m_pathBox->setAutoDeleteCompletionObject(
true);
248 connect(m_pathBox, SIGNAL(returnPressed()),
249 q, SLOT(slotReturnPressed()));
251 q, SLOT(setLocationUrl(
KUrl)));
253 q, SLOT(slotPathBoxChanged(
QString)));
258 m_toggleEditableMode->installEventFilter(q);
259 m_toggleEditableMode->setMinimumWidth(20);
260 connect(m_toggleEditableMode, SIGNAL(clicked()),
261 q, SLOT(switchView()));
263 if (m_placesSelector != 0) {
264 m_layout->addWidget(m_placesSelector);
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);
273 q, SLOT(openContextMenu()));
276 void KUrlNavigator::Private::initialize(
const KUrl& url)
280 m_history.prepend(data);
284 const int minHeight = m_pathBox->sizeHint().height();
293 void KUrlNavigator::Private::appendWidget(
QWidget* widget,
int stretch)
295 m_layout->insertWidget(m_layout->count() - 1, widget, stretch);
298 void KUrlNavigator::Private::slotReturnPressed()
317 m_pathBox->
setUrl(currentUrl);
329 void KUrlNavigator::Private::slotProtocolChanged(
const QString& protocol)
331 Q_ASSERT(m_editable);
337 m_pathBox->setEditUrl(url);
340 void KUrlNavigator::Private::openPathSelectorMenu()
342 if (m_navButtons.count() <= 0) {
346 const KUrl firstVisibleUrl = m_navButtons.first()->
url();
350 popup->setLayoutDirection(Qt::LeftToRight);
352 const QString placePath = retrievePlacePath();
356 const QString path = m_history[m_historyIndex].url.pathOrUrl();
362 const QString text = spacer + dirName;
365 const KUrl currentUrl = buttonUrl(idx);
366 if (currentUrl == firstVisibleUrl) {
367 popup->addSeparator();
370 popup->addAction(action);
374 dirName = path.
section(
'/', idx, idx);
375 }
while (!dirName.isEmpty());
378 const QAction* activatedAction = popup->exec(pos);
379 if (activatedAction != 0) {
386 popup->deleteLater();
390 void KUrlNavigator::Private::switchView()
392 m_toggleEditableMode->setFocus();
393 m_editable = !m_editable;
394 m_toggleEditableMode->setChecked(m_editable);
397 m_pathBox->setFocus();
404 void KUrlNavigator::Private::dropUrls(
const KUrl& destination,
QDropEvent* event)
410 #ifndef KDE_NO_DEPRECATED
418 void KUrlNavigator::Private::slotNavigatorButtonClicked(
const KUrl& url, Qt::MouseButton button)
420 if (button & Qt::LeftButton) {
422 }
else if (button & Qt::MidButton) {
427 void KUrlNavigator::Private::openContextMenu()
439 QAction* pasteAction = popup->addAction(
KIcon(
"edit-paste"),
i18n(
"Paste"));
443 popup->addSeparator();
446 QAction* editAction = popup->addAction(
i18n(
"Edit"));
449 QAction* navigateAction = popup->addAction(
i18n(
"Navigate"));
461 popup->addSeparator();
464 QAction* showFullPathAction = popup->addAction(
i18n(
"Show Full Path"));
469 if (activatedAction == copyAction) {
473 }
else if (activatedAction == pasteAction) {
475 }
else if (activatedAction == editAction) {
477 }
else if (activatedAction == navigateAction) {
479 }
else if (activatedAction == showFullPathAction) {
485 popup->deleteLater();
489 void KUrlNavigator::Private::slotPathBoxChanged(
const QString& text)
493 m_protocols->setProtocol(protocol);
500 void KUrlNavigator::Private::updateContent()
503 if (m_placesSelector != 0) {
504 m_placesSelector->updateSelection(currentUrl);
509 m_dropDownButton->hide();
512 m_toggleEditableMode->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
516 m_pathBox->setUrl(currentUrl);
522 m_toggleEditableMode->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
523 q->
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
528 if ((m_placesSelector != 0) && !m_showFullPath) {
529 placeUrl = m_placesSelector->selectedPlaceUrl();
533 removeTrailingSlash(placePath);
535 const int startIndex = placePath.
count(
'/');
536 updateButtons(startIndex);
540 void KUrlNavigator::Private::updateButtons(
int startIndex)
546 bool createButton =
false;
547 const int oldButtonCount = m_navButtons.
count();
549 int idx = startIndex;
552 createButton = (idx - startIndex >= oldButtonCount);
553 const bool isFirstButton = (idx == startIndex);
555 hasNext = isFirstButton || !dirName.
isEmpty();
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);
570 button = m_navButtons[idx - startIndex];
571 button->
setUrl(buttonUrl(idx));
575 button->
setText(firstButtonText());
580 if (!isFirstButton) {
581 setTabOrder(m_navButtons.last(), button);
583 m_navButtons.append(button);
592 const int newButtonCount = idx - startIndex;
593 if (newButtonCount < oldButtonCount) {
597 while (it != itEnd) {
599 (*it)->deleteLater();
602 m_navButtons.
erase(itBegin, itEnd);
605 setTabOrder(m_dropDownButton, m_navButtons.first());
606 setTabOrder(m_navButtons.last(), m_toggleEditableMode);
608 updateButtonVisibility();
611 void KUrlNavigator::Private::updateButtonVisibility()
617 const int buttonsCount = m_navButtons.count();
618 if (buttonsCount == 0) {
619 m_dropDownButton->hide();
624 int availableWidth = q->
width() - m_toggleEditableMode->minimumWidth();
626 if ((m_placesSelector != 0) && m_placesSelector->isVisible()) {
627 availableWidth -= m_placesSelector->width();
630 if ((m_protocols != 0) && m_protocols->isVisible()) {
631 availableWidth -= m_protocols->width();
635 int requiredButtonWidth = 0;
640 if (requiredButtonWidth > availableWidth) {
644 availableWidth -= m_dropDownButton->width();
650 bool isLastButton =
true;
651 bool hasHiddenButtons =
false;
654 while (it != itBegin) {
658 if ((availableWidth <= 0) && !isLastButton) {
660 hasHiddenButtons =
true;
668 buttonsToShow.
append(button);
670 isLastButton =
false;
679 if (hasHiddenButtons) {
680 m_dropDownButton->show();
683 KUrl url = m_navButtons.front()->
url();
686 m_dropDownButton->setVisible(visible);
690 QString KUrlNavigator::Private::firstButtonText()
const
696 if ((m_placesSelector != 0) && !m_showFullPath) {
697 const KUrl placeUrl = m_placesSelector->selectedPlaceUrl();
698 text = m_placesSelector->selectedPlaceText();
720 KUrl KUrlNavigator::Private::buttonUrl(
int index)
const
729 KUrl newUrl = currentUrl;
743 pathOrUrl = pathOrUrl.
section(
'/', 0, index);
751 void KUrlNavigator::Private::switchToBreadcrumbMode()
756 void KUrlNavigator::Private::deleteButtons()
762 m_navButtons.clear();
765 QString KUrlNavigator::Private::retrievePlacePath()
const
777 QString placePath = (idx < 0) ? path : path.
left(idx);
778 removeTrailingSlash(placePath);
782 bool KUrlNavigator::Private::isCompressedPath(
const KUrl& url)
const
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") ||
793 mime->is(
"application/zip") ||
794 mime->is(
"application/x-archive");
797 void KUrlNavigator::Private::removeTrailingSlash(
QString& url)
const
799 const int length = url.
length();
800 if ((length > 0) && (url.
at(length - 1) ==
QChar(
'/'))) {
801 url.
remove(length - 1, 1);
805 int KUrlNavigator::Private::adjustedHistoryIndex(
int historyIndex)
const
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);
820 d(new Private(this, 0))
822 d->initialize(
KUrl());
829 d(new Private(this, placesModel))
841 historyIndex = d->adjustedHistoryIndex(historyIndex);
847 d->m_history[d->m_historyIndex].state = state;
852 historyIndex = d->adjustedHistoryIndex(historyIndex);
858 const int count = d->m_history.count();
859 if (d->m_historyIndex < count - 1) {
876 if (d->m_historyIndex > 0) {
895 if (upUrl != currentUrl) {
905 if (d->m_homeUrl.isEmpty() || !d->m_homeUrl.isValid()) {
924 if (d->m_editable != editable) {
931 return d->m_editable;
936 if (d->m_showFullPath != show) {
937 d->m_showFullPath =
show;
944 return d->m_showFullPath;
950 if (active != d->m_active) {
951 d->m_active = active;
953 d->m_dropDownButton->setActive(active);
972 if (visible == d->m_showPlacesSelector) {
976 if (visible && (d->m_placesSelector == 0)) {
982 d->m_showPlacesSelector =
visible;
983 d->m_placesSelector->setVisible(visible);
988 return d->m_showPlacesSelector;
993 KUriFilterData filteredData(d->m_pathBox->currentText().trimmed());
996 return filteredData.uri();
999 return KUrl(filteredData.typedString());
1016 bool insideCompressedPath = d->isCompressedPath(url);
1017 if (!insideCompressedPath) {
1020 while (parentUrl != prevUrl) {
1021 if (d->isCompressedPath(parentUrl)) {
1022 insideCompressedPath =
true;
1025 prevUrl = parentUrl;
1026 parentUrl = parentUrl.
upUrl();
1029 if (!insideCompressedPath) {
1038 const LocationData& data = d->m_history[d->m_historyIndex];
1047 if (d->m_historyIndex > 0) {
1053 d->m_history.erase(begin, end);
1054 d->m_historyIndex = 0;
1057 Q_ASSERT(d->m_historyIndex == 0);
1058 LocationData newData;
1060 d->m_history.insert(0, newData);
1064 const int historyMax = 100;
1065 if (d->m_history.size() > historyMax) {
1068 d->m_history.erase(begin, end);
1087 d->m_pathBox->setFocus();
1093 #ifndef KDE_NO_DEPRECATED
1094 void KUrlNavigator::setUrl(
const KUrl& url)
1101 #ifndef KDE_NO_DEPRECATED
1102 void KUrlNavigator::saveRootUrl(
const KUrl& url)
1105 d->m_history[d->m_historyIndex].rootUrl = url;
1109 #ifndef KDE_NO_DEPRECATED
1110 void KUrlNavigator::savePosition(
int x,
int y)
1113 d->m_history[d->m_historyIndex].pos =
QPoint(x, y);
1133 if (event->
button() == Qt::MidButton) {
1134 const QRect bounds = d->m_toggleEditableMode->geometry();
1164 switch (event->
type()) {
1165 case QEvent::FocusIn:
1166 if (watched == d->m_pathBox) {
1175 case QEvent::FocusOut:
1190 return d->m_history.count();
1195 return d->m_historyIndex;
1200 return d->m_pathBox;
1205 d->m_customProtocols = protocols;
1206 d->m_protocols->setCustomProtocols(d->m_customProtocols);
1211 return d->m_customProtocols;
1214 #ifndef KDE_NO_DEPRECATED
1215 const KUrl& KUrlNavigator::url()
const
1227 #ifndef KDE_NO_DEPRECATED
1228 KUrl KUrlNavigator::url(
int index)
const
1231 return d->buttonUrl(index);
1235 #ifndef KDE_NO_DEPRECATED
1236 KUrl KUrlNavigator::historyUrl(
int historyIndex)
const
1243 #ifndef KDE_NO_DEPRECATED
1244 const KUrl& KUrlNavigator::savedRootUrl()
const
1250 static KUrl rootUrl;
1251 rootUrl = d->m_history[d->m_historyIndex].rootUrl;
1256 #ifndef KDE_NO_DEPRECATED
1257 QPoint KUrlNavigator::savedPosition()
const
1260 return d->m_history[d->m_historyIndex].pos;
1264 #ifndef KDE_NO_DEPRECATED
1272 #include "kurlnavigator.moc"
void editableStateChanged(bool editable)
Is emitted, if the editable state for the URL has been changed (see KUrlNavigator::setUrlEditable())...
QString i18n(const char *text)
void urlAboutToBeChanged(const KUrl &newUrl)
Is emitted, before the location URL is going to be changed to newUrl.
void adjustPath(AdjustPathOption trailing)
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
bool goUp()
Goes up one step of the URL path and remembers the old path in the history.
QString & append(QChar ch)
void setActive(bool active)
Set the URL navigator to the active mode, if active is true.
QStringList customProtocols() const
QByteArray locationState(int historyIndex=-1) const
const QMimeData * mimeData() const
Qt::KeyboardModifiers keyboardModifiers()
const QMimeData * mimeData(Mode mode) const
void setCustomProtocols(const QStringList &protocols)
If an application supports only some special protocols, they can be set with protocols ...
KUrl locationUrl(int historyIndex=-1) const
KUrl uncommittedUrl() const
void cleanPath(const CleanPathOption &options=SimplifyDirSeparators)
void setHomeUrl(const KUrl &url)
Sets the home URL used by KUrlNavigator::goHome().
iterator erase(iterator pos)
QAction * addAction(QAction *action)
void urlsDropped(const KUrl &destination, QDropEvent *event)
Is emitted if a dropping has been done above the destination destination.
void goHome()
Goes to the home URL and remembers the old URL in the history.
QString & remove(int position, int n)
void setLocationUrl(const KUrl &url)
Sets the location to url.
Allows to select a bookmark from a popup menu.
void setPath(const QString &path)
bool isUrlEditable() const
void setProtocol(const QString &proto)
void installEventFilter(QObject *filterObj)
void setUrl(const QString &url)
static KUrl::List fromMimeData(const QMimeData *mimeData, KUrl::MetaDataMap *metaData=0)
int removeAll(const T &value)
QString pathOrUrl() const
void setText(const QString &text)
virtual bool eventFilter(QObject *watched, QEvent *event)
bool showFullPath() const
bool contains(const QPoint &point, bool proper) const
bool goBack()
Goes back one step in the URL history.
void setShowFullPath(bool show)
Shows the full path of the URL even if a place represents a part of the URL.
QString path(AdjustPathOption trailing=LeaveTrailingSlash) const
void setMimeData(QMimeData *src, Mode mode)
void activated()
Is emitted, if the URL navigator has been activated by an user interaction.
void saveLocationState(const QByteArray &state)
Saves the location state described by state for the current location.
void setData(const QVariant &userData)
static KUriFilter * self()
bool isPlacesSelectorVisible() const
A combobox listing available protocols.
QString text(Mode mode) const
void tabRequested(const KUrl &url)
Is emitted if the URL url should be opened in a new tab because the user clicked on a breadcrumb with...
KUrlComboBox * editor() const
bool goForward()
Goes forward one step in the URL history.
void returnPressed()
This signal is emitted when the Return or Enter key is pressed.
void historyChanged()
Is emitted, if the history has been changed.
const QChar at(int position) const
QString section(QChar sep, int start, int end, QFlags< QString::SectionFlag > flags) const
QString left(int n) const
void prepend(const T &value)
KUrlNavigator(QWidget *parent=0)
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
void setPlacesSelectorVisible(bool visible)
Sets the places selector visible, if visible is true.
Widget that allows to navigate through the paths of an URL.
void setUrlEditable(bool editable)
Allows to edit the URL of the navigation bar if editable is true, and sets the focus accordingly...
const QPoint & pos() const
void requestActivation()
Activates the URL navigator (KUrlNavigator::isActive() will return true) and emits the signal KUrlNav...
const_iterator constEnd() const
const_iterator constBegin() const
void urlChanged(const KUrl &url)
Is emitted, if the location URL has been changed e.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
bool equals(const KUrl &u, const EqualsOptions &options=0) const
QString prettyUrl(AdjustPathOption trailing=LeaveTrailingSlash) const
void setCheckForExecutables(bool check)
void append(const T &value)
const KShortcut & begin()
This class is a list view model.