/*
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.
*/

/*
  Copyright (C) 2002 Dario Abatianni <eisfuchs@tigress.com>
  Copyright (C) 2005 Ismail Donmez <ismail@kde.org>
  Copyright (C) 2005 Peter Simonsson <psn@linux.se>
  Copyright (C) 2005 John Tapsell <johnflux@gmail.com>
  Copyright (C) 2005-2008 Eike Hein <hein@kde.org>
*/

#include "konversationmainwindow.h"
#include "konversationapplication.h"
#include "linkaddressbook/addressbook.h"
#include "konvisettingsdialog.h"
#include "viewcontainer.h"
#include "konversationstatusbar.h"
#include "konvibookmarkhandler.h"
#include "trayicon.h"
#include "serverlistdialog.h"
#include "identitydialog.h"
#include "notificationhandler.h"
#include "irccharsets.h"
#include "connectionmanager.h"
#include "awaymanager.h"
#include "dcctransfermanager.h"

#include <tqnamespace.h>
#include <tqwhatsthis.h>
#include <tqsignalmapper.h>
#include <tqobjectlist.h>

#include <tdeaccel.h>
#include <tdeaccelmanager.h>
#include <kstdaction.h>
#include <tdeaction.h>
#include <kdebug.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <tdemenubar.h>
#include <kkeydialog.h>
#include <tdeversion.h>
#include <kedittoolbar.h>
#include <tdepopupmenu.h>
#include <twin.h>
#include <tdeglobal.h>
#include <kstandarddirs.h>
#include <dcopclient.h>
#include <scriptmanager.h>
#include <tdeabc/addressbook.h>
#include <tdeabc/errorhandler.h>

#include <config.h>
#ifdef  USE_KNOTIFY
#include <knotifydialog.h>
#endif


