mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 18:32:49 +00:00
692 lines
20 KiB
C++
692 lines
20 KiB
C++
/*****************************************************************************
|
|
* Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at> *
|
|
* Copyright (C) 2006 by Aaron J. Seigo <aseigo@kde.org> *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Library General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library 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 *
|
|
* Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public License *
|
|
* along with this library; see the file COPYING.LIB. If not, write to *
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
|
|
* Boston, MA 02110-1301, USA. *
|
|
*****************************************************************************/
|
|
|
|
#include "kurlnavigatorbutton_p.h"
|
|
|
|
#include "kurlnavigator.h"
|
|
#include "kurlnavigatormenu_p.h"
|
|
|
|
#include <kio/job.h>
|
|
#include <kio/jobclasses.h>
|
|
#include <kglobalsettings.h>
|
|
#include <klocale.h>
|
|
#include <kstringhandler.h>
|
|
|
|
#include <QtCore/QTimer>
|
|
#include <QtGui/QPainter>
|
|
#include <QtGui/qevent.h>
|
|
#include <QtGui/QStyleOption>
|
|
#include <QtGui/QPen>
|
|
|
|
namespace KDEPrivate
|
|
{
|
|
|
|
QPointer<KUrlNavigatorMenu> KUrlNavigatorButton::m_subDirsMenu;
|
|
|
|
KUrlNavigatorButton::KUrlNavigatorButton(const KUrl& url, QWidget* parent) :
|
|
KUrlNavigatorButtonBase(parent),
|
|
m_hoverArrow(false),
|
|
m_pendingTextChange(false),
|
|
m_replaceButton(false),
|
|
m_showMnemonic(false),
|
|
m_wheelSteps(0),
|
|
m_url(url),
|
|
m_subDir(),
|
|
m_openSubDirsTimer(0),
|
|
m_subDirsJob(0)
|
|
{
|
|
setAcceptDrops(true);
|
|
setUrl(url);
|
|
setMouseTracking(true);
|
|
|
|
m_openSubDirsTimer = new QTimer(this);
|
|
m_openSubDirsTimer->setSingleShot(true);
|
|
m_openSubDirsTimer->setInterval(300);
|
|
connect(m_openSubDirsTimer, SIGNAL(timeout()), this, SLOT(startSubDirsJob()));
|
|
|
|
connect(this, SIGNAL(pressed()), this, SLOT(requestSubDirs()));
|
|
}
|
|
|
|
KUrlNavigatorButton::~KUrlNavigatorButton()
|
|
{
|
|
}
|
|
|
|
void KUrlNavigatorButton::setUrl(const KUrl& url)
|
|
{
|
|
m_url = url;
|
|
|
|
bool startTextResolving = !m_url.isLocalFile();
|
|
if (startTextResolving) {
|
|
// Doing a text-resolving with KIO::stat() for all non-local
|
|
// URLs leads to problems for protocols where a limit is given for
|
|
// the number of parallel connections. A black-list
|
|
// is given where KIO::stat() should not be used:
|
|
static QSet<QString> protocols;
|
|
if (protocols.isEmpty()) {
|
|
protocols << "ftp" << "sftp";
|
|
}
|
|
startTextResolving = !protocols.contains(m_url.protocol());
|
|
}
|
|
|
|
if (startTextResolving) {
|
|
m_pendingTextChange = true;
|
|
KIO::StatJob* job = KIO::stat(m_url, KIO::HideProgressInfo);
|
|
connect(job, SIGNAL(result(KJob*)),
|
|
this, SLOT(statFinished(KJob*)));
|
|
emit startedTextResolving();
|
|
} else {
|
|
setText(m_url.fileName().replace('&', "&&"));
|
|
}
|
|
}
|
|
|
|
KUrl KUrlNavigatorButton::url() const
|
|
{
|
|
return m_url;
|
|
}
|
|
|
|
void KUrlNavigatorButton::setText(const QString& text)
|
|
{
|
|
QString adjustedText = text;
|
|
if (adjustedText.isEmpty()) {
|
|
adjustedText = m_url.protocol();
|
|
}
|
|
// Assure that the button always consists of one line
|
|
adjustedText.remove(QLatin1Char('\n'));
|
|
|
|
KUrlNavigatorButtonBase::setText(adjustedText);
|
|
updateMinimumWidth();
|
|
|
|
// Assure that statFinished() does not overwrite a text that has been
|
|
// set by a client of the URL navigator button
|
|
m_pendingTextChange = false;
|
|
}
|
|
|
|
void KUrlNavigatorButton::setActiveSubDirectory(const QString& subDir)
|
|
{
|
|
m_subDir = subDir;
|
|
|
|
// We use a different (bold) font on active, so the size hint changes
|
|
updateGeometry();
|
|
update();
|
|
}
|
|
|
|
QString KUrlNavigatorButton::activeSubDirectory() const
|
|
{
|
|
return m_subDir;
|
|
}
|
|
|
|
QSize KUrlNavigatorButton::sizeHint() const
|
|
{
|
|
QFont adjustedFont(font());
|
|
adjustedFont.setBold(m_subDir.isEmpty());
|
|
// the minimum size is textWidth + arrowWidth() + 2 * BorderWidth; for the
|
|
// preferred size we add the BorderWidth 2 times again for having an uncluttered look
|
|
const int width = QFontMetrics(adjustedFont).width(plainText()) + arrowWidth() + 4 * BorderWidth;
|
|
return QSize(width, KUrlNavigatorButtonBase::sizeHint().height());
|
|
}
|
|
|
|
void KUrlNavigatorButton::setShowMnemonic(bool show)
|
|
{
|
|
if (m_showMnemonic != show) {
|
|
m_showMnemonic = show;
|
|
update();
|
|
}
|
|
}
|
|
|
|
bool KUrlNavigatorButton::showMnemonic() const
|
|
{
|
|
return m_showMnemonic;
|
|
}
|
|
|
|
void KUrlNavigatorButton::paintEvent(QPaintEvent* event)
|
|
{
|
|
Q_UNUSED(event);
|
|
|
|
QPainter painter(this);
|
|
|
|
QFont adjustedFont(font());
|
|
adjustedFont.setBold(m_subDir.isEmpty());
|
|
painter.setFont(adjustedFont);
|
|
|
|
int buttonWidth = width();
|
|
int preferredWidth = sizeHint().width();
|
|
if (preferredWidth < minimumWidth()) {
|
|
preferredWidth = minimumWidth();
|
|
}
|
|
if (buttonWidth > preferredWidth) {
|
|
buttonWidth = preferredWidth;
|
|
}
|
|
const int buttonHeight = height();
|
|
|
|
const QColor fgColor = foregroundColor();
|
|
drawHoverBackground(&painter);
|
|
|
|
int textLeft = 0;
|
|
int textWidth = buttonWidth;
|
|
|
|
const bool leftToRight = (layoutDirection() == Qt::LeftToRight);
|
|
|
|
if (!m_subDir.isEmpty()) {
|
|
// draw arrow
|
|
const int arrowSize = arrowWidth();
|
|
const int arrowX = leftToRight ? (buttonWidth - arrowSize) - BorderWidth : BorderWidth;
|
|
const int arrowY = (buttonHeight - arrowSize) / 2;
|
|
|
|
QStyleOption option;
|
|
option.initFrom(this);
|
|
option.rect = QRect(arrowX, arrowY, arrowSize, arrowSize);
|
|
option.palette = palette();
|
|
option.palette.setColor(QPalette::Text, fgColor);
|
|
option.palette.setColor(QPalette::WindowText, fgColor);
|
|
option.palette.setColor(QPalette::ButtonText, fgColor);
|
|
|
|
if (m_hoverArrow) {
|
|
// highlight the background of the arrow to indicate that the directories
|
|
// popup can be opened by a mouse click
|
|
QColor hoverColor = palette().color(QPalette::HighlightedText);
|
|
hoverColor.setAlpha(96);
|
|
painter.setPen(Qt::NoPen);
|
|
painter.setBrush(hoverColor);
|
|
|
|
int hoverX = arrowX;
|
|
if (!leftToRight) {
|
|
hoverX -= BorderWidth;
|
|
}
|
|
painter.drawRect(QRect(hoverX, 0, arrowSize + BorderWidth, buttonHeight));
|
|
}
|
|
|
|
if (leftToRight) {
|
|
style()->drawPrimitive(QStyle::PE_IndicatorArrowRight, &option, &painter, this);
|
|
} else {
|
|
style()->drawPrimitive(QStyle::PE_IndicatorArrowLeft, &option, &painter, this);
|
|
textLeft += arrowSize + 2 * BorderWidth;
|
|
}
|
|
|
|
textWidth -= arrowSize + 2 * BorderWidth;
|
|
}
|
|
|
|
painter.setPen(fgColor);
|
|
const bool clipped = isTextClipped();
|
|
const QRect textRect(textLeft, 0, textWidth, buttonHeight);
|
|
if (clipped) {
|
|
QColor bgColor = fgColor;
|
|
bgColor.setAlpha(0);
|
|
QLinearGradient gradient(textRect.topLeft(), textRect.topRight());
|
|
if (leftToRight) {
|
|
gradient.setColorAt(0.8, fgColor);
|
|
gradient.setColorAt(1.0, bgColor);
|
|
} else {
|
|
gradient.setColorAt(0.0, bgColor);
|
|
gradient.setColorAt(0.2, fgColor);
|
|
}
|
|
|
|
QPen pen;
|
|
pen.setBrush(QBrush(gradient));
|
|
painter.setPen(pen);
|
|
}
|
|
|
|
int textFlags = clipped ? Qt::AlignVCenter : Qt::AlignCenter;
|
|
if (m_showMnemonic) {
|
|
textFlags |= Qt::TextShowMnemonic;
|
|
painter.drawText(textRect, textFlags, text());
|
|
} else {
|
|
painter.drawText(textRect, textFlags, plainText());
|
|
}
|
|
}
|
|
|
|
void KUrlNavigatorButton::enterEvent(QEvent* event)
|
|
{
|
|
KUrlNavigatorButtonBase::enterEvent(event);
|
|
|
|
// if the text is clipped due to a small window width, the text should
|
|
// be shown as tooltip
|
|
if (isTextClipped()) {
|
|
setToolTip(plainText());
|
|
}
|
|
}
|
|
|
|
void KUrlNavigatorButton::leaveEvent(QEvent* event)
|
|
{
|
|
KUrlNavigatorButtonBase::leaveEvent(event);
|
|
setToolTip(QString());
|
|
|
|
if (m_hoverArrow) {
|
|
m_hoverArrow = false;
|
|
update();
|
|
}
|
|
}
|
|
|
|
void KUrlNavigatorButton::keyPressEvent(QKeyEvent* event)
|
|
{
|
|
switch (event->key()) {
|
|
case Qt::Key_Enter:
|
|
case Qt::Key_Return:
|
|
emit clicked(m_url, Qt::LeftButton);
|
|
break;
|
|
case Qt::Key_Down:
|
|
case Qt::Key_Space:
|
|
startSubDirsJob();
|
|
break;
|
|
default:
|
|
KUrlNavigatorButtonBase::keyPressEvent(event);
|
|
}
|
|
}
|
|
|
|
void KUrlNavigatorButton::dropEvent(QDropEvent* event)
|
|
{
|
|
const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
|
|
if (!urls.isEmpty()) {
|
|
setDisplayHintEnabled(DraggedHint, true);
|
|
|
|
emit urlsDropped(m_url, event);
|
|
|
|
setDisplayHintEnabled(DraggedHint, false);
|
|
update();
|
|
}
|
|
}
|
|
|
|
void KUrlNavigatorButton::dragEnterEvent(QDragEnterEvent* event)
|
|
{
|
|
if (event->mimeData()->hasUrls()) {
|
|
setDisplayHintEnabled(DraggedHint, true);
|
|
event->acceptProposedAction();
|
|
|
|
update();
|
|
}
|
|
}
|
|
|
|
void KUrlNavigatorButton::dragMoveEvent(QDragMoveEvent* event)
|
|
{
|
|
QRect rect = event->answerRect();
|
|
if (isAboveArrow(rect.center().x())) {
|
|
m_hoverArrow = true;
|
|
update();
|
|
|
|
if (m_subDirsMenu == 0) {
|
|
requestSubDirs();
|
|
} else if (m_subDirsMenu->parent() != this) {
|
|
m_subDirsMenu->close();
|
|
m_subDirsMenu->deleteLater();
|
|
m_subDirsMenu = 0;
|
|
|
|
requestSubDirs();
|
|
}
|
|
} else {
|
|
if (m_openSubDirsTimer->isActive()) {
|
|
cancelSubDirsRequest();
|
|
}
|
|
delete m_subDirsMenu;
|
|
m_subDirsMenu = 0;
|
|
m_hoverArrow = false;
|
|
update();
|
|
}
|
|
}
|
|
|
|
void KUrlNavigatorButton::dragLeaveEvent(QDragLeaveEvent* event)
|
|
{
|
|
KUrlNavigatorButtonBase::dragLeaveEvent(event);
|
|
|
|
m_hoverArrow = false;
|
|
setDisplayHintEnabled(DraggedHint, false);
|
|
update();
|
|
}
|
|
|
|
void KUrlNavigatorButton::mousePressEvent(QMouseEvent* event)
|
|
{
|
|
if (isAboveArrow(event->x()) && (event->button() == Qt::LeftButton)) {
|
|
// the mouse is pressed above the [>] button
|
|
startSubDirsJob();
|
|
}
|
|
KUrlNavigatorButtonBase::mousePressEvent(event);
|
|
}
|
|
|
|
void KUrlNavigatorButton::mouseReleaseEvent(QMouseEvent* event)
|
|
{
|
|
if (!isAboveArrow(event->x()) || (event->button() != Qt::LeftButton)) {
|
|
// the mouse has been released above the text area and not
|
|
// above the [>] button
|
|
emit clicked(m_url, event->button());
|
|
cancelSubDirsRequest();
|
|
}
|
|
KUrlNavigatorButtonBase::mouseReleaseEvent(event);
|
|
}
|
|
|
|
void KUrlNavigatorButton::mouseMoveEvent(QMouseEvent* event)
|
|
{
|
|
KUrlNavigatorButtonBase::mouseMoveEvent(event);
|
|
|
|
const bool hoverArrow = isAboveArrow(event->x());
|
|
if (hoverArrow != m_hoverArrow) {
|
|
m_hoverArrow = hoverArrow;
|
|
update();
|
|
}
|
|
}
|
|
|
|
void KUrlNavigatorButton::wheelEvent(QWheelEvent* event)
|
|
{
|
|
if (event->orientation() == Qt::Vertical) {
|
|
m_wheelSteps = event->delta() / 120;
|
|
m_replaceButton = true;
|
|
startSubDirsJob();
|
|
}
|
|
|
|
KUrlNavigatorButtonBase::wheelEvent(event);
|
|
}
|
|
|
|
void KUrlNavigatorButton::requestSubDirs()
|
|
{
|
|
if (!m_openSubDirsTimer->isActive() && (m_subDirsJob == 0)) {
|
|
m_openSubDirsTimer->start();
|
|
}
|
|
}
|
|
|
|
void KUrlNavigatorButton::startSubDirsJob()
|
|
{
|
|
if (m_subDirsJob != 0) {
|
|
return;
|
|
}
|
|
|
|
const KUrl url = m_replaceButton ? m_url.upUrl() : m_url;
|
|
m_subDirsJob = KIO::listDir(url, KIO::HideProgressInfo, false /*no hidden files*/);
|
|
m_subDirs.clear(); // just to be ++safe
|
|
|
|
connect(m_subDirsJob, SIGNAL(entries(KIO::Job*,KIO::UDSEntryList)),
|
|
this, SLOT(addEntriesToSubDirs(KIO::Job*,KIO::UDSEntryList)));
|
|
|
|
if (m_replaceButton) {
|
|
connect(m_subDirsJob, SIGNAL(result(KJob*)), this, SLOT(replaceButton(KJob*)));
|
|
} else {
|
|
connect(m_subDirsJob, SIGNAL(result(KJob*)), this, SLOT(openSubDirsMenu(KJob*)));
|
|
}
|
|
}
|
|
|
|
void KUrlNavigatorButton::addEntriesToSubDirs(KIO::Job* job, const KIO::UDSEntryList& entries)
|
|
{
|
|
Q_ASSERT(job == m_subDirsJob);
|
|
Q_UNUSED(job);
|
|
|
|
foreach (const KIO::UDSEntry& entry, entries) {
|
|
if (entry.isDir()) {
|
|
const QString name = entry.stringValue(KIO::UDSEntry::UDS_NAME);
|
|
QString displayName = entry.stringValue(KIO::UDSEntry::UDS_DISPLAY_NAME);
|
|
if (displayName.isEmpty()) {
|
|
displayName = name;
|
|
}
|
|
if ((name != QLatin1String(".")) && (name != QLatin1String(".."))) {
|
|
m_subDirs.append(qMakePair(name, displayName));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void KUrlNavigatorButton::urlsDropped(QAction* action, QDropEvent* event)
|
|
{
|
|
const int result = action->data().toInt();
|
|
KUrl url = m_url;
|
|
url.addPath(m_subDirs.at(result).first);
|
|
urlsDropped(url, event);
|
|
}
|
|
|
|
void KUrlNavigatorButton::slotMenuActionClicked(QAction* action)
|
|
{
|
|
const int result = action->data().toInt();
|
|
KUrl url = m_url;
|
|
url.addPath(m_subDirs.at(result).first);
|
|
emit clicked(url, Qt::MiddleButton);
|
|
}
|
|
|
|
void KUrlNavigatorButton::statFinished(KJob* job)
|
|
{
|
|
if (m_pendingTextChange) {
|
|
m_pendingTextChange = false;
|
|
|
|
const KIO::UDSEntry entry = static_cast<KIO::StatJob*>(job)->statResult();
|
|
QString name = entry.stringValue(KIO::UDSEntry::UDS_DISPLAY_NAME);
|
|
if (name.isEmpty()) {
|
|
name = m_url.fileName();
|
|
}
|
|
setText(name);
|
|
|
|
emit finishedTextResolving();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function for openSubDirsMenu
|
|
*/
|
|
static bool naturalLessThan(const QPair<QString, QString>& s1, const QPair<QString, QString>& s2)
|
|
{
|
|
return KStringHandler::naturalCompare(s1.first, s2.first, Qt::CaseInsensitive) < 0;
|
|
}
|
|
|
|
void KUrlNavigatorButton::openSubDirsMenu(KJob* job)
|
|
{
|
|
Q_ASSERT(job == m_subDirsJob);
|
|
m_subDirsJob = 0;
|
|
|
|
if (job->error() || m_subDirs.isEmpty()) {
|
|
// clear listing
|
|
return;
|
|
}
|
|
|
|
qSort(m_subDirs.begin(), m_subDirs.end(), naturalLessThan);
|
|
setDisplayHintEnabled(PopupActiveHint, true);
|
|
update(); // ensure the button is drawn highlighted
|
|
|
|
if (m_subDirsMenu != 0) {
|
|
m_subDirsMenu->close();
|
|
m_subDirsMenu->deleteLater();
|
|
m_subDirsMenu = 0;
|
|
}
|
|
|
|
m_subDirsMenu = new KUrlNavigatorMenu(this);
|
|
initMenu(m_subDirsMenu, 0);
|
|
|
|
const bool leftToRight = (layoutDirection() == Qt::LeftToRight);
|
|
const int popupX = leftToRight ? width() - arrowWidth() - BorderWidth : 0;
|
|
const QPoint popupPos = parentWidget()->mapToGlobal(geometry().bottomLeft() + QPoint(popupX, 0));
|
|
|
|
QPointer<QObject> guard(this);
|
|
|
|
const QAction* action = m_subDirsMenu->exec(popupPos);
|
|
|
|
// If 'this' has been deleted in the menu's nested event loop, we have to return
|
|
// immediatedely because any access to a member variable might cause a crash.
|
|
if (!guard) {
|
|
return;
|
|
}
|
|
|
|
if (action != 0) {
|
|
const int result = action->data().toInt();
|
|
KUrl url = m_url;
|
|
url.addPath(m_subDirs[result].first);
|
|
emit clicked(url, Qt::LeftButton);
|
|
}
|
|
|
|
m_subDirs.clear();
|
|
delete m_subDirsMenu;
|
|
m_subDirsMenu = 0;
|
|
|
|
setDisplayHintEnabled(PopupActiveHint, false);
|
|
}
|
|
|
|
void KUrlNavigatorButton::replaceButton(KJob* job)
|
|
{
|
|
Q_ASSERT(job == m_subDirsJob);
|
|
m_subDirsJob = 0;
|
|
m_replaceButton = false;
|
|
|
|
if (job->error() || m_subDirs.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
qSort(m_subDirs.begin(), m_subDirs.end(), naturalLessThan);
|
|
|
|
// Get index of the directory that is shown currently in the button
|
|
const QString currentDir = m_url.fileName();
|
|
int currentIndex = 0;
|
|
const int subDirsCount = m_subDirs.count();
|
|
while (currentIndex < subDirsCount) {
|
|
if (m_subDirs[currentIndex].first == currentDir) {
|
|
break;
|
|
}
|
|
++currentIndex;
|
|
}
|
|
|
|
// Adjust the index by respecting the wheel steps and
|
|
// trigger a replacing of the button content
|
|
int targetIndex = currentIndex - m_wheelSteps;
|
|
if (targetIndex < 0) {
|
|
targetIndex = 0;
|
|
} else if (targetIndex >= subDirsCount) {
|
|
targetIndex = subDirsCount - 1;
|
|
}
|
|
|
|
KUrl url = m_url.upUrl();
|
|
url.addPath(m_subDirs[targetIndex].first);
|
|
|
|
emit clicked(url, Qt::LeftButton);
|
|
|
|
m_subDirs.clear();
|
|
}
|
|
|
|
void KUrlNavigatorButton::cancelSubDirsRequest()
|
|
{
|
|
m_openSubDirsTimer->stop();
|
|
if (m_subDirsJob != 0) {
|
|
m_subDirsJob->kill();
|
|
m_subDirsJob = 0;
|
|
}
|
|
}
|
|
|
|
QString KUrlNavigatorButton::plainText() const
|
|
{
|
|
// Replace all "&&" by '&' and remove all single
|
|
// '&' characters
|
|
const QString source = text();
|
|
const int sourceLength = source.length();
|
|
|
|
QString dest;
|
|
dest.reserve(sourceLength);
|
|
|
|
int sourceIndex = 0;
|
|
int destIndex = 0;
|
|
while (sourceIndex < sourceLength) {
|
|
if (source.at(sourceIndex) == QLatin1Char('&')) {
|
|
++sourceIndex;
|
|
if (sourceIndex >= sourceLength) {
|
|
break;
|
|
}
|
|
}
|
|
dest[destIndex] = source.at(sourceIndex);
|
|
++sourceIndex;
|
|
++destIndex;
|
|
}
|
|
|
|
return dest;
|
|
}
|
|
|
|
int KUrlNavigatorButton::arrowWidth() const
|
|
{
|
|
// if there isn't arrow then return 0
|
|
int width = 0;
|
|
if (!m_subDir.isEmpty()) {
|
|
width = height() / 2;
|
|
if (width < 4) {
|
|
width = 4;
|
|
}
|
|
}
|
|
|
|
return width;
|
|
}
|
|
|
|
bool KUrlNavigatorButton::isAboveArrow(int x) const
|
|
{
|
|
const bool leftToRight = (layoutDirection() == Qt::LeftToRight);
|
|
return leftToRight ? (x >= width() - arrowWidth()) : (x < arrowWidth());
|
|
}
|
|
|
|
bool KUrlNavigatorButton::isTextClipped() const
|
|
{
|
|
int availableWidth = width() - 2 * BorderWidth;
|
|
if (!m_subDir.isEmpty()) {
|
|
availableWidth -= arrowWidth() - BorderWidth;
|
|
}
|
|
|
|
QFont adjustedFont(font());
|
|
adjustedFont.setBold(m_subDir.isEmpty());
|
|
return QFontMetrics(adjustedFont).width(plainText()) >= availableWidth;
|
|
}
|
|
|
|
void KUrlNavigatorButton::updateMinimumWidth()
|
|
{
|
|
const int oldMinWidth = minimumWidth();
|
|
|
|
int minWidth = sizeHint().width();
|
|
if (minWidth < 40) {
|
|
minWidth = 40;
|
|
}
|
|
else if (minWidth > 150) {
|
|
// don't let an overlong path name waste all the URL navigator space
|
|
minWidth = 150;
|
|
}
|
|
if (oldMinWidth != minWidth) {
|
|
setMinimumWidth(minWidth);
|
|
}
|
|
}
|
|
|
|
void KUrlNavigatorButton::initMenu(KUrlNavigatorMenu* menu, int startIndex)
|
|
{
|
|
connect(menu, SIGNAL(middleMouseButtonClicked(QAction*)),
|
|
this, SLOT(slotMenuActionClicked(QAction*)));
|
|
connect(menu, SIGNAL(urlsDropped(QAction*,QDropEvent*)),
|
|
this, SLOT(urlsDropped(QAction*,QDropEvent*)));
|
|
|
|
menu->setLayoutDirection(Qt::LeftToRight);
|
|
|
|
const int maxIndex = startIndex + 30; // Don't show more than 30 items in a menu
|
|
const int lastIndex = qMin(m_subDirs.count() - 1, maxIndex);
|
|
for (int i = startIndex; i <= lastIndex; ++i) {
|
|
const QString subDirName = m_subDirs[i].first;
|
|
const QString subDirDisplayName = m_subDirs[i].second;
|
|
QString text = KStringHandler::csqueeze(subDirDisplayName, 60);
|
|
text.replace(QLatin1Char('&'), QLatin1String("&&"));
|
|
QAction* action = new QAction(text, this);
|
|
if (m_subDir == subDirName) {
|
|
QFont font(action->font());
|
|
font.setBold(true);
|
|
action->setFont(font);
|
|
}
|
|
action->setData(i);
|
|
menu->addAction(action);
|
|
}
|
|
if (m_subDirs.count() > maxIndex) {
|
|
// If too much items are shown, move them into a sub menu
|
|
menu->addSeparator();
|
|
KUrlNavigatorMenu* subDirsMenu = new KUrlNavigatorMenu(menu);
|
|
subDirsMenu->setTitle(i18nc("@action:inmenu", "More"));
|
|
initMenu(subDirsMenu, maxIndex);
|
|
menu->addMenu(subDirsMenu);
|
|
}
|
|
}
|
|
|
|
} // namespace KDEPrivate
|
|
|
|
#include "moc_kurlnavigatorbutton_p.cpp"
|