/**********************************************************************
 This file is based on TQt Designer, Copyright (C) 2000 Trolltech AS. All rights reserved.

 This file may be distributed and/or modified under the terms of the
 GNU General Public License version 2 as published by the Free Software
 Foundation and appearing in the file LICENSE.GPL included in the
 packaging of this file.

 This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

 See http://www.trolltech.com/gpl/ for GPL licensing information.

 Modified for Kommander:
  (C) 2002-2003 Marc Britton <consume@optusnet.com.au>
  (C) 2004      Michal Rudolf <mrudolf@kdewebdev.org>
  (C) 2008      Andras Mantia <amantia@kde.org>

**********************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifndef TQTDOCDIR
#define TQTDOCDIR "/usr/share/tqt3/doc/html"
#endif

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

#include "actiondnd.h"
#include "actioneditorimpl.h"
#include "assoctexteditorimpl.h"
#include "defs.h"
#include "dialog.h"
#include "formfile.h"
#include "formwindow.h"
#include "globaldefs.h"
#include "hierarchyview.h"
#include "kommanderfactory.h"
#include "mainwindow.h"
#include "messagelog.h"
#include "metadatabase.h"
#include "multilineeditorimpl.h"
#include "newformimpl.h"
#include "pixmapchooser.h"
#include "propertyeditor.h"
#include "resource.h"
#include "specialinformation.h"
#include "widgetdatabase.h"
#include "widgetfactory.h"
#include "wizardeditorimpl.h"
#include "workspace.h"

#include <tqaccel.h>
#include <tqbuffer.h>
#include <tqclipboard.h>
#include <tqdir.h>
#include <tqfeatures.h>
#include <tqfile.h>
#include <tqlabel.h>
#include <tqmetaobject.h>
#include <tqpixmap.h>
#include <tqregexp.h>
#include <tqstylefactory.h>
#include <tqstyle.h>
#include <tqtimer.h>
#include <tqtooltip.h>
#include <tqvbox.h>
#include <tqwhatsthis.h>
#include <tqwidget.h>
#include <tqwizard.h>
#include <tqworkspace.h>


#include "qcompletionedit.h"
#include "assistproc.h"

#include <kdebug.h>
#include <tdeaction.h>
#include <tdeapplication.h>
#include <tdecmdlineargs.h>
#include <tdeconfig.h>
#include <kinputdialog.h>
#include <tdelocale.h>
#include <tdemenubar.h>
#include <tdemessagebox.h>
#include <kommanderversion.h>
#include <kommanderwidget.h>
#include <kprocess.h>
#include <kstatusbar.h>
#include <tdetoolbar.h>
#include <kurl.h>
#include <tdeparts/partmanager.h>
#include <tdeio/netaccess.h>

extern TQMap<TQWidget*, TQString> *qwf_functions;
extern TQMap<TQWidget*, TQString> *qwf_forms;
extern TQString *qwf_language;
extern bool qwf_execute_code;
extern bool qwf_stays_on_top;
extern void set_splash_status(const TQString &txt);
/*### static bool tbSettingsRead = false; */

MainWindow *MainWindow::self = 0;

TQString assistantPath()
{
  return "assistant";
}


static TQString textNoAccel(const TQString& text)
{
    TQString t = text;
    int i;
    while ((i = t.find('&'))>= 0) {
        t.remove(i,1);
    }
    return t;
}


MainWindow::MainWindow(bool asClient)
  : KParts::DockMainWindow(0, "mainwindow", WType_TopLevel | WDestructiveClose | WGroupLeader),
      grd(10, 10), sGrid(true), snGrid(true), restoreConfig(true), splashScreen(true),
      docPath(TQTDOCDIR), client(asClient),  databaseAutoEdit(false), previewing(false)
{
  m_partManager = new KParts::PartManager(this);
  //connect(m_partManager, TQ_SIGNAL(activePartChanged(KParts::Part * )),          this, TQ_SLOT(slotActivePartChanged(KParts::Part * )));

  init_colors();
  inDebugMode = true;           //debugging kommander

  setupPlugins();

  kapp->setMainWidget(this);
  self = this;

  prefDia = 0;
  windowMenu = 0;
  hierarchyView = 0;
  actionEditor = 0;
  wspace = 0;

  statusBar()->clear();
  statusBar()->addWidget(new TQLabel(i18n("Welcome to the Kommander Editor"), statusBar()), 1);

  setupMDI();
  setupFileActions();
  setupEditActions();
  layoutToolBar = new TDEToolBar(this, "Layout");
  ((TDEToolBar *) layoutToolBar)->setFullSize(false);
  addToolBar(layoutToolBar, i18n("Layout"));
  setupToolActions();
  setupLayoutActions();
  setupWorkspace();
  setupHierarchyView();
  setupPropertyEditor();
  setupActionEditor();
  setupMessageLog();
  setupRunActions();
  setupWindowActions();
  setupSettingsActions();
  setupHelpActions();
  setupRMBMenus();

  emit hasActiveForm(false);
  emit hasActiveWindow(false);

  lastPressWidget = 0;
  kapp->installEventFilter(this);

  TQSize as(kapp->desktop()->size());
  as -= TQSize(30, 30);
  resize(TQSize(1200, 1000).boundedTo(as));

  connect(kapp->clipboard(), TQ_SIGNAL(dataChanged()), this, TQ_SLOT(clipboardChanged()));
  clipboardChanged();
  layoutChilds = false;
  layoutSelected = false;
  breakLayout = false;
  backPix = true;

  readConfig();

  // hack to make WidgetFactory happy (so it knows TQWidget and TQDialog for resetting properties)
  TQWidget *w = WidgetFactory::create(WidgetDatabase::idFromClassName("TQWidget"), this, 0, false);
  delete w;
  w = WidgetFactory::create(WidgetDatabase::idFromClassName("Dialog"), this, 0, false);

  delete w;
  w = WidgetFactory::create(WidgetDatabase::idFromClassName("TQLabel"), this, 0, false);
  delete w;
  w = WidgetFactory::create(WidgetDatabase::idFromClassName("TQTabWidget"), this, 0, false);
  delete w;
  w = WidgetFactory::create(WidgetDatabase::idFromClassName("TQFrame"), this, 0, false);
  delete w;

  assistant = new AssistProc(this, "Internal Assistant", assistantPath());
  statusBar()->setSizeGripEnabled(true);
  SpecialInformation::registerSpecials();

  backupTimer = new TQTimer(this);
  connect(backupTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(slotCreateBackups()));
  backupTimer->start(1000*60*5); //fire it every five minutes
  //createGUI(0);

}

MainWindow::~MainWindow()
{
  MetaDataBase::clearDataBase();
}

void MainWindow::setupMDI()
{
  KDockWidget* toolDock = createDockWidget("Workspace", TQPixmap(), 0L, "main_workspace");
  TQVBox *vbox = new TQVBox(toolDock);
  vbox->setFrameStyle(TQFrame::StyledPanel | TQFrame::Sunken);
  vbox->setMargin(1);
  vbox->setLineWidth(1);

  toolDock->setWidget(vbox);
  toolDock->setDockSite(KDockWidget::DockCorner);
  toolDock->setEnableDocking(KDockWidget::DockNone);
  setView(toolDock);
  setMainDockWidget(toolDock);

  qworkspace = new TQWorkspace(vbox);
  qworkspace->setBackgroundMode(PaletteDark);
  qworkspace->setBackgroundPixmap(PixmapChooser::loadPixmap("background.png",
                                  PixmapChooser::NoSize));
  qworkspace->setPaletteBackgroundColor(TQColor(238, 238, 238));
  qworkspace->setScrollBarsEnabled(true);
  connect(qworkspace, TQ_SIGNAL(windowActivated(TQWidget *)),
          this, TQ_SLOT(activeWindowChanged(TQWidget *)));
  lastActiveFormWindow = 0;
  qworkspace->setAcceptDrops(true);
}

void MainWindow::setupPropertyEditor()
{
  KDockWidget *dw = createDockWidget("Property Editor", TQPixmap(), 0, i18n("Properties"));
  propertyEditor = new PropertyEditor(dw);
  //addToolBar(dw, TQt::DockLeft);
  dw->setWidget(propertyEditor);
  dw->manualDock(getMainDockWidget(), KDockWidget::DockLeft, 20);
  dw->setCaption(i18n("Property Editor"));
  TQWhatsThis::add(propertyEditor,
                   i18n("<h2>The Property Editor</h2>"
                       "<p>You can change the appearance and behavior of the selected widget in the "
                       "property editor.</p>"
                       "<p>You can set properties for components and forms at design time and see the "
                       "immediately see the effects of the changes. "
                       "Each property has its own editor which (depending on the property) can be used "
                       "to enter "
                       "new values, open a special dialog, or to select values from a predefined list. "
                       "Click <b>F1</b> to get detailed help for the selected property.</p>"
                       "<p>You can resize the columns of the editor by dragging the separators in the "
                       "list's header.</p>"
                       "<p><b>Signal Handlers</b></p>"
                       "<p>In the Signal Handlers tab you can define connections between "
                       "the signals emitted by widgets and the slots in the form. "
                       "(These connections can also be made using the connection tool.)"));

}


