|
|
|
/***************************************************************************
|
|
|
|
* 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 <kurl.h>
|
|
|
|
#include <tqobjectlist.h>
|
|
|
|
#include <tqcombobox.h>
|
|
|
|
#include <klocale.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 <kio/job.h>
|
|
|
|
#include <kurlcombobox.h>
|
|
|
|
#include <kurlcompletion.h>
|
|
|
|
#include <kbookmarkmanager.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(TQ_NoFocus);
|
|
|
|
m_toggleButton->setMinimumHeight(minimumHeight());
|
|
|
|
connect(m_toggleButton, TQT_SIGNAL(clicked()),
|
|
|
|
this, TQT_SLOT(slotClicked()));
|
|
|
|
if (DolphinSettings::instance().isURLEditable()) {
|
|
|
|
m_toggleButton->toggle();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_bookmarkSelector = new BookmarkSelector(this);
|
|
|
|
connect(m_bookmarkSelector, TQT_SIGNAL(bookmarkActivated(int)),
|
|
|
|
this, TQT_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, TQT_SIGNAL(returnPressed(const TQString&)),
|
|
|
|
this, TQT_SLOT(slotReturnPressed(const TQString&)));
|
|
|
|
connect(m_pathBox, TQT_SIGNAL(urlActivated(const KURL&)),
|
|
|
|
this, TQT_SLOT(slotURLActivated(const KURL&)));
|
|
|
|
|
|
|
|
connect(dolphinView, TQT_SIGNAL(contentsMoved(int, int)),
|
|
|
|
this, TQT_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")) {
|
|
|
|
stillInside = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
KURL url1 = url.upURL();
|
|
|
|
while (url1 != url1.upURL()) {
|
|
|
|
if (KMimeType::findByPath(url1.url(-1))
|
|
|
|
->is("application/x-zip")) {
|
|
|
|
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")
|
|
|
|
) {
|
|
|
|
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")
|
|
|
|
) {
|
|
|
|
stillInside = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
url1 = url1.upURL();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!stillInside)
|
|
|
|
{
|
|
|
|
// Drop the tar:/ protocol since we are not in the tar anymore
|
|
|
|
urlStr = url.path();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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(TQT_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)"));
|
|
|
|
|
|
|
|
tqsetSizePolicy(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)"));
|
|
|
|
|
|
|
|
tqsetSizePolicy(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"
|