00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00018 #include <qregexp.h>
00019
00021 #include <kaction.h>
00022 #include <kdebug.h>
00023 #include <kiconloader.h>
00024 #include <klocale.h>
00025 #include <kpopupmenu.h>
00026
00028 #include "autodetailsview.h"
00029
00030 #include "kdevappfrontend.h"
00031 #include "kdevcore.h"
00032 #include "kdevmainwindow.h"
00033 #include "kdevpartcontroller.h"
00034 #include "kdevcreatefile.h"
00035 #include "kdevlanguagesupport.h"
00036 #include "kdevmakefrontend.h"
00037
00038 #include "domutil.h"
00039
00040 #include "targetoptionsdlg.h"
00041 #include "addfiledlg.h"
00042 #include "addicondlg.h"
00043 #include "addexistingfilesdlg.h"
00044 #include "removefiledlg.h"
00045 #include "removetargetdlg.h"
00046
00047 #include "autolistviewitems.h"
00048
00049 #include "autoprojectpart.h"
00050 #include "autoprojectwidget.h"
00051
00052 #include "subclassesdlg.h"
00053
00054 AutoDetailsView::AutoDetailsView(AutoProjectWidget* widget, AutoProjectPart* part, QWidget *parent, const char *name)
00055 : KListView(parent, name)
00056 {
00057 m_widget = widget;
00058 m_part = part;
00059
00060 initActions();
00061 QDomDocument &dom = *(m_part->projectDom());
00062 m_subclasslist = DomUtil::readPairListEntry(dom,"/kdevautoproject/subclassing" ,
00063 "subclass","sourcefile", "uifile");
00064
00065 }
00066
00067
00068 AutoDetailsView::~AutoDetailsView()
00069 {
00070 }
00071
00072 void AutoDetailsView::initActions()
00073 {
00074 KActionCollection * actions = new KActionCollection( this );
00075
00076 targetOptionsAction = new KAction( i18n( "Options..." ), "configure", 0,
00077 this, SLOT( slotTargetOptions() ), actions, "target options" );
00078 targetOptionsAction->setWhatsThis(i18n("<b>Options</b><p>Target options dialog that provides settings for linker flags and lists of dependencies and external libraries."));
00079 addNewFileAction = new KAction( i18n( "Create New File..." ), "filenew", 0,
00080 this, SLOT( slotAddNewFile() ), actions, "add new file" );
00081 addNewFileAction->setWhatsThis(i18n("<b>Create new file</b><p>Creates a new file and adds it to a currently selected target."));
00082 addExistingFileAction = new KAction( i18n( "Add Existing Files..." ), "fileimport", 0,
00083 this, SLOT( slotAddExistingFile() ), actions, "add existing file" );
00084 addExistingFileAction->setWhatsThis(i18n("<b>Add existing files</b><p>Adds existing file to a currently selected target. Header files will not be included in SOURCES list of a target. "
00085 "They will be added to noinst_HEADERS instead."));
00086 addIconAction = new KAction( i18n( "Add Icon..." ), "iconadd_kdevelop", 0,
00087 this, SLOT( slotAddIcon() ), actions, "add icon" );
00088 addIconAction->setWhatsThis(i18n("<b>Add icon</b><p>Adds an icon to a KDEICON target."));
00089 buildTargetAction = new KAction( i18n( "Build Target..." ), "launch", 0,
00090 this, SLOT( slotBuildTarget() ), actions, "build target" );
00091 buildTargetAction->setWhatsThis(i18n("<b>Build target</b><p>Constructs a series of make commands to build the selected target. "
00092 "Also builds dependent targets."));
00093 executeTargetAction = new KAction( i18n( "Execute Target..." ), "exec", 0,
00094 this, SLOT( slotExecuteTarget() ), actions, "execute target" );
00095 executeTargetAction->setWhatsThis(i18n("<b>Execute target</b><p>Executes the target and tries to build in case it isn't."));
00096 setActiveTargetAction = new KAction( i18n( "Make Target Active" ), "", 0,
00097 this, SLOT( slotSetActiveTarget() ), actions, "set active target" );
00098 setActiveTargetAction->setWhatsThis(i18n("<b>Make target active</b><p>Marks the currently selected target as 'active'. New files and classes by default go to an active target. "
00099 "<b>Build Active Target</b> menu command builds it."));
00100 removeDetailAction = new KAction( i18n( "Remove" ), "editdelete", 0,
00101 this, SLOT( slotRemoveDetail() ), actions, "remove detail" );
00102 removeDetailAction->setWhatsThis(i18n("<b>Remove</b><p>Shows a list of targets dependent on the selected target or file and asks for removal. Also asks if the target or file should be removed from disk."));
00103
00104 connect( this, SIGNAL( executed( QListViewItem* ) ),
00105 this, SLOT( slotDetailsExecuted( QListViewItem* ) ) );
00106 connect ( this, SIGNAL ( returnPressed ( QListViewItem* ) ),
00107 this, SLOT ( slotDetailsExecuted ( QListViewItem* ) ) );
00108 connect( this, SIGNAL( contextMenu( KListView*, QListViewItem*, const QPoint& ) ),
00109 this, SLOT( slotDetailsContextMenu( KListView*, QListViewItem*, const QPoint& ) ) );
00110 }
00111
00112 QString AutoDetailsView::getUiFileLink(const QString &relpath, const QString& filename)
00113 {
00114 DomUtil::PairList::iterator it;
00115
00116 for (it=m_subclasslist.begin();it != m_subclasslist.end(); ++it)
00117 {
00118 if ((*it).first==QString("/")+relpath+filename)
00119 return (*it).second;
00120 }
00121
00122 return QString ("");
00123 }
00124
00125 void AutoDetailsView::slotTargetOptions()
00126 {
00127 kdDebug( 9020 ) << "AutoDetailsView::slotTargetOptions()" << endl;
00128 TargetItem *titem = static_cast <TargetItem*> ( selectedItem() );
00129 if ( !titem ) return ;
00130
00131 TargetOptionsDialog dlg( m_widget, titem, this, "target options dialog" );
00132
00133 dlg.setCaption ( i18n ( "Target Options for '%1'" ).arg ( titem->name ) );
00134
00135 dlg.exec();
00136 }
00137
00138
00139 void AutoDetailsView::slotAddNewFile()
00140 {
00141 TargetItem * titem = static_cast <TargetItem*> ( selectedItem() );
00142 if ( !titem )
00143 return ;
00144
00145 KDevCreateFile * createFileSupport = m_part->createFileSupport();
00146 if (createFileSupport)
00147 {
00148 KDevCreateFile::CreatedFile crFile =
00149 createFileSupport->createNewFile(QString::null, m_widget->selectedSubproject()->path);
00150
00151
00152
00153
00154
00155
00156
00157 } else {
00158 AddFileDialog dlg( m_part, m_widget, m_widget->selectedSubproject(), titem,
00159 this, "add file dialog" );
00160 QString caption;
00161 if ( titem->name.isEmpty() )
00162 caption = i18n ( "%1 in %2" ).arg ( titem->primary ).arg ( titem->prefix );
00163 else
00164 caption = titem->name;
00165
00166 dlg.setCaption ( i18n ( "Add New File to '%1'" ).arg ( caption ) );
00167
00168 if ( dlg.exec() )
00169 emit selectionChanged( titem );
00170 }
00171 }
00172
00173
00174 void AutoDetailsView::slotAddExistingFile()
00175 {
00176 TargetItem * titem = static_cast <TargetItem*> ( selectedItem() );
00177 if ( !titem ) return;
00178
00179 AddExistingFilesDialog dlg( m_part, m_widget, m_widget->selectedSubproject(), titem,
00180 this, "add existing files" );
00181 QString caption;
00182 if ( titem->name.isEmpty() )
00183 caption = i18n ( "%1 in %2" ).arg ( titem->primary ).arg ( titem->prefix );
00184 else
00185 caption = titem->name;
00186
00187 dlg.setCaption( i18n( "Add Existing Files to '%1'" ).arg ( caption ) );
00188
00189 dlg.exec();
00190 }
00191
00192
00193 void AutoDetailsView::slotAddIcon()
00194 {
00195 TargetItem * titem = static_cast <TargetItem*> ( selectedItem() );
00196 if ( !titem ) return ;
00197
00198 AddIconDialog dlg( m_part, m_widget, m_widget->selectedSubproject(), titem,
00199 this, "add icon" );
00200 dlg.exec();
00201 }
00202
00203
00204 void AutoDetailsView::slotBuildTarget()
00205 {
00206 ProjectItem * pvitem = static_cast<ProjectItem*>( selectedItem() );
00207
00208 if ( !pvitem )
00209 return;
00210
00211 TargetItem* titem = 0;
00212
00213 if ( pvitem->type() == ProjectItem::File )
00214 titem = static_cast <TargetItem*> ( pvitem->parent() );
00215 else
00216 titem = static_cast <TargetItem*> ( selectedItem() );
00217
00218 QString relpath = m_widget->selectedSubproject()->path.mid( m_part->projectDirectory().length() );
00219 m_part->buildTarget(relpath, titem);
00220 }
00221
00222 void AutoDetailsView::slotExecuteTarget()
00223 {
00224 ProjectItem * pvitem = static_cast<ProjectItem*>( selectedItem() );
00225
00226 if ( !pvitem )
00227 return;
00228
00229 TargetItem* titem = 0;
00230
00231 if ( pvitem->type() == ProjectItem::File )
00232 titem = static_cast <TargetItem*> ( pvitem->parent() );
00233 else
00234 titem = static_cast <TargetItem*> ( selectedItem() );
00235
00236
00237 m_part->executeTarget(m_widget->selectedSubproject()->path, titem);
00238 }
00239
00240 void AutoDetailsView::slotRemoveDetail()
00241 {
00242 ProjectItem * pvitem = static_cast<ProjectItem*>( selectedItem() );
00243
00244 if ( pvitem && ( pvitem->type() == ProjectItem::File ) )
00245 {
00246 FileItem * fitem = static_cast <FileItem*> ( selectedItem() );
00247 if(fitem && fitem->is_subst)
00248 {
00249 fitem->changeMakefileEntry("");
00250 return;
00251 }
00252
00253 QListViewItem* sibling = fitem->nextSibling();
00254
00255 if ( !fitem )
00256 return;
00257
00258 TargetItem *titem = static_cast<TargetItem*>( fitem->parent() );
00259
00260 RemoveFileDialog dlg( m_widget, m_part, m_widget->selectedSubproject(), titem, fitem->text( 0 ),
00261 this, "remove file dialog" );
00262
00263 QString caption;
00264 if ( titem->name.isEmpty() )
00265 caption = i18n ( "%1 in %2" ).arg ( titem->primary ).arg ( titem->prefix );
00266 else
00267 caption = titem->name;
00268
00269 dlg.setCaption ( i18n ( "Remove File From '%1'" ).arg ( caption ) );
00270
00271 if ( dlg.exec() )
00272 {
00273 emit selectionChanged( titem );
00274
00275 if ( sibling)
00276 {
00277 setSelected ( sibling, true );
00278 ensureItemVisible ( sibling );
00279 }
00280 }
00281
00282 return;
00283 }
00284
00285 if ( pvitem && ( pvitem->type() == ProjectItem::Target ) )
00286 {
00287 TargetItem* titem = static_cast <TargetItem*> ( selectedItem() );
00288 QListViewItem* sibling = titem->nextSibling();
00289
00290 if ( !titem ) return;
00291
00292 RemoveTargetDialog dlg ( m_widget, m_part, m_widget->selectedSubproject(), titem, this, "remove target dialog" );
00293
00294 dlg.setCaption ( i18n ( "Remove Target From '%1'" ).arg ( m_widget->selectedSubproject()->subdir ) );
00295
00296 if ( dlg.exec() )
00297 {
00298
00299
00300 m_widget->slotOverviewSelectionChanged ( m_widget->selectedSubproject() );
00301
00302 if ( sibling)
00303 {
00304 setSelected ( sibling, true );
00305 ensureItemVisible ( sibling );
00306 }
00307 }
00308
00309 return;
00310 }
00311 }
00312
00313
00314 void AutoDetailsView::slotDetailsContextMenu( KListView *, QListViewItem *item, const QPoint &p )
00315 {
00316 if ( !item )
00317 return ;
00318
00319 ProjectItem *pvitem = static_cast<ProjectItem*>( item );
00320
00321 if ( pvitem->type() == ProjectItem::Target )
00322 {
00323
00324 TargetItem * titem = static_cast<TargetItem*>( pvitem );
00325
00326 KPopupMenu popup( i18n( "Target: %1" ).arg( titem->name ), this );
00327
00328 if ( titem->primary == "PROGRAMS" || titem->primary == "LIBRARIES"
00329 || titem->primary == "LTLIBRARIES" || titem->primary == "JAVA" )
00330 {
00331 targetOptionsAction->plug( &popup );
00332 popup.insertSeparator();
00333 addNewFileAction->plug( &popup );
00334 addExistingFileAction->plug( &popup );
00335 popup.insertSeparator();
00336 removeDetailAction->plug( &popup );
00337 popup.insertSeparator();
00338 setActiveTargetAction->plug( &popup );
00339 popup.insertSeparator();
00340 buildTargetAction->plug( &popup );
00341 if( titem->primary == "PROGRAMS")
00342 executeTargetAction->plug( &popup );
00343 }
00344 else if ( titem->primary == "KDEDOCS" )
00345 {
00346 addNewFileAction->plug( &popup );
00347 addExistingFileAction->plug( &popup );
00348 popup.insertSeparator();
00349 removeDetailAction->plug( &popup );
00350 popup.insertSeparator();
00351 buildTargetAction->plug( &popup );
00352 }
00353 else if ( titem->primary == "KDEICON" )
00354 {
00355 addIconAction->plug( &popup );
00356 popup.insertSeparator();
00357 removeDetailAction->plug( &popup );
00358 }
00359 else
00360 {
00361 addNewFileAction->plug( &popup );
00362 addExistingFileAction->plug( &popup );
00363 popup.insertSeparator();
00364 removeDetailAction->plug( &popup );
00365 }
00366
00367 popup.exec( p );
00368
00369 }
00370 else if ( pvitem->type() == ProjectItem::File )
00371 {
00372
00373 FileItem * fitem = static_cast<FileItem*>( pvitem );
00374
00375 KPopupMenu popup( i18n( "File: %1" ).arg( fitem->name ), this );
00376
00377 removeDetailAction->plug( &popup );
00378 FileContext context( m_widget->selectedSubproject()->path + "/" + fitem->name, false );
00379
00380 int idSubclassWidget = popup.insertItem(SmallIconSet("qmake_subclass"),i18n("Subclassing Wizard...") );
00381 popup.setWhatsThis(idSubclassWidget, i18n("<b>Subclass widget</b><p>Launches <b>Subclassing</b> wizard. "
00382 "It allows to create a subclass from the class defined in .ui file. "
00383 "There is also possibility to implement slots and functions defined in the base class."));
00384 int idUISubclasses = popup.insertItem(SmallIconSet("qmake_subclass"),i18n("List of Subclasses..."));
00385 popup.setWhatsThis(idUISubclasses, i18n("<b>List of subclasses</b><p>Shows subclasses list editor. "
00386 "There is possibility to add or remove subclasses from the list."));
00387 int idUpdateWidgetclass = popup.insertItem(SmallIconSet("qmake_subclass"),i18n("Edit ui-Subclass..."));
00388 popup.setWhatsThis(idUpdateWidgetclass, i18n("<b>Edit ui-subclass</b><p>Launches <b>Subclassing</b> wizard "
00389 "and prompts to implement missing in childclass slots and functions."));
00390 int idViewUIH = popup.insertItem(SmallIconSet("qmake_ui_h"),i18n("Open ui.h File"));
00391 popup.setWhatsThis(idViewUIH, i18n("<b>Open ui.h file</b><p>Opens .ui.h file associated with the selected .ui."));
00392
00393 if (!fitem->name.contains(QRegExp("ui$")) || fitem->is_subst == true)
00394 {
00395 popup.removeItem(idUISubclasses);
00396 popup.removeItem(idViewUIH);
00397 popup.removeItem(idSubclassWidget);
00398 }
00399 if (fitem->uiFileLink.isEmpty())
00400 {
00401 popup.removeItem(idUpdateWidgetclass);
00402 }
00403
00404 if(fitem->is_subst == false)
00405 m_part->core()->fillContextMenu( &popup, &context );
00406
00407 int r = popup.exec( p );
00408
00409 if(r == idViewUIH)
00410 {
00411 m_part->partController()->editDocument(KURL(m_widget->selectedSubproject()->path + "/" +
00412 QString(fitem->name + ".h")));
00413 }
00414 else if (r == idSubclassWidget)
00415 {
00416 QStringList newFileNames;
00417 newFileNames = m_part->languageSupport()->subclassWidget(m_widget->selectedSubproject()->path + "/" + fitem->name);
00418 if (!newFileNames.empty())
00419 {
00420 QDomDocument &dom = *(m_part->projectDom());
00421 for (uint i=0; i<newFileNames.count(); i++)
00422 {
00423 QString srcfile_relpath = newFileNames[i];
00424 srcfile_relpath.remove(0,m_part->projectDirectory().length());
00425 QString uifile_relpath = QString(m_widget->selectedSubproject()->path + "/" + fitem->name).remove(0,m_part->projectDirectory().length());
00426 DomUtil::PairList list = DomUtil::readPairListEntry(dom,"/kdevautoproject/subclassing" ,
00427 "subclass","sourcefile", "uifile");
00428
00429 list << DomUtil::Pair(srcfile_relpath,uifile_relpath);
00430 DomUtil::writePairListEntry(dom, "/kdevautoproject/subclassing", "subclass", "sourcefile", "uifile", list);
00431 newFileNames[i] = newFileNames[i].replace(QRegExp(m_part->projectDirectory()+"/"),"");
00432 }
00433 m_subclasslist = DomUtil::readPairListEntry(dom,"/kdevautoproject/subclassing" ,
00434 "subclass","sourcefile", "uifile");
00435 m_part->addFiles(newFileNames);
00436 }
00437 }
00438 else if (r == idUpdateWidgetclass)
00439 {
00440 QString noext = m_widget->selectedSubproject()->path + "/" + fitem->name;
00441
00442 if (noext.findRev('.')>-1)
00443 noext = noext.left(noext.findRev('.'));
00444
00445 QStringList dummy;
00446 QString uifile = fitem->uiFileLink;
00447
00448 if (uifile.findRev('/')>-1)
00449 {
00450 QStringList uisplit = QStringList::split('/',uifile);
00451 uifile=uisplit[uisplit.count()-1];
00452 }
00453
00454 m_part->languageSupport()->updateWidget(m_widget->selectedSubproject()->path + "/" + uifile, noext);
00455 }
00456 else if (r == idUISubclasses)
00457 {
00458 QDomDocument &dom = *(m_part->projectDom());
00459 DomUtil::PairList list = DomUtil::readPairListEntry(dom,"/kdevautoproject/subclassing" ,
00460 "subclass","sourcefile", "uifile");
00461 SubclassesDlg *sbdlg = new SubclassesDlg( QString(m_widget->selectedSubproject()->path + "/" + fitem->name).remove(0,m_part->projectDirectory().length()),
00462 list, m_part->projectDirectory());
00463
00464 if (sbdlg->exec())
00465 {
00466 QDomElement el = DomUtil::elementByPath( dom, "/kdevautoproject");
00467 QDomElement el2 = DomUtil::elementByPath( dom, "/kdevautoproject/subclassing");
00468 if ( (!el.isNull()) && (!el2.isNull()) )
00469 {
00470 el.removeChild(el2);
00471 }
00472
00473 DomUtil::writePairListEntry(dom, "/kdevautoproject/subclassing", "subclass", "sourcefile", "uifile", list);
00474
00475 m_subclasslist = DomUtil::readPairListEntry(dom,"/kdevautoproject/subclassing" ,
00476 "subclass","sourcefile", "uifile");
00477 }
00478 }
00479 }
00480 }
00481
00482
00483 void AutoDetailsView::slotDetailsExecuted( QListViewItem *item )
00484 {
00485 if ( !item )
00486 return ;
00487
00488 ProjectItem *pvitem = static_cast<ProjectItem*>( item );
00489 if ( pvitem->type() != ProjectItem::File )
00490 return ;
00491
00492 if ( !m_widget->selectedSubproject() )
00493 return;
00494
00495 QString dirName = m_widget->selectedSubproject()->path;
00496 FileItem *fitem = static_cast<FileItem*>( item );
00497 if(fitem->is_subst)
00498 {
00499 fitem->changeSubstitution();
00500 return;
00501 }
00502
00503 m_part->partController()->editDocument( KURL( dirName + "/" + fitem->name ) );
00504 }
00505
00506 void AutoDetailsView::slotSetActiveTarget()
00507 {
00508 TargetItem * titem = static_cast<TargetItem*>( selectedItem() );
00509 if ( !titem ) return ;
00510
00511 QString targetPath = m_widget->selectedSubproject()->path + "/" + titem->name;
00512 targetPath = targetPath.mid( m_part->projectDirectory().length() + 1 );
00513 kdDebug( 9020 ) << "Setting active " << targetPath << endl;
00514 m_widget->setActiveTarget( targetPath );
00515 QDomDocument &dom = *m_part->projectDom();
00516 DomUtil::writeEntry( dom, "/kdevautoproject/general/activetarget", targetPath );
00517 }
00518
00519 void AutoDetailsView::focusOutEvent(QFocusEvent *)
00520 {
00521 m_widget->setLastFocusedView(AutoProjectWidget::DetailsView);
00522 }
00523
00524 #include "autodetailsview.moc"