You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dolphin/src/urlnavigator.cpp

538 lines
16 KiB

/***************************************************************************
* Copyright (C) 2006 by Peter Penz (peter.penz@gmx.at) *
* Copyright (C) 2006 by Aaron J. Seigo (<aseigo@kde.org>) *
* Copyright (C) 2006 by Patrice Tremblay *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "urlnavigator.h"
#include <assert.h>
#include <dcopref.h>
#include <kurl.h>
#include <tqobjectlist.h>
#include <tqcombobox.h>
#include <tdelocale.h>
#include <kiconloader.h>
#include <tqpopupmenu.h>
#include <tqlineedit.h>
#include <tqpushbutton.h>
#include <tqsizepolicy.h>
#include <tqtooltip.h>
#include <tqfont.h>
#include <tqlistbox.h>
#include <tdeio/job.h>
#include <kurlcombobox.h>
#include <kurlcompletion.h>
#include <kbookmarkmanager.h>
#include <kstandarddirs.h>
#include "dolphin.h"
#include "dolphinsettings.h"
#include "bookmarkselector.h"
#include "dolphinstatusbar.h"
#include "urlnavigatorbutton.h"
#include "dolphinview.h"
URLNavigator::HistoryElem::HistoryElem()
: m_url(),
m_currentFileName(),
m_contentsX(0),
m_contentsY(0)
{
}
URLNavigator::HistoryElem::HistoryElem(const KURL& url)
: m_url(url),
m_currentFileName(),
m_contentsX(0),
m_contentsY(0)
{
}
URLNavigator::HistoryElem::~HistoryElem()
{
}
URLNavigator::URLNavigator(const KURL& url,
DolphinView* dolphinView) :
TQHBox(dolphinView),
m_historyIndex(0),
m_dolphinView(dolphinView)
{
m_history.prepend(HistoryElem(url));
TQFontMetrics fontMetrics(font());
setMinimumHeight(fontMetrics.height() + 8);
m_toggleButton = new TQPushButton(SmallIcon("editurl"), 0, this);
m_toggleButton->setFlat(true);
m_toggleButton->setToggleButton(true);
m_toggleButton->setFocusPolicy(TQWidget::NoFocus);
m_toggleButton->setMinimumHeight(minimumHeight());
connect(m_toggleButton, TQ_SIGNAL(clicked()),
this, TQ_SLOT(slotClicked()));
if (DolphinSettings::instance().isURLEditable()) {
m_toggleButton->toggle();
}
m_bookmarkSelector = new BookmarkSelector(this);
connect(m_bookmarkSelector, TQ_SIGNAL(bookmarkActivated(int)),
this, TQ_SLOT(slotBookmarkActivated(int)));
m_pathBox = new KURLComboBox(KURLComboBox::Directories, true, this);
KURLCompletion* kurlCompletion = new KURLCompletion(KURLCompletion::DirCompletion);
m_pathBox->setCompletionObject(kurlCompletion);
m_pathBox->setAutoDeleteCompletionObject(true);
connect(m_pathBox, TQ_SIGNAL(returnPressed(const TQString&)),
this, TQ_SLOT(slotReturnPressed(const TQString&)));
connect(m_pathBox, TQ_SIGNAL(urlActivated(const KURL&)),
this, TQ_SLOT(slotURLActivated(const KURL&)));
connect(dolphinView, TQ_SIGNAL(contentsMoved(int, int)),
this, TQ_SLOT(slotContentsMoved(int, int)));
updateContent();
}
URLNavigator::~URLNavigator()
{
}
void URLNavigator::setURL(const KURL& url)
{
TQString urlStr(url.prettyURL());
if (url.protocol() == "zip")
{
bool stillInside = false;
if( KMimeType::findByPath( url.url(-1) )->is("application/x-zip") ||
KMimeType::findByPath( url.url(-1) )->is("application/x-jar") ) {
stillInside = true;
}
else {
KURL url1 = url.upURL();
while (url1 != url1.upURL()) {
if( KMimeType::findByPath( url1.url(-1) )->is("application/x-zip") ||
KMimeType::findByPath( url1.url(-1) )->is("application/x-jar") ) {
stillInside = true;
break;
}
url1 = url1.upURL();
}
}
if (!stillInside)
{
// Drop the zip:/ protocol since we are not in the zip anymore
urlStr = url.path();
}
}
else if (url.protocol() == "tar")
{
bool stillInside = false;
KMimeType::Ptr kmp =
KMimeType::findByPath(url.url(-1));
if( kmp->is("application/x-tar") ||
kmp->is("application/x-tarz") ||
kmp->is("application/x-tbz") ||
kmp->is("application/x-tgz") ||
kmp->is("application/x-tzo") ||
kmp->is("application/x-txz") ||
kmp->is("application/x-tlzma")
) {
stillInside = true;
}
else {
KURL url1 = url.upURL();
while (url1 != url1.upURL()) {
KMimeType::Ptr kmp =
KMimeType::findByPath(url1.url(-1));
if( kmp->is("application/x-tar") ||
kmp->is("application/x-tarz") ||
kmp->is("application/x-tbz") ||
kmp->is("application/x-tgz") ||
kmp->is("application/x-tzo") ||
kmp->is("application/x-txz") ||
kmp->is("application/x-tlzma")
) {
stillInside = true;
break;
}
url1 = url1.upURL();
}
}
if (!stillInside)
{
// Drop the tar:/ protocol since we are not in the tar anymore
urlStr = url.path();
}
}
else if (urlStr.startsWith("system:/media") || urlStr.startsWith("media:/"))
{
DCOPRef mediamanager("kded", "mediamanager");
DCOPReply reply = mediamanager.call("mimeType", urlStr );
if (reply.isValid())
{
TQString itemMimeType = reply;
if (itemMimeType.contains("encrypted"))
{
if (itemMimeType.contains("encrypted_locked"))
{
TQString lockingService = TDEGlobal::dirs()->findResource("data", "d3lphin/servicemenus/media_unlock.desktop");
if (!lockingService.isEmpty())
{
TQValueList<KDEDesktopMimeType::Service> serviceList = KDEDesktopMimeType::userDefinedServices(lockingService, url.isLocalFile());
if (serviceList.count() == 1)
{
KURL::List m_lstURLs;
m_lstURLs.append(url);
KDEDesktopMimeType::executeService(m_lstURLs, serviceList[0]);
}
}
}
setURL(KURL("system:/media"));
return;
}
}
}
if (urlStr.at(0) == '~') {
// replace '~' by the home directory
urlStr.remove(0, 1);
urlStr.insert(0, TQDir::home().path());
}
const KURL transformedURL(urlStr);
if (m_historyIndex > 0) {
// Check whether the previous element of the history has the same URL.
// If yes, just go forward instead of inserting a duplicate history
// element.
const KURL& nextURL = m_history[m_historyIndex - 1].url();
if (transformedURL == nextURL) {
goForward();
return;
}
}
const KURL& currURL = m_history[m_historyIndex].url();
if (currURL == transformedURL) {
// don't insert duplicate history elements
return;
}
updateHistoryElem();
const TQValueListIterator<URLNavigator::HistoryElem> it = m_history.at(m_historyIndex);
m_history.insert(it, HistoryElem(transformedURL));
updateContent();
emit urlChanged(transformedURL);
emit historyChanged();
// Prevent an endless growing of the history: remembering
// the last 100 URLs should be enough...
if (m_historyIndex > 100) {
m_history.erase(m_history.begin());
--m_historyIndex;
}
}
const KURL& URLNavigator::url() const
{
assert(!m_history.empty());
return m_history[m_historyIndex].url();
}
KURL URLNavigator::url(int index) const
{
assert(index >= 0);
TQString path(url().prettyURL());
path = path.section('/', 0, index);
if (path.at(path.length()) != '/')
{
path.append('/');
}
return path;
}
const TQValueList<URLNavigator::HistoryElem>& URLNavigator::history(int& index) const
{
index = m_historyIndex;
return m_history;
}
void URLNavigator::goBack()
{
updateHistoryElem();
const int count = m_history.count();
if (m_historyIndex < count - 1) {
++m_historyIndex;
updateContent();
emit urlChanged(url());
emit historyChanged();
}
}
void URLNavigator::goForward()
{
if (m_historyIndex > 0) {
--m_historyIndex;
updateContent();
emit urlChanged(url());
emit historyChanged();
}
}
void URLNavigator::goUp()
{
setURL(url().upURL());
}
void URLNavigator::goHome()
{
setURL(DolphinSettings::instance().homeURL());
}
void URLNavigator::setURLEditable(bool editable)
{
if (isURLEditable() != editable) {
m_toggleButton->toggle();
slotClicked();
}
}
bool URLNavigator::isURLEditable() const
{
return m_toggleButton->state() == TQButton::On;
}
void URLNavigator::editURL()
{
setURLEditable(true);
m_pathBox->setFocus();
}
DolphinView* URLNavigator::dolphinView() const
{
return m_dolphinView;
}
void URLNavigator::keyReleaseEvent(TQKeyEvent* event)
{
TQHBox::keyReleaseEvent(event);
if (isURLEditable() && (event->key() == TQt::Key_Escape)) {
setURLEditable(false);
}
}
void URLNavigator::slotReturnPressed(const TQString& text)
{
// Parts of the following code have been taken
// from the class KateFileSelector located in
// kate/app/katefileselector.hpp of Kate.
// Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
// Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
// Copyright (C) 2001 Anders Lund <anders.lund@lund.tdcadsl.dk>
KURL typedURL(text);
if (typedURL.hasPass()) {
typedURL.setPass(TQString());
}
TQStringList urls = m_pathBox->urls();
urls.remove(typedURL.url());
urls.prepend(typedURL.url());
m_pathBox->setURLs(urls, KURLComboBox::RemoveBottom);
setURL(typedURL);
// The URL might have been adjusted by URLNavigator::setURL(), hence
// synchronize the result in the path box.
m_pathBox->setURL(url());
}
void URLNavigator::slotURLActivated(const KURL& url)
{
setURL(url);
}
void URLNavigator::slotRequestActivation()
{
m_dolphinView->requestActivation();
}
void URLNavigator::slotBookmarkActivated(int index)
{
m_dolphinView->statusBar()->clear();
m_dolphinView->requestActivation();
KBookmark bookmark = DolphinSettings::instance().bookmark(index);
m_dolphinView->setURL(bookmark.url());
}
void URLNavigator::slotContentsMoved(int x, int y)
{
m_history[m_historyIndex].setContentsX(x);
m_history[m_historyIndex].setContentsY(y);
}
void URLNavigator::slotClicked()
{
updateContent();
if (isURLEditable()) {
m_pathBox->setFocus();
}
else {
m_dolphinView->setFocus();
}
}
void URLNavigator::updateHistoryElem()
{
assert(m_historyIndex >= 0);
const KFileItem* item = m_dolphinView->currentFileItem();
if (item != 0) {
m_history[m_historyIndex].setCurrentFileName(item->name());
}
m_history[m_historyIndex].setContentsX(m_dolphinView->contentsX());
m_history[m_historyIndex].setContentsY(m_dolphinView->contentsY());
}
void URLNavigator::updateContent()
{
const TQObjectList list = childrenListObject();
if (list.isEmpty()) {
return;
}
// set the iterator to the first URL navigator button
TQObjectListIterator it(list);
TQObject* object = 0;
while ((object = it.current()) != 0) {
if (object->inherits("URLNavigatorButton")) {
break;
}
++it;
}
// delete all existing URL navigator buttons
TQPtrList<TQWidget> deleteList;
while ((object = it.current()) != 0) {
if (object->inherits("URLNavigatorButton")) {
// Don't close and delete the navigator button immediatly, otherwise
// the iterator won't work anymore and an object would get deleted more
// than once (-> crash).
deleteList.append(static_cast<TQWidget*>(object));
}
++it;
}
// now close and delete all unused navigator buttons
TQPtrListIterator<TQWidget> deleteIter(deleteList);
TQWidget* widget = 0;
while ((widget = deleteIter.current()) != 0) {
widget->close();
widget->deleteLater();
++deleteIter;
}
m_bookmarkSelector->updateSelection(url());
TQToolTip::remove(m_toggleButton);
TQString path(url().prettyURL());
if (m_toggleButton->state() == TQButton::On) {
// TODO: don't hardcode the shortcut as part of the text
TQToolTip::add(m_toggleButton, i18n("Browse (Ctrl+B, Escape)"));
setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed);
m_pathBox->show();
m_pathBox->setURL(url());
}
else {
// TODO: don't hardcode the shortcut as part of the text
TQToolTip::add(m_toggleButton, i18n("Edit location (Ctrl+L)"));
setSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed);
m_pathBox->hide();
TQString dir_name;
// get the data from the currently selected bookmark
KBookmark bookmark = m_bookmarkSelector->selectedBookmark();
//int bookmarkIndex = m_bookmarkSelector->selectedIndex();
TQString bookmarkPath;
if (bookmark.isNull()) {
// No bookmark is a part of the current URL.
// The following code tries to guess the bookmark
// path. E. g. "fish://root@192.168.0.2/var/lib" writes
// "fish://root@192.168.0.2" to 'bookmarkPath', which leads to the
// navigation indication 'Custom Path > var > lib".
int idx = path.find(TQString("//"));
idx = path.find("/", (idx < 0) ? 0 : idx + 2);
bookmarkPath = (idx < 0) ? path : path.left(idx);
}
else {
bookmarkPath = bookmark.url().prettyURL();
}
const uint len = bookmarkPath.length();
// calculate the start point for the URL navigator buttons by counting
// the slashs inside the bookmark URL
int slashCount = 0;
for (uint i = 0; i < len; ++i) {
if (bookmarkPath.at(i) == TQChar('/')) {
++slashCount;
}
}
if ((len > 0) && bookmarkPath.at(len - 1) == TQChar('/')) {
assert(slashCount > 0);
--slashCount;
}
// create URL navigator buttons
int idx = slashCount;
bool hasNext = true;
do {
dir_name = path.section('/', idx, idx);
const bool isFirstButton = (idx == slashCount);
hasNext = isFirstButton || !dir_name.isEmpty();
if (hasNext) {
URLNavigatorButton* button = new URLNavigatorButton(idx, this);
if (isFirstButton) {
// the first URL navigator button should get the name of the bookmark
// instead of the directory name
TQString text = bookmark.text();
if (text.isEmpty()) {
text = bookmarkPath;
}
button->setText(text);
}
button->show();
++idx;
}
} while (hasNext);
}
}
#include "urlnavigator.moc"