28 #include <KActionCollection>
31 #include <KMessageBox>
35 #include <QItemSelectionModel>
37 using namespace MailCommon;
39 class SnippetsManager::Private
43 : q( qq ), mEditor( 0 ), mParent( parent ), mDirty( false )
47 QModelIndex currentGroupIndex()
const;
49 void selectionChanged();
55 void addSnippetGroup();
56 void editSnippetGroup();
57 void deleteSnippetGroup();
59 void insertSelectedSnippet();
60 void insertActionSnippet();
62 void updateActionCollection(
const QString &oldName,
const QString &newName,
63 const QKeySequence &keySequence,
const QString &
text );
65 QString replaceVariables(
const QString &
text );
66 QModelIndex createGroup(
const QString &groupName );
67 void createSnippet(
const QModelIndex &groupIndex,
const QString &snippetName,
68 const QString &snippetText,
const QString &snippetKeySequence );
71 void loadFromOldFormat(
const KConfigGroup &group );
76 QItemSelectionModel *mSelectionModel;
77 KActionCollection *mActionCollection;
79 QByteArray mEditorInsertMethod;
80 QMap<QString, QString> mSavedVariables;
82 QAction *mAddSnippetAction;
83 QAction *mEditSnippetAction;
84 QAction *mDeleteSnippetAction;
85 QAction *mAddSnippetGroupAction;
86 QAction *mEditSnippetGroupAction;
87 QAction *mDeleteSnippetGroupAction;
88 QAction *mInsertSnippetAction;
93 QModelIndex SnippetsManager::Private::currentGroupIndex()
const
95 if ( mSelectionModel->selectedIndexes().isEmpty() ) {
99 const QModelIndex index = mSelectionModel->selectedIndexes().first();
103 return mModel->parent( index );
107 void SnippetsManager::Private::selectionChanged()
109 const bool itemSelected = !mSelectionModel->selectedIndexes().isEmpty();
111 if ( itemSelected ) {
112 const QModelIndex index = mSelectionModel->selectedIndexes().first();
115 mEditSnippetAction->setEnabled(
false );
116 mDeleteSnippetAction->setEnabled(
false );
117 mEditSnippetGroupAction->setEnabled(
true );
118 mDeleteSnippetGroupAction->setEnabled(
true );
119 mInsertSnippetAction->setEnabled(
false );
121 mEditSnippetAction->setEnabled(
true );
122 mDeleteSnippetAction->setEnabled(
true );
123 mEditSnippetGroupAction->setEnabled(
false );
124 mDeleteSnippetGroupAction->setEnabled(
false );
125 mInsertSnippetAction->setEnabled(
true );
128 mEditSnippetAction->setEnabled(
false );
129 mDeleteSnippetAction->setEnabled(
false );
130 mEditSnippetGroupAction->setEnabled(
false );
131 mDeleteSnippetGroupAction->setEnabled(
false );
132 mInsertSnippetAction->setEnabled(
false );
136 void SnippetsManager::Private::addSnippet()
138 const bool noGroupAvailable = ( mModel->rowCount() == 0 );
140 if ( noGroupAvailable ) {
142 if ( !mModel->insertRow( mModel->rowCount(), QModelIndex() ) ) {
146 const QModelIndex groupIndex = mModel->index( mModel->rowCount() - 1, 0, QModelIndex() );
149 mSelectionModel->select( groupIndex, QItemSelectionModel::ClearAndSelect );
152 QPointer<SnippetDialog> dlg =
new SnippetDialog( mActionCollection,
false, mParent );
153 dlg->setWindowTitle( i18nc(
"@title:window",
"Add Snippet" ) );
154 dlg->setGroupModel( mModel );
155 dlg->setGroupIndex( currentGroupIndex() );
158 const QModelIndex groupIndex = dlg->groupIndex();
160 if ( !mModel->insertRow( mModel->rowCount( groupIndex ), groupIndex ) ) {
165 const QModelIndex index = mModel->index( mModel->rowCount( groupIndex ) - 1, 0, groupIndex );
170 updateActionCollection( QString(), dlg->name(), dlg->keySequence(), dlg->text() );
176 void SnippetsManager::Private::dndDone()
181 void SnippetsManager::Private::editSnippet()
183 QModelIndex index = mSelectionModel->selectedIndexes().first();
188 const QModelIndex oldGroupIndex = currentGroupIndex();
192 QPointer<SnippetDialog> dlg =
new SnippetDialog( mActionCollection,
false, mParent );
193 dlg->setWindowTitle( i18nc(
"@title:window",
"Edit Snippet" ) );
194 dlg->setGroupModel( mModel );
195 dlg->setGroupIndex( oldGroupIndex );
196 dlg->setName( oldSnippetName );
199 QKeySequence::fromString(
204 const QModelIndex newGroupIndex = dlg->groupIndex();
206 if ( oldGroupIndex != newGroupIndex ) {
207 mModel->removeRow( index.row(), oldGroupIndex );
208 mModel->insertRow( mModel->rowCount( newGroupIndex ), newGroupIndex );
210 index = mModel->index( mModel->rowCount( newGroupIndex ) - 1, 0, newGroupIndex );
217 updateActionCollection( oldSnippetName, dlg->name(), dlg->keySequence(), dlg->text() );
223 void SnippetsManager::Private::deleteSnippet()
225 const QModelIndex index = mSelectionModel->selectedIndexes().first();
229 if ( KMessageBox::warningContinueCancel(
232 "Do you really want to remove snippet \"%1\"?<nl/>"
233 "<warning>There is no way to undo the removal.</warning>", snippetName ),
235 KStandardGuiItem::remove() ) == KMessageBox::Cancel ) {
239 mModel->removeRow( index.row(), currentGroupIndex() );
241 updateActionCollection( snippetName, QString(), QKeySequence(), QString() );
245 void SnippetsManager::Private::addSnippetGroup()
247 QPointer<SnippetDialog> dlg =
new SnippetDialog( mActionCollection,
true, mParent );
248 dlg->setWindowTitle( i18nc(
"@title:window",
"Add Group" ) );
252 if ( !mModel->insertRow( mModel->rowCount(), QModelIndex() ) ) {
253 kDebug() <<
"unable to insert row";
258 const QModelIndex groupIndex = mModel->index( mModel->rowCount() - 1, 0, QModelIndex() );
265 void SnippetsManager::Private::editSnippetGroup()
267 const QModelIndex groupIndex = currentGroupIndex();
272 QPointer<SnippetDialog> dlg =
new SnippetDialog( mActionCollection,
true, mParent );
273 dlg->setWindowTitle( i18nc(
"@title:window",
"Edit Group" ) );
275 dlg->setName( oldGroupName );
278 if (oldGroupName == dlg->name()) {
289 void SnippetsManager::Private::deleteSnippetGroup()
291 const QModelIndex groupIndex = currentGroupIndex();
292 if ( !groupIndex.isValid() ) {
298 if ( mModel->rowCount( groupIndex ) > 0 ) {
299 if ( KMessageBox::warningContinueCancel(
302 "Do you really want to remove group \"%1\" along with all its snippets?<nl/>"
303 "<warning>There is no way to undo the removal.</warning>", groupName ),
305 KStandardGuiItem::remove() ) == KMessageBox::Cancel ) {
309 if ( KMessageBox::warningContinueCancel(
312 "Do you really want to remove group \"%1\"?", groupName ),
314 KStandardGuiItem::remove() ) == KMessageBox::Cancel ) {
319 mModel->removeRow( groupIndex.row(), QModelIndex() );
323 void SnippetsManager::Private::insertSelectedSnippet()
329 if ( !mSelectionModel->hasSelection() ) {
333 const QModelIndex index = mSelectionModel->selectedIndexes().first();
339 QMetaObject::invokeMethod( mEditor, mEditorInsertMethod, Qt::DirectConnection,
340 Q_ARG( QString, text ) );
343 void SnippetsManager::Private::insertActionSnippet()
349 QAction *action = qobject_cast<QAction*>( q->sender() );
354 const QString text = replaceVariables( action->property(
"snippetText" ).toString() );
355 QMetaObject::invokeMethod( mEditor, mEditorInsertMethod, Qt::DirectConnection,
356 Q_ARG( QString, text ) );
359 void SnippetsManager::Private::updateActionCollection(
const QString &oldName,
360 const QString &newName,
361 const QKeySequence &keySequence,
362 const QString &text )
365 if ( !oldName.isEmpty() ) {
366 const QString actionName = i18nc(
"@action",
"Snippet %1", oldName );
367 const QString normalizedName = QString( actionName ).replace( QLatin1Char(
' '), QLatin1Char(
'_') );
369 QAction *action = mActionCollection->action( normalizedName );
371 mActionCollection->removeAction( action );
375 if ( !newName.isEmpty() ) {
376 const QString actionName = i18nc(
"@action",
"Snippet %1", newName );
377 const QString normalizedName = QString( actionName ).replace( QLatin1Char(
' '), QLatin1Char(
'_') );
380 mActionCollection->addAction( normalizedName, q, SLOT(insertActionSnippet()) );
381 action->setProperty(
"snippetText", text );
382 action->setText( actionName );
383 action->setShortcut( keySequence );
387 QString SnippetsManager::Private::replaceVariables(
const QString &text )
389 QString result =
text;
390 QString variableName;
391 QString variableValue;
392 QMap<QString, QString> localVariables( mSavedVariables );
398 iFound = text.indexOf( QRegExp( QLatin1String(
"\\$[A-Za-z-_0-9\\s]*\\$") ), iEnd + 1 );
400 iEnd = text.indexOf( QLatin1Char(
'$'), iFound + 1 ) + 1;
402 variableName = text.mid( iFound, iEnd - iFound );
404 if ( variableName != QLatin1String(
"$$" ) ) {
405 if ( !localVariables.contains( variableName ) ) {
407 QPointer<SnippetVariableDialog> dlg =
new SnippetVariableDialog( variableName, &mSavedVariables, mParent );
410 if ( dlg->saveVariableIsChecked() ) {
413 variableValue = dlg->variableValue();
420 variableValue = localVariables.value( variableName );
423 variableValue = QLatin1Char(
'$');
426 result.replace( variableName, variableValue );
427 localVariables[ variableName ] = variableValue;
429 }
while ( iFound != -1 );
434 QModelIndex SnippetsManager::Private::createGroup(
const QString &groupName )
436 mModel->insertRow( mModel->rowCount(), QModelIndex() );
437 const QModelIndex groupIndex = mModel->index( mModel->rowCount() - 1, 0, QModelIndex() );
442 void SnippetsManager::Private::createSnippet(
const QModelIndex &groupIndex,
443 const QString &snippetName,
444 const QString &snippetText,
445 const QString &snippetKeySequence )
448 mModel->insertRow( mModel->rowCount( groupIndex ), groupIndex );
449 const QModelIndex index = mModel->index( mModel->rowCount( groupIndex ) - 1, 0, groupIndex );
455 updateActionCollection( QString(),
457 QKeySequence::fromString( snippetKeySequence ),
461 void SnippetsManager::Private::loadFromOldFormat(
const KConfigGroup &group )
466 int iCount = group.readEntry(
"snippetGroupCount", -1 );
467 QMap< int, QModelIndex> listGroup;
468 for (
int i=0; i<iCount; ++i ) {
469 const QString strNameVal =
470 group.readEntry( QString::fromLatin1(
"snippetGroupName_%1" ).arg( i ), QString() );
473 group.readEntry( QString::fromLatin1(
"snippetGroupId_%1" ).arg( i ), -1 );
477 if ( !strNameVal.isEmpty() && iIdVal != -1 ) {
479 const QModelIndex groupIndex = createGroup( strNameVal );
480 listGroup.insert( iIdVal, groupIndex );
490 if ( iCount != -1 ) {
491 iCount = group.readEntry(
"snippetCount", 0 );
492 for (
int i=0; i<iCount; ++i ) {
493 const QString snippetName =
494 group.readEntry( QString::fromLatin1(
"snippetName_%1" ).arg( i ), QString() );
496 const QString snippetText =
497 group.readEntry( QString::fromLatin1(
"snippetText_%1" ).arg( i ), QString() );
499 const int iParentVal =
500 group.readEntry( QString::fromLatin1(
"snippetParent_%1" ).arg( i ), -1 );
502 if ( !snippetText.isEmpty() &&
503 !snippetName.isEmpty() &&
505 const QString snippetKeySequence =
506 group.readEntry( QString::fromLatin1(
"snippetShortcut_%1" ).arg( i ), QString() );
508 const QModelIndex groupIndex = listGroup.value( iParentVal );
509 createSnippet( groupIndex, snippetName, snippetText, snippetKeySequence );
513 iCount = group.readEntry(
"snippetSavedCount", 0 );
515 for (
int i=1; i<=iCount; ++i ) {
516 const QString variableKey =
517 group.readEntry( QString::fromLatin1(
"snippetSavedName_%1" ).arg( i ), QString() );
519 const QString variableValue =
520 group.readEntry( QString::fromLatin1(
"snippetSavedVal_%1" ).arg( i ), QString() );
522 mSavedVariables.insert( variableKey, variableValue );
527 void SnippetsManager::Private::load()
529 const KSharedConfig::Ptr config =
530 KSharedConfig::openConfig( QLatin1String(
"kmailsnippetrc"), KConfig::NoGlobals );
532 const KConfigGroup snippetPartGroup = config->group(
"SnippetPart" );
535 if ( snippetPartGroup.hasKey(
"snippetCount" ) ) {
536 loadFromOldFormat( snippetPartGroup );
538 const int groupCount = snippetPartGroup.readEntry(
"snippetGroupCount", 0 );
540 for (
int i = 0; i < groupCount; ++i ) {
541 const KConfigGroup group =
542 config->group( QString::fromLatin1(
"SnippetGroup_%1" ).arg ( i ) );
544 const QString groupName = group.readEntry(
"Name" );
547 QModelIndex groupIndex = createGroup( groupName );
549 const int snippetCount = group.readEntry(
"snippetCount", 0 );
550 for (
int j = 0; j < snippetCount; ++j ) {
551 const QString snippetName =
552 group.readEntry( QString::fromLatin1(
"snippetName_%1" ).arg( j ), QString() );
554 const QString snippetText =
555 group.readEntry( QString::fromLatin1(
"snippetText_%1" ).arg( j ), QString() );
557 const QString snippetKeySequence =
558 group.readEntry( QString::fromLatin1(
"snippetKeySequence_%1" ).arg( j ), QString() );
560 createSnippet( groupIndex, snippetName, snippetText, snippetKeySequence );
564 mSavedVariables.clear();
565 const KConfigGroup group = config->group(
"SavedVariablesPart" );
566 const int variablesCount = group.readEntry(
"variablesCount", 0 );
568 for (
int i = 0; i < variablesCount; ++i ) {
569 const QString variableKey =
570 group.readEntry( QString::fromLatin1(
"variableName_%1" ).arg( i ), QString() );
572 const QString variableValue =
573 group.readEntry( QString::fromLatin1(
"variableValue_%1" ).arg( i ), QString() );
575 mSavedVariables.insert( variableKey, variableValue );
580 void SnippetsManager::Private::save()
586 KSharedConfig::Ptr config = KSharedConfig::openConfig( QLatin1String(
"kmailsnippetrc"), KConfig::NoGlobals );
589 foreach (
const QString &group, config->groupList() ) {
590 config->deleteGroup( group );
594 KConfigGroup group = config->group(
"SnippetPart" );
596 const int groupCount = mModel->rowCount();
597 group.writeEntry(
"snippetGroupCount", groupCount );
599 for (
int i = 0; i < groupCount; ++i ) {
600 const QModelIndex groupIndex = mModel->index( i, 0, QModelIndex() );
603 KConfigGroup group = config->group( QString::fromLatin1(
"SnippetGroup_%1" ).arg ( i ) );
604 group.writeEntry(
"Name", groupName );
606 const int snippetCount = mModel->rowCount( groupIndex );
608 group.writeEntry(
"snippetCount", snippetCount );
609 for (
int j = 0; j < snippetCount; ++j ) {
610 const QModelIndex index = mModel->index( j, 0, groupIndex );
616 group.writeEntry( QString::fromLatin1(
"snippetName_%1" ).arg( j ), snippetName );
617 group.writeEntry( QString::fromLatin1(
"snippetText_%1" ).arg( j ), snippetText );
618 group.writeEntry( QString::fromLatin1(
"snippetKeySequence_%1" ).arg( j ),
619 snippetKeySequence );
624 KConfigGroup group = config->group(
"SavedVariablesPart" );
626 const int variablesCount = mSavedVariables.count();
627 group.writeEntry(
"variablesCount", variablesCount );
630 QMapIterator<QString, QString> it( mSavedVariables );
631 while ( it.hasNext() ) {
633 group.writeEntry( QString::fromLatin1(
"variableName_%1" ).arg( counter ), it.key() );
634 group.writeEntry( QString::fromLatin1(
"variableValue_%1" ).arg( counter ), it.value() );
645 :
QObject( parent ), d( new Private( this, widget ) )
648 d->mSelectionModel =
new QItemSelectionModel( d->mModel );
649 d->mActionCollection = actionCollection;
651 d->mAddSnippetAction =
new QAction( i18n(
"Add Snippet..." ),
this );
652 d->mEditSnippetAction =
new QAction( i18n(
"Edit Snippet..." ),
this );
653 d->mEditSnippetAction->setIcon( KIcon( QLatin1String(
"document-properties") ) );
654 d->mDeleteSnippetAction =
new QAction( i18n(
"Remove Snippet" ),
this );
655 d->mDeleteSnippetAction->setIcon( KIcon( QLatin1String(
"edit-delete") ) );
657 d->mAddSnippetGroupAction =
new QAction( i18n(
"Add Group..." ),
this );
658 d->mEditSnippetGroupAction =
new QAction( i18n(
"Rename Group..." ),
this );
659 d->mEditSnippetGroupAction->setIcon( KIcon( QLatin1String(
"edit-rename") ) );
660 d->mDeleteSnippetGroupAction =
new QAction( i18n(
"Remove Group" ),
this );
661 d->mDeleteSnippetGroupAction->setIcon( KIcon( QLatin1String(
"edit-delete") ) );
663 d->mInsertSnippetAction =
new QAction( i18n(
"Insert Snippet" ),
this );
665 connect( d->mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
666 this, SLOT(selectionChanged()) );
667 connect( d->mModel, SIGNAL(dndDone()), SLOT(dndDone()) );
669 connect( d->mAddSnippetAction, SIGNAL(triggered(
bool)), SLOT(addSnippet()) );
670 connect( d->mEditSnippetAction, SIGNAL(triggered(
bool)), SLOT(editSnippet()) );
671 connect( d->mDeleteSnippetAction, SIGNAL(triggered(
bool)), SLOT(deleteSnippet()) );
673 connect( d->mAddSnippetGroupAction, SIGNAL(triggered(
bool)), SLOT(addSnippetGroup()) );
674 connect( d->mEditSnippetGroupAction, SIGNAL(triggered(
bool)), SLOT(editSnippetGroup()) );
675 connect( d->mDeleteSnippetGroupAction, SIGNAL(triggered(
bool)), SLOT(deleteSnippetGroup()) );
677 connect( d->mInsertSnippetAction, SIGNAL(triggered(
bool)), SLOT(insertSelectedSnippet()) );
679 d->selectionChanged();
691 const char *dropSignal )
694 d->mEditorInsertMethod = insertSnippetMethod;
698 editor->metaObject()->indexOfSignal(
699 QMetaObject::normalizedSignature( dropSignal + 1 ).data() );
701 connect( editor, dropSignal,
this, SLOT(insertSelectedSnippet()) );
713 return d->mSelectionModel;
718 return d->mAddSnippetAction;
723 return d->mEditSnippetAction;
728 return d->mDeleteSnippetAction;
733 return d->mAddSnippetGroupAction;
738 return d->mEditSnippetGroupAction;
743 return d->mDeleteSnippetGroupAction;
748 return d->mInsertSnippetAction;
753 if ( d->mSelectionModel->selectedIndexes().isEmpty() ) {
762 if ( d->mSelectionModel->selectedIndexes().isEmpty() ) {
769 #include "snippetsmanager.moc"
Returns whether the index represents a group.
The key sequence to activate a snippet.
SnippetsManager(KActionCollection *actionCollection, QObject *parent=0, QWidget *widget=0)
Creates a new snippets manager.
void setEditor(QObject *editor, const char *insertSnippetMethod, const char *dropSignal)
Sets the editor object the snippet manager will act on.
QAction * insertSnippetAction() const
Returns the action that handles inserting a snippet into the editor.
QAbstractItemModel * model() const
Returns the model that represents the snippets.
The name of a snippet or group.
QAction * deleteSnippetGroupAction() const
Returns the action that handles deleting the currently selected snippet group.
QItemSelectionModel * selectionModel() const
Returns the selection model that is used by the manager to select the snippet or snippet group to wor...
~SnippetsManager()
Destroys the snippets manager.
QAction * deleteSnippetAction() const
Returns the action that handles deleting the currently selected snippet.
QAction * editSnippetGroupAction() const
Returns the action that handles editing the currently selected snippet group.
QString selectedName() const
Returns the name of the currently selected snippet or snippet group.
bool snippetGroupSelected() const
Returns whether the currently selected item is a snippet group.
QAction * editSnippetAction() const
Returns the action that handles editing the currently selected snippet.
QAction * addSnippetAction() const
Returns the action that handles adding new snippets.
QAction * addSnippetGroupAction() const
Returns the action that handles adding new snippet groups.