mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 18:32:49 +00:00
543 lines
14 KiB
C++
543 lines
14 KiB
C++
/* 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)
|
|
{
|
|
setDragEnabled(true);
|
|
}
|
|
|
|
void setURL(const KUrl &url)
|
|
{
|
|
m_urls.clear();
|
|
m_urls.append(url);
|
|
}
|
|
|
|
protected:
|
|
virtual QDrag* dragObject()
|
|
{
|
|
if (m_urls.isEmpty()) {
|
|
return nullptr;
|
|
}
|
|
|
|
QDrag *drag = new QDrag(this);
|
|
QMimeData *mimeData = new QMimeData();
|
|
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)
|
|
{
|
|
qRegisterMetaType<KUrl>("KUrl");
|
|
}
|
|
|
|
~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);
|
|
}
|
|
}
|
|
} else {
|
|
edit->setText(text);
|
|
}
|
|
}
|
|
|
|
void connectSignals(QObject *receiver)
|
|
{
|
|
QObject *sender;
|
|
if (combo) {
|
|
sender = combo;
|
|
} else {
|
|
sender = edit;
|
|
}
|
|
|
|
if (combo) {
|
|
connect(
|
|
sender, SIGNAL(editTextChanged(QString)),
|
|
receiver, SIGNAL(textChanged(QString)));
|
|
} else {
|
|
connect(
|
|
sender, SIGNAL(textChanged(QString)),
|
|
receiver, SIGNAL(textChanged(QString))
|
|
);
|
|
}
|
|
|
|
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)
|
|
{
|
|
if (newStartDir.isLocalFile()) {
|
|
myCompletion->setDir(newStartDir.toLocalFile());
|
|
}
|
|
}
|
|
|
|
QString text() const
|
|
{
|
|
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
|
|
{
|
|
const QString txt = text();
|
|
KUrlCompletion *comp;
|
|
if (combo) {
|
|
comp = qobject_cast<KUrlCompletion*>(combo->completionObject());
|
|
} else {
|
|
comp = qobject_cast<KUrlCompletion*>(edit->completionObject());
|
|
}
|
|
|
|
KUrl enteredPath;
|
|
KUrl baseDir(m_startDir);
|
|
if (comp) {
|
|
enteredPath = KUrl(comp->replacedPath(txt));
|
|
} else {
|
|
enteredPath = KUrl(txt);
|
|
}
|
|
|
|
if (enteredPath.isRelative() && !txt.isEmpty()) {
|
|
baseDir.addPath(enteredPath.path());
|
|
return baseDir;
|
|
}
|
|
return enteredPath;
|
|
}
|
|
|
|
// slots
|
|
void _k_slotUpdateUrl();
|
|
void _k_slotOpenDialog();
|
|
void _k_slotFileDialogFinished();
|
|
|
|
KUrl m_startDir;
|
|
bool m_startDirCustomized;
|
|
KUrlRequester* m_parent;
|
|
KLineEdit* edit;
|
|
KComboBox* combo;
|
|
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))
|
|
{
|
|
// 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);
|
|
}
|
|
|
|
d->init();
|
|
}
|
|
|
|
|
|
KUrlRequester::KUrlRequester(QWidget *parent)
|
|
: KHBox(parent),
|
|
d(new KUrlRequesterPrivate(this))
|
|
{
|
|
d->init();
|
|
}
|
|
|
|
|
|
KUrlRequester::KUrlRequester(const KUrl &url, QWidget *parent)
|
|
: KHBox(parent),
|
|
d(new KUrlRequesterPrivate(this))
|
|
{
|
|
d->init();
|
|
setUrl(url);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
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)
|
|
{
|
|
d->setText(text);
|
|
}
|
|
|
|
void KUrlRequester::setStartDir(const KUrl &startDir)
|
|
{
|
|
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);
|
|
}
|
|
|
|
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()) {
|
|
//The file dialog is already being shown, raise it and exit
|
|
myFileDialog->raise();
|
|
myFileDialog->activateWindow();
|
|
return;
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
KUrl newurl;
|
|
if (fileDialogMode & KFile::LocalOnly) {
|
|
newurl = KFileDialog::getExistingDirectory(openUrl, m_parent);
|
|
} else {
|
|
newurl = KFileDialog::getExistingDirectoryUrl(openUrl, m_parent);
|
|
}
|
|
|
|
if (newurl.isValid()) {
|
|
m_parent->setUrl(newurl);
|
|
emit m_parent->urlSelected(url());
|
|
}
|
|
} else {
|
|
emit m_parent->openFileDialog(m_parent);
|
|
|
|
//Creates the fileDialog if it doesn't exist yet
|
|
KFileDialog* dlg = m_parent->fileDialog();
|
|
|
|
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());
|
|
}
|
|
} else {
|
|
dlg->setUrl(m_startDir);
|
|
}
|
|
|
|
//Update the file dialog window modality
|
|
if (dlg->windowModality() != fileDialogModality) {
|
|
dlg->setWindowModality(fileDialogModality);
|
|
}
|
|
|
|
if (fileDialogModality == Qt::NonModal) {
|
|
dlg->show();
|
|
} else {
|
|
dlg->exec();
|
|
}
|
|
}
|
|
}
|
|
|
|
void KUrlRequester::KUrlRequesterPrivate::_k_slotFileDialogFinished()
|
|
{
|
|
if (!myFileDialog) {
|
|
return;
|
|
}
|
|
|
|
if (myFileDialog->result() == QDialog::Accepted) {
|
|
KUrl newUrl = myFileDialog->selectedUrl();
|
|
if (newUrl.isValid()) {
|
|
m_parent->setUrl(newUrl);
|
|
emit m_parent->urlSelected(url());
|
|
// remember url as defaultStartDir and update startdir for autocompletion
|
|
if (newUrl.isLocalFile() && !m_startDirCustomized) {
|
|
m_startDir = newUrl;
|
|
m_startDir.setPath(m_startDir.directory());
|
|
updateCompletionStartDir(m_startDir);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void KUrlRequester::setMode(KFile::Modes mode)
|
|
{
|
|
Q_ASSERT( (mode & KFile::Files) == 0);
|
|
d->fileDialogMode = mode;
|
|
if ((mode & KFile::Directory) && !(mode & KFile::File)) {
|
|
d->myCompletion->setMode( KUrlCompletion::DirCompletion );
|
|
}
|
|
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());
|
|
}
|
|
|
|
KLineEdit* KUrlRequester::lineEdit() const
|
|
{
|
|
return d->edit;
|
|
}
|
|
|
|
KComboBox* KUrlRequester::comboBox() const
|
|
{
|
|
return d->combo;
|
|
}
|
|
|
|
void KUrlRequester::KUrlRequesterPrivate::_k_slotUpdateUrl()
|
|
{
|
|
KUrl u(KUrl::fromPath(QDir::currentPath() + '/'), url().url());
|
|
myButton->setURL(u);
|
|
}
|
|
|
|
bool KUrlRequester::eventFilter(QObject *obj, QEvent *ev)
|
|
{
|
|
if (d->edit == obj || d->combo == obj) {
|
|
if (ev->type() == QEvent::FocusIn || ev->type() == QEvent::FocusOut) {
|
|
// Forward focusin/focusout events to the urlrequester; needed by file form element in khtml
|
|
QApplication::sendEvent(this, ev);
|
|
}
|
|
}
|
|
return QWidget::eventFilter(obj, ev);
|
|
}
|
|
|
|
KPushButton* KUrlRequester::button() const
|
|
{
|
|
return d->myButton;
|
|
}
|
|
|
|
KUrlCompletion *KUrlRequester::completionObject() const
|
|
{
|
|
return d->myCompletion;
|
|
}
|
|
|
|
void KUrlRequester::setClickMessage(const QString& msg)
|
|
{
|
|
if (d->edit) {
|
|
d->edit->setClickMessage(msg);
|
|
}
|
|
}
|
|
|
|
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()
|
|
{
|
|
setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
|
|
|
|
KLineEdit *edit = d->edit;
|
|
if (!edit && d->combo )
|
|
edit = qobject_cast<KLineEdit*>(d->combo->lineEdit());
|
|
|
|
#ifndef NDEBUG
|
|
if ( !edit ) {
|
|
kWarning() << "KUrlRequester's lineedit is not a KLineEdit!??";
|
|
}
|
|
#endif
|
|
|
|
d->editor.setRepresentationWidget(this);
|
|
d->editor.setLineEdit(edit);
|
|
return d->editor;
|
|
}
|
|
|
|
KUrlComboRequester::KUrlComboRequester( QWidget *parent)
|
|
: KUrlRequester( new KComboBox(false), parent)
|
|
{
|
|
}
|
|
|
|
#include "moc_kurlrequester.cpp"
|