void MainWindow::setupHierarchyView()
{
  if (hierarchyView)
    return;
  KDockWidget *dw = createDockWidget("Object Explorer", TQPixmap(), 0, i18n("Widgets"));
  hierarchyView = new HierarchyView(dw);
  dw->setWidget(hierarchyView);
  dw->setCaption(i18n("Object Explorer"));
  TQWhatsThis::add(hierarchyView,
                  i18n("<h2>The Object Explorer</h2>"
                      "<p>The Object Explorer provides an overview of the relationships "
                      "between the widgets in a form. You can use the clipboard functions using "
                      "a context menu for each item in the view. It is also useful for selecting widgets "
                      "in forms that have complex layouts.</p>"
                      "<p>The columns can be resized by dragging the separator in the list's header.</p>"
                      "<p>The second tab shows all the form's slots, class variables, includes, etc.</p>"));
}

void MainWindow::setupWorkspace()
{
  KDockWidget *dw = createDockWidget("Dialogs", TQPixmap(), 0, i18n("Dialogs"));
  TQVBox *vbox = new TQVBox(dw);
  QCompletionEdit *edit = new QCompletionEdit(vbox);
  TQToolTip::add(edit, i18n("Start typing the buffer you want to switch to here (ALT+B)"));
  TQAccel *a = new TQAccel(this);
  a->connectItem(a->insertItem(ALT + Key_B), edit, TQ_SLOT(setFocus()));
  wspace = new Workspace(vbox, this);
  wspace->setBufferEdit(edit);
  dw->setWidget(vbox);
  dw->setCaption(i18n("Dialogs"));
  TQWhatsThis::add(wspace, i18n("<h2>The File Overview Window</h2>"
      "<p>The File Overview Window displays all open dialogs.</p>"));

}

void MainWindow::setupActionEditor()
{
  KDockWidget *dw = createDockWidget("Action Editor", TQPixmap(), 0, i18n("Actions"));
  actionEditor = new ActionEditor(dw, "ActionEditor");
  //addToolBar(dw, TQt::DockLeft);
  dw->setWidget(actionEditor);
  dw->setCaption(i18n("Action Editor"));
  TQWhatsThis::add(actionEditor, i18n("<b>The Action Editor</b>"
      "<p>The Action Editor is used to add actions and action groups to "
          "a form, and to connect actions to slots. Actions and action "
          "groups can be dragged into menus and into toolbars, and may "
          "feature keyboard shortcuts and tooltips. If actions have pixmaps "
          "these are displayed on toolbar buttons and beside their names in " "menus.</p>"));
}

void MainWindow::setupMessageLog()
{
  KDockWidget *dw = createDockWidget("Message Log", TQPixmap(), 0, i18n("Message Log"));
  messageLog = new MessageLog(dw, "MessageLog");
  dw->setWidget(messageLog);
  dw->setCaption(i18n("Message Log"));
  dw->manualDock(getMainDockWidget(), KDockWidget::DockBottom, 20);
}

void MainWindow::setupRMBMenus()
{
  rmbWidgets = new TQPopupMenu(this);
  actionEditCut->plug(rmbWidgets);
  actionEditCopy->plug(rmbWidgets);
  actionEditPaste->plug(rmbWidgets);
  actionEditDelete->plug(rmbWidgets);

  rmbWidgets->insertSeparator();
  actionEditAdjustSize->plug(rmbWidgets);
  actionEditHLayout->plug(rmbWidgets);
  actionEditVLayout->plug(rmbWidgets);
  actionEditGridLayout->plug(rmbWidgets);
  actionEditSplitHorizontal->plug(rmbWidgets);
  actionEditSplitVertical->plug(rmbWidgets);
  actionEditBreakLayout->plug(rmbWidgets);
  rmbWidgets->insertSeparator();
  actionEditConnections->plug(rmbWidgets);
  rmbFormWindow = new TQPopupMenu(this);
  actionEditPaste->plug(rmbFormWindow);
  actionEditSelectAll->plug(rmbFormWindow);
  actionEditAccels->plug(rmbFormWindow);
  rmbFormWindow->insertSeparator();
  actionEditAdjustSize->plug(rmbFormWindow);
  actionEditHLayout->plug(rmbFormWindow);
  actionEditVLayout->plug(rmbFormWindow);
  actionEditGridLayout->plug(rmbFormWindow);
  actionEditBreakLayout->plug(rmbFormWindow);
  rmbFormWindow->insertSeparator();
  actionEditConnections->plug(rmbFormWindow);
  rmbFormWindow->insertSeparator();
  actionEditFormSettings->plug(rmbFormWindow);
}

void MainWindow::toolSelected()
{
  if (!(sender())->inherits("TDEAction"))
    return;
  actionCurrentTool = (TDEAction*)sender();
  emit currentToolChanged();
  if (formWindow())
    formWindow()->commandHistory()->emitUndoRedo();
}

int MainWindow::currentTool() const
{
  if (!actionCurrentTool)
    return POINTER_TOOL;
  return TQString::fromLatin1(actionCurrentTool->name()).toInt();
}

void MainWindow::slotCreateBackups()
{
//create a backup of the opened forms
  TQWidgetList windows = qworkspace->windowList(TQWorkspace::StackingOrder);
  for (int i = 0; i < (int)windows.count(); ++i)
  {
    FormWindow* form = dynamic_cast<FormWindow*>(windows.at(i));
    if (!form || !form->formFile())
      continue;
    TQString fileName = form->formFile()->fileName();
    TQString backupName = fileName + ".backup";
    bool modified = form->formFile()->isModified();
    if (form->formFile()->hasTempFileName())
      continue; //no need to create a backup
    if (!modified)
      continue;
    
    form->formFile()->setFileName(backupName);  
    form->formFile()->setModified(true);
    if (!form->formFile()->save(false))
    {
      KMessageBox::error(this, i18n("<qt>Cannot create backup file <i>%1</i>.</qt>").arg(backupName));
    }
    form->formFile()->setFileName(fileName);  
    form->formFile()->setModified(modified); 
  }
}

void MainWindow::runForm()
{
  if (previewing)
  {
    KMessageBox::information(this, i18n("There is a dialog already running."), i18n("Run"));
    return;
  }
  FormWindow* form = activeForm();
  if (!form || !form->formFile())
    return;

  TQObjectList *editors = queryList("AssocTextEditor");
  TQObjectListIt it(*editors);
  TQObject *editor;

  while ((editor = it.current()) != 0L) 
  {
    ++it;
    static_cast<AssocTextEditor*>(editor)->save();
  }
  delete editors;  

  if (form->formFile()->hasTempFileName())
  {
    if (!form->formFile()->saveAs())
      return;
  }

  m_fileName = form->formFile()->fileName();
  m_backupName = m_fileName + ".running";
  m_modified = form->formFile()->isModified();
    
  bool readOnlyFile = !TQFileInfo(m_fileName).isWritable();
  struct stat statbuf;
  ::stat(m_fileName.local8Bit(), &statbuf);
  if (!readOnlyFile && !TDEIO::NetAccess::file_copy(KURL::fromPathOrURL(m_fileName), KURL::fromPathOrURL(m_backupName), statbuf.st_mode, true))
  {
    KMessageBox::error(this, i18n("<qt>Cannot create temporary file <i>%1</i>.</qt>").arg(m_backupName));
    return;
  }
  form->formFile()->setFileName(m_fileName);  
  if (!readOnlyFile || m_modified)
    form->formFile()->setModified(true);
  if (form->formFile()->save(false))
  {
    if (!readOnlyFile && !TDEIO::NetAccess::file_copy(KURL::fromPathOrURL(m_fileName), KURL::fromPathOrURL(m_fileName + ".backup"), statbuf.st_mode, true))
    {
      KMessageBox::error(this, i18n("<qt>Cannot create backup file <i>%1</i>.</qt>").arg(m_fileName + ".backup"));
    }
    ::chmod(m_fileName.local8Bit(), S_IRWXU);
    TDEProcess* process = new TDEProcess;
    process->setUseShell(true);
    (*process) << "kmdr-executor" << TQString("\"%1\"").arg(form->formFile()->fileName());
    connect(process, TQ_SIGNAL(receivedStdout(TDEProcess*, char*, int)), messageLog,
            TQ_SLOT(receivedStdout(TDEProcess*, char*, int)));
    connect(process, TQ_SIGNAL(receivedStderr(TDEProcess*, char*, int)), messageLog,
            TQ_SLOT(receivedStderr(TDEProcess*, char*, int)));
    connect(process, TQ_SIGNAL(processExited(TDEProcess*)), TQ_SLOT(closeRunningForm(TDEProcess*)));  
    messageLog->clear(MessageLog::All);
    previewing = process->start(TDEProcess::NotifyOnExit, TDEProcess::AllOutput);
  }
}


