/* ============================================================
 *
 * This file is a part of digiKam project
 * http://www.digikam.org
 *
 * Date        : 2002-16-10
 * Description : main digiKam interface implementation
 *
 * Copyright (C) 2002-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
 * Copyright (C)      2006 by Tom Albers <tomalbers@kde.nl>
 * Copyright (C) 2002-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
 *
 * 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, 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.
 *
 * ============================================================ */

// TQt includes.

#include <tqdatastream.h>
#include <tqlabel.h>
#include <tqstringlist.h>
#include <tqtooltip.h>
#include <tqwhatsthis.h>
#include <tqsignalmapper.h>
#include <tqdockarea.h>
#include <tqhbox.h>

// KDE includes.

#include <tdeaboutdata.h>
#include <tdelocale.h>
#include <kstandarddirs.h>
#include <kurl.h>
#include <kstdaction.h>
#include <tdestdaccel.h>
#include <kkeydialog.h>
#include <kedittoolbar.h>
#include <kiconloader.h>
#include <ktip.h>
#include <tdeversion.h>
#include <tdeapplication.h>
#include <tdemenubar.h>
#include <tdeglobalsettings.h>
#include <tdefiledialog.h>
#include <tdemessagebox.h>
#include <twin.h>
#include <kimageio.h>
#include <dcopref.h>

// libKipi includes.

#include <libkipi/plugin.h>

// LibKDcraw includes.

#include <libkdcraw/version.h>
#include <libkdcraw/kdcraw.h>

#if KDCRAW_VERSION < 0x000106
#include <libkdcraw/dcrawbinary.h>
#endif

// Local includes.

#include "ddebug.h"
#include "dlogoaction.h"
#include "album.h"
#include "albumlister.h"
#include "albumthumbnailloader.h"
#include "albumiconviewfilter.h"
#include "cameratype.h"
#include "cameraui.h"
#include "setup.h"
#include "setupplugins.h"
#include "setupeditor.h"
#include "setupicc.h"
#include "rawcameradlg.h"
#include "lighttablewindow.h"
#include "imagewindow.h"
#include "imageinfo.h"
#include "thumbnailsize.h"
#include "themeengine.h"
#include "scanlib.h"
#include "loadingcacheinterface.h"
#include "imageattributeswatch.h"
#include "batchthumbsgenerator.h"
#include "batchalbumssyncmetadata.h"
#include "dcopiface.h"
#include "digikamappprivate.h"
#include "digikamapp.h"
#include "digikamapp.moc"

using TDEIO::Job;
using TDEIO::UDSEntryList;
using TDEIO::UDSEntry;

