diff --git a/Browser/BrowserWidget.cpp b/Browser/BrowserWidget.cpp index c82e67c5..37c9aba5 100644 --- a/Browser/BrowserWidget.cpp +++ b/Browser/BrowserWidget.cpp @@ -1,480 +1,481 @@ /* Copyright (C) 2003-2018 Jesper K. Pedersen 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 of the License, 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. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "BrowserWidget.h" #include #include #include #include #include #include "ImageViewPage.h" #include "CategoryPage.h" #include "TreeFilter.h" #include #include #include "OverviewPage.h" #include "enums.h" #include #include "Settings/SettingsData.h" #include #include #include "Utilities/Util.h" #include "Utilities/ShowBusyCursor.h" #include #include "DB/CategoryCollection.h" #include "TreeCategoryModel.h" Browser::BrowserWidget* Browser::BrowserWidget::s_instance = nullptr; bool Browser::BrowserWidget::s_isResizing = false; Browser::BrowserWidget::BrowserWidget( QWidget* parent ) :QWidget( parent ), m_current(-1) { Q_ASSERT( !s_instance ); s_instance = this; createWidgets(); connect( DB::ImageDB::instance()->categoryCollection(), &DB::CategoryCollection::categoryCollectionChanged, this, &BrowserWidget::reload); connect( this, &BrowserWidget::viewChanged, this, &BrowserWidget::resetIconViewSearch); m_filterProxy = new TreeFilter(this); m_filterProxy->setFilterKeyColumn(0); m_filterProxy->setFilterCaseSensitivity( Qt::CaseInsensitive ); m_filterProxy->setSortRole( ValueRole ); m_filterProxy->setSortCaseSensitivity( Qt::CaseInsensitive ); addAction( new OverviewPage( Breadcrumb::home(), DB::ImageSearchInfo(), this ) ); QTimer::singleShot( 0, this, SLOT(emitSignals()) ); } void Browser::BrowserWidget::forward() { int targetIndex = m_current; while ( targetIndex < m_list.count()-1 ) { targetIndex++; if ( m_list[targetIndex]->showDuringMovement() ) { break; } } activatePage(targetIndex); } void Browser::BrowserWidget::back() { int targetIndex = m_current; while ( targetIndex > 0 ) { targetIndex--; if ( m_list[targetIndex]->showDuringMovement() ) break; } activatePage(targetIndex); } void Browser::BrowserWidget::activatePage(int pageIndex) { if (pageIndex != m_current) { if (currentAction() != 0) { currentAction()->deactivate(); } m_current = pageIndex; go(); } } void Browser::BrowserWidget::go() { switchToViewType( currentAction()->viewType() ); currentAction()->activate(); setBranchOpen(QModelIndex(), true); adjustTreeViewColumnSize(); emitSignals(); } void Browser::BrowserWidget::addSearch( DB::ImageSearchInfo& info ) { addAction( new OverviewPage( Breadcrumb::empty(), info, this ) ); } void Browser::BrowserWidget::addImageView( const DB::FileName& context ) { addAction( new ImageViewPage( context, this ) ); } void Browser::BrowserWidget::addAction( Browser::BrowserPage* action ) { // remove actions which would go forward in the breadcrumbs while ( (int) m_list.count() > m_current+1 ) { BrowserPage* m = m_list.back(); m_list.pop_back(); delete m; } m_list.append(action); activatePage(m_list.count() - 1); } void Browser::BrowserWidget::emitSignals() { emit canGoBack( m_current > 0 ); emit canGoForward( m_current < (int)m_list.count()-1 ); if ( currentAction()->viewer() == ShowBrowser ) emit showingOverview(); emit isSearchable( currentAction()->isSearchable() ); emit isViewChangeable( currentAction()->isViewChangeable() ); bool isCategoryAction = (dynamic_cast( currentAction() ) != 0); if ( isCategoryAction ) { DB::CategoryPtr category = DB::ImageDB::instance()->categoryCollection()->categoryForName( currentCategory() ); Q_ASSERT( category.data() ); emit currentViewTypeChanged( category->viewType()); } emit pathChanged( createPath() ); emit viewChanged(); emit imageCount( DB::ImageDB::instance()->count(currentAction()->searchInfo()).total() ); } void Browser::BrowserWidget::home() { addAction( new OverviewPage( Breadcrumb::home(), DB::ImageSearchInfo(), this ) ); } void Browser::BrowserWidget::reload() { currentAction()->activate(); } Browser::BrowserWidget* Browser::BrowserWidget::instance() { Q_ASSERT( s_instance ); return s_instance; } void Browser::BrowserWidget::load( const QString& category, const QString& value ) { DB::ImageSearchInfo info; info.addAnd( category, value ); DB::MediaCount counts = DB::ImageDB::instance()->count( info ); bool loadImages = (counts.total() < Settings::SettingsData::instance()->autoShowThumbnailView()); - if ( Utilities::ctrlKeyDown() ) loadImages = !loadImages; + if ( QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier) ) + loadImages = !loadImages; if ( loadImages ) addAction( new ImageViewPage( info, this ) ); else addAction( new OverviewPage( Breadcrumb(value, true) , info, this ) ); go(); topLevelWidget()->raise(); activateWindow(); } DB::ImageSearchInfo Browser::BrowserWidget::currentContext() { return currentAction()->searchInfo(); } void Browser::BrowserWidget::slotSmallListView() { changeViewTypeForCurrentView( DB::Category::TreeView ); } void Browser::BrowserWidget::slotLargeListView() { changeViewTypeForCurrentView( DB::Category::ThumbedTreeView ); } void Browser::BrowserWidget::slotSmallIconView() { changeViewTypeForCurrentView( DB::Category::IconView ); } void Browser::BrowserWidget::slotLargeIconView() { changeViewTypeForCurrentView( DB::Category::ThumbedIconView ); } void Browser::BrowserWidget::changeViewTypeForCurrentView( DB::Category::ViewType type ) { Q_ASSERT( m_list.size() > 0 ); DB::CategoryPtr category = DB::ImageDB::instance()->categoryCollection()->categoryForName( currentCategory() ); Q_ASSERT( category.data() ); category->setViewType( type ); switchToViewType( type ); reload(); } void Browser::BrowserWidget::setFocus() { m_curView->setFocus(); } QString Browser::BrowserWidget::currentCategory() const { if ( CategoryPage* action = dynamic_cast( currentAction() ) ) return action->category()->name(); else return QString(); } void Browser::BrowserWidget::slotLimitToMatch( const QString& str ) { m_filterProxy->resetCache(); m_filterProxy->setFilterFixedString( str ); setBranchOpen(QModelIndex(), true); adjustTreeViewColumnSize(); } void Browser::BrowserWidget::resetIconViewSearch() { m_filterProxy->resetCache(); m_filterProxy->setFilterRegExp( QString() ); adjustTreeViewColumnSize(); } void Browser::BrowserWidget::slotInvokeSeleted() { if ( !m_curView->currentIndex().isValid() ) { if ( m_filterProxy->rowCount( QModelIndex() ) == 0 ) { // Absolutely nothing to see here :-) return; } else { // Use the first item itemClicked( m_filterProxy->index( 0,0,QModelIndex() ) ); } } else itemClicked( m_curView->currentIndex() ); } void Browser::BrowserWidget::itemClicked( const QModelIndex& index ) { Utilities::ShowBusyCursor busy; BrowserPage* action = currentAction()->activateChild( m_filterProxy->mapToSource( index ) ); if ( action ) addAction( action ); } Browser::BrowserPage* Browser::BrowserWidget::currentAction() const { return m_current >= 0? m_list[m_current] : 0; } void Browser::BrowserWidget::setModel( QAbstractItemModel* model) { m_filterProxy->setSourceModel( model ); // make sure the view knows about the source model change: m_curView->setModel( m_filterProxy ); if (qobject_cast(model)) { // FIXME: The new-style connect here does not work, reload() is not triggered //connect(model, &QAbstractItemModel::dataChanged, this, &BrowserWidget::reload); // The old-style one triggers reload() correctly connect(model, SIGNAL(dataChanged()), this, SLOT(reload())); } } void Browser::BrowserWidget::switchToViewType( DB::Category::ViewType type ) { if ( m_curView ) { m_curView->setModel(0); disconnect( m_curView, &QAbstractItemView::activated, this, &BrowserWidget::itemClicked); } if ( type == DB::Category::TreeView || type == DB::Category::ThumbedTreeView ) { m_curView = m_treeView; } else { m_curView =m_listView; m_filterProxy->invalidate(); m_filterProxy->sort( 0, Qt::AscendingOrder ); m_listView->setViewMode(dynamic_cast(currentAction()) == 0 ? CenteringIconView::NormalIconView : CenteringIconView::CenterView ); } if ( CategoryPage* action = dynamic_cast( currentAction() ) ) { const int size = action->category()->thumbnailSize(); m_curView->setIconSize( QSize(size,size) ); // m_curView->setGridSize( QSize( size+10, size+10 ) ); } // Hook up the new view m_curView->setModel( m_filterProxy ); connect( m_curView, &QAbstractItemView::activated, this, &BrowserWidget::itemClicked); m_stack->setCurrentWidget( m_curView ); adjustTreeViewColumnSize(); } void Browser::BrowserWidget::setBranchOpen( const QModelIndex& parent, bool open ) { if ( m_curView != m_treeView ) return; const int count = m_filterProxy->rowCount(parent); if ( count > 5 ) open = false; m_treeView->setExpanded( parent, open ); for ( int row = 0; row < count; ++row ) setBranchOpen( m_filterProxy->index( row, 0 ,parent ), open ); } Browser::BreadcrumbList Browser::BrowserWidget::createPath() const { BreadcrumbList result; for ( int i = 0; i <= m_current; ++i ) result.append(m_list[i]->breadcrumb() ); return result; } void Browser::BrowserWidget::widenToBreadcrumb( const Browser::Breadcrumb& breadcrumb ) { while ( currentAction()->breadcrumb() != breadcrumb ) m_current--; go(); } void Browser::BrowserWidget::adjustTreeViewColumnSize() { m_treeView->header()->resizeSections(QHeaderView::ResizeToContents); } void Browser::BrowserWidget::createWidgets() { m_stack = new QStackedWidget; QHBoxLayout* layout = new QHBoxLayout( this ); layout->setContentsMargins(0,0,0,0); layout->addWidget( m_stack ); m_listView = new CenteringIconView ( m_stack ); m_listView->setIconSize( QSize(100,75) ); m_listView->setSelectionMode( QListView::SingleSelection ); m_listView->setSpacing(10); m_listView->setUniformItemSizes(true); m_listView->setResizeMode( QListView::Adjust ); m_stack->addWidget( m_listView ); m_treeView = new QTreeView( m_stack ); m_treeView->setDragEnabled(true); m_treeView->setAcceptDrops(true); m_treeView->setDropIndicatorShown(true); m_treeView->setDefaultDropAction( Qt::MoveAction ); QPalette pal = m_treeView->palette(); pal.setBrush( QPalette::Base, QApplication::palette().color( QPalette::Background ) ); m_treeView->setPalette( pal ); m_treeView->header()->setStretchLastSection(false); m_treeView->header()->setSortIndicatorShown(true); m_treeView->setSortingEnabled(true); m_treeView->sortByColumn( 0, Qt::AscendingOrder ); m_stack->addWidget( m_treeView ); // Do not give focus to the widgets when they are scrolled with the wheel. m_listView->setFocusPolicy( Qt::StrongFocus ); m_treeView->setFocusPolicy( Qt::StrongFocus ); m_treeView->installEventFilter( this ); m_treeView->viewport()->installEventFilter( this ); m_listView->installEventFilter( this ); m_listView->viewport()->installEventFilter( this ); connect( m_treeView, &QTreeView::expanded, this, &BrowserWidget::adjustTreeViewColumnSize); m_curView = nullptr; } bool Browser::BrowserWidget::eventFilter( QObject* /* obj */, QEvent* event) { if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonRelease ) { QMouseEvent* me = static_cast( event ); if ( me->buttons() & Qt::MidButton || me->button() & Qt::MidButton) { handleResizeEvent( me ); return true; } } return false; } void Browser::BrowserWidget::scrollKeyPressed( QKeyEvent* event ) { QApplication::sendEvent(m_curView, event ); } void Browser::BrowserWidget::handleResizeEvent( QMouseEvent* event ) { static int offset; CategoryPage* action = dynamic_cast( currentAction() ); if ( !action ) return; DB::CategoryPtr category = action->category(); if ( !action ) return; if ( event->type() == QEvent::MouseButtonPress ) { m_resizePressPos = event->pos(); offset = category->thumbnailSize(); s_isResizing = true; } else if ( event->type() == QEvent::MouseMove ) { int distance = (event->pos() - m_resizePressPos).x() + (event->pos() - m_resizePressPos).y() / 3; int size = distance + offset; size = qMax( qMin( 512, size ), 32 ); action->category()->setThumbnailSize( size ); m_curView->setIconSize( QSize(size,size) ); m_filterProxy->invalidate(); adjustTreeViewColumnSize(); } else if ( event->type() == QEvent::MouseButtonRelease ) { s_isResizing = false; update(); } } // vi:expandtab:tabstop=4 shiftwidth=4: diff --git a/Utilities/Util.cpp b/Utilities/Util.cpp index 5842a237..95528636 100644 --- a/Utilities/Util.cpp +++ b/Utilities/Util.cpp @@ -1,290 +1,285 @@ /* Copyright (C) 2003-2010 Jesper K. Pedersen 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 of the License, 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. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "Util.h" #include "Logging.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern "C" { #include } void Utilities::checkForBackupFile( const QString& fileName, const QString& message ) { QString backupName = QFileInfo( fileName ).absolutePath() + QString::fromLatin1("/.#") + QFileInfo( fileName ).fileName(); QFileInfo backUpFile( backupName); QFileInfo indexFile( fileName ); if ( !backUpFile.exists() || indexFile.lastModified() > backUpFile.lastModified() || backUpFile.size() == 0 ) if ( !( backUpFile.exists() && !message.isNull() ) ) return; int code; if ( message.isNull() ) code = KMessageBox::questionYesNo( nullptr, i18n("Autosave file '%1' exists (size %3 KB) and is newer than '%2'. " "Should the autosave file be used?", backupName, fileName, backUpFile.size() >> 10 ), i18n("Found Autosave File") ); else if ( backUpFile.size() > 0 ) code = KMessageBox::warningYesNo( nullptr,i18n( "

