# include <sys/types.h>
# include <sys/stat.h>
# include <unistd.h>
# include <tqpopupmenu.h>
# include <tqfile.h>
# include <tqlayout.h>
# include <tqmap.h>
# include <tqlabel.h>
# include <tqradiobutton.h>
# include <tqcheckbox.h>
# include <tqdom.h>
# include <kmimetype.h>
# include <kservice.h>
# include <ktrader.h>
# include <tdeapplication.h>
# include <krun.h>
# include <kdebug.h>
# include <tdelocale.h>
# include <tdemessagebox.h>
# include <tdeparts/part.h>
# include <tdeparts/factory.h>
# include <tdeparts/partmanager.h>
# include <tdeparts/browserextension.h>
# include <tdefiledialog.h>
# include <tdemainwindow.h>
# include <tdeaction.h>
# include <tdemessagebox.h>
# include <kstatusbar.h>
# include <tdehtml_part.h>
# include <tdepopupmenu.h>
# include <tdeio/netaccess.h>
# include <kdialogbase.h>
# include <klineedit.h>
# include <tdeshortcut.h>
# include <kcompletion.h>
# include <kdirwatch.h>
# include <tdeversion.h>
# include <kiconloader.h>
# include <kuserprofile.h>
# include <kencodingfiledialog.h>
# include <ksqueezedtextlabel.h>
# include <tdetexteditor/view.h>
# include <tdetexteditor/document.h>
# include <tdetexteditor/viewcursorinterface.h>
# include <tdetexteditor/encodinginterface.h>
# include "toplevel.h"
# include "api.h"
# include "core.h"
# include "editorproxy.h"
# include "documentationpart.h"
# include "ksavealldialog.h"
# include "kdevproject.h"
# include "urlutil.h"
# include "mimewarningdialog.h"
# include "domutil.h"
# include "kdevjobtimer.h"
# include "designer.h"
# include "kdevlanguagesupport.h"
# include "multibuffer.h"
# include "partcontroller.h"
class TQDomDocument ;
PartController * PartController : : s_instance = 0 ;
using namespace MainWindowUtils ;
struct HistoryEntry
{
KURL url ;
TQString context ;
HistoryEntry ( const KURL & u , const TQString & c ) : url ( u ) , context ( c ) { }
} ;
struct ModificationData
{
KTextEditor : : Document * doc ;
bool isModified ;
unsigned char reason ;
} ;
PartController : : PartController ( TQWidget * parent )
: KDevPartController ( parent ) , _editorFactory ( 0L ) , m_currentActivePart ( 0 ) , m_removingActivePart ( false )
{
connect ( this , TQT_SIGNAL ( partRemoved ( KParts : : Part * ) ) , this , TQT_SLOT ( slotPartRemoved ( KParts : : Part * ) ) ) ;
connect ( this , TQT_SIGNAL ( partAdded ( KParts : : Part * ) ) , this , TQT_SLOT ( slotPartAdded ( KParts : : Part * ) ) ) ;
connect ( this , TQT_SIGNAL ( activePartChanged ( KParts : : Part * ) ) , this , TQT_SLOT ( slotActivePartChanged ( KParts : : Part * ) ) ) ;
setupActions ( ) ;
m_isJumping = false ;
m_openNextAsText = false ;
}
PartController : : ~ PartController ( )
{
}
void PartController : : createInstance ( TQWidget * parent )
{
if ( ! s_instance )
s_instance = new PartController ( parent ) ;
}
PartController * PartController : : getInstance ( )
{
return s_instance ;
}
void PartController : : setupActions ( )
{
TDEActionCollection * ac = TopLevel : : getInstance ( ) - > main ( ) - > actionCollection ( ) ;
TDEAction * newAction = KStdAction : : open ( this , TQT_SLOT ( slotOpenFile ( ) ) , ac , " file_open " ) ;
newAction - > setToolTip ( i18n ( " Open file " ) ) ;
newAction - > setWhatsThis ( i18n ( " <b>Open file</b><p>Opens an existing file without adding it to the project.</p> " ) ) ;
m_openRecentAction = KStdAction : : openRecent ( this , TQT_SLOT ( slotOpenRecent ( const KURL & ) ) , ac , " file_open_recent " ) ;
m_openRecentAction - > setWhatsThis ( TQString ( " <b>%1</b><p>%2 " ) . arg ( beautifyToolTip ( m_openRecentAction - > text ( ) ) ) . arg ( i18n ( " Opens recently opened file. " ) ) ) ;
m_openRecentAction - > loadEntries ( kapp - > config ( ) , " RecentFiles " ) ;
m_saveAllFilesAction = new TDEAction ( i18n ( " Save Al&l " ) , 0 , this , TQT_SLOT ( slotSaveAllFiles ( ) ) , ac , " file_save_all " ) ;
m_saveAllFilesAction - > setToolTip ( i18n ( " Save all modified files " ) ) ;
m_saveAllFilesAction - > setWhatsThis ( i18n ( " <b>Save all</b><p>Saves all modified files. " ) ) ;
m_saveAllFilesAction - > setEnabled ( false ) ;
m_revertAllFilesAction = new TDEAction ( i18n ( " Rever&t All " ) , 0 , this , TQT_SLOT ( slotRevertAllFiles ( ) ) , ac , " file_revert_all " ) ;
m_revertAllFilesAction - > setToolTip ( i18n ( " Revert all changes " ) ) ;
m_revertAllFilesAction - > setWhatsThis ( i18n ( " <b>Revert all</b><p>Reverts all changes in opened files. Prompts to save changes so the reversion can be canceled for each modified file. " ) ) ;
m_revertAllFilesAction - > setEnabled ( false ) ;
m_closeWindowAction = KStdAction : : close ( this , TQT_SLOT ( slotCloseWindow ( ) ) , ac , " file_close " ) ;
m_closeWindowAction - > setToolTip ( i18n ( " Close current file " ) ) ;
m_closeWindowAction - > setWhatsThis ( TQString ( " <b>%1</b><p>%2 " ) . arg ( beautifyToolTip ( m_closeWindowAction - > text ( ) ) ) . arg ( i18n ( " Closes current file. " ) ) ) ;
m_closeWindowAction - > setEnabled ( false ) ;
m_closeAllWindowsAction = new TDEAction ( i18n ( " Close All " ) , 0 , this , TQT_SLOT ( slotCloseAllWindows ( ) ) , ac , " file_close_all " ) ;
m_closeAllWindowsAction - > setToolTip ( i18n ( " Close all files " ) ) ;
m_closeAllWindowsAction - > setWhatsThis ( i18n ( " <b>Close all</b><p>Close all opened files. " ) ) ;
m_closeAllWindowsAction - > setEnabled ( false ) ;
m_closeOtherWindowsAction = new TDEAction ( i18n ( " Close All Others " ) , 0 , this , TQT_SLOT ( slotCloseOtherWindows ( ) ) , ac , " file_closeother " ) ;
m_closeOtherWindowsAction - > setToolTip ( i18n ( " Close other files " ) ) ;
m_closeOtherWindowsAction - > setWhatsThis ( i18n ( " <b>Close all others</b><p>Close all opened files except current. " ) ) ;
m_closeOtherWindowsAction - > setEnabled ( false ) ;
new TDEActionSeparator ( ac , " dummy_separator " ) ;
m_backAction = new TDEToolBarPopupAction ( i18n ( " Back " ) , " back " , 0 , this , TQT_SLOT ( slotBack ( ) ) , ac , " history_back " ) ;
m_backAction - > setEnabled ( false ) ;
m_backAction - > setToolTip ( i18n ( " Back " ) ) ;
m_backAction - > setWhatsThis ( i18n ( " <b>Back</b><p>Moves backwards one step in the navigation history. " ) ) ;
connect ( m_backAction - > popupMenu ( ) , TQT_SIGNAL ( aboutToShow ( ) ) , this , TQT_SLOT ( slotBackAboutToShow ( ) ) ) ;
connect ( m_backAction - > popupMenu ( ) , TQT_SIGNAL ( activated ( int ) ) , this , TQT_SLOT ( slotBackPopupActivated ( int ) ) ) ;
m_forwardAction = new TDEToolBarPopupAction ( i18n ( " Forward " ) , " forward " , 0 , this , TQT_SLOT ( slotForward ( ) ) , ac , " history_forward " ) ;
m_forwardAction - > setEnabled ( false ) ;
m_forwardAction - > setToolTip ( i18n ( " Forward " ) ) ;
m_forwardAction - > setWhatsThis ( i18n ( " <b>Forward</b><p>Moves forward one step in the navigation history. " ) ) ;
connect ( m_forwardAction - > popupMenu ( ) , TQT_SIGNAL ( aboutToShow ( ) ) , this , TQT_SLOT ( slotForwardAboutToShow ( ) ) ) ;
connect ( m_forwardAction - > popupMenu ( ) , TQT_SIGNAL ( activated ( int ) ) , this , TQT_SLOT ( slotForwardPopupActivated ( int ) ) ) ;
m_gotoLastEditPosAction = new TDEAction ( i18n ( " Goto Last Edit Position " ) , " go-bottom " , 0 , this , TQT_SLOT ( gotoLastEditPos ( ) ) , ac , " goto_last_edit_pos " ) ;
m_gotoLastEditPosAction - > setEnabled ( false ) ;
m_gotoLastEditPosAction - > setToolTip ( i18n ( " Goto Last Edit Position " ) ) ;
m_gotoLastEditPosAction - > setWhatsThis ( i18n ( " <b>Goto Last Edit Position</b><p>Open the last edited file and position cursor at the point of edit " ) ) ;
}
void PartController : : setEncoding ( const TQString & encoding )
{
m_presetEncoding = encoding ;
}
KParts : : Part * PartController : : findOpenDocument ( const KURL & url )
{
// if we find it this way, all is well
KParts : : Part * part = partForURL ( url ) ;
if ( part )
{
return part ;
}
// ok, let's see if we can try harder
if ( API : : getInstance ( ) - > project ( ) )
{
KURL partURL = findURLInProject ( url ) ;
partURL . cleanPath ( ) ;
return partForURL ( partURL ) ;
}
return 0L ;
}
KURL PartController : : findURLInProject ( const KURL & url )
{
TQStringList fileList = API : : getInstance ( ) - > project ( ) - > allFiles ( ) ;
bool filenameOnly = ( url . url ( ) . find ( ' / ' ) = = - 1 ) ;
TQString filename = filenameOnly ? " / " : " " ;
filename + = url . url ( ) ;
for ( TQStringList : : Iterator it = fileList . begin ( ) ; it ! = fileList . end ( ) ; + + it ) {
if ( ( * it ) . endsWith ( filename ) ) {
// Match! The first one is as good as any one, I guess...
return KURL ( API : : getInstance ( ) - > project ( ) - > projectDirectory ( ) + " / " + * it ) ;
}
}
return url ;
}
void PartController : : editDocument ( const KURL & inputUrl , int lineNum , int col )
{
editDocumentInternal ( inputUrl , lineNum , col ) ;
}
void PartController : : splitCurrentDocument ( const KURL & inputUrl ,
int lineNum , int col )
{
editDocumentInternal ( inputUrl , lineNum , col , true , true ) ;
}
void PartController : : scrollToLineColumn ( const KURL & inputUrl ,
int lineNum , int col , bool storeHistory )
{
if ( KParts : : ReadOnlyPart * existingPart = partForURL ( inputUrl ) )
{
if ( storeHistory ) addHistoryEntry ( existingPart ) ;
EditorProxy : : getInstance ( ) - > setLineNumber ( existingPart , lineNum , col ) ;
return ;
}
}
void PartController : : editDocumentInternal ( const KURL & inputUrl , int lineNum ,
int col , bool activate ,
bool addToCurrentBuffer )
{
kdDebug ( 9000 ) < < k_funcinfo < < " \n " < < inputUrl . prettyURL ( )
< < " linenum " < < lineNum < < " activate? " < < activate
< < " addToCurrentBuffer? " < < addToCurrentBuffer < < endl ;
KURL url = inputUrl ;
// is it already open?
// (Try this once before verifying the URL, we could be dealing with a file that no longer exists on disc)
if ( KParts : : Part * existingPart = partForURL ( url ) )
{
// if we've been asked to OpenAs an open file with a specific encoding, assume the user wants to change encoding
if ( ! m_presetEncoding . isNull ( ) )
{
if ( KTextEditor : : EncodingInterface * ei = dynamic_cast < KTextEditor : : EncodingInterface * > ( existingPart ) )
{
ei - > setEncoding ( m_presetEncoding ) ;
}
m_presetEncoding = TQString ( ) ;
}
addHistoryEntry ( ) ;
activatePart ( existingPart ) ;
EditorProxy : : getInstance ( ) - > setLineNumber ( existingPart , lineNum , col ) ;
return ;
}
// Make sure the URL exists
if ( ! url . isValid ( ) | | ! TDEIO : : NetAccess : : exists ( url , false , 0 ) )
{
bool done = false ;
// Try to find this file in the current project's list instead
if ( API : : getInstance ( ) - > project ( ) )
{
if ( url . isRelativeURL ( url . url ( ) ) ) {
KURL relURL ( API : : getInstance ( ) - > project ( ) - > projectDirectory ( ) ) ;
relURL . addPath ( url . url ( ) ) ;
kdDebug ( ) < < k_funcinfo < < " Looking for file in project dir: " < < API : : getInstance ( ) - > project ( ) - > projectDirectory ( ) < < " url " < < url . url ( ) < < " transformed to " < < relURL . url ( ) < < " : " < < done < < endl ;
if ( relURL . isValid ( ) & & TDEIO : : NetAccess : : exists ( relURL , false , 0 ) ) {
url = relURL ;
done = true ;
}
else {
KURL relURL ( API : : getInstance ( ) - > project ( ) - > buildDirectory ( ) ) ;
relURL . addPath ( url . url ( ) ) ;
kdDebug ( ) < < k_funcinfo < < " Looking for file in build dir: " < < API : : getInstance ( ) - > project ( ) - > buildDirectory ( ) < < " url " < < url . url ( ) < < " transformed to " < < relURL . url ( ) < < " : " < < done < < endl ;
if ( relURL . isValid ( ) & & TDEIO : : NetAccess : : exists ( relURL , false , 0 ) ) {
url = relURL ;
done = true ;
}
}
}
if ( ! done ) {
url = findURLInProject ( url ) ;
if ( ! url . isValid ( ) | | ! TDEIO : : NetAccess : : exists ( url , false , 0 ) )
// See if this url is relative to the current project's directory
url = API : : getInstance ( ) - > project ( ) - > projectDirectory ( ) + " / " + url . path ( ) ;
else
done = true ;
}
}
if ( ! done & & ( ! url . isValid ( ) | | ! TDEIO : : NetAccess : : exists ( url , false , 0 ) ) )
{
// Not found - prompt the user to find it?
kdDebug ( 9000 ) < < " cannot find URL: " < < url . url ( ) < < endl ;
return ;
}
}
// We now have a url that exists ;)
// clean it and resolve possible symlink
url . cleanPath ( true ) ;
if ( url . isLocalFile ( ) )
{
TQString path = url . path ( ) ;
path = URLUtil : : canonicalPath ( path ) ;
if ( ! path . isEmpty ( ) )
url . setPath ( path ) ;
}
// is it already open?
KParts : : Part * existingPart = partForURL ( url ) ;
if ( existingPart )
{
addHistoryEntry ( ) ;
activatePart ( existingPart ) ;
EditorProxy : : getInstance ( ) - > setLineNumber ( existingPart , lineNum , col ) ;
return ;
}
if ( ! addToCurrentBuffer )
{
if ( KDevLanguageSupport * lang =
API : : getInstance ( ) - > languageSupport ( ) )
{
// Let the language part override the addToCurrentBuffer flag
// if it decides to...
addToCurrentBuffer = lang - > shouldSplitDocument ( inputUrl ) ;
if ( addToCurrentBuffer )
{
kdDebug ( 9000 ) < <
" languagePart() insists addToCurrentBuffer = true " < < endl ;
// Set activate = true, otherwise we have hard to fix
// multi-buffer delayed activation.
// I'll re-look at this later...
activate = true ;
}
}
}
KMimeType : : Ptr MimeType = KMimeType : : findByURL ( url ) ;
kdDebug ( 9000 ) < < " mimeType = " < < MimeType - > name ( ) < < endl ;
// is the URL pointing to a directory?
if ( MimeType - > is ( " inode/directory " ) )
{
return ;
}
if ( ! m_presetEncoding . isNull ( ) )
{
m_openNextAsText = true ;
}
TDEConfig * config = kapp - > config ( ) ;
config - > setGroup ( " General Options " ) ;
// we don't trust KDE with designer files, let's handle it ourselves
if ( ! m_openNextAsText & & MimeType - > is ( " application/x-designer " ) )
{
TQString DesignerSetting = config - > readEntry ( " DesignerSetting " , " ExternalDesigner " ) ;
TQString designerExec = " designer " ;
TQStringList designerPluginPaths ;
TQDomDocument * dom = API : : getInstance ( ) - > projectDom ( ) ;
if ( dom ! = 0 )
{
// The global option specifies a fallback if the project
// has no setting or no project is open. However for TQt4
// projects we want to use ExternalDesigner in any case.
if ( DomUtil : : readIntEntry ( * dom , " /kdevcppsupport/qt/version " , 3 ) = = 4 )
{
designerPluginPaths = DomUtil : : readListEntry ( * dom , " /kdevcppsupport/qt/designerpluginpaths " , " path " ) ;
DesignerSetting = " ExternalDesigner " ;
}
DesignerSetting = DomUtil : : readEntry ( * dom , " /kdevcppsupport/qt/designerintegration " , DesignerSetting ) ;
designerExec = DomUtil : : readEntry ( * dom , " /kdevcppsupport/qt/designer " , designerExec ) ;
}
if ( DesignerSetting = = " ExternalKDevDesigner " )
{
designerExec = " kdevdesigner " ;
}
else if ( DesignerSetting = = " EmbeddedKDevDesigner " )
{
if ( KParts : : ReadOnlyPart * designerPart = qtDesignerPart ( ) )
{
addHistoryEntry ( ) ;
activatePart ( designerPart ) ;
designerPart - > openURL ( url ) ;
return ;
}
else if ( KParts : : Factory * KDevDesignerFactory = static_cast < KParts : : Factory * > ( KLibLoader : : self ( ) - > factory ( TQFile : : encodeName ( " libkdevdesignerpart " ) ) ) )
{
KParts : : ReadWritePart * kdevpart = static_cast < KParts : : ReadWritePart * > ( KDevDesignerFactory - > createPart ( TopLevel : : getInstance ( ) - > main ( ) , 0 , 0 , 0 , " KParts::ReadWritePart " ) ) ;
kdevpart - > openURL ( url ) ;
addHistoryEntry ( ) ;
integratePart ( kdevpart , url ) ;
m_openRecentAction - > addURL ( url ) ;
m_openRecentAction - > saveEntries ( kapp - > config ( ) , " RecentFiles " ) ;
return ;
}
}
if ( designerPluginPaths . isEmpty ( ) )
KRun : : runCommand ( designerExec + " " + url . pathOrURL ( ) ) ;
else
KRun : : runCommand ( " TQT_PLUGIN_PATH= \" " + designerPluginPaths . join ( " : " ) + " \" " + designerExec + " " + url . pathOrURL ( ) ) ;
return ;
}
config - > setGroup ( " General " ) ;
TQStringList texttypeslist = config - > readListEntry ( " TextTypes " ) ;
if ( texttypeslist . contains ( MimeType - > name ( ) ) )
{
m_openNextAsText = true ;
}
bool isText = false ;
TQVariant v = MimeType - > property ( " X-TDE-text " ) ;
if ( v . isValid ( ) )
isText = v . toBool ( ) ;
// is this regular text - open in editor
if ( m_openNextAsText | | isText | | MimeType - > is ( " application/x-zerosize " ) )
{
KTextEditor : : Editor * editorpart =
createEditorPart ( activate , addToCurrentBuffer , url ) ;
if ( editorpart )
{
if ( m_presetEncoding . isNull ( ) & & API : : getInstance ( ) - > projectDom ( ) )
{
TQDomDocument * projectDom = API : : getInstance ( ) - > projectDom ( ) ;
m_presetEncoding = DomUtil : : readEntry ( * projectDom , " /general/defaultencoding " , TQString ( ) ) ;
}
if ( ! m_presetEncoding . isNull ( ) )
{
if ( KTextEditor : : EncodingInterface * ei = dynamic_cast < KTextEditor : : EncodingInterface * > ( editorpart ) )
{
ei - > setEncoding ( m_presetEncoding ) ;
}
m_presetEncoding = TQString ( ) ;
}
addHistoryEntry ( ) ;
TQWidget * widget = EditorProxy : : getInstance ( ) - > topWidgetForPart ( editorpart ) ;
integratePart ( editorpart , url , widget , true , activate , addToCurrentBuffer ) ;
EditorProxy : : getInstance ( ) - > setLineNumber ( editorpart , lineNum , col ) ;
m_openNextAsText = false ;
m_openRecentAction - > addURL ( url ) ;
m_openRecentAction - > saveEntries ( kapp - > config ( ) , " RecentFiles " ) ;
return ;
}
}
// OK, it's not text and it's not a designer file.. let's see what else we can come up with..
KParts : : Factory * factory = 0 ;
TQString className ;
TQString services [ ] = { " KParts/ReadWritePart " , " KParts/ReadOnlyPart " } ;
TQString classnames [ ] = { " KParts::ReadWritePart " , " KParts::ReadOnlyPart " } ;
for ( uint i = 0 ; i < 2 ; + + i )
{
factory = findPartFactory ( MimeType - > name ( ) , services [ i ] ) ;
if ( factory )
{
className = classnames [ i ] ;
break ;
}
}
kdDebug ( 9000 ) < < " factory = " < < factory < < endl ;
if ( factory )
{
// create the object of the desired class
KParts : : ReadOnlyPart * part = static_cast < KParts : : ReadOnlyPart * > ( factory - > createPart ( TopLevel : : getInstance ( ) - > main ( ) , 0 , 0 , 0 , className . latin1 ( ) ) ) ;
if ( part )
{
part - > openURL ( url ) ;
addHistoryEntry ( ) ;
if ( dynamic_cast < KTextEditor : : Editor * > ( part ) ) // we can have ended up with a texteditor, in which case need to treat it as such
{
integratePart ( part , url , part - > widget ( ) , true , activate ) ;
EditorProxy : : getInstance ( ) - > setLineNumber ( part , lineNum , col ) ;
}
else
{
integratePart ( part , url ) ;
}
m_openRecentAction - > addURL ( url ) ;
m_openRecentAction - > saveEntries ( kapp - > config ( ) , " RecentFiles " ) ;
}
}
else
{
MimeWarningDialog dlg ;
dlg . text2 - > setText ( TQString ( " <qt><b>%1</b></qt> " ) . arg ( url . path ( ) ) ) ;
dlg . text3 - > setText ( dlg . text3 - > text ( ) . arg ( MimeType - > name ( ) ) ) ;
if ( dlg . exec ( ) = = TQDialog : : Accepted )
{
if ( dlg . open_with_kde - > isChecked ( ) )
{
KRun : : runURL ( url , MimeType - > name ( ) ) ;
}
else
{
if ( dlg . always_open_as_text - > isChecked ( ) )
{
TDEConfig * config = kapp - > config ( ) ;
config - > setGroup ( " General " ) ;
TQStringList texttypeslist = config - > readListEntry ( " TextTypes " ) ;
texttypeslist < < MimeType - > name ( ) ;
config - > writeEntry ( " TextTypes " , texttypeslist ) ;
}
m_openNextAsText = true ;
editDocument ( url , lineNum , col ) ;
}
}
}
}
void PartController : : showDocument ( const KURL & url , bool newWin )
{
TQString fixedPath = HTMLDocumentationPart : : resolveEnvVarsInURL ( url . url ( ) ) ; // possibly could env vars
KURL docUrl ( fixedPath ) ;
kdDebug ( 9000 ) < < " SHOW: " < < docUrl . url ( ) < < endl ;
if ( docUrl . isLocalFile ( ) & & KMimeType : : findByURL ( docUrl ) - > name ( ) ! = " text/html " ) {
// a link in a html-file pointed to a local text file - display
// it in the editor instead of a html-view to avoid uglyness
editDocument ( docUrl ) ;
return ;
}
addHistoryEntry ( ) ;
HTMLDocumentationPart * part = dynamic_cast < HTMLDocumentationPart * > ( activePart ( ) ) ;
if ( ! part | | newWin )
{
part = new HTMLDocumentationPart ;
integratePart ( part , docUrl ) ;
connect ( part , TQT_SIGNAL ( fileNameChanged ( KParts : : ReadOnlyPart * ) ) ,
this , TQT_SIGNAL ( partURLChanged ( KParts : : ReadOnlyPart * ) ) ) ;
}
else
{
activatePart ( part ) ;
}
part - > openURL ( docUrl ) ;
}
KParts : : Factory * PartController : : findPartFactory ( const TQString & mimeType , const TQString & partType , const TQString & preferredName )
{
TDETrader : : OfferList offers = TDETrader : : self ( ) - > query ( mimeType , TQString ( " '%1' in ServiceTypes " ) . arg ( partType ) ) ;
if ( offers . count ( ) > 0 )
{
KService : : Ptr ptr = 0 ;
// if there is a preferred plugin we'll take it
if ( ! preferredName . isEmpty ( ) ) {
TDETrader : : OfferList : : Iterator it ;
for ( it = offers . begin ( ) ; it ! = offers . end ( ) ; + + it ) {
if ( ( * it ) - > desktopEntryName ( ) = = preferredName ) {
ptr = ( * it ) ;
}
}
}
// else we just take the first in the list
if ( ! ptr ) {
ptr = offers . first ( ) ;
}
return static_cast < KParts : : Factory * > ( KLibLoader : : self ( ) - > factory ( TQFile : : encodeName ( ptr - > library ( ) ) ) ) ;
}
return 0 ;
}
KTextEditor : : Editor * PartController : : createEditorPart ( bool activate ,
bool addToCurrentBuffer ,
const KURL & url )
{
MultiBuffer * multiBuffer = 0 ;
if ( addToCurrentBuffer )
{
multiBuffer =
dynamic_cast < MultiBuffer * > (
EditorProxy : : getInstance ( ) - > topWidgetForPart ( activePart ( ) )
) ;
}
if ( ! multiBuffer )
{
kdDebug ( 9000 ) < < " Creating a new MultiBuffer for "
< < url . fileName ( ) < < endl ;
multiBuffer = new MultiBuffer ( TopLevel : : getInstance ( ) - > main ( ) ) ;
}
static bool alwaysActivate = true ;
kapp - > config ( ) - > setGroup ( " Editor " ) ;
TQString preferred = kapp - > config ( ) - > readPathEntry ( " EmbeddedKTextEditor " ) ;
// If we are not using kyzis...
// Don't create non-wrapped views for now,
// avoid two paths (== two chances for bad bugs)
if ( preferred ! = " kyzispart " )
alwaysActivate = false ;
KTextEditor : : Editor * editorpart =
dynamic_cast < KTextEditor : : Editor * > ( multiBuffer - > createPart ( " text/plain " ,
" KTextEditor/Document " ,
alwaysActivate | activate ?
" KTextEditor::Editor " : " KTextEditor::Document " ,
preferred
) ) ;
if ( url . isValid ( ) )
editorpart - > openURL ( url ) ;
multiBuffer - > registerURL ( url , editorpart ) ;
multiBuffer - > setDelayedActivation ( ! activate ) ;
return editorpart ;
}
void PartController : : integratePart ( KParts : : Part * part , const KURL & url ,
TQWidget * widget , bool isTextEditor ,
bool activate , bool addToCurrentBuffer )
{
if ( ! widget ) widget = part - > widget ( ) ;
if ( ! widget ) {
/// @todo error handling
kdDebug ( 9000 ) < < " no widget for this part!! " < < endl ;
return ; // to avoid later crash
}
if ( ! addToCurrentBuffer )
TopLevel : : getInstance ( ) - > embedPartView ( widget , url . fileName ( ) , url . url ( ) ) ;
addPart ( part , activate ) ;
// tell the parts we loaded a document
KParts : : ReadOnlyPart * ro_part = dynamic_cast < KParts : : ReadOnlyPart * > ( part ) ;
if ( ! ro_part ) return ;
emit loadedFile ( ro_part - > url ( ) ) ;
connect ( part , TQT_SIGNAL ( modifiedOnDisc ( Kate : : Document * , bool , unsigned char ) ) , this , TQT_SLOT ( slotDocumentDirty ( Kate : : Document * , bool , unsigned char ) ) ) ;
// let's get notified when a document has been changed
connect ( part , TQT_SIGNAL ( completed ( ) ) , this , TQT_SLOT ( slotUploadFinished ( ) ) ) ;
// yes, we're cheating again. this signal exists for katepart's
// Document object and our HTMLDocumentationPart
// connect(part, TQT_SIGNAL(fileNameChanged()), this, TQT_SLOT(slotFileNameChanged()));
// Connect to the document's views newStatus() signal in order to keep track of the
// modified-status of the document.
if ( isTextEditor )
integrateTextEditorPart ( static_cast < KTextEditor : : Document * > ( part ) ) ;
KInterfaceDesigner : : Designer * designerPart = dynamic_cast < KInterfaceDesigner : : Designer * > ( part ) ;
if ( designerPart & & API : : getInstance ( ) - > languageSupport ( ) )
{
kdDebug ( ) < < " integrating designer part with language support " < < endl ;
connect ( designerPart , TQT_SIGNAL ( addedFunction ( DesignerType , const TQString & , Function ) ) ,
API : : getInstance ( ) - > languageSupport ( ) ,
TQT_SLOT ( addFunction ( DesignerType , const TQString & , Function ) ) ) ;
connect ( designerPart , TQT_SIGNAL ( editedFunction ( DesignerType , const TQString & , Function , Function ) ) , API : : getInstance ( ) - > languageSupport ( ) ,
TQT_SLOT ( editFunction ( DesignerType , const TQString & , Function , Function ) ) ) ;
connect ( designerPart , TQT_SIGNAL ( removedFunction ( DesignerType , const TQString & , Function ) ) ,
API : : getInstance ( ) - > languageSupport ( ) ,
TQT_SLOT ( removeFunction ( DesignerType , const TQString & , Function ) ) ) ;
connect ( designerPart , TQT_SIGNAL ( editFunction ( DesignerType , const TQString & , const TQString & ) ) ,
API : : getInstance ( ) - > languageSupport ( ) ,
TQT_SLOT ( openFunction ( DesignerType , const TQString & , const TQString & ) ) ) ;
connect ( designerPart , TQT_SIGNAL ( editSource ( DesignerType , const TQString & ) ) ,
API : : getInstance ( ) - > languageSupport ( ) ,
TQT_SLOT ( openSource ( DesignerType , const TQString & ) ) ) ;
connect ( designerPart , TQT_SIGNAL ( newStatus ( const TQString & , int ) ) ,
this , TQT_SLOT ( slotNewDesignerStatus ( const TQString & , int ) ) ) ;
}
}
void PartController : : integrateTextEditorPart ( KTextEditor : : Document * doc )
{
// There's shortcut conflict between Kate and the debugger, resolve
// it here. Ideally, the should be some standard mechanism, configurable
// by config files.
// However, it does not exists and situation here some rare commands
// like "Dynamic word wrap" or "Show line numbers" from Kate take
// all possible shortcuts, leaving us with IDE that has no shortcuts for
// debugger, is very bad.
//
// We could try to handle this in debugger, but that would require
// the debugger to intercept all new KTextEditor::View creations, which is
// not possible.
if ( ! doc ) return ;
connect ( doc , TQT_SIGNAL ( textChanged ( ) ) , this , TQT_SLOT ( textChanged ( ) ) ) ;
connect ( doc , TQT_SIGNAL ( fileNameChanged ( ) ) ,
this , TQT_SLOT ( slotDocumentUrlChanged ( ) ) ) ;
if ( doc - > widget ( ) )
{
connect ( doc - > widget ( ) , TQT_SIGNAL ( dropEventPass ( TQDropEvent * ) ) ,
TopLevel : : getInstance ( ) - > main ( ) , TQT_SLOT ( slotDropEvent ( TQDropEvent * ) ) ) ;
}
if ( KTextEditor : : View * view = dynamic_cast < KTextEditor : : View * > ( doc - > widget ( ) ) )
{
TDEActionCollection * c = view - > actionCollection ( ) ;
// Be extra carefull, in case the part either don't provide those
// action, or uses different shortcuts.
if ( TDEAction * a = c - > action ( " view_folding_markers " ) )
{
if ( a - > shortcut ( ) = = TDEShortcut ( Key_F9 ) )
a - > setShortcut ( TDEShortcut ( ) ) ;
}
if ( TDEAction * a = c - > action ( " view_dynamic_word_wrap " ) )
{
if ( a - > shortcut ( ) = = TDEShortcut ( Key_F10 ) )
a - > setShortcut ( TDEShortcut ( ) ) ;
}
if ( TDEAction * a = c - > action ( " view_line_numbers " ) )
{
if ( a - > shortcut ( ) = = TDEShortcut ( Key_F11 ) )
a - > setShortcut ( TDEShortcut ( ) ) ;
}
}
//EditorProxy::getInstance()->installPopup(doc, contextPopupMenu());
// What's potentially problematic is that this signal isn't officially part of the
// KTextEditor::View interface. It is nevertheless there, and used in kate and kwrite.
// There doesn't seem to be any othere way of making this work with katepart, and since
// signals are dynamic, if we try to connect to an editorpart that lacks this signal,
// all we get is a runtime warning. At this point in time we are only really supported
// by katepart anyway so IMHO this hack is justified. //teatime
TQPtrList < KTextEditor : : View > list = doc - > views ( ) ;
TQPtrListIterator < KTextEditor : : View > it ( list ) ;
while ( it . current ( ) )
{
connect ( it , TQT_SIGNAL ( newStatus ( ) ) , this , TQT_SLOT ( slotNewStatus ( ) ) ) ;
+ + it ;
}
}
void PartController : : slotPartAdded ( KParts : : Part * part )
{
kdDebug ( 9000 ) < < k_funcinfo < < endl ;
if ( KParts : : ReadOnlyPart * ro_part = dynamic_cast < KParts : : ReadOnlyPart * > ( part ) )
{
updatePartURL ( ro_part ) ;
}
updateMenuItems ( ) ;
}
void PartController : : slotPartRemoved ( KParts : : Part * part )
{
kdDebug ( 9000 ) < < k_funcinfo < < endl ;
_partURLMap . remove ( static_cast < KParts : : ReadOnlyPart * > ( part ) ) ;
if ( part = = m_currentActivePart )
{
m_removingActivePart = true ;
}
updateMenuItems ( ) ;
}
void PartController : : updatePartURL ( KParts : : ReadOnlyPart * ro_part )
{
if ( ro_part - > url ( ) . isEmpty ( ) )
{
kdDebug ( 9000 ) < < " updatePartURL() called with empty URL for part: " < < ro_part < < endl ;
return ;
}
_partURLMap [ ro_part ] = ro_part - > url ( ) ;
}
bool PartController : : partURLHasChanged ( KParts : : ReadOnlyPart * ro_part )
{
if ( _partURLMap . contains ( ro_part ) & & ! ro_part - > url ( ) . isEmpty ( ) )
{
if ( _partURLMap [ ro_part ] ! = ro_part - > url ( ) )
{
return true ;
}
}
return false ;
}
KURL PartController : : storedURLForPart ( KParts : : ReadOnlyPart * ro_part )
{
if ( _partURLMap . contains ( ro_part ) )
{
return _partURLMap [ ro_part ] ;
}
return KURL ( ) ;
}
void PartController : : slotUploadFinished ( )
{
KParts : : ReadOnlyPart * ro_part = const_cast < KParts : : ReadOnlyPart * > ( dynamic_cast < const KParts : : ReadOnlyPart * > ( sender ( ) ) ) ;
if ( ! ro_part ) return ;
if ( partURLHasChanged ( ro_part ) )
{
emit partURLChanged ( ro_part ) ;
updatePartURL ( ro_part ) ;
}
}
KParts : : ReadOnlyPart * PartController : : partForURL ( const KURL & url )
{
TQPtrListIterator < KParts : : Part > it ( * parts ( ) ) ;
for ( ; it . current ( ) ; + + it )
{
KParts : : ReadOnlyPart * ro_part = dynamic_cast < KParts : : ReadOnlyPart * > ( it . current ( ) ) ;
if ( ro_part & & url . path ( ) = = ro_part - > url ( ) . path ( ) )
return ro_part ;
}
return 0 ;
}
KParts : : Part * PartController : : partForWidget ( const TQWidget * widget )
{
TQPtrListIterator < KParts : : Part > it ( * parts ( ) ) ;
for ( ; it . current ( ) ; + + it )
{
if ( it . current ( ) - > widget ( ) = = widget )
{
return * it ;
}
}
return 0 ;
}
void PartController : : activatePart ( KParts : : Part * part )
{
if ( ! part ) return ;
TQWidget * widget = EditorProxy : : getInstance ( ) - > widgetForPart ( part ) ;
if ( widget )
{
TopLevel : : getInstance ( ) - > raiseView ( widget ) ;
widget - > show ( ) ;
widget - > setFocus ( ) ;
}
setActivePart ( part ) ;
TQWidget * w2 = EditorProxy : : getInstance ( ) - > widgetForPart ( part ) ;
if ( w2 ! = widget )
w2 - > setFocus ( ) ;
}
bool PartController : : closePart ( KParts : : Part * part )
{
KParts : : ReadOnlyPart * ro_part =
dynamic_cast < KParts : : ReadOnlyPart * > ( part ) ;
if ( ! ro_part ) return true ;
KURL url = ro_part - > url ( ) ;
if ( TQWidget * w = EditorProxy : : getInstance ( ) - > topWidgetForPart ( part ) )
{
if ( MultiBuffer * multiBuffer = dynamic_cast < MultiBuffer * > ( w ) )
{
kdDebug ( 9000 ) < < " About to delete MultiBuffered document... "
< < " numberOfBuffers: " < < multiBuffer - > numberOfBuffers ( )
< < " isActivated: " < < multiBuffer - > isActivated ( )
< < endl ;
if ( ! multiBuffer - > closeURL ( url ) )
return false ;
if ( multiBuffer - > numberOfBuffers ( ) = = 0
| | ! multiBuffer - > isActivated ( ) )
{
TopLevel : : getInstance ( ) - > removeView ( w ) ;
_dirtyDocuments . remove ( static_cast < KParts : : ReadWritePart * > ( ro_part ) ) ;
emit closedFile ( url ) ;
/* kdDebug(9000) << "Deleting MultiBuffer Part" << endl;*/
TopLevel : : getInstance ( ) - > main ( ) - > guiFactory ( ) - > removeClient ( part ) ;
delete part ;
/* kdDebug(9000) << "DeleteLater Actual MultiBuffer" << endl;*/
multiBuffer - > deleteLater ( ) ;
return true ;
}
else
{
/* kdDebug(9000) << "Deleting MultiBuffer Part" << endl;*/
_dirtyDocuments . remove ( static_cast < KParts : : ReadWritePart * > ( ro_part ) ) ;
TopLevel : : getInstance ( ) - > main ( ) - > guiFactory ( ) - > removeClient ( part ) ;
emit closedFile ( url ) ;
delete part ;
// Switch to a remaining buffer
setActivePart ( multiBuffer - > activeBuffer ( ) ) ;
return true ;
}
}
else if ( ! ro_part - > closeURL ( ) )
return false ;
TopLevel : : getInstance ( ) - > removeView ( w ) ;
}
else if ( ! ro_part - > closeURL ( ) )
return false ;
TopLevel : : getInstance ( ) - > main ( ) - > guiFactory ( ) - > removeClient ( part ) ;
_dirtyDocuments . remove ( static_cast < KParts : : ReadWritePart * > ( ro_part ) ) ;
emit closedFile ( url ) ;
/* kdDebug(9000) << "Deleting Regular Part" << endl;*/
delete part ;
return true ;
}
void PartController : : updateMenuItems ( )
{
bool hasWriteParts = false ;
bool hasReadOnlyParts = false ;
TQPtrListIterator < KParts : : Part > it ( * parts ( ) ) ;
for ( ; it . current ( ) ; + + it )
{
if ( it . current ( ) - > inherits ( " KParts::ReadWritePart " ) )
hasWriteParts = true ;
if ( it . current ( ) - > inherits ( " KParts::ReadOnlyPart " ) )
hasReadOnlyParts = true ;
}
m_saveAllFilesAction - > setEnabled ( hasWriteParts ) ;
m_revertAllFilesAction - > setEnabled ( hasWriteParts ) ;
m_closeWindowAction - > setEnabled ( hasReadOnlyParts ) ;
m_closeAllWindowsAction - > setEnabled ( hasReadOnlyParts ) ;
m_closeOtherWindowsAction - > setEnabled ( hasReadOnlyParts ) ;
m_backAction - > setEnabled ( ! m_backHistory . isEmpty ( ) ) ;
}
void PartController : : slotRevertAllFiles ( )
{
revertAllFiles ( ) ;
}
void PartController : : reloadFile ( const KURL & url )
{
KParts : : ReadWritePart * part = dynamic_cast < KParts : : ReadWritePart * > ( partForURL ( url ) ) ;
if ( part )
{
if ( part - > isModified ( ) )
{
if ( KMessageBox : : warningYesNo ( TopLevel : : getInstance ( ) - > main ( ) ,
i18n ( " The file \" %1 \" is modified in memory. Are you sure you want to reload it? (Local changes will be lost.) " ) . arg ( url . path ( ) ) ,
i18n ( " File is Modified " ) , i18n ( " Reload " ) , i18n ( " Do Not Reload " ) ) = = KMessageBox : : Yes )
{
part - > setModified ( false ) ;
}
else
{
return ;
}
}
unsigned int line = 0 ; unsigned int col = 0 ;
KTextEditor : : ViewCursorInterface * iface = dynamic_cast < KTextEditor : : ViewCursorInterface * > ( part - > widget ( ) ) ;
if ( iface )
{
iface - > cursorPositionReal ( & line , & col ) ;
}
part - > openURL ( url ) ;
_dirtyDocuments . remove ( part ) ;
emit documentChangedState ( url , Clean ) ;
if ( iface )
{
iface - > setCursorPositionReal ( line , col ) ;
}
}
}
void PartController : : revertFiles ( const KURL : : List & list )
{
KURL : : List : : ConstIterator it = list . begin ( ) ;
while ( it ! = list . end ( ) )
{
reloadFile ( * it ) ;
+ + it ;
}
}
void PartController : : revertAllFiles ( )
{
revertFiles ( openURLs ( ) ) ;
}
void PartController : : slotCloseWindow ( )
{
closePart ( activePart ( ) ) ;
}
KURL : : List PartController : : modifiedDocuments ( )
{
KURL : : List modFiles ;
TQPtrListIterator < KParts : : Part > it ( * parts ( ) ) ;
while ( it . current ( ) )
{
KParts : : ReadWritePart * rw_part = dynamic_cast < KParts : : ReadWritePart * > ( it . current ( ) ) ;
if ( rw_part & & rw_part - > isModified ( ) )
{
modFiles < < rw_part - > url ( ) ;
}
+ + it ;
}
return modFiles ;
}
void PartController : : slotSave ( )
{
kdDebug ( 9000 ) < < k_funcinfo < < endl ;
if ( KParts : : ReadWritePart * part = dynamic_cast < KParts : : ReadWritePart * > ( activePart ( ) ) )
{
saveFile ( part - > url ( ) ) ;
}
}
void PartController : : slotReload ( )
{
kdDebug ( 9000 ) < < k_funcinfo < < endl ;
if ( KParts : : ReadWritePart * part = dynamic_cast < KParts : : ReadWritePart * > ( activePart ( ) ) )
{
reloadFile ( part - > url ( ) ) ;
}
}
void PartController : : slotSaveAllFiles ( )
{
saveAllFiles ( ) ;
}
bool PartController : : saveFile ( const KURL & url , bool force )
{
KParts : : ReadWritePart * part = dynamic_cast < KParts : : ReadWritePart * > ( partForURL ( url ) ) ;
if ( ! part ) return true ;
switch ( documentState ( url ) )
{
case Clean :
if ( ! force )
{
return true ;
}
kdDebug ( 9000 ) < < " Forced save " < < endl ;
break ;
case Modified :
kdDebug ( 9000 ) < < " Normal save " < < endl ;
break ;
case Dirty :
case DirtyAndModified :
{
int code = KMessageBox : : warningYesNoCancel ( TopLevel : : getInstance ( ) - > main ( ) ,
i18n ( " The file \" %1 \" is modified on disk. \n \n Are you sure you want to overwrite it? (External changes will be lost.) " ) . arg ( url . path ( ) ) ,
i18n ( " File Externally Modified " ) , i18n ( " Overwrite " ) , i18n ( " Do Not Overwrite " ) ) ;
if ( code = = KMessageBox : : Yes )
{
kdDebug ( 9000 ) < < " Dirty save!! " < < endl ;
}
else if ( code = = KMessageBox : : No )
{
return true ;
}
else
{
return false ; // a 'false' return means to interrupt the process that caused the save
}
}
break ;
default :
;
}
if ( part - > save ( ) )
{
_dirtyDocuments . remove ( part ) ;
emit documentChangedState ( url , Clean ) ;
emit savedFile ( url ) ;
}
return true ;
}
bool PartController : : saveAllFiles ( )
{
return saveFiles ( openURLs ( ) ) ;
}
bool PartController : : saveFiles ( KURL : : List const & filelist )
{
KURL : : List : : ConstIterator it = filelist . begin ( ) ;
while ( it ! = filelist . end ( ) )
{
if ( saveFile ( * it ) = = false )
return false ; //user cancelled
+ + it ;
}
return true ;
}
bool PartController : : querySaveFiles ( )
{
return saveFilesDialog ( KURL : : List ( ) ) ;
}
void PartController : : clearModified ( KURL : : List const & filelist )
{
KURL : : List : : ConstIterator it = filelist . begin ( ) ;
while ( it ! = filelist . end ( ) )
{
KParts : : ReadWritePart * rw_part = dynamic_cast < KParts : : ReadWritePart * > ( partForURL ( * it ) ) ;
if ( rw_part )
{
rw_part - > setModified ( false ) ;
}
+ + it ;
}
}
bool PartController : : saveFilesDialog ( KURL : : List const & ignoreList )
{
KURL : : List modList = modifiedDocuments ( ) ;
if ( modList . count ( ) > 0 & & modList ! = ignoreList )
{
KSaveSelectDialog dlg ( modList , ignoreList , TopLevel : : getInstance ( ) - > main ( ) ) ;
if ( dlg . exec ( ) = = TQDialog : : Accepted )
{
saveFiles ( dlg . filesToSave ( ) ) ;
clearModified ( dlg . filesNotToSave ( ) ) ;
}
else
{
return false ;
}
}
return true ;
}
bool PartController : : closeFilesDialog ( KURL : : List const & ignoreList )
{
if ( ! saveFilesDialog ( ignoreList ) ) return false ;
TQPtrList < KParts : : Part > partList ( * parts ( ) ) ;
TQPtrListIterator < KParts : : Part > it ( partList ) ;
while ( KParts : : Part * part = it . current ( ) )
{
KParts : : ReadOnlyPart * ro_part = dynamic_cast < KParts : : ReadOnlyPart * > ( part ) ;
if ( ro_part & & ! ignoreList . contains ( ro_part - > url ( ) ) | | ! ro_part )
{
closePart ( part ) ;
}
+ + it ;
}
return true ;
}
bool PartController : : closeFiles ( const KURL : : List & list )
{
KURL : : List : : ConstIterator it = list . begin ( ) ;
while ( it ! = list . end ( ) )
{
if ( ! closePart ( partForURL ( * it ) ) )
{
return false ;
}
+ + it ;
}
return true ;
}
bool PartController : : closeFile ( const KURL & url )
{
return closePart ( partForURL ( url ) ) ;
}
bool PartController : : closeAllFiles ( )
{
return closeFilesDialog ( KURL : : List ( ) ) ;
}
void PartController : : slotCloseAllWindows ( )
{
closeAllFiles ( ) ;
}
bool PartController : : closeAllOthers ( const KURL & url )
{
KURL : : List ignoreList ;
ignoreList . append ( url ) ;
return closeFilesDialog ( ignoreList ) ;
}
void PartController : : slotCloseOtherWindows ( )
{
if ( KParts : : ReadOnlyPart * active = dynamic_cast < KParts : : ReadOnlyPart * > ( activePart ( ) ) )
{
closeAllOthers ( active - > url ( ) ) ;
}
}
void PartController : : slotOpenFile ( )
{
TQString DefaultEncoding ;
if ( TQDomDocument * projectDom = API : : getInstance ( ) - > projectDom ( ) )
{
DefaultEncoding = DomUtil : : readEntry ( * projectDom , " /general/defaultencoding " , TQString ( ) ) ;
}
if ( DefaultEncoding . isEmpty ( ) )
{
// have a peek at katepart's settings:
TDEConfig * config = kapp - > config ( ) ;
config - > setGroup ( " Kate Document Defaults " ) ;
DefaultEncoding = config - > readEntry ( " Encoding " , TQString ( ) ) ;
}
KEncodingFileDialog : : Result result = KEncodingFileDialog : : getOpenURLsAndEncoding ( DefaultEncoding , TQString ( ) ,
TQString ( ) , TopLevel : : getInstance ( ) - > main ( ) , TQString ( ) ) ;
for ( KURL : : List : : Iterator it = result . URLs . begin ( ) ; it ! = result . URLs . end ( ) ; + + it )
{
m_presetEncoding = result . encoding ;
editDocument ( * it ) ;
}
}
void PartController : : slotOpenRecent ( const KURL & url )
{
editDocument ( url ) ;
// stupid bugfix - don't allow an active item in the list
m_openRecentAction - > setCurrentItem ( - 1 ) ;
}
bool PartController : : readyToClose ( )
{
blockSignals ( true ) ;
closeAllFiles ( ) ; // this should never return false, as the files are already saved
return true ;
}
void PartController : : slotActivePartChanged ( KParts : : Part * part )
{
kdDebug ( 9000 ) < < k_funcinfo < < part < < endl ;
if ( ! m_isJumping & & ! m_removingActivePart )
{
if ( KParts : : ReadOnlyPart * ro_part = dynamic_cast < KParts : : ReadOnlyPart * > ( m_currentActivePart ) )
{
addHistoryEntry ( ro_part ) ;
}
}
m_currentActivePart = part ;
m_removingActivePart = false ;
if ( part ) {
KXMLGUIClient * client = dynamic_cast < KXMLGUIClient * > ( part - > widget ( ) ) ;
if ( client ) Core : : setupShourtcutTips ( client ) ;
}
updateMenuItems ( ) ;
TQTimer : : singleShot ( 100 , this , TQT_SLOT ( slotWaitForFactoryHack ( ) ) ) ;
}
void PartController : : showPart ( KParts : : Part * part , const TQString & name , const TQString & shortDescription )
{
if ( ! part - > widget ( ) ) {
/// @todo error handling
return ; // to avoid later crash
}
TQPtrListIterator < KParts : : Part > it ( * parts ( ) ) ;
for ( ; it . current ( ) ; + + it )
{
if ( it . current ( ) = = part ) {
// part already embedded
activatePart ( it . current ( ) ) ;
return ;
}
}
// embed the part
TopLevel : : getInstance ( ) - > embedPartView ( part - > widget ( ) , name , shortDescription ) ;
addPart ( part ) ;
}
void PartController : : slotDocumentDirty ( Kate : : Document * d , bool isModified , unsigned char reason )
{
kdDebug ( 9000 ) < < k_funcinfo < < endl ;
// KTextEditor::Document * doc = reinterpret_cast<KTextEditor::Document*>( d ); // theoretically unsafe in MI scenario
KTextEditor : : Document * doc = 0 ;
TQPtrListIterator < KParts : : Part > it ( * parts ( ) ) ;
while ( it . current ( ) )
{
if ( ( void * ) it . current ( ) = = ( void * ) d )
{
doc = dynamic_cast < KTextEditor : : Document * > ( it . current ( ) ) ;
break ;
}
+ + it ;
}
// this is a bit strange, but in order to avoid weird crashes
// down in KDirWatcher, we want to step off the call chain before
// opening any messageboxes
if ( doc )
{
ModificationData * p = new ModificationData ;
p - > doc = doc ;
p - > isModified = isModified ;
p - > reason = reason ;
KDevJobTimer : : singleShot ( 0 , this , TQT_SLOT ( slotDocumentDirtyStepTwo ( void * ) ) , p ) ;
}
}
void PartController : : slotDocumentDirtyStepTwo ( void * payload )
{
if ( ! payload ) return ;
ModificationData * p = reinterpret_cast < ModificationData * > ( payload ) ;
KTextEditor : : Document * doc = p - > doc ;
// let's make sure the document is still loaded
bool haveDocument = false ;
if ( const TQPtrList < KParts : : Part > * partlist = parts ( ) )
{
TQPtrListIterator < KParts : : Part > it ( * partlist ) ;
while ( KParts : : Part * part = it . current ( ) )
{
if ( p - > doc = = dynamic_cast < KTextEditor : : Document * > ( part ) )
{
haveDocument = true ;
break ;
}
+ + it ;
}
}
if ( ! haveDocument ) return ;
bool isModified = p - > isModified ;
unsigned char reason = p - > reason ;
delete p ;
KURL url = storedURLForPart ( doc ) ;
if ( url . isEmpty ( ) )
{
kdDebug ( 9000 ) < < " Warning!! the stored url is empty. Bailing out! " < < endl ;
}
if ( reason > 0 )
{
if ( ! _dirtyDocuments . contains ( doc ) )
{
_dirtyDocuments . append ( doc ) ;
}
if ( reactToDirty ( url , reason ) )
{
// file has been reloaded
emit documentChangedState ( url , Clean ) ;
_dirtyDocuments . remove ( doc ) ;
}
else
{
doEmitState ( url ) ;
}
}
else
{
_dirtyDocuments . remove ( doc ) ;
emit documentChangedState ( url , Clean ) ;
}
kdDebug ( 9000 ) < < doc - > url ( ) . url ( ) < < endl ;
kdDebug ( 9000 ) < < isModified < < endl ;
kdDebug ( 9000 ) < < reason < < endl ;
}
bool PartController : : isDirty ( KURL const & url )
{
return _dirtyDocuments . contains ( static_cast < KTextEditor : : Document * > ( partForURL ( url ) ) ) ;
}
bool PartController : : reactToDirty ( KURL const & url , unsigned char reason )
{
TDEConfig * config = kapp - > config ( ) ;
config - > setGroup ( " Editor " ) ;
TQString dirtyAction = config - > readEntry ( " DirtyAction " ) ;
if ( dirtyAction = = " nothing " ) return false ;
bool isModified = true ;
if ( KParts : : ReadWritePart * part = dynamic_cast < KParts : : ReadWritePart * > ( partForURL ( url ) ) )
{
isModified = part - > isModified ( ) ;
}
else
{
kdDebug ( 9000 ) < < k_funcinfo < < " Warning. Not a ReadWritePart. " < < endl ;
return false ;
}
if ( isModified )
{
KMessageBox : : sorry ( TopLevel : : getInstance ( ) - > main ( ) ,
i18n ( " Conflict: The file \" %1 \" has changed on disk while being modified in memory. \n \n "
" You should investigate before saving to make sure you are not losing data. " ) . arg ( url . path ( ) ) ,
i18n ( " Conflict " ) ) ;
return false ;
}
if ( reason = = 3 ) // means the file was deleted
{
KMessageBox : : sorry ( TopLevel : : getInstance ( ) - > main ( ) ,
i18n ( " Warning: The file \" %1 \" has been deleted on disk. \n \n "
" If this was not your intention, make sure to save this file now. " ) . arg ( url . path ( ) ) ,
i18n ( " File Deleted " ) ) ;
return false ;
}
if ( dirtyAction = = " alert " )
{
if ( KMessageBox : : warningYesNo ( TopLevel : : getInstance ( ) - > main ( ) ,
i18n ( " The file \" %1 \" has changed on disk. \n \n Do you want to reload it? " ) . arg ( url . path ( ) ) ,
i18n ( " File Changed " ) , i18n ( " Reload " ) , i18n ( " Do Not Reload " ) ) = = KMessageBox : : No )
{
return false ;
}
}
// here we either answered yes above or are in autoreload mode
reloadFile ( url ) ;
return true ;
}
void PartController : : slotNewDesignerStatus ( const TQString & formName , int status )
{
kdDebug ( 9000 ) < < k_funcinfo < < endl ;
kdDebug ( 9000 ) < < " formName: " < < formName < < " , status: " < < status < < endl ;
emit documentChangedState ( KURL : : fromPathOrURL ( formName ) , DocumentState ( status ) ) ;
}
void PartController : : slotNewStatus ( )
{
kdDebug ( 9000 ) < < k_funcinfo < < endl ;
TQObject * senderobj = TQT_TQOBJECT ( const_cast < TQT_BASE_OBJECT_NAME * > ( sender ( ) ) ) ;
KTextEditor : : View * view = dynamic_cast < KTextEditor : : View * > ( senderobj ) ;
if ( view )
{
doEmitState ( view - > document ( ) - > url ( ) ) ;
}
}
DocumentState PartController : : documentState ( KURL const & url )
{
KParts : : ReadWritePart * rw_part = dynamic_cast < KParts : : ReadWritePart * > ( partForURL ( url ) ) ;
if ( ! rw_part ) return Clean ;
DocumentState state = Clean ;
if ( rw_part - > isModified ( ) )
{
state = Modified ;
}
if ( isDirty ( url ) )
{
if ( state = = Modified )
{
state = DirtyAndModified ;
}
else
{
state = Dirty ;
}
}
return state ;
}
void PartController : : doEmitState ( KURL const & url )
{
emit documentChangedState ( url , documentState ( url ) ) ;
}
KURL : : List PartController : : openURLs ( )
{
KURL : : List list ;
TQPtrListIterator < KParts : : Part > it ( * parts ( ) ) ;
for ( ; it . current ( ) ; + + it )
{
if ( KParts : : ReadOnlyPart * ro_part = dynamic_cast < KParts : : ReadOnlyPart * > ( it . current ( ) ) )
{
list < < ro_part - > url ( ) ;
}
}
return list ;
}
/////////////////////////////////////////////////////////////////////////////
//BEGIN History methods
PartController : : HistoryEntry : : HistoryEntry ( const KURL & u , int l , int c )
: url ( u ) , line ( l ) , col ( c )
{
id = abs ( TQTime : : currentTime ( ) . msecsTo ( TQTime ( ) ) ) ; // should provide a reasonably unique number
}
void PartController : : slotBack ( )
{
HistoryEntry thatEntry = m_backHistory . front ( ) ;
m_backHistory . pop_front ( ) ;
m_backAction - > setEnabled ( ! m_backHistory . isEmpty ( ) ) ;
HistoryEntry thisEntry = createHistoryEntry ( ) ;
if ( ! thisEntry . url . isEmpty ( ) )
{
m_forwardHistory . push_front ( thisEntry ) ;
m_forwardAction - > setEnabled ( true ) ;
}
jumpTo ( thatEntry ) ;
}
void PartController : : slotForward ( )
{
HistoryEntry thatEntry = m_forwardHistory . front ( ) ;
m_forwardHistory . pop_front ( ) ;
m_forwardAction - > setEnabled ( ! m_forwardHistory . isEmpty ( ) ) ;
HistoryEntry thisEntry = createHistoryEntry ( ) ;
if ( ! thisEntry . url . isEmpty ( ) )
{
m_backHistory . push_front ( thisEntry ) ;
m_backAction - > setEnabled ( true ) ;
}
jumpTo ( thatEntry ) ;
}
void PartController : : slotBackAboutToShow ( )
{
TDEPopupMenu * popup = m_backAction - > popupMenu ( ) ;
popup - > clear ( ) ;
if ( m_backHistory . isEmpty ( ) ) return ;
int i = 0 ;
TQValueList < HistoryEntry > : : ConstIterator it = m_backHistory . begin ( ) ;
while ( i < 10 & & it ! = m_backHistory . end ( ) )
{
popup - > insertItem ( ( * it ) . url . fileName ( ) + TQString ( " (%1) " ) . arg ( ( * it ) . line + 1 ) , ( * it ) . id ) ;
+ + i ;
+ + it ;
}
}
void PartController : : slotForwardAboutToShow ( )
{
TDEPopupMenu * popup = m_forwardAction - > popupMenu ( ) ;
popup - > clear ( ) ;
if ( m_forwardHistory . isEmpty ( ) ) return ;
int i = 0 ;
TQValueList < HistoryEntry > : : ConstIterator it = m_forwardHistory . begin ( ) ;
while ( i < 10 & & it ! = m_forwardHistory . end ( ) )
{
popup - > insertItem ( ( * it ) . url . fileName ( ) + TQString ( " (%1) " ) . arg ( ( * it ) . line + 1 ) , ( * it ) . id ) ;
+ + i ;
+ + it ;
}
}
void PartController : : slotBackPopupActivated ( int id )
{
TQValueList < HistoryEntry > : : Iterator it = m_backHistory . begin ( ) ;
while ( it ! = m_backHistory . end ( ) )
{
if ( ( * it ) . id = = id )
{
HistoryEntry entry = * it ;
m_backHistory . erase ( m_backHistory . begin ( ) , + + it ) ;
m_backAction - > setEnabled ( ! m_backHistory . isEmpty ( ) ) ;
HistoryEntry thisEntry = createHistoryEntry ( ) ;
if ( ! thisEntry . url . isEmpty ( ) )
{
m_forwardHistory . push_front ( thisEntry ) ;
m_forwardAction - > setEnabled ( true ) ;
}
jumpTo ( entry ) ;
return ;
}
+ + it ;
}
}
void PartController : : slotForwardPopupActivated ( int id )
{
TQValueList < HistoryEntry > : : Iterator it = m_forwardHistory . begin ( ) ;
while ( it ! = m_forwardHistory . end ( ) )
{
if ( ( * it ) . id = = id )
{
HistoryEntry entry = * it ;
m_forwardHistory . erase ( m_forwardHistory . begin ( ) , + + it ) ;
m_forwardAction - > setEnabled ( ! m_forwardHistory . isEmpty ( ) ) ;
HistoryEntry thisEntry = createHistoryEntry ( ) ;
if ( ! thisEntry . url . isEmpty ( ) )
{
m_backHistory . push_front ( thisEntry ) ;
m_backAction - > setEnabled ( true ) ;
}
jumpTo ( entry ) ;
return ;
}
+ + it ;
}
}
void PartController : : jumpTo ( const HistoryEntry & entry )
{
m_isJumping = true ;
editDocument ( entry . url , entry . line , entry . col ) ;
m_isJumping = false ;
}
PartController : : HistoryEntry PartController : : createHistoryEntry ( KParts : : ReadOnlyPart * ro_part ) {
if ( ro_part = = 0 )
ro_part = dynamic_cast < KParts : : ReadOnlyPart * > ( activePart ( ) ) ;
if ( ! ro_part ) return HistoryEntry ( ) ;
KTextEditor : : ViewCursorInterface * cursorIface = dynamic_cast < KTextEditor : : ViewCursorInterface * > ( ro_part - > widget ( ) ) ;
if ( ! cursorIface ) return HistoryEntry ( ) ;
uint line = 0 ;
uint col = 0 ;
cursorIface - > cursorPositionReal ( & line , & col ) ;
return HistoryEntry ( ro_part - > url ( ) , line , col ) ;
}
// this should be called _before_ a jump is made
void PartController : : addHistoryEntry ( KParts : : ReadOnlyPart * part )
{
if ( m_isJumping ) return ;
HistoryEntry thisEntry = createHistoryEntry ( part ) ;
if ( ! thisEntry . url . isEmpty ( ) )
{
HistoryEntry lastEntry = m_backHistory . front ( ) ;
if ( ( lastEntry . url . path ( ) ! = thisEntry . url . path ( ) ) | | ( lastEntry . line ! = thisEntry . line ) )
{
m_backHistory . push_front ( thisEntry ) ;
m_backAction - > setEnabled ( true ) ;
m_forwardHistory . clear ( ) ;
m_forwardAction - > setEnabled ( false ) ;
}
else
{
kdDebug ( 9000 ) < < " ** avoiding to create duplicate history entry ** " < < endl ;
}
}
}
//END History methods
void PartController : : slotWaitForFactoryHack ( )
{
//kdDebug(9000) << k_funcinfo << endl;
if ( ! activePart ( ) ) return ;
if ( dynamic_cast < KTextEditor : : View * > ( activePart ( ) - > widget ( ) ) )
{
if ( ! activePart ( ) - > factory ( ) )
{
TQTimer : : singleShot ( 100 , this , TQT_SLOT ( slotWaitForFactoryHack ( ) ) ) ;
return ;
}
else
{
EditorProxy : : getInstance ( ) - > installPopup ( activePart ( ) ) ;
}
}
if ( MultiBuffer * multiBuffer =
dynamic_cast < MultiBuffer * > (
EditorProxy : : getInstance ( ) - > topWidgetForPart ( activePart ( ) ) )
)
{
KURL url = dynamic_cast < KParts : : ReadOnlyPart * > ( activePart ( ) ) - > url ( ) ;
multiBuffer - > activePartChanged ( url ) ;
// Really unfortunate, but the mainWindow relies upon this
// to set the tab's icon
emit documentChangedState ( url , documentState ( url ) ) ;
}
}
KParts : : ReadOnlyPart * PartController : : qtDesignerPart ( )
{
TQPtrListIterator < KParts : : Part > it ( * parts ( ) ) ;
for ( ; it . current ( ) ; + + it )
{
KInterfaceDesigner : : Designer * des = dynamic_cast < KInterfaceDesigner : : Designer * > ( it . current ( ) ) ;
if ( des & & des - > designerType ( ) = = KInterfaceDesigner : : TQtDesigner )
return des ;
}
return 0 ;
}
KTextEditor : : Editor * PartController : : openTextDocument ( bool activate )
{
KTextEditor : : Editor * editorpart =
createEditorPart ( activate , false , KURL ( i18n ( " unnamed " ) ) ) ;
if ( editorpart )
{
if ( ! m_presetEncoding . isNull ( ) )
{
KParts : : BrowserExtension * extension =
KParts : : BrowserExtension : : childObject ( editorpart ) ;
if ( extension )
{
KParts : : URLArgs args ;
args . serviceType = TQString ( " text/plain; " ) + m_presetEncoding ;
extension - > setURLArgs ( args ) ;
}
m_presetEncoding = TQString ( ) ;
}
TQWidget * widget =
EditorProxy : : getInstance ( ) - > topWidgetForPart ( editorpart ) ;
addHistoryEntry ( ) ;
integratePart ( editorpart , KURL ( i18n ( " unnamed " ) ) , widget , true , true ) ;
EditorProxy : : getInstance ( ) - > setLineNumber ( editorpart , 0 , 0 ) ;
}
return editorpart ;
}
void PartController : : textChanged ( )
{
if ( KTextEditor : : Document * doc = dynamic_cast < KTextEditor : : Document * > ( activePart ( ) ) )
{
if ( KTextEditor : : ViewCursorInterface * vci = dynamic_cast < KTextEditor : : ViewCursorInterface * > ( doc - > widget ( ) ) )
{
m_gotoLastEditPosAction - > setEnabled ( true ) ;
m_lastEditPos . url = doc - > url ( ) ;
vci - > cursorPosition ( & m_lastEditPos . pos . first , & m_lastEditPos . pos . second ) ;
}
}
}
void PartController : : gotoLastEditPos ( )
{
editDocument ( m_lastEditPos . url , m_lastEditPos . pos . first , m_lastEditPos . pos . second ) ;
}
void PartController : : slotDocumentUrlChanged ( )
{
TQObject * obj = TQT_TQOBJECT ( const_cast < TQT_BASE_OBJECT_NAME * > ( sender ( ) ) ) ;
KTextEditor : : Document * doc = dynamic_cast < KTextEditor : : Document * > ( obj ) ;
if ( ! doc )
return ;
MultiBuffer * multiBuffer = dynamic_cast < MultiBuffer * > (
EditorProxy : : getInstance ( ) - > findPartWidget ( doc ) ) ;
if ( ! multiBuffer )
return ;
multiBuffer - > updateUrlForPart ( doc , doc - > url ( ) ) ;
updatePartURL ( doc ) ;
emit partURLChanged ( doc ) ;
}
# include "partcontroller.moc"