/***************************************************************************
                          instance.cpp  -  running instance of a dialog
                             -------------------
    begin                : Tue Aug 13 2002
    copyright            : (C) 2002 by Marc Britton <consume@optushome.com.au>
                           (C) 2004 by Andras Mantia <amantia@kde.org>
                           (C) 2004 by Michal Rudolf <mrudolf@kdewebdev.org>
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

 /* KDE INCLUDES */
#include <tdeapplication.h>
#include <tdeglobal.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <kstandarddirs.h>

/* QT INCLUDES */
#include <tqdialog.h>
#include <tqfile.h>
#include <tqfileinfo.h>
#include <tqiodevice.h>
#include <tqlabel.h>
#include <tqmainwindow.h>
#include <tqobjectlist.h>
#include <tqstring.h>
#include <tqtabwidget.h>
#include <tqwidget.h>
#include <tqcursor.h>

/* OTHER INCLUDES */
#include "instance.h"
#include "kommanderwidget.h"
#include "kommanderwindow.h"
#include "kommanderfactory.h"
#include "kommanderversion.h"
#include "specials.h"
#include "specialinformation.h"
#include "fileselector.h"

Instance::Instance()
  : DCOPObject("KommanderIf"), m_instance(0), m_textInstance(0), m_parent(0)
{
  SpecialInformation::registerSpecials();
}

Instance::Instance(TQWidget *a_parent)
  : DCOPObject("KommanderIf"), m_instance(0), m_textInstance(0),
  m_parent(a_parent)
{
  SpecialInformation::registerSpecials();
}

void Instance::addCmdlineArguments(const TQStringList& args)
{
  if (!m_textInstance)
    return;
  // Filter out variable arguments ('var=value')
  TQStringList stdArgs;
  for (TQStringList::ConstIterator it = args.begin(); it != args.end(); ++it)
  {
    int pos = (*it).find('=');
    if (pos != -1)
       m_textInstance->setGlobal((*it).left(pos), (*it).mid(pos+1));
    else
       stdArgs.append(*it);
  }
  int i = 0;
  for (TQStringList::ConstIterator it = stdArgs.begin(); it != stdArgs.end(); ++it)
    m_textInstance->setGlobal(TQString("_ARG%1").arg(++i), *it);
  m_textInstance->setGlobal("_ARGS", stdArgs.join(" "));
  m_textInstance->setGlobal("_ARGCOUNT", TQString::number(stdArgs.count()));
}



Instance::~Instance()
{
  delete m_instance;
}

/** Builds the instance */
bool Instance::build(const KURL& fname)
{
  delete m_instance;
  m_instance = 0;
  m_textInstance = 0;

  if (!fname.isValid() || !isFileValid(fname))
    return false; // Check if file is correct

  // create the main instance, must inherit TQDialog
  KommanderFactory::loadPlugins();

  if (fname.isValid())
    m_instance = KommanderFactory::create(fname.path(), 0L, dynamic_cast<TQWidget*>(parent()));
  else
  {
    TQFile inputFile;
    inputFile.open(IO_ReadOnly, stdin);
    m_instance = KommanderFactory::create(TQT_TQIODEVICE(&inputFile));
  }

  // check if build was successful
  if (!m_instance)
  {
    KMessageBox::sorry(0, i18n("<qt>Unable to create dialog.</qt>"));
    return false;
  }

  KommanderWindow* window = dynamic_cast<KommanderWindow*>((TQWidget*)m_instance);  
  if (window)
    window->setFileName(fname.path().local8Bit());

  // FIXME : Should verify that all of the widgets in the dialog derive from KommanderWidget
  m_textInstance = kommanderWidget(TQT_TQOBJECT(m_instance));

  if (!m_textInstance)  // Main dialog/window is not a Kommander widget - look for one
  {
    if (m_instance)
    {
      TQObjectList* widgets = m_instance->queryList();
      for (TQObject* w = widgets->first(); w; w = widgets->next())
        if (kommanderWidget(w))
        {
          m_textInstance = kommanderWidget(w);
          break;
        }
    }
    if (!m_textInstance)
    {
      tqDebug("Warning: no Kommander widget present!");
      return true;
    }
  }

  if (fname.isValid())
  {
      m_textInstance->setGlobal("KDDIR", fname.directory());
      m_textInstance->setGlobal("NAME", fname.fileName());
      m_textInstance->setGlobal("_PID", TQString().setNum(getpid()));
      m_textInstance->setGlobal("VERSION", KOMMANDER_VERSION);
  }
  return true;
}

bool Instance::run()
{
  if (!isBuilt())
    return false;

  // Handle both dialogs and main windows
  if (m_instance->inherits(TQDIALOG_OBJECT_NAME_STRING))
    dynamic_cast<TQDialog*>((TQWidget*)m_instance)->exec();
  else if (m_instance->inherits(TQMAINWINDOW_OBJECT_NAME_STRING))
  {
    kapp->setMainWidget(m_instance);
    dynamic_cast<TQMainWindow*>((TQWidget*)m_instance)->show();
    kapp->exec();
  }
  else return false;
  return true;
}

bool Instance::isBuilt() const
{
  return m_instance;
}

void Instance::setParent(TQWidget *a_parent)
{
  m_parent = a_parent;
}

bool Instance::isFileValid(const KURL& fname) const
{
  if (!TQFileInfo(fname.path()).exists())
  {
    KMessageBox::sorry(0, i18n("<qt>Kommander file<br><b>%1</b><br>does not "
      "exist.</qt>").arg(fname.path()));
    return false;
  }

  // Check whether extension is *.kmdr
  if (!fname.fileName().endsWith(".kmdr"))
  {
    KMessageBox::error(0, i18n("<qt>This file does not have a <b>.kmdr</b> extension. As a security precaution "
           "Kommander will only run Kommander scripts with a clear identity.</qt>"),
           i18n("Wrong Extension"));
    return false;
  }

  // Check whether file is not in some temporary directory.
  TQStringList tmpDirs = TDEGlobal::dirs()->resourceDirs("tmp");
  tmpDirs += TDEGlobal::dirs()->resourceDirs("cache");
  tmpDirs.append("/tmp/");
  tmpDirs.append("/var/tmp/");

  bool inTemp = false;
  for (TQStringList::ConstIterator I = tmpDirs.begin(); I != tmpDirs.end(); ++I)
    if (fname.directory(false).startsWith(*I))
      inTemp = true;

  if (inTemp)
  {
     if (KMessageBox::warningContinueCancel(0, i18n("<qt>This dialog is running from your <i>/tmp</i> directory. "
         " This may mean that it was run from a KMail attachment or from a webpage. "
         "<p>Any script contained in this dialog will have write access to all of your home directory; "
         "<b>running such dialogs may be dangerous: </b>"
             "<p>are you sure you want to continue?</qt>"), TQString(), i18n("Run Nevertheless")) == KMessageBox::Cancel)
       return false;
  }
  if (!TQFileInfo(fname.path()).isExecutable())
  {
     if (KMessageBox::warningContinueCancel(0, i18n("<qt>The Kommander file <i>%1</i> does not have the <b>executable attribute</b> set and could possibly contain dangerous exploits.<p>If you trust the scripting (viewable in kmdr-editor) in this program, make it executable to get rid of this warning.<p>Are you sure you want to continue?</qt>").arg(fname.pathOrURL()), TQString(), i18n("Run Nevertheless")) == KMessageBox::Cancel)
       return false;
  }
  return true;
}





// Widget functions
void Instance::setEnabled(const TQString& widgetName, bool enable)
{
  TQObject* child = stringToWidget(widgetName);
  if (child && child->inherits(TQWIDGET_OBJECT_NAME_STRING))
    ((TQWidget*)child)->setEnabled(enable);
}

void Instance::setVisible(const TQString& widgetName, bool visible)
{
  TQObject* child = stringToWidget(widgetName);
  if (child && child->inherits(TQWIDGET_OBJECT_NAME_STRING))
    ((TQWidget*)child)->setShown(visible);
}

void Instance::setText(const TQString& widgetName, const TQString& text)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    kommanderWidget(child)->handleDCOP(DCOP::setText, text);
  else if (child && child->inherits(TQLABEL_OBJECT_NAME_STRING))
  {
    TQLabel* label = (TQLabel*)child;
    if (label->pixmap())
    {
      TQPixmap pixmap;
      if (pixmap.load(text))
        label->setPixmap(pixmap);
    }
    else
      label->setText(text);
  }
}

TQString Instance::text(const TQString& widgetName)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    return kommanderWidget(child)->handleDCOP(DCOP::text);
  else if (child && child->inherits(TQLABEL_OBJECT_NAME_STRING))
    return ((TQLabel*)child)->text();
  return TQString();
}

void Instance::setSelection(const TQString& widgetName, const TQString& text)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    kommanderWidget(child)->handleDCOP(DCOP::setSelection, text);
  else if (child && child->inherits(TQLABEL_OBJECT_NAME_STRING))
    ((TQLabel*)child)->setText(text);
}

