summaryrefslogtreecommitdiffstats
path: root/src/queryview.cpp
blob: 172e484d0478a0c5d144fb94657e7f98a1777462 (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
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
/***************************************************************************
 *
 * 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 <tqapplication.h>
#include <tqclipboard.h>
#include <tdelocale.h>
#include "queryview.h"
#include "queryresultsmenu.h"
#include "queryviewdlg.h"
#include "cscopefrontend.h"
#include "searchresultsdlg.h"

/**
 * Class constructor.
 * @param	pParent	The parent widget
 * @param	szName	The name of the widget
 */
QueryView::QueryView(TQWidget* pParent, const char* szName) :
	TQListView(pParent, szName),
	m_pLastItem(NULL)
{
	// Create the popup-menu
	m_pQueryMenu = new QueryResultsMenu(this);

	// Initialise the list's columns
	setAllColumnsShowFocus(true);
	addColumn(i18n("Function"));
	addColumn(i18n("File"));
	addColumn(i18n("Line"));
	addColumn(i18n("Text"));
	setColumnAlignment(2, TQt::AlignRight);

	setShowSortIndicator(true);
	
	// A record is selected if it is either double-clicked, or the ENTER
	// key is pressed while the record is highlighted
	connect(this, SIGNAL(doubleClicked(TQListViewItem*)), this, 
		SLOT(slotRecordSelected(TQListViewItem*)));
	connect(this, SIGNAL(returnPressed(TQListViewItem*)), this, 
		SLOT(slotRecordSelected(TQListViewItem*)));
		
	// Show the popup-menu when requested
	connect(this, 
		SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint&, int)),
		m_pQueryMenu, SLOT(slotShow(TQListViewItem*, const TQPoint&, int)));
		
	// Handle popup-menu commands
	connect(m_pQueryMenu, SIGNAL(viewSource(TQListViewItem*)), this,
		SLOT(slotRecordSelected(TQListViewItem*)));
	connect(m_pQueryMenu, SIGNAL(findDef(const TQString&)), this,
		SLOT(slotFindDef(const TQString&)));
	connect(m_pQueryMenu, SIGNAL(copy(TQListViewItem*, int)), this,
		SLOT(slotCopy(TQListViewItem*, int)));
	connect(m_pQueryMenu, SIGNAL(filter(int)), this, SLOT(slotFilter(int)));
	connect(m_pQueryMenu, SIGNAL(showAll()), this, 
		SLOT(slotShowAll()));
	connect(m_pQueryMenu, SIGNAL(remove(TQListViewItem*)), this,
		SLOT(slotRemoveItem(TQListViewItem*)));
}

/**
 * Class destructor.
 */
QueryView::~QueryView()
{
}

/**
 * Creates a new list item showing a query result record.
 * @param	sFunc	The name of the function
 * @param	sFile	The file path
 * @param	sLine	The line number in the above file
 * @param	sText	The line's text
 * @param	pParent	The parent item (ignored)
 */
void QueryView::addRecord(const TQString& sFunc, const TQString& sFile,
	const TQString& sLine, const TQString& sText, TQListViewItem* /* pParent */)
{
	TQListViewItem* pItem;
	
	pItem = new QueryViewItem(this, m_pLastItem, 2);
	pItem->setText(0, sFunc);
	pItem->setText(1, sFile);
	pItem->setText(2, sLine);
	pItem->setText(3, sText);
	
	m_pLastItem = pItem;
}

/**
 * Selects an item.
 * When an item is selected, it is highlighted and made visible. By
 * definition, the lineRequested() signal is also emitted.
 * This method is used for selecting records programmatically (@see
 * selectNext() for example). It has nothing to do with user selection.
 * @param	pItem	The list item to select
 */
void QueryView::select(TQListViewItem* pItem)
{
	ensureItemVisible(pItem);
	setSelected(pItem, true);
	slotRecordSelected(pItem);
}

