1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
|
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
***************************************************************************/
#include <qlabel.h>
#include <qlistview.h>
#include <qpushbutton.h>
#include <qradiobutton.h>
#include <qcheckbox.h>
#include <qgroupbox.h>
#include <kcombobox.h>
#include <klocale.h>
#include "symboldlg.h"
#include "cscopefrontend.h"
#include "kscopeconfig.h"
QStringList SymbolDlg::s_slHistory;
/**
* Class constructor.
* @param pParent Parent widget
* @param szName This widget's name
*/
SymbolDlg::SymbolDlg(QWidget* pParent, const char* szName) :
SymbolLayout(pParent, szName, true, 0),
m_progress(m_pHintList)
{
// Create a persistent Cscope process
m_pCscope = new CscopeFrontend();
// Initialise the hint list (hidden by default)
m_pHintList->addColumn(i18n("Suggested Symbols"));
m_pHintList->hide();
((QWidget*)m_pHintGroup)->hide();
m_pBeginWithRadio->toggle();
adjustSize();
// Close the dialogue when either the "OK" or "Cancel" button are clicked
connect(m_pOKButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(m_pCancelButton, SIGNAL(clicked()), this, SLOT(reject()));
// Run a symbol completion query when the "Hint" button is clicked
connect(m_pHintButton, SIGNAL(clicked()), this, SLOT(slotHintClicked()));
// Add results to the hint list
connect(m_pCscope, SIGNAL(dataReady(FrontendToken*)), this,
SLOT(slotHintDataReady(FrontendToken*)));
// Set hint button availability based on the type of query
connect(m_pTypeCombo, SIGNAL(activated(int)), this,
SLOT(slotTypeChanged(int)));
// Selecting an item in the hint list sets it as the current text
connect(m_pHintList, SIGNAL(selectionChanged(QListViewItem*)), this,
SLOT(slotHintItemSelected(QListViewItem*)));
// Double-clicking an item in the hint list accepts that item as the
// result of the query (i.e., the item is selcted and the dialogue is
// closed)
connect(m_pHintList, SIGNAL(doubleClicked(QListViewItem*)), this,
SLOT(accept()));
// Refresh the hint list when the hint options change
connect(m_pBeginWithRadio, SIGNAL(toggled(bool)), this,
SLOT(slotHintOptionChanged(bool)));
connect(m_pContainRadio, SIGNAL(toggled(bool)), this,
SLOT(slotHintOptionChanged(bool)));
// Show hint query progress information
connect(m_pCscope, SIGNAL(progress(int, int)), this,
SLOT(slotHintProgress(int, int)));
connect(m_pCscope, SIGNAL(finished(uint)), this,
SLOT(slotHintFinished(uint)));
}
/**
* Class destructor.
*/
SymbolDlg::~SymbolDlg()
{
delete m_pCscope;
}
/**
* Displays the requested type of query in the type combo-box.
* @param nType The requested type
*/
void SymbolDlg::setType(uint nType)
{
m_pTypeCombo->setCurrentItem(nType);
slotTypeChanged(nType);
}
/**
* @param sSymbol The initial text of the combo-box
*/
void SymbolDlg::setSymbol(const QString& sSymbol)
{
m_pSymbolHC->setCurrentText(sSymbol);
}
/**
* @param slSymHistory A list of previously queried symbols
*/
void SymbolDlg::setHistory(QStringList& slSymHistory)
{
m_pSymbolHC->setHistoryItems(slSymHistory);
}
/**
* @return The current text of the symbol combo-box
*/
QString SymbolDlg::getSymbol() const
{
QString sResult;
sResult = m_pSymbolHC->currentText().stripWhiteSpace();
if (m_pSubStringCheck->isChecked())
sResult = ".*" + sResult + ".*";
return sResult;
}
/**
* @return The type of query requested by the user
* @note The returned value does not conform to the type used for running
* Cscope queries. Use getQueryType() to translate between these
* values.
*/
uint SymbolDlg::getType() const
{
return m_pTypeCombo->currentItem();
}
bool SymbolDlg::getCase() const
{
return !m_pCaseCheck->isChecked();
}
/**
* A convinience static function for creating and showing SymbolDlg dialogue.
* @param pParent The parent widget
* @param nType The type of query requested by the user (may be
* changed in the dialogue)
* @param sSymbol The initial text of the combo-box
* @return The text entered by the user in the symbol combo-box, or an empty
* string if the dialogue was cancelled
*/
QString SymbolDlg::promptSymbol(QWidget* pParent, uint& nType,
const QString& sSymbol, bool& bCase)
{
SymbolDlg dlg(pParent);
// Initialise the dialogue
dlg.setType(nType);
dlg.setHistory(s_slHistory);
dlg.setSymbol(sSymbol);
// Display the dialogue
if (dlg.exec() != QDialog::Accepted)
return "";
// Return the text entered by the user
nType = dlg.getType();
bCase = dlg.getCase();
dlg.m_pSymbolHC->addToHistory(dlg.getSymbol());
s_slHistory = dlg.m_pSymbolHC->historyItems();
return dlg.getSymbol();
}
/**
* Translates a symbol dialogue type into a Cscope query type.
* @param nType The type to translate
* @return A query type matching the symbol dialogue type
*/
uint SymbolDlg::getQueryType(uint nType)
{
if (nType == CallTree)
return CscopeFrontend::None;
if (nType <= Text)
return nType;
return nType + 1;
}
/**
* Runs a symbol definition query, looking for symbols starting with the
* currently entered text.
* If the hint list is not visible, it is shown first.
* This slot is connected to the clicked() signal of the "Hint" button.
*/
void SymbolDlg::slotHintClicked()
{
QString sText, sRegExp;
// Show the hint list if necessary
if (!m_pHintList->isVisible()) {
m_pHintList->show();
((QWidget*)m_pHintGroup)->show();
adjustSize();
}
// Clear the previous contents
m_pHintList->clear();
// Get the currently entered text (must have at least one character)
sText = m_pSymbolHC->currentText().stripWhiteSpace();
if (sText.isEmpty())
return;
// Create the regular expression
if (m_pBeginWithRadio->isOn())
sRegExp = sText + "[a-zA-Z0-9_]*";
else
sRegExp = "[a-zA-Z0-9_]*" + sText + "[a-zA-Z0-9_]*";
m_reHint.setPattern(sRegExp);
// Run a Cscope symbol definition query using a regular expression
m_pCscope->query(CscopeFrontend::Definition, sRegExp);
}
/**
* Called when a new record is ready to be added to the hint list.
* NOTE: Cscope 15.5 has a bug where the "function" field of the record
* displays the regular expression instead of the matched symbol name. For
* this reason, we need to extract the symbol from the "Text" field.
* @param pToken The head of the record's token list
*/
void SymbolDlg::slotHintDataReady(FrontendToken* pToken)
{
QString sText;
// Get the line text
pToken = pToken->getNext()->getNext()->getNext();
sText = pToken->getData();
// Find the symbol within the line
if (m_reHint.search(sText) == -1)
return;
// Find the symbol within the list, if found - do not add
if (m_pHintList->findItem(m_reHint.capturedTexts().first(), 0))
return;
// Add a list item
(void)new QListViewItem(m_pHintList, m_reHint.capturedTexts().first());
}
/**
* Sets the text of a selected hint list item as the current text of the
* symbol combo-box.
* This slot is connected to the doubleClicked() signal of the hint list-view.
* @param pItem The clicked list item
*/
void SymbolDlg::slotHintItemSelected(QListViewItem* pItem)
{
m_pSymbolHC->setCurrentText(pItem->text(0));
}
/**
* Refreshes the hint list based on the newly selected option.
* This slot is connected to the toggled() signal of the hint options radio
* buttons.
* NOTE: The list is only refreshed if the system profile is set to Fast.
* @param bOn true if the button was toggled on
*/
void SymbolDlg::slotHintOptionChanged(bool bOn)
{
if (bOn && Config().getSysProfile() == KScopeConfig::Fast)
slotHintClicked();
}
/**
* Display a progress bar while the hint query is working.
* This slot is connected to the progress() signal emitted by the Cscope
* frontend object.
* @param nProgress Progress value
* @param nTotal The final expected value
*/
void SymbolDlg::slotHintProgress(int nProgress, int nTotal)
{
m_progress.setProgress(nProgress, nTotal);
}
/**
* Destroys all progress information widget when the query process terminates.
* This slot is connected to the finished() signal emitted by the Cscope
* process.
*/
void SymbolDlg::slotHintFinished(uint /* ignored */)
{
m_progress.finished();
}
/**
* Enables/disables the hint button, based on the newly selected type.
* This slot is connected to the activated() signal of the type combo-box.
* @param nType The newly selected type
*/
void SymbolDlg::slotTypeChanged(int nType)
{
if (nType == FileName || nType == Including)
m_pHintButton->setEnabled(false);
else
m_pHintButton->setEnabled(true);
}
#include "symboldlg.moc"
|