]>
cloud.milkyroute.net Git - dolphin.git/blob - src/urlnavigator.cpp
1 /***************************************************************************
2 * Copyright (C) 2006 by Peter Penz (<peter.penz@gmx.at>) *
3 * Copyright (C) 2006 by Aaron J. Seigo (<aseigo@kde.org>) *
4 * Copyright (C) 2006 by Patrice Tremblay *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20 ***************************************************************************/
22 #include "urlnavigator.h"
24 #include "bookmarkselector.h"
25 #include "dolphinsettings.h"
26 #include "dolphin_generalsettings.h"
27 #include "protocolcombo.h"
28 #include "urlnavigatorbutton.h"
32 #include <kfileitem.h>
35 #include <kprotocolinfo.h>
36 #include <kurlcombobox.h>
37 #include <kurlcompletion.h>
39 #include <QApplication>
42 #include <QHBoxLayout>
45 #include <QMouseEvent>
46 #include <QToolButton>
48 UrlNavigator::HistoryElem::HistoryElem() :
56 UrlNavigator::HistoryElem::HistoryElem(const KUrl
& url
) :
64 UrlNavigator::HistoryElem::~HistoryElem()
68 UrlNavigator::UrlNavigator(KBookmarkManager
* bookmarkManager
,
73 m_showHiddenFiles(false),
77 m_protocolSeparator(0),
81 m_layout
= new QHBoxLayout();
82 m_layout
->setSpacing(0);
83 m_layout
->setMargin(0);
85 m_history
.prepend(HistoryElem(url
));
87 QFontMetrics
fontMetrics(font());
88 setMinimumHeight(fontMetrics
.height() + 10);
90 // intialize toggle button which switches between the breadcrumb view
91 // and the traditional view
92 m_toggleButton
= new QToolButton();
93 m_toggleButton
->setCheckable(true);
94 m_toggleButton
->setAutoRaise(true);
95 m_toggleButton
->setIcon(KIcon("editinput")); // TODO: is just a placeholder icon (?)
96 m_toggleButton
->setFocusPolicy(Qt::NoFocus
);
97 m_toggleButton
->setMinimumHeight(minimumHeight());
98 connect(m_toggleButton
, SIGNAL(clicked()),
99 this, SLOT(switchView()));
100 if (DolphinSettings::instance().generalSettings()->editableUrl()) {
101 m_toggleButton
->toggle();
104 // initialize the bookmark selector
105 m_bookmarkSelector
= new BookmarkSelector(this, bookmarkManager
);
106 connect(m_bookmarkSelector
, SIGNAL(bookmarkActivated(const KUrl
&)),
107 this, SLOT(setUrl(const KUrl
&)));
109 // initialize the path box of the traditional view
110 m_pathBox
= new KUrlComboBox(KUrlComboBox::Directories
, true, this);
112 KUrlCompletion
* kurlCompletion
= new KUrlCompletion(KUrlCompletion::DirCompletion
);
113 m_pathBox
->setCompletionObject(kurlCompletion
);
114 m_pathBox
->setAutoDeleteCompletionObject(true);
116 connect(m_pathBox
, SIGNAL(returnPressed(const QString
&)),
117 this, SLOT(slotReturnPressed(const QString
&)));
118 connect(m_pathBox
, SIGNAL(urlActivated(const KUrl
&)),
119 this, SLOT(slotUrlActivated(const KUrl
&)));
121 //connect(dolphinView, SIGNAL(redirection(const KUrl&, const KUrl&)),
122 // this, SLOT(slotRedirection(const KUrl&, const KUrl&)));
124 // Append a filler widget at the end, which automatically resizes to the
125 // maximum available width. This assures that the URL navigator uses the
126 // whole width, so that the clipboard content can be dropped.
127 m_filler
= new QWidget();
128 m_filler
->setSizePolicy(QSizePolicy::Expanding
, QSizePolicy::Preferred
);
130 m_layout
->addWidget(m_toggleButton
);
131 m_layout
->addWidget(m_bookmarkSelector
);
132 m_layout
->addWidget(m_pathBox
);
133 m_layout
->addWidget(m_filler
);
139 UrlNavigator::~UrlNavigator()
143 const KUrl
& UrlNavigator::url() const
145 assert(!m_history
.empty());
146 return m_history
[m_historyIndex
].url();
149 KUrl
UrlNavigator::url(int index
) const
152 // keep scheme, hostname etc. maybe we will need this in the future
153 // for e.g. browsing ftp repositories.
155 newurl
.setPath(QString());
156 QString
path(url().path());
158 if (!path
.isEmpty()) {
159 if (index
== 0) //prevent the last "/" from being stripped
160 path
= "/"; //or we end up with an empty path
162 path
= path
.section('/', 0, index
);
165 newurl
.setPath(path
);
169 UrlNavigator::HistoryElem
UrlNavigator::currentHistoryItem() const
171 return m_history
[m_historyIndex
];
174 int UrlNavigator::historySize() const
176 return m_history
.count();
179 void UrlNavigator::goBack()
183 const int count
= m_history
.count();
184 if (m_historyIndex
< count
- 1) {
187 emit
urlChanged(url());
188 emit
historyChanged();
192 void UrlNavigator::goForward()
194 if (m_historyIndex
> 0) {
197 emit
urlChanged(url());
198 emit
historyChanged();
202 void UrlNavigator::goUp()
204 setUrl(url().upUrl());
207 void UrlNavigator::goHome()
209 setUrl(DolphinSettings::instance().generalSettings()->homeUrl());
212 void UrlNavigator::setUrlEditable(bool editable
)
214 if (isUrlEditable() != editable
) {
215 m_toggleButton
->toggle();
220 bool UrlNavigator::isUrlEditable() const
222 return m_toggleButton
->isChecked();
225 void UrlNavigator::editUrl(bool editOrBrowse
)
227 setUrlEditable(editOrBrowse
);
229 m_pathBox
->setFocus();
233 void UrlNavigator::setActive(bool active
)
235 if (active
!= m_active
) {
244 void UrlNavigator::setShowHiddenFiles( bool show
)
246 m_showHiddenFiles
= show
;
249 void UrlNavigator::dropUrls(const KUrl::List
& urls
,
250 const KUrl
& destination
)
252 emit
urlsDropped(urls
, destination
);
255 void UrlNavigator::setUrl(const KUrl
& url
)
257 QString
urlStr(url
.pathOrUrl());
259 // TODO: a patch has been submitted by Filip Brcic which adjusts
260 // the URL for tar and zip files. See https://bugs.kde.org/show_bug.cgi?id=142781
261 // for details. The URL navigator part of the patch has not been committed yet,
262 // as the URL navigator will be subject of change and
263 // we might think of a more generic approach to check the protocol + MIME type for
266 //kDebug() << "setUrl(" << url << ")" << endl;
267 if ( urlStr
.length() > 0 && urlStr
.at(0) == '~') {
268 // replace '~' by the home directory
270 urlStr
.insert(0, QDir::home().path());
273 const KUrl
transformedUrl(urlStr
);
275 if (m_historyIndex
> 0) {
276 // Check whether the previous element of the history has the same Url.
277 // If yes, just go forward instead of inserting a duplicate history
279 HistoryElem
& prevHistoryElem
= m_history
[m_historyIndex
- 1];
280 if (transformedUrl
== prevHistoryElem
.url()) {
282 // kDebug() << "goin' forward in history" << endl;
287 if (this->url() == transformedUrl
) {
288 // don't insert duplicate history elements
289 // kDebug() << "current url == transformedUrl" << endl;
294 m_history
.insert(m_historyIndex
, HistoryElem(transformedUrl
));
298 emit
urlChanged(transformedUrl
);
299 emit
historyChanged();
301 // Prevent an endless growing of the history: remembering
302 // the last 100 Urls should be enough...
303 if (m_historyIndex
> 100) {
304 m_history
.removeFirst();
308 /* kDebug() << "history starting ====================" << endl;
310 for (QValueListIterator<UrlNavigator::HistoryElem> it = m_history.begin();
311 it != m_history.end();
314 kDebug() << i << ": " << (*it).url() << endl;
316 kDebug() << "history done ========================" << endl;*/
321 void UrlNavigator::requestActivation()
326 void UrlNavigator::storeContentsPosition(int x
, int y
)
328 HistoryElem
& hist
= m_history
[m_historyIndex
];
329 hist
.setContentsX(x
);
330 hist
.setContentsY(y
);
333 void UrlNavigator::keyReleaseEvent(QKeyEvent
* event
)
335 QWidget::keyReleaseEvent(event
);
336 if (isUrlEditable() && (event
->key() == Qt::Key_Escape
)) {
337 setUrlEditable(false);
341 void UrlNavigator::mouseReleaseEvent(QMouseEvent
* event
)
343 if (event
->button() == Qt::MidButton
) {
344 QClipboard
* clipboard
= QApplication::clipboard();
345 const QMimeData
* mimeData
= clipboard
->mimeData();
346 if (mimeData
->hasText()) {
347 const QString text
= mimeData
->text();
351 QWidget::mouseReleaseEvent(event
);
354 void UrlNavigator::slotReturnPressed(const QString
& text
)
356 // Parts of the following code have been taken
357 // from the class KateFileSelector located in
358 // kate/app/katefileselector.hpp of Kate.
359 // Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
360 // Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
361 // Copyright (C) 2001 Anders Lund <anders.lund@lund.tdcadsl.dk>
364 if (typedUrl
.hasPass()) {
365 typedUrl
.setPass(QString());
368 QStringList urls
= m_pathBox
->urls();
369 urls
.removeAll(typedUrl
.url());
370 urls
.prepend(typedUrl
.url());
371 m_pathBox
->setUrls(urls
, KUrlComboBox::RemoveBottom
);
374 // The URL might have been adjusted by UrlNavigator::setUrl(), hence
375 // synchronize the result in the path box.
376 m_pathBox
->setUrl(url());
379 void UrlNavigator::slotUrlActivated(const KUrl
& url
)
384 void UrlNavigator::slotRemoteHostActivated()
388 QString host
= m_host
->text();
391 int marker
= host
.indexOf("@");
394 user
= host
.left(marker
);
396 host
= host
.right(host
.length() - marker
- 1);
399 marker
= host
.indexOf("/");
402 u
.setPath(host
.right(host
.length() - marker
));
403 host
.truncate(marker
);
410 if (m_protocols
->currentProtocol() != u
.protocol() ||
414 u
.setProtocol(m_protocols
->currentProtocol());
415 u
.setHost(m_host
->text());
417 //TODO: get rid of this HACK for file:///!
418 if (u
.protocol() == "file")
421 if (u
.path().isEmpty())
431 void UrlNavigator::slotProtocolChanged(const QString
& protocol
)
434 url
.setProtocol(protocol
);
435 //url.setPath(KProtocolInfo::protocolClass(protocol) == ":local" ? "/" : "");
437 QLinkedList
<UrlNavigatorButton
*>::const_iterator it
= m_navButtons
.begin();
438 const QLinkedList
<UrlNavigatorButton
*>::const_iterator itEnd
= m_navButtons
.end();
439 while (it
!= itEnd
) {
441 (*it
)->deleteLater();
444 m_navButtons
.clear();
446 if (KProtocolInfo::protocolClass(protocol
) == ":local") {
451 m_protocolSeparator
= new QLabel("://", this);
452 appendWidget(m_protocolSeparator
);
453 m_host
= new QLineEdit(this);
454 appendWidget(m_host
);
456 connect(m_host
, SIGNAL(lostFocus()),
457 this, SLOT(slotRemoteHostActivated()));
458 connect(m_host
, SIGNAL(returnPressed()),
459 this, SLOT(slotRemoteHostActivated()));
464 m_protocolSeparator
->show();
470 void UrlNavigator::slotRedirection(const KUrl
& oldUrl
, const KUrl
& newUrl
)
472 // kDebug() << "received redirection to " << newUrl << endl;
473 kDebug() << "received redirection from " << oldUrl
<< " to " << newUrl
<< endl
;
474 /* UrlStack::iterator it = m_urls.find(oldUrl);
475 if (it != m_urls.end())
477 m_urls.erase(++it, m_urls.end());
480 m_urls.append(newUrl);*/
483 void UrlNavigator::switchView()
486 if (isUrlEditable()) {
487 m_pathBox
->setFocus();
490 setUrl(m_pathBox
->currentText());
492 emit
requestActivation();
495 void UrlNavigator::updateHistoryElem()
497 assert(m_historyIndex
>= 0);
498 const KFileItem
* item
= 0; // TODO: m_dolphinView->currentFileItem();
500 HistoryElem
& hist
= m_history
[m_historyIndex
];
501 hist
.setCurrentFileName(item
->name());
505 void UrlNavigator::updateContent()
507 m_bookmarkSelector
->updateSelection(url());
509 m_toggleButton
->setToolTip(QString());
510 QString
path(url().pathOrUrl());
512 // TODO: prevent accessing the DolphinMainWindow out from this scope
513 //const QAction* action = dolphinView()->mainWindow()->actionCollection()->action("editable_location");
514 // TODO: registry of default shortcuts
515 //QString shortcut = action? action->shortcut().toString() : "Ctrl+L";
516 const QString shortcut
= "Ctrl+L";
518 if (m_toggleButton
->isChecked()) {
519 delete m_protocols
; m_protocols
= 0;
520 delete m_protocolSeparator
; m_protocolSeparator
= 0;
521 delete m_host
; m_host
= 0;
525 m_toggleButton
->setToolTip(i18n("Browse (%1, Escape)", shortcut
));
527 setSizePolicy(QSizePolicy::Minimum
, QSizePolicy::Fixed
);
529 m_pathBox
->setUrl(url());
532 m_toggleButton
->setToolTip(i18n("Edit location (%1)", shortcut
));
534 setSizePolicy(QSizePolicy::Expanding
, QSizePolicy::Fixed
);
538 // get the data from the currently selected bookmark
539 KBookmark bookmark
= m_bookmarkSelector
->selectedBookmark();
541 QString bookmarkPath
;
542 if (bookmark
.isNull()) {
543 // No bookmark is a part of the current Url.
544 // The following code tries to guess the bookmark
545 // path. E. g. "fish://root@192.168.0.2/var/lib" writes
546 // "fish://root@192.168.0.2" to 'bookmarkPath', which leads to the
547 // navigation indication 'Custom Path > var > lib".
548 int idx
= path
.indexOf(QString("//"));
549 idx
= path
.indexOf("/", (idx
< 0) ? 0 : idx
+ 2);
550 bookmarkPath
= (idx
< 0) ? path
: path
.left(idx
);
553 bookmarkPath
= bookmark
.url().pathOrUrl();
555 const uint len
= bookmarkPath
.length();
557 // calculate the start point for the URL navigator buttons by counting
558 // the slashs inside the bookmark URL
560 for (uint i
= 0; i
< len
; ++i
) {
561 if (bookmarkPath
.at(i
) == QChar('/')) {
565 if ((len
> 0) && bookmarkPath
.at(len
- 1) == QChar('/')) {
566 assert(slashCount
> 0);
570 if (!url().isLocalFile() && bookmark
.isNull()) {
571 QString protocol
= url().protocol();
574 m_protocols
= new ProtocolCombo(protocol
, this);
575 appendWidget(m_protocols
);
576 connect(m_protocols
, SIGNAL(activated(const QString
&)),
577 this, SLOT(slotProtocolChanged(const QString
&)));
580 m_protocols
->setProtocol(protocol
);
584 if (KProtocolInfo::protocolClass(protocol
) != ":local") {
585 QString hostText
= url().host();
587 if (!url().user().isEmpty()) {
588 hostText
= url().user() + '@' + hostText
;
592 m_protocolSeparator
= new QLabel("://", this);
593 appendWidget(m_protocolSeparator
);
594 m_host
= new QLineEdit(hostText
, this);
595 appendWidget(m_host
);
597 connect(m_host
, SIGNAL(lostFocus()),
598 this, SLOT(slotRemoteHostActivated()));
599 connect(m_host
, SIGNAL(returnPressed()),
600 this, SLOT(slotRemoteHostActivated()));
603 m_host
->setText(hostText
);
605 m_protocolSeparator
->show();
609 delete m_protocolSeparator
; m_protocolSeparator
= 0;
610 delete m_host
; m_host
= 0;
613 else if (m_protocols
) {
617 m_protocolSeparator
->hide();
622 updateButtons(path
, slashCount
);
626 void UrlNavigator::updateButtons(const QString
& path
, int startIndex
)
628 QLinkedList
<UrlNavigatorButton
*>::iterator it
= m_navButtons
.begin();
629 const QLinkedList
<UrlNavigatorButton
*>::const_iterator itEnd
= m_navButtons
.end();
630 bool createButton
= false;
632 int idx
= startIndex
;
635 createButton
= (it
== itEnd
);
637 const QString dirName
= path
.section('/', idx
, idx
);
638 const bool isFirstButton
= (idx
== startIndex
);
639 hasNext
= isFirstButton
|| !dirName
.isEmpty();
643 // the first URL navigator button should get the name of the
644 // bookmark instead of the directory name
645 const KBookmark bookmark
= m_bookmarkSelector
->selectedBookmark();
646 text
= bookmark
.text();
647 if (text
.isEmpty()) {
648 if (url().isLocalFile()) {
649 text
= i18n("Custom Path");
658 UrlNavigatorButton
* button
= 0;
660 button
= new UrlNavigatorButton(idx
, this);
661 appendWidget(button
);
665 button
->setIndex(idx
);
669 button
->setText(text
);
674 m_navButtons
.append(button
);
683 // delete buttons which are not used anymore
684 QLinkedList
<UrlNavigatorButton
*>::iterator itBegin
= it
;
685 while (it
!= itEnd
) {
687 (*it
)->deleteLater();
690 m_navButtons
.erase(itBegin
, m_navButtons
.end());
693 void UrlNavigator::deleteButtons()
695 QLinkedList
<UrlNavigatorButton
*>::iterator itBegin
= m_navButtons
.begin();
696 QLinkedList
<UrlNavigatorButton
*>::iterator itEnd
= m_navButtons
.end();
697 QLinkedList
<UrlNavigatorButton
*>::iterator it
= itBegin
;
698 while (it
!= itEnd
) {
700 (*it
)->deleteLater();
703 m_navButtons
.erase(itBegin
, itEnd
);
706 void UrlNavigator::appendWidget(QWidget
* widget
)
708 m_layout
->insertWidget(m_layout
->count() - 1, widget
);
711 #include "urlnavigator.moc"