kurlbar.cpp

00001 /* This file is part of the KDE libraries
00002     Copyright (C) 2001,2002,2003 Carsten Pfeiffer <pfeiffer@kde.org>
00003 
00004     library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License as published by the Free Software Foundation, version 2.
00007 
00008     This library is distributed in the hope that it will be useful,
00009     but WITHOUT ANY WARRANTY; without even the implied warranty of
00010     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011     Library General Public License for more details.
00012 
00013     You should have received a copy of the GNU Library General Public License
00014     along with this library; see the file COPYING.LIB.  If not, write to
00015     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016     Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #include <unistd.h>
00020 
00021 #include <qapplication.h>
00022 #include <qcheckbox.h>
00023 #include <qdrawutil.h>
00024 #include <qfontmetrics.h>
00025 #include <qlabel.h>
00026 #include <qgrid.h>
00027 #include <qpainter.h>
00028 #include <qpopupmenu.h>
00029 #include <qstyle.h>
00030 #include <qvbox.h>
00031 #include <qwhatsthis.h>
00032 
00033 #include <kaboutdata.h>
00034 #include <kconfig.h>
00035 #include <kdebug.h>
00036 #include <kglobal.h>
00037 #include <kicondialog.h>
00038 #include <kiconloader.h>
00039 #include <kinstance.h>
00040 #include <klineedit.h>
00041 #include <klocale.h>
00042 #include <kmimetype.h>
00043 #include <kprotocolinfo.h>
00044 #include <kstringhandler.h>
00045 #include <kurldrag.h>
00046 #include <kurlrequester.h>
00047 #include <kio/global.h>
00048 #include <kio/netaccess.h>
00049 
00050 #include "kurlbar.h"
00051 
00056 class KURLBarToolTip : public QToolTip
00057 {
00058 public:
00059     KURLBarToolTip( QListBox *view ) : QToolTip( view ), m_view( view ) {}
00060 
00061 protected:
00062     virtual void maybeTip( const QPoint& point ) {
00063         QListBoxItem *item = m_view->itemAt( point );
00064         if ( item ) {
00065             QString text = static_cast<KURLBarItem*>( item )->toolTip();
00066             if ( !text.isEmpty() )
00067                 tip( m_view->itemRect( item ), text );
00068         }
00069     }
00070 
00071 private:
00072     QListBox *m_view;
00073 };
00074 
00075 
00078 
00079 class KURLBarItem::KURLBarItemPrivate
00080 {
00081 public:
00082     KURLBarItemPrivate()
00083     {
00084         isPersistent = true;
00085     }
00086 
00087     bool isPersistent;
00088 };
00089 
00090 KURLBarItem::KURLBarItem( KURLBar *parent,
00091                           const KURL& url, bool persistent, const QString& description,
00092                           const QString& icon, KIcon::Group group )
00093     : QListBoxPixmap( KIconLoader::unknown() /*, parent->listBox()*/ ),
00094       m_url( url ),
00095       m_pixmap( 0L ),
00096       m_parent( parent ),
00097       m_appLocal( false )
00098 {
00099     init( icon, group, description, persistent );
00100 }
00101 
00102 KURLBarItem::KURLBarItem( KURLBar *parent,
00103                           const KURL& url, const QString& description,
00104                           const QString& icon, KIcon::Group group )
00105     : QListBoxPixmap( KIconLoader::unknown() /*, parent->listBox()*/ ),
00106       m_url( url ),
00107       m_pixmap( 0L ),
00108       m_parent( parent ),
00109       m_appLocal( false )
00110 {
00111     init( icon, group, description, true /*persistent*/ );
00112 }
00113 
00114 void KURLBarItem::init( const QString& icon, KIcon::Group group,
00115                         const QString& description, bool persistent )
00116 {
00117     d = new KURLBarItemPrivate;
00118     d->isPersistent = persistent;
00119 
00120     setCustomHighlighting( true );
00121     setIcon( icon, group );
00122     setDescription( description );
00123 }
00124 
00125 KURLBarItem::~KURLBarItem()
00126 {
00127     delete d;
00128 }
00129 
00130 void KURLBarItem::setURL( const KURL& url )
00131 {
00132     m_url = url;
00133     if ( m_description.isEmpty() )
00134         setText( url.fileName() );
00135 }
00136 
00137 void KURLBarItem::setIcon( const QString& icon, KIcon::Group group )
00138 {
00139     m_icon  = icon;
00140     m_group = group;
00141 
00142     if ( icon.isEmpty() )
00143         m_pixmap = KMimeType::pixmapForURL( m_url, 0, group, iconSize() );
00144     else
00145         m_pixmap = KGlobal::iconLoader()->loadIcon( icon, group, iconSize(),
00146                                                     KIcon::DefaultState );
00147 }
00148 
00149 void KURLBarItem::setDescription( const QString& desc )
00150 {
00151     m_description = desc;
00152     setText( desc.isEmpty() ? m_url.fileName() : desc );
00153 }
00154 
00155 void KURLBarItem::setApplicationLocal( bool local )
00156 {
00157     if ( !local && !isPersistent() )
00158     {
00159         kdWarning() << "KURLBar: dynamic (non-persistent) items can not be global." << endl;
00160         return;
00161     }
00162 
00163     m_appLocal = local;
00164 }
00165 
00166 void KURLBarItem::setToolTip( const QString& tip )
00167 {
00168     m_toolTip = tip;
00169 }
00170 
00171 QString KURLBarItem::toolTip() const
00172 {
00173     return m_toolTip.isEmpty() ? m_url.prettyURL() : m_toolTip;
00174 }
00175 
00176 int KURLBarItem::iconSize() const
00177 {
00178     return m_parent->iconSize();
00179 }
00180 
00181 void KURLBarItem::paint( QPainter *p )
00182 {
00183     QListBox *box = listBox();
00184     int w = width( box );
00185     static const int margin = KDialog::spacingHint();
00186 
00187     // draw sunken selection
00188     if ( isCurrent() || isSelected() ) {
00189         int h = height( box );
00190 
00191         QBrush brush = box->colorGroup().brush( QColorGroup::Highlight );
00192         p->fillRect( 0, 0, w, h, brush );
00193         QPen pen = p->pen();
00194         QPen oldPen = pen;
00195         pen.setColor( box->colorGroup().mid() );
00196         p->setPen( pen );
00197 
00198         p->drawPoint( 0, 0 );
00199         p->drawPoint( 0, h - 1 );
00200         p->drawPoint( w - 1, 0 );
00201         p->drawPoint( w - 1, h - 1 );
00202 
00203         p->setPen( oldPen );
00204     }
00205 
00206     if ( m_parent->iconSize() < KIcon::SizeMedium ) {
00207         // small icon -> draw icon next to text
00208 
00209         // ### mostly cut & paste of QListBoxPixmap::paint() until Qt 3.1
00210         // (where it will properly use pixmap() instead of the internal pixmap)
00211         const QPixmap *pm = pixmap();
00212         int yPos = QMAX( 0, (height(box) - pm->height())/2 );
00213 
00214         p->drawPixmap( margin, yPos, *pm );
00215         if ( !text().isEmpty() ) {
00216             QFontMetrics fm = p->fontMetrics();
00217             if ( pm->height() < fm.height() )
00218                 yPos = fm.ascent() + fm.leading()/2;
00219             else
00220                 yPos = pm->height()/2 - fm.height()/2 + fm.ascent();
00221 
00222             yPos += margin;
00223             int stringWidth = box->width() - pm->width() - 2 - (margin * 2);
00224             QString visibleText = KStringHandler::rPixelSqueeze( text(), fm, stringWidth );
00225             int xPos = pm->width() + margin + 2;
00226 
00227             if ( isCurrent() || isSelected() ) {
00228                 p->setPen( box->colorGroup().highlight().dark(115) );
00229                 p->drawText( xPos + ( QApplication::reverseLayout() ? -1 : 1),
00230                              yPos + 1, visibleText );
00231                 p->setPen( box->colorGroup().highlightedText() );
00232             }
00233 
00234             p->drawText( xPos, yPos, visibleText );
00235         }
00236         // end cut & paste (modulo pixmap centering)
00237     }
00238 
00239     else {
00240         // big icons -> draw text below icon
00241         int y = margin;
00242         const QPixmap *pm = pixmap();
00243 
00244         if ( !pm->isNull() ) {
00245             int x = (w - pm->width()) / 2;
00246             x = QMAX( x, margin );
00247             p->drawPixmap( x, y, *pm );
00248         }
00249 
00250         if ( !text().isEmpty() ) {
00251             QFontMetrics fm = p->fontMetrics();
00252             y += pm->height() + fm.height() - fm.descent();
00253 
00254             int stringWidth = box->width() - (margin * 2);
00255             QString visibleText = KStringHandler::rPixelSqueeze( text(), fm, stringWidth );
00256             int x = (w - fm.width( visibleText )) / 2;
00257             x = QMAX( x, margin );
00258 
00259             if ( isCurrent() || isSelected() ) {
00260                 p->setPen( box->colorGroup().highlight().dark(115) );
00261                 p->drawText( x + ( QApplication::reverseLayout() ? -1 : 1),
00262                              y + 1, visibleText );
00263                 p->setPen( box->colorGroup().highlightedText() );
00264             }
00265 
00266             p->drawText( x, y, visibleText );
00267         }
00268     }
00269 }
00270 
00271 QSize KURLBarItem::sizeHint() const
00272 {
00273     int wmin = 0;
00274     int hmin = 0;
00275     const KURLBarListBox *lb =static_cast<const KURLBarListBox*>(listBox());
00276 
00277     if ( m_parent->iconSize() < KIcon::SizeMedium ) {
00278         wmin = QListBoxPixmap::width( lb ) + KDialog::spacingHint() * 2;
00279         hmin = QListBoxPixmap::height( lb ) + KDialog::spacingHint() * 2;
00280     }
00281     else {
00282         wmin = QMAX(lb->fontMetrics().width(text()), pixmap()->width()) + KDialog::spacingHint() * 2;
00283         hmin = lb->fontMetrics().lineSpacing() + pixmap()->height() + KDialog::spacingHint() * 2;
00284     }
00285 
00286     if ( lb->isVertical() )
00287         wmin = QMIN( wmin, lb->viewport()->sizeHint().width() );
00288     else
00289         hmin = QMIN( hmin, lb->viewport()->sizeHint().height() );
00290 
00291     return QSize( wmin, hmin );
00292 }
00293 
00294 int KURLBarItem::width( const QListBox *lb ) const
00295 {
00296     if ( static_cast<const KURLBarListBox *>( lb )->isVertical() )
00297         return QMAX( sizeHint().width(), lb->viewport()->width() );
00298     else
00299         return sizeHint().width();
00300 }
00301 
00302 int KURLBarItem::height( const QListBox *lb ) const
00303 {
00304     if ( static_cast<const KURLBarListBox *>( lb )->isVertical() )
00305         return sizeHint().height();
00306     else
00307         return QMAX( sizeHint().height(), lb->viewport()->height() );
00308 }
00309 
00310 bool KURLBarItem::isPersistent() const
00311 {
00312     return d->isPersistent;
00313 }
00314 
00317 
00318 class KURLBar::KURLBarPrivate
00319 {
00320 public:
00321     KURLBarPrivate()
00322     {
00323         currentURL.setPath( QDir::homeDirPath() );
00324         defaultIconSize = 0;
00325     }
00326 
00327     int defaultIconSize;
00328     KURL currentURL;
00329 };
00330 
00331 
00332 KURLBar::KURLBar( bool useGlobalItems, QWidget *parent, const char *name, WFlags f )
00333     : QFrame( parent, name, f ),
00334       m_activeItem( 0L ),
00335       m_useGlobal( useGlobalItems ),
00336       m_isModified( false ),
00337       m_isImmutable( false ),
00338       m_listBox( 0L ),
00339       m_iconSize( KIcon::SizeMedium )
00340 {
00341     d = new KURLBarPrivate();
00342 
00343     setListBox( 0L );
00344     setSizePolicy( QSizePolicy( isVertical() ?
00345                                 QSizePolicy::Maximum :
00346                                 QSizePolicy::Preferred,
00347                                 isVertical() ?
00348                                 QSizePolicy::Preferred :
00349                                 QSizePolicy::Maximum ));
00350     QWhatsThis::add(this, i18n("<qt>The <b>Quick Access</b> panel provides easy access to commonly used file locations.<p>"
00351                                "Clicking on one of the shortcut entries will take you to that location.<p>"
00352                                "By right clicking on an entry you can add, edit and remove shortcuts.</qt>"));
00353 }
00354 
00355 KURLBar::~KURLBar()
00356 {
00357     delete d;
00358 }
00359 
00360 KURLBarItem * KURLBar::insertItem(const KURL& url, const QString& description,
00361                                   bool applicationLocal,
00362                                   const QString& icon, KIcon::Group group )
00363 {
00364     KURLBarItem *item = new KURLBarItem(this, url, description, icon, group);
00365     item->setApplicationLocal( applicationLocal );
00366     m_listBox->insertItem( item );
00367     return item;
00368 }
00369 
00370 KURLBarItem * KURLBar::insertDynamicItem(const KURL& url, const QString& description,
00371                                          const QString& icon, KIcon::Group group )
00372 {
00373     KURLBarItem *item = new KURLBarItem(this, url, false, description, icon, group);
00374     m_listBox->insertItem( item );
00375     return item;
00376 }
00377 
00378 void KURLBar::setOrientation( Qt::Orientation orient )
00379 {
00380     m_listBox->setOrientation( orient );
00381     setSizePolicy( QSizePolicy( isVertical() ?
00382                                 QSizePolicy::Maximum :
00383                                 QSizePolicy::Preferred,
00384                                 isVertical() ?
00385                                 QSizePolicy::Preferred :
00386                                 QSizePolicy::Maximum ));
00387 }
00388 
00389 Qt::Orientation KURLBar::orientation() const
00390 {
00391     return m_listBox->orientation();
00392 }
00393 
00394 void KURLBar::setListBox( KURLBarListBox *view )
00395 {
00396     delete m_listBox;
00397 
00398     if ( !view ) {
00399         m_listBox = new KURLBarListBox( this, "urlbar listbox" );
00400         setOrientation( Vertical );
00401     }
00402     else {
00403         m_listBox = view;
00404         if ( m_listBox->parentWidget() != this )
00405             m_listBox->reparent( this, QPoint(0,0) );
00406         m_listBox->resize( width(), height() );
00407     }
00408 
00409     m_listBox->setSelectionMode( KListBox::Single );
00410     paletteChange( palette() );
00411     m_listBox->setFocusPolicy( TabFocus );
00412 
00413     connect( m_listBox, SIGNAL( mouseButtonClicked( int, QListBoxItem *, const QPoint & ) ),
00414              SLOT( slotSelected( int, QListBoxItem * )));
00415     connect( m_listBox, SIGNAL( dropped( QDropEvent * )),
00416              this, SLOT( slotDropped( QDropEvent * )));
00417     connect( m_listBox, SIGNAL( contextMenuRequested( QListBoxItem *,
00418                                                       const QPoint& )),
00419              SLOT( slotContextMenuRequested( QListBoxItem *, const QPoint& )));
00420     connect( m_listBox, SIGNAL( returnPressed( QListBoxItem * ) ),
00421              SLOT( slotSelected( QListBoxItem * ) ));
00422 }
00423 
00424 void KURLBar::setIconSize( int size )
00425 {
00426     if ( size == m_iconSize )
00427         return;
00428 
00429     m_iconSize = size;
00430 
00431     // reload the icons with the new size
00432     KURLBarItem *item = static_cast<KURLBarItem*>( m_listBox->firstItem() );
00433     while ( item ) {
00434         item->setIcon( item->icon(), item->iconGroup() );
00435         item = static_cast<KURLBarItem*>( item->next() );
00436     }
00437 
00438     resize( sizeHint() );
00439     updateGeometry();
00440 }
00441 
00442 void KURLBar::clear()
00443 {
00444     m_listBox->clear();
00445 }
00446 
00447 void KURLBar::resizeEvent( QResizeEvent *e )
00448 {
00449     QFrame::resizeEvent( e );
00450     m_listBox->resize( width(), height() );
00451 }
00452 
00453 void KURLBar::paletteChange( const QPalette & )
00454 {
00455     QPalette pal = palette();
00456     QColor gray = pal.color( QPalette::Normal, QColorGroup::Background );
00457     QColor selectedTextColor = pal.color( QPalette::Normal, QColorGroup::BrightText );
00458     QColor foreground = pal.color( QPalette::Normal, QColorGroup::Foreground );
00459     pal.setColor( QPalette::Normal,   QColorGroup::Base, gray );
00460     pal.setColor( QPalette::Normal,   QColorGroup::HighlightedText, selectedTextColor );
00461     pal.setColor( QPalette::Normal,   QColorGroup::Text, foreground );
00462     pal.setColor( QPalette::Inactive, QColorGroup::Base, gray );
00463     pal.setColor( QPalette::Inactive, QColorGroup::HighlightedText, selectedTextColor );
00464     pal.setColor( QPalette::Inactive, QColorGroup::Text, foreground );
00465 
00466     setPalette( pal );
00467 }
00468 
00469 QSize KURLBar::sizeHint() const
00470 {
00471     return m_listBox->sizeHint();
00472 
00473 #if 0
00474     // this code causes vertical and or horizontal scrollbars appearing
00475     // depending on the text, font, moonphase and earth rotation. Just using
00476     // m_listBox->sizeHint() fixes this (although the widget can then be
00477     // resized to a smaller size so that scrollbars appear).
00478     int w = 0;
00479     int h = 0;
00480     KURLBarItem *item;
00481     bool vertical = isVertical();
00482 
00483     for ( item = static_cast<KURLBarItem*>( m_listBox->firstItem() );
00484           item;
00485           item = static_cast<KURLBarItem*>( item->next() ) ) {
00486 
00487         QSize sh = item->sizeHint();
00488 
00489         if ( vertical ) {
00490             w = QMAX( w, sh.width() );
00491             h += sh.height();
00492         }
00493         else {
00494             w += sh.width();
00495             h = QMAX( h, sh.height() );
00496         }
00497     }
00498 
00499 //     if ( vertical && m_listBox->verticalScrollBar()->isVisible() )
00500 //         w += m_listBox->verticalScrollBar()->width();
00501 //     else if ( !vertical && m_listBox->horizontalScrollBar()->isVisible() )
00502 //         h += m_listBox->horizontalScrollBar()->height();
00503 
00504     if ( w == 0 && h == 0 )
00505         return QSize( 100, 200 );
00506     else
00507         return QSize( 6 + w, h );
00508 #endif
00509 }
00510 
00511 QSize KURLBar::minimumSizeHint() const
00512 {
00513     QSize s = sizeHint(); // ###
00514     int w = s.width()  + m_listBox->verticalScrollBar()->width();
00515     int h = s.height() + m_listBox->horizontalScrollBar()->height();
00516     return QSize( w, h );
00517 }
00518 
00519 void KURLBar::slotSelected( int button, QListBoxItem *item )
00520 {
00521     if ( button != Qt::LeftButton )
00522         return;
00523 
00524     slotSelected( item );
00525 }
00526 
00527 void KURLBar::slotSelected( QListBoxItem *item )
00528 {
00529     if ( item && item != m_activeItem )
00530         m_activeItem = static_cast<KURLBarItem*>( item );
00531 
00532     if ( m_activeItem ) {
00533         m_listBox->setCurrentItem( m_activeItem );
00534         emit activated( m_activeItem->url() );
00535     }
00536 }
00537 
00538 void KURLBar::setCurrentItem( const KURL& url )
00539 {
00540     d->currentURL = url;
00541 
00542     QString u = url.url(-1);
00543 
00544     if ( m_activeItem && m_activeItem->url().url(-1) == u )
00545         return;
00546 
00547     bool hasURL = false;
00548     QListBoxItem *item = m_listBox->firstItem();
00549     while ( item ) {
00550         if ( static_cast<KURLBarItem*>( item )->url().url(-1) == u ) {
00551             m_activeItem = static_cast<KURLBarItem*>( item );
00552             m_listBox->setCurrentItem( item );
00553             m_listBox->setSelected( item, true );
00554             hasURL = true;
00555             break;
00556         }
00557         item = item->next();
00558     }
00559 
00560     if ( !hasURL ) {
00561         m_activeItem = 0L;
00562         m_listBox->clearSelection();
00563     }
00564 }
00565 
00566 KURLBarItem * KURLBar::currentItem() const
00567 {
00568     QListBoxItem *item = m_listBox->item( m_listBox->currentItem() );
00569     if ( item )
00570         return static_cast<KURLBarItem *>( item );
00571     return 0L;
00572 }
00573 
00574 KURL KURLBar::currentURL() const
00575 {
00576     KURLBarItem *item = currentItem();
00577     return item ? item->url() : KURL();
00578 }
00579 
00580 void KURLBar::readConfig( KConfig *appConfig, const QString& itemGroup )
00581 {
00582     m_isImmutable = appConfig->groupIsImmutable( itemGroup );
00583     KConfigGroupSaver cs( appConfig, itemGroup );
00584     d->defaultIconSize = m_iconSize;
00585     m_iconSize = appConfig->readNumEntry( "Speedbar IconSize", m_iconSize );
00586 
00587     if ( m_useGlobal ) { // read global items
00588         KConfig *globalConfig = KGlobal::config();
00589         KConfigGroupSaver cs( globalConfig, (QString)(itemGroup +" (Global)"));
00590         int num = globalConfig->readNumEntry( "Number of Entries" );
00591         for ( int i = 0; i < num; i++ ) {
00592             readItem( i, globalConfig, false );
00593         }
00594     }
00595 
00596     // read application local items
00597     int num = appConfig->readNumEntry( "Number of Entries" );
00598     for ( int i = 0; i < num; i++ ) {
00599         readItem( i, appConfig, true );
00600     }
00601 }
00602 
00603 void KURLBar::readItem( int i, KConfig *config, bool applicationLocal )
00604 {
00605     QString number = QString::number( i );
00606     KURL url = KURL::fromPathOrURL( config->readPathEntry( QString("URL_") + number ));
00607     if ( !url.isValid() || !KProtocolInfo::isKnownProtocol( url ))
00608         return; // nothing we could do.
00609 
00610     QString description = config->readEntry( QString("Description_") + number ); 
00611 
00612     if (description.isEmpty() && url.protocol()=="beagle") {
00613         KIO::UDSEntry uds;
00614         const KURL kurl("beagle:?beagled-status");
00615         if (!KIO::NetAccess::stat(kurl, uds))
00616             return;
00617 
00618         description = i18n("Desktop Search");
00619     }
00620 
00621     insertItem( url,
00622                 description,
00623                 applicationLocal,
00624                 config->readEntry( QString("Icon_") + number ),
00625                 static_cast<KIcon::Group>(
00626                     config->readNumEntry( QString("IconGroup_") + number )) );
00627 }
00628 
00629 void KURLBar::writeConfig( KConfig *config, const QString& itemGroup )
00630 {
00631     KConfigGroupSaver cs1( config, itemGroup );
00632     if(!config->hasDefault("Speedbar IconSize") && m_iconSize == d->defaultIconSize )
00633         config->revertToDefault("Speedbar IconSize");
00634     else
00635         config->writeEntry( "Speedbar IconSize", m_iconSize );
00636 
00637     if ( !m_isModified )
00638         return;
00639 
00640     int i = 0;
00641     int numLocal = 0;
00642     KURLBarItem *item = static_cast<KURLBarItem*>( m_listBox->firstItem() );
00643 
00644     while ( item )
00645     {
00646         if ( item->isPersistent() ) // we only save persistent items
00647         {
00648             if ( item->applicationLocal() )
00649             {
00650                 writeItem( item, numLocal, config, false );
00651                 numLocal++;
00652             }
00653 
00654             i++;
00655         }
00656         item = static_cast<KURLBarItem*>( item->next() );
00657     }
00658     config->writeEntry("Number of Entries", numLocal);
00659 
00660 
00661     // write the global entries to kdeglobals, if any
00662     bool haveGlobalEntries = (i > numLocal);
00663     if ( m_useGlobal && haveGlobalEntries ) {
00664         config->setGroup( itemGroup + " (Global)" );
00665 
00666         int numGlobals = 0;
00667         item = static_cast<KURLBarItem*>( m_listBox->firstItem() );
00668 
00669         while ( item )
00670         {
00671             if ( item->isPersistent() ) // we only save persistent items
00672             {
00673                 if ( !item->applicationLocal() )
00674                 {
00675                     writeItem( item, numGlobals, config, true );
00676                     numGlobals++;
00677                 }
00678             }
00679 
00680             item = static_cast<KURLBarItem*>( item->next() );
00681         }
00682         config->writeEntry("Number of Entries", numGlobals, true, true);
00683     }
00684 
00685     m_isModified = false;
00686 }
00687 
00688 void KURLBar::writeItem( KURLBarItem *item, int i, KConfig *config,
00689                          bool global )
00690 {
00691     if ( !item->isPersistent() )
00692         return;
00693 
00694     QString Description = "Description_";
00695     QString URL = "URL_";
00696     QString Icon = "Icon_";
00697     QString IconGroup = "IconGroup_";
00698 
00699     QString number = QString::number( i );
00700     config->writePathEntry( URL + number, item->url().prettyURL(), true, global );
00701 
00702     config->writeEntry( Description + number, item->description(),true,global);
00703     config->writeEntry( Icon + number, item->icon(), true, global );
00704     config->writeEntry( IconGroup + number, item->iconGroup(), true, global );
00705 }
00706 
00707 
00708 void KURLBar::slotDropped( QDropEvent *e )
00709 {
00710     KURL::List urls;
00711     if ( KURLDrag::decode( e, urls ) ) {
00712         KURL url;
00713         QString description;
00714         QString icon;
00715         bool appLocal = false;
00716 
00717         KURL::List::Iterator it = urls.begin();
00718         for ( ; it != urls.end(); ++it ) {
00719             (void) insertItem( *it, description, appLocal, icon );
00720             m_isModified = true;
00721             updateGeometry();
00722         }
00723     }
00724 }
00725 
00726 void KURLBar::slotContextMenuRequested( QListBoxItem *_item, const QPoint& pos )
00727 {
00728     if (m_isImmutable)
00729         return;
00730 
00731     KURLBarItem *item = dynamic_cast<KURLBarItem*>( _item );
00732 
00733     static const int IconSize   = 10;
00734     static const int AddItem    = 20;
00735     static const int EditItem   = 30;
00736     static const int RemoveItem = 40;
00737 
00738     KURL lastURL = m_activeItem ? m_activeItem->url() : KURL();
00739 
00740     bool smallIcons = m_iconSize < KIcon::SizeMedium;
00741     QPopupMenu *popup = new QPopupMenu();
00742     popup->insertItem( smallIcons ?
00743                        i18n("&Large Icons") : i18n("&Small Icons"),
00744                        IconSize );
00745     popup->insertSeparator();
00746 
00747     if (item != 0L && item->isPersistent())
00748     {
00749         popup->insertItem(SmallIconSet("edit"), i18n("&Edit Entry..."), EditItem);
00750         popup->insertSeparator();
00751     }
00752 
00753     popup->insertItem(SmallIconSet("filenew"), i18n("&Add Entry..."), AddItem);
00754 
00755     if (item != 0L && item->isPersistent())
00756     {
00757         popup->insertItem( SmallIconSet("editdelete"), i18n("&Remove Entry"),
00758                           RemoveItem );
00759     }
00760 
00761     int result = popup->exec( pos );
00762     switch ( result ) {
00763         case IconSize:
00764             setIconSize( smallIcons ? KIcon::SizeMedium : KIcon::SizeSmallMedium );
00765             m_listBox->triggerUpdate( true );
00766             break;
00767         case AddItem:
00768             addNewItem();
00769             break;
00770         case EditItem:
00771             editItem( static_cast<KURLBarItem *>( item ) );
00772             break;
00773         case RemoveItem:
00774             delete item;
00775             m_isModified = true;
00776             break;
00777         default: // abort
00778             break;
00779     }
00780 
00781     // reset current item
00782     m_activeItem = 0L;
00783     setCurrentItem( lastURL );
00784 }
00785 
00786 bool KURLBar::addNewItem()
00787 {
00788     KURLBarItem *item = new KURLBarItem( this, d->currentURL,
00789                                          i18n("Enter a description") );
00790     if ( editItem( item ) ) {
00791         m_listBox->insertItem( item );
00792         return true;
00793     }
00794 
00795     delete item;
00796     return false;
00797 }
00798 
00799 bool KURLBar::editItem( KURLBarItem *item )
00800 {
00801     if ( !item || !item->isPersistent() ) // should never happen tho
00802         return false;
00803 
00804     KURL url            = item->url();
00805     QString description = item->description();
00806     QString icon        = item->icon();
00807     bool appLocal       = item->applicationLocal();
00808 
00809     if ( KURLBarItemDialog::getInformation( m_useGlobal,
00810                                             url, description,
00811                                             icon, appLocal,
00812                                             m_iconSize, this ))
00813     {
00814         item->setURL( url );
00815         item->setDescription( description );
00816         item->setIcon( icon );
00817         item->setApplicationLocal( appLocal );
00818         m_listBox->triggerUpdate( true );
00819         m_isModified = true;
00820         updateGeometry();
00821         return true;
00822     }
00823 
00824     return false;
00825 }
00826 
00829 
00830 
00831 KURLBarListBox::KURLBarListBox( QWidget *parent, const char *name )
00832     : KListBox( parent, name )
00833 {
00834     m_toolTip = new KURLBarToolTip( this );
00835     setAcceptDrops( true );
00836     viewport()->setAcceptDrops( true );
00837 }
00838 
00839 KURLBarListBox::~KURLBarListBox()
00840 {
00841     delete m_toolTip;
00842 }
00843 
00844 void KURLBarListBox::paintEvent( QPaintEvent* )
00845 {
00846     QPainter p(this);
00847     p.setPen( colorGroup().mid() );
00848     p.drawRect( 0, 0, width(), height() );
00849 }
00850 
00851 QDragObject * KURLBarListBox::dragObject()
00852 {
00853     KURL::List urls;
00854     KURLBarItem *item = static_cast<KURLBarItem*>( firstItem() );
00855 
00856     while ( item ) {
00857         if ( item->isSelected() )
00858             urls.append( item->url() );
00859         item = static_cast<KURLBarItem*>( item->next() );
00860     }
00861 
00862     if ( !urls.isEmpty() ) // ### use custom drag-object with description etc.?
00863         return new KURLDrag( urls, this, "urlbar drag" );
00864 
00865     return 0L;
00866 }
00867 
00868 void KURLBarListBox::contentsDragEnterEvent( QDragEnterEvent *e )
00869 {
00870     e->accept( KURLDrag::canDecode( e ));
00871 }
00872 
00873 void KURLBarListBox::contentsDropEvent( QDropEvent *e )
00874 {
00875     emit dropped( e );
00876 }
00877 
00878 void KURLBarListBox::contextMenuEvent( QContextMenuEvent *e )
00879 {
00880     if (e)
00881     {
00882         emit contextMenuRequested( itemAt( e->globalPos() ), e->globalPos() );
00883         e->consume(); // Consume the event to avoid multiple contextMenuEvent calls...
00884     }
00885 }
00886 
00887 void KURLBarListBox::setOrientation( Qt::Orientation orient )
00888 {
00889     if ( orient == Vertical ) {
00890         setColumnMode( 1 );
00891         setRowMode( Variable );
00892     }
00893     else {
00894         setRowMode( 1 );
00895         setColumnMode( Variable );
00896     }
00897 
00898     m_orientation = orient;
00899 }
00900 
00903 
00904 
00905 bool KURLBarItemDialog::getInformation( bool allowGlobal, KURL& url,
00906                                         QString& description, QString& icon,
00907                                         bool& appLocal, int iconSize,
00908                                         QWidget *parent )
00909 {
00910     KURLBarItemDialog *dialog = new KURLBarItemDialog( allowGlobal, url,
00911                                                        description, icon,
00912                                                        appLocal,
00913                                                        iconSize, parent );
00914     if ( dialog->exec() == QDialog::Accepted ) {
00915         // set the return parameters
00916         url         = dialog->url();
00917         description = dialog->description();
00918         icon        = dialog->icon();
00919         appLocal    = dialog->applicationLocal();
00920 
00921         delete dialog;
00922         return true;
00923     }
00924 
00925     delete dialog;
00926     return false;
00927 }
00928 
00929 KURLBarItemDialog::KURLBarItemDialog( bool allowGlobal, const KURL& url,
00930                                       const QString& description,
00931                                       QString icon, bool appLocal,
00932                                       int iconSize,
00933                                       QWidget *parent, const char *name )
00934     : KDialogBase( parent, name, true,
00935                    i18n("Edit Quick Access Entry"), Ok | Cancel, Ok, true )
00936 {
00937     QVBox *box = new QVBox( this );
00938     QString text = i18n("<qt><b>Please provide a description, URL and icon for this Quick Access entry.</b></br></qt>");
00939     QLabel *label = new QLabel( text, box );
00940     box->setSpacing( spacingHint() );
00941 
00942     QGrid *grid = new QGrid( 2, box );
00943     grid->setSpacing( spacingHint() );
00944 
00945     QString whatsThisText = i18n("<qt>This is the text that will appear in the Quick Access panel.<p>"
00946                                  "The description should consist of one or two words "
00947                                  "that will help you remember what this entry refers to.</qt>");
00948     label = new QLabel( i18n("&Description:"), grid );
00949     m_edit = new KLineEdit( grid, "description edit" );
00950     m_edit->setText( description.isEmpty() ? url.fileName() : description );
00951     label->setBuddy( m_edit );
00952     QWhatsThis::add( label, whatsThisText );
00953     QWhatsThis::add( m_edit, whatsThisText );
00954 
00955     whatsThisText = i18n("<qt>This is the location associated with the entry. Any valid URL may be used. For example:<p>"
00956                          "%1<br>http://www.kde.org<br>ftp://ftp.kde.org/pub/kde/stable<p>"
00957                          "By clicking on the button next to the text edit box you can browse to an "
00958                          "appropriate URL.</qt>").arg(QDir::homeDirPath());
00959     label = new QLabel( i18n("&URL:"), grid );
00960     m_urlEdit = new KURLRequester( url.prettyURL(), grid );
00961     m_urlEdit->setMode( KFile::Directory );
00962     label->setBuddy( m_urlEdit );
00963     QWhatsThis::add( label, whatsThisText );
00964     QWhatsThis::add( m_urlEdit, whatsThisText );
00965 
00966     whatsThisText = i18n("<qt>This is the icon that will appear in the Quick Access panel.<p>"
00967                          "Click on the button to select a different icon.</qt>");
00968     label = new QLabel( i18n("Choose an &icon:"), grid );
00969     m_iconButton = new KIconButton( grid, "icon button" );
00970     m_iconButton->setIconSize( iconSize );
00971     if ( icon.isEmpty() )
00972         icon = KMimeType::iconForURL( url );
00973     m_iconButton->setIcon( icon );
00974     label->setBuddy( m_iconButton );
00975     QWhatsThis::add( label, whatsThisText );
00976     QWhatsThis::add( m_iconButton, whatsThisText );
00977 
00978     if ( allowGlobal ) {
00979         QString appName;
00980         if ( KGlobal::instance()->aboutData() )
00981             appName = KGlobal::instance()->aboutData()->programName();
00982         if ( appName.isEmpty() )
00983             appName = QString::fromLatin1( KGlobal::instance()->instanceName() );
00984         m_appLocal = new QCheckBox( i18n("&Only show when using this application (%1)").arg( appName ), box );
00985         m_appLocal->setChecked( appLocal );
00986         QWhatsThis::add( m_appLocal,
00987                          i18n("<qt>Select this setting if you want this "
00988                               "entry to show only when using the current application (%1).<p>"
00989                               "If this setting is not selected, the entry will be available in all "
00990                               "applications.</qt>")
00991                               .arg(appName));
00992     }
00993     else
00994         m_appLocal = 0L;
00995     connect(m_urlEdit->lineEdit(),SIGNAL(textChanged ( const QString & )),this,SLOT(urlChanged(const QString & )));
00996     m_edit->setFocus();
00997     setMainWidget( box );
00998 }
00999 
01000 KURLBarItemDialog::~KURLBarItemDialog()
01001 {
01002 }
01003 
01004 void KURLBarItemDialog::urlChanged(const QString & text )
01005 {
01006     enableButtonOK( !text.isEmpty() );
01007 }
01008 
01009 KURL KURLBarItemDialog::url() const
01010 {
01011     QString text = m_urlEdit->url();
01012     KURL u;
01013     if ( text.at(0) == '/' )
01014         u.setPath( text );
01015     else
01016         u = text;
01017 
01018     return u;
01019 }
01020 
01021 QString KURLBarItemDialog::description() const
01022 {
01023     return m_edit->text();
01024 }
01025 
01026 QString KURLBarItemDialog::icon() const
01027 {
01028     return m_iconButton->icon();
01029 }
01030 
01031 bool KURLBarItemDialog::applicationLocal() const
01032 {
01033     if ( !m_appLocal )
01034         return true;
01035 
01036     return m_appLocal->isChecked();
01037 }
01038 
01039 void KURLBarItem::virtual_hook( int, void* )
01040 { /*BASE::virtual_hook( id, data );*/ }
01041 
01042 void KURLBar::virtual_hook( int, void* )
01043 { /*BASE::virtual_hook( id, data );*/ }
01044 
01045 void KURLBarListBox::virtual_hook( int id, void* data )
01046 { KListBox::virtual_hook( id, data ); }
01047 
01048 
01049 #include "kurlbar.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys