summaryrefslogtreecommitdiffstats
path: root/kmouth/phrasebook/phrasetree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kmouth/phrasebook/phrasetree.cpp')
-rw-r--r--kmouth/phrasebook/phrasetree.cpp556
1 files changed, 556 insertions, 0 deletions
diff --git a/kmouth/phrasebook/phrasetree.cpp b/kmouth/phrasebook/phrasetree.cpp
new file mode 100644
index 0000000..57d4f5e
--- /dev/null
+++ b/kmouth/phrasebook/phrasetree.cpp
@@ -0,0 +1,556 @@
+/***************************************************************************
+ phrasetree.cpp - description
+ -------------------
+ begin : Don Okt 24 2002
+ copyright : (C) 2002 by Gunnar Schmi Dt
+ email : kmouth@schmi-dt.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kaction.h>
+#include <kstdaccel.h>
+#include <kshortcutlist.h>
+#include <kactionshortcutlist.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+
+#include "phrasetree.h"
+#include "phrasebookdialog.h"
+#include "phrasebook.h"
+
+PhraseTreeItem::PhraseTreeItem (QListView *parent, QListViewItem *after, QString phrase, KShortcut shortcut, QPixmap icon)
+ : KListViewItem (parent, after, phrase)
+{
+ isPhraseValue = true;
+ cutValue = shortcut;
+ setText(1, cutValue.toString());
+ setPixmap(0, icon);
+ setExpandable (false);
+}
+
+PhraseTreeItem::PhraseTreeItem (QListViewItem *parent, QListViewItem *after, QString phrase, KShortcut shortcut, QPixmap icon)
+ : KListViewItem (parent, after, phrase)
+{
+ isPhraseValue = true;
+ cutValue = shortcut;
+ setText(1, cutValue.toString());
+ setPixmap(0, icon);
+ setExpandable (false);
+}
+PhraseTreeItem::PhraseTreeItem (QListView *parent, QListViewItem *after, QString name, QPixmap icon)
+ : KListViewItem (parent, after, name)
+{
+ isPhraseValue = false;
+ setPixmap(0, icon);
+ setExpandable (true);
+}
+PhraseTreeItem::PhraseTreeItem (QListViewItem *parent, QListViewItem *after, QString name, QPixmap icon)
+ : KListViewItem (parent, after, name)
+{
+ isPhraseValue = false;
+ setPixmap(0, icon);
+ setExpandable (true);
+}
+bool PhraseTreeItem::isPhrase () {
+ return isPhraseValue;
+}
+KShortcut PhraseTreeItem::cut () {
+ return cutValue;
+}
+void PhraseTreeItem::setCut (KShortcut cut) {
+ cutValue = cut;
+ setText(1, cut.toString());
+}
+
+// ***************************************************************************
+
+PhraseTree::PhraseTree (QWidget *parent, const char *name)
+ : KListView (parent, name)
+{
+ phrasebook_open = KGlobal::iconLoader()->loadIcon("phrasebook", KIcon::Small);
+ phrasebook_closed = KGlobal::iconLoader()->loadIcon("phrasebook_closed", KIcon::Small);
+ phrase = KGlobal::iconLoader()->loadIcon("phrase", KIcon::Small);
+
+ connect (this, SIGNAL(expanded (QListViewItem *)), this, SLOT(itemExpanded (QListViewItem *)));
+ connect (this, SIGNAL(collapsed (QListViewItem *)), this, SLOT(itemCollapsed (QListViewItem *)));
+}
+
+PhraseTree::~PhraseTree (){
+}
+
+namespace PhraseTreePrivate {
+ QListViewItem *prevSibling (QListViewItem *item) {
+ QListViewItem *parent = item->parent();
+ QListViewItem *above = item->itemAbove();
+
+ if (above == parent)
+ return 0;
+
+ while (above->parent() != parent)
+ above = above->parent();
+
+ return above;
+ }
+
+ bool findAbovePosition (QListViewItem *item,
+ QListViewItem **newParent,
+ QListViewItem **newAbove)
+ {
+ if (item == 0)
+ return false;
+
+ QListViewItem *parent = item->parent();
+ QListViewItem *above = item->itemAbove();
+
+ if (above == 0)
+ return false;
+ else if (above == parent) {
+ *newParent = parent->parent();
+ *newAbove = prevSibling (parent);
+ return true;
+ }
+ else if (above->parent() == parent) {
+ *newParent = parent;
+ *newAbove = prevSibling (above);
+ return true;
+ }
+ else {
+ while (above->parent()->parent() != parent)
+ above = above->parent();
+ *newParent = above->parent();
+ *newAbove = above;
+ return true;
+ }
+ }
+
+ bool findBelowPosition (QListViewItem *item,
+ QListViewItem **newParent,
+ QListViewItem **newAbove)
+ {
+ if (item == 0)
+ return false;
+
+ QListViewItem *parent = item->parent();
+ QListViewItem *below = item->nextSibling();
+
+ if (parent == 0 && below == 0)
+ return false;
+ else if (parent != 0 && below == 0) {
+ *newParent = parent->parent();
+ *newAbove = parent;
+ return true;
+ }
+ else if (below->isOpen()) {
+ *newParent = below;
+ *newAbove = 0;
+ return true;
+ }
+ else {
+ *newParent = parent;
+ *newAbove = below;
+ return true;
+ }
+ }
+
+ bool findRightPosition (QListViewItem *item,
+ QListViewItem **newParent,
+ QListViewItem **newAbove)
+ {
+ if (item == 0)
+ return false;
+
+ QListViewItem *above = prevSibling (item);
+
+ if (above == 0)
+ return false;
+ else if (((PhraseTreeItem *)above)->isPhrase())
+ return false;
+ else {
+ above->setOpen(true);
+ *newParent = above;
+ *newAbove = 0;
+ above = (*newParent)->firstChild();
+ while (above != 0) {
+ *newAbove = above;
+ above = above->nextSibling();
+ }
+ return true;
+ }
+ }
+
+ bool findLeftPosition (QListViewItem *item,
+ QListViewItem **newParent,
+ QListViewItem **newAbove)
+ {
+ if (item == 0)
+ return false;
+
+ QListViewItem *parent = item->parent();
+
+ if (parent == 0)
+ return false;
+ else {
+ *newParent = parent->parent();
+ *newAbove = parent;
+ return true;
+ }
+ }
+}
+
+void PhraseTree::moveItem (QListViewItem *item,
+ QListViewItem *parent,
+ QListViewItem *above)
+{
+ if (item != 0) {
+ if (item->parent() == 0)
+ takeItem (item);
+ else
+ item->parent()->takeItem (item);
+
+ if (parent == 0)
+ insertItem (item);
+ else
+ parent->insertItem (item);
+
+ item->moveItem(above);
+ }
+}
+
+bool PhraseTree::hasSelectedItems() {
+ QListViewItem *i = firstChild();
+ if ( !i )
+ return false;
+ int level = 0;
+ do {
+ if (i->isSelected())
+ return true;
+
+ if (i->firstChild() != 0) {
+ i = i->firstChild();
+ level++;
+ }
+ else {
+ while ((i != 0) && (i->nextSibling() == 0)) {
+ i = i->parent();
+ level--;
+ }
+ if (i != 0)
+ i = i->nextSibling();
+ }
+ }
+ while (i != 0);
+
+ return false;
+}
+
+void PhraseTree::deleteSelectedItems() {
+ QListViewItem *i = firstChild();
+ if ( !i )
+ return;
+ QListViewItem *deleteItem = 0;
+ do {
+ if (i->isSelected())
+ deleteItem = i;
+
+ if ((i->firstChild() != 0) && (!i->isSelected())) {
+ i = i->firstChild();
+ }
+ else {
+ while ((i != 0) && (i->nextSibling() == 0)) {
+ i = i->parent();
+ }
+ if (i != 0)
+ i = i->nextSibling();
+ }
+ if (deleteItem != 0) {
+ delete deleteItem;
+ deleteItem = 0;
+ }
+ }
+ while (i != 0);
+}
+
+void PhraseTree::keyPressEvent (QKeyEvent *e) {
+ if ((e->state() & Qt::KeyButtonMask) == Qt::AltButton) {
+ if (e->key() == Qt::Key_Up) {
+ QListViewItem *item = currentItem();
+ if ((item != 0) && (item->isSelected())) {
+ QListViewItem *parent;
+ QListViewItem *above;
+
+ if (PhraseTreePrivate::findAbovePosition (item, &parent, &above)) {
+ moveItem(item, parent, above);
+ setCurrentItem (item);
+ item->setSelected(true);
+ }
+ }
+ e->accept();
+ return;
+ }
+ else if (e->key() == Qt::Key_Down) {
+ QListViewItem *item = currentItem();
+ if ((item != 0) && (item->isSelected())) {
+ QListViewItem *parent;
+ QListViewItem *above;
+
+ if (PhraseTreePrivate::findBelowPosition (item, &parent, &above)) {
+ moveItem(item, parent, above);
+ setCurrentItem (item);
+ item->setSelected(true);
+ }
+ }
+ e->accept();
+ return;
+ }
+ else if (e->key() == Qt::Key_Left) {
+ QListViewItem *item = currentItem();
+ if ((item != 0) && (item->isSelected())) {
+ QListViewItem *parent;
+ QListViewItem *above;
+
+ if (PhraseTreePrivate::findLeftPosition (item, &parent, &above)) {
+ moveItem(item, parent, above);
+ setCurrentItem (item);
+ item->setSelected(true);
+ }
+ }
+ e->accept();
+ return;
+ }
+ else if (e->key() == Qt::Key_Right) {
+ QListViewItem *item = currentItem();
+ if ((item != 0) && (item->isSelected())) {
+ QListViewItem *parent;
+ QListViewItem *above;
+
+ if (PhraseTreePrivate::findRightPosition (item, &parent, &above)) {
+ moveItem(item, parent, above);
+ setCurrentItem (item);
+ item->setSelected(true);
+ }
+ }
+ e->accept();
+ return;
+ }
+ }
+ KListView::keyPressEvent(e);
+}
+
+PhraseTreeItem *PhraseTree::insertPhrase (QListViewItem *parent, QListViewItem *after, QString phrase, QString shortcut) {
+ KShortcut cut = KShortcut(shortcut);
+ if (isKeyPresent (cut, 0, false))
+ cut = KShortcut(QString::null);
+
+ if (parent == 0)
+ return new PhraseTreeItem (this, after, phrase, cut, this->phrase);
+ else
+ return new PhraseTreeItem (parent, after, phrase, cut, this->phrase);
+}
+
+PhraseTreeItem *PhraseTree::insertBook (QListViewItem *parent, QListViewItem *after, QString name) {
+ if (parent == 0)
+ return new PhraseTreeItem (this, after, name, phrasebook_closed);
+ else
+ return new PhraseTreeItem (parent, after, name, phrasebook_closed);
+}
+
+QListViewItem *PhraseTree::addBook (QListViewItem *parent, QListViewItem *after, PhraseBook *book) {
+ QListViewItem *last = after;
+ int level = 0;
+ PhraseBookEntryList::iterator it;
+ for (it = book->begin(); it != book->end(); ++it) {
+ int newLevel = (*it).getLevel();
+ while (level < newLevel) {
+ parent = insertBook(parent, last, "");
+ last = 0;
+ level++;
+ }
+ while (level > newLevel) {
+ last = parent;
+ if (parent != 0)
+ parent = parent->parent();
+ level--;
+ }
+
+ if ((*it).isPhrase()) {
+ Phrase phrase = (*it).getPhrase();
+ last = insertPhrase (parent, last, phrase.getPhrase(), phrase.getShortcut());
+ }
+ else {
+ Phrase phrase = (*it).getPhrase();
+ parent = insertBook(parent, last, phrase.getPhrase());
+ last = 0;
+ level++;
+ }
+ }
+ while (level > 0) {
+ last = parent;
+ if (parent != 0)
+ parent = parent->parent();
+ level--;
+ }
+ return last;
+}
+
+void PhraseTree::fillBook (PhraseBook *book, bool respectSelection) {
+ QListViewItem *i = firstChild();
+ int level = 0;
+ if ( !i )
+ return;
+ do {
+ if (i->isSelected() || !respectSelection || level > 0) {
+ PhraseTreeItem *it = (PhraseTreeItem *)i;
+ Phrase phrase(it->text(0), it->cut().toStringInternal());
+ *book += PhraseBookEntry(phrase, level, it->isPhrase());
+ }
+
+ if (i->firstChild() != 0) {
+ if (i->isSelected() || !respectSelection || level > 0)
+ level++;
+ i = i->firstChild();
+ }
+ else {
+ while ((i != 0) && (i->nextSibling() == 0)) {
+ i = i->parent();
+ if (level > 0)
+ level--;
+ }
+ if (i != 0)
+ i = i->nextSibling();
+ }
+ }
+ while (i != 0);
+}
+
+QDragObject *PhraseTree::dragObject () {
+ return dragObject (true);
+}
+
+QDragObject *PhraseTree::dragObject (bool isDependent) {
+ PhraseBook book;
+ fillBook (&book, true);
+ if (isDependent)
+ return new PhraseBookDrag(&book, viewport());
+ return new PhraseBookDrag(&book);
+}
+
+bool PhraseTree::acceptDrag (QDropEvent* event) const {
+ if (KListView::acceptDrag (event))
+ return true;
+ else
+ return PhraseBookDrag::canDecode(event);
+}
+
+// Returns iSeq index if cut2 has a sequence of equal or higher priority
+// to a sequence in cut, else -1
+static int keyConflict (const KShortcut& cut, const KShortcut& cut2) {
+ for (uint iSeq = 0; iSeq < cut.count(); iSeq++) {
+ for (uint iSeq2 = 0; iSeq2 <= iSeq && iSeq2 < cut2.count(); iSeq2++) {
+ if (cut.seq(iSeq) == cut2.seq(iSeq2))
+ return iSeq;
+ }
+ }
+ return -1;
+}
+
+void PhraseTree::_warning (const KKeySequence& cut, QString sAction, QString sTitle) {
+ sAction = sAction.stripWhiteSpace();
+
+ QString s =
+ i18n("The '%1' key combination has already been allocated "
+ "to %2.\n"
+ "Please choose a unique key combination.").
+ arg(cut.toString()).arg(sAction);
+
+ KMessageBox::sorry( this, s, sTitle );
+}
+
+bool PhraseTree::isStdAccelPresent (const KShortcut& cut, bool warnUser) {
+ for (uint iSeq = 0; iSeq < cut.count(); iSeq++) {
+ const KKeySequence& seq = cut.seq(iSeq);
+
+ KStdAccel::StdAccel id = KStdAccel::findStdAccel( seq );
+ if( id != KStdAccel::AccelNone
+ && keyConflict (cut, KStdAccel::shortcut(id)) > -1)
+ {
+ if (warnUser)
+ _warning (cut.seq(iSeq),
+ i18n("the standard \"%1\" action").arg(KStdAccel::label(id)),
+ i18n("Conflict with Standard Application Shortcut"));
+ return true;
+ }
+ }
+ return false;
+}
+
+bool PhraseTree::isGlobalKeyPresent (const KShortcut& cut, bool warnUser) {
+ QMap<QString, QString> mapEntry = KGlobal::config()->entryMap ("Global Shortcuts");
+ QMap<QString, QString>::Iterator it;
+ for (it = mapEntry.begin(); it != mapEntry.end(); ++it) {
+ int iSeq = keyConflict (cut, KShortcut(*it));
+ if (iSeq > -1) {
+ if (warnUser)
+ _warning (cut.seq(iSeq),
+ i18n("the global \"%1\" action").arg(it.key()),
+ i18n("Conflict with Global Shortcuts"));
+ return true;
+ }
+ }
+ return false;
+}
+
+bool PhraseTree::isPhraseKeyPresent (const KShortcut& cut, PhraseTreeItem* cutItem, bool warnUser) {
+ for (QListViewItemIterator it(this); it.current(); ++it) {
+ PhraseTreeItem* item = dynamic_cast<PhraseTreeItem*>(it.current());
+ if ((item != 0) && (item != cutItem)) {
+ int iSeq = keyConflict (cut, item->cut());
+ if (iSeq > -1) {
+ if (warnUser)
+ _warning (cut.seq(iSeq),
+ i18n("an other phrase"),
+ i18n("Key Conflict"));
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool PhraseTree::isKeyPresent (const KShortcut& cut, PhraseTreeItem* cutItem, bool warnUser) {
+ if (isStdAccelPresent (cut, warnUser))
+ return true;
+
+ if (isGlobalKeyPresent (cut, warnUser))
+ return true;
+
+ if (isPhraseKeyPresent (cut, cutItem, warnUser))
+ return true;
+
+ return false;
+}
+
+void PhraseTree::itemExpanded (QListViewItem *item) {
+ PhraseTreeItem *i = (PhraseTreeItem *)item;
+ if (!i->isPhrase())
+ i->setPixmap(0, phrasebook_open);
+}
+
+void PhraseTree::itemCollapsed (QListViewItem *item) {
+ PhraseTreeItem *i = (PhraseTreeItem *)item;
+ if (!i->isPhrase())
+ i->setPixmap(0, phrasebook_closed);
+}
+
+// ***************************************************************************
+
+#include "phrasetree.moc"