Error: Cannot use current database file '%1':

%2

" "

Do you want to use autosave (%3 - size %4 KB) instead of exiting?

" "

(Manually verifying and copying the file might be a good idea)

", fileName, message, backupName, backUpFile.size() >> 10 ), i18n("Recover from Autosave?") ); else { KMessageBox::error( nullptr, i18n( "

Error: %1

Also autosave file is empty, check manually " "if numbered backup files exist and can be used to restore index.xml.

", message ) ); exit(-1); } if ( code == KMessageBox::Yes ) { QFile in( backupName ); if ( in.open( QIODevice::ReadOnly ) ) { QFile out( fileName ); if (out.open( QIODevice::WriteOnly ) ) { char data[1024]; int len; while ( (len = in.read( data, 1024 ) ) ) out.write( data, len ); } } } else if ( !message.isNull() ) exit(-1); } -bool Utilities::ctrlKeyDown() -{ - return QApplication::keyboardModifiers() & Qt::ControlModifier; -} - bool Utilities::copy( const QString& from, const QString& to ) { if ( QFileInfo(to).exists()) QDir().remove(to); return QFile::copy(from,to); } bool Utilities::makeHardLink( const QString& from, const QString& to ) { if (link(from.toLocal8Bit().constData(), to.toLocal8Bit().constData()) != 0) return false; else return true; } bool Utilities::makeSymbolicLink( const QString& from, const QString& to ) { if (symlink(from.toLocal8Bit().constData(), to.toLocal8Bit().constData()) != 0) return false; else return true; } bool Utilities::canReadImage( const DB::FileName& fileName ) { bool fastMode = !Settings::SettingsData::instance()->ignoreFileExtension(); QMimeDatabase::MatchMode mode = fastMode ? QMimeDatabase::MatchExtension : QMimeDatabase::MatchDefault; QMimeDatabase db; QMimeType mimeType = db.mimeTypeForFile( fileName.absolute(), mode ); return QImageReader::supportedMimeTypes().contains( mimeType.name().toUtf8() ) || ImageManager::ImageDecoder::mightDecode( fileName ); } QString Utilities::locateDataFile(const QString& fileName) { return QStandardPaths::locate(QStandardPaths::DataLocation, fileName); } QString Utilities::readFile( const QString& fileName ) { if ( fileName.isEmpty() ) { KMessageBox::error( nullptr, i18n("

