/***************************************************************************
 *   Copyright (C) 2005-2007 by Rajko Albrecht                             *
 *   ral@alwins-world.de                                                   *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/


#include "tdesvn.h"
#include "urldlg.h"
#include "tdesvn_part.h"

#include <tqdragobject.h>
#include <kprinter.h>
#include <tqpainter.h>
#include <tqpaintdevicemetrics.h>
#include <tqcursor.h>

#include <tdeglobal.h>
#include <tdelocale.h>
#include <kiconloader.h>
#include <tdeversion.h>
#include <kstatusbar.h>
#include <tdeaccel.h>
#include <tdeio/netaccess.h>
#include <tdefiledialog.h>
#include <tdeconfig.h>
#include <kurl.h>
#include <kurldrag.h>
#include <kurlrequesterdlg.h>
#include <khelpmenu.h>
#include <tdemenubar.h>
#include <tdepopupmenu.h>
#include <tdeactionclasses.h>
#include <tdemessagebox.h>
#include <tdestdaccel.h>
#include <tdeaction.h>
#include <kstdaction.h>
#include <kstandarddirs.h>
#include <kbookmarkmanager.h>
#include <kbookmarkmenu.h>
#include <kdebug.h>
#include <klibloader.h>
#include <kedittoolbar.h>
#include <kkeydialog.h>
#include <kdirselectdialog.h>

#ifdef TESTING_RC
#include <kcrash.h>
#endif

tdesvn::tdesvn()
    : KParts::MainWindow( 0, "tdesvn" ),
      KBookmarkOwner()
{
    m_part = 0;
#ifdef TESTING_RC
    setXMLFile(TESTING_RC);
    kdDebug()<<"Using test rc file in " << TESTING_RC << endl;
    // I hate this crashhandler in development
    TDECrash::setCrashHandler(0);
#else
    setXMLFile("tdesvnui.rc");
#endif
    setStandardToolBarMenuEnabled(true);
    // then, setup our actions
    setupActions();
    // and a status bar
    statusBar()->show();

    m_bookmarkFile = locateLocal("appdata",TQString::fromLatin1("bookmarks.xml"),true);

    m_BookmarkManager = KBookmarkManager::managerForFile(m_bookmarkFile,false);
    m_BookmarkManager->setShowNSBookmarks(false);
    m_BookmarkManager->setEditorOptions(TQString::fromLatin1("KDE Svn"),false);

    m_BookmarksActionmenu = new TDEActionMenu(i18n("&Bookmarks"),"bookmark",actionCollection(),"bookmarks");
    m_BookmarksActionmenu->setDelayed(false);
    m_BookmarksActionmenu->setEnabled(true);

    m_Bookmarkactions = new TDEActionCollection( this );
    m_Bookmarkactions->setHighlightingEnabled( true );
    connectActionCollection( m_Bookmarkactions );

    m_pBookmarkMenu = new KBookmarkMenu(m_BookmarkManager,this,m_BookmarksActionmenu->popupMenu(),m_Bookmarkactions,true);
//    m_BookmarksActionmenu->plug(menuBar());
    // this routine will find and load our Part.  it finds the Part by
    // name which is a bad idea usually.. but it's alright in this
    // case since our Part is made for this Shell
    KLibFactory *factory = KLibLoader::self()->factory("tdesvnpart");

    if (factory)
    {
        if (TQCString(factory->className())!="cFactory") {
            kdDebug()<<"wrong factory"<<endl;
            KMessageBox::error(this, i18n("Could not find our part"));
            kapp->quit();
            return;
        }
        cFactory*cfa = static_cast<cFactory*>(factory);

        // now that the Part is loaded, we cast it to a Part to get
        // our hands on it
        m_part = static_cast<KParts::ReadOnlyPart *>(cfa->createAppPart(this,"tdesvn_part", this, "tdesvn_part", "KParts::ReadOnlyPart",TQStringList()));

        if (m_part)
        {
            // tell the KParts::MainWindow that this is indeed the main widget
            setCentralWidget(m_part->widget());

            TDEAction*tmpAction;
            tmpAction = new TDEAction(i18n("Create and open new repository"),"document-new",
                TDEShortcut(),m_part->widget(),TQ_SLOT(slotCreateRepo()),actionCollection(),"subversion_create_repo");
            tmpAction->setToolTip(i18n("Create and opens a new local subversion repository"));
            tmpAction = new TDEAction(i18n("Dump repository to file"),"document-new",
                TDEShortcut(),m_part->widget(),TQ_SLOT(slotDumpRepo()),actionCollection(),"subversion_dump_repo");
            tmpAction->setToolTip(i18n("Dump a subversion repository to a file"));
            tmpAction = new TDEAction(i18n("Hotcopy a repository"),"document-new",
                TDEShortcut(),m_part->widget(),TQ_SLOT(slotHotcopy()),actionCollection(),"subversion_hotcopy_repo");
            tmpAction->setToolTip(i18n("Hotcopy a subversion repository to a new folder"));
            tmpAction = new TDEAction(i18n("Load dump into repository"),"document-new",
                TDEShortcut(),m_part->widget(),TQ_SLOT(slotLoaddump()),actionCollection(),"subversion_load_repo");
            tmpAction->setToolTip(i18n("Load a dump file into a repository."));
            tmpAction = new TDEAction(i18n("Add ssh identities to ssh-agent"),"password",
                TDEShortcut(),m_part,TQ_SLOT(slotSshAdd()),actionCollection(),"tdesvn_ssh_add");
            tmpAction->setToolTip(i18n("Force add ssh-identities to ssh-agent for future use."));
            tmpAction = new TDEAction(i18n("Info about tdesvn part"), "tdesvn",
                        TDEShortcut(), m_part, TQ_SLOT(showAboutApplication()), actionCollection(), "help_about_tdesvnpart");
            tmpAction->setToolTip(i18n("Shows info about the tdesvn plugin not the standalone app."));

            /* enable tooltips in statusbar for menu */
            actionCollection()->setHighlightingEnabled(true);
            connectActionCollection(actionCollection());
            // and integrate the part's GUI with the shells
            createGUI(m_part);
            connectActionCollection(m_part->actionCollection());
        } else {
            KMessageBox::error(this, i18n("Could not load the part:\n")+KLibLoader::self()->lastErrorMessage());
            kapp->quit();
            return;
        }
    }
    else
    {
        // if we couldn't find our Part, we exit since the Shell by
        // itself can't do anything useful
        KMessageBox::error(this, i18n("Could not find our part")+TQString(":\n")+KLibLoader::self()->lastErrorMessage());
        kapp->quit();
        // we return here, cause kapp->quit() only means "exit the
        // next time we enter the event loop...
        return;
    }
    setAutoSaveSettings();
}

