view Core.lua @ 1:6f17035de058

MO will now request a server refresh when mail opening has finished, ignoring the timer. (Collected Module) Fixed the time spent to only be displayed if it is being tracked. The inventory full sound will properly be played again when your bags change.
author Zerotorescue
date Sun, 05 Sep 2010 17:02:19 +0200
parents 823e33465b6e
children 57ba1593ac42
line wrap: on
line source
MailOpener = LibStub("AceAddon-3.0"):NewAddon("MailOpener", "AceEvent-3.0", "AceTimer-3.0");

local enabled = true;
local MailOpenerConfig, lastAmount, lastQuickAuctionsStatus, opening, freshList, mailboxEmptySoundPlayed;

function MailOpener:OnInitialize()
	local defaults = {
		global = {
			uses = 0;
		},
		profile = {
			general = {
				defaultStatus = "_enabled",
				defaultQAStatus = "__remember",
				continueOpeningStackableItems = false,
				autoDisableQAAutoMail = true,
				autoReenableQAAutoMail = false,
				autoSetBackQAAutoMail = true,
				continueOpening = false,
				waitTime = 5,
				initialDelay = 0.5,
			},
			modules = {
				Collected = true,
			},
			notifications = {
				welcome = true,
				bye = true,
				finishedCurrentBatch = true,
				mailboxIsEmpty = true,
				
				skipped = {
					all = true,
					inventoryFull = true,
					keepFreeSpaceLimit = true,
					GMMail = true,
					COD = true,
					normalGoldMail = true,
					normalItemsMail = true,
					AHexpired = true,
					AHsuccess = true,
					AHwon = true,
					AHcanceled = true,
					AHoutbid = true,
					other = true,
				},
				processed = {
					all = true,
					normalGoldMail = true,
					normalItemsMail = true,
					AHexpired = true,
					AHsuccess = true,
					AHwon = true,
					AHcanceled = true,
					AHoutbid = true,
					other = true,
				},
				
				bagsFullSound = false,
				bagsFullSoundFile = "Sound\\Spells\\SimonGame_Visual_BadPress.wav",
				bagsFullSoundFileName = "Simon Error",
				bagsFullSoundOnlyOnce = true,
				mailboxEmptySound = false,
				mailboxEmptySoundFile = "Sound\\Spells\\SimonGame_Visual_GameStart.wav",
				mailboxEmptySoundFileName = "Simon Start",
				mailboxEmptySoundOnlyOnce = true,
			},
		},
	};
	
	-- Register our saved variables database
	self.db = LibStub("AceDB-3.0"):New("MailOpenerDB", defaults, true);
	
	-- Set these as object variables so we can use them in our modules
	if select(6, GetAddOnInfo("Postal")) == nil then
		self.PostalEnabled = true;
		
		-- Ensure this addon is loaded if AddonLoader is installed
		if AddonLoader and AddonLoader.LoadAddOn and not Postal then
			AddonLoader:LoadAddOn("Postal");
		end
	end
	
	if select(6, GetAddOnInfo("QuickAuctions")) == nil then
		self.QuickAuctionsEnabled = true;
		
		-- Ensure this addon is loaded if AddonLoader is installed
		if AddonLoader and AddonLoader.LoadAddOn then
			AddonLoader:LoadAddOn("QuickAuctions");
		end
	end
	
	-- Don't enable the config module until we need it
	for name, module in self:IterateModules() do
		if name == "Config" then
			module:SetEnabledState(false);
		elseif self.db.profile.modules[name] ~= nil then
			if self.db.profile.modules[name] then
				self:Debug("|cff00ff00Enabling|r module: " .. name);
			else
				self:Debug("|cffff0000Disabling|r module: " .. name);
			end
			
			module:SetEnabledState(self.db.profile.modules[name]);
		end
	end
	
	-- Make the open all checkbox
	local check = CreateFrame("CheckButton", "cbMailOpenerEnable", MailFrame, "ChatConfigCheckButtonTemplate");
	check:SetHeight(26);
	check:SetWidth(26);
	check:SetChecked(enabled);
	check:SetHitRectInsets(0, -80, 0, 0);
	check:SetScript("OnClick", function(self)
		if self:GetChecked() then
			MailOpener:Enable();
		else
			MailOpener:Disable();
		end
	end);
	check.tooltip = "Toggle Mail Opener on or off.";
	check:SetPoint("TOPLEFT", MailFrame, "TOPLEFT", 68, -13)
	
	if self.QuickAuctionsEnabled then
		-- QA is enabled so move the checkbox further to the right
		
		check:SetPoint("TOPLEFT", MailFrame, "TOPLEFT", 155, -13);
	end
	
	-- Get reference to the text field
	local checkboxText = _G[check:GetName() .. "Text"];
	checkboxText:SetText("Mail Opener");
	-- We like this color more
	checkboxText:SetTextColor(1, 0.8, 0, 1);
	
	self.cbOpenAll = check;
	
	-- Make the config button
	local button = CreateFrame("Button", "btnMailOpenerConfig", MailFrame, "UIPanelButtonTemplate")
	button:SetText("Config")
	button:SetHeight(23)
	button:SetWidth(55)
	if self.PostalEnabled then
		button:SetPoint("TOPRIGHT", MailFrame, "TOPRIGHT", -75, -13);
	else
		button:SetPoint("TOPRIGHT", MailFrame, "TOPRIGHT", -55, -13);
	end
	button:SetScript("OnClick", function()
		MailOpener:EnableConfigModule();
		
		MailOpenerConfig:Show();
	
		if MailOpener.db.global.uses >= 15 then
			MailOpener:ShowBetaPopup();
		end
	end);
	
	self.btnConfig = button;

	-- Disable the AddonLoader slash commands
	SLASH_MO1 = nil;
	SLASH_MAILOPEN1 = nil;
	SLASH_MAILOPENER1 = nil;
	
	-- Register our own slash commands
	SLASH_MAILOPENER1 = "/mo";
	SLASH_MAILOPENER2 = "/mailopen";
	SLASH_MAILOPENER3 = "/mailopener";
	SlashCmdList["MAILOPENER"] = function(msg)
		MailOpener:EnableConfigModule();
		
		MailOpenerConfig:CommandHandler(msg);
	end
		
	 -- Attempt to remove the interface options added by AddonLoader (if enabled)
	if AddonLoader and AddonLoader.RemoveInterfaceOptions then
		AddonLoader:RemoveInterfaceOptions("Mail Opener");
	end
	
	-- Now create our own options frame
	local frame = CreateFrame("Frame", nil, UIParent);
	frame:Hide();
	frame.name = "Mail Opener";
	frame:HookScript("OnShow", function(self)
		-- Enable the config module
		MailOpener:EnableConfigModule();
		
		-- Load the options and add it to the blizzard interface list
		MailOpenerConfig:Load();
		
		-- Refresh the frame to instantly show the right options
		InterfaceOptionsFrame_OpenToCategory(self.name)
	end);
	-- And add it to the interface options
	InterfaceOptions_AddCategory(frame);
