You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kile/src/kile/kilestructurewidget.cpp

1016 lines
30 KiB

/***************************************************************************
begin : Sun Dec 28 2003
copyright : (C) 2003 by Jeroen Wijnhout
2005-2007 by Holger Danielsson
email : Jeroen.Wijnhout@kdemail.net
holger.danielsson@versanet.de
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
// 2005-11-02: dani
// - cleaning up source (local variables etc.)
// - added different TQToolTips for each item
// - add more types of KilelistViewItems
// - KileStruct::Sect and KileStruct::BeginFloat will remember assigned labels,
// which are displayed as TQToolTips, if these labels are defined in the
// same or the next line
// - Caption for type KileStruct::BeginFloat are displayed in the title
// of this item
// - \includegraphics and float environment items are displayed
// - if an item has a companion label, you can use the context menu (right mouse)
// to insert this label as reference, as a page reference or only the keyword
// into the text or copy it to the clipboard.
// - graphics files have also a context menu to open them with a special program
// 2005-12-08: dani
// - make some items like labels, bibitems, graphics and float environments
// configurable for the user
// 2005-12-16: dani
// - add listview item for undefined references
// 2007-02-15: dani
// - class KileListViewItem gets two new members to
// save the real cursor position of the command
// 2007-03-12 dani
// - use KileDocument::Extensions
// 2007-03-17 dani
// - remember how document structure is collapsed, when structure view is refreshed
// 2007-03-24: dani
// - preliminary minimal support for Beamer class
// - \begin{frame}...\end{frame} and \frame{...} are shown in the structure view
// - if a \frametitle command follows as next LaTeX command, its parameter
// is taken to replace the standard title of this entry in the structure view
// - \begin{block}...\end{block} is taken as child of a frame
// 2007-04-06 dani
// - add TODO/FIXME section to structure view
#include "kilestructurewidget.h"
#include <tqfileinfo.h>
#include <tqheader.h>
#include <tqregexp.h>
#include <tqclipboard.h>
#include <tdeapplication.h>
#include "kiledebug.h"
#include <tdemessagebox.h>
#include <tdelocale.h>
#include <kiconloader.h>
#include <kurl.h>
#include <krun.h>
#include <kmimetype.h>
#include <tdetexteditor/markinterface.h>
#include "kileinfo.h"
#include "kiledocmanager.h"
#include "kiledocumentinfo.h"
#include "kileconfig.h"
////////////////////// KileListViewItem with all info //////////////////////
KileListViewItem::KileListViewItem(TQListViewItem * parent, TQListViewItem * after, const TQString &title, const KURL &url, uint line, uint column, int type, int level, uint startline, uint startcol) :
TDEListViewItem(parent,after),
m_title(title), m_url(url), m_line(line), m_column(column), m_type(type), m_level(level),
m_startline(startline), m_startcol(startcol)
{
setItemEntry();
}
KileListViewItem::KileListViewItem(TQListView * parent, const TQString & label) :
TDEListViewItem(parent,label),
m_title(label), m_url(KURL()), m_line(0), m_column(0), m_type(KileStruct::None), m_level(0)
{}
KileListViewItem::KileListViewItem(TQListViewItem * parent, const TQString & label) :
TDEListViewItem(parent,label),
m_title(label), m_url(KURL()), m_line(0), m_column(0), m_type(KileStruct::None), m_level(0)
{}
void KileListViewItem::setTitle(const TQString &title)
{
m_title = title;
setItemEntry();
}
void KileListViewItem::setItemEntry()
{
setText(0, m_title + " (" + i18n("line") + ' ' + TQString::number(m_line) + ')');
}
////////////////////// introduce a new ToolTip //////////////////////
KileListViewToolTip::KileListViewToolTip(TDEListView *listview) : TQToolTip(listview->viewport()), m_listview(listview)
{}
void KileListViewToolTip::maybeTip(const TQPoint &p)
{
if ( ! m_listview )
return;
const KileListViewItem *item = (KileListViewItem *)m_listview->itemAt(p);
// if ( !item || item->label().isNull() )
if ( !item )
return;
const TQRect rect = m_listview->itemRect(item);
if ( ! rect.isValid() )
return;
if ( ! item->label().isNull() )
{
tip(rect,i18n("Label: ") + item->label());
}
else if ( item->line()==0 && item->column()==0 && item->parent()==0L ) // only root
{
tip(rect,i18n("Click left to jump to the line. A double click will open\n a text file or a graphics file. When a label is assigned\nto this item, it will be shown when the mouse is over\nthis item. Items for a graphics file or an assigned label\nalso offer a context menu (right mouse button)."));
}
}
namespace KileWidget
{
////////////////////// StructureList listview //////////////////////
StructureList::StructureList(Structure *stack, KileDocument::Info *docinfo) :
TDEListView(stack),
m_stack(stack), m_docinfo(docinfo)
{
show();
header()->hide();
addColumn(i18n("Structure"),-1);
setSorting(-1,true);
setAllColumnsShowFocus(true);
setFullWidth(true);
setSizePolicy(TQSizePolicy::Ignored,TQSizePolicy::Ignored);
TQToolTip::remove(this);
new KileListViewToolTip(this);
//connect(this, TQT_SIGNAL(clicked(TQListViewItem *)), m_stack, TQT_SLOT(slotClicked(TQListViewItem *)));
connect(this, TQT_SIGNAL(doubleClicked(TQListViewItem *)), m_stack, TQT_SLOT(slotDoubleClicked(TQListViewItem *)));
connect(this, TQT_SIGNAL(contextMenu(TDEListView *, TQListViewItem *, const TQPoint & )), m_stack, TQT_SLOT(slotPopup(TDEListView *, TQListViewItem * , const TQPoint & )));
connect(this, TQT_SIGNAL(executed(TQListViewItem*)), m_stack, TQT_SLOT(slotClicked(TQListViewItem*)));
connect(m_stack, TQT_SIGNAL(configChanged()), this, TQT_SLOT(slotConfigChanged()));
init();
}
StructureList::~StructureList() {}
void StructureList::init()
{
TQString title = (m_docinfo == 0L ) ? i18n("No \"structure data\" to display.") : m_docinfo->url().fileName();
m_root = new KileListViewItem(this, title);
if ( m_docinfo != 0L )
{
m_root->setURL(m_docinfo->url());
m_root->setOpen(true);
m_root->setPixmap(0, SmallIcon("contents"));
connect(m_docinfo, TQT_SIGNAL(foundItem(const TQString&, uint, uint, int, int, uint, uint, const TQString &, const TQString &)),
this, TQT_SLOT(addItem(const TQString&, uint, uint, int, int, uint, uint, const TQString &, const TQString &)));
// connect(m_docinfo, TQT_SIGNAL(doneUpdating()), this, TQT_SLOT(insertInMasterList()));
}
m_parent[0]=m_parent[1]=m_parent[2]=m_parent[3]=m_parent[4]=m_parent[5]=m_parent[6]=m_root;
m_lastType = KileStruct::None;
m_lastSectioning = 0L;
m_lastFloat = 0L;
m_lastFrame = 0L;
m_lastFrameEnv = 0L;
m_stop = false;
m_folders.clear();
m_references.clear();
if ( m_docinfo )
{
m_openStructureLabels = m_docinfo->openStructureLabels();
m_openStructureReferences = m_docinfo->openStructureReferences();
m_openStructureBibitems = m_docinfo->openStructureBibitems();
m_openStructureTodo = m_docinfo->openStructureTodo();
m_showStructureLabels = m_docinfo->showStructureLabels();
}
else
{
m_openStructureLabels = false;
m_openStructureReferences = false;
m_openStructureBibitems = false;
m_openStructureTodo = false;
m_showStructureLabels = false;
}
}
void StructureList::updateRoot()
{
m_root->setURL( m_docinfo->url() );
m_root->setText(0, m_docinfo->url().fileName() );
}
void StructureList::cleanUp(bool preserveState/* = true */)
{
KILE_DEBUG() << "==void StructureList::cleanUp()========" << endl;
if(preserveState)
saveState();
clear();
if(m_docinfo)
disconnect(m_docinfo, 0, this, 0);
init();
}
void StructureList::slotConfigChanged(){
TQWidget *current = m_stack->visibleWidget();
if(!current)
return;
cleanUp(false);
m_stack->update(m_docinfo,true,false);
m_stack->raiseWidget(current);
}
void StructureList::saveState()
{
KILE_DEBUG() << "===void StructureList::saveState()" << endl;
m_openByTitle.clear();
m_openByLine.clear();
m_openByFolders.clear();
TQListViewItemIterator it(this);
KileListViewItem *item = 0L;
while ( it.current() )
{
item = (KileListViewItem*)it.current();
if ( item->firstChild() )
{
//we don't accept duplicate entries in the map, remove this item alltogether
//and rely on the openByLine map instead
if ( m_openByTitle.contains ( item->title() ) )
m_openByTitle.remove ( item->title() );
else
m_openByTitle [ item->title() ] = item->isOpen();
m_openByLine [ item->line() ] = item->isOpen();
}
++it;
}
if ( m_folders.contains("labels") )
m_openByFolders["labels"] = m_folders["labels"]->isOpen();
if ( m_folders.contains("refs") )
m_openByFolders["refs"] = m_folders["refs"]->isOpen();
if ( m_folders.contains("bibs") )
m_openByFolders["bibs"] = m_folders["bibs"]->isOpen();
if ( m_folders.contains("todo") )
m_openByFolders["todo"] = m_folders["todo"]->isOpen();
if ( m_folders.contains("fixme") )
m_openByFolders["fixme"] = m_folders["fixme"]->isOpen();
}
bool StructureList::shouldBeOpen(KileListViewItem *item, const TQString & folder, int level)
{
if ( item->parent() == 0L )
return true;
if ( folder == "labels" )
{
if ( m_openByFolders.contains("labels") )
return m_openByFolders["labels"];
else
return m_openStructureLabels;
}
else if ( folder == "refs" )
{
if ( m_openByFolders.contains("refs") )
return m_openByFolders["refs"];
else
return m_openStructureReferences;
}
else if ( folder == "bibs" )
{
if ( m_openByFolders.contains("bibs") )
return m_openByFolders["bibs"];
else
return m_openStructureBibitems;
}
else if ( folder=="todo" || folder=="fixme" )
{
if ( m_openByFolders.contains(folder) )
return m_openByFolders[folder];
else
return m_openStructureTodo;
}
if ( m_openByTitle.contains(item->title()) )
return m_openByTitle [ item->title() ];
else if ( m_openByLine.contains(item->line()) )
return m_openByLine [ item->line() ]; //TODO check surrounding lines as well
else
return ((folder == "root") && level <= m_stack->level());
}
KileListViewItem* StructureList::createFolder(const TQString &folder)
{
KileListViewItem *fldr= new KileListViewItem(m_root, folder);
fldr->setOpen(false);
if ( folder == "labels" )
{
fldr->setText(0, i18n("Labels"));
fldr->setPixmap(0, SmallIcon("label"));
}
else if ( folder == "bibs" )
{
fldr->setText(0, i18n("BibTeX References"));
fldr->setPixmap(0, SmallIcon("viewbib"));
}
else if ( folder == "refs" )
{
fldr->setText(0, i18n("Undefined References"));
fldr->setPixmap(0, SmallIcon("stop"));
}
else if ( folder == "todo" )
{
fldr->setText(0, i18n("TODO"));
fldr->setPixmap(0, SmallIcon("bookmark"));
}
else if ( folder == "fixme" )
{
fldr->setText(0, i18n("FIXME"));
fldr->setPixmap(0, SmallIcon("bookmark"));
}
m_folders[ folder ] = fldr;
return m_folders[folder];
}
KileListViewItem* StructureList::folder(const TQString &folder)
{
KileListViewItem *item = m_folders[folder];
if ( item == 0L ) item = createFolder(folder);
return item;
}
void StructureList::activate()
{
m_stack->raiseWidget(this);
}
KileListViewItem *StructureList::parentFor(int lev, const TQString & fldr)
{
KileListViewItem *par = 0L;
if ( fldr == "root" )
{
switch (lev)
{
case KileStruct::Object :
case KileStruct::File :
par = ( m_lastSectioning == 0L ) ? m_root : m_lastSectioning;
break;
case 0 :
case 1 :
par = m_root;
break;
default:
par = m_parent[lev - 2];
break;
}
}
else
{
par = folder(fldr);
}
return par;
}
////////////////////// add a new item to the listview //////////////////////
/* some items have a special action:
- KileStruct::Sect:
The new item is saved in m_lastSectioning, so that all following entries
can be inserted as children. \part will drop back to level 0 of the Listview,
all other sectioning commands will be children of the last sectioning item.
If a \label command follows in the same or the next line, it is assigned
to this item.
- KileStruct::BeginFloat:
The new item is saved in m_lastFloat. If a \caption command follows before
the floating environment is closed, it is inserted into the title of this item.
If a \label command follows, it is assigned to this float item.
- KileStruct::EndFloat
Reset m_lastFloat to 0L to close this environment. No more \caption or \label
commands are assigned to this float after this.
- KileStruct::Caption
If a float environment is opened, the caption is assigned to the float item.
A caption item has hidden attribute, so that no other action is performed and
function addItem() will return immediately.
- KileStruct::Label
If we are inside a float, this label is assigned to this environment. If the last
type was a sectioning command on the current line or the line before, the label is
assigned to this sectioning item. Assigning means that a popup menu will open,
when the mouse is over this item.
- KileStruct::BeamerBeginFrame
The new item is saved in m_lastFrameEnv. If a \frametitle command follows before
the frame environment is closed, it is inserted into the title of this item.
If a \label command follows, it is assigned to this float item.
- KileStruct::BeamerEndFrame
Reset m_lastFloatEnv to 0L to close this environment. No more \frametitle
or \label commands are assigned to this frame after this.
- KileStruct::BeamerBeginBlock
Inside a beamer frame this environment is taken as child of this frame
- KileStruct::BeamerFrame
The new item is saved in m_lastFrame. If a \frametitle command follows
immediately as next command, it is inserted into the title of this item.
*/
void StructureList::addItem(const TQString &title, uint line, uint column, int type, int lev,
uint startline, uint startcol,
const TQString & pix, const TQString &fldr /* = "root" */)
{
// KILE_DEBUG() << "\t\taddItem: " << title << ", with type " << type << endl;
if ( m_stop ) return;
// some types need a special action
if ( type == KileStruct::Reference )
{
m_references.prepend( KileReferenceData(title,line,column) );
}
else if ( type==KileStruct::Caption && m_lastFloat )
{
TQString floattitle = m_lastFloat->title();
if ( floattitle=="figure" || floattitle=="table" )
m_lastFloat->setTitle(floattitle+": "+title);
}
else if ( type == KileStruct::EndFloat )
{
m_lastFloat = 0L;
}
else if ( type==KileStruct::BeamerFrametitle )
{
if ( m_lastFrameEnv )
m_lastFrameEnv->setTitle(title);
else if ( m_lastFrame )
m_lastFrame->setTitle(title);
}
else if ( type == KileStruct::BeamerEndFrame )
{
m_lastFrameEnv = 0L;
}
m_lastFrame = 0L;
// that's all for hidden types: we must immediately return
if ( lev == KileStruct::Hidden )
{
//KILE_DEBUG() << "\t\thidden item: not created" << endl;
return;
}
//KILE_DEBUG() << "\t\tcreate new item" << endl;
// check if we have to update a label before loosing this item
if ( type==KileStruct::Label )
{
if ( m_lastFloat )
{
m_lastFloat->setLabel(title);
}
else if ( m_lastType==KileStruct::Sect )
{
// check if this is a follow up label for the last sectioning item
if ( m_lastSectioning && (m_lastLine==line-1 || m_lastLine==line) )
m_lastSectioning->setLabel(title);
}
else if(m_lastType == KileStruct::BeamerBeginFrame && m_lastFrameEnv) {
m_lastFrameEnv->setLabel(title);
}
if(!m_showStructureLabels) // if we don't want to have it displayed return here
return;
}
// remember current type and line for the next call of addItem()
m_lastType = type;
m_lastLine = line;
//find the parent for the new element
KileListViewItem *parentItem = ( type==KileStruct::BeamerBeginBlock && m_lastFrameEnv ) ? m_lastFrameEnv : parentFor(lev, fldr);
if ( parentItem == 0L )
{
KMessageBox::error(0,i18n("Can't create ListviewItem: no parent found."));
return;
}
//find the last element at this level
KileListViewItem *lastChild = 0L;
KileListViewItem *nextChild = (KileListViewItem *)parentItem->firstChild();
while ( nextChild )
{
lastChild = nextChild;
nextChild = (KileListViewItem *)nextChild->nextSibling();
}
// create a new item
KileListViewItem *newChild = new KileListViewItem(parentItem, lastChild, title, m_docinfo->url(), line, column, type, lev, startline, startcol);
if ( ! pix.isNull() )
newChild->setPixmap(0,SmallIcon(pix));
//m_stop = true;
//if the level is not greater than the defaultLevel
//open the parentItem to make this item visible
parentItem->setOpen( shouldBeOpen(parentItem,fldr,lev) );
//update the m_parent levels, such that section etc. get inserted at the correct level
//m_current = newChild;
if ( lev > 0)
{
m_parent[lev-1] = newChild;
for (int l = lev; l < 7; ++l)
m_parent[l] = newChild;
}
else if ( lev == 0 )
{
m_lastSectioning = 0L;
for ( int l = 0; l < 7; ++l ) m_parent[l] = m_root;
}
// check if we have to remember the new item for setting a label or caption
if ( type == KileStruct::Sect )
m_lastSectioning = newChild;
else if ( type == KileStruct::BeginFloat )
m_lastFloat = newChild;
else if ( type == KileStruct::BeamerBeginFrame )
m_lastFrameEnv = newChild;
else if ( type == KileStruct::BeamerFrame )
m_lastFrame = newChild;
}
void StructureList::showReferences(KileInfo *ki)
{
// remove old listview item for references, if it exists
if ( m_folders.contains("refs") )
{
KileListViewItem *refitem = m_folders["refs"];
m_root->takeItem(refitem);
delete refitem;
m_folders.remove("refs");
}
//KILE_DEBUG() << "==void StructureList::showReferences()========" << endl;
//KILE_DEBUG() << "\tfound " << m_references.count() << " references" << endl;
if ( m_references.count() == 0 )
return;
// read list with all labels
const TQStringList *list = ki->allLabels();
//KILE_DEBUG() << "\tfound " << list->count() << " labels" << endl;
TQMap<TQString,bool> labelmap;
for ( TQStringList::ConstIterator itmap=list->begin(); itmap!=list->end(); ++itmap )
{
labelmap[(*itmap)] = true;
}
// now check if there are unsolved references
TQValueListConstIterator<KileReferenceData> it;
for ( it=m_references.begin(); it!=m_references.end(); ++it )
{
if ( ! labelmap.contains((*it).name()) )
{
KileListViewItem *refitem = folder("refs");
refitem->setOpen( shouldBeOpen(refitem,"refs",0) );
new KileListViewItem(refitem,0L,(*it).name(),m_docinfo->url(),(*it).line(),(*it).column(),KileStruct::Reference,KileStruct::NotSpecified, 0,0 );
}
}
}
////////////////////// Structure: TQWidgetStack //////////////////////
Structure::Structure(KileInfo *ki, TQWidget * parent, const char * name) :
TQWidgetStack(parent,name),
m_ki(ki),
m_docinfo(0L)
{
KILE_DEBUG() << "==KileWidget::Structure::Structure()===========" << endl;
setLineWidth(0);
setMidLineWidth(0);
setMargin(0);
setSizePolicy(TQSizePolicy::Ignored,TQSizePolicy::Ignored);
m_default = new StructureList(this, 0L);
m_default->activate();
m_popup = new TDEPopupMenu(this, "structureview_popup");
}
Structure::~Structure()
{
}
int Structure::level()
{
return KileConfig::defaultLevel();
}
void Structure::addDocumentInfo(KileDocument::Info *docinfo)
{
StructureList *view = new StructureList(this, docinfo);
addWidget(view);
m_map.insert(docinfo, view, true);
}
void Structure::slotClicked(TQListViewItem * itm)
{
KILE_DEBUG() << "\tStructure::slotClicked" << endl;
KileListViewItem *item = (KileListViewItem *)itm;
//return if user didn't click on an item
if (! item) return;
if (! (item->type() & KileStruct::None ))
emit(setCursor(item->url(), item->line()-1, item->column()));
else if ( item->parent() == 0L ) //root item
emit(setCursor(item->url(), 0, 0));
}
void Structure::slotDoubleClicked(TQListViewItem * itm)
{
KILE_DEBUG() << "\tStructure::slotDoubleClicked" << endl;
KileListViewItem *item = (KileListViewItem*)(itm);
static TQRegExp suffix("\\.[\\d\\w]*$");
if (!item)
return;
KILE_DEBUG() <<"item->url() is " << item->url() << ", item->title() is " << item->title() << endl;
if ( item->type() & (KileStruct::Input | KileStruct::Bibliography | KileStruct::Graphics) )
{
TQString fname = item->title();
if(fname.find(suffix) != -1) // check if we have a suffix, if not add standard suffixes
{
KILE_DEBUG() << "Suffix found: " << suffix.cap(0) << endl;
}
else
{
// filename in structureview entry has no extension: this shouldn't happen anymore,
// because all have got one in function updateStruct(). But who knows?
if ( item->type() == KileStruct::Input )
fname += m_ki->extensions()->latexDocumentDefault();
else if ( item->type() == KileStruct::Bibliography )
fname += m_ki->extensions()->bibtexDefault();
else
{
// FIXME get graphics suffix from an project config option
}
}
if(fname.left(1) != "/") // no absolute path
{
TQString fn = m_ki->getCompileName();
fname= TQFileInfo(fn).dirPath() + '/' + fname;
}
TQFileInfo fi(fname);
KURL url;
url.setPath(fname);
if (fi.isReadable())
{
if ( item->type() == KileStruct::Graphics )
{
KMimeType::Ptr pMime = KMimeType::findByURL(url);
KRun::runURL(url,pMime->name());
}
else
emit(fileOpen(url, TQString()));
}
else{
TQString otherFilename;
if( item->type() == KileStruct::Bibliography ){
otherFilename = m_ki->checkOtherPaths(fi.dirPath(),fi.fileName(),KileInfo::bibinputs);
}
else if( item->type() == KileStruct::Input ){
otherFilename = m_ki->checkOtherPaths(fi.dirPath(),fi.fileName(),KileInfo::texinputs);
}
fi.setFile(otherFilename);
if(fi.isReadable()){
url.setPath(otherFilename);
emit(fileOpen(url, TQString()));
}
else{
if ( KMessageBox::warningYesNo(this, i18n("Cannot find the included file. The file does not exist, is not readable or Kile is unable to determine the correct path to it. The filename causing this error was: %1.\nDo you want to create this file?").arg(fname), i18n("Cannot Find File"))
== KMessageBox::Yes) {
url.setPath(fname);
emit(fileNew(url));
}
}
}
}
}
// all popup items get different id's, so that we can see, what item is activated
// - label: 1 - 6
// - sectioning: 10 - 16
// - graphics: 100ff
void Structure::slotPopup(TDEListView *, TQListViewItem *itm, const TQPoint &point)
{
KILE_DEBUG() << "\tStructure::slotPopup" << endl;
m_popupItem = (KileListViewItem *)(itm);
if ( ! m_popupItem )
return;
m_popup->clear();
m_popup->disconnect();
bool hasLabel = ! m_popupItem->label().isEmpty();
if ( m_popupItem->type() == KileStruct::Sect )
{
if ( hasLabel )
m_popup->insertTitle(i18n("Sectioning"));
m_popup->insertItem(i18n("Cu&t"),SectioningCut);
m_popup->insertItem(i18n("&Copy"),SectioningCopy);
m_popup->insertItem(i18n("&Paste below"),SectioningPaste);
m_popup->insertSeparator();
m_popup->insertItem(i18n("&Select"),SectioningSelect);
m_popup->insertItem(i18n("&Delete"),SectioningDelete);
m_popup->insertSeparator();
m_popup->insertItem(i18n("C&omment"),SectioningComment);
m_popup->insertSeparator();
m_popup->insertItem(i18n("Run QuickPreview"), SectioningPreview);
}
else if ( m_popupItem->type() == KileStruct::Graphics )
{
m_popupInfo = m_popupItem->title();
if(m_popupInfo.left(1) != "/") // no absolute path
{
TQString fn = m_ki->getCompileName();
m_popupInfo = TQFileInfo(fn).dirPath() + '/' + m_popupInfo;
}
TQFileInfo fi(m_popupInfo);
if ( fi.isReadable() )
{
KURL url;
url.setPath(m_popupInfo);
m_offerList = TDETrader::self()->query(KMimeType::findByURL(url)->name(), "Type == 'Application'");
for (uint i=0; i < m_offerList.count(); ++i)
{
m_popup->insertItem(SmallIcon(m_offerList[i]->icon()), m_offerList[i]->name(), i+SectioningGraphicsOfferlist);
}
m_popup->insertSeparator();
m_popup->insertItem(i18n("Other..."), SectioningGraphicsOther);
}
}
if ( hasLabel)
{
m_popup->insertTitle(i18n("Insert Label"));
m_popup->insertItem(i18n("As &reference"),1);
m_popup->insertItem(i18n("As &page reference"),2);
m_popup->insertItem(i18n("Only the &label"),3);
m_popup->insertSeparator();
m_popup->insertTitle(i18n("Copy Label to Clipboard"));
m_popup->insertItem(i18n("As reference"),4);
m_popup->insertItem(i18n("As page reference"),5);
m_popup->insertItem(i18n("Only the label"),6);
}
if ( m_popup->count() > 0 )
{
connect(m_popup,TQT_SIGNAL(activated(int)),this,TQT_SLOT(slotPopupActivated(int)));
m_popup->exec(point);
}
}
void Structure::slotPopupActivated(int id)
{
if ( id>=1 && id<=6 )
slotPopupLabel(id);
else if ( id>=SectioningCut && id<=SectioningPreview )
slotPopupSectioning(id);
else if ( id>=SectioningGraphicsOther && id<=SectioningGraphicsOfferlist+(int)m_offerList.count() )
slotPopupGraphics(id);
}
// id's 1..6 (already checked)
void Structure::slotPopupLabel(int id)
{
KILE_DEBUG() << "\tStructure::slotPopupLabel (" << id << ")"<< endl;
TQString s = m_popupItem->label();
if ( id==1 || id==4 )
s = "\\ref{" + s + '}';
else if ( id==2 || id==5 )
s = "\\pageref{" + s + '}';
if ( id <= 3 )
emit( sendText(s) );
else
TQApplication::clipboard()->setText(s);
}
// id's 10..16 (already checked)
void Structure::slotPopupSectioning(int id)
{
KILE_DEBUG() << "\tStructure::slotPopupSectioning (" << id << ")"<< endl;
if ( m_popupItem->level()>=1 && m_popupItem->level()<=7 )
emit( sectioningPopup(m_popupItem,id) );
}
// id's 100ff (already checked)
void Structure::slotPopupGraphics(int id)
{
KILE_DEBUG() << "\tStructure::slotPopupGraphics (" << id << ")"<< endl;
KURL url;
url.setPath(m_popupInfo);
if ( id == SectioningGraphicsOther )
KRun::displayOpenWithDialog(url);
else
KRun::run(*m_offerList[id-SectioningGraphicsOfferlist],url);
}
StructureList* Structure::viewFor(KileDocument::Info *info)
{
if ( info == 0L ) return 0L;
if ( ! viewExistsFor(info) )
m_map.insert(info, new StructureList(this, info), true);
return m_map[info];
}
bool Structure::viewExistsFor(KileDocument::Info *info)
{
if ( info == 0L ) return false;
else
return m_map.contains(info);
}
void Structure::closeDocumentInfo(KileDocument::Info *docinfo)
{
m_docinfo = 0L;
if ( m_map.contains(docinfo) )
{
StructureList *data = m_map[docinfo];
m_map.remove(docinfo);
delete data;
}
if ( m_map.isEmpty() ) m_default->activate();
}
void Structure::clear()
{
TQMapIterator<KileDocument::Info *, StructureList *> it;
TQMapIterator<KileDocument::Info *, StructureList *> itend(m_map.end());
for ( it = m_map.begin(); it != itend; ++it)
if ( it.data() != 0L ) delete it.data();
m_map.clear();
m_docinfo = 0L;
m_default->activate();
}
void Structure::updateUrl(KileDocument::Info *docinfo)
{
StructureList *view = viewFor(docinfo);
if ( view )
view->updateRoot();
}
void Structure::update(KileDocument::Info *docinfo)
{
update(docinfo, true);
}
void Structure::update(KileDocument::Info *docinfo, bool parse, bool activate /* =true */)
{
KILE_DEBUG() << "==KileWidget::Structure::update(" << docinfo << ")=============" << endl;
if ( docinfo == 0L )
{
m_default->activate();
return;
}
m_docinfo = docinfo;
bool needParsing = parse || ( ! viewExistsFor(m_docinfo) );
//find structview-item for this docinfo
StructureList *view = viewFor(m_docinfo);
if ( needParsing ) //need to reparse the doc
{
int xtop = view->contentsX();
int ytop = view->contentsY();
//KILE_DEBUG() << "\tStructure::update parsing doc" << endl;
view->cleanUp();
m_docinfo->updateStruct();
view->showReferences(m_ki);
view->setContentsPos(xtop,ytop);
}
if(activate)
{
KILE_DEBUG() << "===Structure::update() activating view" << endl;
view->activate();
}
}
void Structure::clean(KileDocument::Info *docinfo)
{
KILE_DEBUG() << "==void Structure::clean()========" << endl;
StructureList *view = viewFor(docinfo);
if (view) view->cleanUp();
}
void Structure::updateReferences(KileDocument::Info *docinfo)
{
KILE_DEBUG() << "==void StructureList::updateReferences()========" << endl;
StructureList *view = viewFor(docinfo);
if (view)
{
view->showReferences(m_ki);
}
}
////////////////////// Structure: find sectioning //////////////////////
bool Structure::findSectioning(KileListViewItem *refItem, Kate::Document *doc, uint row, uint col, bool backwards, bool checkLevel, uint &sectRow, uint &sectCol)
{
KileDocument::TextInfo *docinfo = m_ki->docManager()->textInfoFor(doc);
if ( ! docinfo ){
return false;
}
if( checkLevel && !refItem ){ // only allow a refItem == NULL if checkLevel is false
return false;
}
bool found = false;
uint foundRow,foundCol;
StructureList *structurelist = viewFor(docinfo);
TQListViewItemIterator it( structurelist );
while ( it.current() )
{
KileListViewItem *item = (KileListViewItem *)(it.current());
if (item->type() == KileStruct::Sect && (!checkLevel || item->level() <= refItem->level()))
{
foundRow = item->startline() - 1;
foundCol = item->startcol() - 1;
if ( backwards )
{
if ( foundRow<row || (foundRow==row &&foundCol<col) )
{
sectRow = foundRow;
sectCol = foundCol;
found = true;
}
else
{
return found;
}
}
else if ( !backwards && (foundRow>row || (foundRow==row &&foundCol>col)) )
{
sectRow = foundRow;
sectCol = foundCol;
return true;
}
}
++it;
}
return found;
}
}
#include "kilestructurewidget.moc"