/**
 * Selects the next record in the list (if one exists).
 * The function selects the next item as follows:
 * - The first item in the list, if there is no current item
 * - The current item, if it is not selected
 * - The item immediately below the current item, otherwise
 */
void QueryView::selectNext()
{
	TQListViewItem* pItem;
	
	// Do nothing if the list is empty
	if (firstChild() == NULL)
		return;
		
	// Find the next record
	pItem = currentItem();
	if (pItem == NULL) {
		pItem = firstChild();
	}
	else if (pItem->isSelected()) {
		pItem = pItem->itemBelow();
		if (pItem == NULL)
			return;
	}
	
	// Select the new item
	select(pItem);
}

/**
 * Selects the previous record in the list (if one exists).
 * The function selects the previous item as follows:
 * - The first item in the list, if there is no current item
 * - The current item, if it is not selected
 * - The item immediately above the current item, otherwise
 */
void QueryView::selectPrev()
{
	TQListViewItem* pItem;
	
	// Do nothing if the list is empty
	if (firstChild() == NULL)
		return;
	
	// Find the item immediately above this one
	pItem = currentItem();
	if (pItem == NULL) {
		pItem = firstChild();
	}
	else if (pItem->isSelected()) {
		pItem = pItem->itemAbove();
		if (pItem == NULL)
			return;
	}
		
	// Select the new item
	select(pItem);
}

/**
 * Informs the view that query progress information has been received.
 * The view emits the needToShow() signal telling its parent that the widget
 * should become visible (if not already so).
 */
void QueryView::queryProgress()
{
	if (!isVisible())
		emit needToShow();
}

/**
 * Called when a query using this view terminates.
 * @param	nRecords	Number of records generated by the query
 */
void QueryView::queryFinished(uint nRecords, TQListViewItem*)
{
	// Auto-select a single record (no need to emit the show() signal in
	// that case)
	if (nRecords == 1) {
		emit select(firstChild());
		return;
	}
	
	// Report a query that has returned an empty record set
	if (nRecords == 0)
		addRecord(i18n("No results"), "", "", "", NULL);
	
	// Data is available, instruct the owner object to show the view
	emit needToShow();
}

/**
 * Creates an iterator and initialises it to point to the first _visible_
 * item in the list.
 * @return	A new iterator initialised to the beginning of the list
 */
QueryView::Iterator QueryView::getIterator()
{
	TQListViewItem* pItem;
	
	for (pItem = firstChild(); pItem != NULL && !pItem->isVisible(); 
		pItem = pItem->nextSibling());
		
	return Iterator(pItem);
}

/**
 * Handles double-click events over the view.
 * NOTE: We override this method since the TQListView implementation opens
 * expandable items. This is undesired for tree-like query views (such as the
 * call tree.
 * @param	pEvent	Event description object
 */
void QueryView::contentsMouseDoubleClickEvent(TQMouseEvent* pEvent)
{
	TQListViewItem* pItem;
	
	// Handle only left button double-clicks
	if (pEvent == NULL || pEvent->button() != LeftButton)
		return;
		
	// Find the clicked item
	pItem = itemAt(contentsToViewport(pEvent->pos()));
	if (pItem == NULL)
		return;
		
	// Emit the doubleClicked() signal
	emit doubleClicked(pItem);
}

/**
 * Emits the lineRequested() signal when a list item is selected.
 * This slot is connected to the doubleClicked() and returnPressed()
 * signals of the list view.
 * @param	pItem	The selected item
 */
void QueryView::slotRecordSelected(TQListViewItem* pItem)
{
	TQString sFileName, sLine;

	// Get the file name and line number
	sFileName = pItem->text(1);
	sLine = pItem->text(2);

	// Do not process the "No results" item
	if (!sLine.isEmpty())
		emit lineRequested(sFileName, sLine.toUInt());
}

/**
 * Looks up the definition of a given function.
 * Results are displayed in a popup window.
 * This slot is connected to the findDef() signal emitted by the results menu.
 * @param	sFunc	The function to look for
 */
