QTfrontend/ui/widget/SmartLineEdit.cpp
changeset 6150 1d98752c1fba
parent 6149 0b92341adb6a
child 6151 9fd5b70acb1a
equal deleted inserted replaced
6149:0b92341adb6a 6150:1d98752c1fba
    19 
    19 
    20 #include <QStringList>
    20 #include <QStringList>
    21 
    21 
    22 #include "SmartLineEdit.h"
    22 #include "SmartLineEdit.h"
    23 
    23 
    24 SmartLineEdit::SmartLineEdit(QWidget * parent)
    24 SmartLineEdit::SmartLineEdit(QWidget * parent, int maxHistorySize)
    25 : QLineEdit(parent)
    25 : QLineEdit(parent)
    26 {
    26 {
       
    27     m_curHistEntryIdx = 0;
       
    28     m_maxHistorySize = maxHistorySize;
       
    29 
    27     m_whitespace = QRegExp("\\s");
    30     m_whitespace = QRegExp("\\s");
    28 
    31 
    29     m_cmds  = new QStringList();
    32     m_cmds  = new QStringList();
    30     m_nicks = new QStringList();
    33     m_nicks = new QStringList();
       
    34 
       
    35     m_history = new QStringList();
    31 
    36 
    32     resetAutoCompletionStatus();
    37     resetAutoCompletionStatus();
    33 
    38 
    34     // reset autocompletion status when cursor is moved or content is changed
    39     // reset autocompletion status when cursor is moved or content is changed
    35     connect(this, SIGNAL(cursorPositionChanged(int, int)),
    40     connect(this, SIGNAL(cursorPositionChanged(int, int)),
    39 }
    44 }
    40 
    45 
    41 
    46 
    42 void SmartLineEdit::addCommands(const QStringList & commands)
    47 void SmartLineEdit::addCommands(const QStringList & commands)
    43 {
    48 {
    44     m_mutex.lock();
    49     m_keywordMutex.lock();
    45 
    50 
    46     m_cmds->append(commands);
    51     m_cmds->append(commands);
    47 
    52 
    48     m_mutex.unlock();
    53     m_keywordMutex.unlock();
    49 }
    54 }
    50 
    55 
    51 
    56 
    52 void SmartLineEdit::removeCommands(const QStringList & commands)
    57 void SmartLineEdit::removeCommands(const QStringList & commands)
    53 {
    58 {
    54     m_mutex.lock();
    59     m_keywordMutex.lock();
    55 
    60 
    56     foreach (const QString & cmd, commands)
    61     foreach (const QString & cmd, commands)
    57     {
    62     {
    58         m_cmds->removeAll(cmd);
    63         m_cmds->removeAll(cmd);
    59     }
    64     }
    60 
    65 
    61     m_mutex.unlock();
    66     m_keywordMutex.unlock();
    62 }
    67 }
    63 
    68 
    64 
    69 
    65 void SmartLineEdit::addNickname(const QString & name)
    70 void SmartLineEdit::addNickname(const QString & name)
    66 {
    71 {
    67     m_mutex.lock();
    72     m_keywordMutex.lock();
    68 
    73 
    69     m_nicks->append(name);
    74     m_nicks->append(name);
    70 
    75 
    71     m_mutex.unlock();
    76     m_keywordMutex.unlock();
    72 }
    77 }
    73 
    78 
    74 
    79 
    75 void SmartLineEdit::removeNickname(const QString & name)
    80 void SmartLineEdit::removeNickname(const QString & name)
    76 {
    81 {
    77     m_mutex.lock();
    82     m_keywordMutex.lock();
    78 
    83 
    79     m_nicks->removeAll(name);
    84     m_nicks->removeAll(name);
    80 
    85 
    81     m_mutex.unlock();
    86     m_keywordMutex.unlock();
       
    87 }
       
    88 
       
    89 void SmartLineEdit::rememberCurrentText()
       
    90 {
       
    91     m_historyMutex.lock();
       
    92 
       
    93     rememberCurrentTextUnsynced();
       
    94 
       
    95     m_historyMutex.unlock();
       
    96 }
       
    97 
       
    98 void SmartLineEdit::rememberCurrentTextUnsynced()
       
    99 {
       
   100     QString newEntry = text();
       
   101 
       
   102     // don't store whitespace-only/empty text
       
   103     if (newEntry.trimmed().isEmpty())
       
   104         return;
       
   105 
       
   106     m_history->removeOne(newEntry); // no duplicates please
       
   107     m_history->append(newEntry);
       
   108 
       
   109     // do not keep more entries than allowed
       
   110     if (m_history->size() > m_maxHistorySize)
       
   111         m_history->removeFirst();
       
   112 
       
   113     // we're looking at the latest entry
       
   114     m_curHistEntryIdx = m_history->size() - 1;
       
   115 }
       
   116 
       
   117 void SmartLineEdit::clear()
       
   118 {
       
   119     m_historyMutex.lock();
       
   120 
       
   121     QLineEdit::clear();
       
   122     m_curHistEntryIdx = m_history->size();
       
   123 
       
   124     m_historyMutex.unlock();
    82 }
   125 }
    83 
   126 
    84 void SmartLineEdit::forgetEverything()
   127 void SmartLineEdit::forgetEverything()
    85 {
   128 {
    86     m_mutex.lock();
   129     // forget keywords
       
   130     m_keywordMutex.lock();
    87 
   131 
    88     m_cmds->clear();
   132     m_cmds->clear();
    89     m_nicks->clear();
   133     m_nicks->clear();
    90 
   134 
    91     m_mutex.unlock();
   135     m_keywordMutex.unlock();
       
   136 
       
   137     // forget history
       
   138     m_historyMutex.lock();
       
   139 
       
   140     m_history->clear();
       
   141     m_curHistEntryIdx = 0;
       
   142 
       
   143     m_historyMutex.unlock();
    92 
   144 
    93     resetAutoCompletionStatus();
   145     resetAutoCompletionStatus();
       
   146 }
       
   147 
       
   148 void SmartLineEdit::navigateHistory(bool isGoingUp)
       
   149 {
       
   150     m_historyMutex.lock();
       
   151 
       
   152     // save possible changes to new entry
       
   153     if ((m_curHistEntryIdx >= m_history->size() ||
       
   154         (text() != m_history->at(m_curHistEntryIdx))))
       
   155         {
       
   156             rememberCurrentTextUnsynced();
       
   157         }
       
   158 
       
   159     if (isGoingUp)
       
   160         m_curHistEntryIdx--;
       
   161     else
       
   162         m_curHistEntryIdx++;
       
   163 
       
   164     // if Idx higher than valid range
       
   165     if (m_curHistEntryIdx >= m_history->size())
       
   166     {
       
   167         QLineEdit::clear();
       
   168         m_curHistEntryIdx = m_history->size();
       
   169     }
       
   170     // if Idx in valid range
       
   171     else if (m_curHistEntryIdx >= 0)
       
   172     {
       
   173         setText(m_history->at(m_curHistEntryIdx));
       
   174     }
       
   175     // if Idx below 0
       
   176     else
       
   177         m_curHistEntryIdx = 0;
       
   178 
       
   179 
       
   180     m_historyMutex.unlock();
    94 }
   181 }
    95 
   182 
    96 bool SmartLineEdit::event(QEvent * event)
   183 bool SmartLineEdit::event(QEvent * event)
    97 {
   184 {
    98     // we only want special treatment for key press events
   185     // we only want special treatment for key press events
   119     if ((key == Qt::Key_Tab) && (!text().trimmed().isEmpty()))
   206     if ((key == Qt::Key_Tab) && (!text().trimmed().isEmpty()))
   120     {
   207     {
   121         autoComplete();
   208         autoComplete();
   122         event->accept();
   209         event->accept();
   123     }
   210     }
   124     // clear contents on pressed ESC
   211     // clear contents on pressed ESC, navigate history with arrow keys
   125     else if ((event->key() == Qt::Key_Escape) &&
   212     else if (event->modifiers() == Qt::NoModifier)
   126              (event->modifiers() == Qt::NoModifier)
   213         switch (key)
   127     )
   214         {
   128         clear();
   215             case Qt::Key_Escape:
       
   216                 clear();
       
   217                 event->accept();
       
   218                 break;
       
   219 
       
   220             case Qt::Key_Up:
       
   221                 navigateHistory(true);
       
   222                 event->accept();
       
   223                 break;
       
   224 
       
   225             case Qt::Key_Down:
       
   226                 navigateHistory(false);
       
   227                 event->accept();
       
   228                 break;
       
   229 
       
   230             default:
       
   231                 QLineEdit::keyPressEvent(event);
       
   232                 break;
       
   233         }
   129     // otherwise forward keys to parent
   234     // otherwise forward keys to parent
   130     else
   235     else
   131         QLineEdit::keyPressEvent(event);
   236         QLineEdit::keyPressEvent(event);
   132 }
   237 }
   133 
   238 
   150         postfix = m_postfix;
   255         postfix = m_postfix;
   151         isFirstWord = prefix.isEmpty();
   256         isFirstWord = prefix.isEmpty();
   152     }
   257     }
   153     else
   258     else
   154     {
   259     {
   155         m_mutex.lock();
   260         m_keywordMutex.lock();
   156         m_cmds->sort();
   261         m_cmds->sort();
   157         m_nicks->sort();
   262         m_nicks->sort();
   158         m_mutex.unlock();
   263         m_keywordMutex.unlock();
   159 
   264 
   160         int cp = cursorPosition();
   265         int cp = cursorPosition();
   161 
   266 
   162         // cursor is not in or at end/beginning of word
   267         // cursor is not in or at end/beginning of word
   163         if ((cp = matchMe.length()) || (QString(matchMe.at(cp)).contains(m_whitespace)))
   268         if ((cp = matchMe.length()) || (QString(matchMe.at(cp)).contains(m_whitespace)))
   188 
   293 
   189         isFirstWord = prefix.isEmpty(); // true if first word
   294         isFirstWord = prefix.isEmpty(); // true if first word
   190     }
   295     }
   191 
   296 
   192 
   297 
   193     m_mutex.lock();
   298     m_keywordMutex.lock();
   194 
   299 
   195     if (isFirstWord)
   300     if (isFirstWord)
   196     {
   301     {
   197         // find matching commands
   302         // find matching commands
   198         foreach (const QString & cmd, *m_cmds)
   303         foreach (const QString & cmd, *m_cmds)
   227                 break;
   332                 break;
   228             }
   333             }
   229         }
   334         }
   230     }
   335     }
   231 
   336 
   232     m_mutex.unlock();
   337     m_keywordMutex.unlock();
   233 
   338 
   234     // we found a single match?
   339     // we found a single match?
   235     if (!match.isEmpty())
   340     if (!match.isEmpty())
   236     {
   341     {
   237         // replace last word with match
   342         // replace last word with match