/*************************************************************************** * Copyright (C) 2006 by Peter Penz (peter.penz@gmx.at) * * Copyright (C) 2006 by Aaron J. Seigo () * * * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #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 = TDEGlobalSettings::highlightColor(); foregroundColor = TDEGlobalSettings::highlightedTextColor(); } else { backgroundColor = colorGroup().background(); foregroundColor = TDEGlobalSettings::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(colorGroup().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 = TDEIO::listDir(url, false, false); m_subdirs.clear(); // just to be ++safe connect(m_listJob, TQT_SIGNAL(entries(TDEIO::Job*, const TDEIO::UDSEntryList &)), this, TQT_SLOT(entriesList(TDEIO::Job*, const TDEIO::UDSEntryList&))); connect(m_listJob, TQT_SIGNAL(result(TDEIO::Job*)), this, TQT_SLOT(listJobFinished(TDEIO::Job*))); } void URLNavigatorButton::entriesList(TDEIO::Job* job, const TDEIO::UDSEntryList& entries) { if (job != m_listJob) { return; } TDEIO::UDSEntryList::const_iterator it = entries.constBegin(); TDEIO::UDSEntryList::const_iterator itEnd = entries.constEnd(); while (it != itEnd) { TQString name; bool isDir = false; TDEIO::UDSEntry entry = *it; TDEIO::UDSEntry::const_iterator atomIt = entry.constBegin(); TDEIO::UDSEntry::const_iterator atomEndIt = entry.constEnd(); while (atomIt != atomEndIt) { switch ((*atomIt).m_uds) { case TDEIO::UDS_NAME: name = (*atomIt).m_str; break; case TDEIO::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(TDEIO::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(geometry().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"