// // Copyright 2000 Perforce Software. All rights reserved. // // This file is part of Perforce - the FAST SCM System. // // p4wSubmittedChangesPane: // List of submitted changes with a form to change options // with the next display. #include <p4wp4.h> #include "p4wStrBuf.h" #include "p4wHtml.h" #include "p4wPane.h" #include "p4wSubmittedChangesPane.h" #include "p4wMenuPane.h" p4wSubmittedChangesPane::p4wSubmittedChangesPane( p4wView & ParentView, p4wRequest & Request, int isFileBrowser) : p4wPane(ParentView, Request), fIsFileBrowser(isFileBrowser), fRowCtr(0), fChgCtr(0) { generateTitle(); } p4wSubmittedChangesPane::~p4wSubmittedChangesPane() { } // ------------------------------------- // Render functions. // void p4wSubmittedChangesPane::Begin() { // // Begin the submitted changes pane p4wHtml htm(1); p4wURL urlMaker; StrBuf grayIcon; StrBuf clearIcon; // // Used to generate a line underneath the title, and // some vertical whitespace urlMaker.ConstructURL( grayIcon, "/grayPixelIcon", AC_ICON, NULL ); urlMaker.ConstructURL( clearIcon, "/clearpixelIcon", AC_ICON, NULL ); htm.comment( "BEGIN SUBMITTED CHANGES PANE" ); if (fRequest.GetScreenChunks() & SCRN_TITLE) { // Output the title htm.beginTRow(); htm.beginCol(); htm.beginTable( "0", "100%", "0", "0" ); htm.beginTRow(); htm.beginCol(0,0,0,0,0,0,0,1); htm.beginSpan( "title" ); htm << fTitle; htm.endSpan(); htm.endCol(); htm.endTRow(); htm.endTable(); htm.endCol(); htm.endTRow(); // // Generate line underneath the title htm.beginTRow(); htm.beginCol( "top" ); htm.icon( clearIcon.Text(), "2", "100%", "", 1, "0", "0" ); htm.linebreak(); htm.icon( grayIcon.Text(), "1", "100%", "", 1, "0", "0" ); htm.endCol(); htm.endTRow(); } fRequest << htm; htm.Clear(); // // Generate the Changelist Filter form if (fRequest.GetScreenChunks() & SCRN_FILTER) doSubmitButton(); // // Start the table of submitted changes htm.beginTable( "0", "100%", "0", "1" ); htm.beginTRow(); htm.beginCol(NULL, NULL, NULL, NULL, NULL, "8"); htm.icon( clearIcon.Text(), "1", "8", "", 1 ); htm.endCol(); htm.beginCol(); htm.beginTable( "0", "100%", "0", "1" ); htm.beginTRow(); htm.beginCol(); htm.icon( clearIcon.Text(), "2", "1", "", 1 ); htm.endCol(); htm.endTRow(); htm.beginTRow(); htm.beginCol(); htm.beginTable( "0", "100%", "0", "1", "#7F7F7F" ); htm.beginTRow( NULL, NULL, "#FFFFFF" ); htm.beginCol(); htm.beginTable( "0", "100%", "0", "0", "#FFFFFF" ); htm.beginTRow( NULL, NULL, "#EEEEEE" ); htm.beginColHead(); htm.icon( clearIcon.Text(), "18", "18", "", 1 ); htm.endColHead(); // // Generate table headings htm.beginColHead( NULL, "left" ); htm << "Changelist"; htm.endColHead(); htm.beginColHead( NULL, NULL, NULL, NULL, "#EEEEEE" ); htm.icon( clearIcon.Text(), "1", "12", "", 1 ); htm.endColHead(); htm.beginColHead( NULL, "left" ); htm << "Date"; htm.endColHead(); htm.beginColHead( NULL, NULL, NULL, NULL, "#EEEEEE" ); htm.icon( clearIcon.Text(), "1", "12", "", 1 ); htm.endColHead(); htm.beginColHead( NULL, "left" ); htm << "User"; htm.endColHead(); htm.beginColHead( NULL, NULL, NULL, NULL, "#EEEEEE" ); htm.icon( clearIcon.Text(), "1", "12", "", 1 ); htm.endColHead(); htm.beginColHead( NULL, "left" ); htm << "Client"; htm.endColHead(); htm.beginColHead( NULL, NULL, NULL, NULL, "#EEEEEE" ); htm.icon( clearIcon.Text(), "1", "12", "", 1 ); htm.endColHead(); htm.beginColHead( NULL, "left" ); htm << "Description"; htm.endColHead(); htm.endTRow(); htm.beginTRow(); htm.beginCol( "top", NULL, "12", NULL, NULL, NULL, "5" ); htm.icon( grayIcon.Text(), "1", "100%", "", 1, "0", "0" ); htm.endCol(); htm.endTRow(); fRequest << htm; } void p4wSubmittedChangesPane::Render(StrDict * varList) { // // Get the user/client information. const char * user = varList->GetVar( "user" )->Text(); const char * client = varList->GetVar( "client" )->Text(); const char * change = varList->GetVar( "change" )->Text(); p4wStrBuf changeURL; StrBuf newBase; p4wURL urlMaker; StrBuf clearIcon; // // Used to generate some vertical whitespace urlMaker.ConstructURL( clearIcon, "/clearpixelIcon", AC_ICON, NULL ); // // Build the change URL as a describe link fRequest.UseNewBase( newBase, NULL, "path", NULL ); newBase << change; if (fRequest.GetCmd() == AC_FIXSUBMITTED) { StrBufDict cmdArgs; const StrPtr *jb = fRequest.GetDynArg( "jb" ); cmdArgs.SetVar( "jb", jb ); urlMaker.ConstructURL( changeURL, newBase.Text(), AC_ADDFIX, &cmdArgs, fRequest.GetUnicode() ); } else urlMaker.ConstructURL( changeURL, newBase.Text(), AC_DESCRIBE, NULL, fRequest.GetUnicode() ); // // Build the user URL as a user link p4wStrBuf userURL; fRequest.UseNewBase( newBase, NULL, "path", NULL ); newBase << user; urlMaker.ConstructURL( userURL, newBase.Text(), AC_USERVIEW, NULL, fRequest.GetUnicode() ); // // Build the client URL as a client link p4wStrBuf clientURL; fRequest.UseNewBase( newBase, NULL, "path", NULL ); newBase << client; urlMaker.ConstructURL( clientURL, newBase.Text(), AC_CLIENTVIEW, NULL, fRequest.GetUnicode() ); p4wHtml htm( 1 ); // // Output this change. if( PageLimitExceeded() ) return; htm.beginTRow( "top", 0, 0, (fRowCtr & 0x01) ? "list_row alt_row" : "list_row" ); htm.beginCol(); htm.endCol(); // // Changelist htm.beginCol(0,0,0,0,0,0,0,1); htm.beginLink( changeURL.Text() ); htm.text( p4wStrBuf().EscapeHTML( StrRef(change), Unicode() ).Text() ); htm.endLink(); if (!fRequest.GetBrowseMode() && fRequest.GetCmd() != AC_FIXSUBMITTED) { htm << crlf; htm << "<script language=javascript>" << crlf; htm << "document.write(\"<span class='muaro'><a href='javascript:showMenu(\\\""; htm << p4wStrBuf().EscapeHTML( StrRef(change), Unicode() ).Text(); htm << "\\\",\\\"m"; htm << fChgCtr; htm << "\\\",\\\"subchg\\\","; if (strcmp(user, fRequest.GetUser().Text())) // different user? htm << p4wMenuPane::GetOtherUserSubChgMenuShowVals(); else htm << -1; htm << ",\\\"\\\")' id='id_m"; htm << fChgCtr++; htm << "' title ='Menu'>"; htm << " "; htm << "</a></span>"; htm << "\")" << crlf; htm << "</script>" << crlf; } htm.endCol(); htm.beginCol(); htm.icon( clearIcon.Text(), "1", "12", "", 1 ); htm.endCol(); // // Date htm.beginCol(); htm.text( p4wStrBuf().Expand( StrRef( "%time@*Y/*m/*d%" ), *varList, Unicode() ).Text() ); htm.endCol(); htm.beginCol(); htm.icon( clearIcon.Text(), "1", "12", "", 1 ); htm.endCol(); // // User htm.beginCol(); htm.beginLink( userURL.Text() ); htm.text( p4wStrBuf().EscapeHTML( StrRef(user), Unicode() ).Text() ); htm.endLink(); htm.endCol(); htm.beginCol(); htm.icon( clearIcon.Text(), "1", "12", "", 1 ); htm.endCol(); // // Client htm.beginCol(); htm.beginLink( clientURL.Text() ); htm.text( p4wStrBuf().EscapeHTML( StrRef(client), Unicode() ).Text() ); htm.endLink(); htm.endCol(); htm.beginCol(); htm.icon( clearIcon.Text(), "1", "12", "", 1 ); htm.endCol(); // // Description htm.beginCol(); htm.text( p4wStrBuf().Expand( StrRef( "%desc%" ), *varList, Unicode(), 1 ).Text() ); htm.endCol(); htm.endTRow(); // // Vertical space between rows htm.beginTRow( 0, 0, 0, (fRowCtr++ & 0x01) ? "alt_row b" : "b" ); htm.beginCol( 0, 0, "100%" ); htm.icon( clearIcon.Text(), "3", "1", "", 1 ); htm.endCol(); htm.endTRow(); fRequest << htm; } void p4wSubmittedChangesPane::End() { // // If no data was received, output a warning and don't // issue any form elements. p4wHtml htm; if( !fRowCtr && !fRequest.fHadPasswordError ) { htm.beginTRow(); htm.beginCol( NULL, NULL, "4" ); htm.text( " No submitted changelists found." ); const StrPtr *al = fRequest.GetDynArg("al"); if (!al || *(al->Text()) != 'y') { htm << "<p> Uncheck "Include only changelists with files in current path" in the Changelist Filter above,"; htm.linebreak(); htm << " then click the Filter button to view all changelists."; } htm.endCol(); htm.endTRow(); } // // Set hidden field IsFile if this is a file browser. // End the form. if( fIsFileBrowser ) { htm.hiddenField( "IsFile", "yes" ); } htm.endForm(); // // End the pane htm.endTable(); htm.endCol(); htm.endTRow(); htm.endTable(); htm.comment( "END SUBMITTED CHANGES PANE" ); fRequest << htm; } void p4wSubmittedChangesPane::doSubmitButton() { // // Generate form to give user options to choose the max number of // changelists, a range, a file pattern, filtered by user, // filtered by client, and the option of // showing integrated changelists p4wHtml htm; p4wURL urlMaker; StrBuf actionURL; StrBuf path; StrBuf clearIcon; int nCols = 2; const StrPtr *rev1 = fRequest.GetDynArg( "rev1", HE_Page ); // rev# const StrPtr *rev2 = fRequest.GetDynArg( "rev2", HE_Page ); // rev# const StrPtr *sr1 = fRequest.GetDynArg( "sr", HE_Page ); // chg, label, date const StrPtr *sr2 = fRequest.GetDynArg( "sr2", HE_Page ); // chg, label, date const StrPtr *pat = fRequest.GetStateArg( "pat", HE_Page ); // file pattern (saved in base!) const StrPtr *mx = fRequest.GetDynArg( "mx", HE_Page ); // max to retrieve const StrPtr *fl = fRequest.GetDynArg( "fl", HE_Page ); // fl=-i for integrated const StrPtr *al = fRequest.GetDynArg( "al", HE_Page ); // al=y -> only chgs for current path const StrPtr *jb = fRequest.GetDynArg( "jb", HE_Page ); // job const StrPtr *user = fRequest.GetDynArg( "u", HE_Page ); // user const StrPtr *client = fRequest.GetDynArg( "cl", HE_Page ); // client const StrPtr *srevState = fRequest.GetStateArg( "sr", HE_Page ); // // Used to generate some whitespace urlMaker.ConstructURL( clearIcon, "/clearpixelIcon", AC_ICON, NULL ); // // Check if -u & -c flags are supported by this server int userClient = 0; const StrPtr *server = fRequest.GetProtocol( "server2" ); if( server && server->Atoi() > 11 ) { ++userClient; nCols = 4; } // // Pattern field is not relevant for file browser if( fIsFileBrowser ) --nCols; // // If both dynamic and state parameters for sr are // set, dynamic gets priority if( !sr1 && srevState ) sr1 = srevState; StrBuf upTo; if( sr1 ) { upTo << "@" << sr1; if( sr2 ) upTo << ",@" << sr2; } else if( rev1 ) { upTo << "#" << rev1; if( rev2 ) upTo << ",#" << rev2; } // // Construct the action url used for parsing the form. // Some browsers will truncate the path from the BASE // if the path does not end in a forward slash. So if // we're in workspace mode, use the full path as a precaution. if( fRequest.GetViewMode() == VM_WORKSPACE ) fRequest.UseNewBase( path, NULL, "path", fRequest.GetPath().Text() ); else path << fRequest.GetURL(); StrBufDict args; if (jb && jb->Length()) args.SetVar( "jb", jb ); fRequest.ConstructSafeURL( actionURL, path.Text(), fRequest.GetCmd() == AC_FIXSUBMITTED ? AC_FIXSUBPROCESSOR : AC_CHANGESPROCESSOR, &args ); htm.beginTRow(); htm.beginCol(); fRequest << htm; htm.Clear(); StrBuf filtermsg; doFilterMessage(&filtermsg); fRequest.doShowHideBlock(SH_SUBMITTED, "changelist filter", "Changelist Filter", filtermsg.Text()); htm.endCol(); htm.endTRow(); // // Output the Changelist filter // // Start a DIV for showing/hiding the filter htm.beginTRow( NULL, NULL, "#FFFFFF" ); htm.beginCol(); htm << "<script language=javascript>" << crlf; htm << "document.write(\"<div id='showhideBlock'>\")" << crlf; htm << "</script>" << crlf; htm.beginTable(0, "100%", "0", "0"); htm.beginTRow(); htm.beginCol(); htm.beginForm( actionURL.Text() ); htm.beginTable( "0", NULL ); htm.beginTRow(); htm.beginCol(); htm.beginTable( "0", NULL, "4", "0", "#FFFFFF" ); htm.beginTRow(); htm.beginCol(0,0,0,"100%"); htm.icon( clearIcon.Text(), "1", "5", "", 1 ); htm.endCol(); // // Highest changelist or range text box htm.beginCol( 0, 0, NULL, NULL, NULL, NULL, NULL, 1 ); htm.text( "Revision range:" ); htm.endCol(); htm.beginCol(); if( upTo.Length() ) htm.textField( "UpToVal", upTo.Text(), 16 ); else htm.textField( "UpToVal", NULL, 16 ); htm.endCol(); htm.beginCol(0,0,0,"2",0,"20%"); htm.icon( clearIcon.Text(), "1", "14", "", 1 ); htm.endCol(); // Option to filter by user only if supported by // this version of the server if( userClient ) { htm.beginCol(); htm.text( "User:" ); htm.endCol(); htm.beginCol(); if( user ) htm.textField( "User", user->Text(), 16 ); else htm.textField( "User", NULL, 16 ); htm.endCol(); htm.beginCol(0,0,0,0,0,"20%"); htm.endCol(); } // // Max number of changelists on page htm.beginCol(NULL, NULL, 0,0,0,0,0,1); htm.label( "Show", "Max" ); if( mx ) htm.textField( "Max", mx->Text(), 3, "Max" ); else htm.textField( "Max", NULL, 3, "Max" ); htm.label( "changelists", "Max" ); htm.endCol(); htm.beginCol(0,0,0,"100%",0,"100%"); htm.icon( clearIcon.Text(), "1", "14", "", 1 ); htm.endCol(); htm.endTRow(); htm.beginTRow(); // // File pattern is only relevant if we are in // the path browser htm.beginCol(); if( !fIsFileBrowser ) htm.text( "File pattern:" ); htm.endCol(); htm.beginCol(); if( !fIsFileBrowser ) { if( pat ) htm.textField( "PatVal", pat->Text(), 16 ); else htm.textField( "PatVal", "...", 16 ); } htm.endCol(); // // Option to filter by client only if supported by // this version of the server htm.beginCol(); if( userClient ) { htm.text( "Client:" ); htm.endCol(); htm.beginCol(); // // Filter by client if( client ) htm.textField( "Client", client->Text(), 16 ); else htm.textField( "Client", NULL, 16 ); htm.endCol(); } htm.endTRow(); htm.beginTRow(); // // Checkbox for displaying only changelists in this path htm.beginCol( NULL, NULL, "100%", 0,0,0,0,1 ); if( al && *al == "y" ) htm.checkbox( "AllC", "y" ); else htm.checkbox( "AllC", "y", 1 ); htm.label( "Include only changelists with files in current path", "AllC" ); htm.icon( clearIcon.Text(), "1", "14", "", 1 ); // // Show integrated changelists checkbox unless -sh was given if (!SEC_DISALLOW_REVHIST_INTEG || fRequest.isLocalRequest()) { if( fl && *fl == "-i" ) htm.checkbox( "Int", "-i", 1 ); else htm.checkbox( "Int", "-i" ); htm.label( "Include integrated changelists", "Int" ); } htm.endCol(); htm.endTRow(); htm.beginTRow(); // // Filter button htm.beginCol(0,0,"4",0,0,0,0,1); htm.button( "Show", "Filter" ); // // Clear button htm.button( "Clear", "Reset Defaults" ); htm.endCol(); htm.endTRow(); htm.endTable(); htm.endCol(); htm.endTRow(); htm.endTable(); StrBuf grayIcon; urlMaker.ConstructURL( grayIcon, "/grayPixelIcon", AC_ICON, NULL ); htm.icon( grayIcon.Text(), "1", "100%", "", 1, "0", "0" ); htm.endCol(); htm.endTRow(); htm.endTable(); htm.endCol(); htm.endTRow(); htm.endTable(); htm << "<script language=javascript>" << crlf; htm << "document.write(\"</div>\")" << crlf; htm << "</script>" << crlf; htm.endCol(); htm.beginCol(); htm.icon( clearIcon.Text(), "1", "10", "", 1 ); htm.endCol(); htm.endTRow(); htm.endTable(); htm.endCol(); htm.endTRow(); htm.endTRow(); htm.endTable(); fRequest << htm; } void p4wSubmittedChangesPane::generateTitle() { // // Generate the Submitted changelists title const StrPtr *rev1 = fRequest.GetDynArg( "rev1", HE_Page ); const StrPtr *rev2 = fRequest.GetDynArg( "rev2", HE_Page ); const StrPtr *sr1 = fRequest.GetDynArg( "sr", HE_Page ); const StrPtr *sr2 = fRequest.GetDynArg( "sr2", HE_Page ); const StrPtr *jb = fRequest.GetDynArg( "jb", HE_Page ); const StrPtr *srevState = fRequest.GetStateArg( "sr", HE_Page ); // // If both state and dynamic sr variables are set, // dynamic sr gets priority if( !sr1 && srevState ) sr1 = srevState; if (fRequest.GetCmd() == AC_FIXSUBMITTED) { fTitle << "Add Job "; if (jb) fTitle << jb->Text(); fTitle << " to Submitted Changelist"; } else fTitle << "Submitted Changelists"; if( rev1 ) { fTitle << " #" << rev1; if( rev2 ) fTitle << "," << rev2; } else if( sr1 ) { fTitle << " @" << sr1; if( sr2 ) fTitle << "," << sr2; } fTitle << ":"; } void p4wSubmittedChangesPane::doFilterMessage(StrBuf *msg) { const StrPtr *al = fRequest.GetDynArg( "al", HE_Page ); const StrPtr *rev1 = fRequest.GetDynArg( "rev1", HE_Page ); // rev# const StrPtr *rev2 = fRequest.GetDynArg( "rev2", HE_Page ); // rev# const StrPtr *sr1 = fRequest.GetDynArg( "sr", HE_Page ); // chg, label, date const StrPtr *sr2 = fRequest.GetDynArg( "sr2", HE_Page ); // chg, label, date const StrPtr *srevState = fRequest.GetStateArg( "sr", HE_Page ); const StrPtr *fl = fRequest.GetDynArg( "fl", HE_Page ); const StrPtr *cl = fRequest.GetDynArg( "cl", HE_Page ); const StrPtr *u = fRequest.GetDynArg( "u", HE_Page ); const StrPtr *pat= fRequest.GetStateArg( "pat", HE_Page ); const StrPtr *mx = fRequest.GetDynArg( "mx", HE_Page ); // max to retrieve if( !fIsFileBrowser && pat ) { *msg << "(Pattern: \\\"" << pat->Text() << "\\\""; } // // If both dynamic and state parameters for sr are // set, dynamic gets priority if( !sr1 && srevState ) sr1 = srevState; StrBuf upTo; if ( sr1 ) { upTo << "@" << sr1; if( sr2 ) upTo << ",@" << sr2; } else if( rev1 ) { upTo << "#" << rev1; if( rev2 ) upTo << ",#" << rev2; } if (upTo.Length()) { if (*(msg->Text())) *msg << "; "; else *msg << "("; *msg << "Range: \\\"" << upTo << "\\\""; } if (u) { if (*(msg->Text())) *msg << "; "; else *msg << "("; *msg << "User: \\\"" << u << "\\\""; } if (cl) { if (*(msg->Text())) *msg << "; "; else *msg << "("; *msg << "Client: \\\"" << cl << "\\\""; } if (!al) { if (*(msg->Text())) *msg << "; "; else *msg << "("; *msg << "Limit to current path"; } if (fl && *fl == "-i") { if (*(msg->Text())) *msg << "; "; else *msg << "("; *msg << "Include integrations"; } if (mx) { const StrPtr *X = fRequest.GetStateArg( "X" ); // undoc eXperimental flags int bQ = (X && strchr(X->Text(), 'm')) ? 1 : 0; if (!bQ) { if (*(msg->Text())) *msg << "; "; else *msg << "("; *msg << "Show " << mx->Text() << " changelists"; } } if (*(msg->Text())) *msg << ")"; } void p4wSubmittedChangesPane::RenderError( char *data, int escapeHTML ) { RenderErrorTbl( data, escapeHTML ); }
# | 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/p4wSubmittedChangesPane.cpp | |||||
#1 | 8914 | Matt Attaway | Initial add of the P4Web source code |