void QueryView::slotFindDef(const TQString& sFunc)
{
	QueryViewDlg* pDlg;
	
	// Create a query view dialogue
	pDlg = new QueryViewDlg(QueryViewDlg::DestroyOnSelect, this);
	
	// Display a line when it is selected in the dialogue
	connect(pDlg, SIGNAL(lineRequested(const TQString&, uint)), this,
		SIGNAL(lineRequested(const TQString&, uint)));
		
	// Start the query
	pDlg->query(CscopeFrontend::Definition, sFunc);
}

/**
 * Copies the text of the requested field (item+column) to the clipboard.
 * This slot is connected to the copy() signal of the QueryResultsMenu object.
 * @param	pItem	The item from which to copy
 * @param	nCol	The index of the item field to copy
 */
void QueryView::slotCopy(TQListViewItem* pItem, int nCol)
{
	TQApplication::clipboard()->setText(pItem->text(nCol),
		TQClipboard::Clipboard);
}

/**
 * Hides all items in the page that do not meet the given search criteria.
 * This slot is connected to the search() signal of the QueryResultsMenu
 * object.
 * The search is incremental: only visible items are checked, so that a new
 * search goes over the results of the previous one.
 * @param	nCol	The list column to search in
 */
void QueryView::slotFilter(int nCol)
{
	SearchResultsDlg dlg(this);
	TQRegExp re;
	TQListViewItem* pItem;
	bool bNegate;
	
	// Prepare the dialogue
	dlg.setColumn(nCol);
	
	// Show the dialogue
	if (dlg.exec() != TQDialog::Accepted)
		return;
		
	// Get the selected regular expression
	dlg.getPattern(re);
	bNegate = dlg.isNegated();
	
	// Disable visual updates while search is in progress
	setUpdatesEnabled(false);
	
	// Iterate over all items in the list
	pItem = firstChild();
	while (pItem != NULL) {
		// Filter visible items only
		if (pItem->isVisible() &&
			(re.search(pItem->text(nCol)) == -1) != bNegate) {
			pItem->setVisible(false);
		}
		
		pItem = pItem->nextSibling();
	}
	
	// Redraw the list
	setUpdatesEnabled(true);
	triggerUpdate();
}

/**
 * Makes all list items visible.
 * This slot is connected to the showAll() signal of the QueryResultsMenu
 * object.
 */
void QueryView::slotShowAll()
{
	TQListViewItem* pItem;
	
	// Iterate over all items in the list
	pItem = firstChild();
	while (pItem != NULL) {
		pItem->setVisible(true);
		pItem = pItem->nextSibling();
	}
}

/**
 * Deletes the item on which a popup-menu has been invoked.
 * This slot is connected to the remove() signal of the QueryResultsMenu
 * object.
 * @param	pItem	The item to remove
 */
void QueryView::slotRemoveItem(TQListViewItem* pItem)
{
	delete pItem;
}

/**
 * Moves the iterator to the next _visible_ item in the list.
 */
void QueryView::Iterator::next()
{
	if (m_pItem == NULL)
		return;
		
	do {
		m_pItem = m_pItem->nextSibling();
	} while (m_pItem != NULL && !m_pItem->isVisible());
}

/**
 * @return	The function associated with the list item the iterator points to
 */
TQString QueryView::Iterator::getFunc()
{
	if (m_pItem == NULL)
		return "";
		
	return m_pItem->text(0);
}

/**
 * @return	The file associated with the list item the iterator points to
 */
TQString QueryView::Iterator::getFile()
{
	if (m_pItem == NULL)
		return "";
		
	return m_pItem->text(1);
}

/**
 * @return	The line number associated with the list item the iterator points
 *			to
 */
TQString QueryView::Iterator::getLine()
{
	if (m_pItem == NULL)
		return "";
		
	return m_pItem->text(2);
}

/**
 * @return	The text associated with the list item the iterator points to
 */
TQString QueryView::Iterator::getText()
{
	if (m_pItem == NULL)
		return "";
		
	return m_pItem->text(3);
}

#include "queryview.moc"