TQString Instance::selection(const TQString& widgetName)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    return kommanderWidget(child)->handleDCOP(DCOP::selection);
  return TQString();
}

int Instance::currentItem(const TQString &widgetName)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    return kommanderWidget(child)->handleDCOP(DCOP::currentItem).toInt();
  return -1;
}

TQString Instance::item(const TQString &widgetName, int i)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    return kommanderWidget(child)->handleDCOP(DCOP::item, TQString::number(i));
  return TQString();
}

void Instance::removeItem(const TQString &widgetName, int index)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    kommanderWidget(child)->handleDCOP(DCOP::removeItem, TQString::number(index));
}

void Instance::insertItem(const TQString &widgetName, const TQString &item, int index)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
  {
    TQStringList args(item);
    args += TQString::number(index);
    kommanderWidget(child)->handleDCOP(DCOP::insertItem, args);
  }
}

void Instance::insertItems(const TQString &widgetName, const TQStringList &items, int index)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
  {
    TQStringList args(items.join("\n"));
    args += TQString::number(index);
    kommanderWidget(child)->handleDCOP(DCOP::insertItems, args);
  }
}

int Instance::findItem(const TQString &widgetName, const TQString& item)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    return kommanderWidget(child)->handleDCOP(DCOP::findItem, item).toInt();
  return -1;
}

void Instance::addUniqueItem(const TQString &widgetName, const TQString &item)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    kommanderWidget(child)->handleDCOP(DCOP::addUniqueItem, item);
}

int Instance::itemDepth(const TQString &widgetName, int index)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    return kommanderWidget(child)->handleDCOP(DCOP::itemDepth, TQString::number(index)).toInt();
  return -1;
}

TQString Instance::itemPath(const TQString &widgetName, int index)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    return kommanderWidget(child)->handleDCOP(DCOP::itemPath, TQString::number(index));
  return TQString();
}


void Instance::setPixmap(const TQString &widgetName, const TQString& iconName, int index)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
  {
    TQStringList args(iconName);
    args += TQString::number(index);
    kommanderWidget(child)->handleDCOP(DCOP::setPixmap, args);
  }
}

void Instance::clear(const TQString &widgetName)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
    kommanderWidget(child)->handleDCOP(DCOP::clear);
}

void Instance::setCurrentItem(const TQString &widgetName, int index)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
    kommanderWidget(child)->handleDCOP(DCOP::setCurrentItem, TQString::number(index));
}

void Instance::setChecked(const TQString &widgetName, bool checked)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
    kommanderWidget(child)->handleDCOP(DCOP::setChecked, checked ? "true" : "false");
}

bool Instance::checked(const TQString &widgetName)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    return kommanderWidget(child)->handleDCOP(DCOP::checked, widgetName) == "1";
  return false;
}

void Instance::setAssociatedText(const TQString &widgetName, const TQString& text)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
    kommanderWidget(child)->setAssociatedText(TQStringList::split('\n', text, true));
}

TQStringList Instance::associatedText(const TQString &widgetName)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
    kommanderWidget(child)->associatedText();  
  return TQString();
}

TQString Instance::type(const TQString& widget)
{
  TQObject* child = stringToWidget(widget);  
  if (child && child->inherits(TQWIDGET_OBJECT_NAME_STRING))
    return child->className();
  return TQString();
}

TQStringList Instance::children(const TQString& parent, bool recursive)
{
  TQStringList matching;
  TQObject* child = stringToWidget(parent);
  TQObjectList* widgets;
  if (!child)
     child = TQT_TQOBJECT(m_instance);
  if (child->inherits(TQWIDGET_OBJECT_NAME_STRING))
  {
    widgets = child->queryList(TQWIDGET_OBJECT_NAME_STRING, 0, false, recursive);
    for (TQObject* w = widgets->first(); w; w = widgets->next())
      if (w->name() && kommanderWidget(w))
        matching.append(w->name());
  }
  return matching;
}

void Instance::setMaximum(const TQString &widgetName, int value)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
    kommanderWidget(child)->handleDCOP(DCOP::setMaximum, TQString::number(value));
}

TQString Instance::execute(const TQString &widgetName)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
    return kommanderWidget(child)->handleDCOP(DCOP::execute);
  return "";
}

void Instance::cancel(const TQString &widgetName)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
    kommanderWidget(child)->handleDCOP(DCOP::cancel);
}

int Instance::count(const TQString &widgetName)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    return kommanderWidget(child)->handleDCOP(DCOP::count).toInt();
  return -1;
}

int Instance::currentColumn(const TQString &widgetName)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    return kommanderWidget(child)->handleDCOP(DCOP::currentColumn).toInt();
  return -1;
}