void MainWindow::closeRunningForm(TDEProcess* process)
{
  previewing = false;
  delete process;
 
  if (TQFileInfo(m_backupName).exists())
  {
    struct stat statbuf;
    ::stat(m_fileName.local8Bit(), &statbuf);
    FormWindow* form = activeForm();
    TDEIO::NetAccess::file_move(KURL::fromPathOrURL(m_backupName), KURL::fromPathOrURL(m_fileName), statbuf.st_mode, true);
    form->formFile()->setModified(m_modified);
  }
}

void MainWindow::showProperties(TQObject *o)
{
  if (!o->isWidgetType()) {
    propertyEditor->setWidget(o, lastActiveFormWindow);
    if (lastActiveFormWindow)
      hierarchyView->setFormWindow(lastActiveFormWindow, lastActiveFormWindow->mainContainer());
    else
      hierarchyView->setFormWindow(0, 0);
    return;
  }
  TQWidget *w = (TQWidget*)o;
  setupHierarchyView();
  FormWindow *fw = (FormWindow*)isAFormWindowChild(w);
  if (fw) {
    propertyEditor->setWidget(w, fw);
    hierarchyView->setFormWindow(fw, w);
  } else {
    propertyEditor->setWidget(0, 0);
    hierarchyView->setFormWindow(0, 0);
  }

  if (currentTool() == POINTER_TOOL && fw &&
       (!qworkspace->activeWindow() || !qworkspace->activeWindow()->inherits("SourceEditor")))
    fw->setFocus();
}

void MainWindow::resetTool()
{
  actionPointerTool->setChecked(true);
  actionCurrentTool = actionPointerTool;
  emit currentToolChanged();
}

void MainWindow::updateProperties(TQObject *)
{
  if (propertyEditor)
    propertyEditor->refetchData();
}

bool MainWindow::eventFilter(TQObject *o, TQEvent *e)
{
  if (!o || !e || !o->isWidgetType())
    return TQMainWindow::eventFilter(o, e);

  TQWidget *w = 0;
  bool passiveInteractor = WidgetFactory::isPassiveInteractor(o);
  switch (e->type()) {
    case TQEvent::AccelOverride:
      if (((TQKeyEvent*)e)->key() == Key_F1 &&
              (((TQKeyEvent*)e)->state() & ShiftButton) != ShiftButton) {
        w = (TQWidget*)o;
        while (w) {
          if (w->inherits("PropertyList"))
            break;
          w = w->parentWidget(true);
        }
        if (w) {
          propertyEditor->propertyList()->showCurrentWhatsThis();
          ((TQKeyEvent*)e)->accept();
          return true;
        }
              }
              break;
    case TQEvent::Accel:
      if ((((TQKeyEvent*)e)->key() == Key_A ||
                ((TQKeyEvent*)e)->key() == Key_E) &&
                ((TQKeyEvent*)e)->state() & ControlButton) {
        if (qWorkspace()->activeWindow() &&
             qWorkspace()->activeWindow()->inherits("SourceEditor")) {
          ((TQKeyEvent*)e)->ignore();
          return true;
             }
                }
                break;
    case TQEvent::MouseButtonPress:
      if (((TQMouseEvent*)e)->button() == TQt::MidButton && dynamic_cast<KommanderWidget *>(o))
      {
        AssocTextEditor *editor = new AssocTextEditor((TQWidget*)o, formWindow(), propertyEditor, m_partManager,
             this, "AssocTextEditor", false); //deletes itself!
         editor->show();
         ((TQKeyEvent*)e)->accept();
          return true;
      }
    case TQEvent::ContextMenu:
      if (o->inherits("QDesignerPopupMenu"))
        break;
      if (o && currentTool() == POINTER_TOOL && (o->inherits("QDesignerMenuBar") ||
           o->inherits("QDesignerToolBar") ||
           (o->inherits("TQComboBox") || o->inherits("TQToolButton") || o->inherits("QDesignerToolBarSeparator")) &&
           o->parent() && o->parent()->inherits("QDesignerToolBar"))) {
        TQWidget *w = (TQWidget*)o;
        if (w->inherits("TQToolButton") || w->inherits("TQComboBox") || w->inherits("QDesignerToolBarSeparator"))
          w = w->parentWidget();
        TQWidget *pw = w->parentWidget();
        while (pw) {
          if (pw->inherits("FormWindow")) {
            ((FormWindow*)pw)->emitShowProperties(w);
            if (!o->inherits("QDesignerToolBar"))
              return !o->inherits("TQToolButton") && !o->inherits("TQMenuBar") &&
                  !o->inherits("TQComboBox") && !o->inherits("QDesignerToolBarSeparator");
          }
          pw = pw->parentWidget();
        }
           }
           if (o && (o->inherits("QDesignerToolBar") || o->inherits("TQDockWindowHandle"))
                && e->type() == TQEvent::ContextMenu)
             break;
           if (isAToolBarChild(o) && currentTool() != CONNECT_TOOL)
             break;
           if (o && o->inherits("TQSizeGrip"))
             break;
           if (!(w = isAFormWindowChild(o)) || o->inherits("SizeHandle") || o->inherits("OrderIndicator"))
             break;
           if (!w->hasFocus())
             w->setFocus();
           if (!passiveInteractor || currentTool() != ORDER_TOOL) {
             if(e->type() == TQEvent::ContextMenu) {
               ((FormWindow*)w)->handleContextMenu((TQContextMenuEvent*)e,
               ((FormWindow*)w)->designerWidget(o));
               return true;
             } else {
               ((FormWindow*)w)->handleMousePress((TQMouseEvent*)e,
               ((FormWindow*)w)->designerWidget(o));
             }
           }
           lastPressWidget = (TQWidget*)o;
           if (passiveInteractor)
             TQTimer::singleShot(0, formWindow(), TQ_SLOT(visibilityChanged()));
           if (currentTool() == CONNECT_TOOL)
             return true;
           return !passiveInteractor;
    case TQEvent::MouseButtonRelease:
      lastPressWidget = 0;
      if (isAToolBarChild(o)  && currentTool() != CONNECT_TOOL)
        break;
      if (o && o->inherits("TQSizeGrip"))
        break;
      if (!(w = isAFormWindowChild(o)) || o->inherits("SizeHandle") || o->inherits("OrderIndicator"))
        break;
      if (!passiveInteractor)
        ((FormWindow*)w)->handleMouseRelease((TQMouseEvent*)e, ((FormWindow*)w)->designerWidget(o));
      if (passiveInteractor) {
        selectionChanged();
        TQTimer::singleShot(0, formWindow(), TQ_SLOT(visibilityChanged()));
      }
      return !passiveInteractor;
    case TQEvent::MouseMove:
      if (isAToolBarChild(o) && currentTool() != CONNECT_TOOL)
        break;
      w = isAFormWindowChild(o);
      if (lastPressWidget != (TQWidget*)o && w &&
           !o->inherits("SizeHandle") && !o->inherits("OrderIndicator") &&
           !o->inherits("TQPopupMenu") && !o->inherits("TQMenuBar") &&
           !o->inherits("TQSizeGrip"))
        return true;
      if (o && o->inherits("TQSizeGrip"))
        break;
      if (lastPressWidget != (TQWidget*)o ||
           (!w || o->inherits("SizeHandle") || o->inherits("OrderIndicator")))
        break;
      if (!passiveInteractor)
        ((FormWindow*)w)->handleMouseMove((TQMouseEvent*)e, ((FormWindow*)w)->designerWidget(o));
      return !passiveInteractor;
    case TQEvent::KeyPress:
      if (((TQKeyEvent*)e)->key() == Key_Escape && currentTool() != POINTER_TOOL) {
        resetTool();
        return false;
      }
      if (!(w = isAFormWindowChild(o)) || o->inherits("SizeHandle") || o->inherits("OrderIndicator"))
        break;
      ((FormWindow*)w)->handleKeyPress((TQKeyEvent*)e, ((FormWindow*)w)->designerWidget(o));
      if (((TQKeyEvent*)e)->isAccepted())
        return true;
      break;
    case TQEvent::MouseButtonDblClick:
      if (!(w = isAFormWindowChild(o)) || o->inherits("SizeHandle") || o->inherits("OrderIndicator")) {
        if (o && o->inherits("TQToolButton") && ((TQToolButton*)o)->isOn() &&
             o->parent() && o->parent()->inherits("TQToolBar") && formWindow())
          formWindow()->setToolFixed();
        break;
      }
      if (currentTool() == ORDER_TOOL) {
        ((FormWindow*)w)->handleMouseDblClick((TQMouseEvent*)e, ((FormWindow*)w)->designerWidget(o));
        return true;
      }
      if (!WidgetFactory::isPassiveInteractor(o))
        return openEditor(((FormWindow*)w)->designerWidget(o), (FormWindow*)w);
      return true;
    case TQEvent::KeyRelease:
      if (!(w = isAFormWindowChild(o)) || o->inherits("SizeHandle") || o->inherits("OrderIndicator"))
        break;
      ((FormWindow*)w)->handleKeyRelease((TQKeyEvent*)e, ((FormWindow*)w)->designerWidget(o));
      if (((TQKeyEvent*)e)->isAccepted())
        return true;
      break;
    case TQEvent::Hide:
      if (!(w = isAFormWindowChild(o)) || o->inherits("SizeHandle") || o->inherits("OrderIndicator"))
        break;
      if (((FormWindow*)w)->isWidgetSelected(o))
        ((FormWindow*)w)->selectWidget(o, false);
      break;
    case TQEvent::Enter:
    case TQEvent::Leave:
      if (!(w = isAFormWindowChild(o)) || o->inherits("SizeHandle") || o->inherits("OrderIndicator") || o->inherits("QDesignerMenuBar"))
        break;
      return true;
    case TQEvent::Resize:
    case TQEvent::Move:
      if (!(w = isAFormWindowChild(o)) || o->inherits("SizeHandle") || o->inherits("OrderIndicator"))
        break;
      if (WidgetFactory::layoutType((TQWidget*)o->parent()) != WidgetFactory::NoLayout) {
        ((FormWindow*)w)->updateSelection((TQWidget*)o);
        if (e->type() != TQEvent::Resize)
          ((FormWindow*)w)->updateChildSelections((TQWidget*)o);
      }
      break;
    case TQEvent::Close:
      break;
    case TQEvent::DragEnter:
      if (o == qWorkspace() || o == workspace() || o == workspace()->viewport()) {
        workspace()->contentsDragEnterEvent((TQDragEnterEvent*)e);
        return true;
      }
      break;
    case TQEvent::DragMove:
      if (o == qWorkspace() || o == workspace() || o == workspace()->viewport()) {
        workspace()->contentsDragMoveEvent((TQDragMoveEvent*)e);
        return true;
      }
      break;
    case TQEvent::Drop:
      if (o == qWorkspace() || o == workspace() || o == workspace()->viewport()) {
        workspace()->contentsDropEvent((TQDropEvent*)e);
        return true;
      }
      break;
    case TQEvent::Show:
      if (o != this)
        break;
      if (((TQShowEvent*)e)->spontaneous())
        break;
      TQApplication::sendPostedEvents(qworkspace, TQEvent::ChildInserted);
      showEvent((TQShowEvent*)e);
      checkTempFiles();
      return true;
    case TQEvent::Wheel:
      if (!(w = isAFormWindowChild(o)) || o->inherits("SizeHandle") || o->inherits("OrderIndicator"))
        break;
      return true;
    case TQEvent::FocusIn:
      if (!o->inherits("FormWindow") && isAFormWindowChild(o))
        return true;
      break;
    case TQEvent::FocusOut:
      if (!o->inherits("FormWindow") && isAFormWindowChild(o))
        return true;
      break;
    default:
      return TQMainWindow::eventFilter(o, e);
  }

  return TQMainWindow::eventFilter(o, e);
}

