/***************************************************************************
                          plugin_katesymbolviewer.cpp  -  description
                             -------------------
    begin                : Apr 2 2003
    author               : 2003 Massimo Callegari
    email                : massimocallegari@yahoo.it
    
    Changes:
    Apr 07 2003 v 0.1 - First version.
    Apr 19 2003 v 0.2 - Added to CVS. Extract functions and structures
    Apr 22 2003 v 0.3 - Added macro extraction + several bugfixing
    Apr 23 2003 v 0.4 - "View Symbol" moved in Settings menu. "Refresh List" is no
                        longer in Kate menu. Moved into a popup menu activated by a
                        mouse right button click. + Bugfixing.
    Apr 24 2003 v 0.5 - Added three check buttons in popup menu to show/hide symbols
    May 04 2003 v 0.6 - Symbol List becomes a KListView object. Removed Tooltip class.
                        Added a QTimer that every 200ms checks:
                        * if the list width has changed
                        * if the document has changed
                        Added an entry in the popup menu to switch between List and Tree mode
                        Various bugfixing.
    Jun 19 2003 v.1.0 - Removed QTimer (polling is Evil(tm)... )
                        - Captured documentChanged() event to refresh symbol list
                        - Tooltips vanished into nowhere...sigh :(
    Nov 28 2003 v.1.1 - Structured for multilanguage support
                        Added preliminary Tcl/Tk parser (thanks Rohit). To be improved.
                        Various bugfixing.
 ***************************************************************************/
/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
 
#include "plugin_katesymbolviewer.h"
#include "plugin_katesymbolviewer.moc"

#include <kaction.h>
#include <klocale.h>
#include <kstandarddirs.h>
#include <kgenericfactory.h>

K_EXPORT_COMPONENT_FACTORY( katecppsymbolviewerplugin, KGenericFactory<KatePluginSymbolViewer>( "katesymbolviewer" ) )

KatePluginSymbolViewerView::KatePluginSymbolViewerView(Kate::MainWindow *w)
{
    (void) new KToggleAction ( i18n("Show Symbols"), 0, this,
                      SLOT( slotInsertSymbol() ), actionCollection(),
                      "view_insert_symbolviewer" );
                      
    setInstance (new KInstance("kate"));
    setXMLFile("plugins/katecppsymbolviewer/ui.rc");
    w->guiFactory()->addClient (this);
  win = w;
  symbols = 0;

 m_Active = false;
 popup = new QPopupMenu();
 popup->insertItem(i18n("Refresh List"), this, SLOT(slotRefreshSymbol()));
 popup->insertSeparator();
 m_macro = popup->insertItem(i18n("Show Macros"), this, SLOT(toggleShowMacros()));
 m_struct = popup->insertItem(i18n("Show Structures"), this, SLOT(toggleShowStructures()));
 m_func = popup->insertItem(i18n("Show Functions"), this, SLOT(toggleShowFunctions()));
 popup->insertSeparator();
 popup->insertItem(i18n("List/Tree Mode"), this, SLOT(slotChangeMode()));
 
 popup->setItemChecked(m_macro, true);
 popup->setItemChecked(m_struct, true);
 popup->setItemChecked(m_func, true);
 macro_on = true;
 struct_on = true;
 func_on = true;
}

KatePluginSymbolViewerView::~KatePluginSymbolViewerView()
{
  win->guiFactory()->removeClient (this);
  if (symbols)
    win->toolViewManager()->removeToolView(symbols);
}

void KatePluginSymbolViewerView::toggleShowMacros(void)
{
 bool s = !popup->isItemChecked(m_macro);
 popup->setItemChecked(m_macro, s);
 macro_on = s;
 slotRefreshSymbol();
}

void KatePluginSymbolViewerView::toggleShowStructures(void)
{
 bool s = !popup->isItemChecked(m_struct);
 popup->setItemChecked(m_struct, s);
 struct_on = s;
 slotRefreshSymbol();
}

void KatePluginSymbolViewerView::toggleShowFunctions(void)
{
 bool s = !popup->isItemChecked(m_func);
 popup->setItemChecked(m_func, s);
 func_on = s;
 slotRefreshSymbol();
}