namespace Digikam
{

DigikamApp* DigikamApp::m_instance = 0;

DigikamApp::DigikamApp()
          : TDEMainWindow( 0, "Digikam" )
{
    d = new DigikamAppPriv;
    m_instance = this;
    d->config  = kapp->config();
    d->config->setGroup("General Settings");

    if(d->config->readBoolEntry("Show Splash", true) &&
       !kapp->isRestored())
    {
        d->splashScreen = new SplashScreen("digikam-splash.png");
        d->splashScreen->show();
    }

    if(d->splashScreen)
        d->splashScreen->message(i18n("Initializing..."));

    // Register image formats (especially for TIFF )
    KImageIO::registerFormats();

    d->albumSettings = new AlbumSettings();
    d->albumSettings->readSettings();

    d->albumManager = new Digikam::AlbumManager();

    AlbumLister::instance();

    d->cameraMediaList = new TDEPopupMenu;

    connect(d->cameraMediaList, TQ_SIGNAL( aboutToShow() ),
            this, TQ_SLOT(slotCameraMediaMenu()));

    d->cameraList = new CameraList(this, locateLocal("appdata", "cameras.xml"));

    connect(d->cameraList, TQ_SIGNAL(signalCameraAdded(CameraType *)),
            this, TQ_SLOT(slotCameraAdded(CameraType *)));

    connect(d->cameraList, TQ_SIGNAL(signalCameraRemoved(CameraType *)),
            this, TQ_SLOT(slotCameraRemoved(CameraType *)));

    setupView();
    setupStatusBar();
    setupAccelerators();
    setupActions();

    applyMainWindowSettings(d->config);

    // Check ICC profiles repository availability

    if(d->splashScreen)
        d->splashScreen->message(i18n("Checking ICC repository"));

    d->validIccPath = SetupICC::iccRepositoryIsValid();

#if KDCRAW_VERSION < 0x000106
    // Check witch dcraw version available

    if(d->splashScreen)
        d->splashScreen->message(i18n("Checking dcraw version"));

    KDcrawIface::DcrawBinary::instance()->checkSystem();
#endif

    if(d->splashScreen)
        d->splashScreen->message(i18n("Scan Albums"));

    d->albumManager->setLibraryPath(d->albumSettings->getAlbumLibraryPath(), d->splashScreen);

    // Read albums from database
    if(d->splashScreen)
        d->splashScreen->message(i18n("Reading database"));

    d->albumManager->startScan();

    // Load KIPI Plugins.
    loadPlugins();

    // Load Themes
    populateThemes();

    setAutoSaveSettings();

    d->dcopIface = new DCOPIface(this, "camera");

    connect(d->dcopIface, TQ_SIGNAL(signalCameraAutoDetect()),
            this, TQ_SLOT(slotDcopCameraAutoDetect()));

    connect(d->dcopIface, TQ_SIGNAL(signalDownloadImages( const TQString & )),
            this, TQ_SLOT(slotDcopDownloadImages(const TQString &)));
}

DigikamApp::~DigikamApp()
{
    ImageAttributesWatch::shutDown();

    // Close and delete image editor instance.

    if (ImageWindow::imagewindowCreated())
        ImageWindow::imagewindow()->close(true);

    // Close and delete light table instance.

    if (LightTableWindow::lightTableWindowCreated())
        LightTableWindow::lightTableWindow()->close(true);

    if (d->view)
        delete d->view;

    d->albumIconViewFilter->saveSettings();
    d->albumSettings->setRecurseAlbums(d->recurseAlbumsAction->isChecked());
    d->albumSettings->setRecurseTags(d->recurseTagsAction->isChecked());
    d->albumSettings->saveSettings();
    delete d->albumSettings;

    delete d->albumManager;
    delete AlbumLister::instance();

    ImageAttributesWatch::cleanUp();
    LoadingCacheInterface::cleanUp();
#if KDCRAW_VERSION < 0x000106
    KDcrawIface::DcrawBinary::cleanUp();
#endif
    AlbumThumbnailLoader::cleanUp();

    m_instance = 0;

    delete d;
}

DigikamApp* DigikamApp::getinstance()
{
    return m_instance;
}

void DigikamApp::show()
{
    // Remove Splashscreen.

    if(d->splashScreen)
    {
        d->splashScreen->finish(this);
        delete d->splashScreen;
        d->splashScreen = 0;
    }

    // Display application window.

    TDEMainWindow::show();

    // Report errors from ICC repository path.

    if(!d->validIccPath)
    {
        TQString message = i18n("<qt><p>ICC profiles path seems to be invalid.</p>"
                               "<p>If you want to set it now, select \"Yes\", otherwise "
                               "select \"No\". In this case, \"Color Management\" feature "
                               "will be disabled until you solve this issue</p></qt>");

        if (KMessageBox::warningYesNo(this, message) == KMessageBox::Yes)
        {
            if (!setup(true))
            {
                d->config->setGroup("Color Management");
                d->config->writeEntry("EnableCM", false);
                d->config->sync();
            }
        }
        else
        {
            d->config->setGroup("Color Management");
            d->config->writeEntry("EnableCM", false);
            d->config->sync();
        }
    }

#if KDCRAW_VERSION < 0x000106
    // Report errors from dcraw detection.
    KDcrawIface::DcrawBinary::instance()->checkReport();
#endif

    // Init album icon view zoom factor.
    slotThumbSizeChanged(d->albumSettings->getDefaultIconSize());
}

const TQPtrList<TDEAction>& DigikamApp::menuImageActions()
{
    return d->kipiImageActions;
}

const TQPtrList<TDEAction>& DigikamApp::menuBatchActions()
{
    return d->kipiBatchActions;
}

const TQPtrList<TDEAction>& DigikamApp::menuAlbumActions()
{
    return d->kipiAlbumActions;
}

const TQPtrList<TDEAction> DigikamApp::menuImportActions()
{
    TQPtrList<TDEAction> importMenu;
    importMenu = d->kipiFileActionsImport;
    importMenu.append( d->albumImportAction );
    importMenu.append( d->addImagesAction );
    return importMenu;
}

const TQPtrList<TDEAction> DigikamApp::menuExportActions()
{
    return d->kipiFileActionsExport;
}

void DigikamApp::autoDetect()
{
    // Called from main if command line option is set

    if(d->splashScreen)
        d->splashScreen->message(i18n("Auto-detect camera"));

    TQTimer::singleShot(0, this, TQ_SLOT(slotCameraAutoDetect()));
}

void DigikamApp::downloadFrom(const TQString &cameraGuiPath)
{
    // Called from main if command line option is set

    if (!cameraGuiPath.isNull())
    {
        d->cameraGuiPath = cameraGuiPath;

        if(d->splashScreen)
            d->splashScreen->message(i18n("Opening Download Dialog"));

        TQTimer::singleShot(0, this, TQ_SLOT(slotDownloadImages()));
    }
}

bool DigikamApp::queryClose()
{
    if (ImageWindow::imagewindowCreated())
    {
        return ImageWindow::imagewindow()->queryClose();
    }
    else
        return true;
}

void DigikamApp::setupView()
{
    if(d->splashScreen)
        d->splashScreen->message(i18n("Initializing Main View"));

    d->view = new DigikamView(this);
    setCentralWidget(d->view);
    d->view->applySettings();

    connect(d->view, TQ_SIGNAL(signalAlbumSelected(bool)),
            this, TQ_SLOT(slotAlbumSelected(bool)));

    connect(d->view, TQ_SIGNAL(signalTagSelected(bool)),
            this, TQ_SLOT(slotTagSelected(bool)));

    connect(d->view, TQ_SIGNAL(signalImageSelected(const TQPtrList<ImageInfo>&, bool, bool, const KURL::List&)),
            this, TQ_SLOT(slotImageSelected(const TQPtrList<ImageInfo>&, bool, bool, const KURL::List&)));
}

void DigikamApp::setupStatusBar()
{
    d->statusProgressBar = new StatusProgressBar(statusBar());
    d->statusProgressBar->setAlignment(TQt::AlignLeft|TQt::AlignVCenter);
    d->statusProgressBar->setMaximumHeight(fontMetrics().height()+4);
    statusBar()->addWidget(d->statusProgressBar, 100, true);

    //------------------------------------------------------------------------------

    d->albumIconViewFilter = new AlbumIconViewFilter(statusBar());
    d->albumIconViewFilter->setMaximumHeight(fontMetrics().height()+4);
    statusBar()->addWidget(d->albumIconViewFilter, 100, true);

    //------------------------------------------------------------------------------

    d->statusZoomBar = new StatusZoomBar(statusBar());
    d->statusZoomBar->setMaximumHeight(fontMetrics().height()+4);
    statusBar()->addWidget(d->statusZoomBar, 1, true);

    //------------------------------------------------------------------------------

    d->statusNavigateBar = new StatusNavigateBar(statusBar());
    d->statusNavigateBar->setMaximumHeight(fontMetrics().height()+4);
    statusBar()->addWidget(d->statusNavigateBar, 1, true);

    //------------------------------------------------------------------------------

    connect(d->statusZoomBar, TQ_SIGNAL(signalZoomMinusClicked()),
            d->view, TQ_SLOT(slotZoomOut()));

    connect(d->statusZoomBar, TQ_SIGNAL(signalZoomPlusClicked()),
            d->view, TQ_SLOT(slotZoomIn()));

    connect(d->statusZoomBar, TQ_SIGNAL(signalZoomSliderChanged(int)),
            this, TQ_SLOT(slotZoomSliderChanged(int)));

    connect(d->view, TQ_SIGNAL(signalThumbSizeChanged(int)),
            this, TQ_SLOT(slotThumbSizeChanged(int)));

    connect(d->view, TQ_SIGNAL(signalZoomChanged(double, int)),
            this, TQ_SLOT(slotZoomChanged(double, int)));

    connect(d->view, TQ_SIGNAL(signalTogglePreview(bool)),
            this, TQ_SLOT(slotTogglePreview(bool)));

    connect(d->albumIconViewFilter, TQ_SIGNAL(signalResetTagFilters()),
            this, TQ_SIGNAL(signalResetTagFilters()));

    connect(d->statusNavigateBar, TQ_SIGNAL(signalFirstItem()),
            d->view, TQ_SLOT(slotFirstItem()));

    connect(d->statusNavigateBar, TQ_SIGNAL(signalNextItem()),
            d->view, TQ_SLOT(slotNextItem()));

    connect(d->statusNavigateBar, TQ_SIGNAL(signalPrevItem()),
            d->view, TQ_SLOT(slotPrevItem()));

    connect(d->statusNavigateBar, TQ_SIGNAL(signalLastItem()),
            d->view, TQ_SLOT(slotLastItem()));

    connect(d->statusProgressBar, TQ_SIGNAL(signalCancelButtonPressed()),
            this, TQ_SIGNAL(signalCancelButtonPressed()));
}

void DigikamApp::setupAccelerators()
{
    d->accelerators = new TDEAccel(this);

    d->accelerators->insert("Exit Preview Mode", i18n("Exit Preview"),
                           i18n("Exit preview mode"),
                           Key_Escape, this, TQ_SIGNAL(signalEscapePressed()),
                           false, true);

    d->accelerators->insert("Next Image Key_Space", i18n("Next Image"),
                           i18n("Next Image"),
                           Key_Space, this, TQ_SIGNAL(signalNextItem()),
                           false, true);

    d->accelerators->insert("Previous Image SHIFT+Key_Space", i18n("Previous Image"),
                           i18n("Previous Image"),
                           SHIFT+Key_Space, this, TQ_SIGNAL(signalPrevItem()),
                           false, true);

    d->accelerators->insert("Previous Image Key_Backspace", i18n("Previous Image"),
                           i18n("Previous Image"),
                           Key_Backspace, this, TQ_SIGNAL(signalPrevItem()),
                           false, true);

    d->accelerators->insert("Next Image Key_Next", i18n("Next Image"),
                           i18n("Next Image"),
                           Key_Next, this, TQ_SIGNAL(signalNextItem()),
                           false, true);

    d->accelerators->insert("Previous Image Key_Prior", i18n("Previous Image"),
                           i18n("Previous Image"),
                           Key_Prior, this, TQ_SIGNAL(signalPrevItem()),
                           false, true);

    d->accelerators->insert("First Image Key_Home", i18n("First Image"),
                           i18n("First Image"),
                           Key_Home, this, TQ_SIGNAL(signalFirstItem()),
                           false, true);

    d->accelerators->insert("Last Image Key_End", i18n("Last Image"),
                           i18n("Last Image"),
                           Key_End, this, TQ_SIGNAL(signalLastItem()),
                           false, true);

    d->accelerators->insert("Copy Album Items Selection CTRL+Key_C", i18n("Copy Album Items Selection"),
                           i18n("Copy Album Items Selection"),
                           CTRL+Key_C, this, TQ_SIGNAL(signalCopyAlbumItemsSelection()),
                           false, true);

    d->accelerators->insert("Paste Album Items Selection CTRL+Key_V", i18n("Paste Album Items Selection"),
                           i18n("Paste Album Items Selection"),
                           CTRL+Key_V, this, TQ_SIGNAL(signalPasteAlbumItemsSelection()),
                           false, true);
}

void DigikamApp::setupActions()
{
    // -----------------------------------------------------------------

    d->cameraMenuAction = new TDEActionMenu(i18n("&Camera"),
                                    "digitalcam",
                                    actionCollection(),
                                    "camera_menu");
    d->cameraMenuAction->setDelayed(false);

    // -----------------------------------------------------------------

    d->themeMenuAction = new TDESelectAction(i18n("&Themes"), 0, actionCollection(), "theme_menu");
    connect(d->themeMenuAction, TQ_SIGNAL(activated(const TQString&)),
            this, TQ_SLOT(slotChangeTheme(const TQString&)));

    connect(ThemeEngine::instance(), TQ_SIGNAL(signalThemeChanged()),
            this, TQ_SLOT(slotThemeChanged()));

    // -----------------------------------------------------------------

    d->backwardActionMenu = new TDEToolBarPopupAction(i18n("&Back"),
                                    "back",
                                    ALT+Key_Left,
                                    d->view,
                                    TQ_SLOT(slotAlbumHistoryBack()),
                                    actionCollection(),
                                    "album_back");
    d->backwardActionMenu->setEnabled(false);

    connect(d->backwardActionMenu->popupMenu(), TQ_SIGNAL(aboutToShow()),
            this, TQ_SLOT(slotAboutToShowBackwardMenu()));

    connect(d->backwardActionMenu->popupMenu(), TQ_SIGNAL(activated(int)),
            d->view, TQ_SLOT(slotAlbumHistoryBack(int)));

    d->forwardActionMenu = new  TDEToolBarPopupAction(i18n("Forward"),
                                    "forward",
                                    ALT+Key_Right,
                                    d->view,
                                    TQ_SLOT(slotAlbumHistoryForward()),
                                    actionCollection(),
                                    "album_forward");
    d->forwardActionMenu->setEnabled(false);

    connect(d->forwardActionMenu->popupMenu(), TQ_SIGNAL(aboutToShow()),
            this, TQ_SLOT(slotAboutToShowForwardMenu()));

    connect(d->forwardActionMenu->popupMenu(), TQ_SIGNAL(activated(int)),
            d->view, TQ_SLOT(slotAlbumHistoryForward(int)));

    d->newAction = new TDEAction(i18n("&New..."),
                                   "albumfolder-new",
                                   TDEStdAccel::shortcut(TDEStdAccel::New),
                                   d->view,
                                   TQ_SLOT(slotNewAlbum()),
                                   actionCollection(),
                                   "album_new");
    d->newAction->setWhatsThis(i18n("Creates a new empty Album in the database."));

    d->albumSortAction = new TDESelectAction(i18n("&Sort Albums"),
                                    0,
                                    0,
                                    actionCollection(),
                                    "album_sort");

    connect(d->albumSortAction, TQ_SIGNAL(activated(int)),
            d->view, TQ_SLOT(slotSortAlbums(int)));

    // Use same list order as in albumsettings enum
    TQStringList sortActionList;
    sortActionList.append(i18n("By Folder"));
    sortActionList.append(i18n("By Collection"));
    sortActionList.append(i18n("By Date"));
    d->albumSortAction->setItems(sortActionList);

    d->recurseAlbumsAction = new TDEToggleAction(i18n("Include Album Sub-Tree"),
                                               0,
                                               this,
                                               0,
                                               actionCollection(),
                                               "albums_recursive");
    d->recurseAlbumsAction->setWhatsThis(i18n("Activate this option to recursively show all sub-albums below "
                                              "the current album."));

    connect(d->recurseAlbumsAction, TQ_SIGNAL(toggled(bool)),
            this, TQ_SLOT(slotRecurseAlbums(bool)));

    d->recurseTagsAction = new TDEToggleAction(i18n("Include Tag Sub-Tree"),
                                             0,
                                             this,
                                             0,
                                             actionCollection(),
                                             "tags_recursive");
    d->recurseTagsAction->setWhatsThis(i18n("Activate this option to show all images marked by the given tag "
                                            "and its all its sub-tags."));

    connect(d->recurseTagsAction, TQ_SIGNAL(toggled(bool)),
            this, TQ_SLOT(slotRecurseTags(bool)));

    d->deleteAction = new TDEAction(i18n("Delete"),
                                    "edit-delete",
                                    0,
                                    d->view,
                                    TQ_SLOT(slotDeleteAlbum()),
                                    actionCollection(),
                                    "album_delete");

    d->addImagesAction = new TDEAction( i18n("Add Images..."),
                                    "albumfolder-importimages",
                                    CTRL+Key_I,
                                    this,
                                    TQ_SLOT(slotAlbumAddImages()),
                                    actionCollection(),
                                    "album_addImages");
    d->addImagesAction->setWhatsThis(i18n("Adds new items to the current Album."));

    d->albumImportAction = new TDEAction( i18n("Add Folders..."),
                                    "albumfolder-importdir",
                                    0,
                                    d->view,
                                    TQ_SLOT(slotAlbumImportFolder()),
                                    actionCollection(),
                                    "album_importFolder");

    d->propsEditAction = new TDEAction( i18n("Properties..."),
                                    "albumfolder-properties",
                                    0,
                                    d->view,
                                    TQ_SLOT(slotAlbumPropsEdit()),
                                    actionCollection(),
                                    "album_propsEdit");
    d->propsEditAction->setWhatsThis(i18n("Edit Album Properties and Collection information."));

    d->refreshAlbumAction = new TDEAction( i18n("Refresh"),
                                    "rebuild",
                                    Key_F5,
                                    d->view,
                                    TQ_SLOT(slotAlbumRefresh()),
                                    actionCollection(),
                                    "album_refresh");
    d->refreshAlbumAction->setWhatsThis(i18n("Refresh all album contents"));

    d->syncAlbumMetadataAction = new TDEAction( i18n("Synchronize Images with Database"),
                                    "rebuild",
                                    0,
                                    d->view,
                                    TQ_SLOT(slotAlbumSyncPicturesMetadata()),
                                    actionCollection(),
                                    "album_syncmetadata");
    d->syncAlbumMetadataAction->setWhatsThis(i18n("Updates all image metadata of the current "
                                                  "album with the contents of the digiKam database "
                                                  "(image metadata will be over-written with data from the database)."));

    d->openInKonquiAction = new TDEAction( i18n("Open in File Manager"),
                                    "konqueror",
                                    0,
                                    d->view,
                                    TQ_SLOT(slotAlbumOpenInKonqui()),
                                    actionCollection(),
                                    "album_openinkonqui");

    // -----------------------------------------------------------

    d->newTagAction = new TDEAction(i18n("New &Tag..."), "tag-new",
                                0, d->view, TQ_SLOT(slotNewTag()),
                                actionCollection(), "tag_new");

    d->editTagAction = new TDEAction(i18n("Edit Tag Properties..."), "tag-properties",
                                 0, d->view, TQ_SLOT(slotEditTag()),
                                 actionCollection(), "tag_edit");

    d->deleteTagAction = new TDEAction(i18n("Delete Tag"), "tag-delete",
                                   0, d->view, TQ_SLOT(slotDeleteTag()),
                                   actionCollection(), "tag_delete");

    // -----------------------------------------------------------

    d->imagePreviewAction = new TDEToggleAction(i18n("View..."),
                                    "viewimage",
                                    Key_F3,
                                    d->view,
                                    TQ_SLOT(slotImagePreview()),
                                    actionCollection(),
                                    "image_view");

    d->imageViewAction = new TDEAction(i18n("Edit..."),
                                    "editimage",
                                    Key_F4,
                                    d->view,
                                    TQ_SLOT(slotImageEdit()),
                                    actionCollection(),
                                    "image_edit");
    d->imageViewAction->setWhatsThis(i18n("Open the selected item in the image editor."));

    d->imageLightTableAction = new TDEAction(i18n("Place onto Light Table"),
                                    "lighttable",
                                    CTRL+Key_L,
                                    d->view,
                                    TQ_SLOT(slotImageLightTable()),
                                    actionCollection(),
                                    "image_lighttable");
    d->imageLightTableAction->setWhatsThis(i18n("Place the selected items on the light table thumbbar."));

    d->imageAddLightTableAction = new TDEAction(i18n("Add to Light Table"),
                                    "lighttableadd",
                                    SHIFT+CTRL+Key_L,
                                    d->view,
                                    TQ_SLOT(slotImageAddToLightTable()),
                                    actionCollection(),
                                    "image_add_to_lighttable");
    d->imageAddLightTableAction->setWhatsThis(i18n("Add selected items to the light table thumbbar."));

    d->imageRenameAction = new TDEAction(i18n("Rename..."),
                                    "pencil",
                                    Key_F2,
                                    d->view,
                                    TQ_SLOT(slotImageRename()),
                                    actionCollection(),
                                    "image_rename");
    d->imageRenameAction->setWhatsThis(i18n("Change the filename of the currently selected item."));

    // Pop up dialog to ask user whether to move to trash
    d->imageDeleteAction            = new TDEAction(i18n("Delete"),
                                                "edittrash",
                                                Key_Delete,
                                                d->view,
                                                TQ_SLOT(slotImageDelete()),
                                                actionCollection(),
                                                "image_delete");

    // Pop up dialog to ask user whether to permanently delete
    d->imageDeletePermanentlyAction = new TDEAction(i18n("Delete permanently"),
                                                "edit-delete",
                                                SHIFT+Key_Delete,
                                                d->view,
                                                TQ_SLOT(slotImageDeletePermanently()),
                                                actionCollection(),
                                                "image_delete_permanently");

    // These two actions are hidden, no menu entry, no toolbar entry, no shortcut.
    // Power users may add them.
    d->imageDeletePermanentlyDirectlyAction = new TDEAction(i18n("Delete permanently without confirmation"),
                                                        "edit-delete",
                                                        0,
                                                        d->view,
                                                        TQ_SLOT(slotImageDeletePermanentlyDirectly()),
                                                        actionCollection(),
                                                        "image_delete_permanently_directly");

    d->imageTrashDirectlyAction = new TDEAction(i18n("Move to trash without confirmation"),
                                              "edittrash",
                                               0,
                                               d->view,
                                               TQ_SLOT(slotImageTrashDirectly()),
                                               actionCollection(),
                                               "image_trash_directly");

    d->imageSortAction = new TDESelectAction(i18n("&Sort Images"),
                                           0,
                                           0,
                                           actionCollection(),
                                           "image_sort");

    connect(d->imageSortAction, TQ_SIGNAL(activated(int)),
            d->view, TQ_SLOT(slotSortImages(int)));

    // Use same list order as in albumsettings enum
    TQStringList sortImagesActionList;
    sortImagesActionList.append(i18n("By Name"));
    sortImagesActionList.append(i18n("By Path"));
    sortImagesActionList.append(i18n("By Date"));
    sortImagesActionList.append(i18n("By File Size"));
    sortImagesActionList.append(i18n("By Rating"));
    d->imageSortAction->setItems(sortImagesActionList);

    // -----------------------------------------------------------------

    TQSignalMapper *exifOrientationMapper = new TQSignalMapper( d->view );

    connect(exifOrientationMapper, TQ_SIGNAL(mapped(int) ),
            d->view, TQ_SLOT(slotImageExifOrientation(int)));

    d->imageExifOrientationActionMenu = new TDEActionMenu(i18n("Adjust Exif orientation tag"),
                                                        actionCollection(),
                                                        "image_set_exif_orientation");
    d->imageExifOrientationActionMenu->setDelayed(false);

    d->imageSetExifOrientation1Action = new TDEAction(i18n("Normal"),
             0,
             d->imageExifOrientationActionMenu,
             0,
             actionCollection(),
             "image_set_exif_orientation_normal");
    d->imageSetExifOrientation2Action = new TDEAction(i18n("Flipped Horizontally"),
             0,
             d->imageExifOrientationActionMenu,
             0,
             actionCollection(),
             "image_set_exif_orientation_flipped_horizontal");
    d->imageSetExifOrientation3Action = new TDEAction(i18n("Rotated Upside Down"),
             0,
             d->imageExifOrientationActionMenu,
             0,
             actionCollection(),
             "image_set_exif_orientation_rotated_upside_down");
    d->imageSetExifOrientation4Action = new TDEAction(i18n("Flipped Vertically"),
             0,
             d->imageExifOrientationActionMenu,
             0,
             actionCollection(),
             "image_set_exif_orientation_flipped_vertically");
    d->imageSetExifOrientation5Action = new TDEAction(i18n("Rotated Right / Horiz. Flipped"),
             0,
             d->imageExifOrientationActionMenu,
             0,
             actionCollection(),
             "image_set_exif_orientation_rotated_right_hor_flipped");
    d->imageSetExifOrientation6Action = new TDEAction(i18n("Rotated Right"),
             0,
             d->imageExifOrientationActionMenu,
             0,
             actionCollection(),
             "image_set_exif_orientation_rotated_right");
    d->imageSetExifOrientation7Action = new TDEAction(i18n("Rotated Right / Vert. Flipped"),
             0,
             d->imageExifOrientationActionMenu,
             0,
             actionCollection(),
             "image_set_exif_orientation_rotated_right_ver_flipped");
    d->imageSetExifOrientation8Action = new TDEAction(i18n("Rotated Left"),
             0,
             d->imageExifOrientationActionMenu,
             0,
             actionCollection(),
             "image_set_exif_orientation_rotated_left");

    d->imageExifOrientationActionMenu->insert(d->imageSetExifOrientation1Action);
    d->imageExifOrientationActionMenu->insert(d->imageSetExifOrientation2Action);
    d->imageExifOrientationActionMenu->insert(d->imageSetExifOrientation3Action);
    d->imageExifOrientationActionMenu->insert(d->imageSetExifOrientation4Action);
    d->imageExifOrientationActionMenu->insert(d->imageSetExifOrientation5Action);
    d->imageExifOrientationActionMenu->insert(d->imageSetExifOrientation6Action);
    d->imageExifOrientationActionMenu->insert(d->imageSetExifOrientation7Action);
    d->imageExifOrientationActionMenu->insert(d->imageSetExifOrientation8Action);

    connect(d->imageSetExifOrientation1Action, TQ_SIGNAL(activated()),
            exifOrientationMapper, TQ_SLOT(map()));

    connect(d->imageSetExifOrientation2Action, TQ_SIGNAL(activated()),
            exifOrientationMapper, TQ_SLOT(map()));

    connect(d->imageSetExifOrientation3Action, TQ_SIGNAL(activated()),
            exifOrientationMapper, TQ_SLOT(map()));

    connect(d->imageSetExifOrientation4Action, TQ_SIGNAL(activated()),
            exifOrientationMapper, TQ_SLOT(map()));

    connect(d->imageSetExifOrientation5Action, TQ_SIGNAL(activated()),
            exifOrientationMapper, TQ_SLOT(map()));

    connect(d->imageSetExifOrientation6Action, TQ_SIGNAL(activated()),
            exifOrientationMapper, TQ_SLOT(map()));

    connect(d->imageSetExifOrientation7Action, TQ_SIGNAL(activated()),
            exifOrientationMapper, TQ_SLOT(map()));

    connect(d->imageSetExifOrientation8Action, TQ_SIGNAL(activated()),
            exifOrientationMapper, TQ_SLOT(map()));

    exifOrientationMapper->setMapping(d->imageSetExifOrientation1Action, 1);
    exifOrientationMapper->setMapping(d->imageSetExifOrientation2Action, 2);
    exifOrientationMapper->setMapping(d->imageSetExifOrientation3Action, 3);
    exifOrientationMapper->setMapping(d->imageSetExifOrientation4Action, 4);
    exifOrientationMapper->setMapping(d->imageSetExifOrientation5Action, 5);
    exifOrientationMapper->setMapping(d->imageSetExifOrientation6Action, 6);
    exifOrientationMapper->setMapping(d->imageSetExifOrientation7Action, 7);
    exifOrientationMapper->setMapping(d->imageSetExifOrientation8Action, 8);

    // -----------------------------------------------------------------

    d->selectAllAction = new TDEAction(i18n("Select All"),
                                     0,
                                     CTRL+Key_A,
                                     d->view,
                                     TQ_SLOT(slotSelectAll()),
                                     actionCollection(),
                                     "selectAll");

    d->selectNoneAction = new TDEAction(i18n("Select None"),
                                     0,
                                     CTRL+SHIFT+Key_A,
                                     d->view,
                                     TQ_SLOT(slotSelectNone()),
                                     actionCollection(),
                                     "selectNone");

    d->selectInvertAction = new TDEAction(i18n("Invert Selection"),
                                        0,
                                        CTRL+Key_Asterisk,
                                        d->view,
                                        TQ_SLOT(slotSelectInvert()),
                                        actionCollection(),
                                        "selectInvert");

    // -----------------------------------------------------------

    d->showMenuBarAction = KStdAction::showMenubar(this, TQ_SLOT(slotShowMenuBar()), actionCollection());

    KStdAction::keyBindings(this, TQ_SLOT(slotEditKeys()),           actionCollection());
    KStdAction::configureToolbars(this, TQ_SLOT(slotConfToolbars()), actionCollection());
    KStdAction::preferences(this, TQ_SLOT(slotSetup()),              actionCollection());

    // -----------------------------------------------------------

    d->zoomPlusAction = new TDEAction(i18n("Zoom In"),
                                   "zoom-in",
                                   CTRL+Key_Plus,
                                   d->view,
                                   TQ_SLOT(slotZoomIn()),
                                   actionCollection(),
                                   "album_zoomin");

    d->zoomMinusAction = new TDEAction(i18n("Zoom Out"),
                                   "zoom-out",
                                   CTRL+Key_Minus,
                                   d->view,
                                   TQ_SLOT(slotZoomOut()),
                                   actionCollection(),
                                   "album_zoomout");

    d->zoomTo100percents = new TDEAction(i18n("Zoom to 100%"),
                                   "zoom-original",
                                   ALT+CTRL+Key_0,      // NOTE: Photoshop 7 use ALT+CTRL+0.
                                   d->view,
                                   TQ_SLOT(slotZoomTo100Percents()),
                                   actionCollection(),
                                   "album_zoomto100percents");

    d->zoomFitToWindowAction = new TDEAction(i18n("Fit to &Window"),
                                   "view_fit_window",
                                   CTRL+SHIFT+Key_E,
                                   d->view,
                                   TQ_SLOT(slotFitToWindow()),
                                   actionCollection(),
                                   "album_zoomfit2window");

    // Do not use std KDE action for full screen because action text is too large for app. toolbar.
    d->fullScreenAction = new TDEToggleAction(i18n("Full Screen"),
                                   "view-fullscreen",
                                   CTRL+SHIFT+Key_F,
                                   this,
                                   TQ_SLOT(slotToggleFullScreen()),
                                   actionCollection(),
                                   "full_screen");
    d->fullScreenAction->setWhatsThis(i18n("Switch the window to full screen mode"));

    d->slideShowAction = new TDEActionMenu(i18n("Slideshow"), "slideshow",
                                         actionCollection(), "slideshow");

    d->slideShowAction->setDelayed(false);

    d->slideShowAllAction = new TDEAction(i18n("All"), 0, Key_F9,
                                d->view, TQ_SLOT(slotSlideShowAll()),
                                actionCollection(), "slideshow_all");
    d->slideShowAction->insert(d->slideShowAllAction);

    d->slideShowSelectionAction = new TDEAction(i18n("Selection"), 0, ALT+Key_F9,
                                              d->view,
                                              TQ_SLOT(slotSlideShowSelection()),
                                              actionCollection(),
                                              "slideshow_selected");
    d->slideShowAction->insert(d->slideShowSelectionAction);

    d->slideShowRecursiveAction = new TDEAction(i18n("With All Sub-Albums"), 0, SHIFT+Key_F9,
                                              d->view,
                                              TQ_SLOT(slotSlideShowRecursive()),
                                              actionCollection(),
                                              "slideshow_recursive");
    d->slideShowAction->insert(d->slideShowRecursiveAction);

    d->quitAction = KStdAction::quit(this,
                                   TQ_SLOT(slotExit()),
                                   actionCollection(),
                                   "app_exit");

    d->rawCameraListAction = new TDEAction(i18n("Supported RAW Cameras"),
                                   "kdcraw",
                                   0,
                                   this,
                                   TQ_SLOT(slotRawCameraList()),
                                   actionCollection(),
                                   "help_rawcameralist");

    d->kipiHelpAction = new TDEAction(i18n("Kipi Plugins Handbook"),
                                   "kipi",
                                   0,
                                   this,
                                   TQ_SLOT(slotShowKipiHelp()),
                                   actionCollection(),
                                   "help_kipi");

    d->tipAction = KStdAction::tipOfDay(this,
                                   TQ_SLOT(slotShowTip()),
                                   actionCollection(),
                                   "help_tipofday");

    d->donateMoneyAction = new TDEAction(i18n("Donate..."),
                                   0,
                                   0,
                                   this,
                                   TQ_SLOT(slotDonateMoney()),
                                   actionCollection(),
                                   "help_donatemoney");

    d->contributeAction = new TDEAction(i18n("Contribute..."),
                                      0, 0,
                                      this, TQ_SLOT(slotContribute()),
                                      actionCollection(),
                                      "help_contribute");

    new DLogoAction(actionCollection(), "logo_action" );

    // -- Rating actions ---------------------------------------------------------------

    d->rating0Star = new TDEAction(i18n("Assign Rating \"No Stars\""), CTRL+Key_0,
                          d->view, TQ_SLOT(slotAssignRatingNoStar()),
                          actionCollection(), "ratenostar");
    d->rating1Star = new TDEAction(i18n("Assign Rating \"One Star\""), CTRL+Key_1,
                          d->view, TQ_SLOT(slotAssignRatingOneStar()),
                          actionCollection(), "rateonestar");
    d->rating2Star = new TDEAction(i18n("Assign Rating \"Two Stars\""), CTRL+Key_2,
                          d->view, TQ_SLOT(slotAssignRatingTwoStar()),
                          actionCollection(), "ratetwostar");
    d->rating3Star = new TDEAction(i18n("Assign Rating \"Three Stars\""), CTRL+Key_3,
                          d->view, TQ_SLOT(slotAssignRatingThreeStar()),
                          actionCollection(), "ratethreestar");
    d->rating4Star = new TDEAction(i18n("Assign Rating \"Four Stars\""), CTRL+Key_4,
                          d->view, TQ_SLOT(slotAssignRatingFourStar()),
                          actionCollection(), "ratefourstar");
    d->rating5Star = new TDEAction(i18n("Assign Rating \"Five Stars\""), CTRL+Key_5,
                          d->view, TQ_SLOT(slotAssignRatingFiveStar()),
                          actionCollection(), "ratefivestar");

    // -----------------------------------------------------------

    TDEAction* findAction = KStdAction::find(d->view, TQ_SLOT(slotNewQuickSearch()),
                                           actionCollection(), "search_quick");
    findAction->setText(i18n("Search..."));
    findAction->setIconSet(BarIcon("filefind"));

    TDEAction* advFindAction = KStdAction::find(d->view, TQ_SLOT(slotNewAdvancedSearch()),
                                              actionCollection(), "search_advanced");
    advFindAction->setText(i18n("Advanced Search..."));
    advFindAction->setShortcut("Ctrl+Alt+F");

    new TDEAction(i18n("Light Table"), "idea", Key_L,
                d->view, TQ_SLOT(slotLightTable()), actionCollection(),
                "light_table");

    new TDEAction(i18n("Scan for New Images"), "reload_page", 0,
                this, TQ_SLOT(slotDatabaseRescan()), actionCollection(),
                "database_rescan");

    new TDEAction(i18n("Rebuild All Thumbnails..."), "reload_page", 0,
                this, TQ_SLOT(slotRebuildAllThumbs()), actionCollection(),
                "thumbs_rebuild");

    new TDEAction(i18n("Update Metadata Database..."), "reload_page", 0,
                this, TQ_SLOT(slotSyncAllPicturesMetadata()), actionCollection(),
                "sync_metadata");

    // -----------------------------------------------------------

    // Provides a menu entry that allows showing/hiding the toolbar(s)
    setStandardToolBarMenuEnabled(true);

    // Provides a menu entry that allows showing/hiding the statusbar
    createStandardStatusBarAction();

    // Load Cameras -- do this before the createGUI so that the cameras
    // are plugged into the toolbar at startup
    if (d->splashScreen)
        d->splashScreen->message(i18n("Loading cameras"));

    loadCameras();

    createGUI(TQString::fromLatin1( "digikamui.rc" ), false);

    // Initialize Actions ---------------------------------------

    d->deleteAction->setEnabled(false);
    d->addImagesAction->setEnabled(false);
    d->propsEditAction->setEnabled(false);
    d->openInKonquiAction->setEnabled(false);

    d->imageViewAction->setEnabled(false);
    d->imagePreviewAction->setEnabled(false);
    d->imageLightTableAction->setEnabled(false);
    d->imageAddLightTableAction->setEnabled(false);
    d->imageRenameAction->setEnabled(false);
    d->imageDeleteAction->setEnabled(false);
    d->imageExifOrientationActionMenu->setEnabled(false);
    d->slideShowSelectionAction->setEnabled(false);

    d->albumSortAction->setCurrentItem((int)d->albumSettings->getAlbumSortOrder());
    d->imageSortAction->setCurrentItem((int)d->albumSettings->getImageSortOrder());

    d->recurseAlbumsAction->setChecked(d->albumSettings->getRecurseAlbums());
    d->recurseTagsAction->setChecked(d->albumSettings->getRecurseTags());
    slotRecurseAlbums(d->recurseAlbumsAction->isChecked());
    slotRecurseTags(d->recurseTagsAction->isChecked());

    // Setting the filter condition also updates the tooltip.
    // (So `setRating` is called first, as otherwise the filter value is not respected).
    d->albumIconViewFilter->readSettings();
}

void DigikamApp::enableZoomPlusAction(bool val)
{
    d->zoomPlusAction->setEnabled(val);
    d->statusZoomBar->setEnableZoomPlus(val);
}

void DigikamApp::enableZoomMinusAction(bool val)
{
    d->zoomMinusAction->setEnabled(val);
    d->statusZoomBar->setEnableZoomMinus(val);
}

void DigikamApp::enableAlbumBackwardHistory(bool enable)
{
    d->backwardActionMenu->setEnabled(enable);
}

void DigikamApp::enableAlbumForwardHistory(bool enable)
{
    d->forwardActionMenu->setEnabled(enable);
}

void DigikamApp::slotAboutToShowBackwardMenu()
{
    d->backwardActionMenu->popupMenu()->clear();
    TQStringList titles;
    d->view->getBackwardHistory(titles);
    if(!titles.isEmpty())
    {
        int id = 1;
        TQStringList::Iterator iter = titles.begin();
        for(; iter != titles.end(); ++iter,++id)
        {
            d->backwardActionMenu->popupMenu()->insertItem(*iter, id);
        }
    }
}

void DigikamApp::slotAboutToShowForwardMenu()
{
    d->forwardActionMenu->popupMenu()->clear();
    TQStringList titles;
    d->view->getForwardHistory(titles);

    if(!titles.isEmpty())
    {
        int id = 1;
        TQStringList::Iterator iter = titles.begin();
        for(; iter != titles.end(); ++iter,++id)
        {
            d->forwardActionMenu->popupMenu()->insertItem(*iter, id);
        }
    }
}

void DigikamApp::slotAlbumSelected(bool val)
{
    Album *album = d->albumManager->currentAlbum();

    if(album && !val)
    {
        // Not a PAlbum is selected
        d->deleteAction->setEnabled(false);
        d->addImagesAction->setEnabled(false);
        d->propsEditAction->setEnabled(false);
        d->openInKonquiAction->setEnabled(false);
        d->newAction->setEnabled(false);
        d->albumImportAction->setEnabled(false);
    }
    else if(!album && !val)
    {
        // Groupitem selected (Collection/date)
        d->deleteAction->setEnabled(false);
        d->addImagesAction->setEnabled(false);
        d->propsEditAction->setEnabled(false);
        d->openInKonquiAction->setEnabled(false);
        d->newAction->setEnabled(false);
        d->albumImportAction->setEnabled(false);

        TDEAction *action;
        for (action = d->kipiFileActionsImport.first(); action;
             action = d->kipiFileActionsImport.next())
        {
            action->setEnabled(false);
        }
    }
    else if(album && !album->isRoot() && album->type() == Album::PHYSICAL)
    {
        // Normal Album selected
        d->deleteAction->setEnabled(true);
        d->addImagesAction->setEnabled(true);
        d->propsEditAction->setEnabled(true);
        d->openInKonquiAction->setEnabled(true);
        d->newAction->setEnabled(true);
        d->albumImportAction->setEnabled(true);

        TDEAction *action;
        for (action = d->kipiFileActionsImport.first(); action;
             action = d->kipiFileActionsImport.next())
        {
            action->setEnabled(true);
        }
    }
    else if(album && album->isRoot() && album->type() == Album::PHYSICAL)
    {
        // Root Album selected
        d->deleteAction->setEnabled(false);
        d->addImagesAction->setEnabled(false);
        d->propsEditAction->setEnabled(false);

        if(album->type() == Album::PHYSICAL)
        {
            d->newAction->setEnabled(true);
            d->openInKonquiAction->setEnabled(true);
            d->albumImportAction->setEnabled(true);
        }
        else
        {
            d->newAction->setEnabled(false);
            d->openInKonquiAction->setEnabled(false);
            d->albumImportAction->setEnabled(false);
        }

        TDEAction *action;
        for (action = d->kipiFileActionsImport.first(); action;
             action = d->kipiFileActionsImport.next())
        {
            action->setEnabled(false);
        }
    }
}

void DigikamApp::slotTagSelected(bool val)
{
    Album *album = d->albumManager->currentAlbum();
    if (!album) return;

    if(!val)
    {
        d->deleteTagAction->setEnabled(false);
        d->editTagAction->setEnabled(false);
    }
    else if(!album->isRoot())
    {
        d->deleteTagAction->setEnabled(true);
        d->editTagAction->setEnabled(true);

        TDEAction *action;
        for (action = d->kipiFileActionsImport.first(); action;
             action = d->kipiFileActionsImport.next())
        {
            action->setEnabled(false);
        }
    }
    else
    {
        d->deleteTagAction->setEnabled(false);
        d->editTagAction->setEnabled(false);

        TDEAction *action;
        for (action = d->kipiFileActionsImport.first(); action;
             action = d->kipiFileActionsImport.next())
        {
            action->setEnabled(false);
        }
    }
}

void DigikamApp::slotImageSelected(const TQPtrList<ImageInfo>& list, bool hasPrev, bool hasNext,
                                   const KURL::List& listAll)
{
    TQPtrList<ImageInfo> selection = list;
    KURL::List all                = listAll;
    int num_images                = listAll.count();
    bool val                      = selection.isEmpty() ? false : true;
    TQString text;
    int index = 1;

    d->imageViewAction->setEnabled(val);
    d->imagePreviewAction->setEnabled(val);
    d->imageLightTableAction->setEnabled(val);
    d->imageAddLightTableAction->setEnabled(val);
    d->imageRenameAction->setEnabled(val);
    d->imageDeleteAction->setEnabled(val);
    d->imageExifOrientationActionMenu->setEnabled(val);
    d->slideShowSelectionAction->setEnabled(selection.count() != 0);

    switch (selection.count())
    {
        case 0:
            d->statusProgressBar->setText(i18n("No item selected"));
        break;
        case 1:
        {
            KURL first = selection.first()->kurl();

            for (KURL::List::iterator it = all.begin();
                it != all.end(); ++it)
            {
                if ((*it) == first)
                    break;

                index++;
            }

            text = selection.first()->kurl().fileName()
                                   + i18n(" (%1 of %2)")
                                   .arg(TQString::number(index))
                                   .arg(TQString::number(num_images));
            d->statusProgressBar->setText(text);
            break;
        }
        default:
          d->statusProgressBar->setText(i18n("%1/%2 items selected")
                                .arg(selection.count()).arg(TQString::number(num_images)));

        break;
    }

    d->statusNavigateBar->setNavigateBarState(hasPrev, hasNext);
}

void DigikamApp::slotProgressBarMode(int mode, const TQString& text)
{
    d->statusProgressBar->progressBarMode(mode, text);
}

void DigikamApp::slotProgressValue(int count)
{
    d->statusProgressBar->setProgressValue(count);
}

void DigikamApp::slotExit()
{
    if (d->fullScreen)
    {
        slotToggleFullScreen();
        TQTimer::singleShot(0, this, TQ_SLOT(close()));
    }
    else
        close();
}

TQString DigikamApp::convertToLocalUrl( const TQString& folder )
{
    // This function is copied from k3b.

    KURL url( folder );
    if( !url.isLocalFile() )
    {
        // Support for system:/ and media:/ (c) Stephan Kulow
        KURL mlu = TDEIO::NetAccess::mostLocalURL( url, 0 );
        if (mlu.isLocalFile())
            return mlu.path();

        DWarning() << folder << " mlu " << mlu << endl;

        TQString path = mlu.path();

        if ( mlu.protocol() == "system" && path.startsWith("/media") )
            path = path.mid(7);
        else if (mlu.protocol() == "media")
            path = path.mid(1);
        else
            return folder; // nothing to see - go on

        DDebug() << "parsed import path is: " << path << endl;
        DCOPRef ref("kded", "mediamanager");
        DCOPReply reply = ref.call("properties", path);
        if (reply.isValid()) {
            TQStringList slreply;
            reply.get(slreply);
            if ((slreply.count()>=9) && !slreply[9].isEmpty())
                return slreply[9];
            else
                return slreply[6];
        }
        else
        {
            DWarning() << "dcop call failed\n";
        }

        return path;
    }

    return url.path();
}

void DigikamApp::slotDcopDownloadImages( const TQString& folder )
{
    if (!folder.isNull())
    {
        // activate window when called by media menu and DCOP
        if (isMinimized())
            KWin::deIconifyWindow(winId());
        KWin::activateWindow(winId());

        slotDownloadImages(folder);
    }
}

void DigikamApp::slotDcopCameraAutoDetect()
{
    // activate window when called by media menu and DCOP
    if (isMinimized())
        KWin::deIconifyWindow(winId());
    KWin::activateWindow(winId());

    slotCameraAutoDetect();
}

void DigikamApp::slotDownloadImages( const TQString& folder)
{
    if (!folder.isNull())
    {
        d->cameraGuiPath = folder;

        TQTimer::singleShot(0, this, TQ_SLOT(slotDownloadImages()));
    }
}

void DigikamApp::slotDownloadImages()
{
    if (d->cameraGuiPath.isNull())
        return;

    // Fetch the contents of the device. This is needed to make sure that the
    // media:/device gets mounted.
    TDEIO::ListJob *job = TDEIO::listDir(KURL(d->cameraGuiPath), false, false);
    TDEIO::NetAccess::synchronousRun(job,0);

    TQString localUrl = convertToLocalUrl(d->cameraGuiPath);
    DDebug() << "slotDownloadImages: convertToLocalUrl " << d->cameraGuiPath << " to " << localUrl << endl;

    if (localUrl.isNull())
        return;

    bool alreadyThere = false;

    for (uint i = 0 ; i != actionCollection()->count() ; i++)
    {
        if (actionCollection()->action(i)->name() == d->cameraGuiPath)
            alreadyThere = true;
    }

    if (!alreadyThere)
    {
        TDEAction *cAction  = new TDEAction(
                 i18n("Browse %1").arg(KURL(d->cameraGuiPath).prettyURL()),
                 "camera-photo",
                 0,
                 this,
                 TQ_SLOT(slotDownloadImages()),
                 actionCollection(),
                 d->cameraGuiPath.latin1() );

        d->cameraMenuAction->insert(cAction, 0);
    }

    // the CameraUI will delete itself when it has finished
    CameraUI* cgui = new CameraUI(this,
                                  i18n("Images found in %1").arg(d->cameraGuiPath),
                                  "directory browse","Fixed", localUrl, TQDateTime::currentDateTime());
    cgui->show();

    connect(cgui, TQ_SIGNAL(signalLastDestination(const KURL&)),
            d->view, TQ_SLOT(slotSelectAlbum(const KURL&)));

    connect(cgui, TQ_SIGNAL(signalAlbumSettingsChanged()),
            this, TQ_SLOT(slotSetupChanged()));
}

void DigikamApp::slotCameraConnect()
{
    CameraType* ctype = d->cameraList->find(TQString::fromUtf8(sender()->name()));

    if (ctype)
    {
        // check not to open two dialogs for the same camera
        if (ctype->currentCameraUI() && !ctype->currentCameraUI()->isClosed())
        {
            // show and raise dialog
            if (ctype->currentCameraUI()->isMinimized())
                KWin::deIconifyWindow(ctype->currentCameraUI()->winId());
            KWin::activateWindow(ctype->currentCameraUI()->winId());
        }
        else
        {
            // the CameraUI will delete itself when it has finished
            CameraUI* cgui = new CameraUI(this, ctype->title(), ctype->model(),
                                          ctype->port(), ctype->path(), ctype->lastAccess());

            ctype->setCurrentCameraUI(cgui);

            cgui->show();

            connect(cgui, TQ_SIGNAL(signalLastDestination(const KURL&)),
                    d->view, TQ_SLOT(slotSelectAlbum(const KURL&)));

            connect(cgui, TQ_SIGNAL(signalAlbumSettingsChanged()),
                    this, TQ_SLOT(slotSetupChanged()));
        }
    }
}

void DigikamApp::slotCameraAdded(CameraType *ctype)
{
    if (!ctype) return;

    TDEAction *cAction = new TDEAction(ctype->title(), "camera-photo", 0,
                                   this, TQ_SLOT(slotCameraConnect()),
                                   actionCollection(),
                                   ctype->title().utf8());
    d->cameraMenuAction->insert(cAction, 0);
    ctype->setAction(cAction);
}

void DigikamApp::slotCameraMediaMenu()
{
    d->mediaItems.clear();

    d->cameraMediaList->clear();
    d->cameraMediaList->insertItem(i18n("No media devices found"), 0);
    d->cameraMediaList->setItemEnabled(0, false);

    KURL kurl("media:/");
    TDEIO::ListJob *job = TDEIO::listDir(kurl, false, false);

    connect( job, TQ_SIGNAL(entries(TDEIO::Job*,const TDEIO::UDSEntryList&)),
             this, TQ_SLOT(slotCameraMediaMenuEntries(TDEIO::Job*,const TDEIO::UDSEntryList&)) );
}

void DigikamApp::slotCameraMediaMenuEntries( Job *, const UDSEntryList & list )
{
    int i = 0;

    for(TDEIO::UDSEntryList::ConstIterator it = list.begin() ; it != list.end() ; ++it)
    {
        TQString name;
        TQString path;

        for ( UDSEntry::const_iterator et = (*it).begin() ; et != (*it).end() ; ++et )
        {
            if ( (*et).m_uds == TDEIO::UDS_NAME)
                name = ( *et ).m_str;
            if ( (*et).m_uds == TDEIO::UDS_URL)
                path = ( *et ).m_str;

            //DDebug() << ( *et ).m_str << endl;
        }

        if (!name.isEmpty() && !path.isEmpty())
        {
            //DDebug() << "slotCameraMediaMenuEntries: Adding " << name << ", path " << path << endl;
            if (i == 0)
                d->cameraMediaList->clear();

            d->mediaItems[i] = path;

            d->cameraMediaList->insertItem(name, this, TQ_SLOT(slotDownloadImagesFromMedia(int)), 0, i);
            d->cameraMediaList->setItemParameter(i, i);
            i++;
        }
    }
}

void DigikamApp::slotDownloadImagesFromMedia( int id )
{
    slotDownloadImages( d->mediaItems[id] );
}

void DigikamApp::slotCameraRemoved(CameraType *ctype)
{
    if (!ctype) return;

    TDEAction *cAction = ctype->action();

    if (cAction)
        d->cameraMenuAction->remove(cAction);
}

void DigikamApp::slotCameraAutoDetect()
{
    bool retry = false;

    CameraType* ctype = d->cameraList->autoDetect(retry);

    if (!ctype && retry)
    {
        TQTimer::singleShot(0, this, TQ_SLOT(slotCameraAutoDetect()));
        return;
    }

    if (ctype && ctype->action())
    {
        ctype->action()->activate();
    }
}

void DigikamApp::slotSetup()
{
    setup();
}

bool DigikamApp::setup(bool iccSetupPage)
{
    Setup setup(this, 0, iccSetupPage ? Setup::IccProfiles : Setup::LastPageUsed);

    // To show the number of KIPI plugins in the setup dialog.

    KIPI::PluginLoader::PluginList list = d->kipiPluginLoader->pluginList();
    setup.kipiPluginsPage()->initPlugins((int)list.count());

    if (setup.exec() != TQDialog::Accepted)
        return false;

    setup.kipiPluginsPage()->applyPlugins();

    slotSetupChanged();

    return true;
}

void DigikamApp::slotSetupCamera()
{
    Setup setup(this, 0, Setup::Camera);

    // For to show the number of KIPI plugins in the setup dialog.

    KIPI::PluginLoader::PluginList list = d->kipiPluginLoader->pluginList();
    setup.kipiPluginsPage()->initPlugins((int)list.count());

    if (setup.exec() != TQDialog::Accepted)
        return;

    setup.kipiPluginsPage()->applyPlugins();

    slotSetupChanged();
}

void DigikamApp::slotSetupChanged()
{
    // raw loading options might have changed
    LoadingCacheInterface::cleanCache();

    if(d->albumSettings->getAlbumLibraryPath() != d->albumManager->getLibraryPath())
        d->view->clearHistory();

    d->albumManager->setLibraryPath(d->albumSettings->getAlbumLibraryPath());
    d->albumManager->startScan();

    if(d->albumSettings->getShowFolderTreeViewItemsCount())
        d->albumManager->refresh();

    d->view->applySettings();
    d->albumIconViewFilter->readSettings();

    AlbumThumbnailLoader::instance()->setThumbnailSize(d->albumSettings->getDefaultTreeIconSize());

    if (ImageWindow::imagewindowCreated())
        ImageWindow::imagewindow()->applySettings();

    if (LightTableWindow::lightTableWindowCreated())
        LightTableWindow::lightTableWindow()->applySettings();

    d->config->sync();
}

void DigikamApp::slotEditKeys()
{
    KKeyDialog* dialog = new KKeyDialog();
    dialog->insert( actionCollection(), i18n( "General" ) );

    KIPI::PluginLoader::PluginList list = d->kipiPluginLoader->pluginList();

    for( KIPI::PluginLoader::PluginList::Iterator it = list.begin() ; it != list.end() ; ++it )
    {
        KIPI::Plugin* plugin = (*it)->plugin();

        if ( plugin )
           dialog->insert( plugin->actionCollection(), (*it)->comment() );
    }

    dialog->configure();
    delete dialog;
}

void DigikamApp::slotConfToolbars()
{
    saveMainWindowSettings(TDEGlobal::config());
    KEditToolbar *dlg = new KEditToolbar(actionCollection(), "digikamui.rc");

    if(dlg->exec())
    {
        createGUI(TQString::fromLatin1( "digikamui.rc" ), false);
        applyMainWindowSettings(TDEGlobal::config());
        plugActionList( TQString::fromLatin1("file_actions_import"), d->kipiFileActionsImport );
        plugActionList( TQString::fromLatin1("image_actions"), d->kipiImageActions );
        plugActionList( TQString::fromLatin1("tool_actions"), d->kipiToolsActions );
        plugActionList( TQString::fromLatin1("batch_actions"), d->kipiBatchActions );
        plugActionList( TQString::fromLatin1("album_actions"), d->kipiAlbumActions );
        plugActionList( TQString::fromLatin1("file_actions_export"), d->kipiFileActionsExport );
    }

    delete dlg;
}

void DigikamApp::slotToggleFullScreen()
{
    if (d->fullScreen)
    {
        setWindowState( windowState() & ~WindowFullScreen );
        menuBar()->show();
        statusBar()->show();
        topDock()->show();
        bottomDock()->show();
        leftDock()->show();
        rightDock()->show();
        d->view->showSideBars();

        d->fullScreen = false;
    }
    else
    {
        TDEConfig* config = kapp->config();
        config->setGroup("ImageViewer Settings");
        bool fullScreenHideToolBar = config->readBoolEntry("FullScreen Hide ToolBar", false);

        menuBar()->hide();
        statusBar()->hide();
        if (fullScreenHideToolBar)
            topDock()->hide();
        bottomDock()->hide();
        leftDock()->hide();
        rightDock()->hide();
        d->view->hideSideBars();

        showFullScreen();
        d->fullScreen = true;
    }
}

void DigikamApp::slotShowTip()
{
    TQStringList tipsFiles;
    tipsFiles.append("digikam/tips");

    tipsFiles.append("kipi/tips");

    KTipDialog::showMultiTip(this, tipsFiles, true);
}

void DigikamApp::slotShowKipiHelp()
{
    TDEApplication::kApplication()->invokeHelp( TQString(), "kipi-plugins" );
}

void DigikamApp::slotRawCameraList()
{
    RawCameraDlg dlg(this);
    dlg.exec();
}

void DigikamApp::loadPlugins()
{
    if(d->splashScreen)
        d->splashScreen->message(i18n("Loading Kipi Plugins"));

    TQStringList ignores;
    d->kipiInterface = new DigikamKipiInterface( this, "Digikam_KIPI_interface" );

    ignores.append( "HelloWorld" );
    ignores.append( "KameraKlient" );

    d->kipiPluginLoader = new KIPI::PluginLoader( ignores, d->kipiInterface );

    connect( d->kipiPluginLoader, TQ_SIGNAL( replug() ),
             this, TQ_SLOT( slotKipiPluginPlug() ) );

    d->kipiPluginLoader->loadPlugins();

    d->kipiInterface->slotCurrentAlbumChanged(d->albumManager->currentAlbum());

    // Setting the initial menu options after all plugins have been loaded
    d->view->slotAlbumSelected(d->albumManager->currentAlbum());

    d->imagePluginsLoader = new ImagePluginLoader(this, d->splashScreen);
}

void DigikamApp::slotKipiPluginPlug()
{
    unplugActionList( TQString::fromLatin1("file_actions_export") );
    unplugActionList( TQString::fromLatin1("file_actions_import") );
    unplugActionList( TQString::fromLatin1("image_actions") );
    unplugActionList( TQString::fromLatin1("tool_actions") );
    unplugActionList( TQString::fromLatin1("batch_actions") );
    unplugActionList( TQString::fromLatin1("album_actions") );

    d->kipiImageActions.clear();
    d->kipiFileActionsExport.clear();
    d->kipiFileActionsImport.clear();
    d->kipiToolsActions.clear();
    d->kipiBatchActions.clear();
    d->kipiAlbumActions.clear();

    KIPI::PluginLoader::PluginList list = d->kipiPluginLoader->pluginList();

    int cpt = 0;

    for( KIPI::PluginLoader::PluginList::Iterator it = list.begin() ; it != list.end() ; ++it )
    {
        KIPI::Plugin* plugin = (*it)->plugin();

        if ( !plugin || !(*it)->shouldLoad() )
            continue;

        ++cpt;

        plugin->setup( this );
        TQPtrList<TDEAction>* popup = 0;

        // Plugin category identification using TDEAction method based.

        TDEActionPtrList actions = plugin->actions();

        // List of obsolete kipi-plugins to not load.
        TQStringList pluginActionsDisabled;
        pluginActionsDisabled << TQString("raw_converter_single");  // Obsolete Since 0.9.5 and new Raw Import tool.

        for( TDEActionPtrList::Iterator it2 = actions.begin(); it2 != actions.end(); ++it2 )
        {
            if ( plugin->category(*it2) == KIPI::IMAGESPLUGIN )
               popup = &d->kipiImageActions;

            else if ( plugin->category(*it2) == KIPI::EXPORTPLUGIN )
               popup = &d->kipiFileActionsExport;

            else if ( plugin->category(*it2) == KIPI::IMPORTPLUGIN )
               popup = &d->kipiFileActionsImport;

            else if ( plugin->category(*it2) == KIPI::TOOLSPLUGIN )
               popup = &d->kipiToolsActions;

            else if ( plugin->category(*it2) == KIPI::BATCHPLUGIN )
               popup = &d->kipiBatchActions;

            else if ( plugin->category(*it2) == KIPI::COLLECTIONSPLUGIN )
               popup = &d->kipiAlbumActions;

            TQString actionName((*it2)->name());

            // Plug the KIPI plugins actions in according with the TDEAction method.

            if (popup)
            {
                if (!pluginActionsDisabled.contains(actionName))
                    popup->append( *it2 );
                else
                    DDebug() << "Plugin '" << actionName << "' disabled." << endl;
            }
            else
            {
                DDebug() << "No menu found for plugin '" << actionName << "' !!!" << endl;
            }
        }

        plugin->actionCollection()->readShortcutSettings();
    }

    // Create GUI menu in according with plugins.

    plugActionList( TQString::fromLatin1("file_actions_export"), d->kipiFileActionsExport );
    plugActionList( TQString::fromLatin1("file_actions_import"), d->kipiFileActionsImport );
    plugActionList( TQString::fromLatin1("image_actions"), d->kipiImageActions );
    plugActionList( TQString::fromLatin1("tool_actions"), d->kipiToolsActions );
    plugActionList( TQString::fromLatin1("batch_actions"), d->kipiBatchActions );
    plugActionList( TQString::fromLatin1("album_actions"), d->kipiAlbumActions );
}

void DigikamApp::loadCameras()
{
    d->cameraList->load();

    d->cameraMenuAction->popupMenu()->insertSeparator();

    d->cameraMenuAction->popupMenu()->insertItem(i18n("Browse Media"), d->cameraMediaList);

    d->cameraMenuAction->popupMenu()->insertSeparator();

    d->cameraMenuAction->insert(new TDEAction(i18n("Add Camera..."), 0,
                                          this, TQ_SLOT(slotSetupCamera()),
                                          actionCollection(),
                                          "camera_add"));
}

void DigikamApp::populateThemes()
{
    if(d->splashScreen)
        d->splashScreen->message(i18n("Loading themes"));

    ThemeEngine::instance()->scanThemes();
    d->themeMenuAction->setItems(ThemeEngine::instance()->themeNames());
    slotThemeChanged();
    ThemeEngine::instance()->slotChangeTheme(d->themeMenuAction->currentText());
}

void DigikamApp::slotChangeTheme(const TQString& theme)
{
    d->albumSettings->setCurrentTheme(theme);
    ThemeEngine::instance()->slotChangeTheme(theme);
}

void DigikamApp::slotThemeChanged()
{
    TQStringList themes(ThemeEngine::instance()->themeNames());
    int index = themes.findIndex(d->albumSettings->getCurrentTheme());
    if (index == -1)
        index = themes.findIndex(i18n("Default"));

    d->themeMenuAction->setCurrentItem(index);
}

void DigikamApp::slotDatabaseRescan()
{
    ScanLib sLib;
    sLib.startScan();

    d->view->refreshView();

    if (ImageWindow::imagewindowCreated())
        ImageWindow::imagewindow()->refreshView();

    if (LightTableWindow::lightTableWindowCreated())
        LightTableWindow::lightTableWindow()->refreshView();
}

void DigikamApp::slotRebuildAllThumbs()
{
    TQString msg = i18n("Rebuilding all image thumbnails can take some time.\n"
                       "Do you want to continue?");
    int result = KMessageBox::warningContinueCancel(this, msg);
    if (result != KMessageBox::Continue)
        return;

    BatchThumbsGenerator *thumbsGenerator = new BatchThumbsGenerator(this);

    connect(thumbsGenerator, TQ_SIGNAL(signalRebuildAllThumbsDone()),
            this, TQ_SLOT(slotRebuildAllThumbsDone()));

    thumbsGenerator->exec();
}

void DigikamApp::slotRebuildAllThumbsDone()
{
    d->view->applySettings();
}

void DigikamApp::slotSyncAllPicturesMetadata()
{
    TQString msg = i18n("Updating the metadata database can take some time. \nDo you want to continue?");
    int result = KMessageBox::warningContinueCancel(this, msg);
    if (result != KMessageBox::Continue)
        return;

    BatchAlbumsSyncMetadata *syncMetadata = new BatchAlbumsSyncMetadata(this);

    connect(syncMetadata, TQ_SIGNAL(signalComplete()),
            this, TQ_SLOT(slotSyncAllPicturesMetadataDone()));

    syncMetadata->exec();
}

void DigikamApp::slotSyncAllPicturesMetadataDone()
{
    d->view->applySettings();
}

void DigikamApp::slotDonateMoney()
{
    TDEApplication::kApplication()->invokeBrowser("http://www.digikam.org/?q=donation");
}

void DigikamApp::slotContribute()
{
    TDEApplication::kApplication()->invokeBrowser("http://www.digikam.org/?q=contrib");
}

void DigikamApp::slotRecurseAlbums(bool checked)
{
    AlbumLister::instance()->setRecurseAlbums(checked);
}

void DigikamApp::slotRecurseTags(bool checked)
{
    AlbumLister::instance()->setRecurseTags(checked);
}

void DigikamApp::slotZoomSliderChanged(int size)
{
    d->view->setThumbSize(size);
}

void DigikamApp::slotThumbSizeChanged(int size)
{
    d->statusZoomBar->setZoomSliderValue(size);
    d->statusZoomBar->setZoomTrackerText(i18n("Size: %1").arg(size));
}

void DigikamApp::slotZoomChanged(double zoom, int size)
{
    d->statusZoomBar->setZoomSliderValue(size);
    d->statusZoomBar->setZoomTrackerText(i18n("zoom: %1%").arg((int)(zoom*100.0)));
}

void DigikamApp::slotTogglePreview(bool t)
{
    // NOTE: if 't' is true, we are in Preview Mode, else we are in AlbumView Mode

    // This is require if ESC is pressed to go out of Preview Mode.
    // imagePreviewAction is handled by F3 key only.
    d->imagePreviewAction->setChecked(t);

    // Here, we will toggle some menu actions depending of current Mode.

    // Select menu.
    d->selectAllAction->setEnabled(!t);
    d->selectNoneAction->setEnabled(!t);
    d->selectInvertAction->setEnabled(!t);

    // View menu
    d->albumSortAction->setEnabled(!t);
    d->imageSortAction->setEnabled(!t);
    d->zoomTo100percents->setEnabled(t);
    d->zoomFitToWindowAction->setEnabled(t);
}

void DigikamApp::slotAlbumAddImages()
{
    TQString path = KFileDialog::getExistingDirectory(TDEGlobalSettings::documentPath(), this,
                                i18n("Select folder to parse"));

    if(path.isEmpty())
        return;

    // The folder contents will be parsed by Camera interface in "Directory Browse" mode.
    downloadFrom(path);
}

void DigikamApp::slotShowMenuBar()
{
    if (menuBar()->isVisible())
        menuBar()->hide();
    else
        menuBar()->show();
}

}  // namespace Digikam