TQWidget *MainWindow::isAFormWindowChild(TQObject *o) const
{
  if (o->parent() && o->parent()->inherits("TQWizard") && !o->inherits("TQPushButton"))
    return 0;
  while (o) {
    if (o->inherits("FormWindow"))
      return (TQWidget*)o;
    o = o->parent();
  }
  return 0;
}

TQWidget *MainWindow::isAToolBarChild(TQObject *o) const
{
  while (o) {
    if (o->inherits("QDesignerToolBar"))
      return (TQWidget*)o;
    if (o->inherits("FormWindow"))
      return 0;
    o = o->parent();
  }
  return 0;
}

FormWindow *MainWindow::formWindow()
{
  if (qworkspace->activeWindow()) {
    FormWindow *fw = 0;
    if (qworkspace->activeWindow()->inherits("FormWindow"))
      fw = (FormWindow*)qworkspace->activeWindow();
    else if (lastActiveFormWindow &&
              qworkspace->windowList().find(lastActiveFormWindow) != -1)
      fw = lastActiveFormWindow;
    return fw;
  }
  return 0;
}

void MainWindow::insertFormWindow(FormWindow *fw)
{
  if (fw)
    TQWhatsThis::add(fw, i18n("<b>The Form Window</b>"
        "<p>Use the various tools to add widgets or to change the layout "
            "and behavior of the components in the form. Select one or multiple "
            "widgets to move them or lay them out. If a single widget is chosen it can "
            "be resized using the resize handles.</p>"
            "<p>Changes in the <b>Property Editor</b> are visible at design time, "
            "and you can preview the form in different styles.</p>"
            "<p>You can change the grid resolution, or turn the grid off in the "
            "<b>Preferences</b> dialog from the <b>Edit</b> menu."
            "<p>You can have several forms open, and all open forms are listed "
            "in the <b>Form List</b>."));

  connect(fw, TQ_SIGNAL(showProperties(TQObject *)),
           this, TQ_SLOT(showProperties(TQObject *)));
  connect(fw, TQ_SIGNAL(updateProperties(TQObject *)),
           this, TQ_SLOT(updateProperties(TQObject *)));
  connect(this, TQ_SIGNAL(currentToolChanged()),
           fw, TQ_SLOT(currentToolChanged()));
  connect(fw, TQ_SIGNAL(selectionChanged()),
           this, TQ_SLOT(selectionChanged()));
  connect(fw, TQ_SIGNAL(undoRedoChanged(bool, bool, const TQString &, const TQString &)),
           this, TQ_SLOT(updateUndoRedo(bool, bool, const TQString &, const TQString &)));

  fw->show();
  fw->currentToolChanged();
  if (fw->caption().isEmpty() && tqstrlen(fw->name()) )
    fw->setCaption(fw->name());
  fw->mainContainer()->setCaption(fw->caption());
  WidgetFactory::saveDefaultProperties(fw->mainContainer(),
                                          WidgetDatabase::
                                              idFromClassName(WidgetFactory::classNameOf(fw->mainContainer())));
  activeWindowChanged(fw);
  emit formWindowsChanged();
}



bool MainWindow::unregisterClient(FormWindow *w)
{
  propertyEditor->closed(w);
  objectHierarchy()->closed(w);
  if (w == lastActiveFormWindow)
    lastActiveFormWindow = 0;

  if (actionEditor->form() == w) 
    actionEditor->setFormWindow(0);
    
  return true;
}

void MainWindow::activeWindowChanged(TQWidget *w)
{
  TQWidget *old = formWindow();
  if (w && w->inherits("FormWindow"))
  {
    FormWindow *fw = (FormWindow *) w;
    lastActiveFormWindow = fw;
    lastActiveFormWindow->updateUndoInfo();
    emit hasActiveForm(true);
    if (formWindow())
    {
      formWindow()->emitShowProperties();
      emit formModified(formWindow()->commandHistory()->isModified());
      if (currentTool() != POINTER_TOOL)
        formWindow()->clearSelection();
    }
    workspace()->activeFormChanged(fw);
    actionEditor->setFormWindow(lastActiveFormWindow);
    emit formWindowChanged();

  } else if (w == propertyEditor)
  {
    propertyEditor->resetFocus();
  } else if (!lastActiveFormWindow)
  {
    emit formWindowChanged();
    emit hasActiveForm(false);
    actionEditUndo->setEnabled(false);
    actionEditRedo->setEnabled(false);
  }

  if (!w)
  {
    emit formWindowChanged();
    emit hasActiveForm(false);
    propertyEditor->clear();
    hierarchyView->clear();
    updateUndoRedo(false, false, TQString(), TQString());
  }

  selectionChanged();

  if (currentTool() == ORDER_TOOL && w != old)
    emit currentToolChanged();

  emit hasActiveWindow(!!qworkspace->activeWindow());
}


void MainWindow::updateUndoRedo(bool undoAvailable, bool redoAvailable,
                                 const TQString &undoCmd, const TQString &redoCmd)
{
    actionEditUndo->setEnabled(undoAvailable);
    actionEditRedo->setEnabled(redoAvailable);
    if (!undoCmd.isEmpty())
        actionEditUndo->setText(i18n("&Undo: %1").arg(undoCmd));
    else
        actionEditUndo->setText(i18n("&Undo: Not Available"));
    if (!redoCmd.isEmpty())
        actionEditRedo->setText(i18n("&Redo: %1").arg(redoCmd));
    else
        actionEditRedo->setText(i18n("&Redo: Not Available"));

    actionEditUndo->setToolTip(textNoAccel(actionEditUndo->text()));
    actionEditRedo->setToolTip(textNoAccel(actionEditRedo->text()));

    if (currentTool() == ORDER_TOOL) {
        actionEditUndo->setEnabled(false);
        actionEditRedo->setEnabled(false);
    }
}

