kdelibs/kio/kfile/kurlrequester.cpp

544 lines
14 KiB
C++
Raw Normal View History

2014-11-13 01:04:59 +02:00
/* This file is part of the KDE libraries
Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2, as published by the Free Software Foundation.
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 "kurlrequester.h"
#include <kcombobox.h>
#include <kfiledialog.h>
#include <klineedit.h>
#include <klocale.h>
#include <kurlcompletion.h>
#include <kprotocolmanager.h>
#include <khbox.h>
#include <kstandardshortcut.h>
#include <kdebug.h>
#include <QEvent>
#include <QDrag>
#include <QMimeData>
#include <QAction>
#include <QApplication>
#include <QDir>
class KUrlDragPushButton : public KPushButton
{
public:
KUrlDragPushButton(QWidget *parent)
: KPushButton(parent)
2014-11-13 01:04:59 +02:00
{
setDragEnabled(true);
2014-11-13 01:04:59 +02:00
}
void setURL(const KUrl &url)
2014-11-13 01:04:59 +02:00
{
m_urls.clear();
m_urls.append(url);
2014-11-13 01:04:59 +02:00
}
protected:
virtual QDrag* dragObject()
2014-11-13 01:04:59 +02:00
{
if (m_urls.isEmpty()) {
return nullptr;
}
2014-11-13 01:04:59 +02:00
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData();
2014-11-13 01:04:59 +02:00
m_urls.populateMimeData(mimeData);
drag->setMimeData(mimeData);
return drag;
}
private:
KUrl::List m_urls;
};
class KUrlRequester::KUrlRequesterPrivate
{
public:
KUrlRequesterPrivate(KUrlRequester *parent)
: m_startDirCustomized(false),
m_parent(parent),
edit(nullptr),
combo(nullptr),
fileDialogMode(KFile::File | KFile::ExistingOnly | KFile::LocalOnly),
myButton(nullptr),
myFileDialog(nullptr),
myCompletion(nullptr),
fileDialogModality(Qt::ApplicationModal)
2014-11-13 01:04:59 +02:00
{
qRegisterMetaType<KUrl>("KUrl");
2014-11-13 01:04:59 +02:00
}
~KUrlRequesterPrivate()
{
delete myCompletion;
delete myFileDialog;
}
void init();
void setText(const QString &text)
{
if (combo) {
if (combo->isEditable()) {
combo->setEditText(text);
} else {
int i = combo->findText(text);
if (i == -1) {
combo->addItem(text);
combo->setCurrentIndex(combo->count() - 1);
} else {
combo->setCurrentIndex(i);
2014-11-13 01:04:59 +02:00
}
}
} else {
edit->setText(text);
2014-11-13 01:04:59 +02:00
}
}
void connectSignals(QObject *receiver)
2014-11-13 01:04:59 +02:00
{
QObject *sender;
if (combo) {
2014-11-13 01:04:59 +02:00
sender = combo;
} else {
2014-11-13 01:04:59 +02:00
sender = edit;
}
2014-11-13 01:04:59 +02:00
if (combo) {
connect(
sender, SIGNAL(editTextChanged(QString)),
receiver, SIGNAL(textChanged(QString)));
} else {
connect(
sender, SIGNAL(textChanged(QString)),
receiver, SIGNAL(textChanged(QString))
);
}
2014-11-13 01:04:59 +02:00
connect( sender, SIGNAL(returnPressed()),
receiver, SIGNAL(returnPressed()));
connect( sender, SIGNAL(returnPressed(QString)),
receiver, SIGNAL(returnPressed(QString)));
}
void setCompletionObject( KCompletion *comp )
{
if ( combo )
combo->setCompletionObject( comp );
else
edit->setCompletionObject( comp );
}
void updateCompletionStartDir(const KUrl &newStartDir)
2014-11-13 01:04:59 +02:00
{
if (newStartDir.isLocalFile()) {
2014-11-13 01:04:59 +02:00
myCompletion->setDir(newStartDir.toLocalFile());
}
2014-11-13 01:04:59 +02:00
}
QString text() const
{
2014-11-13 01:04:59 +02:00
return combo ? combo->currentText() : edit->text();
}
/**
* replaces ~user or $FOO, if necessary
* if text() is a relative path, make it absolute using startDir()
*/
KUrl url() const
{
2014-11-13 01:04:59 +02:00
const QString txt = text();
KUrlCompletion *comp;
if (combo) {
2014-11-13 01:04:59 +02:00
comp = qobject_cast<KUrlCompletion*>(combo->completionObject());
} else {
2014-11-13 01:04:59 +02:00
comp = qobject_cast<KUrlCompletion*>(edit->completionObject());
}
2014-11-13 01:04:59 +02:00
KUrl enteredPath;
KUrl baseDir(m_startDir);
if (comp) {
enteredPath = KUrl(comp->replacedPath(txt));
} else {
enteredPath = KUrl(txt);
}
2014-11-13 01:04:59 +02:00
if (enteredPath.isRelative() && !txt.isEmpty()) {
2014-11-13 01:04:59 +02:00
baseDir.addPath(enteredPath.path());
return baseDir;
}
return enteredPath;
2014-11-13 01:04:59 +02:00
}
// slots
void _k_slotUpdateUrl();
void _k_slotOpenDialog();
void _k_slotFileDialogFinished();
KUrl m_startDir;
bool m_startDirCustomized;
KUrlRequester* m_parent;
KLineEdit* edit;
KComboBox* combo;
2014-11-13 01:04:59 +02:00
KFile::Modes fileDialogMode;
QString fileDialogFilter;
KEditListWidget::CustomEditor editor;
KUrlDragPushButton *myButton;
KFileDialog *myFileDialog;
KUrlCompletion *myCompletion;
Qt::WindowModality fileDialogModality;
};
KUrlRequester::KUrlRequester(QWidget *editWidget, QWidget *parent)
: KHBox(parent),
d(new KUrlRequesterPrivate(this))
2014-11-13 01:04:59 +02:00
{
// must have this as parent
editWidget->setParent(this);
d->combo = qobject_cast<KComboBox*>(editWidget);
d->edit = qobject_cast<KLineEdit*>(editWidget);
if (d->edit) {
d->edit->setClearButtonShown(true);
2014-11-13 01:04:59 +02:00
}
d->init();
}
KUrlRequester::KUrlRequester(QWidget *parent)
: KHBox(parent),
d(new KUrlRequesterPrivate(this))
2014-11-13 01:04:59 +02:00
{
d->init();
}
KUrlRequester::KUrlRequester(const KUrl &url, QWidget *parent)
: KHBox(parent),
d(new KUrlRequesterPrivate(this))
2014-11-13 01:04:59 +02:00
{
d->init();
setUrl(url);
2014-11-13 01:04:59 +02:00
}
KUrlRequester::~KUrlRequester()
{
delete d;
}
void KUrlRequester::KUrlRequesterPrivate::init()
{
m_parent->setMargin(0);
m_parent->setSpacing(-1); // use default spacing
if (!combo && !edit) {
edit = new KLineEdit(m_parent);
edit->setClearButtonShown(true);
2014-11-13 01:04:59 +02:00
}
QWidget *widget = combo ? (QWidget*) combo : (QWidget*) edit;
myButton = new KUrlDragPushButton(m_parent);
myButton->setIcon(KIcon("document-open"));
int buttonSize = myButton->sizeHint().expandedTo(widget->sizeHint()).height();
myButton->setFixedSize(buttonSize, buttonSize);
myButton->setToolTip(i18n("Open file dialog"));
m_parent->connect(myButton, SIGNAL(pressed()), SLOT(_k_slotUpdateUrl()));
widget->installEventFilter(m_parent);
2014-11-13 01:04:59 +02:00
m_parent->setFocusProxy( widget );
m_parent->setFocusPolicy(Qt::StrongFocus);
connectSignals( m_parent );
m_parent->connect(myButton, SIGNAL(clicked()), m_parent, SLOT(_k_slotOpenDialog()));
m_startDir = KUrl::fromPath(QDir::currentPath());
myCompletion = new KUrlCompletion();
updateCompletionStartDir(m_startDir);
setCompletionObject( myCompletion );
QAction* openAction = new QAction(m_parent);
openAction->setShortcut(KStandardShortcut::Open);
m_parent->connect(openAction, SIGNAL(triggered(bool)), SLOT(_k_slotOpenDialog()));
}
void KUrlRequester::setUrl( const KUrl& url )
{
d->setText( url.pathOrUrl() );
}
void KUrlRequester::setText(const QString &text)
2014-11-13 01:04:59 +02:00
{
d->setText(text);
}
void KUrlRequester::setStartDir(const KUrl &startDir)
2014-11-13 01:04:59 +02:00
{
d->m_startDir = startDir;
d->m_startDirCustomized = true;
d->updateCompletionStartDir(startDir);
}
void KUrlRequester::changeEvent(QEvent *e)
{
if (e->type()==QEvent::WindowTitleChange) {
if (d->myFileDialog) {
d->myFileDialog->setCaption(windowTitle());
}
}
KHBox::changeEvent(e);
2014-11-13 01:04:59 +02:00
}
KUrl KUrlRequester::url() const
{
return d->url();
}
KUrl KUrlRequester::startDir() const
{
return d->m_startDir;
}
QString KUrlRequester::text() const
{
return d->text();
}
void KUrlRequester::KUrlRequesterPrivate::_k_slotOpenDialog()
{
if (myFileDialog) {
if (myFileDialog->isVisible()) {
2014-11-13 01:04:59 +02:00
//The file dialog is already being shown, raise it and exit
myFileDialog->raise();
myFileDialog->activateWindow();
return;
}
}
2014-11-13 01:04:59 +02:00
if ( ((fileDialogMode & KFile::Directory) && !(fileDialogMode & KFile::File)) ||
/* catch possible fileDialog()->setMode( KFile::Directory ) changes */
(myFileDialog && (myFileDialog->mode() & KFile::Directory) &&
(myFileDialog->mode() & (KFile::File | KFile::Files)) == 0)) {
const KUrl openUrl = (!m_parent->url().isEmpty() && !m_parent->url().isRelative()) ? m_parent->url() : m_startDir;
2014-11-13 01:04:59 +02:00
KUrl newurl;
if (fileDialogMode & KFile::LocalOnly) {
newurl = KFileDialog::getExistingDirectory(openUrl, m_parent);
} else {
newurl = KFileDialog::getExistingDirectoryUrl(openUrl, m_parent);
}
2014-11-13 01:04:59 +02:00
if (newurl.isValid()) {
m_parent->setUrl(newurl);
emit m_parent->urlSelected(url());
2014-11-13 01:04:59 +02:00
}
} else {
emit m_parent->openFileDialog(m_parent);
2014-11-13 01:04:59 +02:00
//Creates the fileDialog if it doesn't exist yet
KFileDialog* dlg = m_parent->fileDialog();
2014-11-13 01:04:59 +02:00
if (!url().isEmpty() && !url().isRelative()) {
KUrl u( url() );
// If we won't be able to list it (e.g. http), then don't try :)
if (KProtocolManager::supportsListing(u)) {
dlg->setSelection(u.url());
}
2014-11-13 01:04:59 +02:00
} else {
dlg->setUrl(m_startDir);
2014-11-13 01:04:59 +02:00
}
//Update the file dialog window modality
if (dlg->windowModality() != fileDialogModality) {
2014-11-13 01:04:59 +02:00
dlg->setWindowModality(fileDialogModality);
}
2014-11-13 01:04:59 +02:00
if (fileDialogModality == Qt::NonModal) {
2014-11-13 01:04:59 +02:00
dlg->show();
} else {
dlg->exec();
}
}
}
void KUrlRequester::KUrlRequesterPrivate::_k_slotFileDialogFinished()
{
if (!myFileDialog) {
2014-11-13 01:04:59 +02:00
return;
}
2014-11-13 01:04:59 +02:00
if (myFileDialog->result() == QDialog::Accepted) {
2014-11-13 01:04:59 +02:00
KUrl newUrl = myFileDialog->selectedUrl();
if (newUrl.isValid()) {
m_parent->setUrl(newUrl);
emit m_parent->urlSelected(url());
2014-11-13 01:04:59 +02:00
// remember url as defaultStartDir and update startdir for autocompletion
if (newUrl.isLocalFile() && !m_startDirCustomized) {
2014-11-13 01:04:59 +02:00
m_startDir = newUrl;
m_startDir.setPath(m_startDir.directory());
updateCompletionStartDir(m_startDir);
}
}
}
}
void KUrlRequester::setMode(KFile::Modes mode)
2014-11-13 01:04:59 +02:00
{
Q_ASSERT( (mode & KFile::Files) == 0);
2014-11-13 01:04:59 +02:00
d->fileDialogMode = mode;
if ((mode & KFile::Directory) && !(mode & KFile::File)) {
2014-11-13 01:04:59 +02:00
d->myCompletion->setMode( KUrlCompletion::DirCompletion );
}
2014-11-13 01:04:59 +02:00
if (d->myFileDialog) {
d->myFileDialog->setMode(d->fileDialogMode);
}
}
KFile::Modes KUrlRequester::mode() const
{
return d->fileDialogMode;
}
void KUrlRequester::setFilter(const QString &filter)
{
d->fileDialogFilter = filter;
if (d->myFileDialog) {
d->myFileDialog->setFilter(d->fileDialogFilter);
}
}
QString KUrlRequester::filter( ) const
{
return d->fileDialogFilter;
}
KFileDialog * KUrlRequester::fileDialog() const
{
if (!d->myFileDialog) {
QWidget *p = parentWidget();
d->myFileDialog = new KFileDialog(QString(), d->fileDialogFilter, p);
d->myFileDialog->setMode(d->fileDialogMode);
d->myFileDialog->setCaption(windowTitle());
d->myFileDialog->setWindowModality(d->fileDialogModality);
connect(d->myFileDialog, SIGNAL(finished()), SLOT(_k_slotFileDialogFinished()));
}
return d->myFileDialog;
}
void KUrlRequester::clear()
{
d->setText(QString());
2014-11-13 01:04:59 +02:00
}
KLineEdit* KUrlRequester::lineEdit() const
2014-11-13 01:04:59 +02:00
{
return d->edit;
}
KComboBox* KUrlRequester::comboBox() const
2014-11-13 01:04:59 +02:00
{
return d->combo;
}
void KUrlRequester::KUrlRequesterPrivate::_k_slotUpdateUrl()
{
KUrl u(KUrl::fromPath(QDir::currentPath() + '/'), url().url());
myButton->setURL(u);
2014-11-13 01:04:59 +02:00
}
bool KUrlRequester::eventFilter(QObject *obj, QEvent *ev)
2014-11-13 01:04:59 +02:00
{
if (d->edit == obj || d->combo == obj) {
if (ev->type() == QEvent::FocusIn || ev->type() == QEvent::FocusOut) {
2014-11-13 01:04:59 +02:00
// Forward focusin/focusout events to the urlrequester; needed by file form element in khtml
QApplication::sendEvent(this, ev);
}
2014-11-13 01:04:59 +02:00
}
return QWidget::eventFilter(obj, ev);
2014-11-13 01:04:59 +02:00
}
KPushButton* KUrlRequester::button() const
2014-11-13 01:04:59 +02:00
{
return d->myButton;
}
KUrlCompletion *KUrlRequester::completionObject() const
{
return d->myCompletion;
}
void KUrlRequester::setClickMessage(const QString& msg)
{
if (d->edit) {
2014-11-13 01:04:59 +02:00
d->edit->setClickMessage(msg);
}
2014-11-13 01:04:59 +02:00
}
QString KUrlRequester::clickMessage() const
{
if(d->edit)
return d->edit->clickMessage();
else
return QString();
}
Qt::WindowModality KUrlRequester::fileDialogModality() const
{
return d->fileDialogModality;
}
void KUrlRequester::setFileDialogModality(Qt::WindowModality modality)
{
d->fileDialogModality = modality;
}
const KEditListWidget::CustomEditor& KUrlRequester::customEditor()
2014-11-13 01:04:59 +02:00
{
setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
2014-11-13 01:04:59 +02:00
KLineEdit *edit = d->edit;
if (!edit && d->combo )
edit = qobject_cast<KLineEdit*>(d->combo->lineEdit());
2014-11-13 01:04:59 +02:00
#ifndef NDEBUG
if ( !edit ) {
kWarning() << "KUrlRequester's lineedit is not a KLineEdit!??";
2014-11-13 01:04:59 +02:00
}
#endif
d->editor.setRepresentationWidget(this);
d->editor.setLineEdit(edit);
return d->editor;
}
KUrlComboRequester::KUrlComboRequester( QWidget *parent)
: KUrlRequester( new KComboBox(false), parent)
2014-11-13 01:04:59 +02:00
{
}
#include "moc_kurlrequester.cpp"