/*
 * Copyright (C) 2003, 2004, 2005 Johnathan Burchill
 * <jkerrb@users.sourceforge.net>
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "kdar.h"

#include "kdardeclarations.h"

#include "controller.h"

#include "kdarview.h"
#include "kdarListViewItem.h"

#include <kaboutdata.h>
#include <kaboutdialog.h>
#include <kaccel.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kedittoolbar.h>
#include <khelpmenu.h>
#include <kkeydialog.h>
#include <klocale.h>
#include <kmenubar.h>
#include <kpopupmenu.h>
#include <kprinter.h>
#include <kstatusbar.h>

#include <qdragobject.h>
#include <qpaintdevicemetrics.h>
#include <qpainter.h>
#include <qpushbutton.h>

//auto_ptr
#include <memory>

kdarListViewItem *currentDirectory = 0;

bool libdarWorking( false );

//For expanding the tree list view
kdarListViewItem * myExpandChild;

kdar::kdar( controller * archiveController )
    : KMainWindow( 0, "kdar"),
      m_view( new kdarView( archiveController, this ) ),
      m_printer( 0 ),
      m_kdarCancel( 0 ),
      m_logWindowAction( 0 ),
      m_toolbarAction( 0 ),
      m_statusbarAction( 0 ),
      m_recentFilesAction( 0 ),
      contextPopupMenu( new KActionMenu( "What to you want to do?", this ) )
{
    // accept dnd
    setAcceptDrops( true );

    // tell the KMainWindow that this is indeed the main widget
    kdDebug() << "kdar::kdar(): calling setCentralWidget()" << endl;
    setCentralWidget( m_view );

    // then, setup our actions
    kdDebug() << "kdar::kdar(): calling setupActions()" << endl;
    setupActions();

    // and a status bar
    kdDebug() << "kdar::kdar(): calling statusBar()->show()" << endl;
    statusBar()->show();

    // apply the saved mainwindow settings, if any, and ask the mainwindow
    // to automatically save settings if changed: window size, toolbar
    // position, icon size, etc.
    kdDebug() << "kdar::kdar(): calling setAutoSaveSettings()" << endl;
    setAutoSaveSettings();

    kdDebug() << "kdar::kdar(): connecting dialog signals to slots..." << endl;
    connect( m_view->createDlg->configureCreationSettingsPushButton, SIGNAL( clicked() ), m_view, SLOT( slotConfigureCreationSettings() ) );
    //Connect the createDlg save profile button clicked() signal to its slot
    connect( m_view->createDlg->saveProfilePushButton, SIGNAL( clicked() ), m_view, SLOT( slotSaveCreationProfile() ) );
    //Connect the createDlg restore profile button clicked() signal to its
    //slot
    connect( m_view->createDlg->restoreProfilePushButton, SIGNAL( clicked() ), m_view, SLOT( slotRestoreCreationProfile() ) );
    //slot for exporting an equivalent dar command line.
    connect( m_view->createDlg->exportDarCommandButton, SIGNAL( clicked() ), m_view, SLOT( slotExportDarCreateCommand() ) );

    //Create Wizard dialog connections
    //Connect the createDlgWizard "configure" clicked() signal to its slot
    connect( m_view->createDlgWizard->configureCreationSettingsPushButton, SIGNAL( clicked() ), m_view, SLOT( slotConfigureCreationSettings() ) );
    //Connect the createDlgWizard save profile button clicked() signal to
    //its slot
    connect( m_view->createDlgWizard->saveProfilePushButton, SIGNAL( clicked() ), m_view, SLOT( slotSaveCreationProfile() ) );
    //Connect the createDlgWizard restore profile button clicked() signal to
    //its slot
    connect( m_view->createDlgWizard->restoreProfilePushButton, SIGNAL( clicked() ), m_view, SLOT( slotRestoreCreationProfile() ) );
    //slot for exporting an equivalent dar command line.
    connect( m_view->createDlgWizard->exportDarCommandButton, SIGNAL( clicked() ), m_view, SLOT( slotExportDarCreateCommand() ) );

    //Restore dialog connections
    //Connect the extractDlg "configure" clicked() signal to its slot
    connect( m_view->extractDlg->configureRestoreSettingsPushButton, SIGNAL( clicked() ), m_view, SLOT( slotConfigureRestoreSettings() ) );
    //Connect the extractDlg save profile button clicked() signal to its slot
    connect( m_view->extractDlg->saveProfilePushButton, SIGNAL( clicked() ), m_view, SLOT( slotSaveRestoreProfile() ) );
    //Connect the extractDlg restore profile button clicked() signal to its slot
    connect( m_view->extractDlg->restoreProfilePushButton, SIGNAL( clicked() ), m_view, SLOT( slotRestoreRestoreProfile() ) );
    //slot for exporting an equivalent dar command line.
    connect( m_view->extractDlg->exportDarCommandButton, SIGNAL( clicked() ), m_view, SLOT( slotExportDarRestoreCommand() ) );

    kdDebug() << "kdar::kdar(): finished connecting dialog signals to slots." << endl;
    kdDebug() << "kdar::kdar(): constructor all finished." << endl;

    //Read the global settings into the kdarView
    m_view->readProperties();
    //Use custom "about" dialog.
/*    menuBar()->removeItem( menuBar()->idAt( menuBar()->count() - 1 ) );
    menuBar()->insertItem( i18n( "&Help" ), customHelpMenu() );
    const KAboutData *aboutKdar = kapp->aboutData();
    m_aboutKDarDialog = new KAboutDialog( KAboutDialog::AbtAppStandard, i18n( "KDar" ), KDialogBase::Close, KDialogBase::Close,  this, "aboutKDarDialog" );
    m_aboutKDarDialog->setProduct( aboutKdar->programName(), "", aboutKdar->version(), "2003 - 2005, Johnathan K. Burchill" );
//    m_aboutKDarDialog->setAuthor( aboutKdar->authors() );
//    m_aboutKDarDialog->setLogo( aboutKdar->programLogo() );
//    (void) m_aboutKDarDialog->addTextPage( "Features", "None!" );
*/
}