TQWorkspace *MainWindow::qWorkspace() const
{
    return qworkspace;
}

void MainWindow::popupFormWindowMenu(const TQPoint & gp, FormWindow *fw)
{
    TQValueList<int> ids;
    TQMap<TQString, int> commands;

    setupRMBSpecialCommands(ids, commands, fw);
    setupRMBProperties(ids, commands, fw);

    kapp->processEvents();
    int r = rmbFormWindow->exec(gp);

    handleRMBProperties(r, commands, fw);
    handleRMBSpecialCommands(r, commands, fw);

    for (TQValueList<int>::Iterator i = ids.begin(); i != ids.end(); ++i)
        rmbFormWindow->removeItem(*i);
}

void MainWindow::popupWidgetMenu(const TQPoint &gp, FormWindow * /*fw*/, TQWidget * w)
{
    TQValueList<int> ids;
    TQMap<TQString, int> commands;

    setupRMBSpecialCommands(ids, commands, w);
    setupRMBProperties(ids, commands, w);

    kapp->processEvents();
    int r = rmbWidgets->exec(gp);

    handleRMBProperties(r, commands, w);
    handleRMBSpecialCommands(r, commands, w);

    for (TQValueList<int>::Iterator i = ids.begin(); i != ids.end(); ++i)
        rmbWidgets->removeItem(*i);
}

void MainWindow::setupRMBProperties(TQValueList<int> &ids, TQMap<TQString, int> &props, TQWidget *w)
{
    const TQMetaProperty* text = w->metaObject()->property(w->metaObject()->findProperty("text", true), true);
    if (text && qstrcmp(text->type(), "TQString") != 0)
        text = 0;
    const TQMetaProperty* title = w->metaObject()->property(w->metaObject()->findProperty("title", true), true);
    if (title && qstrcmp(title->type(), "TQString") != 0)
        title = 0;
    const TQMetaProperty* pagetitle =
        w->metaObject()->property(w->metaObject()->findProperty("pageTitle", true), true);
    if (pagetitle && qstrcmp(pagetitle->type(), "TQString") != 0)
        pagetitle = 0;
    const TQMetaProperty* pixmap =
        w->metaObject()->property(w->metaObject()->findProperty("pixmap", true), true);
    if (pixmap && qstrcmp(pixmap->type(), "TQPixmap") != 0)
        pixmap = 0;

    if (text && text->designable(w) ||
         title && title->designable(w) ||
         pagetitle && pagetitle->designable(w) ||
         pixmap && pixmap->designable(w)) {
        int id = 0;
        if (ids.isEmpty())
            ids << rmbWidgets->insertSeparator(0);
        if (pixmap && pixmap->designable(w)) {
            ids << (id = rmbWidgets->insertItem(i18n("Choose Pixmap..."), -1, 0));
            props.insert("pixmap", id);
        }
        if (text && text->designable(w) && !w->inherits("TQTextEdit")) {
            ids << (id = rmbWidgets->insertItem(i18n("Edit Text..."), -1, 0));
            props.insert("text", id);
        }
        if (title && title->designable(w)) {
            ids << (id = rmbWidgets->insertItem(i18n("Edit Title..."), -1, 0));
            props.insert("title", id);
        }
        if (pagetitle && pagetitle->designable(w)) {
            ids << (id = rmbWidgets->insertItem(i18n("Edit Page Title..."), -1, 0));
            props.insert("pagetitle", id);
        }
    }
}

void MainWindow::setupRMBSpecialCommands(TQValueList<int> &ids, TQMap<TQString, int> &commands, TQWidget *w)
{
    int id;
    // KommanderWidget doesn't derive from TQObject
    KommanderWidget *atw = dynamic_cast<KommanderWidget *>(w);
    if(atw)
    {
            if(ids.isEmpty())
                    ids << rmbWidgets->insertSeparator(0);

            ids << (id = rmbWidgets->insertItem(i18n("Edit Kommander Text..."), -1, 0));

            commands.insert("assoc", id);
    }

    if (w->inherits("TQTabWidget")) {
        if (ids.isEmpty())
            ids << rmbWidgets->insertSeparator(0);
        if (((QDesignerTabWidget*)w)->count() > 1) {
            ids << (id = rmbWidgets->insertItem(i18n("Delete Page"), -1, 0));
            commands.insert("remove", id);
        }
        ids << (id = rmbWidgets->insertItem(i18n("Add Page"), -1, 0));
        commands.insert("add", id);
    }
     if (w->inherits("TQToolBox")) {
        if (ids.isEmpty())
            ids << rmbWidgets->insertSeparator(0);
        if (((TQToolBox*)w)->count() > 1) {
            ids << (id = rmbWidgets->insertItem(i18n("Delete Page"), -1, 0));
            commands.insert("remove", id);
        }
        ids << (id = rmbWidgets->insertItem(i18n("Add Page"), -1, 0));
        commands.insert("add", id);
    }
   if (WidgetFactory::hasSpecialEditor(WidgetDatabase::idFromClassName(WidgetFactory::classNameOf(w))))
    {
        if (ids.isEmpty())
            ids << rmbWidgets->insertSeparator(0);
        ids << (id = rmbWidgets->insertItem(i18n("Edit..."), -1, 0));
        commands.insert("edit", id);
    }
}

void MainWindow::setupRMBSpecialCommands(TQValueList<int> &ids, TQMap<TQString, int> &commands, FormWindow *fw)
{
    int id;

    // KommanderWidget doesn't derive from TQObject
    KommanderWidget *atw = dynamic_cast<KommanderWidget *>(fw->mainContainer());
    if(atw)
    {
            if(ids.isEmpty())
                    ids << rmbFormWindow->insertSeparator(0);

            ids << (id = rmbFormWindow->insertItem(i18n("Edit Kommander Text..."), -1, 0));

            commands.insert("assoc", id);
    }

    if (fw->mainContainer()->inherits("TQWizard")) {
        if (ids.isEmpty())
            ids << rmbFormWindow->insertSeparator(0);

        if (((TQWizard*)fw->mainContainer())->pageCount() > 1) {
            ids << (id = rmbFormWindow->insertItem(i18n("Delete Page"), -1, 0));
            commands.insert("remove", id);
        }

        ids << (id = rmbFormWindow->insertItem(i18n("Add Page"), -1, 0));
        commands.insert("add", id);

        ids << (id = rmbFormWindow->insertItem(i18n("Edit Page Title..."), -1, 0));
        commands.insert("rename", id);

        ids << (id = rmbFormWindow->insertItem(i18n("Edit Pages..."), -1, 0));
        commands.insert("edit", id);

    } else if (fw->mainContainer()->inherits("TQMainWindow")) {
        if (ids.isEmpty())
            ids << rmbFormWindow->insertSeparator(0);
        ids << (id = rmbFormWindow->insertItem(i18n("Add Menu Item"), -1, 0));
        commands.insert("add_menu_item", id);
        ids << (id = rmbFormWindow->insertItem(i18n("Add Toolbar"), -1, 0));
        commands.insert("add_toolbar", id);
    }
}

void MainWindow::handleRMBProperties(int id, TQMap<TQString, int> &props, TQWidget *w)
{
    if (id == props[ "text" ]) {
        bool ok = false;
        TQString text;
        if (w->inherits("TQTextView") || w->inherits("TQLabel")) {
            text = TextEditor::getText(this, w->property("text").toString());
            ok = !text.isEmpty();
        } else {
            text = KInputDialog::getText(i18n("Text"), i18n("New text:"), w->property("text").toString(), &ok, this);
        }
        if (ok) {
            TQString pn(i18n("Set the 'text' of '%1'").arg(w->name()));
            SetPropertyCommand *cmd = new SetPropertyCommand(pn, formWindow(), w, propertyEditor,
                                                              "text", w->property("text"),
                                                              text, TQString(), TQString());
            cmd->execute();
            formWindow()->commandHistory()->addCommand(cmd);
            MetaDataBase::setPropertyChanged(w, "text", true);
        }
    } else if (id == props[ "title" ]) {
        bool ok = false;
        TQString title = KInputDialog::getText(i18n("Title"), i18n("New title:"), w->property("title").toString(), &ok, this);
        if (ok) {
            TQString pn(i18n("Set the 'title' of '%1'").arg(w->name()));
            SetPropertyCommand *cmd = new SetPropertyCommand(pn, formWindow(), w, propertyEditor,
                                                              "title", w->property("title"),
                                                              title, TQString(), TQString());
            cmd->execute();
            formWindow()->commandHistory()->addCommand(cmd);
            MetaDataBase::setPropertyChanged(w, "title", true);
        }
    } else if (id == props[ "pagetitle" ]) {
        bool ok = false;
        TQString text = KInputDialog::getText(i18n("Page Title"), i18n("New page title:"), w->property("pageTitle").toString(), &ok, this);
        if (ok) {
            TQString pn(i18n("Set the 'pageTitle' of '%1'").arg(w->name()));
            SetPropertyCommand *cmd = new SetPropertyCommand(pn, formWindow(), w, propertyEditor,
                                                              "pageTitle", w->property("pageTitle"),
                                                              text, TQString(), TQString());
            cmd->execute();
            formWindow()->commandHistory()->addCommand(cmd);
            MetaDataBase::setPropertyChanged(w, "pageTitle", true);
        }
    } else if (id == props[ "pixmap" ]) {
        TQPixmap oldPix = TQVariant(w->property("pixmap")).toPixmap();
        TQPixmap pix = qChoosePixmap(this, formWindow(), oldPix);
        if (!pix.isNull()) {
            TQString pn(i18n("Set the 'pixmap' of '%1'").arg(w->name()));
            SetPropertyCommand *cmd = new SetPropertyCommand(pn, formWindow(), w, propertyEditor,
                                                              "pixmap", w->property("pixmap"),
                                                              pix, TQString(), TQString());
            cmd->execute();
            formWindow()->commandHistory()->addCommand(cmd);
            MetaDataBase::setPropertyChanged(w, "pixmap", true);
        }
    }
}