end

function MailOpener:OnEnable()
	self:RegisterEvent("MAIL_SHOW");
	self:RegisterEvent("PLAYER_ENTERING_WORLD");
	
	self.btnConfig:Show();
	
	-- Reset variables
	lastAmount = 0;
	self.debugChannel = nil;
	
	self.db.global.uses = ( self.db.global.uses + 1 );
	
	if self.db.global.uses == 15 then
		self:ShowBetaPopup();
	end
	
	-- If we were toggling this addon on while the mailbox is opened we must register all events again
	if MailFrame:IsVisible() then
		self:MAIL_SHOW();
	end
end

function MailOpener:OnDisable()
	self:UnregisterEvent("MAIL_SHOW");
	
	self.btnConfig:Hide();
	
	enabled = false;
	MailOpener:Stop();
end

-- We must disable Quick Auction's auto mail (if set up that way in the settings) before opening the mailbox or it will instantly start sending stuff
function MailOpener:PLAYER_ENTERING_WORLD()
	self:UnregisterEvent("PLAYER_ENTERING_WORLD");
	
	self:ToggleQAStatus();
end

-- Fired when the mailbox is opened
function MailOpener:MAIL_SHOW()
	-- To stop the timer when the mailbox is closed
	self:RegisterEvent("MAIL_CLOSED", "Stop");
	self:RegisterEvent("PLAYER_LEAVING_WORLD", "Stop");
	
	-- To set the timer for when to refresh again
	self:RegisterEvent("MAIL_INBOX_UPDATE");
	
	-- We need to know when opening has completed
	self:RegisterMessage("MO_OPEN_COMPLETE");
	
	self:Debug("defaultStatus:" .. self.db.profile.general.defaultStatus);
	-- Change the mail opening status according to our settings
	if self.db.profile.general.defaultStatus == "_enabled" then
		enabled = true;
	else
		enabled = false;
	end
	self.cbOpenAll:SetChecked(enabled);
	
	self:ToggleQAStatus();
	
	-- Hide the InboxTooMuchMail warning to allow room for our mail remaining info line
	InboxTooMuchMail:Hide()
	InboxTooMuchMail.Show = function() end
	
	if self.QuickAuctionsEnabled then
		-- Go through all children of the mail frame to find the post button
		local kids = { InboxFrame:GetChildren() };
		
		for _, child in ipairs(kids) do
			if child then
				local width = floor( child:GetWidth() + .5 );
				local height = floor( child:GetHeight() + .5 );
				
				-- The open all button has a static width and height
				if width == 130 and height == 24 then
					child:Hide();
					break;
				end
			end
		end
	end
	
	if self.db.profile.notifications.welcome then
		-- Welcome notification
		local _, c = UnitClass("player");
		c = RAID_CLASS_COLORS[c];
		c = string.format("|cff%02x%02x%02x", c.r * 255 + 0.5, c.g * 255 + 0.5, c.b * 255 + 0.5);
	
		print("|cff15ff00Mail Opener|r: Welcome back "..c..UnitName("player").."|r. Requesting new mail from the local Postal Service, your mail will automatically be opened when it becomes available.");
	end
	
	mailboxEmptySoundPlayed = nil;
	
	self:Recheck();
	
	if self.db.profile.general.continueOpening then
		self:ScheduleOpen(true);
	end
