From e4de40ad8e1abed99c8c8d681c1dda46e72df94f Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 14 Sep 2012 14:37:48 +0300 Subject: CHUI-119 (Add Nearby chat to Conversations floater): addit. fix: use LLSD(LLUUID::null) instead LLSD::null as "default" floater's key --- indra/llui/llfloaterreg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui/llfloaterreg.cpp') diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 9115eb7174..920525448c 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -318,7 +318,7 @@ void LLFloaterReg::showInitialVisibleInstances() BOOL isvis = LLFloater::getControlGroup()->getBOOL(controlname); if (isvis) { - showInstance(name, LLSD()); // keyed floaters shouldn't set save_vis to true + showInstance(name, LLSD(LLUUID())); // keyed floaters shouldn't set save_vis to true } } } -- cgit v1.3 From 0d25cca2e1e117962aad57dc951c102bec52cb50 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Mon, 22 Oct 2012 15:01:03 -0700 Subject: Backed out changeset: 4202e227f8e4 --- indra/llui/llfloaterreg.cpp | 2 +- indra/llui/llfloaterreg.h | 24 ++++++++++++------------ indra/newview/llnearbychat.cpp | 12 ++++++------ 3 files changed, 19 insertions(+), 19 deletions(-) (limited to 'indra/llui/llfloaterreg.cpp') diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 920525448c..9115eb7174 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -318,7 +318,7 @@ void LLFloaterReg::showInitialVisibleInstances() BOOL isvis = LLFloater::getControlGroup()->getBOOL(controlname); if (isvis) { - showInstance(name, LLSD(LLUUID())); // keyed floaters shouldn't set save_vis to true + showInstance(name, LLSD()); // keyed floaters shouldn't set save_vis to true } } } diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h index 7924b2a7b8..a1e1f8a988 100644 --- a/indra/llui/llfloaterreg.h +++ b/indra/llui/llfloaterreg.h @@ -90,23 +90,23 @@ public: static LLFloater* getLastFloaterCascading(); // Find / get (create) / remove / destroy - static LLFloater* findInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); - static LLFloater* getInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); - static LLFloater* removeInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); - static bool destroyInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); + static LLFloater* findInstance(const std::string& name, const LLSD& key = LLSD()); + static LLFloater* getInstance(const std::string& name, const LLSD& key = LLSD()); + static LLFloater* removeInstance(const std::string& name, const LLSD& key = LLSD()); + static bool destroyInstance(const std::string& name, const LLSD& key = LLSD()); // Iterators static const_instance_list_t& getFloaterList(const std::string& name); // Visibility Management // return NULL if instance not found or can't create instance (no builder) - static LLFloater* showInstance(const std::string& name, const LLSD& key = LLSD(LLUUID()), BOOL focus = FALSE); + static LLFloater* showInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE); // Close a floater (may destroy or set invisible) // return false if can't find instance - static bool hideInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); + static bool hideInstance(const std::string& name, const LLSD& key = LLSD()); // return true if instance is visible: - static bool toggleInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())); - static bool instanceVisible(const std::string& name, const LLSD& key = LLSD(LLUUID())); + static bool toggleInstance(const std::string& name, const LLSD& key = LLSD()); + static bool instanceVisible(const std::string& name, const LLSD& key = LLSD()); static void showInitialVisibleInstances(); static void hideVisibleInstances(const std::set& exceptions = std::set()); @@ -126,23 +126,23 @@ public: static void registerControlVariables(); // Callback wrappers - static void toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD(LLUUID())); + static void toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD()); // Typed find / get / show template - static T* findTypedInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())) + static T* findTypedInstance(const std::string& name, const LLSD& key = LLSD()) { return dynamic_cast(findInstance(name, key)); } template - static T* getTypedInstance(const std::string& name, const LLSD& key = LLSD(LLUUID())) + static T* getTypedInstance(const std::string& name, const LLSD& key = LLSD()) { return dynamic_cast(getInstance(name, key)); } template - static T* showTypedInstance(const std::string& name, const LLSD& key = LLSD(LLUUID()), BOOL focus = FALSE) + static T* showTypedInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE) { return dynamic_cast(showInstance(name, key, focus)); } diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a89ae4a2dc..5b274dd389 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -287,10 +287,10 @@ void LLNearbyChat::setVisible(BOOL visible) { LLIMConversation::setVisible(visible); - if(visible) - { - removeScreenChat(); - } + if(visible) + { + removeScreenChat(); + } setFocus(visible); } @@ -327,7 +327,7 @@ void LLNearbyChat::addToHost() mIsHostSet = true; } -} + } bool LLNearbyChat::isHostSet() { @@ -722,7 +722,7 @@ void LLNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BO send_chat_from_viewer(utf8_out_text, type, channel); } -// static +// static bool LLNearbyChat::isWordsName(const std::string& name) { // checking to see if it's display name plus username in parentheses -- cgit v1.3 From 86150b4019d1a84b4af73f0ea18c47baff955562 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 21 Feb 2013 19:15:48 -0800 Subject: CHUI-568 : WIP : Introduced Ctrl-T and Ctrl-H for conversations and nearby chat --- indra/llui/llfloater.cpp | 33 ++++++++++++++++++++-- indra/llui/llfloater.h | 3 ++ indra/llui/llfloaterreg.cpp | 30 ++++++++++++-------- indra/newview/llfloaterimnearbychat.cpp | 21 ++++++++++++++ indra/newview/llfloaterimnearbychat.h | 2 ++ indra/newview/skins/default/xui/en/menu_viewer.xml | 8 +++--- 6 files changed, 79 insertions(+), 18 deletions(-) (limited to 'indra/llui/llfloaterreg.cpp') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 734e2cfda7..bf424883b3 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -812,6 +812,22 @@ void LLFloater::closeFloater(bool app_quitting) } } +/*virtual*/ +void LLFloater::closeHostedFloater() +{ + // When toggling *visibility*, close the host instead of the floater when hosted + if (getHost()) + { + llinfos << "Merov debug : closeHostedFloater : host " << llendl; + getHost()->closeFloater(); + } + else + { + llinfos << "Merov debug : closeHostedFloater : floater " << llendl; + closeFloater(); + } +} + /*virtual*/ void LLFloater::reshape(S32 width, S32 height, BOOL called_from_parent) { @@ -1609,8 +1625,19 @@ void LLFloater::bringToFront( S32 x, S32 y ) // virtual void LLFloater::setVisibleAndFrontmost(BOOL take_focus) { - setVisible(TRUE); - setFrontmost(take_focus); + LLMultiFloater* hostp = getHost(); + if (hostp) + { + llinfos << "Merov debug : setVisibleAndFrontmost : hostp->setFrontmost " << llendl; + hostp->setVisible(TRUE); + hostp->setFrontmost(take_focus); + } + else + { + llinfos << "Merov debug : setVisibleAndFrontmost : setFrontmost " << llendl; + setVisible(TRUE); + setFrontmost(take_focus); + } } void LLFloater::setFrontmost(BOOL take_focus) @@ -1618,12 +1645,14 @@ void LLFloater::setFrontmost(BOOL take_focus) LLMultiFloater* hostp = getHost(); if (hostp) { + llinfos << "Merov debug : setFrontmost : hostp->showFloater " << llendl; // this will bring the host floater to the front and select // the appropriate panel hostp->showFloater(this); } else { + llinfos << "Merov debug : setFrontmost : bringToFront " << llendl; // there are more than one floater view // so we need to query our parent directly ((LLFloaterView*)getParent())->bringToFront(this, take_focus); diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 157b9b0113..cb5bf28db3 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -226,6 +226,9 @@ public: // If allowed, close the floater cleanly, releasing focus. virtual void closeFloater(bool app_quitting = false); + // Close the floater or its host. Use when hidding or toggling a floater instance. + virtual void closeHostedFloater(); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); // Release keyboard and mouse focus diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 306caf2b91..c0be086671 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -264,11 +264,7 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key) LLFloater* instance = findInstance(name, key); if (instance) { - // When toggling *visibility*, close the host instead of the floater when hosted - if (instance->getHost()) - instance->getHost()->closeFloater(); - else - instance->closeFloater(); + instance->closeHostedFloater(); return true; } else @@ -281,18 +277,17 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key) // returns true if the instance is visible when completed bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key) { + llinfos << "Merov debug : toggleInstance, name = " << name << ", key = " << key.asString() << llendl; LLFloater* instance = findInstance(name, key); if (LLFloater::isShown(instance)) { - // When toggling *visibility*, close the host instead of the floater when hosted - if (instance->getHost()) - instance->getHost()->closeFloater(); - else - instance->closeFloater(); + llinfos << "Merov debug : call closeHostedFloater " << llendl; + instance->closeHostedFloater(); return false; } else { + llinfos << "Merov debug : call show instance " << llendl; return showInstance(name, key, TRUE) ? true : false; } } @@ -481,31 +476,42 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& // * Also, if it is not on top, bring it forward when focus is given. // * Else the target floater is open, close it. // + llinfos << "Merov debug : toggleInstanceOrBringToFront, name = " << sdname.asString() << ", key = " << key.asString() << llendl; std::string name = sdname.asString(); LLFloater* instance = getInstance(name, key); + if (!instance) { lldebugs << "Unable to get instance of floater '" << name << "'" << llendl; + return; } - else if (instance->isMinimized()) + + // If hosted, we need to take that into account + //LLFloater* host = instance->getHost(); + + if (instance->isMinimized()) { + llinfos << "Merov debug : unminimize, make visible and set to front " << llendl; instance->setMinimized(FALSE); instance->setVisibleAndFrontmost(); } else if (!instance->isShown()) { + llinfos << "Merov debug : open, make visible and set to front " << llendl; instance->openFloater(key); instance->setVisibleAndFrontmost(); } else if (!instance->isFrontmost()) { + llinfos << "Merov debug : make visible and set to front " << llendl; instance->setVisibleAndFrontmost(); } else { - instance->closeFloater(); + llinfos << "Merov debug : closeHostedFloater " << llendl; + instance->closeHostedFloater(); } } diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 430326203f..80051eb7f1 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -135,6 +135,27 @@ BOOL LLFloaterIMNearbyChat::postBuild() return result; } +// virtual +void LLFloaterIMNearbyChat::closeFloater(bool app_quitting) +{ + llinfos << "Merov debug : LLFloaterIMNearbyChat::closeFloater! " << llendl; + LLFloater::closeFloater(app_quitting); +} + +// virtual +void LLFloaterIMNearbyChat::closeHostedFloater() +{ + if (getHost()) + { + llinfos << "Merov debug : LLFloaterIMNearbyChat::closeHostedFloater : hosted -> do nothing" << llendl; + } + else + { + llinfos << "Merov debug : LLFloaterIMNearbyChat::closeHostedFloater : close floater " << llendl; + LLFloater::closeFloater(); + } +} + // virtual void LLFloaterIMNearbyChat::refresh() { diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index 14c7d01ecd..2d32bb3fc9 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -54,6 +54,8 @@ public: /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ void closeFloater(bool app_quitting = false); + /*virtual*/ void closeHostedFloater(); void loadHistory(); void reloadMessages(bool clean_messages = false); diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b50deb7d7a..544f06ac0c 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -183,8 +183,7 @@ + name="Toolbars"> @@ -223,7 +222,8 @@ tear_off="true"> + name="Conversations" + shortcut="control|T"> @@ -240,7 +240,7 @@ function="Floater.Visible" parameter="nearby_chat" /> Date: Sat, 23 Feb 2013 11:22:09 -0800 Subject: CHUI-568 : Fixed! Implemented Ctrl-H for Nearby Chat, taking into account the existence of other conversations and docked/torn off state --- indra/llui/llfloater.cpp | 6 --- indra/llui/llfloaterreg.cpp | 65 +++++++++++++++++++-------------- indra/newview/llfloaterimcontainer.cpp | 24 ++++++++++++ indra/newview/llfloaterimcontainer.h | 2 + indra/newview/llfloaterimnearbychat.cpp | 20 +++++----- indra/newview/llfloaterimnearbychat.h | 1 - 6 files changed, 72 insertions(+), 46 deletions(-) (limited to 'indra/llui/llfloaterreg.cpp') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index bf424883b3..27dd7f5b32 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -818,12 +818,10 @@ void LLFloater::closeHostedFloater() // When toggling *visibility*, close the host instead of the floater when hosted if (getHost()) { - llinfos << "Merov debug : closeHostedFloater : host " << llendl; getHost()->closeFloater(); } else { - llinfos << "Merov debug : closeHostedFloater : floater " << llendl; closeFloater(); } } @@ -1628,13 +1626,11 @@ void LLFloater::setVisibleAndFrontmost(BOOL take_focus) LLMultiFloater* hostp = getHost(); if (hostp) { - llinfos << "Merov debug : setVisibleAndFrontmost : hostp->setFrontmost " << llendl; hostp->setVisible(TRUE); hostp->setFrontmost(take_focus); } else { - llinfos << "Merov debug : setVisibleAndFrontmost : setFrontmost " << llendl; setVisible(TRUE); setFrontmost(take_focus); } @@ -1645,14 +1641,12 @@ void LLFloater::setFrontmost(BOOL take_focus) LLMultiFloater* hostp = getHost(); if (hostp) { - llinfos << "Merov debug : setFrontmost : hostp->showFloater " << llendl; // this will bring the host floater to the front and select // the appropriate panel hostp->showFloater(this); } else { - llinfos << "Merov debug : setFrontmost : bringToFront " << llendl; // there are more than one floater view // so we need to query our parent directly ((LLFloaterView*)getParent())->bringToFront(this, take_focus); diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index c0be086671..c20d863612 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -265,29 +265,22 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key) if (instance) { instance->closeHostedFloater(); - return true; - } - else - { - return false; } + return (instance != NULL); } //static // returns true if the instance is visible when completed bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key) { - llinfos << "Merov debug : toggleInstance, name = " << name << ", key = " << key.asString() << llendl; LLFloater* instance = findInstance(name, key); if (LLFloater::isShown(instance)) { - llinfos << "Merov debug : call closeHostedFloater " << llendl; instance->closeHostedFloater(); return false; } else { - llinfos << "Merov debug : call show instance " << llendl; return showInstance(name, key, TRUE) ? true : false; } } @@ -476,8 +469,6 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& // * Also, if it is not on top, bring it forward when focus is given. // * Else the target floater is open, close it. // - llinfos << "Merov debug : toggleInstanceOrBringToFront, name = " << sdname.asString() << ", key = " << key.asString() << llendl; - std::string name = sdname.asString(); LLFloater* instance = getInstance(name, key); @@ -489,29 +480,47 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& } // If hosted, we need to take that into account - //LLFloater* host = instance->getHost(); + LLFloater* host = instance->getHost(); - if (instance->isMinimized()) - { - llinfos << "Merov debug : unminimize, make visible and set to front " << llendl; - instance->setMinimized(FALSE); - instance->setVisibleAndFrontmost(); - } - else if (!instance->isShown()) - { - llinfos << "Merov debug : open, make visible and set to front " << llendl; - instance->openFloater(key); - instance->setVisibleAndFrontmost(); - } - else if (!instance->isFrontmost()) + if (host) { - llinfos << "Merov debug : make visible and set to front " << llendl; - instance->setVisibleAndFrontmost(); + if (host->isMinimized() || !host->isShown() || !host->isFrontmost()) + { + host->setMinimized(FALSE); + instance->openFloater(key); + instance->setVisibleAndFrontmost(); + } + else if (!instance->getVisible()) + { + instance->openFloater(key); + instance->setVisibleAndFrontmost(); + instance->setFocus(TRUE); + } + else + { + instance->closeHostedFloater(); + } } else { - llinfos << "Merov debug : closeHostedFloater " << llendl; - instance->closeHostedFloater(); + if (instance->isMinimized()) + { + instance->setMinimized(FALSE); + instance->setVisibleAndFrontmost(); + } + else if (!instance->isShown()) + { + instance->openFloater(key); + instance->setVisibleAndFrontmost(); + } + else if (!instance->isFrontmost()) + { + instance->setVisibleAndFrontmost(); + } + else + { + instance->closeHostedFloater(); + } } } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c8088588da..73fcfa244e 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1337,6 +1337,30 @@ void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) selectConversationPair(session_id, true); } +// Select the conversation *after* (or before if none after) the passed uuid conversation +// Used to change the selection on key hits +void LLFloaterIMContainer::selectNextConversation(const LLUUID& uuid) +{ + LLFolderViewItem* new_selection = NULL; + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); + if (widget) + { + new_selection = mConversationsRoot->getNextFromChild(widget, FALSE); + if (!new_selection) + { + new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE); + } + } + if (new_selection) + { + LLConversationItem* vmi = dynamic_cast(new_selection->getViewModelItem()); + if (vmi) + { + selectConversationPair(vmi->getUUID(), true); + } + } +} + // Synchronous select the conversation item and the conversation floater BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget) { diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 569fa9faab..33d63a391c 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -69,6 +69,7 @@ public: void returnFloaterToHost(); void showConversation(const LLUUID& session_id); void selectConversation(const LLUUID& session_id); + void selectNextConversation(const LLUUID& session_id); BOOL selectConversationPair(const LLUUID& session_id, bool select_widget); void clearAllFlashStates(); @@ -186,6 +187,7 @@ public: static bool isConversationLoggingAllowed(); void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes); boost::signals2::connection mMicroChangedSignal; + S32 getConversationListItemSize() { return mConversationsWidgets.size(); } private: LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 80051eb7f1..a3b81e037a 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -135,24 +135,22 @@ BOOL LLFloaterIMNearbyChat::postBuild() return result; } -// virtual -void LLFloaterIMNearbyChat::closeFloater(bool app_quitting) -{ - llinfos << "Merov debug : LLFloaterIMNearbyChat::closeFloater! " << llendl; - LLFloater::closeFloater(app_quitting); -} - // virtual void LLFloaterIMNearbyChat::closeHostedFloater() { - if (getHost()) + // Should check how many conversations are ongoing. Close all if 1 only (the Nearby Chat), select next one otherwise + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + if (floater_container->getConversationListItemSize() == 1) { - llinfos << "Merov debug : LLFloaterIMNearbyChat::closeHostedFloater : hosted -> do nothing" << llendl; + floater_container->closeFloater(); } else { - llinfos << "Merov debug : LLFloaterIMNearbyChat::closeHostedFloater : close floater " << llendl; - LLFloater::closeFloater(); + if (!getHost()) + { + setVisible(FALSE); + } + floater_container->selectNextConversation(LLUUID()); } } diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index 2d32bb3fc9..2992c12436 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -54,7 +54,6 @@ public: /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setVisible(BOOL visible); - /*virtual*/ void closeFloater(bool app_quitting = false); /*virtual*/ void closeHostedFloater(); void loadHistory(); -- cgit v1.3