KonversationMainWindow::KonversationMainWindow() : TDEMainWindow(0,"main_window", WStyle_ContextHelp | WType_TopLevel | WDestructiveClose)
{
    m_hasDirtySettings = false;
    m_closeApp = false;
    m_serverListDialog = 0;
    m_settingsDialog = NULL;

    m_viewContainer = new ViewContainer(this);
    setCentralWidget(m_viewContainer->getWidget());

    //used for event compression. See header file for resetHasDirtySettings()
    connect(KonversationApplication::instance(), TQ_SIGNAL(appearanceChanged()), this, TQ_SLOT(resetHasDirtySettings()));
    connect(KonversationApplication::instance(), TQ_SIGNAL(appearanceChanged()), this, TQ_SLOT(updateTrayIcon()));


    // Set up view container
    connect(KonversationApplication::instance(), TQ_SIGNAL(appearanceChanged()), m_viewContainer, TQ_SLOT(updateAppearance()));
    connect(KonversationApplication::instance(), TQ_SIGNAL(iconChanged(int)), m_viewContainer, TQ_SLOT(updateViewIcons()));
    connect(KonversationApplication::instance(), TQ_SIGNAL(serverGroupsChanged(const Konversation::ServerGroupSettings*)),
            m_viewContainer, TQ_SLOT(updateViews(const Konversation::ServerGroupSettings*)));
    connect(m_viewContainer, TQ_SIGNAL(autoJoinToggled(const Konversation::ServerGroupSettings*)),
            KonversationApplication::instance(), TQ_SIGNAL(serverGroupsChanged(const Konversation::ServerGroupSettings*)));
    connect(m_viewContainer, TQ_SIGNAL(setWindowCaption(const TQString&)), this, TQ_SLOT(setCaption(const TQString&)));
    connect(KonversationApplication::instance()->getConnectionManager(),
            TQ_SIGNAL(connectionChangedState(Server*, Konversation::ConnectionState)),
            m_viewContainer, TQ_SLOT(connectionStateChanged(Server*, Konversation::ConnectionState)));
    connect(this, TQ_SIGNAL(triggerRememberLine()), m_viewContainer, TQ_SLOT(insertRememberLine()));
    connect(this, TQ_SIGNAL(triggerRememberLines(Server*)), m_viewContainer, TQ_SLOT(insertRememberLines(Server*)));
    connect(this, TQ_SIGNAL(cancelRememberLine()), m_viewContainer, TQ_SLOT(cancelRememberLine()));
    connect(this, TQ_SIGNAL(insertMarkerLine()), m_viewContainer, TQ_SLOT(insertMarkerLine()));

    // Set up status bar
    m_statusBar = new KonversationStatusBar(this);
    connect(KonversationApplication::instance(), TQ_SIGNAL(appearanceChanged()), m_statusBar, TQ_SLOT(updateAppearance()));

    createStandardStatusBarAction();

    connect(actionCollection(), TQ_SIGNAL(actionStatusText(const TQString&)), m_statusBar, TQ_SLOT(setMainLabelTempText(const TQString&)));
    connect(actionCollection(), TQ_SIGNAL(clearStatusText()), m_statusBar, TQ_SLOT(clearMainLabelTempText()));
    actionCollection()->setHighlightingEnabled(true);

    connect(m_viewContainer, TQ_SIGNAL(resetStatusBar()), m_statusBar, TQ_SLOT(resetStatusBar()));
    connect(m_viewContainer, TQ_SIGNAL(setStatusBarTempText(const TQString&)), m_statusBar, TQ_SLOT(setMainLabelTempText(const TQString&)));
    connect(m_viewContainer, TQ_SIGNAL(clearStatusBarTempText()), m_statusBar, TQ_SLOT(clearMainLabelTempText()));
    connect(m_viewContainer, TQ_SIGNAL(setStatusBarInfoLabel(const TQString&)), m_statusBar, TQ_SLOT(updateInfoLabel(const TQString&)));
    connect(m_viewContainer, TQ_SIGNAL(clearStatusBarInfoLabel()), m_statusBar, TQ_SLOT(clearInfoLabel()));
    connect(m_viewContainer, TQ_SIGNAL(setStatusBarLagLabelShown(bool)), m_statusBar, TQ_SLOT(setLagLabelShown(bool)));
    connect(m_viewContainer, TQ_SIGNAL(updateStatusBarLagLabel(Server*, int)), m_statusBar, TQ_SLOT(updateLagLabel(Server*, int)));
    connect(m_viewContainer, TQ_SIGNAL(resetStatusBarLagLabel()), m_statusBar, TQ_SLOT(resetLagLabel()));
    connect(m_viewContainer, TQ_SIGNAL(setStatusBarLagLabelTooLongLag(Server*, int)), m_statusBar, TQ_SLOT(setTooLongLag(Server*, int)));
    connect(m_viewContainer, TQ_SIGNAL(updateStatusBarSSLLabel(Server*)), m_statusBar, TQ_SLOT(updateSSLLabel(Server*)));
    connect(m_viewContainer, TQ_SIGNAL(removeStatusBarSSLLabel()), m_statusBar, TQ_SLOT(removeSSLLabel()));


    // Actions
    KStdAction::quit(this,TQ_SLOT(quitProgram()),actionCollection());

    hideMenuBarAction = KStdAction::showMenubar(this, TQ_SLOT(toggleMenubar()), actionCollection());

    setStandardToolBarMenuEnabled(true);
    KStdAction::configureToolbars(this, TQ_SLOT(configureToolbar()), actionCollection());

    KStdAction::keyBindings(this, TQ_SLOT(openKeyBindings()), actionCollection());
    TDEAction *preferencesAction = KStdAction::preferences(this, TQ_SLOT(openPrefsDialog()), actionCollection());

#ifdef USE_KNOTIFY // options_configure_notifications
    TDEAction *configureNotificationsAction = KStdAction::configureNotifications(this,TQ_SLOT(openNotifications()), actionCollection());
#endif

    TDEAction* action;

    (new TDEAction(i18n("&Server List..."), "server", TDEShortcut("F2"), this, TQ_SLOT(openServerList()),
        actionCollection(), "open_server_list"))->setToolTip(i18n("Manage networks and servers"));
    (new TDEAction(i18n("Quick &Connect..."), "connect_creating", TDEShortcut("F7"), this, TQ_SLOT(openQuickConnectDialog()),
        actionCollection(), "quick_connect_dialog"))->setToolTip(i18n("Type in the address of a new IRC server to connect to"));

    action = new TDEAction(i18n("&Reconnect"), "connect_creating", 0, m_viewContainer, TQ_SLOT(reconnectFrontServer()), actionCollection(), "reconnect_server");
    action->setEnabled(false);
    action->setToolTip(i18n("Reconnect to the current server."));

    action = new TDEAction(i18n("&Disconnect"), "connect_no", 0, m_viewContainer, TQ_SLOT(disconnectFrontServer()), actionCollection(), "disconnect_server");
    action->setEnabled(false);
    action->setToolTip(i18n("Disconnect from the current server."));

    (new TDEAction(i18n("&Identities..."), "identity", TDEShortcut("F8"), this, TQ_SLOT(openIdentitiesDialog()),
        actionCollection(), "identities_dialog"))->setToolTip(i18n("Manage your nick, away and other identity settings"));

    new TDEToggleAction(i18n("&Watched Nicks Online"), "kontact_contacts", TDEShortcut("F4"), m_viewContainer, TQ_SLOT(openNicksOnlinePanel()), actionCollection(), "open_nicksonline_window");
    new TDEToggleAction(i18n("&DCC Status"), "2rightarrow", TDEShortcut("F9"), m_viewContainer, TQ_SLOT(toggleDccPanel()), actionCollection(), "open_dccstatus_window");
    action = new TDEAction(i18n("&Open Logfile"), "history", TDEShortcut("Ctrl+O"), m_viewContainer, TQ_SLOT(openLogFile()), actionCollection(), "open_logfile");
    action->setEnabled(false);
    action->setToolTip(i18n("Open the known history for this channel in a new tab"));

    action = new TDEAction(i18n("&Channel Settings..."), "edit", m_viewContainer, TQ_SLOT(openChannelSettings()), actionCollection(), "channel_settings");
    action->setEnabled(false);
    action->setToolTip(i18n("Open the channel settings dialog for this tab"));

    TDEToggleAction* channelListAction = new TDEToggleAction(i18n("Channel &List"), "view_text", TDEShortcut("F5"), m_viewContainer, TQ_SLOT(openChannelList()), actionCollection(), "open_channel_list");
    channelListAction->setEnabled(false);
    channelListAction->setToolTip(i18n("Show a list of all the known channels on this server"));

    action = new TDEToggleAction(i18n("&URL Catcher"), "enhanced_browsing", TDEShortcut("F6"), m_viewContainer, TQ_SLOT(addUrlCatcher()), actionCollection(), "open_url_catcher");
    action->setToolTip(i18n("List all URLs that have been mentioned recently in a new tab"));

    if (kapp->authorize("shell_access"))
    {
        action = new TDEAction(i18n("New &Konsole"), "openterm", 0, m_viewContainer, TQ_SLOT(addKonsolePanel()), actionCollection(), "open_konsole");
        action->setToolTip(i18n("Open a terminal in a new tab"));
    }

    // Actions to navigate through the different pages
    TDEShortcut nextShortcut = TDEStdAccel::tabNext();
    nextShortcut.setSeq(1, KKeySequence("Alt+Right"));
    TDEShortcut prevShortcut = TDEStdAccel::tabPrev();
    prevShortcut.setSeq(1, KKeySequence("Alt+Left"));
    action = new TDEAction(i18n("&Next Tab"), TQApplication::reverseLayout() ? "go-previous" : "go-next",
        TQApplication::reverseLayout() ? prevShortcut : nextShortcut,
        m_viewContainer, TQ_SLOT(showNextView()), actionCollection(), "next_tab");
    action->setEnabled(false);
    action = new TDEAction(i18n("&Previous Tab"), TQApplication::reverseLayout() ? "go-next" : "go-previous",
        TQApplication::reverseLayout() ? nextShortcut : prevShortcut,
        m_viewContainer, TQ_SLOT(showPreviousView()),actionCollection(),"previous_tab");
    action->setEnabled(false);
    action = new TDEAction(i18n("Close &Tab"),"tab_remove",TDEShortcut("Ctrl+w"), m_viewContainer, TQ_SLOT(closeCurrentView()),actionCollection(),"close_tab");
    action->setEnabled(false);
    action = new TDEAction(i18n("Next Active Tab"), 0, TDEShortcut("Ctrl+Alt+Space"), m_viewContainer, TQ_SLOT(showNextActiveView()),
                         actionCollection(), "next_active_tab");
    action->setEnabled(false);

    if (Preferences::tabPlacement()==PreferencesBase::Left)
    {
        action = new TDEAction(i18n("Move Tab Up"), "1uparrow", TDEShortcut("Alt+Shift+Left"),
            m_viewContainer, TQ_SLOT(moveViewLeft()), actionCollection(), "move_tab_left");
        action->setEnabled(false);
        action->setToolTip("Move this tab");
        action = new TDEAction(i18n("Move Tab Down"), "1downarrow", TDEShortcut("Alt+Shift+Right"),
            m_viewContainer, TQ_SLOT(moveViewRight()), actionCollection(), "move_tab_right");
        action->setEnabled(false);
        action->setToolTip("Move this tab");
    }
    else
    {
        TDEAction* action2;
        if (TQApplication::reverseLayout())
        {
            action2 = new TDEAction(i18n("Move Tab Right"), "1rightarrow", TDEShortcut("Alt+Shift+Right"),
                          m_viewContainer, TQ_SLOT(moveViewLeft()), actionCollection(), "move_tab_left");
            action  = new TDEAction(i18n("Move Tab Left"), "1leftarrow", TDEShortcut("Alt+Shift+Left"),
                          m_viewContainer, TQ_SLOT(moveViewRight()), actionCollection(), "move_tab_right");
        }
        else
        {
            action  = new TDEAction(i18n("Move Tab Left"), "1leftarrow", TDEShortcut("Alt+Shift+Left"),
                          m_viewContainer, TQ_SLOT(moveViewLeft()), actionCollection(), "move_tab_left");
                action2 = new TDEAction(i18n("Move Tab Right"), "1rightarrow", TDEShortcut("Alt+Shift+Right"),
                          m_viewContainer, TQ_SLOT(moveViewRight()), actionCollection(), "move_tab_right");
        }

        action->setEnabled(false);
        action->setToolTip("Move this tab");
        action2->setEnabled(false);
        action2->setToolTip("Move this tab");
    }

    action = new TDEAction(i18n("Rejoin Channel"), 0, m_viewContainer, TQ_SLOT(rejoinChannel()), actionCollection(), "rejoin_channel");
    action->setEnabled(false);

    action = new TDEToggleAction(i18n("Enable Notifications"), 0, 0, m_viewContainer, TQ_SLOT(toggleViewNotifications()), actionCollection(), "tab_notifications");
    action->setEnabled(false);

    action = new TDEToggleAction(i18n("Join on Connect"), 0, 0, m_viewContainer, TQ_SLOT(toggleAutoJoin()), actionCollection(), "tab_autojoin");
    action->setEnabled(false);

    TDESelectAction* selectAction = new TDESelectAction(i18n("Set Encoding"), "charset", 0, actionCollection(), "tab_encoding");
    selectAction->setEditable(false);
    TQStringList encodingDescs = Konversation::IRCCharsets::self()->availableEncodingDescriptiveNames();
    encodingDescs.prepend(i18n("Default"));
    selectAction->setItems(encodingDescs);
    selectAction->setEnabled(false);
    connect(selectAction, TQ_SIGNAL(activated(int)), m_viewContainer, TQ_SLOT(changeViewCharset(int)));

    TQSignalMapper* tabSelectionMapper = new TQSignalMapper(this);
    connect(tabSelectionMapper, TQ_SIGNAL(mapped(int)), m_viewContainer, TQ_SLOT(goToView(int)));

    for (uint i = 1; i <= 10; ++i)
    {
        TDEAction* tabSelectionAction = new TDEAction(i18n("Go to Tab %1").arg(i), 0, TDEShortcut(TQString("Alt+%1").arg(i%10)),
            tabSelectionMapper, TQ_SLOT(map()), actionCollection(), TQString("go_to_tab_%1").arg(i).local8Bit());
        tabSelectionMapper->setMapping( tabSelectionAction, i-1);
    }

    action = new TDEAction(i18n("Clear &Marker Lines"), 0, TDEShortcut("CTRL+SHIFT+R"), m_viewContainer, TQ_SLOT(clearViewLines()),actionCollection(),"clear_lines");
    action->setToolTip(i18n("Clear marker lines in the current tab"));
    action->setEnabled(false);
    action = new TDEAction(i18n("&Clear Window"), 0, TDEShortcut("Ctrl+L"), m_viewContainer, TQ_SLOT(clearView()),actionCollection(),"clear_window");
    action->setToolTip(i18n("Clear the contents of the current tab"));
    action->setEnabled(false);
    action = new TDEAction(i18n("Clear &All Windows"),0,TDEShortcut("CTRL+SHIFT+L"), m_viewContainer, TQ_SLOT(clearAllViews()),actionCollection(),"clear_tabs");
    action->setToolTip(i18n("Clear the contents of all open tabs"));
    action->setEnabled(false);

    TDEToggleAction* awayAction = new TDEToggleAction(i18n("Global Away"), TDEShortcut("Ctrl+Shift+A"), actionCollection(), "toggle_away");
    connect(awayAction, TQ_SIGNAL(toggled(bool)), static_cast<KonversationApplication*>(kapp)->getAwayManager(), TQ_SLOT(toggleGlobalAway(bool)));
    awayAction->setEnabled(false);

    action = new TDEAction(i18n("&Join Channel..."), "add", TDEShortcut("Ctrl+J"), m_viewContainer, TQ_SLOT(showJoinChannelDialog()), actionCollection(), "join_channel");
    action->setEnabled(false);
    action->setToolTip("Join a new channel on this server");

    action = KStdAction::find(m_viewContainer, TQ_SLOT(findText()), actionCollection());
    action->setEnabled(false);
    action = KStdAction::findNext(m_viewContainer, TQ_SLOT(findNextText()), actionCollection());
    action->setEnabled(false);
    action = KStdAction::findPrev(m_viewContainer, TQ_SLOT(findPrevText()), actionCollection());
    action->setEnabled(false);

    action = new TDEAction(i18n("&IRC Color..."), "colorize", CTRL+Key_K, m_viewContainer, TQ_SLOT(insertIRCColor()), actionCollection(), "irc_colors");
    action->setToolTip(i18n("Set the color of your current IRC message"));
    action->setEnabled(false);
    action = new TDEAction(i18n("&Marker Line"), 0,  TDEShortcut("Ctrl+R") , m_viewContainer, TQ_SLOT(insertMarkerLine()), actionCollection(), "insert_marker_line");
    action->setToolTip(i18n("Insert a horizontal line into the current tab that only you can see"));
    action->setEnabled(false);
    action = new TDEAction(i18n("Special &Character..."), "char", TDEShortcut("Alt+Shift+C"), m_viewContainer, TQ_SLOT(insertCharacter()), actionCollection(), "insert_character");
    action->setToolTip(i18n("Insert any character into your current IRC message"));
    action->setEnabled(false);

    action = new TDEAction(i18n("Close &All Open Queries"), 0, TDEShortcut("F11"), m_viewContainer, TQ_SLOT(closeQueries()), actionCollection(), "close_queries");
    action->setEnabled(false);

    TDEToggleAction* toggleChannelNickListsAction = new TDEToggleAction(i18n("Hide Nicklist"), 0,
        TDEShortcut("Ctrl+H"), m_viewContainer, TQ_SLOT(toggleChannelNicklists()), actionCollection(), "hide_nicknamelist");
    if (!Preferences::showNickList())
        toggleChannelNickListsAction->setChecked(true);

    // set up system tray
    m_trayIcon = new Konversation::TrayIcon(this);
    connect(this, TQ_SIGNAL(endNotification()), m_trayIcon, TQ_SLOT(endNotification()));
    connect(KonversationApplication::instance(), TQ_SIGNAL(iconChanged(int)), m_trayIcon, TQ_SLOT(updateAppearance()));
    connect(m_trayIcon, TQ_SIGNAL(quitSelected()), this, TQ_SLOT(quitProgram()));
    TDEPopupMenu *trayMenu = m_trayIcon->contextMenu();
    #ifdef USE_KNOTIFY
    configureNotificationsAction->plug(trayMenu);
    #endif
    preferencesAction->plug(trayMenu);
    awayAction->plug(trayMenu);

    // decide whether to show the tray icon or not
    updateTrayIcon();

    createGUI(NULL, false);

    resize(700, 500);                             // Give the app a sane default size
    setAutoSaveSettings();

    // Apply menubar show/hide pref
    hideMenuBarAction->setChecked(Preferences::showMenuBar());
    toggleMenubar(true);

    // Bookmarks
    m_bookmarkHandler = new KonviBookmarkHandler(this);

    // set up KABC with a nice gui error dialog
    TDEABC::GuiErrorHandler *m_guiErrorHandler = new TDEABC::GuiErrorHandler(this);
    kapp->dcopClient()->setAcceptCalls( false );
    Konversation::Addressbook::self()->getAddressBook()->setErrorHandler(m_guiErrorHandler);
    kapp->dcopClient()->setAcceptCalls( true );

    if (Preferences::useNotify() && Preferences::openWatchedNicksAtStartup())
        m_viewContainer->openNicksOnlinePanel();

}

KonversationMainWindow::~KonversationMainWindow()
{
    delete m_viewContainer;
}

int KonversationMainWindow::confirmQuit()
{
    KonversationApplication* konvApp = static_cast<KonversationApplication*>(kapp);

    if (konvApp->getConnectionManager()->connectionCount() == 0)
        return KMessageBox::Continue;

    int result = KMessageBox::Cancel;

    if (!KMessageBox::shouldBeShownContinue("systemtrayquitKonversation")
         && konvApp->getDccTransferManager()->hasActiveTransfers())
    {
        result = KMessageBox::warningContinueCancel(
            this,
            i18n("<qt>You have active DCC file transfers. Are you sure you want to quit <b>Konversation</b>?</qt>"),
            i18n("Confirm Quit"),
            i18n("Quit"),
            "QuitWithActiveDccTransfers");
    }
    else
    {
        result = KMessageBox::warningContinueCancel(
            this,
            i18n("<qt>Are you sure you want to quit <b>Konversation</b>?</qt>"),
            i18n("Confirm Quit"),
            i18n("Quit"),
            "systemtrayquitKonversation");
    }

    return result;
}

void KonversationMainWindow::quitProgram()
{
    if (Preferences::showTrayIcon() &&
        sender() != m_trayIcon &&
        confirmQuit() == KMessageBox::Cancel) return;

    // will call queryClose()
    m_closeApp = true;
    close();
}