end

-- Fired after a successful server sync
-- Fired when mail is deleted (which happens after taking all attachments from a mail sent by the game)
function MailOpener:MAIL_INBOX_UPDATE()
	local current, total = GetInboxNumItems();
	
	local tempLastAmount = lastAmount;
	lastAmount = current;
	
	if current ~= tempLastAmount then
		self:Debug("MAIL_INBOX_UPDATE - lastAmount:" .. tempLastAmount .. " - current:" .. current);
	end
	
	if current > tempLastAmount then
		-- New messages arrived in our mailbox, so this was a refresh, so set a timer
		
		-- Yell that we successfully synced with the server
		self:SendMessage("MO_SERVER_SYNCED");
		
		-- This list is fresh
		freshList = true;
		mailboxEmptySoundPlayed = nil;
		
		-- Stop previous timer
		self:CancelTimer(self.tmrRecheck, true);
		-- More will arrive in 60 seconds
		self.tmrRecheck = self:ScheduleTimer(function()
			self:Debug("tmrRecheck 61 finished");
			
			-- We can get a fresh list now, so query the server
			freshList = false;
			
			-- Look for mail
			self:Recheck();
		end, 61);
		self:Debug("tmrRecheck 61");
		
		if not IsShiftKeyDown() then
			-- Allow overriding of mailopening with the shift key
			
			-- Open the current mail
			self:ScheduleOpen(false);
		end
	elseif (current == 50 and tempLastAmount == 50) then
		if not IsShiftKeyDown() then
			-- Allow overriding of mailopening with the shift key
			
			-- Open the current mail
			self:ScheduleOpen(false);
		end
	end
	
	tempLastAmount = current;
end

function MailOpener:ScheduleOpen(continued)
	if lastAmount > 0 then
		local waitTime;
		if continued then
			waitTime = self.db.profile.general.waitTime;
		else
			-- Even though this is not a continuation and should be instant, we set a .5 second timer to prevent multiple calls of the OpenNow function
			waitTime = self.db.profile.general.initialDelay;
		end
		
		-- Stop previous timer
		self:CancelTimer(self.tmrOpenNow, true);
		-- Schedule the next open
		self.tmrOpenNow = self:ScheduleTimer("OpenNow", waitTime);
	end
end

