00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
#include "config.h"
00020
00021
#include <qtimer.h>
00022
#include <qpainter.h>
00023
#include <qpixmapcache.h>
00024
#include <qcleanuphandler.h>
00025
00026
#include "kiconview.h"
00027
#include "kwordwrap.h"
00028
#include <kconfig.h>
00029
#include <kdebug.h>
00030
#include <kglobal.h>
00031
#include <kglobalsettings.h>
00032
#include <kapplication.h>
00033
00034
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00035
#include <kipc.h>
00036
#endif
00037
00038
#include <kcursor.h>
00039
#include <kpixmap.h>
00040
#include <kpixmapeffect.h>
00041
00042
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00043
#include <X11/Xlib.h>
00044
#endif
00045
00046
class KIconView::KIconViewPrivate
00047 {
00048
public:
00049 KIconViewPrivate() {
00050 mode = KIconView::Execute;
00051 fm = 0L;
00052 doAutoSelect =
true;
00053 }
00054
KIconView::Mode mode;
00055
bool doAutoSelect;
00056
QFontMetrics *fm;
00057
QPixmapCache maskCache;
00058 };
00059
00060 KIconView::KIconView(
QWidget *parent,
const char *name, WFlags f )
00061 :
QIconView( parent,
name, f )
00062 {
00063 d =
new KIconViewPrivate;
00064
00065
connect(
this, SIGNAL( onViewport() ),
00066
this, SLOT( slotOnViewport() ) );
00067
connect(
this, SIGNAL( onItem(
QIconViewItem * ) ),
00068
this, SLOT( slotOnItem(
QIconViewItem * ) ) );
00069 slotSettingsChanged( KApplication::SETTINGS_MOUSE );
00070
if ( kapp ) {
00071
connect( kapp, SIGNAL( settingsChanged(
int) ), SLOT( slotSettingsChanged(
int) ) );
00072
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00073
kapp->addKipcEventMask( KIPC::SettingsChanged );
00074
#endif
00075
}
00076
00077 m_pCurrentItem = 0L;
00078
00079 m_pAutoSelect =
new QTimer(
this );
00080
connect( m_pAutoSelect, SIGNAL( timeout() ),
00081
this, SLOT( slotAutoSelect() ) );
00082 }
00083
00084 KIconView::~KIconView()
00085 {
00086
delete d->fm;
00087
delete d;
00088 }
00089
00090
00091 void KIconView::setMode( KIconView::Mode mode )
00092 {
00093 d->mode = mode;
00094 }
00095
00096 KIconView::Mode
KIconView::mode()
const
00097
{
00098
return d->mode;
00099 }
00100
00101
void KIconView::slotOnItem(
QIconViewItem *item )
00102 {
00103
if ( item ) {
00104
if ( m_bUseSingle ) {
00105
if ( m_bChangeCursorOverItem )
00106 viewport()->setCursor(
KCursor().handCursor() );
00107
00108
if ( (m_autoSelectDelay > -1) ) {
00109 m_pAutoSelect->
start( m_autoSelectDelay,
true );
00110 }
00111 }
00112 m_pCurrentItem = item;
00113 }
00114 }
00115
00116
void KIconView::slotOnViewport()
00117 {
00118
if ( m_bUseSingle && m_bChangeCursorOverItem )
00119 viewport()->unsetCursor();
00120
00121 m_pAutoSelect->
stop();
00122 m_pCurrentItem = 0L;
00123 }
00124
00125
void KIconView::slotSettingsChanged(
int category)
00126 {
00127
if ( category != KApplication::SETTINGS_MOUSE )
00128
return;
00129 m_bUseSingle =
KGlobalSettings::singleClick();
00130
00131
00132 disconnect(
this, SIGNAL(
mouseButtonClicked(
int,
QIconViewItem *,
00133
const QPoint & ) ),
00134
this, SLOT( slotMouseButtonClicked(
int,
QIconViewItem *,
00135
const QPoint & ) ) );
00136
00137
00138
00139
00140
00141
if( m_bUseSingle ) {
00142 connect(
this, SIGNAL(
mouseButtonClicked(
int,
QIconViewItem *,
00143
const QPoint & ) ),
00144
this, SLOT( slotMouseButtonClicked(
int,
QIconViewItem *,
00145
const QPoint & ) ) );
00146 }
00147
else {
00148
00149
00150
00151
00152 }
00153
00154 m_bChangeCursorOverItem =
KGlobalSettings::changeCursorOverIcon();
00155 m_autoSelectDelay = m_bUseSingle ?
KGlobalSettings::autoSelectDelay() : -1;
00156
00157
if( !m_bUseSingle || !m_bChangeCursorOverItem )
00158 viewport()->unsetCursor();
00159 }
00160
00161 void KIconView::slotAutoSelect()
00162 {
00163
00164
if(
index( m_pCurrentItem ) == -1 || !d->doAutoSelect )
00165
return;
00166
00167
00168
if( !hasFocus() )
00169 setFocus();
00170
00171
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00172
00173 Window root;
00174 Window child;
00175
int root_x, root_y, win_x, win_y;
00176 uint keybstate;
00177 XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
00178 &root_x, &root_y, &win_x, &win_y, &keybstate );
00179
00180
QIconViewItem* previousItem =
currentItem();
00181
#endif
00182
setCurrentItem( m_pCurrentItem );
00183
00184
if( m_pCurrentItem ) {
00185
00186
#if defined Q_WS_X11 && ! defined K_WS_QTONLY //FIXME
00187
if( (keybstate & ShiftMask) ) {
00188
00189
bool block = signalsBlocked();
00190 blockSignals(
true );
00191
00192
00193
if( !(keybstate & ControlMask) )
00194
clearSelection();
00195
00196
bool select = !m_pCurrentItem->
isSelected();
00197
bool update = viewport()->isUpdatesEnabled();
00198 viewport()->setUpdatesEnabled(
false );
00199
00200
00201
00202
QRect r;
00203
QRect redraw;
00204
if ( previousItem )
00205 r =
QRect( QMIN( previousItem->
x(), m_pCurrentItem->
x() ),
00206 QMIN( previousItem->
y(), m_pCurrentItem->
y() ),
00207 0, 0 );
00208
else
00209 r =
QRect( 0, 0, 0, 0 );
00210
if ( previousItem->
x() < m_pCurrentItem->
x() )
00211 r.
setWidth( m_pCurrentItem->
x() - previousItem->
x() + m_pCurrentItem->
width() );
00212
else
00213 r.
setWidth( previousItem->
x() - m_pCurrentItem->
x() + previousItem->
width() );
00214
if ( previousItem->
y() < m_pCurrentItem->
y() )
00215 r.
setHeight( m_pCurrentItem->
y() - previousItem->
y() + m_pCurrentItem->
height() );
00216
else
00217 r.
setHeight( previousItem->
y() - m_pCurrentItem->
y() + previousItem->
height() );
00218 r = r.
normalize();
00219
00220
00221
00222
for(
QIconViewItem* i =
firstItem(); i; i = i->
nextItem() ) {
00223
if( i->
intersects( r ) ) {
00224 redraw = redraw.
unite( i->
rect() );
00225
setSelected( i, select,
true );
00226 }
00227 }
00228
00229 blockSignals( block );
00230 viewport()->setUpdatesEnabled( update );
00231 repaintContents( redraw,
false );
00232
00233 emit
selectionChanged();
00234
00235
if(
selectionMode() == QIconView::Single )
00236 emit
selectionChanged( m_pCurrentItem );
00237
00238
00239 }
00240
else if( (keybstate & ControlMask) )
00241
setSelected( m_pCurrentItem, !m_pCurrentItem->
isSelected(),
true );
00242
else
00243
#endif
00244
setSelected( m_pCurrentItem,
true );
00245 }
00246
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00247
00248
else
00249
kdDebug() <<
"KIconView: That's not supposed to happen!!!!" <<
endl;
00250
#endif
00251
}
00252
00253
void KIconView::emitExecute(
QIconViewItem *item,
const QPoint &pos )
00254 {
00255
if ( d->mode != Execute )
00256 {
00257
00258
return;
00259 }
00260
00261
#if defined Q_WS_X11 && ! defined K_WS_QTONLY //FIXME
00262
Window root;
00263 Window child;
00264
int root_x, root_y, win_x, win_y;
00265 uint keybstate;
00266 XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
00267 &root_x, &root_y, &win_x, &win_y, &keybstate );
00268
#endif
00269
00270 m_pAutoSelect->
stop();
00271
00272
00273
#if defined Q_WS_X11 && ! defined K_WS_QTONLY //FIXME
00274
if( !( m_bUseSingle && ((keybstate & ShiftMask) || (keybstate & ControlMask)) ) ) {
00275
setSelected( item,
false );
00276 emit
executed( item );
00277 emit
executed( item, pos );
00278 }
00279
#endif
00280
}
00281
00282
void KIconView::focusOutEvent(
QFocusEvent *fe )
00283 {
00284 m_pAutoSelect->
stop();
00285
00286 QIconView::focusOutEvent( fe );
00287 }
00288
00289
void KIconView::leaveEvent(
QEvent *e )
00290 {
00291 m_pAutoSelect->
stop();
00292
00293 QIconView::leaveEvent( e );
00294 }
00295
00296
void KIconView::contentsMousePressEvent(
QMouseEvent *e )
00297 {
00298
if( (
selectionMode() == Extended) && (e->
state() & ShiftButton) && !(e->
state() & ControlButton) ) {
00299
bool block = signalsBlocked();
00300 blockSignals(
true );
00301
00302
clearSelection();
00303
00304 blockSignals( block );
00305 }
00306
00307 QIconView::contentsMousePressEvent( e );
00308 d->doAutoSelect =
false;
00309 }
00310
00311
void KIconView::contentsMouseDoubleClickEvent (
QMouseEvent * e )
00312 {
00313 QIconView::contentsMouseDoubleClickEvent( e );
00314
00315
QIconViewItem* item =
findItem( e->
pos() );
00316
00317
if( item ) {
00318
if( (e->
button() == LeftButton) && !m_bUseSingle )
00319 emitExecute( item, e->
globalPos() );
00320
00321 emit
doubleClicked( item, e->
globalPos() );
00322 }
00323 }
00324
00325
void KIconView::slotMouseButtonClicked(
int btn,
QIconViewItem *item,
const QPoint &pos )
00326 {
00327
00328
if( (btn == LeftButton) && item )
00329 emitExecute( item, pos );
00330 }
00331
00332
void KIconView::contentsMouseReleaseEvent(
QMouseEvent *e )
00333 {
00334 d->doAutoSelect =
true;
00335 QIconView::contentsMouseReleaseEvent( e );
00336 }
00337
00338 void KIconView::setFont(
const QFont &font )
00339 {
00340
delete d->fm;
00341 d->fm = 0L;
00342 QIconView::setFont( font );
00343 }
00344
00345
QFontMetrics *KIconView::itemFontMetrics()
const
00346
{
00347
if (!d->fm) {
00348
00349 d->fm =
new QFontMetrics( font() );
00350 }
00351
return d->fm;
00352 }
00353
00354
QPixmap KIconView::selectedIconPixmap(
QPixmap *pix,
const QColor &col )
const
00355
{
00356
QPixmap m;
00357
if ( d->maskCache.find( QString::number( pix->
serialNumber() ), m ) )
00358
return m;
00359 m =
KPixmapEffect::selectedPixmap(
KPixmap(*pix), col );
00360 d->maskCache.insert( QString::number( pix->
serialNumber() ), m );
00361
return m;
00362 }
00363
00365
00366
struct KIconViewItem::KIconViewItemPrivate
00367 {
00368 };
00369
00370
void KIconViewItem::init()
00371 {
00372 m_wordWrap = 0L;
00373 d = 0L;
00374
00375
if (
iconView() &&
iconView()->wordWrapIconText() )
00376
calcRect();
00377 }
00378
00379 KIconViewItem::~KIconViewItem()
00380 {
00381
delete m_wordWrap;
00382
delete d;
00383 }
00384
00385
void KIconViewItem::calcRect(
const QString& text_ )
00386 {
00387 Q_ASSERT(
iconView() );
00388
if ( !
iconView() )
00389
return;
00390
delete m_wordWrap;
00391 m_wordWrap = 0L;
00392
00393
if ( !
iconView()->wordWrapIconText() )
00394 {
00395
QIconViewItem::calcRect( text_ );
00396
return;
00397 }
00398
#ifndef NDEBUG // be faster for the end-user, such a bug will have been fixed before hand :)
00399
if ( !
iconView()->inherits(
"KIconView") )
00400 {
00401
kdWarning() <<
"KIconViewItem used in a " <<
iconView()->className() <<
" !!" <<
endl;
00402
return;
00403 }
00404
#endif
00405
00406
KIconView *view = static_cast<KIconView *>(
iconView());
00407
QRect itemIconRect =
pixmapRect();
00408
QRect itemTextRect =
textRect();
00409
QRect itemRect =
rect();
00410
00411
int pw = 0;
00412
int ph = 0;
00413
00414
#ifndef QT_NO_PICTURE
00415
if (
picture() ) {
00416
QRect br =
picture()->boundingRect();
00417 pw = br.
width() + 2;
00418 ph = br.
height() + 2;
00419 }
else
00420
#endif
00421
{
00422
00423
if (!
pixmap())
00424
return;
00425 pw =
pixmap()->width() + 2;
00426 ph =
pixmap()->height() + 2;
00427 }
00428 itemIconRect.
setWidth( pw );
00429 itemIconRect.
setHeight( ph );
00430
00431
00432
00433
00434
QString t = text_.
isEmpty() ?
text() : text_;
00435
00436
int tw = 0;
00437
int th = 0;
00438
QFontMetrics *fm = view->
itemFontMetrics();
00439
QRect outerRect( 0, 0, view->
maxItemWidth() -
00440 ( view->
itemTextPos() == QIconView::Bottom ? 0 :
00441
pixmapRect().width() ), 0xFFFFFFFF );
00442
00443 m_wordWrap =
KWordWrap::formatText( *fm, outerRect, AlignHCenter | WordBreak , t );
00444
QRect r = m_wordWrap->
boundingRect();
00445 r.
setWidth( r.
width() + 4 );
00446
00447
00448
if ( r.
width() > view->
maxItemWidth() -
00449 ( view->
itemTextPos() == QIconView::Bottom ? 0 :
00450
pixmapRect().width() ) )
00451 r.
setWidth( view->
maxItemWidth() - ( view->
itemTextPos() == QIconView::Bottom ? 0 :
00452
pixmapRect().width() ) );
00453
00454 tw = r.
width();
00455 th = r.
height();
00456
int minw = fm->
width(
"X" );
00457
if ( tw < minw )
00458 tw = minw;
00459
00460 itemTextRect.
setWidth( tw );
00461 itemTextRect.
setHeight( th );
00462
00463
00464
00465
00466
00467
int w = 0;
int h = 0;
00468
if ( view->
itemTextPos() == QIconView::Bottom ) {
00469 w = QMAX( itemTextRect.
width(), itemIconRect.
width() );
00470 h = itemTextRect.
height() + itemIconRect.
height() + 1;
00471
00472 itemRect.
setWidth( w );
00473 itemRect.
setHeight( h );
00474
int width = QMAX( w, QApplication::globalStrut().
width() );
00475
int height = QMAX( h, QApplication::globalStrut().
height() );
00476 itemTextRect =
QRect( ( width - itemTextRect.
width() ) / 2, height - itemTextRect.
height(),
00477 itemTextRect.
width(), itemTextRect.
height() );
00478 itemIconRect =
QRect( ( width - itemIconRect.
width() ) / 2, 0,
00479 itemIconRect.
width(), itemIconRect.
height() );
00480 }
else {
00481 h = QMAX( itemTextRect.
height(), itemIconRect.
height() );
00482 w = itemTextRect.
width() + itemIconRect.
width() + 1;
00483
00484 itemRect.
setWidth( w );
00485 itemRect.
setHeight( h );
00486
int width = QMAX( w, QApplication::globalStrut().
width() );
00487
int height = QMAX( h, QApplication::globalStrut().
height() );
00488
00489 itemTextRect =
QRect( width - itemTextRect.
width(), ( height - itemTextRect.
height() ) / 2,
00490 itemTextRect.
width(), itemTextRect.
height() );
00491
if ( itemIconRect.
height() > itemTextRect.
height() )
00492 itemIconRect =
QRect( 0, ( height - itemIconRect.
height() ) / 2,
00493 itemIconRect.
width(), itemIconRect.
height() );
00494
else
00495 itemIconRect =
QRect( 0, QMAX(( fm->
height() - itemIconRect.
height() ) / 2, 0),
00496 itemIconRect.
width(), itemIconRect.
height() );
00497 }
00498
#if 0
00499
kdDebug() <<
"KIconViewItem::calcRect itemIconRect=" << itemIconRect.
x() <<
"," << itemIconRect.
y()
00500 <<
" " << itemIconRect.
width() <<
"x" << itemIconRect.
height() <<
endl;
00501
kdDebug() <<
"KIconViewItem::calcRect itemTextRect=" << itemTextRect.
x() <<
"," << itemTextRect.
y()
00502 <<
" " << itemTextRect.
width() <<
"x" << itemTextRect.
height() <<
endl;
00503
kdDebug() <<
"KIconViewItem::calcRect itemRect=" << itemRect.
x() <<
"," << itemRect.
y()
00504 <<
" " << itemRect.
width() <<
"x" << itemRect.
height() <<
endl;
00505
kdDebug() <<
"KIconViewItem::calcRect - DONE" <<
endl;
00506
#endif
00507
00508
if ( itemIconRect !=
pixmapRect() )
00509
setPixmapRect( itemIconRect );
00510
if ( itemTextRect !=
textRect() )
00511
setTextRect( itemTextRect );
00512
if ( itemRect !=
rect() )
00513
setItemRect( itemRect );
00514
00515
00516
00517
00518 }
00519
00520
void KIconViewItem::paintItem(
QPainter *p,
const QColorGroup &cg )
00521 {
00522
QIconView* view =
iconView();
00523 Q_ASSERT( view );
00524
if ( !view )
00525
return;
00526
00527
00528
00529
00530
if ( !view->
wordWrapIconText() )
00531 {
00532
QIconViewItem::paintItem( p, cg );
00533
return;
00534 }
00535
#ifndef NDEBUG // be faster for the end-user, such a bug will have been fixed before hand :)
00536
if ( !view->inherits(
"KIconView") )
00537 {
00538
kdWarning() <<
"KIconViewItem used in a " << view->className() <<
" !!" <<
endl;
00539
return;
00540 }
00541
#endif
00542
if ( !m_wordWrap )
00543 {
00544
kdWarning() <<
"KIconViewItem::paintItem called but wordwrap not ready - calcRect not called, or aborted!" <<
endl;
00545
return;
00546 }
00547
00548 p->
save();
00549
00550 paintPixmap(p, cg);
00551 paintText(p, cg);
00552
00553 p->
restore();
00554 }
00555
00556
KWordWrap * KIconViewItem::wordWrap()
00557 {
00558
return m_wordWrap;
00559 }
00560
00561
void KIconViewItem::paintPixmap(
QPainter *p,
const QColorGroup &cg )
00562 {
00563
KIconView *kview = static_cast<KIconView *>(
iconView());
00564
int iconX =
pixmapRect(
false ).x();
00565
int iconY =
pixmapRect(
false ).y();
00566
00567
#ifndef QT_NO_PICTURE
00568
if (
picture() ) {
00569
QPicture *pic =
picture();
00570
if (
isSelected() ) {
00571
00572 p->
fillRect(
pixmapRect(
false ),
QBrush( cg.
highlight(), QBrush::Dense4Pattern) );
00573 }
00574 p->
drawPicture(
x()-pic->
boundingRect().x(),
y()-pic->
boundingRect().y(), *pic );
00575 }
else
00576
#endif
00577
{
00578
QPixmap *pix =
pixmap();
00579
if (
isSelected() ) {
00580
if ( pix && !pix->
isNull() ) {
00581
QPixmap selectedPix = kview->
selectedIconPixmap( pix, cg.
highlight() );
00582 p->
drawPixmap( iconX, iconY, selectedPix );
00583 }
00584 }
else {
00585 p->
drawPixmap( iconX, iconY, *pix );
00586 }
00587 }
00588 }
00589
00590
void KIconViewItem::paintText(
QPainter *p,
const QColorGroup &cg )
00591 {
00592
int textX =
textRect(
false ).x();
00593
int textY =
textRect(
false ).y();
00594
00595
if (
isSelected() ) {
00596 p->
fillRect(
textRect(
false ), cg.
highlight() );
00597 p->
setPen(
QPen( cg.
highlightedText() ) );
00598 }
else {
00599
if (
iconView()->itemTextBackground() != NoBrush )
00600 p->
fillRect(
textRect(
false ),
iconView()->itemTextBackground() );
00601 p->
setPen( cg.
text() );
00602 }
00603
00604
int align =
iconView()->itemTextPos() == QIconView::Bottom ? AlignHCenter : AlignAuto;
00605 m_wordWrap->
drawText( p, textX, textY, align );
00606 }
00607
00608
void KIconView::virtual_hook(
int,
void* )
00609 { }
00610
00611
#include "kiconview.moc"