kdar::~kdar()
{
    if ( m_view ) delete m_view;
}

void kdar::myquit()
{
    if ( m_view ) delete m_view;
    kapp->quit();
}

void kdar::setupActions()
{
    KStdAction::print( this, SLOT( filePrint() ), actionCollection(), "print" );
    KStdAction::quit( this, SLOT( myquit() ), actionCollection(), "quit" );

    m_logWindowAction = new KToggleAction( i18n( "Show &Log Window" ), "log", 0, this, SLOT( optionsShowLogWindow() ), actionCollection(), "show_logwindow" );
    m_toolbarAction = KStdAction::showToolbar( this, SLOT( optionsShowToolbar() ), actionCollection() );
    m_statusbarAction = KStdAction::showStatusbar( this, SLOT( optionsShowStatusbar() ), actionCollection() );
    m_recentFilesAction = KStdAction::openRecent( this, SLOT( slotArchiveChoose( const KURL & ) ), actionCollection(), "open_recent" );

    KStdAction::keyBindings( this, SLOT( optionsConfigureKeys() ), actionCollection() );
    KStdAction::configureToolbars( this, SLOT( optionsConfigureToolbars() ), actionCollection() );
    KStdAction::preferences( this, SLOT( optionsPreferences() ), actionCollection() );

    (void) new KAction( i18n( "&Open archive" ), "kdar", 0,
                                  m_view, SLOT( slotArchiveChoose() ),
                                  actionCollection(), "select_archive" );
    (void) new KAction( i18n( "&View" ), "kdar_view", 0,
                                  m_view, SLOT( slotArchiveList() ),
                                  actionCollection(), "list_archive" );
    (void) new KAction( i18n( "&Create" ), "kdar_create", 0,
                                  m_view, SLOT( slotArchiveCreate() ),
                                  actionCollection(), "create_archive" );
    KAction *kdarExtract( new KAction( i18n( "&Restore" ), "kdar_extract", 0,
                                  m_view, SLOT( slotArchiveExtract() ),
                                  actionCollection(), "extract_archive" ) );
    (void) new KAction( i18n( "&Isolate" ), "kdar_isolate", 0,
                                  m_view, SLOT( slotArchiveIsolate() ),
                                  actionCollection(), "isolate_archive" );
    KAction *kdarDiff( new KAction(i18n( "&Diff" ), "kdar_diff", 0,
                                  m_view, SLOT( slotArchiveDiff() ),
                                  actionCollection(), "diff_archive" ) );
    KAction *kdarTest( new KAction( i18n( "&Test" ), "kdar_test", 0,
                                  m_view, SLOT( slotArchiveTest() ),
                                  actionCollection(), "test_archive" ) );
    (void) new KAction( i18n( "Clear &Message Window" ), "eraser", 0, m_view, SLOT( slotClearMessages()), actionCollection(), "clear_messages" );
    m_kdarCancel = new KAction( i18n( "&Stop operation" ), "stop", 0, m_view, SLOT( cancelOperation() ), actionCollection(), "stop_operation" );
    m_kdarCancel->setEnabled( false );
    contextPopupMenu->insert(kdarExtract);
    contextPopupMenu->insert(kdarDiff);
    contextPopupMenu->insert(kdarTest);

    createGUI();
}

