From f04cf8a9dd3150a0127a449e606ead585a31d6d2 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Tue, 12 Apr 2011 23:21:52 -0400 Subject: [PATCH] Add a search widget and fix go to. go to wasn't indexing the call indexes but the row counts, which don't always match. also adding a nice search widget to search for specific calls within the view. --- gui/CMakeLists.txt | 2 + gui/apitrace.cpp | 10 +++ gui/apitrace.h | 1 + gui/apitracefilter.cpp | 4 +- gui/apitracemodel.cpp | 3 +- gui/mainwindow.cpp | 97 ++++++++++++++++++++ gui/mainwindow.h | 5 ++ gui/qapitrace.qrc | 2 + gui/resources/go-down-search.png | Bin 0 -> 1249 bytes gui/resources/go-up-search.png | Bin 0 -> 1231 bytes gui/searchwidget.cpp | 80 +++++++++++++++++ gui/searchwidget.h | 37 ++++++++ gui/ui/searchwidget.ui | 150 +++++++++++++++++++++++++++++++ 13 files changed, 388 insertions(+), 3 deletions(-) create mode 100644 gui/resources/go-down-search.png create mode 100644 gui/resources/go-up-search.png create mode 100644 gui/searchwidget.cpp create mode 100644 gui/searchwidget.h create mode 100644 gui/ui/searchwidget.ui diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 15d14ce..6787043 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -15,6 +15,7 @@ set(qapitrace_SRCS mainwindow.cpp main.cpp retracer.cpp + searchwidget.cpp settingsdialog.cpp shaderssourcewidget.cpp tracedialog.cpp @@ -33,6 +34,7 @@ set(qapitrace_UIS ui/retracerdialog.ui ui/settings.ui ui/tracedialog.ui + ui/searchwidget.ui ui/shaderssourcewidget.ui ) diff --git a/gui/apitrace.cpp b/gui/apitrace.cpp index 6cc360b..03ff02e 100644 --- a/gui/apitrace.cpp +++ b/gui/apitrace.cpp @@ -171,4 +171,14 @@ void ApiTrace::detectFrames() emit framesAdded(0, m_frames.count()); } +ApiTraceCall * ApiTrace::callWithIndex(int idx) const +{ + for (int i = 0; i < m_calls.count(); ++i) { + ApiTraceCall *call = m_calls[i]; + if (call->index == idx) + return call; + } + return NULL; +} + #include "apitrace.moc" diff --git a/gui/apitrace.h b/gui/apitrace.h index a46e8e0..f1f6811 100644 --- a/gui/apitrace.h +++ b/gui/apitrace.h @@ -31,6 +31,7 @@ public: QList calls() const; ApiTraceCall *callAt(int idx) const; + ApiTraceCall *callWithIndex(int idx) const; int numCalls() const; QList frames() const; diff --git a/gui/apitracefilter.cpp b/gui/apitracefilter.cpp index 5c80450..7580bba 100644 --- a/gui/apitracefilter.cpp +++ b/gui/apitracefilter.cpp @@ -89,10 +89,10 @@ void ApiTraceFilter::setFilterOptions(ApiTraceFilter::FilterOptions opts) } } -QModelIndex ApiTraceFilter::callIndex(int callNum) const +QModelIndex ApiTraceFilter::callIndex(int callIdx) const { ApiTraceModel *model = static_cast(sourceModel()); - QModelIndex index = model->callIndex(callNum); + QModelIndex index = model->callIndex(callIdx); return mapFromSource(index); } diff --git a/gui/apitracemodel.cpp b/gui/apitracemodel.cpp index eb29a0e..2b4b6bb 100644 --- a/gui/apitracemodel.cpp +++ b/gui/apitracemodel.cpp @@ -255,9 +255,10 @@ void ApiTraceModel::stateSetOnEvent(ApiTraceEvent *event) QModelIndex ApiTraceModel::callIndex(int callNum) const { - ApiTraceCall *call = m_trace->callAt(callNum); + ApiTraceCall *call = m_trace->callWithIndex(callNum); if (!call) { + qDebug()<<"couldn't find call at "<addWidget(m_jumpWidget); m_jumpWidget->hide(); + m_searchWidget = new SearchWidget(this); + m_ui.centralLayout->addWidget(m_searchWidget); + m_searchWidget->hide(); + m_traceProcess = new TraceProcess(this); new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_G), this, SLOT(slotGoTo())); + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F), + this, SLOT(slotSearch())); } void MainWindow::initConnections() @@ -584,6 +591,11 @@ void MainWindow::initConnections() connect(m_jumpWidget, SIGNAL(jumpTo(int)), SLOT(slotJumpTo(int))); + connect(m_searchWidget, SIGNAL(searchNext(const QString&, Qt::CaseSensitivity)), + SLOT(slotSearchNext(const QString&, Qt::CaseSensitivity))); + connect(m_searchWidget, SIGNAL(searchPrev(const QString&, Qt::CaseSensitivity)), + SLOT(slotSearchPrev(const QString&, Qt::CaseSensitivity))); + connect(m_traceProcess, SIGNAL(tracedFile(const QString&)), SLOT(createdTrace(const QString&))); connect(m_traceProcess, SIGNAL(error(const QString&)), @@ -603,6 +615,7 @@ void MainWindow::replayStateFound(const ApiTraceState &state) void MainWindow::slotGoTo() { + m_searchWidget->hide(); m_jumpWidget->show(); } @@ -628,4 +641,88 @@ void MainWindow::traceError(const QString &msg) msg); } +void MainWindow::slotSearch() +{ + m_jumpWidget->hide(); + m_searchWidget->show(); +} + +void MainWindow::slotSearchNext(const QString &str, Qt::CaseSensitivity sensitivity) +{ + QModelIndex index = m_ui.callView->currentIndex(); + ApiTraceEvent *event = + index.data(ApiTraceModel::EventRole).value(); + ApiTraceCall *call = 0; + + if (event->type() == ApiTraceCall::Call) + call = static_cast(event); + else { + Q_ASSERT(event->type() == ApiTraceCall::Frame); + ApiTraceFrame *frame = static_cast(event); + call = frame->calls.value(0); + } + + if (!call) { + m_searchWidget->setFound(false); + return; + } + const QList &calls = m_trace->calls(); + int callNum = calls.indexOf(call); + + for (int i = callNum + 1; i < calls.count(); ++i) { + ApiTraceCall *testCall = calls[i]; + QString txt = testCall->filterText(); + if (txt.contains(str, sensitivity)) { + QModelIndex index = m_proxyModel->callIndex(testCall->index); + /* if it's not valid it means that the proxy model has already + * filtered it out */ + if (index.isValid()) { + m_ui.callView->setCurrentIndex(index); + m_searchWidget->setFound(true); + return; + } + } + } + m_searchWidget->setFound(false); +} + +void MainWindow::slotSearchPrev(const QString &str, Qt::CaseSensitivity sensitivity) +{ + QModelIndex index = m_ui.callView->currentIndex(); + ApiTraceEvent *event = + index.data(ApiTraceModel::EventRole).value(); + ApiTraceCall *call = 0; + + if (event->type() == ApiTraceCall::Call) + call = static_cast(event); + else { + Q_ASSERT(event->type() == ApiTraceCall::Frame); + ApiTraceFrame *frame = static_cast(event); + call = frame->calls.value(0); + } + + if (!call) { + m_searchWidget->setFound(false); + return; + } + const QList &calls = m_trace->calls(); + int callNum = calls.indexOf(call); + + for (int i = callNum - 1; i >= 0; --i) { + ApiTraceCall *testCall = calls[i]; + QString txt = testCall->filterText(); + if (txt.contains(str, sensitivity)) { + QModelIndex index = m_proxyModel->callIndex(testCall->index); + /* if it's not valid it means that the proxy model has already + * filtered it out */ + if (index.isValid()) { + m_ui.callView->setCurrentIndex(index); + m_searchWidget->setFound(true); + return; + } + } + } + m_searchWidget->setFound(false); +} + #include "mainwindow.moc" diff --git a/gui/mainwindow.h b/gui/mainwindow.h index bd483ed..ae28441 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -19,6 +19,7 @@ class QModelIndex; class QProgressBar; class QUrl; class Retracer; +class SearchWidget; class ShadersSourceWidget; class TraceProcess; class VertexDataInterpreter; @@ -54,6 +55,9 @@ private slots: void slotJumpTo(int callNum); void createdTrace(const QString &path); void traceError(const QString &msg); + void slotSearch(); + void slotSearchNext(const QString &str, Qt::CaseSensitivity sensitivity); + void slotSearchPrev(const QString &str, Qt::CaseSensitivity sensitivity); private: void initObjects(); @@ -86,6 +90,7 @@ private: ImageViewer *m_imageViewer; JumpWidget *m_jumpWidget; + SearchWidget *m_searchWidget; TraceProcess *m_traceProcess; }; diff --git a/gui/qapitrace.qrc b/gui/qapitrace.qrc index c5fc6f7..a989c42 100644 --- a/gui/qapitrace.qrc +++ b/gui/qapitrace.qrc @@ -5,6 +5,8 @@ resources/dialog-information.png resources/document-new.png resources/document-open.png + resources/go-down-search.png + resources/go-up-search.png resources/media-playback-start.png resources/media-playback-stop.png resources/media-record.png diff --git a/gui/resources/go-down-search.png b/gui/resources/go-down-search.png new file mode 100644 index 0000000000000000000000000000000000000000..a1b12554df2f497f3d2fbfcf5455fab0a378811c GIT binary patch literal 1249 zcmV<71Rnc|P)lA2Z;ttbc;wTRL9M=gp~ z5lm2`4??BdC($=i)1*S%Hy;G`MJ3TjE4Cm?6txsd6s#hxiWN$s7+nr1n5kK;AGG}Mz`_4Ic?o32ViT@KZR3Q?HY^HD>{#%@+qEFW~P!Z2$vxhCy zthk{+mq5)iANsD{;AOn?RYapvT-@3^1R&4=EYpH%*{+yRP4k6Z0W}7SN0g|HKmm)f zs6x*GGgTBYY{|Kcnl!}QG{uMtzBbfAptw4UT*>jOH!TOD}G@#-T1FB;9v1FwIv$g!`x6)!&27t#Uc3AkrV2ZWGFqzvr)FoADR=WD7k zEK$uG@#AwjjD7Gs&YUarJ?_6D-uMWv-LwXe-_Z?QNECDjuYI1x+tYu-c4XZVRNzn; z|1ybJJ~>;thOgbVeFLt)yuE=DR4usvE8Dr%ZyZ}f1)rWwV|J;GXLoFbW!H`%mACNn z)LG0XOI~jG-5YVs)$6blYCg$Gc(7C|9Tt+Sgyx!=IeaV}jjISK)Wrg=HWW4Ep6 zYi!$g&l8Qkj%A&lZFryuMML1o@pDk&IPfsk-;GCZ?t)<$Y`}3G&wy^(28DdEf#6+@ zOpK8DV#q$Qx|c~T zs^P$+o6&z&2Xp`M6@U~lO%thf8cng7C;rlb{WAyO8h;MJAE*a%<&iL0)^$lUlsZLP zNRn^77N3bK8 z&+8$rS4Y6-WU@JV>eo5_;o;#|0ra}}45hjiucvSmv5gp2s40vveMonc`H{Fxbcl8p zEiV%P8B2s+5Zs%_h|O+na@p+07XF{8yvBgVYB*llKRZ(B0 zKB-i(Qb7=W_f0Ih)GHKyRO>?|u}!IBun&z$Em3R=)uvk77>IYI*^Sc4Ub1O+XLk4a z&*5-5*|W%@Z%LSe-gf*BDt(<%MyA`B5EIfVhO@c7m5bBB*^3Si7aB40fH#xdD#b8mK3c*3o zK}`NW^^J?^@AG;K!v*MN|9Y{Ek1x11YzD`jHz#o9neDJm$o>b(UgPn^Fli5|JD3qz0Jf=t>GL=rqUx_hE^&!o$7j>vEJ#xTv-RcF*ly80bmhy)UxJ<*PIgE_UDA8D0VPu*dH1#viVS z2X>{=5wn_yiDKGeDggrz0)uT{ydwh|E1Pu-`JRx5H& zSgBMv3WXxpZmjW)Qt5PkXk>T{z{L;&(I$9PhuQ+(Yc61YeI2grVkw(N+=-*7C&Sx1 zJUV*vqshtFXK(tAwPp;PUYPE`Txr}Q|OSo_EUaCe7x!f`i9UhrJJ~1&w)B!A`2H_jdZVEiQjzem3b84DHEyV;R(%0B2h zFMqLELVsVcBp*Ba{)+$>nDRdU`x(&Rbs?h4#haFemq$jXC&z=#Ie8=cJrLcrAq?8k zmC4YwA3k~F*u+p!c19MaUV`k=(&}o3hKW%>8NJIK^geSC!3I#)0r;LmvBVY@f37@r z;J`Zowu&=DVbDJ{n?7=T2q}Wq1al*_&jk~g%oReOP$$$B_|g+ZTVQY%Wa3bp;0PZR taD +#include + +SearchWidget::SearchWidget(QWidget *parent) + : QWidget(parent) +{ + m_ui.setupUi(this); + + m_ui.notFoundLabel->hide(); + m_origPalette = m_ui.lineEdit->palette(); + + connect(m_ui.nextButton, SIGNAL(clicked()), + SLOT(slotSearchNext())); + connect(m_ui.prevButton, SIGNAL(clicked()), + SLOT(slotSearchPrev())); + connect(m_ui.closeButton, SIGNAL(clicked()), + SLOT(slotCancel())); + connect(m_ui.lineEdit, SIGNAL(returnPressed()), + SLOT(slotSearchNext())); + + installEventFilter(this); +} + +void SearchWidget::slotSearchNext() +{ + QString txt = m_ui.lineEdit->text(); + if (!txt.isEmpty()) + emit searchNext(txt, caseSensitivity()); +} + +void SearchWidget::slotSearchPrev() +{ + QString txt = m_ui.lineEdit->text(); + if (!txt.isEmpty()) + emit searchPrev(txt, caseSensitivity()); +} + +void SearchWidget::slotCancel() +{ + hide(); +} + +void SearchWidget::showEvent(QShowEvent *event) +{ + m_ui.lineEdit->selectAll(); + m_ui.lineEdit->setFocus(Qt::ShortcutFocusReason); + m_ui.lineEdit->setPalette(m_origPalette); + return QWidget::showEvent(event); +} + +Qt::CaseSensitivity SearchWidget::caseSensitivity() const +{ + if (m_ui.caseSensitiveBox->isChecked()) + return Qt::CaseSensitive; + else + return Qt::CaseInsensitive; +} + +bool SearchWidget::eventFilter(QObject *object, QEvent* event) +{ + if (event->type() == QEvent::KeyPress) { + if ((static_cast(event))->key() == Qt::Key_Escape) { + hide(); + } + } + return QWidget::eventFilter(object, event); +} + +void SearchWidget::setFound(bool found) +{ + QPalette pal = m_origPalette; + pal.setColor(QPalette::Active, QPalette::Base, + found ? Qt::white : QColor(255, 102, 102)); + m_ui.lineEdit->setPalette(pal); + m_ui.notFoundLabel->setVisible(!found); +} + +#include "searchwidget.moc" diff --git a/gui/searchwidget.h b/gui/searchwidget.h new file mode 100644 index 0000000..d105303 --- /dev/null +++ b/gui/searchwidget.h @@ -0,0 +1,37 @@ +#ifndef SEARCHWIDGET_H +#define SEARCHWIDGET_H + +#include "ui_searchwidget.h" +#include +#include + +class QShowEvent; + +class SearchWidget : public QWidget +{ + Q_OBJECT +public: + SearchWidget(QWidget *parent=0); + + void setFound(bool f); +signals: + void searchNext(const QString &str, Qt::CaseSensitivity cs = Qt::CaseInsensitive); + void searchPrev(const QString &str, Qt::CaseSensitivity cs = Qt::CaseInsensitive); + +private slots: + void slotSearchNext(); + void slotSearchPrev(); + void slotCancel(); + +protected: + virtual bool eventFilter(QObject *object, QEvent* event); + virtual void showEvent(QShowEvent *event); + +private: + Qt::CaseSensitivity caseSensitivity() const; +private: + Ui_SearchWidget m_ui; + QPalette m_origPalette; +}; + +#endif diff --git a/gui/ui/searchwidget.ui b/gui/ui/searchwidget.ui new file mode 100644 index 0000000..c13feac --- /dev/null +++ b/gui/ui/searchwidget.ui @@ -0,0 +1,150 @@ + + + SearchWidget + + + + 0 + 0 + 547 + 33 + + + + + 0 + 0 + + + + Form + + + + + + ... + + + + :/resources/dialog-close.png:/resources/dialog-close.png + + + true + + + Qt::NoArrow + + + + + + + + 0 + 0 + + + + + 170 + 0 + + + + + + + + Find previous occurance of the string + + + ... + + + + :/resources/go-up-search.png:/resources/go-up-search.png + + + + + + + Find next occurance of the text + + + ... + + + + :/resources/go-down-search.png:/resources/go-down-search.png + + + + + + + Case Sensitive + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 130 + 25 + + + + <b>Text not found</b> + + + Qt::RichText + + + true + + + 0 + + + 30 + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + + + -- 2.43.0