bool KonversationMainWindow::queryClose()
{
    KonversationApplication* konvApp = static_cast<KonversationApplication*>(kapp);

    if (!konvApp->sessionSaving())
    {
        if (sender() == m_trayIcon)
            m_closeApp = true;

        if (Preferences::showTrayIcon() && !m_closeApp)
        {
            KMessageBox::information( this,
                i18n("<p>Closing the main window will keep Konversation running in the system tray. "
                "Use <b>Quit</b> from the <b>Konversation</b> menu to quit the application.</p>"),
                i18n( "Docking in System Tray" ),  "HideOnCloseInfo" );
            hide();

            return false;
        }

        if (!Preferences::showTrayIcon() && confirmQuit() == KMessageBox::Cancel)
            return false;
    }

    return true;
}

void KonversationMainWindow::hideEvent(TQHideEvent *e)
{
    emit triggerRememberLine();

    m_statusBar->clearMainLabelTempText();

    TDEMainWindow::hideEvent(e);
}

void KonversationMainWindow::showEvent(TQShowEvent *e)
{
    emit cancelRememberLine();

    TDEMainWindow::showEvent(e);
}

void KonversationMainWindow::leaveEvent(TQEvent* e)
{
    m_statusBar->clearMainLabelTempText();

    TDEMainWindow::leaveEvent(e);
}