int Instance::currentRow(const TQString &widgetName)
{
  TQObject* child = stringToWidget(widgetName);
  if (kommanderWidget(child))
    return kommanderWidget(child)->handleDCOP(DCOP::currentRow).toInt();
  return -1;
}

void Instance::insertRow(const TQString &widgetName, int row, int count)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
  {
    TQStringList args(TQString::number(row));
    args += TQString::number(count);
    kommanderWidget(child)->handleDCOP(DCOP::insertRow, args);
  }
}

void Instance::insertColumn(const TQString &widgetName, int column, int count)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
  {
    TQStringList args(TQString::number(column));
    args += TQString::number(count);
    kommanderWidget(child)->handleDCOP(DCOP::insertColumn, args);
  }
}

void Instance::setCellText(const TQString &widgetName, int row, int column, const TQString& text)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
  {
    TQStringList args(TQString::number(row));
    args += TQString::number(column);
    args += text;
    kommanderWidget(child)->handleDCOP(DCOP::setCellText, args);
  }
}

TQString Instance::cellText(const TQString &widgetName, int row, int column)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
  {
    TQStringList args(TQString::number(row));
    args += TQString::number(column);
    return kommanderWidget(child)->handleDCOP(DCOP::cellText, args);
  }
  else return TQString();
}

void Instance::removeRow(const TQString &widgetName, int row, int count)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
  {
    TQStringList args(TQString::number(row));
    args += TQString::number(count);
    kommanderWidget(child)->handleDCOP(DCOP::removeRow, args);
  }
}

void Instance::removeColumn(const TQString &widgetName, int column, int count)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
  {
    TQStringList args(TQString::number(column));
    args += TQString::number(count);
    kommanderWidget(child)->handleDCOP(DCOP::removeColumn, args);
  }
}

void Instance::setRowCaption(const TQString &widgetName, int row, const TQString& text)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
  {
    TQStringList args(TQString::number(row));
    args += text;
    kommanderWidget(child)->handleDCOP(DCOP::setRowCaption, args);
  }
}

void Instance::setColumnCaption(const TQString &widgetName, int column, const TQString& text)
{
  TQObject* child = stringToWidget(widgetName);  
  if (kommanderWidget(child))
  {
    TQStringList args(TQString::number(column));
    args += text;
    kommanderWidget(child)->handleDCOP(DCOP::setColumnCaption, args);
  }
}










TQString Instance::global(const TQString& variableName)
{
  return m_textInstance ? m_textInstance->global(variableName) : TQString();
}

void Instance::setGlobal(const TQString& variableName, const TQString& value)
{
  if (m_textInstance)
    m_textInstance->setGlobal(variableName, value);
}

TQObject* Instance::stringToWidget(const TQString& name)
{
  return m_instance->child(name);
}

KommanderWidget* Instance::kommanderWidget(TQObject* object)
{
  return dynamic_cast<KommanderWidget*>(object);
}


/*** Deprecated methods: just call appropriate method  ***/
void Instance::changeWidgetText(const TQString& widgetName, const TQString& text)
{
  setText(widgetName, text);
}

void Instance::clearList(const TQString &widgetName)
{
  clear(widgetName);
}

void Instance::setCurrentListItem(const TQString& widgetName, const TQString& item)
{
  setSelection(widgetName, item);
}

void Instance::setCurrentTab(const TQString &widgetName, int index)
{
  setCurrentItem(widgetName, index);
}

void Instance::insertTab(const TQString &widgetName, const TQString &label, int index)
{
  TQObject* child = stringToWidget(widgetName);  
  TQStringList l;
  l << label;
  l << TQString::number(index);
  if (kommanderWidget(child))
    kommanderWidget(child)->handleDCOP(DCOP::insertTab, l);  
}

void Instance::addListItems(const TQString &widgetName, const TQStringList &items, int index)
{
  insertItems(widgetName, items, index);
}

void Instance::enableWidget(const TQString& widgetName, bool enable)
{
  setEnabled(widgetName, enable);
}

void Instance::removeListItem(const TQString &widgetName, int index)
{
  removeItem(widgetName, index);
}

void Instance::addListItem(const TQString & widgetName, const TQString & item, int index)
{
  insertItem(widgetName, item, index);
}

int Instance::getWinID()
{
  return m_instance->winId();
}

void Instance::setBusyCursor(bool busy)
{
  if (busy)
    m_instance->setCursor(TQCursor(TQt::WaitCursor));
 else
    m_instance->setCursor(TQCursor(TQt::ArrowCursor));
}


#include "instance.moc"