void kdar::addRecentURL( const KURL & name )
{
    m_recentFilesAction->addURL( name );
}

void kdar::removeRecentURL( const KURL & name )
{
    m_recentFilesAction->removeURL( name );
}

void kdar::restoreRecentURLEntries( KConfig * config )
{
    m_recentFilesAction->loadEntries( config );
}

void kdar::saveRecentURLEntries( KConfig * config )
{
    m_recentFilesAction->saveEntries( config );
}

void kdar::dragEnterEvent(QDragEnterEvent *event)
{
    // accept uri drops only
    kdDebug() << "kdar::dragEnterEvent reached." << endl;
    event->accept(QUriDrag::canDecode(event));
}

void kdar::filePrint()
{
    // this slot is called whenever the File->Print menu is selected,
    // the Print shortcut is pressed (usually CTRL+P) or the Print toolbar
    // button is clicked
    if (!m_printer) m_printer = new KPrinter;
    if ( m_printer->setup( this ) )
    {
        // setup the printer.  with Qt, you always "print" to a
        // QPainter.. whether the output medium is a pixmap, a screen,
        // or paper
        QPainter p;
        p.begin( m_printer );

        // we let our view do the actual printing
        QPaintDeviceMetrics metrics( m_printer );
        m_view->print( &p, m_printer, &metrics );

        // and send the result to the printer
        p.end();
    }
}

void kdar::optionsShowToolbar()
{
    // this is all very cut and paste code for showing/hiding the
    // toolbar
    if (m_toolbarAction->isChecked())
        toolBar()->show();
    else
        toolBar()->hide();
}

void kdar::optionsShowLogWindow()
{
    m_view->showLogWindow( m_logWindowAction->isChecked() );
}

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

void kdar::optionsConfigureKeys()
{
    KKeyDialog::configure(actionCollection());
}

void kdar::optionsConfigureToolbars()
{
    // use the standard toolbar editor
    saveMainWindowSettings( m_view->globalConfig(), autoSaveGroup() );
    KEditToolbar toolDlg(actionCollection());
    connect(&toolDlg, SIGNAL(newToolbarConfig()), this, SLOT(newToolbarConfig()));
    toolDlg.exec();
}

void kdar::newToolbarConfig()
{
    // this slot is called when user clicks "Ok" or "Apply" in the toolbar editor.
    // recreate our GUI, and re-apply the settings (e.g. "text under icons", etc.)
    createGUI();
    applyMainWindowSettings(m_view->globalConfig(), autoSaveGroup() );
}

void kdar::optionsPreferences()
{
    // popup some sort of preference dialog, here
    // We let kdarView handle this:
    m_view->optionsPreferences();
}

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

void kdar::changeCaption(const QString& text)
{
    // display the text on the caption
    setCaption(text);
}

/*void kdar::showAboutApplication()
{
    m_aboutKDarDialog->show();
}
*/

void kdar::popupContextMenu( const QPoint & point )
{
    contextPopupMenu->popup(point);
}

void kdar::slotArchiveChoose( const KURL & name )
{
    m_view->slotArchiveChoose( name );
}

void kdar::setCancelButtonState( bool state )
{
    if ( m_kdarCancel ) m_kdarCancel->setEnabled( state );
}

std::string kdar::toStdString( const QString & qstring )
{
    return qstring.ascii() ? qstring.ascii() : "";
}

#include "kdar.moc"