bool KonversationMainWindow::event(TQEvent* e)
{
    if (e->type() == TQEvent::WindowActivate)
    {
        emit endNotification();
        emit cancelRememberLine();
    }
    else if(e->type() == TQEvent::WindowDeactivate)
    {
        m_statusBar->clearMainLabelTempText();

        if (kapp->activeModalWidget() == 0)
            emit triggerRememberLine();
    }

    return TDEMainWindow::event(e);
}

void KonversationMainWindow::settingsChangedSlot()
{
    // This is for compressing the events. m_hasDirtySettings is set to true
    // when the settings have changed, then set to false when the app reacts to it
    // via the appearanceChanged signal.  This prevents a series of settingsChanged signals
    // causing the app expensively rereading its settings many times.
    // The appearanceChanged signal is connected to resetHasDirtySettings to reset this bool
    if (!m_hasDirtySettings) 
    {
        TQTimer::singleShot(0, KonversationApplication::instance(), TQ_SIGNAL(appearanceChanged()));
        m_hasDirtySettings = true;
    }
}

void KonversationMainWindow::resetHasDirtySettings()
{
    m_hasDirtySettings = false;
}

void KonversationMainWindow::updateTrayIcon()
{
    m_trayIcon->setNotificationEnabled(Preferences::trayNotify());

    if (Preferences::showTrayIcon())
        m_trayIcon->show();
    else
        m_trayIcon->hide();
}