void MainWindow::handleRMBSpecialCommands(int id, TQMap<TQString, int> &commands, TQWidget *w)
{
    // associated text menu
    // we assume all widgets derive from KommanderWidget [MB02]
    if(id == commands["assoc"])
    {
         AssocTextEditor *editor = new AssocTextEditor(w, formWindow(), propertyEditor, m_partManager,
             this, "AssocTextEditor", false); //deletes itself!
         editor->show();
    }

    if (w->inherits("TQTabWidget")) {
        TQTabWidget *tw = (TQTabWidget*)w;
        if (id == commands[ "add" ]) {
            AddTabPageCommand *cmd = new AddTabPageCommand(i18n("Add Page to %1").arg(tw->name()), formWindow(),
                                                            tw, "Tab");
            formWindow()->commandHistory()->addCommand(cmd);
            cmd->execute();
        } else if (id == commands[ "remove" ]) {
            if (tw->currentPage()) {
                QDesignerTabWidget *dtw = (QDesignerTabWidget*)tw;
                DeleteTabPageCommand *cmd = new DeleteTabPageCommand(i18n("Delete Page %1 of %2").
                                                                      arg(dtw->pageTitle()).arg(tw->name()),
                                                                      formWindow(), tw, tw->currentPage());
                formWindow()->commandHistory()->addCommand(cmd);
                cmd->execute();
            }
        }
    }
    if (w->inherits("TQToolBox")) {
        TQToolBox *tw = (TQToolBox*)w;
        if (id == commands[ "add" ]) {
            AddToolBoxPageCommand *cmd = new AddToolBoxPageCommand(i18n("Add Page to %1").arg(tw->name()), formWindow(),
                                                            tw, "Page");
            formWindow()->commandHistory()->addCommand(cmd);
            cmd->execute();
        } else if (id == commands[ "remove" ]) {
            if (tw->currentItem()) {
                EditorToolBox *dtw = (EditorToolBox*)tw;
                DeleteToolBoxPageCommand *cmd = new DeleteToolBoxPageCommand(i18n("Delete Page %1 of %2").
                                                                      arg(dtw->pageTitle()).arg(tw->name()),
                                                                      formWindow(), tw, tw->currentItem());
                formWindow()->commandHistory()->addCommand(cmd);
                cmd->execute();
            }
        }
    }
    if (WidgetFactory::hasSpecialEditor(WidgetDatabase::idFromClassName(WidgetFactory::classNameOf(w)))) {
        if (id == commands[ "edit" ])
            WidgetFactory::editWidget(WidgetDatabase::idFromClassName(WidgetFactory::classNameOf(w)), this, w, formWindow());
    }
}

void MainWindow::handleRMBSpecialCommands(int id, TQMap<TQString, int> &commands, FormWindow *fw)
{

    if(id == commands["assoc"])
    {
         AssocTextEditor *editor = new AssocTextEditor(fw->mainContainer(), formWindow(), propertyEditor, m_partManager,
             this, "AssocTextEditor", false); //deletes itself!
         editor->show();
    }


    if (fw->mainContainer()->inherits("TQWizard")) {
        TQWizard *wiz = (TQWizard*)fw->mainContainer();
        if (id == commands[ "add" ]) {
            AddWizardPageCommand *cmd = new AddWizardPageCommand(i18n("Add Page to %1").arg(wiz->name()), formWindow(),
                                                                  wiz, "Page");
            formWindow()->commandHistory()->addCommand(cmd);
            cmd->execute();
        } else if (id == commands[ "remove" ]) {
            if (wiz->currentPage()) {
              QDesignerWizard *dw = (QDesignerWizard*)wiz;
                DeleteWizardPageCommand *cmd = new DeleteWizardPageCommand(i18n("Delete Page %1 of %2").
                                                                            arg(dw->pageTitle()).arg(wiz->name()),
                                                                            formWindow(), wiz, wiz->indexOf(wiz->currentPage()));
                formWindow()->commandHistory()->addCommand(cmd);
                cmd->execute();
            }
        } else if (id == commands[ "edit" ]) {
            WizardEditor *e = new WizardEditor(this, wiz, fw);
            e->exec();
            delete e;
        } else if (id == commands[ "rename" ]) {

            bool ok = false;
            QDesignerWizard *dw = (QDesignerWizard*)wiz;
            TQString text = KInputDialog::getText(i18n("Page Title"), i18n("New page title:"), dw->pageTitle(), &ok, this);
            if (ok) {
                TQString pn(i18n("Rename page %1 of %2").arg(dw->pageTitle()).arg(wiz->name()));
                RenameWizardPageCommand *cmd = new RenameWizardPageCommand(pn, formWindow()
                                                                            , wiz, wiz->indexOf(wiz->currentPage()), text);
                formWindow()->commandHistory()->addCommand(cmd);
                cmd->execute();
            }
        }
    } else if (fw->mainContainer()->inherits("TQMainWindow")) {
        TQMainWindow *mw = (TQMainWindow*)fw->mainContainer();
        if (id == commands[ "add_toolbar" ]) {
            AddToolBarCommand *cmd = new AddToolBarCommand(i18n("Add Toolbar to '%1'").arg(formWindow()->name()), formWindow(), mw);
            formWindow()->commandHistory()->addCommand(cmd);
            cmd->execute();
        } else if (id == commands[ "add_menu_item" ]) {
            AddMenuCommand *cmd = new AddMenuCommand(i18n("Add Menu to '%1'").arg(formWindow()->name()), formWindow(), mw);
            formWindow()->commandHistory()->addCommand(cmd);
            cmd->execute();
        }
    }
}

void MainWindow::clipboardChanged()
{
    TQString text(kapp->clipboard()->text());
    TQString start("<!DOCTYPE UI-SELECTION>");
    actionEditPaste->setEnabled(text.left(start.length()) == start);
}