void tdesvn::connectActionCollection( TDEActionCollection *coll )
{
    if (!coll)return;
    connect( coll, TQ_SIGNAL( actionStatusText( const TQString & ) ),
             this, TQ_SLOT( changeStatusbar( const TQString & ) ) );
    connect( coll, TQ_SIGNAL( clearStatusText() ),
             this, TQ_SLOT( resetStatusBar() ) );
}

void tdesvn::disconnectActionCollection( TDEActionCollection *coll )
{
    if (!coll)return;
}

tdesvn::~tdesvn()
{
}

void tdesvn::loadRescent(const KURL& url)
{
    load(url,true);
}

void tdesvn::load(const KURL& url,bool addRescent)
{
    if (m_part) {
        bool ret = m_part->openURL(url);
        TDERecentFilesAction*rac = 0;
        if (addRescent) {
            TDEAction * ac = actionCollection()->action("file_open_recent");
            if (ac) {
                rac = (TDERecentFilesAction*)ac;
            }
        }
        if (!ret) {
            changeStatusbar(i18n("Could not open url %1").arg(url.prettyURL()));
            if (rac) {
                rac->removeURL(url);
            }
        } else {
            resetStatusBar();
            if (rac) {
                rac->addURL(url);
            }
        }
        if (rac) {
            rac->saveEntries(TDEGlobal::config(),"recent_files");
        }
    }
}

void tdesvn::setupActions()
{
    TDEAction*ac;
    KStdAction::open(this, TQ_SLOT(fileOpen()), actionCollection());
    KStdAction::openNew(this,TQ_SLOT(fileNew()),actionCollection());
    ac = KStdAction::close(this,TQ_SLOT(fileClose()),actionCollection());
    ac->setEnabled(getMemberList()->count()>1);
    KStdAction::quit(kapp, TQ_SLOT(quit()), actionCollection());

    TDERecentFilesAction*rac = KStdAction::openRecent(this,TQ_SLOT(loadRescent(const KURL&)),actionCollection());
    if (rac)
    {
        rac->setMaxItems(8);
        rac->loadEntries(TDEGlobal::config(),"recent_files");
        rac->setText(i18n("Recent opened URLs"));
    }

    KStdAction::keyBindings(this, TQ_SLOT(optionsConfigureKeys()), actionCollection());
    KStdAction::configureToolbars(this, TQ_SLOT(optionsConfigureToolbars()), actionCollection());

    m_statusbarAction = KStdAction::showStatusbar(this, TQ_SLOT(optionsShowStatusbar()), actionCollection());

    TDEToggleAction *toggletemp;
    toggletemp = new TDEToggleAction(i18n("Load last opened URL on start"),TDEShortcut(),
            actionCollection(),"toggle_load_last_url");
    toggletemp->setToolTip(i18n("Reload last opened url if no one is given on commandline"));
    TDEConfigGroup cs(TDEGlobal::config(),"startup");
    toggletemp->setChecked(cs.readBoolEntry("load_last_on_start",false));
    connect(toggletemp,TQ_SIGNAL(toggled(bool)),this,TQ_SLOT(slotLoadLast(bool)));
}

void tdesvn::optionsShowStatusbar()
{
    // this is all very cut and paste code for showing/hiding the
    // statusbar
    if (m_statusbarAction->isChecked())
        statusBar()->show();
    else
        statusBar()->hide();
}

