Index: skins/common/log.js
===================================================================
--- skins/common/log.js	(révision 0)
+++ skins/common/log.js	(révision 0)
@@ -0,0 +1,19 @@
+/**
+ * On Special:Log, do not allow to tick the 'inverse selection'
+ * checkbox if "All logs" type is selected
+ * @return boolean : Can 'Invert the selection' checkbox be checked ?
+ */
+
+function toggleNegateCheckBox() {
+	var sel = document.getElementById('mw-select-logtype');
+	var negate = document.getElementById('mw-invert-logtype');
+	for (i=0; i < sel.options.length; i++) {
+		if (sel.options[i].value == ""  && sel.options[i].selected) {
+			negate.checked = false;
+			negate.disabled = true;
+			return false;
+		}
+	}
+	negate.disabled = false;
+	return true;
+}

Modification de propriétés sur skins/common/log.js
___________________________________________________________________
Nom : svn:eol-style
   + native

Index: includes/SpecialLog.php
===================================================================
--- includes/SpecialLog.php	(révision 32300)
+++ includes/SpecialLog.php	(copie de travail)
@@ -41,7 +41,12 @@
  */
 class LogReader {
 	var $db, $joinClauses, $whereClauses;
-	var $type = '', $user = '', $title = null, $pattern = false;
+	var $offset, $limit;
+	var $type = '',			//LogType to show
+		$user = '',			//Search events by username
+		$title = null,		//Search events by pageTitle
+		$pattern = false,	//pattern for titles
+		$invert = false;	// 'All but these logs' checkbox
 
 	/**
 	 * @param WebRequest $request For internal use use a FauxRequest object to pass arbitrary parameters.
@@ -64,7 +69,8 @@
 			"INNER JOIN $user ON user_id=log_user" );
 		$this->whereClauses = array();
 
-		$this->limitType( $request->getVal( 'type' ) );
+		$this->limitType( $request->getVal( 'type' ),
+						  $request->getBool( 'invert' ) );
 		$this->limitUser( $request->getText( 'user' ) );
 		$this->limitTitle( $request->getText( 'page' ) , $request->getBool( 'pattern' ) );
 		$this->limitTime( $request->getVal( 'from' ), '>=' );
@@ -81,15 +87,22 @@
 	/**
 	 * Set the log reader to return only entries of the given type.
 	 * @param string $type A log type ('upload', 'delete', etc)
+	 * @param boolean $invert : If true, all logs but $type
 	 * @private
 	 */
-	function limitType( $type ) {
+	function limitType( $type, $invert ) {
 		if( empty( $type ) ) {
+			//Don't invert all logs
+			$this->invert = false;
 			return false;
 		}
 		$this->type = $type;
+		$this->invert = $invert;
 		$safetype = $this->db->strencode( $type );
-		$this->whereClauses[] = "log_type='$safetype'";
+		$clause = "log_type='$safetype'";
+		if ( $invert )
+			$clause = "NOT " . $clause;
+		$this->whereClauses[] = $clause;
 	}
 
 	/**
@@ -163,10 +176,11 @@
 	 */
 	function getQuery() {
 		$logging = $this->db->tableName( "logging" );
+		$forceIndex = $this->invert? "FORCE INDEX (times)" : "";
 		$sql = "SELECT /*! STRAIGHT_JOIN */ log_type, log_action, log_timestamp,
 			log_user, user_name,
 			log_namespace, log_title, page_id,
-			log_comment, log_params FROM $logging ";
+			log_comment, log_params FROM $logging $forceIndex";
 		if( !empty( $this->joinClauses ) ) {
 			$sql .= implode( ' ', $this->joinClauses );
 		}
@@ -209,6 +223,13 @@
 	}
 
 	/**
+	 * @return boolean the 'Invert selection' checkbox
+	 */
+	function queryNegate() {
+		return $this->invert;
+	}
+
+	/**
 	 * @return string The text of the title that this LogReader has been limited to.
 	 */
 	function queryTitle() {
@@ -247,7 +268,7 @@
 	/**
 	 * @var LogReader $reader
 	 */
-	var $reader;
+	var $reader, $skin;
 	var $numResults = 0;
 	var $flags = 0;
 
@@ -420,6 +441,10 @@
 	function showHeader( &$out ) {
 		$type = $this->reader->queryType();
 		if( LogPage::isLogType( $type ) ) {
+			//TODO : Actually, there are no special titles / headers 
+			// for queries with reader->queryInvert = True
+			// It just displays wrongly "here are the logs for type ttt"
+			// while the printed logs are actually all but these ttt logs.
 			$out->setPageTitle( LogPage::logName( $type ) );
 			$out->addWikiText( LogPage::logHeader( $type ) );
 		}
@@ -434,11 +459,25 @@
 		$action = htmlspecialchars( $wgScript );
 		$title = SpecialPage::getTitleFor( 'Log' );
 		$special = htmlspecialchars( $title->getPrefixedDBkey() );
+
+		$out->addHeadItem('special-log-js', $this->buildScript());	
 		$out->addHTML( "<form action=\"$action\" method=\"get\">\n" .
 			'<fieldset>' .
 			Xml::element( 'legend', array(), wfMsg( 'log' ) ) .
 			Xml::hidden( 'title', $special ) . "\n" .
+
+			Xml::openElement( 'table', 
+				array('style' => 'background-color:transparent') ) . "\n" .
+			Xml::openElement('tr') . "\n" .
+			Xml::openElement('td') . "\n" .
 			$this->getTypeMenu() . "\n" .
+			Xml::closeElement('td') . "\n" .
+			Xml::openElement('td') . "\n" .
+			$this->getNegateCheckBox() . "\n" .
+			Xml::closeElement('td') . "\n" .
+			Xml::closeElement('tr') . "\n" .
+			Xml::closeElement( 'table') . "<br/>\n" .
+
 			$this->getUserInput() . "\n" .
 			$this->getTitleInput() . "\n" .
 			(!$wgMiserMode?($this->getTitlePattern()."\n"):"") .
@@ -451,7 +490,7 @@
 	 * @private
 	 */
 	function getTypeMenu() {
-		$out = "<select name='type'>\n";
+		$out = "<select name='type' id='mw-select-logtype' onchange='toggleNegateCheckBox()'>\n";
 
 		$validTypes = LogPage::validTypes();
 		$m = array(); // Temporary array
@@ -479,6 +518,19 @@
 	 * @return string Formatted HTML
 	 * @private
 	 */
+	function getNegateCheckBox() {
+		$checked = $this->reader->queryNegate();
+		$attr = array();
+		$type = $this->reader->queryType();
+		if ( empty($type) ) //Don't allow to exclude "all logs but all logs"
+			$attr['disabled'] = 'disabled';
+		return Xml::checkLabel( wfMsg('invert'), 'invert', 'mw-invert-logtype', $checked , $attr );
+	}
+
+	/**
+	 * @return string Formatted HTML
+	 * @private
+	 */
 	function getUserInput() {
 		$user =  $this->reader->queryUser();
 		return Xml::inputLabel( wfMsg( 'specialloguserlabel' ), 'user', 'user', 12, $user );
@@ -502,6 +554,13 @@
 		return Xml::checkLabel( wfMsg( 'log-title-wildcard' ), 'pattern', 'pattern', $pattern );
 	}
 
+	function buildScript() {
+		global $wgStylePath, $wgStyleVersion;
+		return '<script type="text/javascript" src="' .
+			htmlspecialchars( $wgStylePath . "/common/log.js?$wgStyleVersion" ) .
+			'"></script>';
+	}
+
 	/**
 	 * @param OutputPage &$out where to send output
 	 * @private
@@ -513,6 +572,7 @@
 		$pieces[] = 'user=' . urlencode( $this->reader->queryUser() );
 		$pieces[] = 'page=' . urlencode( $this->reader->queryTitle() );
 		$pieces[] = 'pattern=' . urlencode( $this->reader->queryPattern() );
+		$pieces[] = 'invert=' . urlencode( $this->reader->queryNegate() );
 		$bits = implode( '&', $pieces );
 		list( $limit, $offset ) = $wgRequest->getLimitOffset();
 
