You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

257 lines
8.9 KiB

/* Copyright 2010 Thomas McGuire <mcguire@kde.org>
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) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
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. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tagging.h"
#include "messagetag.h"
#include "messageactions.h"
#include <Akonadi/Item>
#include <Nepomuk/Variant>
#include <Nepomuk/ResourceManager>
#include <KActionCollection>
#include <KActionMenu>
#include <KMenu>
#include <KIcon>
#include <KToggleAction>
#include <KXMLGUIClient>
#include <QSignalMapper>
using namespace KMail;
Tag::Ptr Tag::fromNepomuk( const Nepomuk::Tag& nepomukTag )
{
Tag::Ptr tag( new Tag() );
tag->tagName = nepomukTag.label();
if ( nepomukTag.symbols().isEmpty() )
tag->iconName = "mail-tagged";
else
tag->iconName = nepomukTag.symbols().first();
tag->nepomukResourceUri = nepomukTag.resourceUri();
if ( nepomukTag.hasProperty( Vocabulary::MessageTag::textColor() ) ) {
const QString name = nepomukTag.property( Vocabulary::MessageTag::textColor() ).toString();
tag->textColor = QColor( name );
}
if ( nepomukTag.hasProperty( Vocabulary::MessageTag::backgroundColor() ) ) {
const QString name = nepomukTag.property( Vocabulary::MessageTag::backgroundColor() ).toString();
tag->backgroundColor = QColor( name );
}
if ( nepomukTag.hasProperty( Vocabulary::MessageTag::font() ) ) {
const QString fontString = nepomukTag.property( Vocabulary::MessageTag::font() ).toString();
QFont font;
font.fromString( fontString );
tag->textFont = font;
}
if ( nepomukTag.hasProperty( Vocabulary::MessageTag::priority() ) ) {
tag->priority = nepomukTag.property( Vocabulary::MessageTag::priority() ).toInt();
}
else
tag->priority = -1;
if ( nepomukTag.hasProperty( Vocabulary::MessageTag::shortcut() ) ) {
tag->shortcut = KShortcut( nepomukTag.property( Vocabulary::MessageTag::shortcut() ).toString() );
}
if ( nepomukTag.hasProperty( Vocabulary::MessageTag::inToolbar() ) ) {
tag->inToolbar = nepomukTag.property( Vocabulary::MessageTag::inToolbar() ).toBool();
}
else
tag->inToolbar = true;
return tag;
}
void Tag::saveToNepomuk( SaveFlags saveFlags ) const
{
Nepomuk::Tag nepomukTag( nepomukResourceUri );
nepomukTag.setLabel( tagName );
nepomukTag.setSymbols( QStringList( iconName ) );
nepomukTag.setProperty( Vocabulary::MessageTag::priority(), priority );
nepomukTag.setProperty( Vocabulary::MessageTag::inToolbar(), inToolbar );
nepomukTag.setProperty( Vocabulary::MessageTag::shortcut(), shortcut.toString() );
if ( textColor.isValid() && saveFlags & TextColor )
nepomukTag.setProperty( Vocabulary::MessageTag::textColor(), textColor.name() );
else
nepomukTag.removeProperty( Vocabulary::MessageTag::textColor() );
if ( backgroundColor.isValid() && saveFlags & BackgroundColor )
nepomukTag.setProperty( Vocabulary::MessageTag::backgroundColor(), backgroundColor.name() );
else
nepomukTag.removeProperty( Vocabulary::MessageTag::backgroundColor() );
if ( saveFlags & Font )
nepomukTag.setProperty( Vocabulary::MessageTag::font(), textFont.toString() );
else
nepomukTag.removeProperty( Vocabulary::MessageTag::font() );
}
bool Tag::compare( Tag::Ptr &tag1, Tag::Ptr &tag2 )
{
return tag1->priority < tag2->priority;
}
QList<TagActionManager*> TagActionManager::mInstances;
TagActionManager::TagActionManager( QObject *parent, KActionCollection *actionCollection,
MessageActions *messageActions, KXMLGUIClient *guiClient )
: QObject( parent ),
mActionCollection( actionCollection ),
mMessageActions( messageActions ),
mMessageTagToggleMapper( 0 ),
mGUIClient( guiClient ),
mSopranoModel( new Soprano::Util::SignalCacheModel( Nepomuk::ResourceManager::instance()->mainModel() ) )
{
mInstances.append( this );
// Listen to Nepomuk tag updates
// ### This is way too slow for now, we use triggerUpdate() instead
/*connect( mSopranoModel.data(), SIGNAL(statementAdded(Soprano::Statement)),
SLOT(statementChanged(Soprano::Statement)) );
connect( mSopranoModel.data(), SIGNAL(statementRemoved(Soprano::Statement)),
SLOT(statementChanged(Soprano::Statement)) );*/
}
TagActionManager::~TagActionManager()
{
mInstances.removeAll( this );
}
void TagActionManager::statementChanged( Soprano::Statement statement )
{
// When a tag changes, immediatley update the actions to reflect that
if ( statement.subject().type() == Soprano::Node::ResourceNode ) {
Nepomuk::Resource res( statement.subject().uri() );
if ( res.resourceType() == Nepomuk::Tag::resourceTypeUri() ) {
createActions();
}
}
}
void TagActionManager::clearActions()
{
//Remove the tag actions from the toolbar
if ( !mToolbarActions.isEmpty() ) {
if ( mGUIClient->factory() )
mGUIClient->unplugActionList( "toolbar_messagetag_actions" );
mToolbarActions.clear();
}
//Remove the tag actions from the status menu and the action collection,
//then delete them.
foreach( KAction *action, mTagActions ) {
mMessageActions->messageStatusMenu()->removeAction( action );
// This removes and deletes the action at the same time
mActionCollection->removeAction( action );
}
mTagActions.clear();
delete mMessageTagToggleMapper;
mMessageTagToggleMapper = 0;
}
void TagActionManager::createActions()
{
clearActions();
//Use a mapper to understand which tag button is triggered
mMessageTagToggleMapper = new QSignalMapper( this );
connect( mMessageTagToggleMapper, SIGNAL( mapped( const QString& ) ),
this, SIGNAL( tagActionTriggered( const QString& ) ) );
// Build a sorted list of tags
QList<Tag::Ptr> tagList;
foreach( const Nepomuk::Tag &nepomukTag, Nepomuk::Tag::allTags() ) {
tagList.append( Tag::fromNepomuk( nepomukTag ) );
}
qSort( tagList.begin(), tagList.end(), KMail::Tag::compare );
// Create a action for each tag and plug it into various places
foreach( const Tag::Ptr &tag, tagList ) {
QString cleanName( i18n("Message Tag %1", tag->tagName ) );
cleanName.replace('&',"&&");
KToggleAction * const tagAction = new KToggleAction( KIcon( tag->iconName ),
cleanName, this );
tagAction->setShortcut( tag->shortcut );
tagAction->setIconText( tag->tagName );
mActionCollection->addAction( tag->nepomukResourceUri.toString(), tagAction );
connect( tagAction, SIGNAL( triggered( bool ) ),
mMessageTagToggleMapper, SLOT( map() ) );
// The shortcut configuration is done in the config dialog.
// The shortcut set in the shortcut dialog would not be saved back to
// the tag descriptions correctly.
tagAction->setShortcutConfigurable( false );
mMessageTagToggleMapper->setMapping( tagAction, tag->nepomukResourceUri.toString() );
mTagActions.insert( tag->nepomukResourceUri.toString(), tagAction );
mMessageActions->messageStatusMenu()->menu()->addAction( tagAction );
if ( tag->inToolbar )
mToolbarActions.append( tagAction );
}
if ( !mToolbarActions.isEmpty() && mGUIClient->factory() ) {
mGUIClient->plugActionList( "toolbar_messagetag_actions", mToolbarActions );
}
}
void TagActionManager::updateActionStates( int numberOfSelectedMessages,
const Akonadi::Item &selectedItem )
{
QMap<QString,KToggleAction*>::const_iterator it = mTagActions.constBegin();
if ( 1 == numberOfSelectedMessages )
{
Q_ASSERT( selectedItem.isValid() );
Nepomuk::Resource itemResource( selectedItem.url() );
for ( ; it != mTagActions.constEnd(); it++ ) {
const bool hasTag = itemResource.tags().contains( Nepomuk::Tag( it.key() ) );
it.value()->setChecked( hasTag );
it.value()->setEnabled( true );
}
}
else if ( numberOfSelectedMessages > 1 ) {
for ( ; it != mTagActions.constEnd(); it++ ) {
Nepomuk::Tag tag( it.key() );
it.value()->setChecked( false );
it.value()->setEnabled( true );
it.value()->setText( i18n("Toggle Message Tag %1", tag.label() ) );
}
}
else {
for ( ; it != mTagActions.constEnd(); it++ ) {
it.value()->setEnabled( false );
}
}
}
void TagActionManager::triggerUpdate()
{
foreach( TagActionManager *instance, mInstances ) {
instance->createActions();
}
}