void KonversationMainWindow::toggleMenubar(bool dontShowWarning)
{
    if (hideMenuBarAction->isChecked())
        menuBar()->show();
    else
    {
        if (!dontShowWarning)
        {
            TQString accel = hideMenuBarAction->shortcut().toString();
            KMessageBox::information(this,
                i18n("<qt>This will hide the menu bar completely. You can show it again by typing %1.</qt>").arg(accel),
                "Hide menu bar","HideMenuBarWarning");
        }
        menuBar()->hide();
    }

    Preferences::setShowMenuBar(hideMenuBarAction->isChecked());
}

int KonversationMainWindow::configureToolbar()
{
    saveMainWindowSettings(TDEGlobal::config());
    KEditToolbar dlg(actionCollection(), xmlFile(), true, this);
    connect(&dlg, TQ_SIGNAL(newToolbarConfig()), TQ_SLOT(saveToolbarConfig()));
    return dlg.exec();
}

void KonversationMainWindow::saveToolbarConfig()
{
    createGUI(xmlFile(), false);
    applyMainWindowSettings(TDEGlobal::config());
}

void KonversationMainWindow::focusAndShowErrorMessage(const TQString &errorMsg)
{
    show();
    KWin::demandAttention(winId());
    KWin::activateWindow(winId());
    KMessageBox::error(this, errorMsg);
}

