Logo Search packages:      
Sourcecode: qalculate-kde version File versions  Download package

qalculateexpressionedit.cpp

/***************************************************************************
 *   Copyright (C) 2005 by Niklas Knutsson   *
 *   nq@altern.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) any later version.                                   *
 *                                                                         *
 *   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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "qalculateexpressionedit.h"

#include "qalculate_kde_utils.h"
#include "kqalculate.h"
#include <kdeversion.h>
#include <kcursor.h>
#include <qstyle.h>
#include <qpainter.h>
#include <qapplication.h>
#include <qfontmetrics.h>
#include <kstringhandler.h>
#include <kpopupmenu.h>
#include <kxmlguifactory.h>
#include <kxmlguiclient.h>
#include <kaction.h>
#include <klocale.h>
#include <qsimplerichtext.h>

extern vector<mode_struct> modes;

extern KQalculate *mainWin;
extern PrintOptions printops;
extern EvaluationOptions evalops;
extern tree_struct function_cats, unit_cats, variable_cats;
extern vector<void*> ia_units, ia_variables, ia_functions;

class QalculateExpressionEditListBoxItem : public QListBoxItem {

public:

      QalculateExpressionEditListBoxItem(ExpressionItem *eitem);
      virtual ~QalculateExpressionEditListBoxItem();

      int height(const QListBox*) const;
      int width(const QListBox*)  const;
      
      bool reuse(ExpressionItem *newItem);
      
      ExpressionItem *item;

protected:

      void paint(QPainter*);

private:

      QString title;
      int italic_index;
      bool rich_text;
      
};

QalculateExpressionEdit::QalculateExpressionEdit(bool connected_to_main_win, QWidget *parent, const char *name) : KLineEdit(parent, name) {

      qalculateCompletionBox = new QalculateExpressionEditCompletionBox(this);
      qalculateCompletion = new KCompletion();
      setCompletionObject(qalculateCompletion);
      
      pos_before_completion = 0;
      
      b_main = connected_to_main_win;
      
      dont_change_index = false;
      expression_history_index = -1;
      
      setCompletionMode(KGlobalSettings::CompletionPopup);
      
      setKeyCompression(false);
      
      //check for position changes regularly
      prev_position = 0;
      pos_timer = startTimer(50);
      
      connect(qalculateCompletionBox, SIGNAL(highlighted(QListBoxItem*)), this, SLOT(insertCompletion(QListBoxItem*)));
      connect(qalculateCompletionBox, SIGNAL(userCancelled(const QString&)), this, SLOT(cancelCompletion(const QString&)));
      connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(onTextChanged(const QString&)));
      
}

QalculateExpressionEdit::~QalculateExpressionEdit() {}

void QalculateExpressionEdit::timerEvent(QTimerEvent *event) {
      if(event->timerId() == pos_timer) {
            if(cursorPosition() != prev_position) {
                  prev_position = cursorPosition();
                  emit cursorMoved();
            }
      } else {
            KLineEdit::timerEvent(event);
      }
}

void QalculateExpressionEdit::onTextChanged(const QString &str) {
      if(str.isEmpty()) {
            if(qalculateCompletionBox) {
                  qalculateCompletionBox->hide();
                  qalculateCompletionBox->clear();
            }
            return;
      }
      prev_position = cursorPosition();
}

void QalculateExpressionEdit::cancelCompletion(const QString &str) {
      int new_pos = pos_before_completion;
      setText(str);
      setCursorPosition(new_pos);
}

void QalculateExpressionEdit::enableCompletion() {
      setCompletionMode(KGlobalSettings::CompletionPopup);
}
void QalculateExpressionEdit::disableCompletion() {
      setCompletionMode(KGlobalSettings::CompletionNone);
}
bool QalculateExpressionEdit::completionEnabled() const {
      return completionMode() == KGlobalSettings::CompletionPopup;
}

QPopupMenu *QalculateExpressionEdit::createPopupMenu() {

      setCompletionObject(NULL);
      QPopupMenu *menu = KLineEdit::createPopupMenu();
      setCompletionObject(qalculateCompletion);
      menu->insertSeparator();
      if(completionMode() == KGlobalSettings::CompletionPopup) menu->insertItem(i18n("Disable Completion"), this, SLOT(disableCompletion()));
      else menu->insertItem(i18n("Enable Completion"), this, SLOT(enableCompletion()));
      if(b_main) {
            menu->insertSeparator();
            mainWin->ActionReadPrecision->plug(menu);
            mainWin->ActionLimitImplicitMultiplication->plug(menu);
            mainWin->ActionRPNMode->plug(menu);
            QPopupMenu *modes_menu = new QPopupMenu(menu);
            QObject::connect(modes_menu, SIGNAL(activated(int)), mainWin, SLOT(loadMode(int)));
            for(size_t i = 0; i < modes.size(); i++) {
                  modes_menu->insertItem(modes[i].name, i, i);
            }
            modes_menu->insertSeparator();
            mainWin->ActionSaveModeAs->plug(modes_menu);
            mainWin->ActionDeleteMode->plug(modes_menu);
            menu->insertItem(i18n("Meta Modes"), modes_menu);
            menu->insertSeparator();
            mainWin->ActionInsertMatrix->plug(menu);
            mainWin->ActionInsertVector->plug(menu);
      }
      return menu;

}

#if QT_VERSION >= 0x030200
#define GET_SELECTION               int start = selectionStart(), end = -1; if(start >= 0) end = start + selectedText().length();
#else
#define GET_SELECTION               int start = -1, end = -1; getSelection(&start, &end);
#endif
#define RESTORE_SELECTION           if(start > 0) setSelection(start, end - start);

void QalculateExpressionEdit::addToHistory(const QString &str) {
      for(QStringList::Iterator it = expression_history.begin(); it != expression_history.end(); ++it) {
            if(*it == str) {
                  expression_history.erase(it);
                  break;
            }
      }
      if(expression_history.size() >= 25) {
            expression_history.pop_back();
      }
      expression_history.insert(expression_history.begin(), str);
      expression_history_index = 0;
}


void QalculateExpressionEdit::setAfterCompletionPosition() {
      setCursorPosition(cpos_ac);
}

void QalculateExpressionEdit::insertCompletion(QListBoxItem *li) {

      ExpressionItem *item = ((QalculateExpressionEditListBoxItem*) li)->item;
      
      setSelection(cstart, cend - cstart + 1);
      
      QString str = completed_text;
      const ExpressionName *ename = NULL, *ename_r = NULL;
      ename_r = &item->preferredInputName(false, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) this); 
      for(size_t name_i = 0; name_i <= item->countNames() && !ename; name_i++) {
            if(name_i == 0) {
                  ename = ename_r;
            } else {
                  ename = &item->getName(name_i);
                  if(!ename || ename == ename_r || ename->plural || (ename->unicode && (!printops.use_unicode_signs || !can_display_unicode_string_function(ename->name.c_str(), (void*) this)))) {
                        ename = NULL;
                  }
            }
            if(ename) {
                  if(str.length() <= ename->name.length()) {
                        for(size_t i = 0; i < str.length(); i++) {
                              if(ename->name[i] != str[i]) {
                                    ename = NULL;
                                    break;
                              }
                        }
                  } else {
                        ename = NULL;
                  }
            }
      }
      for(size_t name_i = 1; name_i <= item->countNames() && !ename; name_i++) {
            ename = &item->getName(name_i);
            if(!ename || ename == ename_r || (!ename->plural && !(ename->unicode && (!printops.use_unicode_signs || !can_display_unicode_string_function(ename->name.c_str(), (void*) this))))) {
                  ename = NULL;
            }
            if(ename) {
                  if(str.length() <= ename->name.length()) {
                        for(size_t i = 0; i < str.length(); i++) {
                              if(ename->name[i] != str[i]) {
                                    ename = NULL;
                                    break;
                              }
                        }
                  } else {
                        ename = NULL;
                  }
            }
      }
      if(!ename) ename = ename_r;
      if(!ename) return;
      if(item->type() == TYPE_FUNCTION) {       
            if(text()[cend + 1] == '(') {
                  insert(ename->name.c_str());
                  cend = cstart + ename->name.length() - 1;
                  cpos_ac = cend + 2;
            } else {
                  str = ename->name.c_str();
                  str += "()";
                  insert(str);
                  cend = cstart + str.length() - 1;
                  cpos_ac = cend;
            }
      } else {
            insert(ename->name.c_str());
            cend = cstart + ename->name.length() - 1;
            cpos_ac = cend + 1;
      }     
      setCursorPosition(cpos_ac);
      
}

bool matchesExpressionItem(const QString &str, ExpressionItem *item) {
      bool b_match = false;
      for(size_t name_i = 1; !b_match && name_i <= item->countNames(); name_i++) {
            const ExpressionName *ename = &item->getName(name_i);
            if(ename && str.length() <= ename->name.length()) {
                  b_match = true;
                  for(size_t i = 0; i < str.length(); i++) {
                        if(ename->name[i] != str[i]) {
                              b_match = false;
                              break;
                        }                       
                  }
            }
      }
      return b_match;
}

void QalculateExpressionEdit::makeCompletion(const QString &str) {
      if(cursorPosition() <= 0 || str.isEmpty()) {
            if(qalculateCompletionBox) {
                  qalculateCompletionBox->hide();
                  qalculateCompletionBox->clear();
            }
            return;
      }
      uint start = (uint) cursorPosition();
      cend = (int) start - 1;
      QString str2 = str;
      str2.truncate(start);
      const char *cstr = str2.ascii();
      bool non_number_before = false;
      size_t cpos = strlen(cstr) - 1;
      start--;
      while(true) {
            while(cpos > 0 && (unsigned char) cstr[cpos] >= 0x80 && (unsigned char) cstr[cpos] <= 0xBF) {
                  cpos--;
            }
            if(!CALCULATOR->utf8_pos_is_valid_in_name((char*) &cstr[cpos])) {
                  start++;
                  break;
            } else if(is_in(NUMBERS, cstr[cpos])) {
                  if(non_number_before) {
                        start++;
                        break;
                  }
            } else {
                  non_number_before = true;
            }
            if(start == 0 || cpos == 0) break;
            start--;
            cpos--;
      }
      if(start >= (uint) cursorPosition()) {
            if(qalculateCompletionBox) {
                  qalculateCompletionBox->hide();
                  qalculateCompletionBox->clear();
            }
            return;
      }
      cstart = (int) start;
      str2.remove(0, start);
      
      completed_text = str2;
      pos_before_completion = cursorPosition();
      qalculateCompletionBox->setCancelledText(text());
      
      matched_items.clear();
      if(evalops.parse_options.functions_enabled) {
            for(size_t i = 0; i < CALCULATOR->functions.size(); i++) {
                  if(CALCULATOR->functions[i]->isActive()) {
                        if(matchesExpressionItem(str2, CALCULATOR->functions[i])) {
                              matched_items.push_back(CALCULATOR->functions[i]);
                        }
                  }
            }
      }
      if(evalops.parse_options.variables_enabled) {
            for(size_t i = 0; i < CALCULATOR->variables.size(); i++) {
                  if(CALCULATOR->variables[i]->isActive()) {
                        if(matchesExpressionItem(str2, CALCULATOR->variables[i])) {
                              matched_items.push_back(CALCULATOR->variables[i]);
                        }
                  }
            }
      }
      if(evalops.parse_options.units_enabled) {
            for(size_t i = 0; i < CALCULATOR->units.size(); i++) {
                  if(CALCULATOR->units[i]->isActive() && CALCULATOR->units[i]->subtype() != SUBTYPE_COMPOSITE_UNIT) {
                        if(matchesExpressionItem(str2, CALCULATOR->units[i])) {
                              matched_items.push_back(CALCULATOR->units[i]);
                        }
                  }
            }
      }
      
      if(matched_items.isEmpty()) {
            if(qalculateCompletionBox) {
                  qalculateCompletionBox->hide();
                  qalculateCompletionBox->clear();
            }
      } else {
            setCompletedItems();
      }
}

void QalculateExpressionEdit::updateCompletion() {
}

void QalculateExpressionEdit::wrapSelection() {
      GET_SELECTION
      if(start >= 0) {
            deselect();
            setCursorPosition(start);
            insert("(");
            setCursorPosition(end + 1);
            insert(")");
            setSelection(start, end - start + 2);
      }
}

void QalculateExpressionEdit::keyPressEvent(QKeyEvent *e) {
      if(e->state() != 0 && e->state() != ShiftButton && e->state() != Keypad) {
            KLineEdit::keyPressEvent(e);
            return;
      }
      switch(e->key()) {
            case Key_AsciiCircum: {
                  wrapSelection();
                  deselect();
                  insert("^");
                  e->accept();
                  return;
            }
            case Key_Slash: {
                  wrapSelection();
                  deselect();
                  if(printops.use_unicode_signs && printops.division_sign == DIVISION_SIGN_DIVISION && can_display_unicode_string_function(SIGN_DIVISION, (void*) this)) {
                        insert(SIGN_DIVISION);
                        e->accept();
                        return;
                  }
                  break;
            }
            case Key_Asterisk: {
                  wrapSelection();
                  deselect();
                  if(printops.use_unicode_signs && printops.multiplication_sign == MULTIPLICATION_SIGN_DOT && can_display_unicode_string_function(SIGN_MULTIDOT, (void*) this)) {
                        insert(SIGN_MULTIDOT);
                  } else if(printops.use_unicode_signs && printops.multiplication_sign == MULTIPLICATION_SIGN_DOT && can_display_unicode_string_function(SIGN_SMALLCIRCLE, (void*) this)) {
                        insert(SIGN_SMALLCIRCLE);
                  } else if(printops.use_unicode_signs && printops.multiplication_sign == MULTIPLICATION_SIGN_X && can_display_unicode_string_function(SIGN_MULTIPLICATION, (void*) this)) {
                        insert(SIGN_MULTIPLICATION);
                  } else {
                        insert("*");
                  }
                  e->accept();
                  return;
            }
            case Key_Plus: {
                  wrapSelection();
                  deselect();
                  e->accept();
                  break;
            }
            case Key_Minus: {
                  wrapSelection();
                  deselect();
                  if(printops.use_unicode_signs && can_display_unicode_string_function(SIGN_MINUS, (void*) this)) {
                        insert(SIGN_MINUS);
                        e->accept();
                        return;
                  }
                  break;
            }
            case Key_Up: {}
            case Key_PageUp: {
                  if(expression_history_index + 1 < (int) expression_history.size()) {
                        expression_history_index++;
                        dont_change_index = true;
                        setText(expression_history[expression_history_index]);
                        dont_change_index = false;
                  }
                  e->accept();
                  return;
            }
            case Key_Down: {}
            case Key_PageDown: {
                  if(expression_history_index > -1) {
                        expression_history_index--;
                        dont_change_index = true;
                        if(expression_history_index < 0) {
                              clear();
                        } else {
                              setText(expression_history[expression_history_index]);
                        }
                        dont_change_index = false;
                  }
                  e->accept();
                  return;
            }
            case Key_BraceLeft: {}
            case Key_BraceRight: {
                  return;
            }
            case 0xffff: {
                  if(e->text().utf8() == "⁰") {
                        insert("°");
                        e->accept();
                        return;
                  }
                  if(e->text().utf8() == "¹") {
                        wrapSelection();
                        deselect();
                        insert("^1");
                        e->accept();
                        return;
                  }
                  if(e->text().utf8() == "²") {
                        wrapSelection();
                        deselect();
                        insert("^2");
                        e->accept();
                        return;
                  }
                  if(e->text().utf8() == "³") {
                        wrapSelection();
                        deselect();
                        insert("^3");
                        e->accept();
                        return;
                  }
                  if(e->text().utf8() == "⁴") {
                        wrapSelection();
                        deselect();
                        insert("^4");
                        e->accept();
                        return;
                  }
                  if(e->text().utf8() == "⁵") {
                        wrapSelection();
                        deselect();
                        insert("^5");
                        e->accept();
                        return;
                  }
                  if(e->text().utf8() == "⁶") {
                        wrapSelection();
                        deselect();
                        insert("^6");
                        e->accept();
                        return;
                  }
                  if(e->text().utf8() == "⁷") {
                        wrapSelection();
                        deselect();
                        insert("^7");
                        e->accept();
                        return;
                  }
                  if(e->text().utf8() == "⁸") {
                        wrapSelection();
                        deselect();
                        insert("^8");
                        e->accept();
                        return;
                  }
                  if(e->text().utf8() == "⁹") {
                        wrapSelection();
                        deselect();
                        insert("^9");
                        e->accept();
                        return;
                  }
                  break;
            }
      }
      KLineEdit::keyPressEvent(e);
}

bool QalculateExpressionEdit::eventFilter(QObject *o, QEvent *ev) {
      if(o == this && ev->type() == QEvent::KeyPress) {
            QKeyEvent *e = static_cast<QKeyEvent *>(ev);
            if((e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) && qalculateCompletionBox && qalculateCompletionBox->isVisible()) {
                  if(qalculateCompletionBox->selectedItem()) {
                        KCursor::autoHideEventFilter(this, ev);
                        e->accept();
                        qalculateCompletionBox->hide();
                        deselect();
                        return true;
                  } else {
                        qalculateCompletionBox->hide();
                        return false;
                  }
            }
      }
      return KLineEdit::eventFilter(o, ev);
}


string sub_suffix(const ExpressionName *ename) {
      size_t i = ename->name.rfind('_');
      bool b = i == string::npos || i == ename->name.length() - 1 || i == 0;
      size_t i2 = 1;
      string str;
      if(b) {
            if(is_in(NUMBERS, ename->name[ename->name.length() - 1])) {
                  while(ename->name.length() > i2 + 1 && is_in(NUMBERS, ename->name[ename->name.length() - 1 - i2])) {
                              i2++;
                  }
            }
            str += ename->name.substr(0, ename->name.length() - i2);
      } else {
            str += ename->name.substr(0, i);
      }
      str += "<sub>";
      if(b) str += ename->name.substr(ename->name.length() - i2, i2);
      else str += ename->name.substr(i + 1, ename->name.length() - (i + 1));
      str += "</sub>";
      return str;
}

QString makeListName(ExpressionItem *item, QWidget *w, int *italic_index, bool *rich_text) {
      string str;
      const ExpressionName *ename, *ename_r;
      *rich_text = false;
      bool b = false;
      ename_r = &item->preferredInputName(false, printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) w);
      if(ename_r->suffix && ename_r->name.length() > 1) {
            str = sub_suffix(ename_r);
            *rich_text = true;
      } else {
            str = ename_r->name;
      }
      if(item->type() == TYPE_FUNCTION) str += "()";
      for(size_t name_i = 1; name_i <= item->countNames(); name_i++) {
            ename = &item->getName(name_i);
            if(ename && ename != ename_r && !ename->plural && (!ename->unicode || can_display_unicode_string_function(ename->name.c_str(), (void*) w))) {         
                  str += " ";
                  if(!b) {
                        *italic_index = str.length();
                        *rich_text = true;
                        str += "<i>";
                        b = true;
                  }
                  if(ename->suffix && ename->name.length() > 1) {
                        str += sub_suffix(ename);
                  } else {
                        str += ename->name;
                  }
                  if(item->type() == TYPE_FUNCTION) str += "()";
            }
      }
      if(b) str += "</i>";
      return str.c_str();
}

QalculateExpressionEditListBoxItem::QalculateExpressionEditListBoxItem(ExpressionItem *eitem) : QListBoxItem() {
      item = eitem;
      italic_index = -1;
      setText(makeListName(item, listBox(), &italic_index, &rich_text));
      title = item->title().c_str();
}
QalculateExpressionEditListBoxItem::~QalculateExpressionEditListBoxItem() {
}

#if KDE_VERSION_MAJOR < 4 && KDE_VERSION_MINOR < 2
QString rPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels)
{
  uint nameWidth = fontMetrics.width(name);

  if (maxPixels < nameWidth)
  {
    QString tmp = name;
    const uint em = fontMetrics.maxWidth();
    maxPixels -= fontMetrics.width("...");

    while (maxPixels < nameWidth && !tmp.isEmpty())
    {
      int length = tmp.length();
      int delta = em ? (nameWidth - maxPixels) / em : length;

      if(delta < 1) delta = 1;
      else if(length < delta) delta = length;

      tmp.remove(length - delta, delta);
      nameWidth = fontMetrics.width(tmp);
    }

    return (tmp + "...");
  }

  return name;
}
#endif

void QalculateExpressionEditListBoxItem::paint(QPainter *painter) {

      int itemHeight = height(listBox());

      int entryWidth = listBox()->width() - listBox()->style().pixelMetric(QStyle::PM_ScrollBarExtent) - 2 * listBox()->style().pixelMetric(QStyle::PM_DefaultFrameWidth);
      int titleWidth = (entryWidth / 2) - 1;
      int nameWidth = entryWidth - titleWidth - 2;

      if(!text().isEmpty()) {
            QString squeezedText;
            if(rich_text) {
                  QSimpleRichText rt(text(), painter->font());
                  rt.setWidth(entryWidth);
                  if(rt.widthUsed() > nameWidth - 1) {
                        squeezedText = text();              
                        if(italic_index > 0) squeezedText.truncate(italic_index);
#if KDE_VERSION_MAJOR < 4 && KDE_VERSION_MINOR < 2    
                        squeezedText = rPixelSqueeze(squeezedText, listBox()->fontMetrics(), nameWidth);
#else
                        squeezedText = KStringHandler::rPixelSqueeze(squeezedText, listBox()->fontMetrics(), nameWidth);
#endif
                        painter->drawText(0, 0, nameWidth, itemHeight, Qt::AlignLeft | Qt::AlignVCenter, squeezedText);
                  } else {
                        QColorGroup cg = listBox()->colorGroup();
                        cg.setColor(QColorGroup::Text, painter->pen().color());
                        rt.draw(painter, 1, 0, QRect(0, 0, nameWidth - 1, itemHeight), cg, &painter->brush());
                  }
            } else {
#if KDE_VERSION_MAJOR < 4 && KDE_VERSION_MINOR < 2    
                  squeezedText = rPixelSqueeze(text(), listBox()->fontMetrics(), nameWidth);
#else
                  squeezedText = KStringHandler::rPixelSqueeze(text(), listBox()->fontMetrics(), nameWidth);
#endif
                  painter->drawText(0, 0, nameWidth, itemHeight, Qt::AlignLeft | Qt::AlignVCenter, squeezedText);
            }
#if KDE_VERSION_MAJOR < 4 && KDE_VERSION_MINOR < 2    
            squeezedText = rPixelSqueeze(title, listBox()->fontMetrics(), titleWidth);
#else
            squeezedText = KStringHandler::rPixelSqueeze(title, listBox()->fontMetrics(), titleWidth);
#endif            
            QFont font = painter->font();
            font.setItalic(true);
            painter->setFont(font);
            painter->drawText(entryWidth - titleWidth, 0, titleWidth, itemHeight, Qt::AlignLeft | Qt::AlignVCenter, squeezedText);
      }
      
}

int QalculateExpressionEditListBoxItem::height(const QListBox *lb) const {
      int h;
      h = lb->fontMetrics().lineSpacing() + 4;
      return QMAX(h, QApplication::globalStrut().height());
}

int QalculateExpressionEditListBoxItem::width(const QListBox *lb) const {
      return QMAX(lb->fontMetrics().width(text()) + 6, QApplication::globalStrut().width());
}
bool QalculateExpressionEditListBoxItem::reuse(ExpressionItem *newItem) {
      if(item == newItem) return false;
      item = newItem;
      italic_index = -1;
      setText(makeListName(item, listBox(), &italic_index, &rich_text));
      title = item->title().c_str();
      return true;
}

QalculateExpressionEditCompletionBox::QalculateExpressionEditCompletionBox(QWidget *parent, const char *name) : KCompletionBox(parent, name) {
}
QalculateExpressionEditCompletionBox::~QalculateExpressionEditCompletionBox() {
}

void QalculateExpressionEditCompletionBox::setItems(const QValueVector<ExpressionItem*>& items) {

      bool block = signalsBlocked();
      blockSignals(true);

      QListBoxItem* item = firstItem();
      if(!item) {
            insertItemList(items);
      } else {
            //Keep track of whether we need to change anything,
            //so we can avoid a repaint for identical updates,
            //to reduce flicker
            bool dirty = false;

#if QT_VERSION >= 0x030200
            QValueVector<ExpressionItem*>::ConstIterator it = items.constBegin();
            const QValueVector<ExpressionItem*>::ConstIterator itEnd = items.constEnd();
#else
            QValueVector<ExpressionItem*>::ConstIterator it = items.begin();
            const QValueVector<ExpressionItem*>::ConstIterator itEnd = items.end();
#endif

            for (; it != itEnd; ++it) {
                  if(item) {
                        const bool changed = ((QalculateExpressionEditListBoxItem*) item)->reuse(*it);
                        dirty = dirty || changed;
                        item = item->next();
                  } else {
                        dirty = true;
                        //Inserting an item is a way of making this dirty
                        insertItem(new QalculateExpressionEditListBoxItem(*it));
                  }
            }

            //If there is an unused item, mark as dirty -> less items now
            if(item) dirty = true;

            QListBoxItem* tmp = item;
            while((item = tmp)) {
                  tmp = item->next();
                  delete item;
            }

            if(dirty) triggerUpdate(false);
      }
      sort();

      if(isVisible() && size().height() != sizeHint().height()) {
#if KDE_VERSION_MAJOR < 4 && KDE_VERSION_MINOR < 2
            hide();
            popup();
#else
            sizeAndPosition();
#endif
      }

      blockSignals(block);

      // Trigger d->down_workaround = true within KCompletionBox
      QStringList dummy;
      KCompletionBox::insertItems(dummy, 1);
      
}

void QalculateExpressionEditCompletionBox::insertItemList(const QValueVector<ExpressionItem*> & list, int index) {
      if(index < 0) index = count();
      for(QValueVector<ExpressionItem*>::ConstIterator it = list.begin(); it != list.end(); ++it) {
            insertItem(new QalculateExpressionEditListBoxItem(*it), index++);
      }
}

void QalculateExpressionEdit::setCompletedItems() {

      QString txt;
      if(qalculateCompletionBox && qalculateCompletionBox->isVisible()) {
            // The popup is visible already - do the matching on the initial string,
            // not on the currently selected one.
            txt = qalculateCompletionBox->cancelledText();
      } else {
            txt = text();
      }

      if(!matched_items.isEmpty() && !(matched_items.size() == 1 && matched_items[0]->hasName(txt.ascii()))) {
      
            if(qalculateCompletionBox->isVisible()) {
                  bool wasSelected = qalculateCompletionBox->isSelected(qalculateCompletionBox->currentItem());
                  const QString currentSelection = qalculateCompletionBox->currentText();
                  qalculateCompletionBox->setItems(matched_items);
                  QListBoxItem* item = qalculateCompletionBox->findItem(currentSelection, Qt::ExactMatch);
                  // If no item is selected, that means the listbox hasn't been manipulated by the user yet,
                  // because it's not possible otherwise to have no selected item. In such case make
                  // always the first item current and unselected, so that the current item doesn't jump.
                  if(!item || !wasSelected) {
                        wasSelected = false;
                        item = qalculateCompletionBox->item(0);
                  }
                  if(item) {
                        qalculateCompletionBox->blockSignals(true);
                        qalculateCompletionBox->setCurrentItem(item);
                        qalculateCompletionBox->setSelected(item, wasSelected);
                        qalculateCompletionBox->blockSignals(false);
                  }
            } else { // completion box not visible yet -> show it 
                  if(!txt.isEmpty()) qalculateCompletionBox->setCancelledText(txt);
                  ((QalculateExpressionEditCompletionBox*) qalculateCompletionBox)->setItems(matched_items);
                  qalculateCompletionBox->popup();
            }

      } else {
      
            if(qalculateCompletionBox && qalculateCompletionBox->isVisible()) {
                  qalculateCompletionBox->hide();
            }
      
      }
      
}

void QalculateExpressionEditCompletionBox::hideEvent(QHideEvent*) {
      emit hidden();
}

#include "qalculateexpressionedit.moc"

Generated by  Doxygen 1.6.0   Back to index