function MailOpener:OpenNow()
	self:Debug("OpenNow (" .. ((opening and "1") or "0") .. ")");
	if not opening and MailFrame:IsVisible() then
		self:Debug("OpenNow");
			
		-- BeanCounter is the only addon hiding the mail close button while busy, so we can look for that
		local BeanCounterActive = not InboxCloseButton:IsVisible();
		
		if not BeanCounterActive then
			-- BeanCounter is INACTIVE
			
			self:CancelTimer(self.tmrTryAgain, true); -- Insurance
			
			if QuickAuctionsAutoMail then
				-- Remember the last known quick auctions status
				lastQuickAuctionsStatus = QuickAuctionsAutoMail:GetChecked();
			end
			if self.db.profile.general.autoDisableQAAutoMail and self.QuickAuctionsEnabled and QuickAuctionsAutoMail and QuickAuctionsAutoMail:GetChecked() then
				-- If auto disable "QA Auto mail" is enabled and QA's auto mail is currently toggled on, turn it off
				-- We need to do this with a :click to trigger the right events
				
				self:Debug("Turning automail |cffff0000off|r.");
				
				QuickAuctionsAutoMail:Click();
			end
			
			opening = true;
			
			self:Debug("MO_OPEN_MAIL");
			
			-- Summon the mail opening gods
			self:SendMessage("MO_OPEN_MAIL");
		else
			-- BeanCounter is ACTIVE
			self:Debug("BeanCounter active, waiting .5 seconds...");
			
			self:CancelTimer(self.tmrTryAgain, true); -- Insurance
			-- Wait with summoning until BeanCounter is done, try again every 0.5 seconds
			self.tmrTryAgain = self:ScheduleTimer("OpenNow", 0.5);
		end
	end
end

function MailOpener:MO_OPEN_COMPLETE()
	opening = false;
	
	-- Try a recheck
	self:Recheck();
	
	local current, total = GetInboxNumItems();
	
	if (total - current) == 0 then
		-- Play the sound
		if self.db.profile.notifications.mailboxEmptySound and (not MailOpener.db.profile.notifications.mailboxEmptySoundOnlyOnce or not mailboxEmptySoundPlayed) then
			PlaySoundFile(self.db.profile.notifications.mailboxEmptySoundFile);
			mailboxEmptySoundPlayed = true;
		end
	end
	
	if self.db.profile.general.autoReenableQAAutoMail and self.QuickAuctionsEnabled and QuickAuctionsAutoMail and not QuickAuctionsAutoMail:GetChecked() then
		-- If auto re-enable "QA Auto mail" is enabled and QA's auto mail is currently toggled OFF, turn it on
		-- We need to do this with a :click to trigger the right events
		
		self:Debug("Turning automail |cff00ff00on|r.");
		
		QuickAuctionsAutoMail:Click();
	elseif self.db.profile.general.autoSetBackQAAutoMail and self.QuickAuctionsEnabled and QuickAuctionsAutoMail and lastQuickAuctionsStatus ~= QuickAuctionsAutoMail:GetChecked() then
		-- If auto set back "QA Auto mail" is enabled and QA's auto mail is currently not the same as it was before starting, toggle it
		-- We need to do this with a :click to trigger the right events
		
		if lastQuickAuctionsStatus then
			self:Debug("Turning automail |cff00ff00on|r.");
		else
			self:Debug("Turning automail |cffff0000off|r.");
		end
			
		QuickAuctionsAutoMail:Click();
	end
	
	if self.db.profile.general.continueOpening then
		self:ScheduleOpen(true);
	end
end

-- Run another CheckInbox
function MailOpener:Recheck()
	self:Debug("|cffffff00Recheck|r");
	
	-- Freshlist prevents this from being run too often
	-- It is set to true after a server sync
	-- and set to false 61 seconds afterwards with a recheck called instantly after it
	if not freshList and MailFrame:IsVisible() then
		self:Debug("|cff00ff00Recheck|r");
		
		-- If this isn't a fresh list (so messages weren't received within the last 60 seconds) and the mailbox wasn't closed
	
		-- BeanCounter is the only addon hiding the mail close button while busy, so we can look for that
		local BeanCounterActive = not InboxCloseButton:IsVisible();
		
		if not BeanCounterActive then
			-- Query the server
			CheckInbox();
		end
		
		-- Stop previous timer
		self:CancelTimer(self.tmrRecheck, true);
		-- Keep trying until it works
		self.tmrRecheck = self:ScheduleTimer("Recheck", 2);
		
		self:Debug("tmrRecheck 2");
	end
end

