KDEUI
krecentfilesaction.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> 00003 (C) 1999 Simon Hausmann <hausmann@kde.org> 00004 (C) 2000 Nicolas Hadacek <haadcek@kde.org> 00005 (C) 2000 Kurt Granroth <granroth@kde.org> 00006 (C) 2000 Michael Koch <koch@kde.org> 00007 (C) 2001 Holger Freyther <freyther@kde.org> 00008 (C) 2002 Ellis Whitehead <ellis@kde.org> 00009 (C) 2002 Joseph Wenninger <jowenn@kde.org> 00010 (C) 2003 Andras Mantia <amantia@kde.org> 00011 (C) 2005-2006 Hamish Rodda <rodda@kde.org> 00012 00013 This library is free software; you can redistribute it and/or 00014 modify it under the terms of the GNU Library General Public 00015 License version 2 as published by the Free Software Foundation. 00016 00017 This library is distributed in the hope that it will be useful, 00018 but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00020 Library General Public License for more details. 00021 00022 You should have received a copy of the GNU Library General Public License 00023 along with this library; see the file COPYING.LIB. If not, write to 00024 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00025 Boston, MA 02110-1301, USA. 00026 */ 00027 00028 #include "krecentfilesaction.h" 00029 #include "krecentfilesaction_p.h" 00030 00031 #include <QtCore/QFile> 00032 #include <QtGui/QDesktopWidget> 00033 #ifdef Q_OS_WIN 00034 #include <QtCore/QDir> 00035 #endif 00036 00037 #include <kconfig.h> 00038 #include <kconfiggroup.h> 00039 #include <kdebug.h> 00040 #include <kicon.h> 00041 #include <klocale.h> 00042 #include <kstandarddirs.h> 00043 00044 #include "kmenu.h" 00045 00046 00047 KRecentFilesAction::KRecentFilesAction(QObject *parent) 00048 : KSelectAction(*new KRecentFilesActionPrivate, parent) 00049 { 00050 Q_D(KRecentFilesAction); 00051 d->init(); 00052 } 00053 00054 KRecentFilesAction::KRecentFilesAction(const QString &text, QObject *parent) 00055 : KSelectAction(*new KRecentFilesActionPrivate, parent) 00056 { 00057 Q_D(KRecentFilesAction); 00058 d->init(); 00059 00060 // Want to keep the ampersands 00061 setText(text); 00062 } 00063 00064 KRecentFilesAction::KRecentFilesAction(const KIcon &icon, const QString &text, QObject *parent) 00065 : KSelectAction(*new KRecentFilesActionPrivate, parent) 00066 { 00067 Q_D(KRecentFilesAction); 00068 d->init(); 00069 00070 setIcon(icon); 00071 // Want to keep the ampersands 00072 setText(text); 00073 } 00074 00075 void KRecentFilesActionPrivate::init() 00076 { 00077 Q_Q(KRecentFilesAction); 00078 delete q->menu(); 00079 q->setMenu(new KMenu()); 00080 q->setToolBarMode(KSelectAction::MenuMode); 00081 m_noEntriesAction = q->menu()->addAction(i18n("No Entries")); 00082 m_noEntriesAction->setEnabled(false); 00083 clearSeparator = q->menu()->addSeparator(); 00084 clearSeparator->setVisible(false); 00085 clearAction = q->menu()->addAction(i18n("Clear List"), q, SLOT(clear())); 00086 clearAction->setVisible(false); 00087 q->setEnabled(false); 00088 q->connect(q, SIGNAL(triggered(QAction*)), SLOT(_k_urlSelected(QAction*))); 00089 } 00090 00091 KRecentFilesAction::~KRecentFilesAction() 00092 { 00093 } 00094 00095 void KRecentFilesActionPrivate::_k_urlSelected( QAction* action ) 00096 { 00097 Q_Q(KRecentFilesAction); 00098 emit q->urlSelected(m_urls[action]); 00099 } 00100 00101 int KRecentFilesAction::maxItems() const 00102 { 00103 Q_D(const KRecentFilesAction); 00104 return d->m_maxItems; 00105 } 00106 00107 void KRecentFilesAction::setMaxItems( int maxItems ) 00108 { 00109 Q_D(KRecentFilesAction); 00110 // set new maxItems 00111 d->m_maxItems = maxItems; 00112 00113 // remove all excess items 00114 while( selectableActionGroup()->actions().count() > maxItems ) 00115 delete removeAction(selectableActionGroup()->actions().last()); 00116 } 00117 00118 static QString titleWithSensibleWidth(const QString& nameValue, const QString& value) 00119 { 00120 // Calculate 3/4 of screen geometry, we do not want 00121 // action titles to be bigger than that 00122 // Since we do not know in which screen we are going to show 00123 // we choose the min of all the screens 00124 const QDesktopWidget desktopWidget; 00125 int maxWidthForTitles = INT_MAX; 00126 for (int i = 0; i < desktopWidget.screenCount(); ++i) { 00127 maxWidthForTitles = qMin(maxWidthForTitles, desktopWidget.availableGeometry(i).width() * 3 / 4); 00128 } 00129 const QFontMetrics fontMetrics = QFontMetrics(QFont()); 00130 00131 QString title = nameValue + " [" + value + ']'; 00132 if (fontMetrics.width(title) > maxWidthForTitles){ 00133 // If it does not fit, try to cut only the whole path, though if the 00134 // name is too long (more than 3/4 of the whole text) we cut it a bit too 00135 const int nameValueMaxWidth = maxWidthForTitles * 3 / 4; 00136 const int nameWidth = fontMetrics.width(nameValue); 00137 QString cutNameValue, cutValue; 00138 if (nameWidth > nameValueMaxWidth) { 00139 cutNameValue = fontMetrics.elidedText(nameValue, Qt::ElideMiddle, nameValueMaxWidth); 00140 cutValue = fontMetrics.elidedText(value, Qt::ElideMiddle, maxWidthForTitles - nameValueMaxWidth); 00141 } else { 00142 cutNameValue = nameValue; 00143 cutValue = fontMetrics.elidedText(value, Qt::ElideMiddle, maxWidthForTitles - nameWidth); 00144 } 00145 title = cutNameValue + " [" + cutValue + ']'; 00146 } 00147 return title; 00148 } 00149 00150 void KRecentFilesAction::addUrl( const KUrl& _url, const QString& name ) 00151 { 00152 Q_D(KRecentFilesAction); 00158 const KUrl url( _url ); 00159 00160 if ( url.isLocalFile() && KGlobal::dirs()->relativeLocation("tmp", url.toLocalFile()) != url.toLocalFile() ) 00161 return; 00162 const QString tmpName = name.isEmpty() ? url.fileName() : name; 00163 #ifdef Q_OS_WIN 00164 const QString file = url.isLocalFile() ? QDir::toNativeSeparators( url.pathOrUrl() ) : url.pathOrUrl(); 00165 #else 00166 const QString file = url.pathOrUrl(); 00167 #endif 00168 00169 // remove file if already in list 00170 foreach (QAction* action, selectableActionGroup()->actions()) 00171 { 00172 if ( d->m_urls[action].pathOrUrl().endsWith(file) ) 00173 { 00174 removeAction(action)->deleteLater(); 00175 break; 00176 } 00177 } 00178 // remove oldest item if already maxitems in list 00179 if( d->m_maxItems && selectableActionGroup()->actions().count() == d->m_maxItems ) 00180 { 00181 // remove oldest added item 00182 delete removeAction(selectableActionGroup()->actions().first()); 00183 } 00184 00185 d->m_noEntriesAction->setVisible(false); 00186 d->clearSeparator->setVisible(true); 00187 d->clearAction->setVisible(true); 00188 setEnabled(true); 00189 // add file to list 00190 const QString title = titleWithSensibleWidth(tmpName, file); 00191 QAction* action = new QAction(title, selectableActionGroup()); 00192 addAction(action, url, tmpName); 00193 } 00194 00195 void KRecentFilesAction::addAction(QAction* action, const KUrl& url, const QString& name) 00196 { 00197 Q_D(KRecentFilesAction); 00198 //kDebug (129) << "KRecentFilesAction::addAction(" << action << ")"; 00199 00200 action->setActionGroup(selectableActionGroup()); 00201 00202 // Keep in sync with createToolBarWidget() 00203 foreach (QToolButton* button, d->m_buttons) 00204 button->insertAction(button->actions().value(0), action); 00205 00206 foreach (KComboBox* comboBox, d->m_comboBoxes) 00207 comboBox->insertAction(comboBox->actions().value(0), action); 00208 00209 menu()->insertAction(menu()->actions().value(0), action); 00210 00211 d->m_shortNames.insert( action, name ); 00212 d->m_urls.insert( action, url ); 00213 } 00214 00215 QAction* KRecentFilesAction::removeAction(QAction* action) 00216 { 00217 Q_D(KRecentFilesAction); 00218 KSelectAction::removeAction( action ); 00219 00220 d->m_shortNames.remove( action ); 00221 d->m_urls.remove( action ); 00222 00223 return action; 00224 } 00225 00226 void KRecentFilesAction::removeUrl( const KUrl& url ) 00227 { 00228 Q_D(KRecentFilesAction); 00229 for (QMap<QAction*, KUrl>::ConstIterator it = d->m_urls.constBegin(); it != d->m_urls.constEnd(); ++it) 00230 if (it.value() == url) { 00231 delete removeAction(it.key()); 00232 return; 00233 } 00234 } 00235 00236 KUrl::List KRecentFilesAction::urls() const 00237 { 00238 Q_D(const KRecentFilesAction); 00239 return d->m_urls.values (); 00240 } 00241 00242 void KRecentFilesAction::clear() 00243 { 00244 clearEntries(); 00245 emit recentListCleared(); 00246 } 00247 00248 void KRecentFilesAction::clearEntries() 00249 { 00250 Q_D(KRecentFilesAction); 00251 KSelectAction::clear(); 00252 d->m_shortNames.clear(); 00253 d->m_urls.clear(); 00254 d->m_noEntriesAction->setVisible(true); 00255 d->clearSeparator->setVisible(false); 00256 d->clearAction->setVisible(false); 00257 setEnabled(false); 00258 } 00259 00260 void KRecentFilesAction::loadEntries( const KConfigGroup& _config) 00261 { 00262 Q_D(KRecentFilesAction); 00263 clearEntries(); 00264 00265 QString key; 00266 QString value; 00267 QString nameKey; 00268 QString nameValue; 00269 QString title; 00270 KUrl url; 00271 00272 KConfigGroup cg = _config; 00273 if ( cg.name().isEmpty()) 00274 cg = KConfigGroup(cg.config(),"RecentFiles"); 00275 00276 bool thereAreEntries=false; 00277 // read file list 00278 for( int i = 1 ; i <= d->m_maxItems ; i++ ) 00279 { 00280 key = QString( "File%1" ).arg( i ); 00281 value = cg.readPathEntry( key, QString() ); 00282 if (value.isEmpty()) continue; 00283 url = KUrl( value ); 00284 00285 // Don't restore if file doesn't exist anymore 00286 if (url.isLocalFile() && !QFile::exists(url.toLocalFile())) 00287 continue; 00288 00289 // Don't restore where the url is already known (eg. broken config) 00290 if (d->m_urls.values().contains(url)) 00291 continue; 00292 00293 #ifdef Q_OS_WIN 00294 // convert to backslashes 00295 if ( url.isLocalFile() ) 00296 value = QDir::toNativeSeparators( value ); 00297 #endif 00298 00299 nameKey = QString( "Name%1" ).arg( i ); 00300 nameValue = cg.readPathEntry( nameKey, url.fileName() ); 00301 title = titleWithSensibleWidth(nameValue, value); 00302 if (!value.isNull()) 00303 { 00304 thereAreEntries=true; 00305 addAction(new QAction(title, selectableActionGroup()), url, nameValue); 00306 } 00307 } 00308 if (thereAreEntries) 00309 { 00310 d->m_noEntriesAction->setVisible(false); 00311 d->clearSeparator->setVisible(true); 00312 d->clearAction->setVisible(true); 00313 setEnabled(true); 00314 } 00315 } 00316 00317 void KRecentFilesAction::saveEntries( const KConfigGroup &_cg ) 00318 { 00319 Q_D(KRecentFilesAction); 00320 QString key; 00321 QString value; 00322 QStringList lst = items(); 00323 00324 KConfigGroup cg = _cg; 00325 if (cg.name().isEmpty()) 00326 cg = KConfigGroup(cg.config(),"RecentFiles"); 00327 00328 cg.deleteGroup(); 00329 00330 // write file list 00331 for ( int i = 1 ; i <= selectableActionGroup()->actions().count() ; i++ ) 00332 { 00333 key = QString( "File%1" ).arg( i ); 00334 // i - 1 because we started from 1 00335 value = d->m_urls[ selectableActionGroup()->actions()[ i - 1 ] ].pathOrUrl(); 00336 cg.writePathEntry( key, value ); 00337 key = QString( "Name%1" ).arg( i ); 00338 value = d->m_shortNames[ selectableActionGroup()->actions()[ i - 1 ] ]; 00339 cg.writePathEntry( key, value ); 00340 } 00341 00342 } 00343 00344 /* vim: et sw=2 ts=2 00345 */ 00346 00347 #include "krecentfilesaction.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Wed May 2 2012 17:57:37 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Wed May 2 2012 17:57:37 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.