1 /***************************************************************************
2 phrasetree.cpp - description
4 begin : Don Okt 24 2002
5 copyright : (C) 2002 by Gunnar Schmi Dt
6 email : kmouth@schmi-dt.de
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 ***************************************************************************/
21 #include <kstdaccel.h>
22 #include <kiconloader.h>
23 #include <kmessagebox.h>
24 #include <kactionmenu.h>
25 #include <ktoolbarpopupaction.h>
26 #include "phrasetree.h"
27 #include "phrasebookdialog.h"
28 #include "phrasebook.h"
34 PhraseTreeItem::PhraseTreeItem (Q3ListView
*parent
, Q3ListViewItem
*after
, QString phrase
, KShortcut shortcut
, QPixmap icon
)
35 : K3ListViewItem (parent
, after
, phrase
)
39 setText(1, cutValue
.toString());
41 setExpandable (false);
44 PhraseTreeItem::PhraseTreeItem (Q3ListViewItem
*parent
, Q3ListViewItem
*after
, QString phrase
, KShortcut shortcut
, QPixmap icon
)
45 : K3ListViewItem (parent
, after
, phrase
)
49 setText(1, cutValue
.toString());
51 setExpandable (false);
53 PhraseTreeItem::PhraseTreeItem (Q3ListView
*parent
, Q3ListViewItem
*after
, QString name
, QPixmap icon
)
54 : K3ListViewItem (parent
, after
, name
)
56 isPhraseValue
= false;
60 PhraseTreeItem::PhraseTreeItem (Q3ListViewItem
*parent
, Q3ListViewItem
*after
, QString name
, QPixmap icon
)
61 : K3ListViewItem (parent
, after
, name
)
63 isPhraseValue
= false;
67 bool PhraseTreeItem::isPhrase () {
70 KShortcut
PhraseTreeItem::cut () {
73 void PhraseTreeItem::setCut (KShortcut cut
) {
75 setText(1, cut
.toString());
78 // ***************************************************************************
80 PhraseTree::PhraseTree (QWidget
*parent
, const char *name
)
84 phrasebook_open
= KGlobal::iconLoader()->loadIcon("phrasebook", K3Icon::Small
);
85 phrasebook_closed
= KGlobal::iconLoader()->loadIcon("phrasebook_closed", K3Icon::Small
);
86 phrase
= KGlobal::iconLoader()->loadIcon("phrase", K3Icon::Small
);
88 connect (this, SIGNAL(expanded (Q3ListViewItem
*)), this, SLOT(itemExpanded (Q3ListViewItem
*)));
89 connect (this, SIGNAL(collapsed (Q3ListViewItem
*)), this, SLOT(itemCollapsed (Q3ListViewItem
*)));
92 PhraseTree::~PhraseTree (){
95 namespace PhraseTreePrivate
{
96 Q3ListViewItem
*prevSibling (Q3ListViewItem
*item
) {
97 Q3ListViewItem
*parent
= item
->parent();
98 Q3ListViewItem
*above
= item
->itemAbove();
103 while (above
->parent() != parent
)
104 above
= above
->parent();
109 bool findAbovePosition (Q3ListViewItem
*item
,
110 Q3ListViewItem
**newParent
,
111 Q3ListViewItem
**newAbove
)
116 Q3ListViewItem
*parent
= item
->parent();
117 Q3ListViewItem
*above
= item
->itemAbove();
121 else if (above
== parent
) {
122 *newParent
= parent
->parent();
123 *newAbove
= prevSibling (parent
);
126 else if (above
->parent() == parent
) {
128 *newAbove
= prevSibling (above
);
132 while (above
->parent()->parent() != parent
)
133 above
= above
->parent();
134 *newParent
= above
->parent();
140 bool findBelowPosition (Q3ListViewItem
*item
,
141 Q3ListViewItem
**newParent
,
142 Q3ListViewItem
**newAbove
)
147 Q3ListViewItem
*parent
= item
->parent();
148 Q3ListViewItem
*below
= item
->nextSibling();
150 if (parent
== 0 && below
== 0)
152 else if (parent
!= 0 && below
== 0) {
153 *newParent
= parent
->parent();
157 else if (below
->isOpen()) {
169 bool findRightPosition (Q3ListViewItem
*item
,
170 Q3ListViewItem
**newParent
,
171 Q3ListViewItem
**newAbove
)
176 Q3ListViewItem
*above
= prevSibling (item
);
180 else if (((PhraseTreeItem
*)above
)->isPhrase())
183 above
->setOpen(true);
186 above
= (*newParent
)->firstChild();
189 above
= above
->nextSibling();
195 bool findLeftPosition (Q3ListViewItem
*item
,
196 Q3ListViewItem
**newParent
,
197 Q3ListViewItem
**newAbove
)
202 Q3ListViewItem
*parent
= item
->parent();
207 *newParent
= parent
->parent();
214 void PhraseTree::moveItem (Q3ListViewItem
*item
,
215 Q3ListViewItem
*parent
,
216 Q3ListViewItem
*above
)
219 if (item
->parent() == 0)
222 item
->parent()->takeItem (item
);
227 parent
->insertItem (item
);
229 item
->moveItem(above
);
233 bool PhraseTree::hasSelectedItems() {
234 Q3ListViewItem
*i
= firstChild();
242 if (i
->firstChild() != 0) {
247 while ((i
!= 0) && (i
->nextSibling() == 0)) {
252 i
= i
->nextSibling();
260 void PhraseTree::deleteSelectedItems() {
261 Q3ListViewItem
*i
= firstChild();
264 Q3ListViewItem
*deleteItem
= 0;
269 if ((i
->firstChild() != 0) && (!i
->isSelected())) {
273 while ((i
!= 0) && (i
->nextSibling() == 0)) {
277 i
= i
->nextSibling();
279 if (deleteItem
!= 0) {
287 void PhraseTree::keyPressEvent (QKeyEvent
*e
) {
288 if (e
->modifiers() & Qt::AltModifier
) {
289 if (e
->key() == Qt::Key_Up
) {
290 Q3ListViewItem
*item
= currentItem();
291 if ((item
!= 0) && (item
->isSelected())) {
292 Q3ListViewItem
*parent
;
293 Q3ListViewItem
*above
;
295 if (PhraseTreePrivate::findAbovePosition (item
, &parent
, &above
)) {
296 moveItem(item
, parent
, above
);
297 setCurrentItem (item
);
298 item
->setSelected(true);
304 else if (e
->key() == Qt::Key_Down
) {
305 Q3ListViewItem
*item
= currentItem();
306 if ((item
!= 0) && (item
->isSelected())) {
307 Q3ListViewItem
*parent
;
308 Q3ListViewItem
*above
;
310 if (PhraseTreePrivate::findBelowPosition (item
, &parent
, &above
)) {
311 moveItem(item
, parent
, above
);
312 setCurrentItem (item
);
313 item
->setSelected(true);
319 else if (e
->key() == Qt::Key_Left
) {
320 Q3ListViewItem
*item
= currentItem();
321 if ((item
!= 0) && (item
->isSelected())) {
322 Q3ListViewItem
*parent
;
323 Q3ListViewItem
*above
;
325 if (PhraseTreePrivate::findLeftPosition (item
, &parent
, &above
)) {
326 moveItem(item
, parent
, above
);
327 setCurrentItem (item
);
328 item
->setSelected(true);
334 else if (e
->key() == Qt::Key_Right
) {
335 Q3ListViewItem
*item
= currentItem();
336 if ((item
!= 0) && (item
->isSelected())) {
337 Q3ListViewItem
*parent
;
338 Q3ListViewItem
*above
;
340 if (PhraseTreePrivate::findRightPosition (item
, &parent
, &above
)) {
341 moveItem(item
, parent
, above
);
342 setCurrentItem (item
);
343 item
->setSelected(true);
350 K3ListView::keyPressEvent(e
);
353 PhraseTreeItem
*PhraseTree::insertPhrase (Q3ListViewItem
*parent
, Q3ListViewItem
*after
, QString phrase
, QString shortcut
) {
354 KShortcut cut
= KShortcut(shortcut
);
355 if (isKeyPresent (cut
, 0, false))
356 cut
= KShortcut(QString());
359 return new PhraseTreeItem (this, after
, phrase
, cut
, this->phrase
);
361 return new PhraseTreeItem (parent
, after
, phrase
, cut
, this->phrase
);
364 PhraseTreeItem
*PhraseTree::insertBook (Q3ListViewItem
*parent
, Q3ListViewItem
*after
, QString name
) {
366 return new PhraseTreeItem (this, after
, name
, phrasebook_closed
);
368 return new PhraseTreeItem (parent
, after
, name
, phrasebook_closed
);
371 Q3ListViewItem
*PhraseTree::addBook (Q3ListViewItem
*parent
, Q3ListViewItem
*after
, PhraseBook
*book
) {
372 Q3ListViewItem
*last
= after
;
374 PhraseBookEntryList::iterator it
;
375 for (it
= book
->begin(); it
!= book
->end(); ++it
) {
376 int newLevel
= (*it
).getLevel();
377 while (level
< newLevel
) {
378 parent
= insertBook(parent
, last
, "");
382 while (level
> newLevel
) {
385 parent
= parent
->parent();
389 if ((*it
).isPhrase()) {
390 Phrase phrase
= (*it
).getPhrase();
391 last
= insertPhrase (parent
, last
, phrase
.getPhrase(), phrase
.getShortcut());
394 Phrase phrase
= (*it
).getPhrase();
395 parent
= insertBook(parent
, last
, phrase
.getPhrase());
403 parent
= parent
->parent();
409 void PhraseTree::fillBook (PhraseBook
*book
, bool respectSelection
) {
410 Q3ListViewItem
*i
= firstChild();
415 if (i
->isSelected() || !respectSelection
|| level
> 0) {
416 PhraseTreeItem
*it
= (PhraseTreeItem
*)i
;
417 Phrase
phrase(it
->text(0), it
->cut().toString());
418 *book
+= PhraseBookEntry(phrase
, level
, it
->isPhrase());
421 if (i
->firstChild() != 0) {
422 if (i
->isSelected() || !respectSelection
|| level
> 0)
427 while ((i
!= 0) && (i
->nextSibling() == 0)) {
433 i
= i
->nextSibling();
439 Q3DragObject
*PhraseTree::dragObject () {
440 return dragObject (true);
443 Q3DragObject
*PhraseTree::dragObject (bool isDependent
) {
445 fillBook (&book
, true);
447 return new PhraseBookDrag(&book
, viewport());
448 return new PhraseBookDrag(&book
);
451 bool PhraseTree::acceptDrag (QDropEvent
* event
) const {
452 if (K3ListView::acceptDrag (event
))
455 return PhraseBookDrag::canDecode(event
);
458 // Returns iSeq index if cut2 has a sequence of equal or higher priority
459 // to a sequence in cut, else -1
460 static int keyConflict (const KShortcut
& cut
, const KShortcut
& cut2
) {
461 int nbCut
= cut
.count();
462 int nbCut2
= cut2
.count();
463 for (int iSeq
= 0; iSeq
< nbCut
; iSeq
++) {
464 for (int iSeq2
= 0; iSeq2
<= iSeq
&& iSeq2
< nbCut2
; iSeq2
++) {
465 if (cut
[iSeq
] == cut2
[iSeq2
])
472 void PhraseTree::_warning (const QKeySequence
& cut
, QString sAction
, const QString
&sTitle
) {
473 sAction
= sAction
.trimmed();
476 i18n("The '%1' key combination has already been allocated "
478 "Please choose a unique key combination.",
479 cut
.toString(), sAction
);
481 KMessageBox::sorry( this, s
, sTitle
);
484 bool PhraseTree::isStdAccelPresent (const KShortcut
& cut
, bool warnUser
) {
485 for (int iSeq
= 0; iSeq
< cut
.count(); iSeq
++) {
486 const QKeySequence
& seq
= cut
[iSeq
];
488 KStdAccel::StdAccel id
= KStdAccel::findStdAccel( seq
);
489 if( id
!= KStdAccel::AccelNone
490 && keyConflict (cut
, KStdAccel::shortcut(id
)) > -1)
494 i18n("the standard \"%1\" action", KStdAccel::label(id
)),
495 i18n("Conflict with Standard Application Shortcut"));
502 bool PhraseTree::isGlobalKeyPresent (const KShortcut
& cut
, bool warnUser
) {
503 QMap
<QString
, QString
> mapEntry
= KGlobal::config()->entryMap ("Global Shortcuts");
504 QMap
<QString
, QString
>::Iterator it
;
505 for (it
= mapEntry
.begin(); it
!= mapEntry
.end(); ++it
) {
506 int iSeq
= keyConflict (cut
, KShortcut(*it
));
510 i18n("the global \"%1\" action", it
.key()),
511 i18n("Conflict with Global Shortcuts"));
518 bool PhraseTree::isPhraseKeyPresent (const KShortcut
& cut
, PhraseTreeItem
* cutItem
, bool warnUser
) {
519 for (Q3ListViewItemIterator
it(this); it
.current(); ++it
) {
520 PhraseTreeItem
* item
= dynamic_cast<PhraseTreeItem
*>(it
.current());
521 if ((item
!= 0) && (item
!= cutItem
)) {
522 int iSeq
= keyConflict (cut
, item
->cut());
526 i18n("an other phrase"),
527 i18n("Key Conflict"));
535 bool PhraseTree::isKeyPresent (const KShortcut
& cut
, PhraseTreeItem
* cutItem
, bool warnUser
) {
536 if (isStdAccelPresent (cut
, warnUser
))
539 if (isGlobalKeyPresent (cut
, warnUser
))
542 if (isPhraseKeyPresent (cut
, cutItem
, warnUser
))
548 void PhraseTree::itemExpanded (Q3ListViewItem
*item
) {
549 PhraseTreeItem
*i
= (PhraseTreeItem
*)item
;
551 i
->setPixmap(0, phrasebook_open
);
554 void PhraseTree::itemCollapsed (Q3ListViewItem
*item
) {
555 PhraseTreeItem
*i
= (PhraseTreeItem
*)item
;
557 i
->setPixmap(0, phrasebook_closed
);
560 // ***************************************************************************
562 #include "phrasetree.moc"