00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "problemreporter.h"
00020 #include "javasupportpart.h"
00021 #include "configproblemreporter.h"
00022 #include "backgroundparser.h"
00023
00024 #include <kdevpartcontroller.h>
00025 #include <kdevmainwindow.h>
00026
00027 #include <kdeversion.h>
00028 #include <kparts/part.h>
00029 #include <ktexteditor/editinterface.h>
00030 #include <ktexteditor/document.h>
00031 #include <ktexteditor/markinterface.h>
00032
00033 #if (KDE_VERSION > 305)
00034 # include <ktexteditor/markinterfaceextension.h>
00035 #else
00036 # include "kde30x_markinterfaceextension.h"
00037 #endif
00038 #include <ktexteditor/view.h>
00039
00040 #include <kdebug.h>
00041 #include <klocale.h>
00042 #include <kstatusbar.h>
00043 #include <kurl.h>
00044 #include <kapplication.h>
00045 #include <kiconloader.h>
00046 #include <kdialogbase.h>
00047
00048 #include <kconfig.h>
00049
00050 #include <qtimer.h>
00051 #include <qregexp.h>
00052 #include <qvbox.h>
00053 #include <qfileinfo.h>
00054 #include <qwhatsthis.h>
00055 #include <qgroupbox.h>
00056
00057
00058 class ProblemItem: public KListViewItem
00059 {
00060 public:
00061 ProblemItem( QListView* parent, const QString& level, const QString& problem,
00062 const QString& file, const QString& line, const QString& column )
00063 : KListViewItem( parent, level, problem, file, line, column ) {}
00064
00065 ProblemItem( QListViewItem* parent, const QString& level, const QString& problem,
00066 const QString& file, const QString& line, const QString& column )
00067 : KListViewItem( parent, level, problem, file, line, column ) {}
00068
00069 int compare( QListViewItem* item, int column, bool ascending ) const {
00070 if( column == 2 || column == 3 ){
00071 int a = text( column ).toInt();
00072 int b = item->text( column ).toInt();
00073 if( a == b )
00074 return 0;
00075 return( a > b ? 1 : -1 );
00076 }
00077 return KListViewItem::compare( item, column, ascending );
00078 }
00079
00080 };
00081
00082 ProblemReporter::ProblemReporter( JavaSupportPart* part, QWidget* parent, const char* name )
00083 : KListView( parent, name ? name : "problemreporter" ),
00084 m_javaSupport( part ),
00085 m_document( 0 ),
00086 m_markIface( 0 )
00087 {
00088 QWhatsThis::add(this, i18n("<b>Problem reporter</b><p>This window shows various \"problems\" in your project. "
00089 "It displays TODO entries, FIXME's and errors reported by a language parser. "
00090 "To add a TODO or FIXME entry, just type<br>"
00091 "<tt>//@todo my todo</tt><br>"
00092 "<tt>//TODO: my todo</tt><br>"
00093 "<tt>//FIXME fix this</tt>"));
00094
00095 addColumn( i18n("Level") );
00096 addColumn( i18n("File") );
00097 addColumn( i18n("Line") );
00098 addColumn( i18n("Column") );
00099 addColumn( i18n("Problem") );
00100 setAllColumnsShowFocus( TRUE );
00101
00102 m_timer = new QTimer( this );
00103
00104 connect( part->partController(), SIGNAL(activePartChanged(KParts::Part*)),
00105 this, SLOT(slotActivePartChanged(KParts::Part*)) );
00106 connect( part->partController(), SIGNAL(partAdded(KParts::Part*)),
00107 this, SLOT(slotPartAdded(KParts::Part*)) );
00108 connect( part->partController(), SIGNAL(partRemoved(KParts::Part*)),
00109 this, SLOT(slotPartRemoved(KParts::Part*)) );
00110
00111 connect( m_timer, SIGNAL(timeout()), this, SLOT(reparse()) );
00112
00113 connect( this, SIGNAL(executed(QListViewItem*)),
00114 this, SLOT(slotSelected(QListViewItem*)) );
00115
00116 configure();
00117 }
00118
00119 ProblemReporter::~ProblemReporter()
00120 {
00121 }
00122
00123 void ProblemReporter::slotActivePartChanged( KParts::Part* part )
00124 {
00125 if( !part )
00126 return;
00127
00128 m_timer->stop();
00129
00130 if( m_document )
00131 disconnect( m_document, 0, this, 0 );
00132
00133 m_document = dynamic_cast<KTextEditor::Document*>( part );
00134 m_markIface = 0;
00135
00136 if( !m_document )
00137 return;
00138
00139 m_fileName = m_document->url().path();
00140
00141 if( !m_javaSupport->isValidSource(m_fileName) )
00142 return;
00143
00144 connect( m_document, SIGNAL(textChanged()), this, SLOT(slotTextChanged()) );
00145 m_markIface = dynamic_cast<KTextEditor::MarkInterface*>( part );
00146
00147 if( !m_javaSupport->backgroundParser() )
00148 return;
00149
00150 m_javaSupport->backgroundParser()->lock();
00151 bool needReparse = false;
00152 if( !m_javaSupport->backgroundParser()->translationUnit(m_fileName) )
00153 needReparse = true;
00154 m_javaSupport->backgroundParser()->unlock();
00155
00156 if( needReparse )
00157 reparse();
00158 }
00159
00160 void ProblemReporter::slotTextChanged()
00161 {
00162 if( m_active )
00163 m_timer->changeInterval( m_delay );
00164 }
00165
00166 void ProblemReporter::removeAllProblems( const QString& filename )
00167 {
00168 QListViewItem* current = firstChild();
00169 while( current ){
00170 QListViewItem* i = current;
00171 current = current->nextSibling();
00172
00173 if( i->text(1) == filename )
00174 delete( i );
00175 }
00176
00177 if( m_document && m_markIface ){
00178 QPtrList<KTextEditor::Mark> marks = m_markIface->marks();
00179 QPtrListIterator<KTextEditor::Mark> it( marks );
00180 while( it.current() ){
00181 m_markIface->removeMark( it.current()->line, KTextEditor::MarkInterface::markType07 );
00182 ++it;
00183 }
00184 }
00185 }
00186
00187 void ProblemReporter::reparse()
00188 {
00189 if( !m_javaSupport->isValid() )
00190 return;
00191
00192
00193
00194 if ( !m_fileName.endsWith(".java") )
00195 return;
00196
00197 m_timer->stop();
00198
00199 kdDebug(9013) << "ProblemReporter::reparse()" << endl;
00200 m_javaSupport->backgroundParser()->addFile( m_fileName );
00201 kdDebug(9013) << "---> file added " << m_fileName << endl;
00202 }
00203
00204 void ProblemReporter::slotSelected( QListViewItem* item )
00205 {
00206 KURL url( item->text(1) );
00207 int line = item->text( 2 ).toInt();
00208
00209 m_javaSupport->partController()->editDocument( url, line-1 );
00210
00211 }
00212
00213 void ProblemReporter::reportProblem( const QString& fileName, const Problem& p )
00214 {
00215 int markType = levelToMarkType( p.level() );
00216 if( markType != -1 && m_document && m_markIface && m_fileName == fileName ){
00217 m_markIface->addMark( p.line(), markType );
00218 }
00219
00220 QString msg = p.text();
00221 msg = msg.replace( QRegExp("\n"), "" );
00222
00223 new ProblemItem( this,
00224 levelToString( p.level() ),
00225 fileName,
00226 QString::number( p.line() + 1 ),
00227 QString::number( p.column() + 1 ),
00228 msg );
00229 }
00230
00231 void ProblemReporter::configure()
00232 {
00233 kdDebug(9013) << "ProblemReporter::configure()" << endl;
00234 KConfig* config = kapp->config();
00235 config->setGroup( "General Options" );
00236 m_active = config->readBoolEntry( "EnableJavaBgParser", TRUE );
00237 m_delay = config->readNumEntry( "BgParserDelay", 250 );
00238 }
00239
00240 void ProblemReporter::configWidget( KDialogBase* dlg )
00241 {
00242 QVBox *vbox = dlg->addVBoxPage(i18n("Java Parsing"));
00243 ConfigureProblemReporter* w = new ConfigureProblemReporter( vbox );
00244
00245 w->groupBox3->hide();
00246 connect(dlg, SIGNAL(okClicked()), w, SLOT(accept()));
00247 connect(dlg, SIGNAL(okClicked()), this, SLOT(configure()));
00248 }
00249
00250 void ProblemReporter::slotPartAdded( KParts::Part* part )
00251 {
00252 KTextEditor::MarkInterfaceExtension* iface = dynamic_cast<KTextEditor::MarkInterfaceExtension*>( part );
00253
00254 if( !iface )
00255 return;
00256
00257 iface->setPixmap( KTextEditor::MarkInterface::markType07, SmallIcon("stop") );
00258 }
00259
00260 void ProblemReporter::slotPartRemoved( KParts::Part* part )
00261 {
00262 kdDebug(9013) << "ProblemReporter::slotPartRemoved()" << endl;
00263 if( part == m_document ){
00264 m_document = 0;
00265 m_timer->stop();
00266 }
00267 }
00268
00269 QString ProblemReporter::levelToString( int level ) const
00270 {
00271 switch( level )
00272 {
00273 case Problem::Level_Error:
00274 return QString::fromLatin1( "Error" );
00275 case Problem::Level_Warning:
00276 return QString::fromLatin1( "Warning" );
00277 case Problem::Level_Todo:
00278 return QString::fromLatin1( "Todo" );
00279 case Problem::Level_Fixme:
00280 return QString::fromLatin1( "Fixme" );
00281 default:
00282 return QString::null;
00283 }
00284 }
00285
00286 int ProblemReporter::levelToMarkType( int level ) const
00287 {
00288 switch( level )
00289 {
00290 case Problem::Level_Error:
00291 return KTextEditor::MarkInterface::markType07;
00292 case Problem::Level_Warning:
00293 return -1;
00294 case Problem::Level_Todo:
00295 return -1;
00296 case Problem::Level_Fixme:
00297 return -1;
00298 default:
00299 return -1;
00300 }
00301 }
00302
00303 #include "problemreporter.moc"