-- Stop checking for new mail and unregister the events we needed
function MailOpener:Stop()
	if self.db.profile.notifications.bye then
		print("|cff15ff00Mail Opener|r: Have a nice day. :)");
	end
	
	opening = false;
	
	-- We won't need this anymore
	self:UnregisterEvent("MAIL_CLOSED");
	self:UnregisterEvent("PLAYER_LEAVING_WORLD");
	self:UnregisterEvent("MAIL_INBOX_UPDATE");
	
	-- Messages
	self:UnregisterMessage("MO_OPEN_COMPLETE");
	
	-- Timers
	self:CancelTimer(self.tmrTryAgain, true);
	self:CancelTimer(self.tmrOpenNow, true);
	
	-- If we wait with disabling QA automail until MAIL_SHOW, QA will beat us to it and already start sending stuff
	self:ToggleQAStatus();
end

function MailOpener:Debug(t)
	if not self.debugChannel and self.debugChannel ~= false then
		-- We want to check just once, so if you add a debug channel later just do a /reload (registering an event for this is wasted resources)
		self.debugChannel = false;
		
		for i = 1, NUM_CHAT_WINDOWS do
			local name = GetChatWindowInfo(i);
			
			if name:upper() == "DEBUG" then
				self.debugChannel = _G["ChatFrame" .. i];
			end
		end
	end
	
	if self.debugChannel then
		self.debugChannel:AddMessage(t);
	end
end

-- Enable our config module if it's disabled and make a reference to it
function MailOpener:EnableConfigModule()
	if not MailOpenerConfig then
		MailOpenerConfig = self:GetModule("Config");
		MailOpenerConfig:Enable();
	end
end

-- Toggle Postal's opening modules on or off
function MailOpener:TogglePostalModule(name, status)
	if MailOpener.PostalEnabled and Postal then
		-- Postal must be enabled
		
		-- Remember the setting in Postal
		Postal.db.profile.ModuleEnabledState[name] = status;
		
		-- Toggle module
		if status then
			Postal:GetModule(name):Enable();
		else
			Postal:GetModule(name):Disable();
		end
	end
end

-- Change Quick Auction's auto mail status based on our prefered settings
function MailOpener:ToggleQAStatus()
	self:Debug("defaultQAStatus:" .. self.db.profile.general.defaultQAStatus);
	
	if self.QuickAuctionsEnabled and self.db.profile.general.defaultQAStatus ~= "__remember" and QuickAuctionsAutoMail then
		if self.db.profile.general.defaultQAStatus == "_enabled" and not QuickAuctionsAutoMail:GetChecked() then
			self:Debug("Turning automail |cff00ff00on|r.");
			
			QuickAuctionsAutoMail:Click();
		elseif self.db.profile.general.defaultQAStatus == "disabled" and QuickAuctionsAutoMail:GetChecked() then
			self:Debug("Turning automail |cffff0000off|r.");
			
			QuickAuctionsAutoMail:Click();
		end
	end
end

function MailOpener:FormatMoney(copper)
	local gold = floor( copper / 10000 );
	local silver = floor( ( copper - ( gold * 10000 ) ) / 100 );
	local copper = mod(copper, 100);
	
	if gold > 0 then
		return format(GOLD_AMOUNT_TEXTURE .. " " .. SILVER_AMOUNT_TEXTURE .. " " .. COPPER_AMOUNT_TEXTURE, gold, 0, 0, silver, 0, 0, copper, 0, 0);
	elseif silver > 0 then
		return format(SILVER_AMOUNT_TEXTURE .. " " .. COPPER_AMOUNT_TEXTURE, silver, 0, 0, copper, 0, 0);
	else
		return format(COPPER_AMOUNT_TEXTURE, copper, 0, 0);
	end
end

StaticPopupDialogs["MailOpenerCopyWindow"] = {
	text = "Please CTRL-C to copy.",
	button2 = CLOSE,
	hasEditBox = 1,
	hasWideEditBox = 1,
	OnShow = function()
		local editBox = _G[this:GetName().."WideEditBox"];
		if editBox and MailOpener.currentPopupContents then
			editBox:SetText(MailOpener.currentPopupContents);
			editBox:SetFocus();
			editBox:HighlightText(0);
		end
		
		-- Position the close button in the middle
		local button = _G[this:GetName().."Button2"];
		if button then
			-- Remove previous know position
			button:ClearAllPoints();
			button:SetWidth(200);
			-- Reposition in the center
			button:SetPoint("CENTER", editBox, "CENTER", 0, -30);
		end
	end,
	EditBoxOnEscapePressed = function()
		this:GetParent():Hide();
	end,
	timeout = 0,
	whileDead = 1,
	hideOnEscape = 1,
	maxLetters = 1024,
};

-- The below either has to be removed or changed when releasing

