summaryrefslogtreecommitdiffstats
path: root/src/symboldlg.cpp
blob: f1b4047cd6805d0cd3ba61dc77018506593ef214 (plain)
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 ([email protected])
 *
 * 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 <tqlabel.h>
#include <tqlistview.h>
#include <tqpushbutton.h>
#include <tqradiobutton.h>
#include <tqcheckbox.h>
#include <tqgroupbox.h>
#include <kcombobox.h>
#include <tdelocale.h>
#include "symboldlg.h"
#include "cscopefrontend.h"
#include "kscopeconfig.h"

TQStringList SymbolDlg::s_slHistory;

/**
 * Class constructor.
 * @param	pParent	Parent widget
 * @param	szName	This widget's name
 */
SymbolDlg::SymbolDlg(TQWidget* 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();
	((TQWidget*)m_pHintGroup)->hide();
	m_pBeginWithRadio->toggle();
	adjustSize();
	
	// Close the dialogue when either the "OK" or "Cancel" button are clicked
	connect(m_pOKButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(accept()));
	connect(m_pCancelButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(reject()));
	
	// Run a symbol completion query when the "Hint" button is clicked
	connect(m_pHintButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotHintClicked()));
	
	// Add results to the hint list
	connect(m_pCscope, TQ_SIGNAL(dataReady(FrontendToken*)), this,
		TQ_SLOT(slotHintDataReady(FrontendToken*)));

	// Set hint button availability based on the type of query
	connect(m_pTypeCombo, TQ_SIGNAL(activated(int)), this, 
		TQ_SLOT(slotTypeChanged(int)));
		
	// Selecting an item in the hint list sets it as the current text	
	connect(m_pHintList, TQ_SIGNAL(selectionChanged(TQListViewItem*)), this,
		TQ_SLOT(slotHintItemSelected(TQListViewItem*)));
	
	// 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, TQ_SIGNAL(doubleClicked(TQListViewItem*)), this,
		TQ_SLOT(accept()));
		
	// Refresh the hint list when the hint options change
	connect(m_pBeginWithRadio, TQ_SIGNAL(toggled(bool)), this,
		TQ_SLOT(slotHintOptionChanged(bool)));
	connect(m_pContainRadio, TQ_SIGNAL(toggled(bool)), this,
		TQ_SLOT(slotHintOptionChanged(bool)));
		
	// Show hint query progress information
	connect(m_pCscope, TQ_SIGNAL(progress(int, int)), this,
		TQ_SLOT(slotHintProgress(int, int)));
	connect(m_pCscope, TQ_SIGNAL(finished(uint)), this,
		TQ_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 TQString& sSymbol)
{
	m_pSymbolHC->setCurrentText(sSymbol);
}

/**
 * @param	slSymHistory	A list of previously queried symbols
 */
void SymbolDlg::setHistory(TQStringList& slSymHistory)
{
	m_pSymbolHC->setHistoryItems(slSymHistory);
}

/**
 * @return	The current text of the symbol combo-box
 */
TQString SymbolDlg::getSymbol() const
{
	TQString 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
 */
TQString SymbolDlg::promptSymbol(TQWidget* pParent, uint& nType, 
	const TQString& 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() != TQDialog::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()
{
	TQString sText, sRegExp;
	
	// Show the hint list if necessary
	if (!m_pHintList->isVisible()) {
		m_pHintList->show();
		((TQWidget*)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)
{
	TQString 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 TQListViewItem(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(TQListViewItem* 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"