/* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2004-11-22 * Description : a bar widget to display image thumbnails * * Copyright (C) 2004-2005 by Renchi Raju * Copyright (C) 2005-2008 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program 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 General Public License for more details. * * ============================================================ */ // C Ansi includes. extern "C" { #include } // C++ includes. #include // TQt includes. #include #include #include #include #include #include #include #include #include #include // KDE includes. #include #include #include #include #include #include #include #include // LibKDcraw includes. #include #include #if KDCRAW_VERSION < 0x000106 #include #endif // Local includes. #include "dmetadata.h" #include "thumbnailjob.h" #include "thumbnailsize.h" #include "thumbbar.h" #include "thumbbar.moc" namespace Digikam { class ThumbBarViewPriv { public: ThumbBarViewPriv() : margin(5) { dragging = false; exifRotate = false; clearing = false; toolTip = 0; firstItem = 0; lastItem = 0; currItem = 0; count = 0; thumbJob = 0; tileSize = ThumbnailSize::Small; itemDict.setAutoDelete(false); } bool clearing; bool exifRotate; bool dragging; const int margin; int count; int tileSize; int orientation; TQTimer *timer; TQPoint dragStartPos; ThumbBarItem *firstItem; ThumbBarItem *lastItem; ThumbBarItem *currItem; TQDict itemDict; TQGuardedPtr thumbJob; ThumbBarToolTipSettings toolTipSettings; ThumbBarToolTip *toolTip; }; // ------------------------------------------------------------------------- class ThumbBarItemPriv { public: ThumbBarItemPriv() { pos = 0; pixmap = 0; next = 0; prev = 0; view = 0; } int pos; TQPixmap *pixmap; KURL url; ThumbBarItem *next; ThumbBarItem *prev; ThumbBarView *view; }; // ------------------------------------------------------------------------- ThumbBarView::ThumbBarView(TQWidget* parent, int orientation, bool exifRotate, ThumbBarToolTipSettings settings) : TQScrollView(parent) { d = new ThumbBarViewPriv; d->orientation = orientation; d->exifRotate = exifRotate; d->toolTipSettings = settings; d->toolTip = new ThumbBarToolTip(this); d->timer = new TQTimer(this); connect(d->timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotUpdate())); viewport()->setBackgroundMode(TQt::NoBackground); viewport()->setMouseTracking(true); viewport()->setAcceptDrops(true); setFrameStyle(TQFrame::NoFrame); setAcceptDrops(true); if (d->orientation ==Qt::Vertical) { setHScrollBarMode(TQScrollView::AlwaysOff); } else { setVScrollBarMode(TQScrollView::AlwaysOff); } } ThumbBarView::~ThumbBarView() { if (!d->thumbJob.isNull()) { d->thumbJob->kill(); d->thumbJob = 0; } clear(false); delete d->timer; delete d->toolTip; delete d; } void ThumbBarView::resizeEvent(TQResizeEvent* e) { if (!e) return; TQScrollView::resizeEvent(e); if (d->orientation ==Qt::Vertical) { d->tileSize = width() - 2*d->margin - verticalScrollBar()->sizeHint().width(); verticalScrollBar()->setLineStep(d->tileSize); verticalScrollBar()->setPageStep(2*d->tileSize); } else { d->tileSize = height() - 2*d->margin - horizontalScrollBar()->sizeHint().height(); horizontalScrollBar()->setLineStep(d->tileSize); horizontalScrollBar()->setPageStep(2*d->tileSize); } rearrangeItems(); ensureItemVisible(currentItem()); } void ThumbBarView::setExifRotate(bool exifRotate) { if (d->exifRotate == exifRotate) return; d->exifRotate = exifRotate; TQString thumbCacheDir = TQDir::homeDirPath() + "/.thumbnails/"; for (ThumbBarItem *item = d->firstItem; item; item = item->d->next) { // Remove all current album item thumbs from disk cache. TQString uri = "file://" + TQDir::cleanDirPath(item->url().path(-1)); KMD5 md5(TQFile::encodeName(uri).data()); uri = md5.hexDigest(); TQString smallThumbPath = thumbCacheDir + "normal/" + uri + ".png"; TQString bigThumbPath = thumbCacheDir + "large/" + uri + ".png"; ::unlink(TQFile::encodeName(smallThumbPath)); ::unlink(TQFile::encodeName(bigThumbPath)); invalidateThumb(item); } triggerUpdate(); } bool ThumbBarView::getExifRotate() { return d->exifRotate; } int ThumbBarView::getOrientation() { return d->orientation; } int ThumbBarView::getTileSize() { return d->tileSize; } int ThumbBarView::getMargin() { return d->margin; } void ThumbBarView::setToolTipSettings(const ThumbBarToolTipSettings &settings) { d->toolTipSettings = settings; } ThumbBarToolTipSettings& ThumbBarView::getToolTipSettings() { return d->toolTipSettings; } int ThumbBarView::countItems() { return d->count; } KURL::List ThumbBarView::itemsURLs() { KURL::List urlList; if (!countItems()) return urlList; for (ThumbBarItem *item = firstItem(); item; item = item->next()) urlList.append(item->url()); return urlList; } void ThumbBarView::clear(bool updateView) { d->clearing = true; ThumbBarItem *item = d->firstItem; while (item) { ThumbBarItem *tmp = item->d->next; delete item; item = tmp; } d->firstItem = 0; d->lastItem = 0; d->count = 0; d->currItem = 0; if (updateView) slotUpdate(); d->clearing = false; emit signalItemSelected(0); } void ThumbBarView::triggerUpdate() { d->timer->start(0, true); } ThumbBarItem* ThumbBarView::currentItem() const { return d->currItem; } ThumbBarItem* ThumbBarView::firstItem() const { return d->firstItem; } ThumbBarItem* ThumbBarView::lastItem() const { return d->lastItem; } ThumbBarItem* ThumbBarView::findItem(const TQPoint& pos) const { int itemPos; if (d->orientation ==Qt::Vertical) itemPos = pos.y(); else itemPos = pos.x(); for (ThumbBarItem *item = d->firstItem; item; item = item->d->next) { if (itemPos >= item->d->pos && itemPos <= (item->d->pos+d->tileSize+2*d->margin)) { return item; } } return 0; } ThumbBarItem* ThumbBarView::findItemByURL(const KURL& url) const { for (ThumbBarItem *item = d->firstItem; item; item = item->d->next) { if (item->url().equals(url)) { return item; } } return 0; } void ThumbBarView::setSelected(ThumbBarItem* item) { if (!item) return; ensureItemVisible(item); emit signalURLSelected(item->url()); emit signalItemSelected(item); if (d->currItem == item) return; if (d->currItem) { ThumbBarItem* item = d->currItem; d->currItem = 0; item->repaint(); } d->currItem = item; if (d->currItem) item->repaint(); } void ThumbBarView::ensureItemVisible(ThumbBarItem* item) { if (item) { // We want the complete thumb visible and the next one. // find the middle of the image and give a margin of 1,5 image // When changed, watch regression for bug 104031 if (d->orientation ==Qt::Vertical) ensureVisible(0, (int)(item->d->pos + d->margin + d->tileSize*.5), 0, (int)(d->tileSize*1.5 + 3*d->margin)); else ensureVisible((int)(item->d->pos + d->margin + d->tileSize*.5), 0, (int)(d->tileSize*1.5 + 3*d->margin), 0); } } void ThumbBarView::refreshThumbs(const KURL::List& urls) { for (KURL::List::const_iterator it = urls.begin() ; it != urls.end() ; ++it) { ThumbBarItem *item = findItemByURL(*it); if (item) { invalidateThumb(item); } } } void ThumbBarView::invalidateThumb(ThumbBarItem* item) { if (!item) return; if (item->d->pixmap) { delete item->d->pixmap; item->d->pixmap = 0; } if (!d->thumbJob.isNull()) { d->thumbJob->kill(); d->thumbJob = 0; } d->thumbJob = new ThumbnailJob(item->url(), ThumbnailSize::Huge, true, d->exifRotate); connect(d->thumbJob, TQT_SIGNAL(signalThumbnail(const KURL&, const TQPixmap&)), this, TQT_SLOT(slotGotThumbnail(const KURL&, const TQPixmap&))); connect(d->thumbJob, TQT_SIGNAL(signalFailed(const KURL&)), this, TQT_SLOT(slotFailedThumbnail(const KURL&))); } void ThumbBarView::viewportPaintEvent(TQPaintEvent* e) { int cy, cx, ts, y1, y2, x1, x2; TQPixmap bgPix, tile; TQRect er(e->rect()); if (d->orientation ==Qt::Vertical) { cy = viewportToContents(er.topLeft()).y(); bgPix.resize(contentsRect().width(), er.height()); ts = d->tileSize + 2*d->margin; tile.resize(visibleWidth(), ts); y1 = (cy/ts)*ts; y2 = ((y1 + er.height())/ts +1)*ts; } else { cx = viewportToContents(er.topLeft()).x(); bgPix.resize(er.width(), contentsRect().height()); ts = d->tileSize + 2*d->margin; tile.resize(ts, visibleHeight()); x1 = (cx/ts)*ts; x2 = ((x1 + er.width())/ts +1)*ts; } bgPix.fill(colorGroup().background()); for (ThumbBarItem *item = d->firstItem; item; item = item->d->next) { if (d->orientation ==Qt::Vertical) { if (y1 <= item->d->pos && item->d->pos <= y2) { if (item == d->currItem) tile.fill(colorGroup().highlight()); else tile.fill(colorGroup().background()); TQPainter p(&tile); p.setPen(TQt::white); p.drawRect(0, 0, tile.width(), tile.height()); p.end(); if (item->d->pixmap) { TQPixmap pix; pix.convertFromImage(TQImage(item->d->pixmap->convertToImage()). smoothScale(d->tileSize, d->tileSize, TQ_ScaleMin)); int x = (tile.width() - pix.width())/2; int y = (tile.height() - pix.height())/2; bitBlt(&tile, x, y, &pix); } bitBlt(&bgPix, 0, item->d->pos - cy, &tile); } } else { if (x1 <= item->d->pos && item->d->pos <= x2) { if (item == d->currItem) tile.fill(colorGroup().highlight()); else tile.fill(colorGroup().background()); TQPainter p(&tile); p.setPen(TQt::white); p.drawRect(0, 0, tile.width(), tile.height()); p.end(); if (item->d->pixmap) { TQPixmap pix; pix.convertFromImage(TQImage(item->d->pixmap->convertToImage()). smoothScale(d->tileSize, d->tileSize, TQ_ScaleMin)); int x = (tile.width() - pix.width())/2; int y = (tile.height()- pix.height())/2; bitBlt(&tile, x, y, &pix); } bitBlt(&bgPix, item->d->pos - cx, 0, &tile); } } } if (d->orientation ==Qt::Vertical) bitBlt(viewport(), 0, er.y(), &bgPix); else bitBlt(viewport(), er.x(), 0, &bgPix); } void ThumbBarView::contentsMousePressEvent(TQMouseEvent* e) { ThumbBarItem* barItem = findItem(e->pos()); d->dragging = true; d->dragStartPos = e->pos(); if (!barItem || barItem == d->currItem) return; if (d->currItem) { ThumbBarItem* item = d->currItem; d->currItem = 0; item->repaint(); } d->currItem = barItem; barItem->repaint(); } void ThumbBarView::contentsMouseMoveEvent(TQMouseEvent *e) { if (!e) return; if (d->dragging && (e->state() & Qt::LeftButton)) { if ( findItem(d->dragStartPos) && (d->dragStartPos - e->pos()).manhattanLength() > TQApplication::startDragDistance() ) { startDrag(); } return; } } void ThumbBarView::contentsMouseReleaseEvent(TQMouseEvent *e) { d->dragging = false; ThumbBarItem *item = findItem(e->pos()); if (item) { emit signalURLSelected(item->url()); emit signalItemSelected(item); } } void ThumbBarView::contentsWheelEvent(TQWheelEvent *e) { e->accept(); if (e->delta() < 0) { if (e->state() & TQt::ShiftButton) { if (d->orientation ==Qt::Vertical) scrollBy(0, verticalScrollBar()->pageStep()); else scrollBy(horizontalScrollBar()->pageStep(), 0); } else { if (d->orientation ==Qt::Vertical) scrollBy(0, verticalScrollBar()->lineStep()); else scrollBy(horizontalScrollBar()->lineStep(), 0); } } if (e->delta() > 0) { if (e->state() & TQt::ShiftButton) { if (d->orientation ==Qt::Vertical) scrollBy(0, (-1)*verticalScrollBar()->pageStep()); else scrollBy((-1)*horizontalScrollBar()->pageStep(), 0); } else { if (d->orientation ==Qt::Vertical) scrollBy(0, (-1)*verticalScrollBar()->lineStep()); else scrollBy((-1)*horizontalScrollBar()->lineStep(), 0); } } } void ThumbBarView::startDrag() { } void ThumbBarView::insertItem(ThumbBarItem* item) { if (!item) return; if (!d->firstItem) { d->firstItem = item; d->lastItem = item; item->d->prev = 0; item->d->next = 0; } else { d->lastItem->d->next = item; item->d->prev = d->lastItem; item->d->next = 0; d->lastItem = item; } if (!d->currItem) { d->currItem = item; emit signalURLSelected(item->url()); emit signalItemSelected(item); } d->itemDict.insert(item->url().url(), item); d->count++; triggerUpdate(); emit signalItemAdded(); } void ThumbBarView::removeItem(ThumbBarItem* item) { if (!item) return; d->count--; if (item == d->firstItem) { d->firstItem = d->currItem = d->firstItem->d->next; if (d->firstItem) d->firstItem->d->prev = 0; else d->firstItem = d->lastItem = d->currItem = 0; } else if (item == d->lastItem) { d->lastItem = d->currItem = d->lastItem->d->prev; if ( d->lastItem ) d->lastItem->d->next = 0; else d->firstItem = d->lastItem = d->currItem = 0; } else { ThumbBarItem *i = item; if (i) { if (i->d->prev ) { i->d->prev->d->next = d->currItem = i->d->next; } if ( i->d->next ) { i->d->next->d->prev = d->currItem = i->d->prev; } } } d->itemDict.remove(item->url().url()); if (!d->clearing) { triggerUpdate(); } if (d->count == 0) emit signalItemSelected(0); } void ThumbBarView::rearrangeItems() { KURL::List urlList; int pos = 0; ThumbBarItem *item = d->firstItem; while (item) { item->d->pos = pos; pos += d->tileSize + 2*d->margin; if (!(item->d->pixmap)) urlList.append(item->d->url); item = item->d->next; } if (d->orientation ==Qt::Vertical) resizeContents(visibleWidth(), d->count*(d->tileSize+2*d->margin)); else resizeContents(d->count*(d->tileSize+2*d->margin), visibleHeight()); if (!urlList.isEmpty()) { if (!d->thumbJob.isNull()) { d->thumbJob->kill(); d->thumbJob = 0; } d->thumbJob = new ThumbnailJob(urlList, ThumbnailSize::Huge, true, d->exifRotate); connect(d->thumbJob, TQT_SIGNAL(signalThumbnail(const KURL&, const TQPixmap&)), this, TQT_SLOT(slotGotThumbnail(const KURL&, const TQPixmap&))); connect(d->thumbJob, TQT_SIGNAL(signalFailed(const KURL&)), this, TQT_SLOT(slotFailedThumbnail(const KURL&))); } } void ThumbBarView::repaintItem(ThumbBarItem* item) { if (item) { if (d->orientation ==Qt::Vertical) repaintContents(0, item->d->pos, visibleWidth(), d->tileSize+2*d->margin); else repaintContents(item->d->pos, 0, d->tileSize+2*d->margin, visibleHeight()); } } void ThumbBarView::slotUpdate() { rearrangeItems(); viewport()->update(); } void ThumbBarView::slotGotThumbnail(const KURL& url, const TQPixmap& pix) { if (!pix.isNull()) { ThumbBarItem* item = d->itemDict.find(url.url()); if (!item) return; if (item->d->pixmap) { delete item->d->pixmap; item->d->pixmap = 0; } item->d->pixmap = new TQPixmap(pix); item->repaint(); } } void ThumbBarView::slotFailedThumbnail(const KURL& url) { ThumbBarItem* item = d->itemDict.find(url.url()); if (!item) return; KIconLoader* iconLoader = TDEApplication::kApplication()->iconLoader(); TQPixmap pix = iconLoader->loadIcon("image", KIcon::NoGroup, ThumbnailSize::Huge); if (item->d->pixmap) { delete item->d->pixmap; item->d->pixmap = 0; } item->d->pixmap = new TQPixmap(pix); item->repaint(); } // ------------------------------------------------------------------------- ThumbBarItem::ThumbBarItem(ThumbBarView* view, const KURL& url) { d = new ThumbBarItemPriv; d->url = url; d->view = view; d->view->insertItem(this); } ThumbBarItem::~ThumbBarItem() { d->view->removeItem(this); if (d->pixmap) delete d->pixmap; delete d; } KURL ThumbBarItem::url() const { return d->url; } ThumbBarItem* ThumbBarItem::next() const { return d->next; } ThumbBarItem* ThumbBarItem::prev() const { return d->prev; } TQRect ThumbBarItem::rect() const { if (d->view->d->orientation == ThumbBarView::Vertical) { return TQRect(0, d->pos, d->view->visibleWidth(), d->view->d->tileSize + 2*d->view->d->margin); } else { return TQRect(d->pos, 0, d->view->d->tileSize + 2*d->view->d->margin, d->view->visibleHeight()); } } int ThumbBarItem::position() const { return d->pos; } TQPixmap* ThumbBarItem::pixmap() const { return d->pixmap; } void ThumbBarItem::repaint() { d->view->repaintItem(this); } // ------------------------------------------------------------------------- ThumbBarToolTip::ThumbBarToolTip(ThumbBarView* parent) : TQToolTip(parent->viewport()), m_maxStringLen(30), m_view(parent) { m_headBeg = TQString("" ""); m_headEnd = TQString(""); m_cellBeg = TQString(""); m_cellMid = TQString("" ""); m_cellEnd = TQString(""); m_cellSpecBeg = TQString(""); m_cellSpecMid = TQString("" ""); m_cellSpecEnd = TQString(""); } void ThumbBarToolTip::maybeTip(const TQPoint& pos) { if ( !parentWidget() || !m_view) return; ThumbBarItem* item = m_view->findItem( m_view->viewportToContents(pos) ); if (!item) return; if (!m_view->getToolTipSettings().showToolTips) return; TQString tipText = tipContent(item); tipText.append(tipContentExtraData(item)); tipText.append(""); TQRect r(item->rect()); r = TQRect( m_view->contentsToViewport(r.topLeft()), r.size() ); tip(r, tipText); } TQString ThumbBarToolTip::tipContent(ThumbBarItem* item) { ThumbBarToolTipSettings settings = m_view->getToolTipSettings(); TQString tipText, str; TQString unavailable(i18n("unavailable")); tipText = ""; TQFileInfo fileInfo(item->url().path()); KFileItem fi(KFileItem::Unknown, KFileItem::Unknown, item->url()); DMetadata metaData(item->url().path()); // -- File properties ---------------------------------------------- if (settings.showFileName || settings.showFileDate || settings.showFileSize || settings.showImageType || settings.showImageDim) { tipText += m_headBeg + i18n("File Properties") + m_headEnd; if (settings.showFileName) { tipText += m_cellBeg + i18n("Name:") + m_cellMid; tipText += item->url().fileName() + m_cellEnd; } if (settings.showFileDate) { TQDateTime modifiedDate = fileInfo.lastModified(); str = KGlobal::locale()->formatDateTime(modifiedDate, true, true); tipText += m_cellBeg + i18n("Modified:") + m_cellMid + str + m_cellEnd; } if (settings.showFileSize) { tipText += m_cellBeg + i18n("Size:") + m_cellMid; str = i18n("%1 (%2)").arg(KIO::convertSize(fi.size())) .arg(KGlobal::locale()->formatNumber(fi.size(), 0)); tipText += str + m_cellEnd; } TQSize dims; #if KDCRAW_VERSION < 0x000106 TQString rawFilesExt(KDcrawIface::DcrawBinary::instance()->rawFiles()); #else TQString rawFilesExt(KDcrawIface::KDcraw::rawFiles()); #endif TQString ext = fileInfo.extension(false).upper(); if (!ext.isEmpty() && rawFilesExt.upper().contains(ext)) { str = i18n("RAW Image"); dims = metaData.getImageDimensions(); } else { str = fi.mimeComment(); KFileMetaInfo meta = fi.metaInfo(); if (meta.isValid()) { if (meta.containsGroup("Jpeg EXIF Data")) dims = meta.group("Jpeg EXIF Data").item("Dimensions").value().toSize(); else if (meta.containsGroup("General")) dims = meta.group("General").item("Dimensions").value().toSize(); else if (meta.containsGroup("Technical")) dims = meta.group("Technical").item("Dimensions").value().toSize(); } } if (settings.showImageType) { tipText += m_cellBeg + i18n("Type:") + m_cellMid + str + m_cellEnd; } if (settings.showImageDim) { TQString mpixels; mpixels.setNum(dims.width()*dims.height()/1000000.0, 'f', 2); str = (!dims.isValid()) ? i18n("Unknown") : i18n("%1x%2 (%3Mpx)") .arg(dims.width()).arg(dims.height()).arg(mpixels); tipText += m_cellBeg + i18n("Dimensions:") + m_cellMid + str + m_cellEnd; } } // -- Photograph Info ---------------------------------------------------- if (settings.showPhotoMake || settings.showPhotoDate || settings.showPhotoFocal || settings.showPhotoExpo || settings.showPhotoMode || settings.showPhotoFlash || settings.showPhotoWB) { PhotoInfoContainer photoInfo = metaData.getPhotographInformations(); if (!photoInfo.isEmpty()) { TQString metaStr; tipText += m_headBeg + i18n("Photograph Properties") + m_headEnd; if (settings.showPhotoMake) { str = TQString("%1 / %2").arg(photoInfo.make.isEmpty() ? unavailable : photoInfo.make) .arg(photoInfo.model.isEmpty() ? unavailable : photoInfo.model); if (str.length() > m_maxStringLen) str = str.left(m_maxStringLen-3) + "..."; metaStr += m_cellBeg + i18n("Make/Model:") + m_cellMid + TQStyleSheet::escape( str ) + m_cellEnd; } if (settings.showPhotoDate) { if (photoInfo.dateTime.isValid()) { str = KGlobal::locale()->formatDateTime(photoInfo.dateTime, true, true); if (str.length() > m_maxStringLen) str = str.left(m_maxStringLen-3) + "..."; metaStr += m_cellBeg + i18n("Created:") + m_cellMid + TQStyleSheet::escape( str ) + m_cellEnd; } else metaStr += m_cellBeg + i18n("Created:") + m_cellMid + TQStyleSheet::escape( unavailable ) + m_cellEnd; } if (settings.showPhotoFocal) { str = photoInfo.aperture.isEmpty() ? unavailable : photoInfo.aperture; if (photoInfo.focalLength35mm.isEmpty()) str += TQString(" / %1").arg(photoInfo.focalLength.isEmpty() ? unavailable : photoInfo.focalLength); else str += TQString(" / %1").arg(i18n("%1 (35mm: %2)").arg(photoInfo.focalLength).arg(photoInfo.focalLength35mm)); if (str.length() > m_maxStringLen) str = str.left(m_maxStringLen-3) + "..."; metaStr += m_cellBeg + i18n("Aperture/Focal:") + m_cellMid + TQStyleSheet::escape( str ) + m_cellEnd; } if (settings.showPhotoExpo) { str = TQString("%1 / %2").arg(photoInfo.exposureTime.isEmpty() ? unavailable : photoInfo.exposureTime) .arg(photoInfo.sensitivity.isEmpty() ? unavailable : i18n("%1 ISO").arg(photoInfo.sensitivity)); if (str.length() > m_maxStringLen) str = str.left(m_maxStringLen-3) + "..."; metaStr += m_cellBeg + i18n("Exposure/Sensitivity:") + m_cellMid + TQStyleSheet::escape( str ) + m_cellEnd; } if (settings.showPhotoMode) { if (photoInfo.exposureMode.isEmpty() && photoInfo.exposureProgram.isEmpty()) str = unavailable; else if (!photoInfo.exposureMode.isEmpty() && photoInfo.exposureProgram.isEmpty()) str = photoInfo.exposureMode; else if (photoInfo.exposureMode.isEmpty() && !photoInfo.exposureProgram.isEmpty()) str = photoInfo.exposureProgram; else str = TQString("%1 / %2").arg(photoInfo.exposureMode).arg(photoInfo.exposureProgram); if (str.length() > m_maxStringLen) str = str.left(m_maxStringLen-3) + "..."; metaStr += m_cellBeg + i18n("Mode/Program:") + m_cellMid + TQStyleSheet::escape( str ) + m_cellEnd; } if (settings.showPhotoFlash) { str = photoInfo.flash.isEmpty() ? unavailable : photoInfo.flash; if (str.length() > m_maxStringLen) str = str.left(m_maxStringLen-3) + "..."; metaStr += m_cellBeg + i18n("Flash:") + m_cellMid + TQStyleSheet::escape( str ) + m_cellEnd; } if (settings.showPhotoWB) { str = photoInfo.whiteBalance.isEmpty() ? unavailable : photoInfo.whiteBalance; if (str.length() > m_maxStringLen) str = str.left(m_maxStringLen-3) + "..."; metaStr += m_cellBeg + i18n("White Balance:") + m_cellMid + TQStyleSheet::escape( str ) + m_cellEnd; } tipText += metaStr; } } return tipText; } TQString ThumbBarToolTip::breakString(const TQString& input) { TQString str = input.simplifyWhiteSpace(); str = TQStyleSheet::escape(str); const uint maxLen = m_maxStringLen; if (str.length() <= maxLen) return str; TQString br; uint i = 0; uint count = 0; while (i < str.length()) { if (count >= maxLen && str[i].isSpace()) { count = 0; br.append("
"); } else { br.append(str[i]); } i++; count++; } return br; } } // NameSpace Digikam