void MainWindow::selectionChanged()
{
    layoutChilds = false;
    layoutSelected = false;
    breakLayout = false;
    if (!formWindow()) {
        actionEditCut->setEnabled(false);
        actionEditCopy->setEnabled(false);
        actionEditDelete->setEnabled(false);
        actionEditAdjustSize->setEnabled(false);
        actionEditHLayout->setEnabled(false);
        actionEditVLayout->setEnabled(false);
        actionEditSplitHorizontal->setEnabled(false);
        actionEditSplitVertical->setEnabled(false);
        actionEditGridLayout->setEnabled(false);
        actionEditBreakLayout->setEnabled(false);
        actionEditLower->setEnabled(false);
        actionEditRaise->setEnabled(false);
        actionEditAdjustSize->setEnabled(false);
        return;
    }

    int selectedWidgets = formWindow()->numSelectedWidgets();
    bool enable = selectedWidgets > 0;
    actionEditCut->setEnabled(enable);
    actionEditCopy->setEnabled(enable);
    actionEditDelete->setEnabled(enable);
    actionEditLower->setEnabled(enable);
    actionEditRaise->setEnabled(enable);

    actionEditAdjustSize->setEnabled(false);
    actionEditSplitHorizontal->setEnabled(false);
    actionEditSplitVertical->setEnabled(false);

    enable = false;
    TQWidgetList widgets = formWindow()->selectedWidgets();
    if (selectedWidgets > 1) {
        int unlaidout = 0;
        int laidout = 0;
        for (TQWidget *w = widgets.first(); w; w = widgets.next()) {
            if (!w->parentWidget() || WidgetFactory::layoutType(w->parentWidget()) == WidgetFactory::NoLayout)
                unlaidout++;
            else
                laidout++;
        }
        actionEditHLayout->setEnabled(unlaidout > 1);
        actionEditVLayout->setEnabled(unlaidout > 1);
        actionEditSplitHorizontal->setEnabled(unlaidout > 1);
        actionEditSplitVertical->setEnabled(unlaidout > 1);
        actionEditGridLayout->setEnabled(unlaidout > 1);
        actionEditBreakLayout->setEnabled(laidout > 0);
        actionEditAdjustSize->setEnabled(laidout > 0);
        layoutSelected = unlaidout > 1;
        breakLayout = laidout > 0;
    } else if (selectedWidgets == 1) {
        TQWidget *w = widgets.first();
        bool isContainer = WidgetDatabase::isContainer(WidgetDatabase::idFromClassName(WidgetFactory::classNameOf(w))) ||
                           w == formWindow()->mainContainer();
        actionEditAdjustSize->setEnabled(!w->parentWidget() ||
                                          WidgetFactory::layoutType(w->parentWidget()) == WidgetFactory::NoLayout);

        if (!isContainer) {
            actionEditHLayout->setEnabled(false);
            actionEditVLayout->setEnabled(false);
            actionEditGridLayout->setEnabled(false);
            if (w->parentWidget() && WidgetFactory::layoutType(w->parentWidget()) != WidgetFactory::NoLayout) {
                actionEditBreakLayout->setEnabled(!isAToolBarChild(w));
                breakLayout = true;
            } else {
                actionEditBreakLayout->setEnabled(false);
            }
        } else {
            if (WidgetFactory::layoutType(w) == WidgetFactory::NoLayout) {
                if (!formWindow()->hasInsertedChildren(w)) {
                    actionEditHLayout->setEnabled(false);
                    actionEditVLayout->setEnabled(false);
                    actionEditGridLayout->setEnabled(false);
                    actionEditBreakLayout->setEnabled(false);
                } else {
                    actionEditHLayout->setEnabled(true);
                    actionEditVLayout->setEnabled(true);
                    actionEditGridLayout->setEnabled(true);
                    actionEditBreakLayout->setEnabled(false);
                    layoutChilds = true;
                }
                if (w->parentWidget() && WidgetFactory::layoutType(w->parentWidget()) != WidgetFactory::NoLayout) {
                    actionEditBreakLayout->setEnabled(!isAToolBarChild(w));
                    breakLayout = true;
                }
            } else {
                actionEditHLayout->setEnabled(false);
                actionEditVLayout->setEnabled(false);
                actionEditGridLayout->setEnabled(false);
                actionEditBreakLayout->setEnabled(!isAToolBarChild(w));
                breakLayout = true;
            }
        }
    } else if (selectedWidgets == 0 && formWindow()) {
        actionEditAdjustSize->setEnabled(true);
        TQWidget *w = formWindow()->mainContainer();
        if (WidgetFactory::layoutType(w) == WidgetFactory::NoLayout) {
            if (!formWindow()->hasInsertedChildren(w)) {
                actionEditHLayout->setEnabled(false);
                actionEditVLayout->setEnabled(false);
                actionEditGridLayout->setEnabled(false);
                actionEditBreakLayout->setEnabled(false);
            } else {
                actionEditHLayout->setEnabled(true);
                actionEditVLayout->setEnabled(true);
                actionEditGridLayout->setEnabled(true);
                actionEditBreakLayout->setEnabled(false);
                layoutChilds = true;
            }
        } else {
            actionEditHLayout->setEnabled(false);
            actionEditVLayout->setEnabled(false);
            actionEditGridLayout->setEnabled(false);
            actionEditBreakLayout->setEnabled(true);
            breakLayout = true;
        }
    } else {
        actionEditHLayout->setEnabled(false);
        actionEditVLayout->setEnabled(false);
        actionEditGridLayout->setEnabled(false);
        actionEditBreakLayout->setEnabled(false);
    }
}

void MainWindow::writeConfig()
{
  TDEConfig* config = kapp->config();

  config->setGroup("General");
  config->writeEntry("RestoreWorkspace", restoreConfig);
  config->writeEntry("SplashScreen", splashScreen);
  config->writeEntry("X-DocPath", docPath);
  config->writeEntry("TemplatePath", templPath);

  config->setGroup("Grid");
  config->writeEntry("Snap", snGrid);
  config->writeEntry("Show", sGrid);
  config->writeEntry("x", grid().x());
  config->writeEntry("y", grid().y());

  config->setGroup("Background");
  config->writeEntry("UsePixmap", backPix);
  config->writeEntry("Color", TQString(qworkspace->backgroundColor().name()));

  /*
  config->setGroup("Geometry");
  config->writeEntry("MainWindow", size());
  config->writeEntry("MainWindowMax", isMaximized());
  */
  writeDockConfig(config, "Docks");

  config->setGroup("View");
  config->writeEntry("TextLabels", usesTextLabel());
  config->writeEntry("BigIcons", usesBigPixmaps());

  actionCollection()->writeShortcutSettings("Keys", config);

  config->deleteGroup("Recent Files");
  actionRecent->saveEntries(config, "Recent Files");
}

void MainWindow::readConfig()
{
  TDEConfig *config = kapp->config();

  config->setGroup("General");
  restoreConfig = config->readBoolEntry("RestoreWorkspace", true);
  splashScreen = config->readBoolEntry("SplashScreen", true);
  docPath = config->readEntry("X-DocPath", docPath);
  templPath = config->readEntry("TemplatePath", TQString());

  config->setGroup("Grid");
  sGrid = config->readBoolEntry("Snap", true);
  snGrid = config->readBoolEntry("Show", true);
  grd.setX(config->readNumEntry("x", 10));
  grd.setY(config->readNumEntry("y", 10));

  config->setGroup("Background");
  if (config->readBoolEntry("UsePixmap", true))
    qworkspace->setBackgroundPixmap(PixmapChooser::loadPixmap("background.png", PixmapChooser::NoSize));
  else
    qworkspace->setBackgroundColor(TQColor(config->readEntry("Color", "#f0f0f0")).rgb());

  /*
  config->setGroup("Geometry");
  TQSize winSize = size();
  resize(config->readSizeEntry("MainWindow", &winSize));
  if (config->readBoolEntry("MainWindowMax", false))
    showMaximized();
  */
  readDockConfig(config, "Docks");


  config->setGroup("View");
  setUsesTextLabel(config->readBoolEntry("TextLabels", false));
  setUsesBigPixmaps(config->readBoolEntry("BigIcons", false));

  actionCollection()->readShortcutSettings("Keys", config);

  actionRecent->loadEntries(config, "Recent Files");

  TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
  for(int i = 0; i < args->count(); i++)
  {
    TQFileInfo fi(args->url(i).path());
    if (fi.exists() && openFormWindow(args->url(i).path()))
      actionRecent->addURL(args->url(i));
  }
  args->clear();
}


HierarchyView *MainWindow::objectHierarchy() const
{
  if (!hierarchyView)
    ((MainWindow *) this)->setupHierarchyView();
  return hierarchyView;
}

TQPopupMenu *MainWindow::setupNormalHierarchyMenu(TQWidget *parent)
{
  TQPopupMenu *menu = new TQPopupMenu(parent);

  actionEditCut->plug(menu);
  actionEditCopy->plug(menu);
  actionEditPaste->plug(menu);
  actionEditDelete->plug(menu);

  return menu;
}

TQPopupMenu *MainWindow::setupTabWidgetHierarchyMenu(TQWidget *parent, const char *addSlot, const char *removeSlot)
{
    TQPopupMenu *menu = new TQPopupMenu(parent);

    menu->insertItem(i18n("Add Page"), parent, addSlot);
    menu->insertItem(i18n("Delete Page"), parent, removeSlot);
    menu->insertSeparator();
    actionEditCut->plug(menu);
    actionEditCopy->plug(menu);
    actionEditPaste->plug(menu);
    actionEditDelete->plug(menu);

    return menu;
}

void MainWindow::closeEvent(TQCloseEvent *e)
{
  TQWidgetList windows = qWorkspace()->windowList();
  TQWidgetListIt wit(windows);
  while (wit.current())
  {
    TQWidget *w = wit.current();
    ++wit;
    if (w->inherits("FormWindow"))
    {
      if (!((FormWindow *) w)->formFile()->close())
      {
        e->ignore();
        return;
      }
    }
  }

  writeConfig();
  hide();
  e->accept();

  if (client)
  {
    TQDir home(TQDir::homeDirPath());
    home.remove(".designerpid");
  }
}

Workspace *MainWindow::workspace() const
{
    if (!wspace)
        ((MainWindow*)this)->setupWorkspace();
    return wspace;
}

PropertyEditor *MainWindow::propertyeditor() const
{
    if (!propertyEditor)
        ((MainWindow*)this)->setupPropertyEditor();
    return propertyEditor;
}

ActionEditor *MainWindow::actioneditor() const
{
    if (!actionEditor)
        ((MainWindow*)this)->setupActionEditor();
    return actionEditor;
}