void KonversationMainWindow::openPrefsDialog()
{
    //An instance of your dialog could be already created and could be cached,
    //in which case you want to display the cached dialog instead of creating
    //another one
    if (!m_settingsDialog)
    {
        m_settingsDialog = new KonviSettingsDialog(this);
        //User edited the configuration - update your local copies of the
        //configuration data
        connect(m_settingsDialog, TQ_SIGNAL(settingsChanged()), this, TQ_SLOT(settingsChangedSlot()));
    }
    m_settingsDialog->show();
}

void KonversationMainWindow::openKeyBindings()
{
    // Change a number of action names to make them friendlier for the shortcut list.
    actionCollection()->action("tab_notifications")->setText(i18n("Toggle Notifications"));
    actionCollection()->action("toggle_away")->setText(i18n("Toggle Away Globally"));
    actionCollection()->action("irc_colors")->setText(i18n("Insert &IRC Color..."));
    actionCollection()->action("insert_character")->setText(i18n("Insert Special &Character..."));
    actionCollection()->action("insert_marker_line")->setText(i18n("Insert &Marker Line"));
    TQString openChannelListString = actionCollection()->action("open_channel_list")->text();
    actionCollection()->action("open_channel_list")->setText(i18n("&Channel List"));
    TQString openLogFileString = actionCollection()->action("open_logfile")->text();
    actionCollection()->action("open_logfile")->setText(i18n("&Open Logfile"));

    // Open shortcut configuration dialog.
    KKeyDialog::configure(actionCollection());

    // Reset action names.
    actionCollection()->action("tab_notifications")->setText(i18n("Enable Notifications"));
    actionCollection()->action("toggle_away")->setText(i18n("Set &Away Globally"));
    actionCollection()->action("irc_colors")->setText(i18n("&IRC Color..."));
    actionCollection()->action("insert_character")->setText(i18n("Special &Character..."));
    actionCollection()->action("insert_marker_line")->setText(i18n("&Marker Line"));
    actionCollection()->action("open_channel_list")->setText(openChannelListString);
    actionCollection()->action("open_logfile")->setText(openLogFileString);
}