No file name given!

") ); return QString(); } QFile file( fileName ); if ( !file.open( QIODevice::ReadOnly ) ) { //KMessageBox::error( nullptr, i18n("Could not open file %1").arg( fileName ) ); return QString(); } QTextStream stream( &file ); QString content = stream.readAll(); file.close(); return content; } namespace Utilities { QString normalizedFileName( const QString& fileName ) { return QFileInfo(fileName).absoluteFilePath(); } QString dereferenceSymLinks( const QString& fileName ) { QFileInfo fi(fileName); int rounds = 256; while (fi.isSymLink() && --rounds > 0) fi = QFileInfo(fi.readLink()); if (rounds == 0) return QString(); return fi.filePath(); } } QString Utilities::stripEndingForwardSlash( const QString& fileName ) { static QString slash = QString::fromLatin1("/"); if ( fileName.endsWith( slash ) ) return fileName.left( fileName.length()-1); else return fileName; } QString Utilities::relativeFolderName( const QString& fileName) { int index= fileName.lastIndexOf( QChar::fromLatin1('/'), -1); if (index == -1) return QString(); else return fileName.left( index ); } QString Utilities::absoluteImageFileName( const QString& relativeName ) { return stripEndingForwardSlash( Settings::SettingsData::instance()->imageDirectory() ) + QString::fromLatin1( "/" ) + relativeName; } QString Utilities::imageFileNameToAbsolute( const QString& fileName ) { if ( fileName.startsWith( Settings::SettingsData::instance()->imageDirectory() ) ) return fileName; else if ( fileName.startsWith( QString::fromLatin1("file://") ) ) return imageFileNameToAbsolute( fileName.mid( 7 ) ); // 7 == length("file://") else if ( fileName.startsWith( QString::fromLatin1("/") ) ) return QString(); // Not within our image root else return absoluteImageFileName( fileName ); } const QSet& Utilities::supportedVideoExtensions() { static QSet videoExtensions; if ( videoExtensions.empty() ) { videoExtensions.insert( QString::fromLatin1( "3gp" ) ); videoExtensions.insert( QString::fromLatin1( "avi" ) ); videoExtensions.insert( QString::fromLatin1( "mp4" ) ); videoExtensions.insert( QString::fromLatin1( "m4v" ) ); videoExtensions.insert( QString::fromLatin1( "mpeg" ) ); videoExtensions.insert( QString::fromLatin1( "mpg" ) ); videoExtensions.insert( QString::fromLatin1( "qt" ) ); videoExtensions.insert( QString::fromLatin1( "mov" ) ); videoExtensions.insert( QString::fromLatin1( "moov" ) ); videoExtensions.insert( QString::fromLatin1( "qtvr" ) ); videoExtensions.insert( QString::fromLatin1( "rv" ) ); videoExtensions.insert( QString::fromLatin1( "3g2" ) ); videoExtensions.insert( QString::fromLatin1( "fli" ) ); videoExtensions.insert( QString::fromLatin1( "flc" ) ); videoExtensions.insert( QString::fromLatin1( "mkv" ) ); videoExtensions.insert( QString::fromLatin1( "mng" ) ); videoExtensions.insert( QString::fromLatin1( "asf" ) ); videoExtensions.insert( QString::fromLatin1( "asx" ) ); videoExtensions.insert( QString::fromLatin1( "wmp" ) ); videoExtensions.insert( QString::fromLatin1( "wmv" ) ); videoExtensions.insert( QString::fromLatin1( "ogm" ) ); videoExtensions.insert( QString::fromLatin1( "rm" ) ); videoExtensions.insert( QString::fromLatin1( "flv" ) ); videoExtensions.insert( QString::fromLatin1( "webm" ) ); videoExtensions.insert( QString::fromLatin1( "mts" ) ); videoExtensions.insert( QString::fromLatin1( "ogg" ) ); videoExtensions.insert( QString::fromLatin1( "ogv" ) ); videoExtensions.insert( QString::fromLatin1( "m2ts" ) ); } return videoExtensions; } bool Utilities::isVideo( const DB::FileName& fileName ) { QFileInfo fi( fileName.relative() ); QString ext = fi.suffix().toLower(); return supportedVideoExtensions().contains( ext ); } bool Utilities::isRAW( const DB::FileName& fileName ) { return ImageManager::RAWImageDecoder::isRAW( fileName ); } QImage Utilities::scaleImage(const QImage &image, int w, int h, Qt::AspectRatioMode mode ) { return image.scaled( w, h, mode, Settings::SettingsData::instance()->smoothScale() ? Qt::SmoothTransformation : Qt::FastTransformation ); } QImage Utilities::scaleImage(const QImage &image, const QSize& s, Qt::AspectRatioMode mode ) { return scaleImage( image, s.width(), s.height(), mode ); } QString Utilities::cStringWithEncoding( const char *c_str, const QString& charset ) { QTextCodec* codec = QTextCodec::codecForName( charset.toLatin1() ); if (!codec) codec = QTextCodec::codecForLocale(); return codec->toUnicode( c_str ); } QColor Utilities::contrastColor( const QColor& col ) { if ( col.red() < 127 && col.green() < 127 && col.blue() < 127 ) return Qt::white; else return Qt::black; } void Utilities::saveImage( const DB::FileName& fileName, const QImage& image, const char* format ) { const QFileInfo info(fileName.absolute()); QDir().mkpath(info.path()); const bool ok = image.save(fileName.absolute(),format); Q_ASSERT(ok); Q_UNUSED(ok); } // vi:expandtab:tabstop=4 shiftwidth=4: diff --git a/Utilities/Util.h b/Utilities/Util.h index 9525d7ab..b7a8ca6c 100644 --- a/Utilities/Util.h +++ b/Utilities/Util.h @@ -1,65 +1,64 @@ /* Copyright (C) 2003-2010 Jesper K. Pedersen 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 of the License, 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. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef UTIL_H #define UTIL_H #include "DB/CategoryPtr.h" #include "DB/FileName.h" #include "DB/ImageInfoPtr.h" #include #include #include #include #include namespace Utilities { void checkForBackupFile( const QString& fileName, const QString& message = QString() ); -bool ctrlKeyDown(); bool copy( const QString& from, const QString& to ); bool makeSymbolicLink( const QString& from, const QString& to ); bool makeHardLink( const QString& from, const QString& to ); bool canReadImage( const DB::FileName& fileName ); const QSet& supportedVideoExtensions(); bool isVideo( const DB::FileName& fileName ); bool isRAW( const DB::FileName& fileName ); QString locateDataFile(const QString& fileName); QString readFile( const QString& fileName ); QString stripEndingForwardSlash( const QString& fileName ); QString absoluteImageFileName( const QString& relativeName ); QString imageFileNameToAbsolute( const QString& fileName ); QString relativeFolderName( const QString& fileName); QImage scaleImage(const QImage &image, int w, int h, Qt::AspectRatioMode mode=Qt::IgnoreAspectRatio ); QImage scaleImage(const QImage &image, const QSize& s, Qt::AspectRatioMode mode=Qt::IgnoreAspectRatio ); QString cStringWithEncoding( const char *c_str, const QString& charset ); QColor contrastColor( const QColor& ); void saveImage( const DB::FileName& fileName, const QImage& image, const char* format ); } #endif /* UTIL_H */ // vi:expandtab:tabstop=4 shiftwidth=4: