// // Copyright 1501 Perforce Software. All rights reserved. // // This file is part of Perforce - the FAST SCM System. // // p4wDescribePane: // Generates output of a p4 describe command #include <p4wp4.h> #include "p4wStrBuf.h" #include "p4wHtml.h" #include "p4wPane.h" #include "p4wDescribePane.h" #include "p4wMenuPane.h" p4wDescribePane::p4wDescribePane( p4wView & ParentView, p4wRequest & Request ) : p4wPane( ParentView, Request ), fState( gettingChange ), fSeenFixes( 0 ), fPending( 0 ) { } p4wDescribePane::~p4wDescribePane() { } // ------------------------------------- // Render functions. // void p4wDescribePane::Begin() { // // Begin the pane. if( fState != gettingChange ) return; p4wHtml htm; p4wURL urlMaker; StrBuf grayIcon; StrBuf clearIcon; // // Used to generate line & vertical white space urlMaker.ConstructURL( grayIcon, "/grayPixelIcon", AC_ICON, NULL ); urlMaker.ConstructURL( clearIcon, "/clearpixelIcon", AC_ICON, NULL ); htm.comment( "BEGIN DESCRIBE PANE" ); if (fRequest.GetScreenChunks() & SCRN_TITLE) { // // Generate title with line underneath htm.beginTRow(); htm.beginCol(); htm.beginSpan( "title" ); htm << "Changelist:"; htm.endSpan(); htm.endCol(); htm.endTRow(); htm.beginTRow(); htm.beginCol( "top" ); htm.icon( clearIcon.Text(), "2", "100%", "", 1, "0", "0" ); htm.icon( grayIcon.Text(), "1", "100%", "", 1, "0", "0" ); htm.endCol(); htm.endTRow(); // // Some vertical white space htm.beginTRow(); htm.beginCol(); htm.icon( clearIcon.Text(), "15", "0", "", 1 ); htm.endCol(); htm.endTRow(); } htm.beginTRow(); htm.beginCol(); htm.beginTable( "0" ); fRequest << htm; } void p4wDescribePane::Render( StrDict * varList ) { // // Generate either the describe or fixes output // based on the state switch(fState) { case gettingChange: doChange( varList ); break; case gettingFixes: doFixes( varList ); break; case addingFixes: doAddFix( varList ); break; default: break; } } void p4wDescribePane::doChange( StrDict * varList ) { // // Display the output of the describe command StrPtr *val; StrPtr *action; StrPtr *rev; StrBuf url, url2; StrBuf newBase; StrBuf clearIcon; const StrPtr *change = varList->GetVar( "change" ); const StrPtr *user = varList->GetVar( "user" ); const StrPtr *status = varList->GetVar( "status" ); const StrPtr *desc = varList->GetVar( "desc" ); fChange << change; fUser << user; p4wHtml htm( 1 ); htm.SetRequest(&fRequest); htm.beginTRow(); htm.beginCol(); fRequest << htm; htm.Clear(); p4wMenuPane::renderSubChgMenu( &fRequest, fUser.Text() ); if (*status == "pending" && !fRequest.GetBrowseMode()) { StrBuf location; if( fRequest.GetJavascriptMode() == 2 ) location << p4wStrBuf().NormalizeBase( fRequest.GetBase(), 0 ); else location << p4wStrBuf().NormalizeBase( fRequest.GetBase(), fRequest.GetUnicode() ); location << "?ac=" << AC_CHANGEPENDINGEDIT << "&arg=" << change; htm << crlf << "<script language=javascript>" << crlf; htm << "window.location = '" << location << "'" << crlf; htm << "</script>"; fPending = 1; } htm.text( "Changelist:", "b" ); htm.endCol(); htm.beginCol(); htm.text( p4wStrBuf().Expand( StrRef( "%change%" ), *varList, Unicode() ).Text() ); htm.endCol(); htm.endTRow(); if ( !strcmp( status->Text(), "pending" ) ) { htm.beginTRow(); htm.beginCol(); htm.text( "Status:", "b" ); htm.endCol(); htm.beginCol(); if( !fRequest.GetBrowseMode() ) { fRequest.UseNewBase( newBase, NULL, "path", NULL ); p4wURL urlMaker; StrBuf changeURL; StrBufDict cmdArgs; cmdArgs.SetVar( "arg", change ); urlMaker.ConstructURL( changeURL, newBase.Text(), AC_CHANGEPENDINGEDIT, &cmdArgs, fRequest.GetUnicode() ); htm.beginLink( changeURL.Text() ); } htm.text( p4wStrBuf().Expand( StrRef( "%status%" ), *varList, Unicode() ).Text() ); if( !fRequest.GetBrowseMode() ) htm.endLink(); htm.endCol(); htm.endTRow(); } htm.beginTRow(); htm.beginCol(); htm.text( "Date:", "b" ); htm.endCol(); htm.beginCol(); htm.text( p4wStrBuf().Expand( StrRef( "%time@*Y/*m/*d *H:*M%" ), *varList, Unicode() ).Text() ); htm.endCol(); htm.endTRow(); htm.beginTRow(); htm.beginCol(); htm.text( "Client:", "b" ); htm.endCol(); htm.beginCol(); htm.text( p4wStrBuf().Expand( StrRef( "%client%" ), *varList, Unicode() ).Text() ); htm.endCol(); htm.endTRow(); htm.beginTRow(); htm.beginCol(); htm.text( "User:", "b" ); htm.endCol(); htm.beginCol(); htm.text( p4wStrBuf().Expand( StrRef( "%user%" ), *varList, Unicode() ).Text() ); htm.endCol(); htm.endTRow(); htm.beginTRow(); htm.beginCol( "top" ); htm.text( "Description:", "b" ); htm.endCol(); htm.beginCol(); htm.beginUnformatted(); // // Convert http: & https: into real links in the // Description field htm.text( p4wStrBuf().EscapeHTMLDoURLs( *desc, Unicode() ).Text() ); htm.endUnformatted(); htm.endCol(); htm.endTRow(); htm.beginTRow(); htm.beginCol( "top", NULL, NULL, NULL, NULL, NULL, NULL, 1 ); htm.text( "Affected files:", "b" ); htm.endCol(); htm.beginCol( NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1 ); fRequest << htm; htm.Clear(); p4wURL urlMaker; urlMaker.ConstructURL( clearIcon, "/clearpixelIcon", AC_ICON, NULL ); for( int i = 0; ( val = varList->GetVar( StrRef( "depotFile" ), i ) ) != NULL; i++ ) { // // If page content limit in bytes has been exceeded, don't // generate this entry if( PageLimitExceeded() ) return; // Fetch some information about this file. action = varList->GetVar( StrRef( "action" ), i ); rev = varList->GetVar( StrRef( "rev" ), i ); // Prepare the file browser url if( fRequest.GetViewMode() != VM_WORKSPACE ) { fRequest.ConstructSafeURL( url, val->Text() + 2, AC_BROWSEFILE, NULL ); } else { fRequest.UseNewBase( newBase, NULL, "md", "d" ); fRequest.UseNewBase( newBase, newBase.Text(), "cd", "//" ); fRequest.UseNewBase( newBase, newBase.Text(), "wr", NULL ); fRequest.UseNewBase( newBase, newBase.Text(), "path", val->Text() ); urlMaker.ConstructURL( url, newBase.Text(), AC_BROWSEFILE, NULL, fRequest.GetUnicode() ); } int isWriteable; StrPtr *type = varList->GetVar( StrRef("type"), i ); if( type && ( strstr(type->Text(), "text") || strstr(type->Text(), "symlink") || strstr(type->Text(), "unicode") || strstr(type->Text(), "utf16") ) ) { isWriteable = 1; } else { isWriteable = 0; } int doDiff = 0; int revNo = atoi( rev->Text() ); int doText = ( isWriteable && ( strcmp( action->Text(), "delete" ) ) ); if( ( revNo > 1 ) && ( ( !strcmp( action->Text(), "edit" ) ) || ( !strcmp( action->Text(), "integrate" ) ) ) ) doDiff = 1; if( doText ) { StrBufDict tempArgs; tempArgs.SetVar( "rev1", varList->GetVar( StrRef("rev"), i )->Text() ); if( fRequest.GetViewMode() == VM_WORKSPACE ) { urlMaker.ConstructURL( url2, newBase.Text(), AC_FILETEXTDEPOT, &tempArgs, fRequest.GetUnicode() ); } else { fRequest.ConstructSafeURL( url2, val->Text() + 2, AC_FILETEXTDEPOT, &tempArgs ); } StrBuf textIcon; urlMaker.ConstructIcon( textIcon, "/showtextsmallIcon", 18, 25, "View file text", 1, "absmiddle" ); htm.beginLink( url2.Text(), NULL, NULL, NULL, "View file text" ); htm << textIcon; htm.endLink(); } else htm.icon( clearIcon.Text(), "18", "25", "", 1, 0, 0, "absmiddle" ); if (doDiff) { p4wStrBuf rev1; rev1 << ( revNo - 1 ); StrPtr * rev2 = varList->GetVar( StrRef("rev"), i ); StrBufDict args; args.SetVar( "rev1", rev1 ); args.SetVar( "rev2", rev2 ); if( fRequest.GetViewMode() == VM_WORKSPACE ) { urlMaker.ConstructURL( url2, newBase.Text(), AC_DIFF2, &args, fRequest.GetUnicode() ); } else { fRequest.ConstructSafeURL( url2, val->Text() + 2, AC_DIFF2, &args ); } StrBuf altText; StrBuf diffIcon; altText.Set( "Diff rev #" ); altText << rev1 << " vs. rev #" << rev2; urlMaker.ConstructIcon( diffIcon, "/rundiffprevsmallIcon", 18, 25, altText.Text(), 1, "absmiddle" ); htm.beginLink( url2.Text() ); htm << diffIcon; htm.endLink(); } else htm.icon( clearIcon.Text(), "18", "25", "", 1, 0, 0, "absmiddle" ); // Output this entry & url htm.beginLink( url.Text() ); htm.text( p4wStrBuf().EscapeHTML( *val, Unicode() ).Text() ); htm.endLink(); htm << "#" << rev << " " << action; htm.linebreak(); fRequest << htm; htm.Clear(); } htm.endCol(); htm.endTRow(); fRequest << htm; } void p4wDescribePane::doFixes( StrDict *varList ) { // // Display the output of the fixes -c changelist command StrBuf url; const StrPtr *job = varList->GetVar( "Job" ); const StrPtr *u = varList->GetVar( "User" ); const StrPtr *client = varList->GetVar( "Client" ); StrBuf user; fRequest.ConstructSafeURL( url, job->Text(), AC_JOBVIEW, NULL ); user << u << "@" << client; // // The first fix has the title as the first element // of the table. Subsequent fixes have a blank first // table element. p4wHtml htm; if( !fSeenFixes ) { ++fSeenFixes; htm.beginTRow(); htm.beginCol(); htm.text( "Fixes:", "b" ); htm.endCol(); } else { htm.beginTRow(); htm.beginCol(); htm.endCol(); } htm.beginCol(); StrBuf clearIcon; p4wURL urlMaker; urlMaker.ConstructURL( clearIcon, "/clearpixelIcon", AC_ICON, NULL ); htm.icon( clearIcon.Text(), "1", "50", "", 1 ); htm.beginLink( url.Text() ); htm.text( p4wStrBuf().Expand( StrRef( "%Job%" ), *varList, Unicode() ).Text() ); htm.endLink(); htm << " fixed by change "; htm << p4wStrBuf().Expand( StrRef( "%Change%" ), *varList, Unicode() ); htm << " on "; htm << p4wStrBuf().Expand( StrRef( "%Date@*m/*d/*Y *H:*M%" ), *varList, Unicode() ); htm << " by " << p4wStrBuf().EscapeHTML( user, Unicode() ); htm.endCol(); htm.endTRow(); fRequest << htm; } void p4wDescribePane::doAddFix( StrDict * varList ) { p4wHtml htm; StrBuf actionURL; fRequest.ConstructSafeURL( actionURL, fRequest.GetURL().Text(), AC_ADDFIXPROCESSOR, NULL ); htm.beginForm( actionURL.Text() ); StrBuf tag; tag << "Jobs:"; htm.beginTRow(); htm.beginCol( "top" ); htm.text( tag.Text(), "b" ); htm.endCol(); htm.beginCol(); htm.beginTextbox( "Jobs", 6, 40 ); const StrPtr *jb = fRequest.GetDynArg( "jb" ); if (jb && jb->Length()) htm.text( p4wStrBuf().EscapeHTML( *jb, Unicode() ).Text() ); htm.endTextbox(); htm.endCol(); htm.endTRow(); htm.beginTRow(); htm.beginCol(); htm.endCol(); tag.Clear(); tag << "JobStatus: "; htm.beginCol(); htm.text( tag.Text(), "b" ); htm.beginSelect( "JobStatus" ); StrPtr * val = varList->GetVar( StrRef( "Values" ), 0 ); char *selectVal = strtok( val->Text(), " " ); selectVal = "(default)"; while( selectVal != NULL ) { htm.selectOpt( 0 ); htm.text( selectVal ); selectVal = strtok( NULL, "/" ); } htm.endSelect(); htm.endCol(); htm.endTRow(); htm.beginTRow(); htm.beginCol(); htm.endCol(); htm.beginCol(); htm.button( "addfixes", "Add Jobs" ); htm.endCol(); htm.endTRow(); htm.endForm(); fRequest << htm; } void p4wDescribePane::End() { // // Handle state transitions p4wHtml htm; if( FatalError() && fState == gettingChange ) { htm.endTable(); htm.endCol(); htm.endTRow(); htm.comment( "END DESCRIBE PANE" ); fRequest << htm; return; } if( fState == gettingChange ) { fState = gettingFixes; return; } if( fState == gettingFixes && fRequest.GetCmd() == AC_ADDFIX) { fState = addingFixes; return; } // // End the pane. If we issued a fixes command but had // no fixes, we need to terminate the table row. if( !fSeenFixes ) htm.endTRow(); // // Add the Edit button if not browse-only // and this chglist belongs to the current user // and server supports editing chglists. if (!fRequest.GetBrowseMode() && !fPending && !strcmp(fUser.Text(), fRequest.GetUser().Text())) { const StrPtr *server; int protocol = 0; server = fRequest.GetProtocol( "server2" ); if( server ) protocol = server->Atoi(); if( protocol >= 23 ) // 2007.2 or later? { htm.beginTRow(); htm.beginCol( NULL, "center", "2" ); htm << "<script language=javascript>" << crlf; htm << "</script>" << crlf; htm << "<noscript>" << crlf; StrBuf actionURL; p4wURL url; StrBufDict args; args.SetVar( "arg", fChange.Text() ); StrBuf newBase; fRequest.UseNewBase( newBase, NULL, "path", NULL ); newBase << fChange.Text(); url.ConstructURL( actionURL, newBase.Text(), AC_EDITCHANGE, &args, fRequest.GetUnicode() ); htm.beginForm( actionURL.Text() ); htm.button( NULL, "Edit" ); htm << "</noscript>" << crlf; htm.endCol(); htm.endTRow(); } } htm.endTable(); htm.endCol(); htm.endTRow(); htm.comment( "END DESCRIBE PANE" ); fRequest << htm; } void p4wDescribePane::RenderInfo( char *data, char level ) { p4wHtml htm; htm.text(data); htm.linebreak(); fRequest << htm; }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 12234 | Matt Attaway |
Rejigger P4Web project in preparation for official sunsetting The bin directory contains the last official builds of P4Web from the Perforce download site. P4Web is soon to be completely sunsetted; these builds are here for folks who don't want to build their own. To better handle the archived builds the source code has been moved into a separate src directory. |
||
//guest/perforce_software/p4web/Panes/p4wDescribePane.cpp | |||||
#1 | 8914 | Matt Attaway | Initial add of the P4Web source code |