void KatePluginSymbolViewerView::slotInsertSymbol()
{
 QPixmap cls( ( const char** ) class_xpm );
 
 if (m_Active == false)
     {
      symbols = new KListView(0);
      listMode = 0;
      
      connect(symbols, SIGNAL(executed(QListViewItem *)), this, SLOT(goToSymbol(QListViewItem *)));
      connect(symbols, SIGNAL(rightButtonClicked(QListViewItem *, const QPoint&, int)),
               SLOT(slotShowContextMenu(QListViewItem *, const QPoint&, int)));
      connect(win->viewManager(), SIGNAL(viewChanged()), this, SLOT(slotDocChanged()));
      connect(symbols, SIGNAL(resizeEvent(QResizeEvent * e)), this, SLOT(slotViewChanged(QResizeEvent * e)));
      
      win->toolViewManager()->addToolView(KDockWidget::DockLeft, symbols, cls, i18n("Symbol List"));
          
      m_Active = true;
      //symbols->addColumn(i18n("Symbols"), symbols->parentWidget()->width());
      symbols->addColumn(i18n("Symbols"));
      symbols->setSorting(-1, FALSE);
      symbols->setRootIsDecorated(0);
      symbols->setTreeStepSize(10);
      symbols->setShowToolTips(TRUE);
     
      /* First Symbols parsing here...*/
      parseSymbols();
     }
  else
     {
      win->toolViewManager()->removeToolView(symbols);
      symbols = 0;
      m_Active = false;
     }
}

void KatePluginSymbolViewerView::slotRefreshSymbol()
{
  if (!symbols)
    return;
 symbols->clear();
 parseSymbols();
}

void KatePluginSymbolViewerView::slotChangeMode()
{
 listMode = !listMode;
 symbols->clear();
 parseSymbols();
}

void KatePluginSymbolViewerView::slotDocChanged()
{
 //kdDebug(13000)<<"Document changed !!!!"<<endl;
 slotRefreshSymbol();
}

void KatePluginSymbolViewerView::slotViewChanged(QResizeEvent *)
{
 kdDebug(13000)<<"View changed !!!!"<<endl;
 symbols->setColumnWidth(0, symbols->parentWidget()->width());
}

void KatePluginSymbolViewerView::slotShowContextMenu(QListViewItem *, const QPoint &p, int)
{
 popup->popup(p);
}

void KatePluginSymbolViewerView::parseSymbols(void)
{
  if (!win->viewManager()->activeView())
    return;

  Kate::Document *kv = win->viewManager()->activeView()->getDoc();
  
  // be sure we have some document around !
  if (!kv)
    return;
  
  QString docName = kv->docName();
  if(docName.endsWith(".cpp") || docName.endsWith(".c") || docName.endsWith(".h"))
      parseCppSymbols();
  else if(docName.endsWith(".tcl") || docName.endsWith(".tk")) 
      parseTclSymbols();
}

void KatePluginSymbolViewerView::goToSymbol(QListViewItem *it)
{  
  Kate::View *kv = win->viewManager()->activeView();
  
  // be sure we really have a view !
  if (!kv)
    return;
  
  kdDebug(13000)<<"Slot Activated at pos: "<<symbols->itemIndex(it) <<endl;
  kv->gotoLineNumber(positions.at(symbols->itemIndex(it)) + 10);
  kv->setFocus();
  kv->gotoLineNumber(positions.at(symbols->itemIndex(it)));
}

KatePluginSymbolViewer::KatePluginSymbolViewer( QObject* parent, const char* name, const QStringList& )
    : Kate::Plugin ( (Kate::Application*)parent, name )
{
}

KatePluginSymbolViewer::~KatePluginSymbolViewer()
{
}

void KatePluginSymbolViewer::addView (Kate::MainWindow *win)
{
  KatePluginSymbolViewerView *view = new KatePluginSymbolViewerView (win);           
  m_views.append (view);
}   

void KatePluginSymbolViewer::removeView(Kate::MainWindow *win)
{
  for (uint z=0; z < m_views.count(); z++)
    if (m_views.at(z)->win == win)
    {
      KatePluginSymbolViewerView *view = m_views.at(z);
      m_views.remove (view);
      delete view;
    }  
}