void tdesvn::fileClose()
{
    if (m_part) m_part->closeURL();
    if (getMemberList()->count()>1) {
        close();
    } else {
        enableClose(false);
    }
}

void tdesvn::saveProperties(TDEConfig *config)
{
    // the 'config' object points to the session managed
    // config file.  anything you write here will be available
    // later when this app is restored
    if (!m_part) return;
    if (!m_part->url().isEmpty()) {
#if KDE_IS_VERSION(3,1,3)
        config->writePathEntry("lastURL", m_part->url().prettyURL());
#else
        config->writeEntry("lastURL", m_part->url().prettyURL());
#endif
    }
}

void tdesvn::readProperties(TDEConfig *config)
{
    // the 'config' object points to the session managed
    // config file.  this function is automatically called whenever
    // the app is being restored.  read in here whatever you wrote
    // in 'saveProperties'

    TQString url = config->readPathEntry("lastURL");

    if (!url.isEmpty() && m_part)
        m_part->openURL(KURL(url));
}

void tdesvn::fileNew()
{
    // this slot is called whenever the File->New menu is selected,
    // the New shortcut is pressed (usually CTRL+N) or the New toolbar
    // button is clicked

    // create a new window
    (new tdesvn)->show();
    enableClose(true);
}

void tdesvn::fileOpen()
{
    KURL url = UrlDlg::getURL(this);
    if (!url.isEmpty())
        load(url,true);
}

void tdesvn::changeStatusbar(const TQString& text)
{
    // display the text on the statusbar
    statusBar()->message(text);
}

void tdesvn::resetStatusBar()
{
    statusBar()->message(i18n("Ready"));
}

void tdesvn::openBookmarkURL (const TQString &_url)
{
    if (!_url.isEmpty() && m_part)
        load(_url,false);
}

TQString tdesvn::currentURL () const
{
    if (!m_part) return "";
    return m_part->url().prettyURL();
}

void tdesvn::enableClose(bool how)
{
    TDEAction * ac;
    if ( (ac=actionCollection()->action("file_close"))) {
        ac->setEnabled(how);
    }
}

/*!
    \fn tdesvn::slotUrlOpened(bool)
 */
void tdesvn::slotUrlOpened(bool how)
{
    enableClose(how);
}


/*!
    \fn tdesvn::optionsConfigureToolbars()
 */
void tdesvn::optionsConfigureToolbars()
{
#if defined(TDE_MAKE_VERSION)
# if TDE_VERSION >= TDE_MAKE_VERSION(3,1,0)
    saveMainWindowSettings(TDEGlobal::config(), autoSaveGroup());
# else
    saveMainWindowSettings(TDEGlobal::config() );
# endif
#else
    saveMainWindowSettings(TDEGlobal::config() );
#endif

    // use the standard toolbar editor
    KEditToolbar dlg(factory());
    connect(&dlg, TQ_SIGNAL(newToolbarConfig()),
            this, TQ_SLOT(applyNewToolbarConfig()));
    dlg.exec();
}


/*!
    \fn tdesvn::applyNewToolbarConfig()
 */
void tdesvn::applyNewToolbarConfig()
{
#if defined(TDE_MAKE_VERSION)
# if TDE_VERSION >= TDE_MAKE_VERSION(3,1,0)
    applyMainWindowSettings(TDEGlobal::config(), autoSaveGroup());
# else
    applyMainWindowSettings(tdesvnPart::config());
# endif
#else
    applyMainWindowSettings(tdesvnPart::config());
#endif
}

void tdesvn::optionsConfigureKeys()
{
    KKeyDialog kdlg(true,m_part->widget());
    kdlg.insert(actionCollection());
    kdlg.insert(m_part->actionCollection());
    bool b = kdlg.configure(true);
    if (b) {
        kdlg.commitChanges();
    }
}


/*!
    \fn tdesvn::queryExit()
 */
bool tdesvn::queryExit()
{
    if (m_part) {
        TDEConfigGroup cs(TDEGlobal::config(),"startup");
#if KDE_IS_VERSION(3,1,3)
        cs.writePathEntry("lastURL", m_part->url().prettyURL());
#else
        cs.writeEntry("lastURL", m_part->url().prettyURL());
#endif
    }
    return KParts::MainWindow::queryExit();
}


/*!
    \fn tdesvn::checkReload()
 */
void tdesvn::checkReload()
{
    TDEConfigGroup cs(TDEGlobal::config(),"startup");
    if (!cs.readBoolEntry("load_last_on_start",false))
        return;

    TQString url = cs.readPathEntry("lastURL");

    if (!url.isEmpty() && m_part)
        load(KURL(url),false);
}


/*!
    \fn tdesvn::slotLoadLast(bool)
 */
void tdesvn::slotLoadLast(bool how)
{
    TDEConfigGroup cs(TDEGlobal::config(),"startup");
    cs.writeEntry("load_last_on_start",how);
}

#include "tdesvn.moc"
