2 QuestHelper_File
["error.lua"] = "Development Version"
4 Much of this code is ganked wholesale from Swatter, and is Copyright (C) 2006 Norganna.
7 QuestHelper_local_version
= QuestHelper_File
["error.lua"]
8 QuestHelper_toc_version
= GetAddOnMetadata("QuestHelper", "Version")
10 local origHandler
= geterrorhandler()
12 local QuestHelper_ErrorCatcher
= { }
14 local startup_errors
= {}
15 local completely_started
= false
16 local yelled_at_user
= false
18 local first_error
= nil
20 QuestHelper_Errors
= {}
21 QuestHelper_Errors
.crashes
= {}
23 function QuestHelper_ErrorCatcher
.TextError(text
)
24 DEFAULT_CHAT_FRAME
:AddMessage(string.format("|cffff8080QuestHelper Error Handler: |r%s", text
))
28 -- ganked verbatim from Swatter
29 function QuestHelper_ErrorCatcher
.GetAddOns()
31 for i
= 1, GetNumAddOns() do
32 local name
, title
, notes
, enabled
, loadable
, reason
, security
= GetAddOnInfo(i
)
34 local loaded
= IsAddOnLoaded(i
)
36 if not name
then name
= "Anonymous" end
37 name
= name
:gsub("[^a-zA-Z0-9]+", "")
38 local version
= GetAddOnMetadata(i
, "Version")
39 local class
= getglobal(name
)
40 if not class
or type(class
)~='table' then class
= getglobal(name
:lower()) end
41 if not class
or type(class
)~='table' then class
= getglobal(name
:sub(1,1):upper()..name
:sub(2):lower()) end
42 if not class
or type(class
)~='table' then class
= getglobal(name
:upper()) end
43 if class
and type(class
)=='table' then
44 if (class
.version
) then
45 version
= class
.version
46 elseif (class
.Version
) then
47 version
= class
.Version
48 elseif (class
.VERSION
) then
49 version
= class
.VERSION
52 local const
= getglobal(name
:upper().."_VERSION")
53 if (const
) then version
= const
end
55 if type(version
)=='table' then
57 nLog
.AddMessage("!swatter", "Swatter.lua", N_INFO
, "version is a table", name
, table.concat(version
,":"))
59 version
= table.concat(version
,":")
63 addlist
= addlist
.." "..name
..", v"..version
.."\n"
65 addlist
= addlist
.." "..name
.."\n"
74 function QuestHelper_ErrorCatcher
.CondenseErrors()
75 while next(startup_errors
) do
76 _
, err
= next(startup_errors
)
77 table.remove(startup_errors
)
81 for _
, item
in ipairs(QuestHelper_Errors
.crashes
) do
82 if item
.message
== err
.message
and item
.stack
== err
.stack
and item
.local_version
== err
.local_version
and item
.toc_version
== err
.toc_version
and item
.addons
== err
.addons
and item
.game_version
== err
.game_version
and item
.locale
== err
.locale
then
84 item
.count
= item
.count
+ 1
89 table.insert(QuestHelper_Errors
.crashes
, err
)
94 function QuestHelper_ErrorPackage(depth
)
96 timestamp
= date("%Y-%m-%d %H:%M:%S"),
98 local_version
= QuestHelper_local_version
,
99 toc_version
= QuestHelper_toc_version
,
100 game_version
= GetBuildInfo(),
101 locale
= GetLocale(),
102 stack
= debugstack(depth
or 4, 20, 20),
106 function QuestHelper_ErrorCatcher_ExplicitError(o_msg
, o_frame
, o_stack
, ...)
109 -- We toss it into StartupErrors, and then if we're running properly, we'll merge it into the main DB.
110 local terror
= QuestHelper_ErrorPackage()
114 terror
.addons
= QuestHelper_ErrorCatcher
.GetAddOns()
115 terror
.stack
= o_stack
or terror
.stack
117 table.insert(startup_errors
, terror
)
119 if not first_error
then first_error
= terror
end
121 if completely_started
then QuestHelper_ErrorCatcher
.CondenseErrors() end
123 if not yelled_at_user
then
124 message("QuestHelper has broken. You may have to restart WoW. Type \"/qh error\" for a detailed error message.")
125 yelled_at_user
= true
129 function QuestHelper_ErrorCatcher
.OnError(o_msg
, o_frame
, o_stack
, o_etype
, ...)
130 if (string.find(o_msg
, "QuestHelper") or string.find(debugstack(2, 20, 20), "QuestHelper")) and not string.find(o_msg
, "Cartographer_POI") then
131 QuestHelper_ErrorCatcher_ExplicitError(o_msg
, o_frame
, o_stack
)
134 return origHandler(o_msg
, o_frame
, o_stack
, o_etype
, unpack(arg
or {})) -- pass it on
137 seterrorhandler(QuestHelper_ErrorCatcher
.OnError
) -- at this point we can catch errors
139 function QuestHelper_ErrorCatcher
.CompletelyStarted()
140 completely_started
= true
141 QuestHelper_ErrorCatcher
.CondenseErrors()
144 function QuestHelper_ErrorCatcher_CompletelyStarted()
145 QuestHelper_ErrorCatcher
.CompletelyStarted()
150 -- and here is the GUI
154 function QHE_Gui
.ErrorUpdate()
155 QHE_Gui
.ErrorTextinate()
156 QHE_Gui
.Error
.Box
:SetText(QHE_Gui
.Error
.curError
)
157 QHE_Gui
.Error
.Scroll
:UpdateScrollChildRect()
158 QHE_Gui
.Error
.Box
:ClearFocus()
161 function QHE_Gui
.ErrorTextinate()
163 QHE_Gui
.Error
.curError
= string.format("msg: %s\ntoc: %s\nv: %s\ngame: %s\nlocale: %s\ntimestamp: %s\n\n%s\naddons:\n%s", first_error
.message
, first_error
.toc_version
, first_error
.local_version
, first_error
.game_version
, first_error
.locale
, first_error
.timestamp
, first_error
.stack
, first_error
.addons
)
165 QHE_Gui
.Error
.curError
= "None"
169 function QHE_Gui
.ErrorClicked()
170 if (QHE_Gui
.Error
.selected
) then return end
171 QHE_Gui
.Error
.Box
:HighlightText()
172 QHE_Gui
.Error
.selected
= true
175 function QHE_Gui
.ErrorDone()
180 -- Create our error message frame. Most of this is also ganked from Swatter.
181 QHE_Gui
.Error
= CreateFrame("Frame", "QHE_GUIErrorFrame", UIParent
)
183 QHE_Gui
.Error
:SetPoint("CENTER", "UIParent", "CENTER")
184 QHE_Gui
.Error
:SetFrameStrata("TOOLTIP")
185 QHE_Gui
.Error
:SetHeight(300)
186 QHE_Gui
.Error
:SetWidth(600)
187 QHE_Gui
.Error
:SetBackdrop({
188 bgFile
= "Interface/Tooltips/ChatBubble-Background",
189 edgeFile
= "Interface/Tooltips/ChatBubble-BackDrop",
190 tile
= true, tileSize
= 32, edgeSize
= 32,
191 insets
= { left
= 32, right
= 32, top
= 32, bottom
= 32 }
193 QHE_Gui
.Error
:SetBackdropColor(0.2,0,0, 1)
194 QHE_Gui
.Error
:SetScript("OnShow", QHE_Gui
.ErrorShow
)
195 QHE_Gui
.Error
:SetMovable(true)
197 QHE_Gui
.ProxyFrame
= CreateFrame("Frame", "QHE_GuiProxyFrame")
198 QHE_Gui
.ProxyFrame
:SetParent(QHE_Gui
.Error
)
199 QHE_Gui
.ProxyFrame
.IsShown
= function() return QHE_Gui
.Error
:IsShown() end
200 QHE_Gui
.ProxyFrame
.escCount
= 0
201 QHE_Gui
.ProxyFrame
.timer
= 0
202 QHE_Gui
.ProxyFrame
.Hide
= (
204 local numEscapes
= QHE_Gui
.numEscapes
or 1
205 self
.escCount
= self
.escCount
+ 1
206 if ( self
.escCount
>= numEscapes
) then
207 self
:GetParent():Hide()
210 if ( self
.escCount
== 1 ) then
215 QHE_Gui
.ProxyFrame
:SetScript("OnUpdate",
216 function( self
, elapsed
)
217 local timer
= self
.timer
+ elapsed
218 if ( timer
>= 1 ) then
224 table.insert(UISpecialFrames
, "QHE_GuiProxyFrame")
226 QHE_Gui
.Drag
= CreateFrame("Button", nil, QHE_Gui
.Error
)
227 QHE_Gui
.Drag
:SetPoint("TOPLEFT", QHE_Gui
.Error
, "TOPLEFT", 10,-5)
228 QHE_Gui
.Drag
:SetPoint("TOPRIGHT", QHE_Gui
.Error
, "TOPRIGHT", -10,-5)
229 QHE_Gui
.Drag
:SetHeight(8)
230 QHE_Gui
.Drag
:SetHighlightTexture("Interface\\FriendsFrame\\UI-FriendsFrame-HighlightBar")
232 QHE_Gui
.Drag
:SetScript("OnMouseDown", function() QHE_Gui
.Error
:StartMoving() end)
233 QHE_Gui
.Drag
:SetScript("OnMouseUp", function() QHE_Gui
.Error
:StopMovingOrSizing() end)
235 QHE_Gui
.Error
.Done
= CreateFrame("Button", "", QHE_Gui
.Error
, "OptionsButtonTemplate")
236 QHE_Gui
.Error
.Done
:SetText("Close")
237 QHE_Gui
.Error
.Done
:SetPoint("BOTTOMRIGHT", QHE_Gui
.Error
, "BOTTOMRIGHT", -10, 10)
238 QHE_Gui
.Error
.Done
:SetScript("OnClick", QHE_Gui
.ErrorDone
)
240 QHE_Gui
.Error
.Mesg
= QHE_Gui
.Error
:CreateFontString("", "OVERLAY", "GameFontNormalSmall")
241 QHE_Gui
.Error
.Mesg
:SetJustifyH("LEFT")
242 QHE_Gui
.Error
.Mesg
:SetPoint("TOPRIGHT", QHE_Gui
.Error
.Prev
, "TOPLEFT", -10, 0)
243 QHE_Gui
.Error
.Mesg
:SetPoint("LEFT", QHE_Gui
.Error
, "LEFT", 15, 0)
244 QHE_Gui
.Error
.Mesg
:SetHeight(20)
245 QHE_Gui
.Error
.Mesg
:SetText("Select All and Copy the above error message to report this bug.")
247 QHE_Gui
.Error
.Scroll
= CreateFrame("ScrollFrame", "QHE_GUIErrorInputScroll", QHE_Gui
.Error
, "UIPanelScrollFrameTemplate")
248 QHE_Gui
.Error
.Scroll
:SetPoint("TOPLEFT", QHE_Gui
.Error
, "TOPLEFT", 20, -20)
249 QHE_Gui
.Error
.Scroll
:SetPoint("RIGHT", QHE_Gui
.Error
, "RIGHT", -30, 0)
250 QHE_Gui
.Error
.Scroll
:SetPoint("BOTTOM", QHE_Gui
.Error
.Done
, "TOP", 0, 10)
252 QHE_Gui
.Error
.Box
= CreateFrame("EditBox", "QHE_GUIErrorEditBox", QHE_Gui
.Error
.Scroll
)
253 QHE_Gui
.Error
.Box
:SetWidth(500)
254 QHE_Gui
.Error
.Box
:SetHeight(85)
255 QHE_Gui
.Error
.Box
:SetMultiLine(true)
256 QHE_Gui
.Error
.Box
:SetAutoFocus(false)
257 QHE_Gui
.Error
.Box
:SetFontObject(GameFontHighlight
)
258 QHE_Gui
.Error
.Box
:SetScript("OnEscapePressed", QHE_Gui
.ErrorDone
)
259 QHE_Gui
.Error
.Box
:SetScript("OnTextChanged", QHE_Gui
.ErrorUpdate
)
260 QHE_Gui
.Error
.Box
:SetScript("OnEditFocusGained", QHE_Gui
.ErrorClicked
)
262 QHE_Gui
.Error
.Scroll
:SetScrollChild(QHE_Gui
.Error
.Box
)
264 function QuestHelper_ErrorCatcher_ReportError()
265 QHE_Gui
.Error
.selected
= false
266 QHE_Gui
.ErrorUpdate()