KDevelop API Documentation

perforcepart.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 1999-2001 by Bernd Gehrmann                             *
00003  *   bernd@kdevelop.org                                                    *
00004  *   Extended 2002 by Harald Fernengel <harry@kdevelop.org>                *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU General Public License as published by  *
00008  *   the Free Software Foundation; either version 2 of the License, or     *
00009  *   (at your option) any later version.                                   *
00010  *                                                                         *
00011  ***************************************************************************/
00012 
00013 #include "perforcepart.h"
00014 
00015 #include <qfileinfo.h>
00016 #include <qpopupmenu.h>
00017 #include <qregexp.h>
00018 #include <kpopupmenu.h>
00019 #include <kdebug.h>
00020 #include <kdevgenericfactory.h>
00021 #include <klocale.h>
00022 #include <kprocess.h>
00023 #include <kmessagebox.h>
00024 #include <kapplication.h>
00025 #include <kaction.h>
00026 #include <kurl.h>
00027 #include <kparts/part.h>
00028 
00029 #include "kdevpartcontroller.h"
00030 #include "kdevcore.h"
00031 #include "kdevmakefrontend.h"
00032 #include "kdevdifffrontend.h"
00033 #include "commitdlg.h"
00034 #include "execcommand.h"
00035 
00036 static const KAboutData data("kdevperforce", I18N_NOOP("Perforce"), "1.0");
00037 
00038 typedef KDevGenericFactory<PerforcePart> PerforceFactory;
00039 K_EXPORT_COMPONENT_FACTORY( libkdevperforce, PerforceFactory( &data ) )
00040 
00041 PerforcePart::PerforcePart( QObject *parent, const char *name, const QStringList & )
00042     : KDevPlugin( "Perforce", "perforce", parent, name ? name : "PerforcePart" )
00043 {
00044     setInstance(PerforceFactory::instance());
00045     setupActions();
00046 
00047     connect( core(), SIGNAL(contextMenu(QPopupMenu *, const Context *)),
00048              this, SLOT(contextMenu(QPopupMenu *, const Context *)) );
00049 }
00050 
00051 
00052 PerforcePart::~PerforcePart()
00053 {}
00054 
00055 void PerforcePart::setupActions()
00056 {
00057     actionEdit = new KAction( i18n("Edit"), 0, this, SLOT(slotActionEdit()),
00058                 actionCollection(), "perforce_edit" );
00059     actionEdit->setToolTip(i18n("Edit"));
00060     actionEdit->setWhatsThis(i18n("<b>Edit</b><p>Opens file(s) in a client workspace for edit."));
00061     actionRevert = new KAction( i18n("Revert"), 0, this, SLOT(slotActionRevert()),
00062                 actionCollection(), "perforce_revert" );
00063     actionRevert->setToolTip(i18n("Revert"));
00064     actionRevert->setWhatsThis(i18n("<b>Revert</b><p>Discards changes made to open files."));
00065     actionSubmit = new KAction( i18n("Submit"), 0, this, SLOT(slotActionCommit()),
00066                 actionCollection(), "perforce_submit" );
00067     actionSubmit->setToolTip(i18n("Submit"));
00068     actionSubmit->setWhatsThis(i18n("<b>Submit</b><p>Sends changes made to open files to the depot."));
00069     actionSync = new KAction( i18n("Sync"), 0, this, SLOT(slotActionUpdate()),
00070                 actionCollection(), "perforce_sync" );
00071     actionSync->setToolTip(i18n("Sync"));
00072     actionSync->setWhatsThis(i18n("<b>Sync</b><p>Copies files from the depot into the workspace."));
00073     actionDiff = new KAction( i18n("Diff Against Repository"), 0, this, SLOT(slotActionDiff()),
00074                 actionCollection(), "perforce_diff" );
00075     actionDiff->setToolTip(i18n("Diff against repository"));
00076     actionDiff->setWhatsThis(i18n("<b>Diff against repository</b><p>Compares a client workspace file to a revision in the depot."));
00077     actionAdd = new KAction( i18n("Add to Repository"), 0, this, SLOT(slotActionAdd()),
00078                 actionCollection(), "perforce_add" );
00079     actionAdd->setToolTip(i18n("Add to repository"));
00080     actionAdd->setWhatsThis(i18n("<b>Add to repository</b><p>Open file(s) in a client workspace for addition to the depot."));
00081     actionRemove = new KAction( i18n("Remove From Repository"), 0, this, SLOT(slotActionRemove()),
00082                 actionCollection(), "perforce_remove" );
00083     actionRemove->setToolTip(i18n("Remove from repository"));
00084     actionRemove->setWhatsThis(i18n("<b>Remove from repository</b><p>Open file(s) in a client workspace for deletion from the depot."));
00085 }
00086 
00087 void PerforcePart::contextMenu(QPopupMenu *popup, const Context *context)
00088 {
00089     if (context->hasType( Context::FileContext )) {
00090         const FileContext *fcontext = static_cast<const FileContext*>(context);
00091         popupfile = fcontext->fileName();
00092         QFileInfo fi( popupfile );
00093         popup->insertSeparator();
00094 
00095         KPopupMenu *sub = new KPopupMenu(popup);
00096         QString name = fi.fileName();
00097         sub->insertTitle( i18n("Actions for %1").arg(name) );
00098 
00099         int id = sub->insertItem( i18n("Edit"),
00100                            this, SLOT(slotEdit()) );
00101         sub->setWhatsThis(id, i18n("<b>Edit</b><p>Opens file(s) in a client workspace for edit."));
00102         id = sub->insertItem( i18n("Revert"),
00103                            this, SLOT(slotRevert()) );
00104         sub->setWhatsThis(id, i18n("<b>Revert</b><p>Discards changes made to open files."));
00105         id = sub->insertItem( i18n("Submit"),
00106                            this, SLOT(slotCommit()) );
00107         sub->setWhatsThis(id, i18n("<b>Submit</b><p>Sends changes made to open files to the depot."));
00108         id = sub->insertItem( i18n("Sync"),
00109                            this, SLOT(slotUpdate()) );
00110         sub->setWhatsThis(id, i18n("<b>Sync</b><p>Copies files from the depot into the workspace."));
00111         sub->insertSeparator();
00112         id = sub->insertItem( i18n("Diff Against Repository"),
00113                           this, SLOT(slotDiff()) );
00114         sub->setWhatsThis(id, i18n("<b>Diff against repository</b><p>Compares a client workspace file to a revision in the depot."));
00115         id = sub->insertItem( i18n("Add to Repository"),
00116                            this, SLOT(slotAdd()) );
00117         sub->setWhatsThis(id, i18n("<b>Add to repository</b><p>Open file(s) in a client workspace for addition to the depot."));
00118         id = sub->insertItem( i18n("Remove From Repository"),
00119                            this, SLOT(slotRemove()) );
00120         sub->setWhatsThis(id, i18n("<b>Remove from repository</b><p>Open file(s) in a client workspace for deletion from the depot."));
00121         id = popup->insertItem(i18n("Perforce"), sub);
00122     }
00123 }
00124 
00125 void PerforcePart::execCommand( const QString& cmd, const QString& filename )
00126 {
00127     if ( filename.isEmpty() )
00128         return;
00129 
00130     QFileInfo fi( filename );
00131     if (fi.isDir()) {
00132         KMessageBox::error( 0, i18n("Cannot handle directories, please select single files") );
00133         return;
00134     }
00135     QString dir = fi.dirPath();
00136     QString name = fi.fileName();
00137 
00138     QString command("cd ");
00139     command += KProcess::quote(dir);
00140     command += " && p4 " + cmd + " ";
00141     command += name;
00142 
00143     makeFrontend()->queueCommand(dir, command);
00144 }
00145 
00146 void PerforcePart::edit( const QString& filename )
00147 {
00148     execCommand( "edit", filename );
00149 }
00150 
00151 void PerforcePart::revert( const QString& filename )
00152 {
00153     if ( KMessageBox::questionYesNo( 0,
00154             i18n("Do you really want to revert "
00155                  "the file %1 and lose all your changes?").arg( filename ) ) == KMessageBox::Yes ) {
00156         execCommand( "revert", filename );
00157     }
00158 }
00159 
00160 void PerforcePart::commit( const QString& filename )
00161 {
00162     if ( filename.isEmpty() )
00163         return;
00164 
00165     QFileInfo fi( filename );
00166     if ( fi.isDir() ) {
00167         KMessageBox::error( 0, i18n("Submitting of subdirectories is not supported") );
00168         return;
00169     }
00170 
00171     CommitDialog d;
00172     QStringList lst;
00173     lst << filename;
00174     d.setFiles( lst );
00175     if (d.exec() == QDialog::Rejected)
00176         return;
00177 
00178     QString message = d.changeList();
00179     if (!message.isEmpty())
00180      message = KShellProcess::quote(message);
00181 
00182     QString command("echo " + message);
00183     command += " | p4 submit -i";
00184 
00185     makeFrontend()->queueCommand("", command);
00186 }
00187 
00188 
00189 void PerforcePart::update( const QString& filename )
00190 {
00191     if ( filename.isEmpty() )
00192         return;
00193 
00194     QString dir, name;
00195     QFileInfo fi( filename );
00196     if (fi.isDir()) {
00197         dir = fi.absFilePath();
00198         name = "..."; // three dots means "recoursive"
00199     } else {
00200         dir = fi.dirPath();
00201         name = fi.fileName();
00202     }
00203 
00204     QString command("cd ");
00205     command += KProcess::quote(dir);
00206     command += " && p4 sync ";
00207     command += name;
00208 
00209     makeFrontend()->queueCommand(dir, command);
00210 }
00211 
00212 
00213 void PerforcePart::add( const QString& filename )
00214 {
00215     execCommand( "add", filename );
00216 }
00217 
00218 
00219 void PerforcePart::remove( const QString& filename )
00220 {
00221     execCommand( "delete", filename );
00222 }
00223 
00224 void PerforcePart::diff( const QString& filename )
00225 {
00226     if ( filename.isEmpty() )
00227         return;
00228 
00229     QString name;
00230     QFileInfo fi( filename );
00231 
00232     if ( fi.isDir() ) {
00233     name = fi.absFilePath() + "...";
00234     } else {
00235     name = filename;
00236     }
00237     QStringList args;
00238 
00239     args << "diff";
00240     args << name;
00241     ExecCommand* cmv = new ExecCommand( "p4", args, QString::null, QStringList(), this );
00242     connect( cmv, SIGNAL(finished( const QString&, const QString& )),
00243              this, SLOT(slotDiffFinished( const QString&, const QString& )) );
00244 }
00245 
00246 void PerforcePart::slotDiffFinished( const QString& diff, const QString& err )
00247 {
00248     if ( diff.isNull() && err.isNull() ) {
00249         kdDebug(9000) << "p4 diff cancelled" << endl;
00250         return; // user pressed cancel or an error occured
00251     }
00252 
00253     if ( diff.isEmpty() && !err.isEmpty() ) {
00254         KMessageBox::detailedError( 0, i18n("P4 outputted errors during diff."), err, i18n("Errors During Diff") );
00255         return;
00256     }
00257 
00258     if ( !err.isEmpty() ) {
00259         int s = KMessageBox::warningContinueCancelList( 0, i18n("P4 outputted errors during diff. Do you still want to continue?"),
00260                         QStringList::split( "\n", err, false ), i18n("Errors During Diff") );
00261         if ( s != KMessageBox::Continue )
00262             return;
00263     }
00264 
00265     if ( diff.isEmpty() ) {
00266         KMessageBox::information( 0, i18n("There is no difference to the repository."), i18n("No Differences Found") );
00267         return;
00268     }
00269 
00270     // strip the ==== headers
00271     static QRegExp rx( "(^|\\n)====.*====\\n" );
00272     rx.setMinimal( true );
00273     QString strippedDiff = diff;
00274     strippedDiff.replace( rx, QString::null );
00275 
00276     Q_ASSERT( diffFrontend() );
00277     diffFrontend()->showDiff( strippedDiff );
00278 }
00279 
00280 QString PerforcePart::currentFile()
00281 {
00282     KParts::ReadOnlyPart *part = dynamic_cast<KParts::ReadOnlyPart*>( partController()->activePart() );
00283     if ( part ) {
00284         KURL url = part->url();
00285         if ( url.isLocalFile() )
00286             return url.path();
00287     }
00288     return QString::null;
00289 }
00290 
00291 void PerforcePart::slotActionCommit()
00292 {
00293     commit( currentFile() );
00294 }
00295 
00296 void PerforcePart::slotActionUpdate()
00297 {
00298     update( currentFile() );
00299 }
00300 void PerforcePart::slotActionAdd()
00301 {
00302     add( currentFile() );
00303 }
00304 
00305 void PerforcePart::slotActionRemove()
00306 {
00307     remove( currentFile() );
00308 }
00309 
00310 void PerforcePart::slotActionEdit()
00311 {
00312     edit( currentFile() );
00313 }
00314 
00315 void PerforcePart::slotActionRevert()
00316 {
00317     revert( currentFile() );
00318 }
00319 
00320 void PerforcePart::slotActionDiff()
00321 {
00322     diff( currentFile() );
00323 }
00324 
00325 void PerforcePart::slotCommit()
00326 {
00327     commit( popupfile );
00328 }
00329 
00330 void PerforcePart::slotUpdate()
00331 {
00332     update( popupfile );
00333 }
00334 
00335 void PerforcePart::slotAdd()
00336 {
00337     add( popupfile );
00338 }
00339 
00340 void PerforcePart::slotRemove()
00341 {
00342     remove( popupfile );
00343 }
00344 
00345 void PerforcePart::slotEdit()
00346 {
00347     edit( popupfile );
00348 }
00349 
00350 void PerforcePart::slotRevert()
00351 {
00352     revert( popupfile );
00353 }
00354 
00355 void PerforcePart::slotDiff()
00356 {
00357     diff( popupfile );
00358 }
00359 
00360 #include "perforcepart.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Feb 22 09:22:43 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003