kdelibs/kdeui/actions/krecentfilesaction.cpp
Ivailo Monev 9acda75f99 kdeui: format and indent
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2023-08-28 02:57:26 +03:00

334 lines
10 KiB
C++

/* This file is part of the KDE libraries
Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
(C) 1999 Simon Hausmann <hausmann@kde.org>
(C) 2000 Nicolas Hadacek <haadcek@kde.org>
(C) 2000 Kurt Granroth <granroth@kde.org>
(C) 2000 Michael Koch <koch@kde.org>
(C) 2001 Holger Freyther <freyther@kde.org>
(C) 2002 Ellis Whitehead <ellis@kde.org>
(C) 2002 Joseph Wenninger <jowenn@kde.org>
(C) 2003 Andras Mantia <amantia@kde.org>
(C) 2005-2006 Hamish Rodda <rodda@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "krecentfilesaction.h"
#include "krecentfilesaction_p.h"
#include "kconfig.h"
#include "kconfiggroup.h"
#include "kdebug.h"
#include "kicon.h"
#include "klocale.h"
#include "kstandarddirs.h"
#include "kmenu.h"
#include <QtCore/QFile>
#include <QtGui/QDesktopWidget>
#include <limits.h>
static QString titleWithSensibleWidth(const QString &nameValue, const QString &value)
{
// Calculate 3/4 of screen geometry, we do not want
// action titles to be bigger than that
// Since we do not know in which screen we are going to show
// we choose the min of all the screens
const QDesktopWidget desktopWidget;
int maxWidthForTitles = INT_MAX;
for (int i = 0; i < desktopWidget.screenCount(); ++i) {
maxWidthForTitles = qMin(maxWidthForTitles, desktopWidget.availableGeometry(i).width() * 3 / 4);
}
const QFontMetrics fontMetrics = QFontMetrics(QFont());
QString title = nameValue + " [" + value + ']';
if (fontMetrics.width(title) > maxWidthForTitles){
// If it does not fit, try to cut only the whole path, though if the
// name is too long (more than 3/4 of the whole text) we cut it a bit too
const int nameValueMaxWidth = maxWidthForTitles * 3 / 4;
const int nameWidth = fontMetrics.width(nameValue);
QString cutNameValue, cutValue;
if (nameWidth > nameValueMaxWidth) {
cutNameValue = fontMetrics.elidedText(nameValue, Qt::ElideMiddle, nameValueMaxWidth);
cutValue = fontMetrics.elidedText(value, Qt::ElideMiddle, maxWidthForTitles - nameValueMaxWidth);
} else {
cutNameValue = nameValue;
cutValue = fontMetrics.elidedText(value, Qt::ElideMiddle, maxWidthForTitles - nameWidth);
}
title = cutNameValue + " [" + cutValue + ']';
}
return title;
}
KRecentFilesAction::KRecentFilesAction(QObject *parent)
: KSelectAction(*new KRecentFilesActionPrivate, parent)
{
Q_D(KRecentFilesAction);
d->init();
}
KRecentFilesAction::KRecentFilesAction(const QString &text, QObject *parent)
: KSelectAction(*new KRecentFilesActionPrivate, parent)
{
Q_D(KRecentFilesAction);
d->init();
// Want to keep the ampersands
setText(text);
}
KRecentFilesAction::KRecentFilesAction(const KIcon &icon, const QString &text, QObject *parent)
: KSelectAction(*new KRecentFilesActionPrivate, parent)
{
Q_D(KRecentFilesAction);
d->init();
setIcon(icon);
// Want to keep the ampersands
setText(text);
}
void KRecentFilesActionPrivate::init()
{
Q_Q(KRecentFilesAction);
delete q->menu();
q->setMenu(new KMenu());
q->setToolBarMode(KSelectAction::MenuMode);
m_noEntriesAction = q->menu()->addAction(i18n("No Entries"));
m_noEntriesAction->setEnabled(false);
clearSeparator = q->menu()->addSeparator();
clearSeparator->setVisible(false);
clearAction = q->menu()->addAction(i18n("Clear List"), q, SLOT(clear()));
clearAction->setVisible(false);
q->setEnabled(false);
q->connect(q, SIGNAL(triggered(QAction*)), SLOT(_k_urlSelected(QAction*)));
}
KRecentFilesAction::~KRecentFilesAction()
{
}
void KRecentFilesActionPrivate::_k_urlSelected(QAction *action)
{
Q_Q(KRecentFilesAction);
emit q->urlSelected(m_urls[action]);
}
int KRecentFilesAction::maxItems() const
{
Q_D(const KRecentFilesAction);
return d->m_maxItems;
}
void KRecentFilesAction::setMaxItems(int maxItems)
{
Q_D(KRecentFilesAction);
// set new maxItems
d->m_maxItems = maxItems;
// remove all excess items
while( selectableActionGroup()->actions().count() > maxItems) {
delete removeAction(selectableActionGroup()->actions().last());
}
}
void KRecentFilesAction::addUrl(const KUrl &_url, const QString &name)
{
Q_D(KRecentFilesAction);
/**
* Create a deep copy here, because if _url is the parameter from
* urlSelected() signal, we will delete it in the removeAction() call below.
* but access it again in the addAction call... => crash
*/
const KUrl url(_url);
if (url.isLocalFile() && KGlobal::dirs()->relativeLocation("tmp", url.toLocalFile()) != url.toLocalFile()) {
return;
}
const QString tmpName = (name.isEmpty() ? url.fileName() : name);
const QString file = url.pathOrUrl();
// remove file if already in list
foreach (QAction *action, selectableActionGroup()->actions()) {
if ( d->m_urls[action].pathOrUrl().endsWith(file)) {
removeAction(action)->deleteLater();
break;
}
}
// remove oldest item if already maxitems in list
if( d->m_maxItems && selectableActionGroup()->actions().count() == d->m_maxItems) {
// remove oldest added item
delete removeAction(selectableActionGroup()->actions().first());
}
d->m_noEntriesAction->setVisible(false);
d->clearSeparator->setVisible(true);
d->clearAction->setVisible(true);
setEnabled(true);
// add file to list
const QString title = titleWithSensibleWidth(tmpName, file);
QAction* action = new QAction(title, selectableActionGroup());
addAction(action, url, tmpName);
}
void KRecentFilesAction::addAction(QAction *action, const KUrl &url, const QString &name)
{
Q_D(KRecentFilesAction);
// kDebug (129) << "KRecentFilesAction::addAction(" << action << ")";
action->setActionGroup(selectableActionGroup());
// Keep in sync with createToolBarWidget()
foreach (QToolButton* button, d->m_buttons) {
button->insertAction(button->actions().value(0), action);
}
foreach (KComboBox* comboBox, d->m_comboBoxes)
comboBox->insertAction(comboBox->actions().value(0), action);
menu()->insertAction(menu()->actions().value(0), action);
d->m_shortNames.insert( action, name );
d->m_urls.insert( action, url );
}
QAction* KRecentFilesAction::removeAction(QAction *action)
{
Q_D(KRecentFilesAction);
KSelectAction::removeAction(action);
d->m_shortNames.remove(action);
d->m_urls.remove(action);
return action;
}
void KRecentFilesAction::removeUrl( const KUrl& url )
{
Q_D(KRecentFilesAction);
for (QMap<QAction*, KUrl>::ConstIterator it = d->m_urls.constBegin(); it != d->m_urls.constEnd(); ++it) {
if (it.value() == url) {
delete removeAction(it.key());
return;
}
}
}
KUrl::List KRecentFilesAction::urls() const
{
Q_D(const KRecentFilesAction);
return d->m_urls.values();
}
void KRecentFilesAction::clear()
{
clearEntries();
emit recentListCleared();
}
void KRecentFilesAction::clearEntries()
{
Q_D(KRecentFilesAction);
KSelectAction::clear();
d->m_shortNames.clear();
d->m_urls.clear();
d->m_noEntriesAction->setVisible(true);
d->clearSeparator->setVisible(false);
d->clearAction->setVisible(false);
setEnabled(false);
}
void KRecentFilesAction::loadEntries(const KConfigGroup &config)
{
Q_D(KRecentFilesAction);
clearEntries();
QString key;
QString value;
QString nameKey;
QString nameValue;
QString title;
KUrl url;
KConfigGroup cg = config;
if (cg.name().isEmpty()) {
cg = KConfigGroup(cg.config(), "RecentFiles");
}
bool thereAreEntries = false;
// read file list
for(int i = 1; i <= d->m_maxItems; i++) {
key = QString("File%1").arg(i);
value = cg.readPathEntry(key, QString());
if (value.isEmpty()) {
continue;
}
url = KUrl(value);
// Don't restore if file doesn't exist anymore
if (url.isLocalFile() && !QFile::exists(url.toLocalFile())) {
continue;
}
// Don't restore where the url is already known (eg. broken config)
if (d->m_urls.values().contains(url)) {
continue;
}
nameKey = QString("Name%1").arg(i);
nameValue = cg.readPathEntry(nameKey, url.fileName());
title = titleWithSensibleWidth(nameValue, value);
if (!value.isNull()) {
thereAreEntries=true;
addAction(new QAction(title, selectableActionGroup()), url, nameValue);
}
}
if (thereAreEntries) {
d->m_noEntriesAction->setVisible(false);
d->clearSeparator->setVisible(true);
d->clearAction->setVisible(true);
setEnabled(true);
}
}
void KRecentFilesAction::saveEntries(const KConfigGroup &_cg)
{
Q_D(KRecentFilesAction);
QString key;
QString value;
QStringList lst = items();
KConfigGroup cg = _cg;
if (cg.name().isEmpty()) {
cg = KConfigGroup(cg.config(), "RecentFiles");
}
cg.deleteGroup();
// write file list
for (int i = 1 ; i <= selectableActionGroup()->actions().count(); i++) {
key = QString("File%1").arg(i);
// i - 1 because we started from 1
value = d->m_urls[ selectableActionGroup()->actions()[i - 1]].pathOrUrl();
cg.writePathEntry(key, value);
key = QString("Name%1" ).arg(i);
value = d->m_shortNames[selectableActionGroup()->actions()[i - 1]];
cg.writePathEntry(key, value);
}
}
/* vim: et sw=2 ts=2
*/
#include "moc_krecentfilesaction.cpp"