|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2006 by Peter Penz (peter.penz@gmx.at) *
|
|
|
|
* Copyright (C) 2006 by Aaron J. Seigo (<aseigo@kde.org>) *
|
|
|
|
* *
|
|
|
|
* 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 "urlnavigatorbutton.h"
|
|
|
|
#include <tqcursor.h>
|
|
|
|
#include <tqfontmetrics.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
|
|
|
|
#include <kglobalsettings.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <kio/jobclasses.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kpopupmenu.h>
|
|
|
|
#include <kurl.h>
|
|
|
|
#include <kurldrag.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "urlnavigator.h"
|
|
|
|
#include "dolphinview.h"
|
|
|
|
#include "dolphin.h"
|
|
|
|
|
|
|
|
URLNavigatorButton::URLNavigatorButton(int index, URLNavigator* parent) :
|
|
|
|
URLButton(parent),
|
|
|
|
m_index(-1),
|
|
|
|
m_listJob(0)
|
|
|
|
{
|
|
|
|
setAcceptDrops(true);
|
|
|
|
setMinimumWidth(arrowWidth());
|
|
|
|
setIndex(index);
|
|
|
|
connect(this, TQT_SIGNAL(clicked()), this, TQT_SLOT(updateNavigatorURL()));
|
|
|
|
|
|
|
|
m_popupDelay = new TQTimer(this);
|
|
|
|
connect(m_popupDelay, TQT_SIGNAL(timeout()), this, TQT_SLOT(startListJob()));
|
|
|
|
connect(this, TQT_SIGNAL(pressed()), this, TQT_SLOT(startPopupDelay()));
|
|
|
|
}
|
|
|
|
|
|
|
|
URLNavigatorButton::~URLNavigatorButton()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::setIndex(int index)
|
|
|
|
{
|
|
|
|
if (index < 0) {
|
|
|
|
index = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_index = index;
|
|
|
|
TQString path(urlNavigator()->url().prettyURL());
|
|
|
|
setText(path.section('/', index, index));
|
|
|
|
|
|
|
|
// Check whether the button indicates the full path of the URL. If
|
|
|
|
// this is the case, the button is marked as 'active'.
|
|
|
|
++index;
|
|
|
|
TQFont adjustedFont(font());
|
|
|
|
if (path.section('/', index, index).isEmpty()) {
|
|
|
|
setDisplayHintEnabled(ActivatedHint, true);
|
|
|
|
adjustedFont.setBold(true);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
setDisplayHintEnabled(ActivatedHint, false);
|
|
|
|
adjustedFont.setBold(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
setFont(adjustedFont);
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
int URLNavigatorButton::index() const
|
|
|
|
{
|
|
|
|
return m_index;
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::drawButton(TQPainter* painter)
|
|
|
|
{
|
|
|
|
const int buttonWidth = width();
|
|
|
|
const int buttonHeight = height();
|
|
|
|
|
|
|
|
TQColor backgroundColor;
|
|
|
|
TQColor foregroundColor;
|
|
|
|
const bool isHighlighted = isDisplayHintEnabled(EnteredHint) ||
|
|
|
|
isDisplayHintEnabled(DraggedHint) ||
|
|
|
|
isDisplayHintEnabled(PopupActiveHint);
|
|
|
|
if (isHighlighted) {
|
|
|
|
backgroundColor = KGlobalSettings::highlightColor();
|
|
|
|
foregroundColor = KGlobalSettings::highlightedTextColor();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
backgroundColor = tqcolorGroup().background();
|
|
|
|
foregroundColor = KGlobalSettings::buttonTextColor();
|
|
|
|
}
|
|
|
|
|
|
|
|
// dimm the colors if the parent view does not have the focus
|
|
|
|
const DolphinView* parentView = urlNavigator()->dolphinView();
|
|
|
|
const Dolphin& dolphin = Dolphin::mainWin();
|
|
|
|
|
|
|
|
const bool isActive = (dolphin.activeView() == parentView);
|
|
|
|
if (!isActive) {
|
|
|
|
TQColor dimmColor(tqcolorGroup().background());
|
|
|
|
foregroundColor = mixColors(foregroundColor, dimmColor);
|
|
|
|
if (isHighlighted) {
|
|
|
|
backgroundColor = mixColors(backgroundColor, dimmColor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw button background
|
|
|
|
painter->setPen(NoPen);
|
|
|
|
painter->setBrush(backgroundColor);
|
|
|
|
painter->drawRect(0, 0, buttonWidth, buttonHeight);
|
|
|
|
|
|
|
|
int textWidth = buttonWidth;
|
|
|
|
if (isDisplayHintEnabled(ActivatedHint) && isActive || isHighlighted) {
|
|
|
|
painter->setPen(foregroundColor);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// dimm the foreground color by mixing it with the background
|
|
|
|
foregroundColor = mixColors(foregroundColor, backgroundColor);
|
|
|
|
painter->setPen(foregroundColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isDisplayHintEnabled(ActivatedHint)) {
|
|
|
|
// draw arrow
|
|
|
|
const int border = 2; // horizontal border
|
|
|
|
const int middleY = height() / 2;
|
|
|
|
const int width = arrowWidth();
|
|
|
|
const int startX = (buttonWidth - width) - (2 * border);
|
|
|
|
const int startTopY = middleY - (width - 1);
|
|
|
|
const int startBottomY = middleY + (width - 1);
|
|
|
|
for (int i = 0; i < width; ++i) {
|
|
|
|
painter->drawLine(startX, startTopY + i, startX + i, startTopY + i);
|
|
|
|
painter->drawLine(startX, startBottomY - i, startX + i, startBottomY - i);
|
|
|
|
}
|
|
|
|
|
|
|
|
textWidth = startX - border;
|
|
|
|
}
|
|
|
|
|
|
|
|
const bool clipped = isTextClipped();
|
|
|
|
const int align = clipped ? TQt::AlignVCenter : TQt::AlignCenter;
|
|
|
|
painter->drawText(TQRect(0, 0, textWidth, buttonHeight), align, text());
|
|
|
|
|
|
|
|
if (clipped) {
|
|
|
|
// Blend the right area of the text with the background, as the
|
|
|
|
// text is clipped.
|
|
|
|
// TODO: use alpha blending in TQt4 instead of drawing the text that often
|
|
|
|
const int blendSteps = 16;
|
|
|
|
|
|
|
|
TQColor blendColor(backgroundColor);
|
|
|
|
const int redInc = (foregroundColor.red() - backgroundColor.red()) / blendSteps;
|
|
|
|
const int greenInc = (foregroundColor.green() - backgroundColor.green()) / blendSteps;
|
|
|
|
const int blueInc = (foregroundColor.blue() - backgroundColor.blue()) / blendSteps;
|
|
|
|
for (int i = 0; i < blendSteps; ++i) {
|
|
|
|
painter->setClipRect(TQRect(textWidth - i, 0, 1, buttonHeight));
|
|
|
|
painter->setPen(blendColor);
|
|
|
|
painter->drawText(TQRect(0, 0, textWidth, buttonHeight), align, text());
|
|
|
|
|
|
|
|
blendColor.setRgb(blendColor.red() + redInc,
|
|
|
|
blendColor.green() + greenInc,
|
|
|
|
blendColor.blue() + blueInc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::enterEvent(TQEvent* event)
|
|
|
|
{
|
|
|
|
URLButton::enterEvent(event);
|
|
|
|
|
|
|
|
// if the text is clipped due to a small window width, the text should
|
|
|
|
// be shown as tooltip
|
|
|
|
if (isTextClipped()) {
|
|
|
|
TQToolTip::add(this, text());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::leaveEvent(TQEvent* event)
|
|
|
|
{
|
|
|
|
URLButton::leaveEvent(event);
|
|
|
|
TQToolTip::remove(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::dropEvent(TQDropEvent* event)
|
|
|
|
{
|
|
|
|
KURL::List urls;
|
|
|
|
if (KURLDrag::decode(event, urls) && !urls.isEmpty()) {
|
|
|
|
setDisplayHintEnabled(DraggedHint, true);
|
|
|
|
|
|
|
|
TQString path(urlNavigator()->url().prettyURL());
|
|
|
|
path = path.section('/', 0, m_index);
|
|
|
|
|
|
|
|
Dolphin::mainWin().dropURLs(urls, KURL(path));
|
|
|
|
|
|
|
|
setDisplayHintEnabled(DraggedHint, false);
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::dragEnterEvent(TQDragEnterEvent* event)
|
|
|
|
{
|
|
|
|
event->accept(KURLDrag::canDecode(event));
|
|
|
|
|
|
|
|
setDisplayHintEnabled(DraggedHint, true);
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::dragLeaveEvent(TQDragLeaveEvent* event)
|
|
|
|
{
|
|
|
|
URLButton::dragLeaveEvent(event);
|
|
|
|
|
|
|
|
setDisplayHintEnabled(DraggedHint, false);
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void URLNavigatorButton::updateNavigatorURL()
|
|
|
|
{
|
|
|
|
URLNavigator* navigator = urlNavigator();
|
|
|
|
assert(navigator != 0);
|
|
|
|
navigator->setURL(navigator->url(m_index));
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::startPopupDelay()
|
|
|
|
{
|
|
|
|
if (m_popupDelay->isActive() || m_listJob) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_popupDelay->start(300, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::stopPopupDelay()
|
|
|
|
{
|
|
|
|
m_popupDelay->stop();
|
|
|
|
if (m_listJob) {
|
|
|
|
m_listJob->kill();
|
|
|
|
m_listJob = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::startListJob()
|
|
|
|
{
|
|
|
|
if (m_listJob) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
KURL url = urlNavigator()->url(m_index);
|
|
|
|
m_listJob = KIO::listDir(url, false, false);
|
|
|
|
m_subdirs.clear(); // just to be ++safe
|
|
|
|
|
|
|
|
connect(m_listJob, TQT_SIGNAL(entries(KIO::Job*, const KIO::UDSEntryList &)),
|
|
|
|
this, TQT_SLOT(entriesList(KIO::Job*, const KIO::UDSEntryList&)));
|
|
|
|
connect(m_listJob, TQT_SIGNAL(result(KIO::Job*)), this, TQT_SLOT(listJobFinished(KIO::Job*)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::entriesList(KIO::Job* job, const KIO::UDSEntryList& entries)
|
|
|
|
{
|
|
|
|
if (job != m_listJob) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
KIO::UDSEntryList::const_iterator it = entries.constBegin();
|
|
|
|
KIO::UDSEntryList::const_iterator itEnd = entries.constEnd();
|
|
|
|
while (it != itEnd) {
|
|
|
|
TQString name;
|
|
|
|
bool isDir = false;
|
|
|
|
KIO::UDSEntry entry = *it;
|
|
|
|
KIO::UDSEntry::const_iterator atomIt = entry.constBegin();
|
|
|
|
KIO::UDSEntry::const_iterator atomEndIt = entry.constEnd();
|
|
|
|
|
|
|
|
while (atomIt != atomEndIt) {
|
|
|
|
switch ((*atomIt).m_uds) {
|
|
|
|
case KIO::UDS_NAME:
|
|
|
|
name = (*atomIt).m_str;
|
|
|
|
break;
|
|
|
|
case KIO::UDS_FILE_TYPE:
|
|
|
|
isDir = S_ISDIR((*atomIt).m_long);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++atomIt;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isDir) {
|
|
|
|
m_subdirs.append(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_subdirs.sort();
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::listJobFinished(KIO::Job* job)
|
|
|
|
{
|
|
|
|
if (job != m_listJob) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (job->error() || m_subdirs.isEmpty()) {
|
|
|
|
// clear listing
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
setDisplayHintEnabled(PopupActiveHint, true);
|
|
|
|
update(); // ensure the button is drawn highlighted
|
|
|
|
TQPopupMenu* dirsMenu = new TQPopupMenu(this);
|
|
|
|
//setPopup(dirsMenu);
|
|
|
|
TQStringList::const_iterator it = m_subdirs.constBegin();
|
|
|
|
TQStringList::const_iterator itEnd = m_subdirs.constEnd();
|
|
|
|
int i = 0;
|
|
|
|
while (it != itEnd) {
|
|
|
|
dirsMenu->insertItem(*it, i);
|
|
|
|
++i;
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
|
|
|
|
int result = dirsMenu->exec(urlNavigator()->mapToGlobal(tqgeometry().bottomLeft()));
|
|
|
|
|
|
|
|
if (result >= 0) {
|
|
|
|
KURL url = urlNavigator()->url(m_index);
|
|
|
|
url.addPath(*m_subdirs.at(result));
|
|
|
|
urlNavigator()->setURL(url);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_listJob = 0;
|
|
|
|
m_subdirs.clear();
|
|
|
|
delete dirsMenu;
|
|
|
|
setDisplayHintEnabled(PopupActiveHint, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
int URLNavigatorButton::arrowWidth() const
|
|
|
|
{
|
|
|
|
int width = (height() / 2) - 7;
|
|
|
|
if (width < 4) {
|
|
|
|
width = 4;
|
|
|
|
}
|
|
|
|
return width;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool URLNavigatorButton::isTextClipped() const
|
|
|
|
{
|
|
|
|
int availableWidth = width();
|
|
|
|
if (!isDisplayHintEnabled(ActivatedHint)) {
|
|
|
|
availableWidth -= arrowWidth() + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQFontMetrics fontMetrics(font());
|
|
|
|
return fontMetrics.width(text()) >= availableWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void URLNavigatorButton::mousePressEvent(TQMouseEvent * event)
|
|
|
|
{
|
|
|
|
if (event->button() == Qt::LeftButton)
|
|
|
|
dragPos = event->pos();
|
|
|
|
URLButton::mousePressEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::mouseMoveEvent(TQMouseEvent * event)
|
|
|
|
{
|
|
|
|
if (event->state() & Qt::LeftButton) {
|
|
|
|
int distance = (event->pos() - dragPos).manhattanLength();
|
|
|
|
if (distance > TQApplication::startDragDistance()*2)//don't start on small move (for submenu usability)
|
|
|
|
startDrag();
|
|
|
|
}
|
|
|
|
URLButton::mouseMoveEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void URLNavigatorButton::startDrag()
|
|
|
|
{
|
|
|
|
KURL url = urlNavigator()->url(m_index);
|
|
|
|
KURL::List lst;
|
|
|
|
lst.append( url );
|
|
|
|
KURLDrag *drag = new KURLDrag(lst, this);
|
|
|
|
drag->drag();
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "urlnavigatorbutton.moc"
|