void KonversationMainWindow::openServerList()
{
    if (!m_serverListDialog)
    {
        m_serverListDialog = new Konversation::ServerListDialog(this);
        KonversationApplication* konvApp = static_cast<KonversationApplication*>(kapp);

        connect(m_serverListDialog, TQ_SIGNAL(serverGroupsChanged(const Konversation::ServerGroupSettings*)),
                konvApp, TQ_SIGNAL(serverGroupsChanged(const Konversation::ServerGroupSettings*)));
        connect(konvApp, TQ_SIGNAL(serverGroupsChanged(const Konversation::ServerGroupSettings*)),
                m_serverListDialog, TQ_SLOT(updateServerList()));
        connect(m_serverListDialog, TQ_SIGNAL(connectTo(Konversation::ConnectionFlag, int)),
                konvApp->getConnectionManager(), TQ_SLOT(connectTo(Konversation::ConnectionFlag, int)));
        connect(m_serverListDialog, TQ_SIGNAL(connectTo(Konversation::ConnectionFlag, ConnectionSettings&)),
                konvApp->getConnectionManager(), TQ_SLOT(connectTo(Konversation::ConnectionFlag, ConnectionSettings&)));
        connect(konvApp->getConnectionManager(), TQ_SIGNAL(closeServerList()), m_serverListDialog, TQ_SLOT(slotClose()));
    }

    m_serverListDialog->show();
}

void KonversationMainWindow::openQuickConnectDialog()
{
    emit showQuickConnectDialog();
}

// open the preferences dialog and show the watched nicknames page
void KonversationMainWindow::openNotify()
{
    openPrefsDialog();
    if (m_settingsDialog) m_settingsDialog->openWatchedNicknamesPage();
}

void KonversationMainWindow::openIdentitiesDialog()
{
    Konversation::IdentityDialog dlg(this);

    if (dlg.exec() == KDialog::Accepted)
    {
        if (m_serverListDialog)
            m_serverListDialog->updateServerList();
        m_viewContainer->updateViewEncoding(m_viewContainer->getFrontView());
    }
}

IdentityPtr KonversationMainWindow::editIdentity(IdentityPtr identity)
{
    IdentityPtr newIdentity;

    Konversation::IdentityDialog dlg(this);
    newIdentity = dlg.setCurrentIdentity(identity);

    if ((dlg.exec() == KDialog::Accepted) && m_serverListDialog)
    {
        m_serverListDialog->updateServerList();
        return newIdentity;
    }
    else
        return 0;
}

void KonversationMainWindow::openNotifications()
{
    #ifdef USE_KNOTIFY
    (void) KNotifyDialog::configure(this);
    #endif
}

void KonversationMainWindow::notifyAction(const TQString& serverName, const TQString& nick)
{
    KonversationApplication* konvApp = static_cast<KonversationApplication*>(kapp);
    Server* server = konvApp->getConnectionManager()->getServerByName(serverName);
    if (server) server->notifyAction(nick);
}

// TODO: Let an own class handle notify things
void KonversationMainWindow::setOnlineList(Server* notifyServer,const TQStringList& /*list*/, bool /*changed*/)
{
    emit nicksNowOnline(notifyServer);
    // FIXME  if (changed && nicksOnlinePanel) newText(nicksOnlinePanel, TQString(), true);
}

TQString KonversationMainWindow::currentURL(bool passNetwork)
{
    return m_viewContainer->currentViewURL(passNetwork);
}

TQString KonversationMainWindow::currentTitle()
{
    return m_viewContainer->currentViewTitle();
}

#include "konversationmainwindow.moc"