function MailOpener:ShowBetaPopup()
	function TableDump(key, val, jumps)
		local cache = "";
		
		if not jumps then
			jumps = 0;
		end
		
		local spacer = "";
		if jumps > 0 then
			for i = 1, jumps do
				spacer = spacer .. "    ";
			end
		end
		
		if type(val) == "table" then
			cache = cache .. spacer .. key .. " = {\n";
			foreach(val, function(k, v)
				cache = cache .. TableDump(k, v, (jumps + 1));
			end);
			cache = cache .. spacer .. "},\n";
		else
			cache = cache .. spacer .. key .. " = " .. tostring(val) .. ",\n";
		end
		
		return cache;
	end
	
	local cache = "";
	foreach(MailOpener.db.profile, function(k, v)
		cache = cache .. TableDump(k, v, 0);
	end);
	
	local AceGUI = LibStub("AceGUI-3.0");
	local frame = AceGUI:Create("Frame");
	frame:SetTitle("Mail Opener ALPHA");
	frame:SetWidth(575);
	frame:SetHeight(375);
	
	-- Add a normal description label
	local desc = AceGUI:Create("Label");
	desc:SetText("|cff00ff00After you have been using Mail Opener for a while and configured it just as you want it to be, please report your favorite settings by copying the text below at either of the below links. Thanks in advance!|r\n\n");
	desc:SetFont(GameFontHighlightSmall:GetFont(), 13);
	desc:SetFullWidth(true);
	frame:AddChild(desc);
	
	-- Add a MultiLineEditBox
	local settingsMLEEB = AceGUI:Create("MultiLineEditBox");
	settingsMLEEB:SetText(cache);
	settingsMLEEB:SetLabel("Hit CTRL-A to select all and CTRL-C to copy the text. You can then use CTRL-V to paste.");
	settingsMLEEB:SetFullWidth(true);
	settingsMLEEB:SetNumLines(8);
	settingsMLEEB:DisableButton(true);
	settingsMLEEB:SetCallback("OnTextChanged", function()
		settingsMLEEB:SetText(cache);
	end);
	frame:AddChild(settingsMLEEB);
	
	-- Empty line between the two links
	local label = AceGUI:Create("Label");
	label:SetText("Please post the above text at either of these two links:");
	label:SetFullWidth(true);
	frame:AddChild(label);
	
	local desc1 = AceGUI:Create("InteractiveLabel");
	desc1:SetText("|cff00bbbb[http://wow.curseforge.com/addons/mailopener/create-ticket/]|r");
	desc1:SetFont(GameFontHighlightSmall:GetFont(), 13);
	desc1:SetFullWidth(true);
	desc1:SetCallback("OnClick", function()
		MailOpener.currentPopupContents = "http://wow.curseforge.com/addons/mailopener/create-ticket/";
		
		StaticPopup_Show("MailOpenerCopyWindow");
	end);
	desc1:SetCallback("OnEnter", function()
		frame:SetStatusText("Click to copy this URL.");
	end);
	desc1:SetCallback("OnLeave", function()
		frame:SetStatusText("");
	end);
	frame:AddChild(desc1);
	
	-- Empty line between the two links
	local spacer = AceGUI:Create("Label");
	spacer:SetText(" ");
	frame:AddChild(spacer);
	
	local desc2 = AceGUI:Create("InteractiveLabel");
	desc2:SetText("|cff00bbbb[http://20kleveling.com/JMTCforum/posting.php?mode=reply&f=9&t=1403]|r");
	desc2:SetFont(GameFontHighlightSmall:GetFont(), 13);
	desc2:SetFullWidth(true);
	desc2:SetCallback("OnClick", function()
		MailOpener.currentPopupContents = "http://20kleveling.com/JMTCforum/posting.php?mode=reply&f=9&t=1403";
		
		StaticPopup_Show("MailOpenerCopyWindow");
	end);
	desc2:SetCallback("OnEnter", function()
		frame:SetStatusText("Click to copy this URL.");
	end);
	desc2:SetCallback("OnLeave", function()
		frame:SetStatusText("");
	end);
	frame:AddChild(desc2);
	
	-- Empty line between the two links
	local label = AceGUI:Create("Label");
	label:SetText("\n\nps. You can always view this window again at a later time by clicking the \"Config\" button in the mail frame.\nps2. The information above is completely Mail Opener related. It will be used to determine the best default settings.");
	label:SetFullWidth(true);
	frame:AddChild(label);
end