/*************************************************************************** * Copyright (C) 1999-2001 by Bernd Gehrmann * * bernd@tdevelop.org * * Extended 2002 by Harald Fernengel * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "perforcepart.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "kdevpartcontroller.h" #include "kdevcore.h" #include "kdevmakefrontend.h" #include "kdevdifffrontend.h" #include "kdevplugininfo.h" #include "commitdlg.h" #include "execcommand.h" static const KDevPluginInfo data("kdevperforce"); typedef KDevGenericFactory PerforceFactory; K_EXPORT_COMPONENT_FACTORY( libkdevperforce, PerforceFactory( data ) ) PerforcePart::PerforcePart( TQObject *parent, const char *name, const TQStringList & ) : KDevVersionControl( &data, parent, name ? name : "PerforcePart" ) { setInstance(PerforceFactory::instance()); setupActions(); connect( core(), TQT_SIGNAL(contextMenu(TQPopupMenu *, const Context *)), this, TQT_SLOT(contextMenu(TQPopupMenu *, const Context *)) ); } PerforcePart::~PerforcePart() {} void PerforcePart::setupActions() { actionEdit = new KAction( i18n("Edit"), 0, this, TQT_SLOT(slotActionEdit()), actionCollection(), "perforce_edit" ); actionEdit->setToolTip(i18n("Edit")); actionEdit->setWhatsThis(i18n("Edit

Opens file(s) in a client workspace for edit.")); actionRevert = new KAction( i18n("Revert"), 0, this, TQT_SLOT(slotActionRevert()), actionCollection(), "perforce_revert" ); actionRevert->setToolTip(i18n("Revert")); actionRevert->setWhatsThis(i18n("Revert

Discards changes made to open files.")); actionSubmit = new KAction( i18n("Submit"), 0, this, TQT_SLOT(slotActionCommit()), actionCollection(), "perforce_submit" ); actionSubmit->setToolTip(i18n("Submit")); actionSubmit->setWhatsThis(i18n("Submit

Sends changes made to open files to the depot.")); actionSync = new KAction( i18n("Sync"), 0, this, TQT_SLOT(slotActionUpdate()), actionCollection(), "perforce_sync" ); actionSync->setToolTip(i18n("Sync")); actionSync->setWhatsThis(i18n("Sync

Copies files from the depot into the workspace.")); actionDiff = new KAction( i18n("Diff Against Repository"), 0, this, TQT_SLOT(slotActionDiff()), actionCollection(), "perforce_diff" ); actionDiff->setToolTip(i18n("Diff against repository")); actionDiff->setWhatsThis(i18n("Diff against repository

Compares a client workspace file to a revision in the depot.")); actionAdd = new KAction( i18n("Add to Repository"), 0, this, TQT_SLOT(slotActionAdd()), actionCollection(), "perforce_add" ); actionAdd->setToolTip(i18n("Add to repository")); actionAdd->setWhatsThis(i18n("Add to repository

Open file(s) in a client workspace for addition to the depot.")); actionRemove = new KAction( i18n("Remove From Repository"), 0, this, TQT_SLOT(slotActionRemove()), actionCollection(), "perforce_remove" ); actionRemove->setToolTip(i18n("Remove from repository")); actionRemove->setWhatsThis(i18n("Remove from repository

Open file(s) in a client workspace for deletion from the depot.")); } void PerforcePart::contextMenu(TQPopupMenu *popup, const Context *context) { if (context->hasType( Context::FileContext )) { const FileContext *fcontext = static_cast(context); popupfile = fcontext->urls().first().path(); TQFileInfo fi( popupfile ); popup->insertSeparator(); KPopupMenu *sub = new KPopupMenu(popup); TQString name = fi.fileName(); sub->insertTitle( i18n("Actions for %1").tqarg(name) ); int id = sub->insertItem( i18n("Edit"), this, TQT_SLOT(slotEdit()) ); sub->tqsetWhatsThis(id, i18n("Edit

Opens file(s) in a client workspace for edit.")); id = sub->insertItem( i18n("Revert"), this, TQT_SLOT(slotRevert()) ); sub->tqsetWhatsThis(id, i18n("Revert

Discards changes made to open files.")); id = sub->insertItem( i18n("Submit"), this, TQT_SLOT(slotCommit()) ); sub->tqsetWhatsThis(id, i18n("Submit

Sends changes made to open files to the depot.")); id = sub->insertItem( i18n("Sync"), this, TQT_SLOT(slotUpdate()) ); sub->tqsetWhatsThis(id, i18n("Sync

Copies files from the depot into the workspace.")); sub->insertSeparator(); id = sub->insertItem( i18n("Diff Against Repository"), this, TQT_SLOT(slotDiff()) ); sub->tqsetWhatsThis(id, i18n("Diff against repository

Compares a client workspace file to a revision in the depot.")); id = sub->insertItem( i18n("Add to Repository"), this, TQT_SLOT(slotAdd()) ); sub->tqsetWhatsThis(id, i18n("Add to repository

Open file(s) in a client workspace for addition to the depot.")); id = sub->insertItem( i18n("Remove From Repository"), this, TQT_SLOT(slotRemove()) ); sub->tqsetWhatsThis(id, i18n("Remove from repository

Open file(s) in a client workspace for deletion from the depot.")); id = popup->insertItem(i18n("Perforce"), sub); } } void PerforcePart::execCommand( const TQString& cmd, const TQString& filename ) { if ( filename.isEmpty() ) return; TQFileInfo fi( filename ); if (fi.isDir()) { KMessageBox::error( 0, i18n("Cannot handle directories, please select single files") ); return; } TQString dir = fi.dirPath(); TQString name = fi.fileName(); TQString command("cd "); command += KProcess::quote(dir); command += " && p4 " + cmd + " "; command += name; if (KDevMakeFrontend *makeFrontend = extension("KDevelop/MakeFrontend")) makeFrontend->queueCommand(dir, command); } void PerforcePart::edit( const TQString& filename ) { execCommand( "edit", filename ); } void PerforcePart::revert( const TQString& filename ) { if ( KMessageBox::questionYesNo( 0, i18n("Do you really want to revert " "the file %1 and lose all your changes?").tqarg( filename ), TQString(), i18n("Revert"), i18n("Do Not Revert") ) == KMessageBox::Yes ) { execCommand( "revert", filename ); } } void PerforcePart::commit( const TQString& filename ) { if ( filename.isEmpty() ) return; TQFileInfo fi( filename ); if ( fi.isDir() ) { KMessageBox::error( 0, i18n("Submitting of subdirectories is not supported") ); return; } CommitDialog d; TQStringList lst; lst << filename; d.setFiles( lst ); if (d.exec() == TQDialog::Rejected) return; TQString message = d.changeList(); if (!message.isEmpty()) message = KShellProcess::quote(message); TQString command("echo " + message); command += " | p4 submit -i"; if (KDevMakeFrontend *makeFrontend = extension("KDevelop/MakeFrontend")) makeFrontend->queueCommand("", command); } void PerforcePart::update( const TQString& filename ) { if ( filename.isEmpty() ) return; TQString dir, name; TQFileInfo fi( filename ); if (fi.isDir()) { dir = fi.absFilePath(); name = "..."; // three dots means "recoursive" } else { dir = fi.dirPath(); name = fi.fileName(); } TQString command("cd "); command += KProcess::quote(dir); command += " && p4 sync "; command += name; if (KDevMakeFrontend *makeFrontend = extension("KDevelop/MakeFrontend")) makeFrontend->queueCommand(dir, command); } void PerforcePart::add( const TQString& filename ) { execCommand( "add", filename ); } void PerforcePart::remove( const TQString& filename ) { execCommand( "delete", filename ); } void PerforcePart::diff( const TQString& filename ) { if ( filename.isEmpty() ) return; TQString name; TQFileInfo fi( filename ); if ( fi.isDir() ) { name = fi.absFilePath() + "..."; } else { name = filename; } TQStringList args; args << "diff"; args << "-du"; args << name; ExecCommand* cmv = new ExecCommand( "p4", args, TQString(), TQStringList(), this ); connect( cmv, TQT_SIGNAL(finished( const TQString&, const TQString& )), this, TQT_SLOT(slotDiffFinished( const TQString&, const TQString& )) ); } void PerforcePart::slotDiffFinished( const TQString& diff, const TQString& err ) { if ( diff.isNull() && err.isNull() ) { kdDebug(9000) << "p4 diff cancelled" << endl; return; // user pressed cancel or an error occured } if ( diff.isEmpty() && !err.isEmpty() ) { KMessageBox::detailedError( 0, i18n("P4 output errors during diff."), err, i18n("Errors During Diff") ); return; } if ( !err.isEmpty() ) { int s = KMessageBox::warningContinueCancelList( 0, i18n("P4 output errors during diff. Do you still want to continue?"), TQStringList::split( "\n", err, false ), i18n("Errors During Diff") ); if ( s != KMessageBox::Continue ) return; } if ( diff.isEmpty() ) { KMessageBox::information( 0, i18n("There is no difference to the repository."), i18n("No Differences Found") ); return; } // strip the ==== headers static TQRegExp rx( "(^|\\n)==== ([^ ]+) -.*====\\n" ); rx.setMinimal( true ); TQString strippedDiff = diff; strippedDiff.replace( rx, "--- \\2\n+++ \\2\n" ); if (KDevDiffFrontend *diffFrontend = extension("KDevelop/DiffFrontend")) diffFrontend->showDiff( strippedDiff ); } TQString PerforcePart::currentFile() { KParts::ReadOnlyPart *part = dynamic_cast( partController()->activePart() ); if ( part ) { KURL url = part->url(); if ( url.isLocalFile() ) return url.path(); } return TQString(); } void PerforcePart::slotActionCommit() { commit( currentFile() ); } void PerforcePart::slotActionUpdate() { update( currentFile() ); } void PerforcePart::slotActionAdd() { add( currentFile() ); } void PerforcePart::slotActionRemove() { remove( currentFile() ); } void PerforcePart::slotActionEdit() { edit( currentFile() ); } void PerforcePart::slotActionRevert() { revert( currentFile() ); } void PerforcePart::slotActionDiff() { diff( currentFile() ); } void PerforcePart::slotCommit() { commit( popupfile ); } void PerforcePart::slotUpdate() { update( popupfile ); } void PerforcePart::slotAdd() { add( popupfile ); } void PerforcePart::slotRemove() { remove( popupfile ); } void PerforcePart::slotEdit() { edit( popupfile ); } void PerforcePart::slotRevert() { revert( popupfile ); } void PerforcePart::slotDiff() { diff( popupfile ); } #include "perforcepart.moc"