bool MainWindow::openEditor(TQWidget* w, FormWindow*)
{
    if (WidgetFactory::hasSpecialEditor(WidgetDatabase::idFromClassName(WidgetFactory::classNameOf(w)))) {
        statusBar()->message(i18n("Edit %1...").arg(w->className()));
        WidgetFactory::editWidget(WidgetDatabase::idFromClassName(WidgetFactory::classNameOf(w)), this, w, formWindow());
        statusBar()->clear();
        return true;
    }

    const TQMetaProperty* text = w->metaObject()->property(w->metaObject()->findProperty("text", true), true);
    const TQMetaProperty* title = w->metaObject()->property(w->metaObject()->findProperty("title", true), true);
    if (text && text->designable(w)) {
        bool ok = false;
        TQString text;
        if (w->inherits("TQTextView") || w->inherits("TQLabel")) {
            text = TextEditor::getText(this, w->property("text").toString());
            ok = !text.isEmpty();
        } else {
            text = KInputDialog::getText(i18n("Text"), i18n("New text:"), w->property("text").toString(), &ok, this);
        }
        if (ok) {
            TQString pn(i18n("Set the 'text' of '%2'").arg(w->name()));
            SetPropertyCommand *cmd = new SetPropertyCommand(pn, formWindow(), w, propertyEditor,
                                                              "text", w->property("text"),
                                                              text, TQString(), TQString());
            cmd->execute();
            formWindow()->commandHistory()->addCommand(cmd);
            MetaDataBase::setPropertyChanged(w, "text", true);
        }
        return true;
    }
    if (title && title->designable(w)) {
        bool ok = false;
        TQString text;
        text = KInputDialog::getText(i18n("Title"), i18n("New title:"), w->property("title").toString(), &ok, this);
        if (ok) {
            TQString pn(i18n("Set the 'title' of '%2'").arg(w->name()));
            SetPropertyCommand *cmd = new SetPropertyCommand(pn, formWindow(), w, propertyEditor,
                                                              "title", w->property("title"),
                                                              text, TQString(), TQString());
            cmd->execute();
            formWindow()->commandHistory()->addCommand(cmd);
            MetaDataBase::setPropertyChanged(w, "title", true);
        }
        return true;
    }

    return true;
}

void MainWindow::setGrid(const TQPoint &p)
{
    if (p == grd)
        return;
    grd = p;
    TQWidgetList windows = qWorkspace()->windowList();
    for (TQWidget *w = windows.first(); w; w = windows.next()) {
        if (!w->inherits("FormWindow"))
            continue;
        ((FormWindow*)w)->mainContainer()->update();
    }
}

void MainWindow::setShowGrid(bool b)
{
    if (b == sGrid)
        return;
    sGrid = b;
    TQWidgetList windows = qWorkspace()->windowList();
    for (TQWidget *w = windows.first(); w; w = windows.next()) {
        if (!w->inherits("FormWindow"))
            continue;
        ((FormWindow*)w)->mainContainer()->update();
    }
}

void MainWindow::setSnapGrid(bool b)
{
    if (b == snGrid)
        return;
    snGrid = b;
}

TQString MainWindow::documentationPath() const
{
    TQString result = docPath;

    if (docPath[0] == '$') {
        int fs = docPath.find('/');
        if (fs == -1)
            fs = docPath.find('\\');

        if (fs > -1) {
            result = docPath.mid(1, fs-1);
        } else {
            fs=docPath.length();
            result = docPath.right(fs-1);
        }
        result = getenv(result.latin1()) + docPath.right(docPath.length()-fs);
    }

    return result;
}

void MainWindow::windowsMenuActivated(int id)
{
    TQWidget* w = qworkspace->windowList().at(id);
    if (w)
        w->setFocus();
}



void MainWindow::checkTempFiles()
{
    TQString s = TQDir::homeDirPath() + "/.designer";
    TQString baseName = s+ "/saved-form-";
    if (!TQFile::exists(baseName + "1.kmdr"))
        return;
    TQDir d(s);
    d.setNameFilter("*.kmdr");
    TQStringList lst = d.entryList();
    TQApplication::restoreOverrideCursor();
    bool load = KMessageBox::questionYesNo(this,
                i18n("Kommander found some temporary saved files, which were\n"
                "written when Kommander crashed last time. Do you want to\n"
                    "load these files?"), i18n("Restoring Last Session"), i18n("Load"), i18n("Do Not Load")) == KMessageBox::Yes;
    TQApplication::setOverrideCursor(waitCursor);
    for (TQStringList::Iterator it = lst.begin(); it != lst.end(); ++it) {
        if (load)
            openFormWindow(s + "/" + *it, false);
        d.remove(*it);
    }
}

void MainWindow::showDialogHelp()
{
    TQWidget *w = (TQWidget*)sender();
    w = w->topLevelWidget();

    TQString link = "designer-manual-12.html#";

    if (w->inherits("NewFormBase"))
        link += "dialog-file-new";
    else if (w->inherits("CreateTemplate"))
        link += "dialog-file-create-template";
    else if (w->inherits("EditSlotsBase"))
        link += "dialog-edit-slots";
    else if (w->inherits("ConnectionViewerBase"))
        link += "dialog-view-connections";
    else if (w->inherits("FormSettingsBase"))
        link += "dialog-edit-form-settings";
    else if (w->inherits("Preferences"))
        link += "dialog-edit-preferences";
    else if (w->inherits("PixmapCollectionEditor"))
        link += "dialog-image-collection";
    else if (w->inherits("DatabaseConnectionBase"))
        link += "dialog-edit-database-connections";
    else if (w->inherits("FindDialog"))
        link += "dialog-find-text";
    else if (w->inherits("ReplaceDialog"))
        link += "dialog-replace-text";
    else if (w->inherits("GotoLineDialog"))
        link += "dialog-go-to-line";
    else if (w->inherits("ConnectionEditorBase"))
        link += "dialog-edit-connections";
    else if (w->inherits("PaletteEditorBase"))
        link += "dialog-edit-palette";
    else if (w->inherits("ListBoxEditorBase"))
        link += "dialog-edit-listbox";
    else if (w->inherits("ListViewEditorBase"))
        link += "dialog-edit-listview";
    else if (w->inherits("IconViewEditorBase"))
        link += "dialog-edit-iconview";
    else if (w->inherits("TableEditorBase"))
        link += "dialog-edit-table";

    else {
        KMessageBox::information(this, 
            i18n("There is no help available for this dialog at the moment."), i18n("Help"));
        return;
    }

    if (assistant)
        assistant->sendRequest(link+'\n');
}



void MainWindow::fileOpenRecent(const KURL& filename)
{
  if (!TQFile::exists(filename.path()))
  {
    KMessageBox::error(this, i18n("<qt>Could not open file:<br><b>%1</b><br>File does not exist.</qt>").
        arg(filename.path()), i18n("Open File"));
    actionRecent->removeURL(filename);
  }
  else
    fileOpen(filename.path());
}

void MainWindow::setupPlugins()
{
  KommanderFactory::loadPlugins();
}



void MainWindow::setModified(bool b, TQWidget *window)
{
  TQWidget *w = window;
  while (w)
  {
    if (w->inherits("FormWindow"))
    {
      ((FormWindow *) w)->modificationChanged(b);
      return;
    }
    w = w->parentWidget(true);
    if (w->inherits("FormWindow"))
    {
      ((FormWindow *) w)->modificationChanged(b);
      return;
    }
    w = w->parentWidget(true);
  }
}


void MainWindow::updateWorkspace()
{
}

TQWidget *MainWindow::findRealForm(TQWidget *wid)
{
    TQWidgetList windows = qWorkspace()->windowList();
    for (TQWidget *w = windows.first(); w; w = windows.next()) {
        if (TQString(w->name()) == TQString(wid->name()))
            return w;
    }
    return 0;
}

void MainWindow::formNameChanged(FormWindow*)
{
}


int MainWindow::currentLayoutDefaultSpacing() const
{
    if (((MainWindow*)this)->formWindow())
        return ((MainWindow*)this)->formWindow()->layoutDefaultSpacing();
    return BOXLAYOUT_DEFAULT_SPACING;
}

int MainWindow::currentLayoutDefaultMargin() const
{
    if (((MainWindow*)this)->formWindow())
        return ((MainWindow*)this)->formWindow()->layoutDefaultMargin();
    return BOXLAYOUT_DEFAULT_MARGIN;
}

TQString MainWindow::whatsThisFrom(const TQString&)
{
  return TQString();
}

void MainWindow::slotActivePartChanged(KParts::Part * part)
{
//   kdDebug(24000) << "ActivePartChanged" << part << endl; 
  if (part) // if part == 0L the pointer m_oldKTextEditor is not useable
  {
  //  guiFactory()->removeClient(part);
  }
  createGUI(part);
  if (part)
  {
    guiFactory()->addClient(part);
  }
}

#include "mainwindow.moc"

