Revert "Added ability to roughly measure UI latency; code to try and maintain that latency at <50ms" (#859)
This commit is contained in:
parent
85e147a6ab
commit
8c1981361a
|
@ -1,7 +1,6 @@
|
|||
#include "_global.h"
|
||||
|
||||
GUIGUIINIT _gui_guiinit;
|
||||
GUIMESSAGELATENCY _gui_messagelatency;
|
||||
GUISENDMESSAGE _gui_sendmessage;
|
||||
GUISENDMESSAGEASYNC _gui_sendmessageasync;
|
||||
|
||||
|
|
|
@ -6,13 +6,11 @@
|
|||
|
||||
//GUI typedefs
|
||||
typedef int (*GUIGUIINIT)(int, char**);
|
||||
typedef uint32(*GUIMESSAGELATENCY)();
|
||||
typedef void* (*GUISENDMESSAGE)(GUIMSG type, void* param1, void* param2);
|
||||
typedef void (*GUISENDMESSAGEASYNC)(GUIMSG type, void* param1, void* param2);
|
||||
|
||||
//GUI functions
|
||||
extern GUIGUIINIT _gui_guiinit;
|
||||
extern GUIMESSAGELATENCY _gui_messagelatency;
|
||||
extern GUISENDMESSAGE _gui_sendmessage;
|
||||
extern GUISENDMESSAGEASYNC _gui_sendmessageasync;
|
||||
|
||||
|
|
|
@ -64,7 +64,6 @@ BRIDGE_IMPEXP const wchar_t* BridgeInit()
|
|||
//GUI Load
|
||||
LOADLIBRARY(gui_lib);
|
||||
LOADEXPORT(_gui_guiinit);
|
||||
LOADEXPORT(_gui_messagelatency);
|
||||
LOADEXPORT(_gui_sendmessage);
|
||||
|
||||
//DBG Load
|
||||
|
@ -996,13 +995,6 @@ BRIDGE_IMPEXP void GuiSetDebugState(DBGSTATE state)
|
|||
_gui_sendmessage(GUI_SET_DEBUG_STATE, (void*)state, 0);
|
||||
}
|
||||
|
||||
BRIDGE_IMPEXP DWORD GuiGetLatency()
|
||||
{
|
||||
return _gui_messagelatency();
|
||||
}
|
||||
|
||||
|
||||
|
||||
BRIDGE_IMPEXP void GuiAddLogMessage(const char* msg)
|
||||
{
|
||||
_gui_sendmessage(GUI_ADD_MSG_TO_LOG, (void*)msg, 0);
|
||||
|
|
|
@ -25,12 +25,6 @@ typedef unsigned long duint;
|
|||
typedef signed long dsint;
|
||||
#endif //_WIN64
|
||||
|
||||
typedef int int32;
|
||||
typedef unsigned int uint32;
|
||||
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
|
||||
#include "bridgegraph.h"
|
||||
|
||||
#ifndef BRIDGE_IMPEXP
|
||||
|
@ -985,7 +979,6 @@ typedef struct
|
|||
|
||||
//GUI functions
|
||||
//code page is utf8
|
||||
BRIDGE_IMPEXP DWORD GuiGetLatency();
|
||||
BRIDGE_IMPEXP void GuiDisasmAt(duint addr, duint cip);
|
||||
BRIDGE_IMPEXP void GuiSetDebugState(DBGSTATE state);
|
||||
BRIDGE_IMPEXP void GuiAddLogMessage(const char* msg);
|
||||
|
|
|
@ -140,7 +140,7 @@ typedef TRACERECORDTYPE(*GETTRACERECORDTYPE)(duint pageAddress);
|
|||
typedef bool(*ENUMHANDLES)(ListOf(HANDLEINFO) handles);
|
||||
typedef bool(*GETHANDLENAME)(duint handle, char* name, size_t nameSize, char* typeName, size_t typeNameSize);
|
||||
typedef bool(*ENUMTCPCONNECTIONS)(ListOf(TCPCONNECTIONINFO) connections);
|
||||
typedef uint64(*GETDBGEVENTS)();
|
||||
typedef duint(*GETDBGEVENTS)();
|
||||
typedef int(*MODGETPARTY)(duint base);
|
||||
typedef void(*MODSETPARTY)(duint base, int party);
|
||||
typedef bool(*WATCHISWATCHDOGTRIGGERED)(unsigned int id);
|
||||
|
|
|
@ -230,7 +230,6 @@ bool BpSetBreakCondition(duint Address, BP_TYPE Type, const char* Condition)
|
|||
return false;
|
||||
|
||||
strcpy_s(bpInfo->breakCondition, Condition);
|
||||
DebugUpdateBreakpointsViewAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -246,7 +245,6 @@ bool BpSetLogText(duint Address, BP_TYPE Type, const char* Log)
|
|||
return false;
|
||||
|
||||
strcpy_s(bpInfo->logText, Log);
|
||||
DebugUpdateBreakpointsViewAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -292,7 +290,6 @@ bool BpSetCommandCondition(duint Address, BP_TYPE Type, const char* Condition)
|
|||
return false;
|
||||
|
||||
strcpy_s(bpInfo->commandCondition, Condition);
|
||||
DebugUpdateBreakpointsViewAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -308,8 +305,6 @@ bool BpSetFastResume(duint Address, BP_TYPE Type, bool fastResume)
|
|||
return false;
|
||||
|
||||
bpInfo->fastResume = fastResume;
|
||||
DebugUpdateBreakpointsViewAsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ HANDLE hProcessToken;
|
|||
bool bUndecorateSymbolNames = true;
|
||||
bool bEnableSourceDebugging = true;
|
||||
bool bTraceRecordEnabledDuringTrace = true;
|
||||
uint64 DbgEvents = 0;
|
||||
duint DbgEvents = 0;
|
||||
|
||||
static duint dbgcleartracecondition()
|
||||
{
|
||||
|
@ -280,9 +280,9 @@ bool dbgcmddel(const char* name)
|
|||
return true;
|
||||
}
|
||||
|
||||
uint64 dbggetdbgevents()
|
||||
duint dbggetdbgevents()
|
||||
{
|
||||
return InterlockedCompareExchange64((int64*)&DbgEvents, -1, -1);
|
||||
return InterlockedExchange(&DbgEvents, 0);
|
||||
}
|
||||
|
||||
static DWORD WINAPI updateCallStackThread(duint ptr)
|
||||
|
@ -356,56 +356,23 @@ void DebugUpdateGui(duint disasm_addr, bool stack)
|
|||
GuiFocusView(GUI_DISASSEMBLY);
|
||||
}
|
||||
|
||||
void DebugUpdateGuiSetState(duint disasm_addr, bool stack, DBGSTATE state = paused, bool setDebugState = true)
|
||||
void DebugUpdateGuiSetState(duint disasm_addr, bool stack, DBGSTATE state = paused)
|
||||
{
|
||||
if(setDebugState)
|
||||
GuiSetDebugState(state);
|
||||
if(disasm_addr != 0)
|
||||
DebugUpdateGui(disasm_addr, stack);
|
||||
GuiSetDebugState(state);
|
||||
DebugUpdateGui(disasm_addr, stack);
|
||||
}
|
||||
|
||||
typedef TaskThread_<decltype(&DebugUpdateGuiSetState), duint, bool, DBGSTATE, bool> UpdateGuiSetStateTaskBase;
|
||||
struct UpdateGuiSetStateTask : public UpdateGuiSetStateTaskBase
|
||||
{
|
||||
UpdateGuiSetStateTask(UpdateGuiSetStateTaskBase::Fn_t f) : UpdateGuiSetStateTaskBase(f) {}
|
||||
virtual UpdateGuiSetStateTaskBase::Args_t CompressArguments(duint && addr, bool && stack, DBGSTATE && state, bool && updateDebugState) override
|
||||
{
|
||||
// Addr and stack args are not simply set; if addr is 0 it doesn't change the current addr and we
|
||||
// stack is sticky until its reset after running.
|
||||
return std::make_tuple(
|
||||
addr != 0 ? addr : std::get<0>(args),
|
||||
stack || std::get<1>(args),
|
||||
updateDebugState ? state : std::get<2>(args),
|
||||
updateDebugState || std::get<3>(args));
|
||||
}
|
||||
virtual void ResetArgs() override
|
||||
{
|
||||
// Necessary or addr and stack would always be non-zero, and always would run
|
||||
args = std::make_tuple(0, false, paused, false);
|
||||
}
|
||||
};
|
||||
|
||||
void DebugUpdateGuiSetStateAsync(duint disasm_addr, bool stack, DBGSTATE state, bool updateDebugState)
|
||||
void DebugUpdateGuiSetStateAsync(duint disasm_addr, bool stack, DBGSTATE state)
|
||||
{
|
||||
//correctly orders the GuiSetDebugState DebugUpdateGui to prevent drawing inconsistencies
|
||||
static UpdateGuiSetStateTask DebugUpdateGuiSetStateTask(&DebugUpdateGuiSetState);
|
||||
DebugUpdateGuiSetStateTask.WakeUp(disasm_addr, stack, state, updateDebugState);
|
||||
static TaskThread_<decltype(&DebugUpdateGuiSetState), duint, bool, DBGSTATE> DebugUpdateGuiSetStateTask(&DebugUpdateGuiSetState);
|
||||
DebugUpdateGuiSetStateTask.WakeUp(disasm_addr, stack, state);
|
||||
}
|
||||
|
||||
void DebugUpdateGuiAsync(duint disasm_addr, bool stack)
|
||||
{
|
||||
DebugUpdateGuiSetStateAsync(disasm_addr, stack, paused, false);
|
||||
}
|
||||
|
||||
void GuiSetDebugStateAsync(DBGSTATE state)
|
||||
{
|
||||
DebugUpdateGuiSetStateAsync(0, false, state);
|
||||
}
|
||||
|
||||
void DebugUpdateBreakpointsViewAsync()
|
||||
{
|
||||
static TaskThread_<decltype(&GuiUpdateBreakpointsView)> BreakpointsUpdateGuiTask(&GuiUpdateBreakpointsView);
|
||||
BreakpointsUpdateGuiTask.WakeUp();
|
||||
static TaskThread_<decltype(&DebugUpdateGui), duint, bool> DebugUpdateGuiTask(&DebugUpdateGui);
|
||||
DebugUpdateGuiTask.WakeUp(disasm_addr, stack);
|
||||
}
|
||||
|
||||
void DebugUpdateStack(duint dumpAddr, duint csp, bool forceDump)
|
||||
|
@ -545,6 +512,12 @@ static bool getConditionValue(const char* expression)
|
|||
return true;
|
||||
}
|
||||
|
||||
void GuiSetDebugStateAsync(DBGSTATE state)
|
||||
{
|
||||
static TaskThread_<decltype(&GuiSetDebugState), DBGSTATE> GuiSetDebugStateTask(&GuiSetDebugState);
|
||||
GuiSetDebugStateTask.WakeUp(state);
|
||||
}
|
||||
|
||||
void cbPauseBreakpoint()
|
||||
{
|
||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||
|
@ -1668,7 +1641,7 @@ static void cbException(EXCEPTION_DEBUG_INFO* ExceptionData)
|
|||
|
||||
static void cbDebugEvent(DEBUG_EVENT* DebugEvent)
|
||||
{
|
||||
InterlockedIncrement64((int64_t*)&DbgEvents);
|
||||
InterlockedIncrement(&DbgEvents);
|
||||
PLUG_CB_DEBUGEVENT debugEventInfo;
|
||||
debugEventInfo.DebugEvent = DebugEvent;
|
||||
plugincbcall(CB_DEBUGEVENT, &debugEventInfo);
|
||||
|
|
|
@ -69,8 +69,7 @@ bool dbgisdll();
|
|||
void dbgsetattachevent(HANDLE handle);
|
||||
void DebugUpdateGui(duint disasm_addr, bool stack);
|
||||
void DebugUpdateGuiAsync(duint disasm_addr, bool stack);
|
||||
void DebugUpdateGuiSetStateAsync(duint disasm_addr, bool stack, DBGSTATE state = paused, bool updateDebugState = true);
|
||||
void DebugUpdateBreakpointsViewAsync();
|
||||
void DebugUpdateGuiSetStateAsync(duint disasm_addr, bool stack, DBGSTATE state = paused);
|
||||
void DebugUpdateStack(duint dumpAddr, duint csp, bool forceDump = false);
|
||||
void GuiSetDebugStateAsync(DBGSTATE state);
|
||||
void dbgsetskipexceptions(bool skip);
|
||||
|
@ -88,7 +87,7 @@ bool dbgsetcmdline(const char* cmd_line, cmdline_error_t* cmd_line_error);
|
|||
bool dbggetcmdline(char** cmd_line, cmdline_error_t* cmd_line_error);
|
||||
void dbgstartscriptthread(CBPLUGINSCRIPT cbScript);
|
||||
duint dbggetdebuggedbase();
|
||||
uint64 dbggetdbgevents();
|
||||
duint dbggetdbgevents();
|
||||
bool dbgsettracecondition(String expression, duint maxCount);
|
||||
bool dbgtraceactive();
|
||||
|
||||
|
|
|
@ -31,8 +31,6 @@ protected:
|
|||
// Reset called after we latch in a value
|
||||
virtual void ResetArgs() { }
|
||||
public:
|
||||
typedef F Fn_t;
|
||||
typedef std::tuple<Args...> Args_t;
|
||||
void WakeUp(Args...);
|
||||
TaskThread_(F, size_t minSleepTimeMs = TASK_THREAD_DEFAULT_SLEEP_TIME);
|
||||
~TaskThread_();
|
||||
|
@ -130,11 +128,7 @@ template <typename F, typename... Args> void TaskThread_<F, Args...>::Loop()
|
|||
if(active)
|
||||
{
|
||||
apply_from_tuple(fn, argLatch);
|
||||
do
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(minSleepTimeMs));
|
||||
}
|
||||
while(GuiGetLatency() > 100);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(minSleepTimeMs));
|
||||
execs++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -221,6 +221,7 @@ HANDLE ThreadGetHandle(DWORD ThreadId)
|
|||
if(threadList.find(ThreadId) != threadList.end())
|
||||
return threadList[ThreadId].Handle;
|
||||
|
||||
ASSERT_ALWAYS("Trying to get handle of a thread that doesn't exist!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -952,10 +952,10 @@ int AbstractTableView::getLineToPrintcount()
|
|||
*
|
||||
* @param[in] width Width of the column in pixel
|
||||
* @param[in] isClickable Boolean that tells whether the header is clickable or not
|
||||
* @param[in] sortFn The sort function to use for this column. Defaults to case insensitve text search
|
||||
*
|
||||
* @return Nothing.
|
||||
*/
|
||||
void AbstractTableView::addColumnAt(int width, const QString & title, bool isClickable, SortBy::t sortFn)
|
||||
void AbstractTableView::addColumnAt(int width, const QString & title, bool isClickable)
|
||||
{
|
||||
HeaderButton_t wHeaderButton;
|
||||
Column_t wColumn;
|
||||
|
@ -969,7 +969,6 @@ void AbstractTableView::addColumnAt(int width, const QString & title, bool isCli
|
|||
wColumn.width = width;
|
||||
wColumn.hidden = false;
|
||||
wColumn.title = title;
|
||||
wColumn.sortFunction = sortFn;
|
||||
wCurrentCount = mColumnList.length();
|
||||
mColumnList.append(wColumn);
|
||||
mColumnOrder.append(wCurrentCount);
|
||||
|
@ -1007,12 +1006,12 @@ QString AbstractTableView::getColTitle(int index)
|
|||
/************************************************************************************
|
||||
Getter & Setter
|
||||
************************************************************************************/
|
||||
dsint AbstractTableView::getRowCount() const
|
||||
dsint AbstractTableView::getRowCount()
|
||||
{
|
||||
return mRowCount;
|
||||
}
|
||||
|
||||
int AbstractTableView::getColumnCount() const
|
||||
int AbstractTableView::getColumnCount()
|
||||
{
|
||||
return mColumnList.size();
|
||||
}
|
||||
|
@ -1043,12 +1042,7 @@ bool AbstractTableView::getColumnHidden(int col)
|
|||
else
|
||||
return true;
|
||||
}
|
||||
AbstractTableView::SortBy::t AbstractTableView::getColumnSortBy(int col) const
|
||||
{
|
||||
if(col < getColumnCount() && col >= 0)
|
||||
return mColumnList[col].sortFunction;
|
||||
return SortBy::AsText;
|
||||
}
|
||||
|
||||
void AbstractTableView::setColumnHidden(int col, bool hidden)
|
||||
{
|
||||
if(col < getColumnCount() && col >= 0)
|
||||
|
@ -1172,6 +1166,7 @@ void AbstractTableView::updateViewport()
|
|||
this->viewport()->update();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This method is called when data have to be reloaded (e.g. When table offset changes).
|
||||
*
|
||||
|
@ -1183,18 +1178,3 @@ void AbstractTableView::prepareData()
|
|||
dsint wRemainingRowsCount = getRowCount() - mTableOffset;
|
||||
mNbrOfLineToPrint = (dsint)wRemainingRowsCount > (dsint)wViewableRowsCount ? (int)wViewableRowsCount : (int)wRemainingRowsCount;
|
||||
}
|
||||
|
||||
bool AbstractTableView::SortBy::AsText(const QString & a, const QString & b)
|
||||
{
|
||||
return QString::compare(a, b, Qt::CaseInsensitive) < 0;
|
||||
}
|
||||
|
||||
bool AbstractTableView::SortBy::AsInt(const QString & a, const QString & b)
|
||||
{
|
||||
return a.toLongLong() < b.toLongLong();
|
||||
}
|
||||
|
||||
bool AbstractTableView::SortBy::AsHex(const QString & a, const QString & b)
|
||||
{
|
||||
return a.toLongLong(0, 16) < b.toLongLong(0, 16);
|
||||
}
|
||||
|
|
|
@ -86,24 +86,16 @@ public:
|
|||
int getViewableRowsCount();
|
||||
virtual int getLineToPrintcount();
|
||||
|
||||
struct SortBy
|
||||
{
|
||||
typedef std::function<bool(const QString &, const QString &)> t;
|
||||
static bool AsText(const QString & a, const QString & b);
|
||||
static bool AsInt(const QString & a, const QString & b);
|
||||
static bool AsHex(const QString & a, const QString & b);
|
||||
};
|
||||
|
||||
// New Columns/New Size
|
||||
virtual void addColumnAt(int width, const QString & title, bool isClickable, SortBy::t sortFn = SortBy::AsText);
|
||||
virtual void addColumnAt(int width, const QString & title, bool isClickable);
|
||||
virtual void setRowCount(dsint count);
|
||||
virtual void deleteAllColumns();
|
||||
void setColTitle(int index, const QString & title);
|
||||
QString getColTitle(int index);
|
||||
|
||||
// Getter & Setter
|
||||
dsint getRowCount() const;
|
||||
int getColumnCount() const;
|
||||
dsint getRowCount();
|
||||
int getColumnCount();
|
||||
int getRowHeight();
|
||||
int getColumnWidth(int index);
|
||||
void setColumnWidth(int index, int width);
|
||||
|
@ -116,7 +108,6 @@ public:
|
|||
int getCharWidth();
|
||||
bool getColumnHidden(int col);
|
||||
void setColumnHidden(int col, bool hidden);
|
||||
SortBy::t getColumnSortBy(int idx) const;
|
||||
|
||||
// UI customization
|
||||
void loadColumnFromConfig(const QString & viewName);
|
||||
|
@ -176,7 +167,6 @@ private:
|
|||
bool hidden;
|
||||
HeaderButton_t header;
|
||||
QString title;
|
||||
SortBy::t sortFunction;
|
||||
} Column_t;
|
||||
|
||||
typedef struct _Header_t
|
||||
|
|
|
@ -771,23 +771,18 @@ void Disassembly::keyPressEvent(QKeyEvent* event)
|
|||
if(event->modifiers() & Qt::ShiftModifier) //SHIFT pressed
|
||||
expand = true;
|
||||
|
||||
dsint initialStart = getSelectionStart();
|
||||
|
||||
if(key == Qt::Key_Up)
|
||||
selectPrevious(expand);
|
||||
else
|
||||
selectNext(expand);
|
||||
|
||||
bool expandedUp = initialStart != getSelectionStart();
|
||||
dsint modifiedSelection = expandedUp ? getSelectionStart() : getSelectionEnd();
|
||||
|
||||
if(modifiedSelection < botRVA)
|
||||
if(getSelectionStart() < botRVA)
|
||||
{
|
||||
setTableOffset(modifiedSelection);
|
||||
setTableOffset(getSelectionStart());
|
||||
}
|
||||
else if(modifiedSelection >= topRVA)
|
||||
else if(getSelectionEnd() >= topRVA)
|
||||
{
|
||||
setTableOffset(getInstructionRVA(modifiedSelection, -getNbrOfLineToPrint() + 2));
|
||||
setTableOffset(getInstructionRVA(getSelectionEnd(), -getNbrOfLineToPrint() + 2));
|
||||
}
|
||||
|
||||
updateViewport();
|
||||
|
|
|
@ -1,43 +1,17 @@
|
|||
#include "HistoryLineEdit.h"
|
||||
#include "Bridge.h"
|
||||
|
||||
HistoryLineEdit::HistoryLineEdit(QWidget* parent) : QLineEdit(parent)
|
||||
{
|
||||
mCmdHistory.clear();
|
||||
mCmdIndex = -1;
|
||||
bSixPressed = false;
|
||||
}
|
||||
|
||||
void HistoryLineEdit::loadSettings(QString sectionPrefix)
|
||||
{
|
||||
char buffer[MAX_SETTING_SIZE];
|
||||
for(int i = 1; BridgeSettingGet(sectionPrefix.toUtf8().constData(),
|
||||
QString("Line%1").arg(i).toUtf8().constData(),
|
||||
buffer) && buffer[0] && i < mCmdHistoryMaxSize; i++)
|
||||
{
|
||||
QString entry = QString::fromUtf8(buffer);
|
||||
mCmdHistory.append(entry);
|
||||
}
|
||||
}
|
||||
void HistoryLineEdit::saveSettings(QString sectionPrefix)
|
||||
{
|
||||
int i = 1;
|
||||
for(i = 1; i <= mCmdHistory.size(); i++)
|
||||
{
|
||||
BridgeSettingSet(sectionPrefix.toUtf8().constData(),
|
||||
QString("Line%1").arg(i).toUtf8().constData(),
|
||||
mCmdHistory.at(i - 1).toUtf8().constData());
|
||||
}
|
||||
|
||||
// Sentinel in case we saved less than is in the store currently
|
||||
BridgeSettingSet(sectionPrefix.toUtf8().constData(),
|
||||
QString("Line%1").arg(i).toUtf8().constData(),
|
||||
"");
|
||||
}
|
||||
void HistoryLineEdit::addLineToHistory(QString parLine)
|
||||
{
|
||||
mCmdHistory.prepend(parLine);
|
||||
|
||||
if(mCmdHistory.size() > mCmdHistoryMaxSize)
|
||||
if(mCmdHistory.size() > 32)
|
||||
mCmdHistory.removeLast();
|
||||
|
||||
mCmdIndex = -1;
|
||||
|
|
|
@ -12,13 +12,11 @@ public:
|
|||
void keyPressEvent(QKeyEvent* event);
|
||||
void addLineToHistory(QString parLine);
|
||||
void setFocus();
|
||||
void loadSettings(QString sectionPrefix);
|
||||
void saveSettings(QString sectionPrefix);
|
||||
|
||||
signals:
|
||||
void keyPressed(int parKey);
|
||||
|
||||
private:
|
||||
int mCmdHistoryMaxSize = 1000;
|
||||
QList<QString> mCmdHistory;
|
||||
int mCmdIndex;
|
||||
bool bSixPressed;
|
||||
|
|
|
@ -172,13 +172,11 @@ void StdTable::expandSelectionUpTo(int to)
|
|||
{
|
||||
mSelection.fromIndex = to;
|
||||
mSelection.toIndex = mSelection.firstSelectedIndex;
|
||||
emit selectionChangedSignal(to);
|
||||
}
|
||||
else if(to > mSelection.firstSelectedIndex)
|
||||
{
|
||||
mSelection.fromIndex = mSelection.firstSelectedIndex;
|
||||
mSelection.toIndex = to;
|
||||
emit selectionChangedSignal(to);
|
||||
}
|
||||
else if(to == mSelection.firstSelectedIndex)
|
||||
{
|
||||
|
@ -199,17 +197,6 @@ int StdTable::getInitialSelection()
|
|||
return mSelection.firstSelectedIndex;
|
||||
}
|
||||
|
||||
QList<int> StdTable::getSelection()
|
||||
{
|
||||
QList<int> selection;
|
||||
selection.reserve(mSelection.toIndex - mSelection.fromIndex);
|
||||
for(int i = mSelection.fromIndex; i <= mSelection.toIndex; i++)
|
||||
{
|
||||
selection.append(i);
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
|
||||
void StdTable::selectNext()
|
||||
{
|
||||
int wNext = getInitialSelection() + 1;
|
||||
|
@ -245,9 +232,9 @@ bool StdTable::isSelected(int base, int offset)
|
|||
/************************************************************************************
|
||||
Data Management
|
||||
************************************************************************************/
|
||||
void StdTable::addColumnAt(int width, QString title, bool isClickable, QString copyTitle, SortBy::t sortFn)
|
||||
void StdTable::addColumnAt(int width, QString title, bool isClickable, QString copyTitle)
|
||||
{
|
||||
AbstractTableView::addColumnAt(width, title, isClickable, sortFn);
|
||||
AbstractTableView::addColumnAt(width, title, isClickable);
|
||||
|
||||
//append empty column to list of rows
|
||||
for(int i = 0; i < mData.size(); i++)
|
||||
|
@ -487,6 +474,6 @@ void StdTable::headerButtonPressedSlot(int col)
|
|||
void StdTable::reloadData()
|
||||
{
|
||||
if(mSort.first != -1) //re-sort if the user wants to sort
|
||||
qSort(mData.begin(), mData.end(), ColumnCompare(mSort.first, mSort.second, getColumnSortBy(mSort.first)));
|
||||
qSort(mData.begin(), mData.end(), ColumnCompare(mSort.first, mSort.second));
|
||||
AbstractTableView::reloadData();
|
||||
}
|
||||
|
|
|
@ -24,13 +24,12 @@ public:
|
|||
void expandSelectionUpTo(int to);
|
||||
void setSingleSelection(int index);
|
||||
int getInitialSelection();
|
||||
QList<int> getSelection();
|
||||
void selectNext();
|
||||
void selectPrevious();
|
||||
bool isSelected(int base, int offset);
|
||||
|
||||
// Data Management
|
||||
void addColumnAt(int width, QString title, bool isClickable, QString copyTitle = "", SortBy::t sortFn = SortBy::AsText);
|
||||
void addColumnAt(int width, QString title, bool isClickable, QString copyTitle = "");
|
||||
void setRowCount(int count);
|
||||
void deleteAllColumns();
|
||||
void setCellContent(int r, int c, QString s);
|
||||
|
@ -61,16 +60,15 @@ private:
|
|||
class ColumnCompare
|
||||
{
|
||||
public:
|
||||
ColumnCompare(int col, bool greater, SortBy::t fn)
|
||||
ColumnCompare(int col, bool greater)
|
||||
{
|
||||
mCol = col;
|
||||
mGreater = greater;
|
||||
mSortFn = fn;
|
||||
}
|
||||
|
||||
inline bool operator()(const QList<QString> & a, const QList<QString> & b) const
|
||||
{
|
||||
bool less = mSortFn(a.at(mCol), b.at(mCol));
|
||||
bool less = QString::compare(a.at(mCol), b.at(mCol), Qt::CaseInsensitive) < 0;
|
||||
if(mGreater)
|
||||
return !less;
|
||||
return less;
|
||||
|
@ -78,7 +76,6 @@ private:
|
|||
private:
|
||||
int mCol;
|
||||
int mGreater;
|
||||
SortBy::t mSortFn;
|
||||
};
|
||||
|
||||
enum GuiState_t {NoState, MultiRowsSelectionState};
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
#include "QBeaEngine.h"
|
||||
#include "main.h"
|
||||
#include "Exports.h"
|
||||
#include <qmetaobject.h>
|
||||
|
||||
#define MEASURE_LATENCY_EVENT ((QEvent::Type)(QEvent::User + 42))
|
||||
/************************************************************************************
|
||||
Global Variables
|
||||
************************************************************************************/
|
||||
|
@ -23,49 +21,11 @@ Bridge::Bridge(QObject* parent) : QObject(parent)
|
|||
bridgeResult = 0;
|
||||
hasBridgeResult = false;
|
||||
dbgStopped = false;
|
||||
|
||||
qRegisterMetaType <uint32_t>("uint32_t");
|
||||
connect(this, SIGNAL(measureLatency(uint32_t)),
|
||||
this, SLOT(measureLatencySlot(uint32_t)), Qt::ConnectionType::QueuedConnection);
|
||||
|
||||
latencyThread = std::thread([this]
|
||||
{
|
||||
while(mBridgeMutex)
|
||||
{
|
||||
std::unique_lock<std::mutex> guard(latencyLock);
|
||||
latencyLastRequest = GetTickCount();
|
||||
|
||||
// We can't use a normal signal/slot for this since we can't se the priority on that.
|
||||
// If we don't have the low priority set; this gets scheduled ahead of UI events so
|
||||
// we won't get accurate measurements.
|
||||
QCoreApplication::postEvent(this, new QEvent(MEASURE_LATENCY_EVENT), Qt::LowEventPriority);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
||||
latencyCV.wait(guard, [this] { return latencyLastRequest < latencyLastResponse; });
|
||||
}
|
||||
});
|
||||
}
|
||||
void Bridge::customEvent(QEvent* ev)
|
||||
{
|
||||
if(ev->type() == MEASURE_LATENCY_EVENT)
|
||||
{
|
||||
std::unique_lock<std::mutex> guard(latencyLock);
|
||||
latencyLastResponse = GetTickCount();
|
||||
|
||||
// TickCount can overflow; just reset lastrequest
|
||||
if(latencyLastResponse < latencyLastRequest)
|
||||
latencyLastRequest = 0;
|
||||
|
||||
latencyMs = latencyLastResponse - latencyLastRequest;
|
||||
latencyCV.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
Bridge::~Bridge()
|
||||
{
|
||||
delete mBridgeMutex;
|
||||
mBridgeMutex = 0;
|
||||
latencyCV.notify_all();
|
||||
latencyThread.join();
|
||||
}
|
||||
|
||||
void Bridge::CopyToClipboard(const QString & text)
|
||||
|
@ -625,24 +585,6 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
|||
/************************************************************************************
|
||||
Exported Functions
|
||||
************************************************************************************/
|
||||
__declspec(dllexport) uint32 _gui_messagelatency()
|
||||
{
|
||||
uint32 latencyLastRequest = Bridge::getBridge()->latencyLastRequest;
|
||||
uint32 latencyLastResponse = Bridge::getBridge()->latencyLastResponse;
|
||||
uint32 latencyMs = Bridge::getBridge()->latencyMs;
|
||||
|
||||
// Indicates a pending request
|
||||
if(latencyLastResponse > latencyLastRequest)
|
||||
{
|
||||
// If the current wait time exceeds the last measurement, use that instead.
|
||||
// this makes sure that if the pipeline is super stalled all of a sudden,
|
||||
// the measurement is still somewhat accurate; although it would still be
|
||||
// a floor on the actual latency.
|
||||
uint32 currentWait = GetTickCount() - latencyLastRequest;
|
||||
latencyMs = std::max(latencyMs, currentWait);
|
||||
}
|
||||
return latencyMs;
|
||||
}
|
||||
__declspec(dllexport) int _gui_guiinit(int argc, char* argv[])
|
||||
{
|
||||
return main(argc, argv);
|
||||
|
|
|
@ -8,18 +8,12 @@
|
|||
#include "Imports.h"
|
||||
#include "ReferenceManager.h"
|
||||
#include "BridgeResult.h"
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
class Bridge : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class BridgeResult;
|
||||
std::thread latencyThread;
|
||||
std::mutex latencyLock;
|
||||
std::condition_variable latencyCV;
|
||||
|
||||
public:
|
||||
explicit Bridge(QObject* parent = 0);
|
||||
|
@ -28,10 +22,6 @@ public:
|
|||
static Bridge* getBridge();
|
||||
static void initBridge();
|
||||
|
||||
uint32 latencyMs = 0;
|
||||
uint32 latencyLastRequest = 0;
|
||||
uint32 latencyLastResponse = 0;
|
||||
|
||||
// Message processing function
|
||||
void* processMessage(GUIMSG type, void* param1, void* param2);
|
||||
|
||||
|
@ -51,9 +41,6 @@ public:
|
|||
QWidget* scriptView;
|
||||
ReferenceManager* referenceManager;
|
||||
|
||||
protected:
|
||||
virtual void customEvent(QEvent* event) override;
|
||||
|
||||
signals:
|
||||
void disassembleAt(dsint va, dsint eip);
|
||||
void repaintGui();
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
************************************************************************************/
|
||||
|
||||
#ifdef BUILD_LIB
|
||||
extern "C" __declspec(dllexport) uint32 _gui_messagelatency();
|
||||
extern "C" __declspec(dllexport) int _gui_guiinit(int argc, char* argv[]);
|
||||
extern "C" __declspec(dllexport) void* _gui_sendmessage(GUIMSG type, void* param1, void* param2);
|
||||
extern "C" __declspec(dllexport) void _gui_sendmessageasync(GUIMSG type, void* param1, void* param2);
|
||||
#endif
|
||||
|
||||
|
||||
#endif // EXPORTS_H
|
||||
|
|
|
@ -16,8 +16,6 @@ CommandLineEdit::CommandLineEdit(QWidget* parent)
|
|||
mCompleterModel = (QStringListModel*)mCompleter->model();
|
||||
this->setCompleter(mCompleter);
|
||||
|
||||
loadSettings("CommandLine");
|
||||
|
||||
//Setup signals & slots
|
||||
connect(mCompleter, SIGNAL(activated(const QString &)), this, SLOT(clear()), Qt::QueuedConnection);
|
||||
connect(this, SIGNAL(textEdited(QString)), this, SLOT(autoCompleteUpdate(QString)));
|
||||
|
@ -29,11 +27,6 @@ CommandLineEdit::CommandLineEdit(QWidget* parent)
|
|||
connect(mCmdScriptType, SIGNAL(currentIndexChanged(int)), this, SLOT(scriptTypeChanged(int)));
|
||||
}
|
||||
|
||||
CommandLineEdit::~CommandLineEdit()
|
||||
{
|
||||
saveSettings("CommandLine");
|
||||
}
|
||||
|
||||
void CommandLineEdit::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if(event->type() == QEvent::KeyPress && event->key() == Qt::Key_Tab)
|
||||
|
|
|
@ -14,8 +14,6 @@ class CommandLineEdit : public HistoryLineEdit
|
|||
|
||||
public:
|
||||
explicit CommandLineEdit(QWidget* parent = 0);
|
||||
~CommandLineEdit();
|
||||
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
bool focusNextPrevChild(bool next);
|
||||
|
||||
|
|
|
@ -103,10 +103,7 @@ void LogView::addMsgToLogSlot(QString msg)
|
|||
return;
|
||||
if(this->document()->characterCount() > 10000 * 100) //limit the log to ~100mb
|
||||
this->clear();
|
||||
// This sets the cursor to the end for the next insert
|
||||
this->moveCursor(QTextCursor::End);
|
||||
this->insertPlainText(msg);
|
||||
// This sets the cursor to the end to display the new text
|
||||
this->moveCursor(QTextCursor::End);
|
||||
}
|
||||
|
||||
|
|
|
@ -341,8 +341,9 @@ void MainWindow::setupStatusBar()
|
|||
ui->statusBar->addPermanentWidget(mLastLogLabel, 1);
|
||||
|
||||
// Time wasted counter
|
||||
mTimeWastedCounter = new TimeWastedCounter(this);
|
||||
ui->statusBar->addPermanentWidget(mTimeWastedCounter);
|
||||
QLabel* timeWastedLabel = new QLabel(this);
|
||||
ui->statusBar->addPermanentWidget(timeWastedLabel);
|
||||
mTimeWastedCounter = new TimeWastedCounter(this, timeWastedLabel);
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent* event)
|
||||
|
|
|
@ -25,7 +25,6 @@ SymbolView::SymbolView(QWidget* parent) : QWidget(parent), ui(new Ui::SymbolView
|
|||
mModuleList = new SearchListView();
|
||||
mModuleList->mSearchStartCol = 1;
|
||||
int charwidth = mModuleList->mList->getCharWidth();
|
||||
mModuleList->mList->enableMultiSelection(true);
|
||||
mModuleList->mList->setCipBase(true);
|
||||
mModuleList->mList->addColumnAt(charwidth * 2 * sizeof(dsint) + 8, tr("Base"), false);
|
||||
mModuleList->mList->addColumnAt(300, tr("Module"), true);
|
||||
|
@ -36,14 +35,12 @@ SymbolView::SymbolView(QWidget* parent) : QWidget(parent), ui(new Ui::SymbolView
|
|||
mModuleList->mSearchList->addColumnAt(charwidth * 8, tr("Party"), false);
|
||||
|
||||
// Setup symbol list
|
||||
mSearchListView->mList->enableMultiSelection(true);
|
||||
mSearchListView->mList->addColumnAt(charwidth * 2 * sizeof(dsint) + 8, tr("Address"), true);
|
||||
mSearchListView->mList->addColumnAt(charwidth * 6 + 8, tr("Type"), true);
|
||||
mSearchListView->mList->addColumnAt(charwidth * 80, tr("Symbol"), true);
|
||||
mSearchListView->mList->addColumnAt(2000, tr("Symbol (undecorated)"), true);
|
||||
|
||||
// Setup search list
|
||||
mSearchListView->mSearchList->enableMultiSelection(true);
|
||||
mSearchListView->mSearchList->addColumnAt(charwidth * 2 * sizeof(dsint) + 8, tr("Address"), true);
|
||||
mSearchListView->mSearchList->addColumnAt(charwidth * 6 + 8, tr("Type"), true);
|
||||
mSearchListView->mSearchList->addColumnAt(charwidth * 80, tr("Symbol"), true);
|
||||
|
@ -226,22 +223,15 @@ void SymbolView::cbSymbolEnum(SYMBOLINFO* symbol, void* user)
|
|||
|
||||
void SymbolView::moduleSelectionChanged(int index)
|
||||
{
|
||||
setUpdatesEnabled(false);
|
||||
|
||||
QString mod = mModuleList->mCurList->getCellContent(index, 1);
|
||||
if(!mModuleBaseList.count(mod))
|
||||
return;
|
||||
mSearchListView->mList->setRowCount(0);
|
||||
for(auto index : mModuleList->mCurList->getSelection())
|
||||
{
|
||||
QString mod = mModuleList->mCurList->getCellContent(index, 1);
|
||||
if(!mModuleBaseList.count(mod))
|
||||
continue;
|
||||
DbgSymbolEnumFromCache(mModuleBaseList[mod], cbSymbolEnum, mSearchListView->mList);
|
||||
}
|
||||
DbgSymbolEnumFromCache(mModuleBaseList[mod], cbSymbolEnum, mSearchListView->mList);
|
||||
mSearchListView->mList->reloadData();
|
||||
mSearchListView->mList->setSingleSelection(0);
|
||||
mSearchListView->mList->setTableOffset(0);
|
||||
mSearchListView->mSearchBox->setText("");
|
||||
|
||||
setUpdatesEnabled(true);
|
||||
}
|
||||
|
||||
void SymbolView::updateSymbolList(int module_count, SYMBOLMODULEINFO* modules)
|
||||
|
@ -400,33 +390,27 @@ void SymbolView::toggleBreakpoint()
|
|||
|
||||
if(!mSearchListView->mCurList->getRowCount())
|
||||
return;
|
||||
QString addrText = mSearchListView->mCurList->getCellContent(mSearchListView->mCurList->getInitialSelection(), 0);
|
||||
duint wVA;
|
||||
if(!DbgFunctions()->ValFromString(addrText.toUtf8().constData(), &wVA))
|
||||
return;
|
||||
|
||||
auto selection = mSearchListView->mCurList->getSelection();
|
||||
if(!DbgMemIsValidReadPtr(wVA))
|
||||
return;
|
||||
|
||||
for(auto selectedIdx : selection)
|
||||
BPXTYPE wBpType = DbgGetBpxTypeAt(wVA);
|
||||
QString wCmd;
|
||||
|
||||
if((wBpType & bp_normal) == bp_normal)
|
||||
{
|
||||
QString addrText = mSearchListView->mCurList->getCellContent(selectedIdx, 0);
|
||||
duint wVA;
|
||||
if(!DbgFunctions()->ValFromString(addrText.toUtf8().constData(), &wVA))
|
||||
return;
|
||||
|
||||
if(!DbgMemIsValidReadPtr(wVA))
|
||||
return;
|
||||
|
||||
BPXTYPE wBpType = DbgGetBpxTypeAt(wVA);
|
||||
QString wCmd;
|
||||
|
||||
if((wBpType & bp_normal) == bp_normal)
|
||||
{
|
||||
wCmd = "bc " + QString("%1").arg(wVA, sizeof(dsint) * 2, 16, QChar('0')).toUpper();
|
||||
}
|
||||
else
|
||||
{
|
||||
wCmd = "bp " + QString("%1").arg(wVA, sizeof(dsint) * 2, 16, QChar('0')).toUpper();
|
||||
}
|
||||
|
||||
DbgCmdExec(wCmd.toUtf8().constData());
|
||||
wCmd = "bc " + QString("%1").arg(wVA, sizeof(dsint) * 2, 16, QChar('0')).toUpper();
|
||||
}
|
||||
else
|
||||
{
|
||||
wCmd = "bp " + QString("%1").arg(wVA, sizeof(dsint) * 2, 16, QChar('0')).toUpper();
|
||||
}
|
||||
|
||||
DbgCmdExec(wCmd.toUtf8().constData());
|
||||
}
|
||||
|
||||
void SymbolView::toggleBookmark()
|
||||
|
|
|
@ -189,16 +189,16 @@ void ThreadView::setupContextMenu()
|
|||
ThreadView::ThreadView(StdTable* parent) : StdTable(parent)
|
||||
{
|
||||
int charwidth = getCharWidth();
|
||||
addColumnAt(8 + charwidth * sizeof(unsigned int) * 2, tr("Number"), false, "", SortBy::AsInt);
|
||||
addColumnAt(8 + charwidth * sizeof(unsigned int) * 2, tr("ID"), false, "", SortBy::AsHex);
|
||||
addColumnAt(8 + charwidth * sizeof(duint) * 2, tr("Entry"), false, "", SortBy::AsHex);
|
||||
addColumnAt(8 + charwidth * sizeof(duint) * 2, tr("TEB"), false, "", SortBy::AsHex);
|
||||
addColumnAt(8 + charwidth * sizeof(unsigned int) * 2, tr("Number"), false);
|
||||
addColumnAt(8 + charwidth * sizeof(unsigned int) * 2, tr("ID"), false);
|
||||
addColumnAt(8 + charwidth * sizeof(duint) * 2, tr("Entry"), false);
|
||||
addColumnAt(8 + charwidth * sizeof(duint) * 2, tr("TEB"), false);
|
||||
#ifdef _WIN64
|
||||
addColumnAt(8 + charwidth * sizeof(duint) * 2, tr("RIP"), false, "", SortBy::AsHex);
|
||||
addColumnAt(8 + charwidth * sizeof(duint) * 2, tr("RIP"), false);
|
||||
#else
|
||||
addColumnAt(8 + charwidth * sizeof(duint) * 2, tr("EIP"), false, "", SortBy::AsHex);
|
||||
addColumnAt(8 + charwidth * sizeof(duint) * 2, tr("EIP"), false);
|
||||
#endif //_WIN64
|
||||
addColumnAt(8 + charwidth * 14, tr("Suspend Count"), false, "", SortBy::AsInt);
|
||||
addColumnAt(8 + charwidth * 14, tr("Suspend Count"), false);
|
||||
addColumnAt(8 + charwidth * 12, tr("Priority"), false);
|
||||
addColumnAt(8 + charwidth * 12, tr("Wait Reason"), false);
|
||||
addColumnAt(8 + charwidth * 11, tr("Last Error"), false);
|
||||
|
|
|
@ -1,61 +1,20 @@
|
|||
#include "TimeWastedCounter.h"
|
||||
#include "Bridge.h"
|
||||
|
||||
TimeWastedCounter::TimeWastedCounter(QWidget* parent)
|
||||
: QLabel(parent)
|
||||
TimeWastedCounter::TimeWastedCounter(QObject* parent, QLabel* label)
|
||||
: QObject(parent), mLabel(label)
|
||||
{
|
||||
setFrameStyle(QFrame::Sunken | QFrame::Panel); //sunken style
|
||||
setStyleSheet("QLabel { background-color : #c0c0c0; }");
|
||||
mLastTime = GetTickCount64();
|
||||
BridgeSettingGetUint("TimeWastedCounter", "CounterMode", (duint*)&mCounterMode);
|
||||
mLabel->setFrameStyle(QFrame::Sunken | QFrame::Panel); //sunken style
|
||||
mLabel->setStyleSheet("QLabel { background-color : #c0c0c0; }");
|
||||
connect(Bridge::getBridge(), SIGNAL(updateTimeWastedCounter()), this, SLOT(updateTimeWastedCounter()));
|
||||
}
|
||||
|
||||
void TimeWastedCounter::mousePressEvent(QMouseEvent*)
|
||||
{
|
||||
mCounterMode = (TimeWastedCounterMode::t)((int)mCounterMode + 1);
|
||||
if(mCounterMode >= TimeWastedCounterMode::SIZE)
|
||||
{
|
||||
mCounterMode = (TimeWastedCounterMode::t)0;
|
||||
}
|
||||
BridgeSettingSetUint("TimeWastedCounter", "CounterMode", mCounterMode);
|
||||
}
|
||||
|
||||
void TimeWastedCounter::updateTimeWastedCounter()
|
||||
{
|
||||
uint64 totalDbgEvents = DbgFunctions()->GetDbgEvents();
|
||||
uint64 dbgEvents = totalDbgEvents - mLastEventCount;
|
||||
mLastEventCount = totalDbgEvents;
|
||||
|
||||
uint64 time = GetTickCount64();
|
||||
uint64 timeDelta = time - mLastTime;
|
||||
mLastTime = time;
|
||||
|
||||
duint dbgEvents = DbgFunctions()->GetDbgEvents();
|
||||
if(dbgEvents > 4)
|
||||
{
|
||||
QString msg = "";
|
||||
switch(mCounterMode)
|
||||
{
|
||||
default:
|
||||
case TimeWastedCounterMode::EventsDelta:
|
||||
msg = tr("%1 events in %2ms (%3ms)")
|
||||
.arg(dbgEvents)
|
||||
.arg(timeDelta);
|
||||
break;
|
||||
case TimeWastedCounterMode::EventsTotal:
|
||||
msg = tr("%1(+%2) total events (%3ms)")
|
||||
.arg(totalDbgEvents)
|
||||
.arg(dbgEvents);
|
||||
break;
|
||||
case TimeWastedCounterMode::EventsHertz:
|
||||
if(timeDelta == 0) // Keeps the old message
|
||||
return;
|
||||
msg = tr("%1 events/sec (%3ms)")
|
||||
.arg(dbgEvents * 1000 / timeDelta);
|
||||
break;
|
||||
}
|
||||
msg = msg.arg(Bridge::getBridge()->latencyMs);
|
||||
setText(msg);
|
||||
mLabel->setText(tr("%1 events/s").arg(dbgEvents));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -64,6 +23,6 @@ void TimeWastedCounter::updateTimeWastedCounter()
|
|||
int hours = (timeWasted / (60 * 60)) % 24;
|
||||
int minutes = (timeWasted / 60) % 60;
|
||||
int seconds = timeWasted % 60;
|
||||
setText(tr("Time Wasted Debugging:") + QString().sprintf(" %d:%02d:%02d:%02d", days, hours, minutes, seconds));
|
||||
mLabel->setText(tr("Time Wasted Debugging:") + QString().sprintf(" %d:%02d:%02d:%02d", days, hours, minutes, seconds));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,33 +3,18 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QLabel>
|
||||
#include <stdint.h>
|
||||
|
||||
class TimeWastedCounter : public QLabel
|
||||
class TimeWastedCounter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TimeWastedCounter(QWidget* parent);
|
||||
explicit TimeWastedCounter(QObject* parent, QLabel* label);
|
||||
|
||||
private slots:
|
||||
void updateTimeWastedCounter();
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
private:
|
||||
struct TimeWastedCounterMode
|
||||
{
|
||||
enum t
|
||||
{
|
||||
EventsDelta = 0,
|
||||
EventsTotal,
|
||||
EventsHertz,
|
||||
SIZE
|
||||
};
|
||||
};
|
||||
|
||||
TimeWastedCounterMode::t mCounterMode = TimeWastedCounterMode::EventsDelta;
|
||||
uint64_t mLastEventCount = 0;
|
||||
uint64_t mLastTime = 0;
|
||||
private:
|
||||
QLabel* mLabel;
|
||||
};
|
||||
|
||||
#endif // TIMEWASTEDCOUNTER_H
|
||||
|
|
Loading…
Reference in New Issue