Extension talk:Graphical Category Browser

Latest comment: 6 years ago by Squeak24 in topic Error when using graphical category browser

doesn't work with 1.35.1

edit
[b026c8931d2a6fccff479219] /index.php?title=$whatever Error from line 127 of /var/www/wiki/extensions/xyCategoryBrowser/xyCategoryBrowser.php: Call to undefined method OutputPage::setSquidMaxage()

Backtrace:

#0 /var/www/wiki/includes/HookContainer/HookContainer.php(320): xyCategoryHook::hook(CategoryTreeCategoryPage)
#1 /var/www/wiki/includes/HookContainer/HookContainer.php(131): MediaWiki\HookContainer\HookContainer->callLegacyHook(string, array, array, array)
#2 /var/www/wiki/includes/HookContainer/HookRunner.php(1115): MediaWiki\HookContainer\HookContainer->run(string, array)
#3 /var/www/wiki/includes/page/CategoryPage.php(54): MediaWiki\HookContainer\HookRunner->onCategoryPageView(CategoryTreeCategoryPage)
#4 /var/www/wiki/includes/actions/ViewAction.php(74): CategoryPage->view()
#5 /var/www/wiki/includes/MediaWiki.php(527): ViewAction->show()
#6 /var/www/wiki/includes/MediaWiki.php(313): MediaWiki->performAction(CategoryTreeCategoryPage, Title)
#7 /var/www/wiki/includes/MediaWiki.php(940): MediaWiki->performRequest()
#8 /var/www/wiki/includes/MediaWiki.php(543): MediaWiki->main()
#9 /var/www/wiki/index.php(53): MediaWiki->run()
#10 /var/www/wiki/index.php(46): wfIndexMain()
#11 {main}

… according to https://www.mediawiki.org/wiki/Release_notes/1.31 , setSquidMaxage() has been deprecated with mediawiki 1.27. to save others from disappointments, i'll mark this extension as unmaintained - no bnad faith intended.

other probs

edit

I get the extension to work. Graphviz renders the images and the message 'rendered with..' but if i click on the image (name of a category) i get an empty white page.The normal categoryoverview don't work anymore, too. I user MW 1.10 on Wamp. Any Idea? -- 13.8.2007

same problem as above

edit

Hi

I also have the same problem as described above. any solutions, plz?

Jack

Use of SpecialPage::addPage was deprecated in MediaWiki 1.7.

edit

Backtrace: xyCategoryBrowser.php line 81 calls SpecialPage::addPage() - line - calls xyfCategoryBrowserSetup() Setup.php line 551 calls call_user_func() WebStart.php line 157 calls require_once() index.php line 55 calls require()


How To fix?

How to I install graphwiz?

edit

I'm confused about how to install graphwiz? Which version should I chose (debian, ubuntu?? Executable Packages from AT&T?, Java?)

Is this extension for a local use? I don't have any control on which software my web provider have installed on his system...

To install it on JumpBox VM, which uses Ubuntu, go to a shell windows and:

  1. apt-get update /* updte avail packages */
  2. apt-get install graphviz /* install graphviz */

dot will be installed in /usr/bin/dot

Solved problem with white page

edit

Hi I propably solved problem with white page described above.

Please disable this line in code:

$wgHooks['CategoryPageView'][] = 'xyCategoryGraphHook';

so it will be:

//$wgHooks['CategoryPageView'][] = 'xyCategoryGraphHook';

what i have done wrong? ERROR

edit

I have no image to display. in the apache log i am getting always usr/bin/dot: symbol lookup error: /usr/lib/libcairo.so.2: undefined symbol: FT_Library_SetLcd

in cache .dot is created, .png is corrupted

if i compile .dot manually, i'll get a graph without errors

Example Please

edit

Any examples of this extension?

Solved problem with white page on Windows

edit

The problem was in the shell_exec commands in the lines 170 to 180 while generating the png- and mapfile, now it works.

The script

edit


<?php
//Path to the GraphViz dot executable (Linux)
//$xyDotPath = "/usr/local/bin/dot";
//Path to the GraphViz dot executable (Windows)
$xyDotPath = "\"c:\\Programme\\Graphviz 2.21\\bin\\dot.exe\"";
 
$xyCategoriesMaxAge = 36;
// Path for the file cache relative to this script.
$xyCategoriesCache = "/images/xyGraphvizCache/";
 
if(!defined('MEDIAWIKI')){
  // Serve the PNG image
  $cap = new xyCategoryGraph();
  if ($cap->serveFile()) die();
  header("HTTP/1.1 404 Not Found");
  die("<H1>404 Not Found </H1>");
  }
 
//install special page
$wgExtensionFunctions[] = 'xyfCategoryBrowserSetup';
$wgExtensionCredits['specialpage'][] = array(
        'name' => 'Xypron Category Browser',
        'author' =>'xypron',
        'description' => 'Graphviz graphs for categories',
        'url' => 'http://www.xypron.de');
 
// Setup Special Page
function xyfCategoryBrowserSetup() {
  global $IP, $wgMessageCache, $wgHooks;
 
  //$wgHooks['CategoryPageView'][] = 'xyCategoryGraphHook';
 
  require_once($IP . '/includes/SpecialPage.php');
 
  SpecialPage::addPage(new SpecialPage('Xygraphicalcategorybrowser', '', true, 'xyfGraphicalCategoryBrowser', false));
 
  $wgMessageCache->addMessages( array(
    'xygraphicalcategorybrowser' => 'Graphical Category Browser',
    'xyrenderedwith'    => 'rendered with')
    );
  $wgMessageCache->addMessages( array(
    'xygraphicalcategorybrowser' => 'Graphische Kategorieuebersicht',
    'xyrenderedwith'    => 'gezeichnet mit'),
    'de');
  }
 
function xyfGraphicalCategoryBrowser() {
  $cap = new xyCategoriesPage();
  $cap->doQuery();
  $cap->doDot('xycategorybrowser');
  $cap->showImg('xycategorybrowser');
  }
 
class xyCategoriesPage {
  var $debug = false;
  var $dot = "";
 
  function doQuery($title = null) {
    global $wgOut;
 
    error_reporting(0);
 
    $redirections= Array();
    $nodes=Array();
 
    $this->dot = "digraph a {\nsize=\"8,20\";\nrankdir=LR;\nnode [height=0 style=\"filled\", shape=\"box\", font=\"Helvetica-Bold\", fontsize=\"10\", color=\"#00000\"];\n";
    $dbr =& wfGetDB( DB_SLAVE );
 
    $sql= $this->getSQLCategories($title);
    $res = $dbr->query( $sql );
    # Only read at most $num rows, because $res may contain the whole 1000
    for ( $i = 0; $obj = $dbr->fetchObject($res); $i++ ) {
      $l_title = Title::makeTitle(NS_CATEGORY, $obj->cat);
 
      $color = "#CCFFCC";
      if($obj->redirect==1) $color = "#FFCCCC";
      if($obj->virtual == 1) $color = "#FFFFCC";
      $nodes[$obj->cat] = array(
        'color' => $color,
        'url'   => $l_title->getFullURL(),
        'peri'  => 1
        );
 
      if ($title && $obj->cat == $title->getDBkey()) {
        $nodes[$obj->cat]['peri']=2;
        }
      if ($obj->redirect) {
        $article = new article($l_title);
        if ($article) {
          $text = $article->getContent();
          $rt = Title::newFromRedirect($text);
          if ($rt) {
            if (NS_CATEGORY == $rt->getNamespace()) {
              $redirections[$l_title->getDBkey()] = $rt->getDBkey();
              if (!$nodes[$rt->getDBkey()]){
                $nodes[$rt->getDBkey()] = array(
                  'color' => "#CCFFCC",
                  'url'   => $rt->getFullURL(),
                  'peri'  => 1
                  );
                }
              }
            }
          }
        }
      }
 
    $sql= $this->getSQLCategoryLinks($title);
    $res = $dbr->query( $sql );
    for ( $i = 0; $obj = $dbr->fetchObject( $res ); $i++ ) {
      $cat_from = Title::makeName(NS_CATEGORY, $obj->cat_from);
      $cat_to   = Title::makeName(NS_CATEGORY, $obj->cat_to);
      if (@!$nodes[$obj->cat_to]){
        $rt = Title::makeTitle(NS_CATEGORY, $obj->cat_to);
        $nodes[$rt->getDBkey()] = array(
          'color' => "#FF0000",
          'url'   => $rt->getFullURL(),
          'peri'  => ($title && $rt->getDBkey() == $title->getDBkey())? 2 : 1
          );
        }
      if (!$redirections[$obj->cat_from] &&  $redirections[$obj->cat_from] != $obj->cat_to) {
        $this->dot .= "\"$obj->cat_to\" -> \"$obj->cat_from\" [dir=back];\n";
        }
      }
 
    foreach( $redirections as $cat_from => $cat_to) {
      $this->dot .= "\"$cat_to\" -> \"$cat_from\" [color=\"#FF0000\", dir=back];\n";
      }
 
    foreach( $nodes as $l_DbKey=>$properties ) {   
      $l_title = Title::makeTitle(NS_CATEGORY, $l_DbKey);
      $this->dot .= "\"$l_DbKey\" [URL=\"{$properties['url']}\", peripheries={$properties['peri']}, fillcolor=\"{$properties['color']}\"];\n";
      }
 
    $this->dot .= "}\n";
    if ($this->debug) $wgOut->addWikiText("<"."pre>$this->dot<"."pre>");
    }
 
/**
 * Save dot file and generate png and map file
 * @param title to generate md5 for filename
 */
  function cacheAge( $title ) {
    $md5 = md5($title);
    $docRoot = $this->cachePath();
    $fileMap = "$docRoot$md5.map";
 
    if (!file_exists($fileMap)) return false; 
    return time() - filemtime($fileMap);
    }
 
 
/**
 * Save dot file and generate png and map file
 * @param title to generate md5 for filename
 */
  function doDot( $title ) {
    global $wgOut;
    global $xyDotPath;
 
    $md5 = md5($title);
    $docRoot = $this->cachePath();
    $fileDot = "$docRoot$md5.dot";
    $fileMap = "\"$docRoot$md5.map\"";
    $filePng = "\"$docRoot$md5.png\"";


 
    $this->file_put_contents($fileDot, $this->dot);
 
    if ($xyDotPath) {

      if ($this->debug) $wgOut->addWikiText("$xyDotPath -Tpng -o$filePng <\"$fileDot\"");
      #$result = shell_exec("$xyDotPath -T png -o $filePng \"$fileDot\"");
      $WshShell = new COM("WScript.Shell");
      $ret = $WshShell->Exec("$xyDotPath -T png -o $filePng \"$fileDot\"");

      if ($this->debug) $wgOut->addWikiText("$xyDotPath -Tcmap -o$fileMap <\"$fileDot\"");
      #$map = shell_exec("$xyDotPath -T cmap -o $fileMap <\"$fileDot\"");
      $WshShell2 = new COM("WScript.Shell");
      $ret2 = $WshShell2->Exec("$xyDotPath -T cmap -o $fileMap \"$fileDot\"");

    }
}

/**
 * serveFile()
 *
 * This function is used to deliver the PNG file to the client.
 * Client side cache behaviour is controlled here.
 * This is necessary to get a match between the html and the image.
 */
 function serveFile() {
   global $xyCategoriesMaxAge;
   // Get filename from GET parameter
   if(isset($_GET['png'])) {
     $filename = @$_GET['png'];
     }
   else {
     return false;
     }
   // Check filename is valid
   if (preg_match('/\\W/',$filename))return false;
   $docRoot = $this->cachePath();
   $file = "$docRoot$filename.png";
   // Check file exists
   if (!file_exists($file)) return false;
   // Get filetime
   $time = @filemtime($file);
   // Get filesize
   $size = @filesize($file);
 
   $etag = md5("$time|$size");
   // Get "Last-Modified"
   if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
     $oldtime=strtotime(current(explode(';',$_SERVER['HTTP_IF_MODIFIED_SINCE'])));
     }
   // Get "ETag"
   if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
     $oldetag=explode(',',$_SERVER['HTTP_IF_NONE_MATCH']);
     }
   // If either is unchanged the file is not modified.     
   if ( (isset($oldtime) && $oldtime == $time ) ||
      (isset($oldetag) && $oldetag == $etag ) ) {
     header('HTTP/1.1 304 Not Modified');
     header('Date: '.gmdate('D, d M Y H:i:s').' GMT');
     header('Server: PHP');
     header("ETag: $etag");
     return true;
     }
   // Send headers
   header('HTTP/1.1 200 OK');
   header('Date: '.gmdate('D, d M Y H:i:s').' GMT');
   header('Server: PHP');
   header('Last-Modified: '.gmdate('D, d M Y H:i:s',$time).' GMT');
   header('Expires: '.gmdate('D, d M Y H:i:s',$time+$xyCategoriesMaxAge).' GMT');
   // Supply the filename that is proposed when saving the file to disk   
   header("Content-Disposition: inline; filename=cat.png");
   header("ETag: $etag");
   header("Accept-Ranges: bytes");
   header("Content-Length: ".(string)(filesize($file)));
   header("Connection: close\n");
   header("Content-Type: image/png");
   // Send file
   $h = fopen($file, 'rb');
   fpassthru($h);
   fclose($h);
   return true;
   }
 
 
/**
 * Output the image to the OutputPage object.
 * @param title to generate md5 for filename
 */
  function showImg( $title ) {
    global $wgOut;
    global $wgUploadPath, $wgScriptPath;
 
    $docRoot = $this->cachePath();
    $md5 = md5($title);
    $fileMap = "$docRoot$md5.map";
 
    // Get name of this script this will keep it working after renaming
    $path_parts = pathinfo(__FILE__);
    $script = $path_parts['basename'];
 
    if (file_exists($fileMap)) {
      $map = $this->file_get_contents($fileMap);
      if ($this->debug) $wgOut->addWikiText("<"."pre>$map<"."/pre>");
 
      $URLpng =  "$wgScriptPath/extensions/$script?png=$md5";
      $wgOut->addHTML("<IMG src=\"$URLpng\" usemap=\"#map1\" alt=\"$title\"><MAP name=\"map1\">$map</MAP>");
      $wgOut->addWikiText(
        wfMsg('xyrenderedwith')." [http://www.graphviz.org/ Graphviz - Graph Visualization Software]".
        ', '.date("Y-m-d H:i:s.", filemtime($fileMap))."\n----\n");
      return true;
      }
    else {
      return false;
      }
    }
 
/**
 * @return directory for graphviz files
 */
  function cachePath() {
    global $xyCategoriesCache;
 
    $path = pathinfo(__FILE__);
    $path = $path['dirname'].$xyCategoriesCache;
    if (substr( php_uname( ), 0, 7 ) == "Windows") $path = preg_replace('/\\//', '\\',$path);
    if (!is_dir($path)) {
      mkdir($path, 0775);
      }
    return $path;
    }
 
  function getSQLCategories( $title = null ) {
    global $wgOut;
 
    $NScat = NS_CATEGORY;
    $dbr =& wfGetDB(DB_SLAVE);
    $categorylinks = $dbr->tableName('categorylinks');
    $page          = $dbr->tableName('page');
    $sql =
      "SELECT\n".
      "    page_title AS cat,\n".
      "    page_is_redirect AS redirect,\n".
      "    0 AS virtual\n".
      "  FROM $page\n".
      "  WHERE\n".
      "    page_namespace={$NScat}\n".
      "UNION\n".
      "SELECT\n".
      "    cl_to as cat,\n".
      "    0 AS redirect,\n".
      "    1 AS virtual\n".
      "  FROM $categorylinks\n".
      "  LEFT JOIN $page\n".
      "  ON page_title=cl_to\n".
      "  WHERE\n".
      "    page_id IS NULL";
    if ($this->debug) $wgOut->addWikiText("<"."pre>$sql<"."/pre>");
    return $sql;
    }
 
 
  function getSQLCategoryLinks( $title = null ) {
    global $wgOut;
 
    $NScat = NS_CATEGORY;
    $dbr =& wfGetDB(DB_SLAVE);
    $categorylinks = $dbr->tableName('categorylinks');
    $page          = $dbr->tableName('page');
    $sql =
      "SELECT\n".
      "    page_title AS cat_from, \n".
      "    cl_to as cat_to,\n".
      "    page_is_redirect AS redirect\n".
      "  FROM $page\n".
      "  INNER JOIN $categorylinks\n".
      "  ON page_id=cl_from\n".
      "  WHERE\n".
      "    page_namespace={$NScat}";
    if ($this->debug) $wgOut->addWikiText("<"."pre>$sql<"."/pre>");
 
    return $sql;
    }
 
  function neighboursOnly(){ return false ;}
 
// This function is only needed for PHP prior to version 5.
  function file_put_contents($n,$d) {
    $f=@fopen($n,"wb");
    if (!$f) {
      return false;
      } 
    else {
      fwrite($f,$d);
      fclose($f);
      return true;
      }
    }    
// This function is only needed for PHP prior to version 5.
  function file_get_contents($n) {
    $f=@fopen($n,"rb");
    if (!$f) {
      return false;
      } 
    else {
      $s=filesize($n);
      $d=false;
      if ($s) $d=fread($f, $s) ; 
      fclose($f);
      return $d;
      }
    }    
  }
 
 
class xyCategoryGraph extends xyCategoriesPage{
 
  function neighboursOnly(){ return true ;}
 
  function getSQLCategories( $title ) {
    global $wgOut;
 
    $id   = $title->getArticleID();
    $text = $title->getDBkey();
 
    $NScat = NS_CATEGORY;
    $dbr =& wfGetDB(DB_SLAVE);
    // Use the following for MediaWiki 1.9:
    // $text = $dbr->addQuotes($text);
    $text = "'".wfStrencode($text)."'"; 
 
    $categorylinks = $dbr->tableName('categorylinks');
    $page          = $dbr->tableName('page');
    $sql =
      "SELECT DISTINCT\n".
      "    page_title AS cat,\n".
      "    page_is_redirect AS redirect,\n".
      "    0                AS virtual\n".
      "  FROM $page as a\n".
      "  left JOIN $categorylinks as b\n".
      "  ON a.page_id=b.cl_from\n".
      "  left join $categorylinks as c\n".
      "  ON a.page_title=c.cl_to\n".
      "  WHERE\n".
      "    page_namespace = {$NScat} AND\n".
      "  (  c.cl_from    = $id OR\n".
      "     a.page_id    = $id OR\n".
      "     b.cl_to      = {$text} )\n";
    if ($this->debug) $wgOut->addWikiText("<"."pre>$sql<"."/pre>");
    return $sql;
    }
 
  function getSQLCategoryLinks( $title ) {
    global $wgOut;
 
    $id   = $title->getArticleID();
    $text = $title->getDBkey();
 
    $NScat = NS_CATEGORY;
    $dbr =& wfGetDB(DB_SLAVE);
    // Use the following for MediaWiki 1.9:
    // $text = $dbr->addQuotes($text);
    $text = "'".wfStrencode($text)."'"; 
 
    $categorylinks = $dbr->tableName('categorylinks');
    $page          = $dbr->tableName('page');
    $sql =
      "SELECT\n".
      "    page_title AS cat_from, \n".
      "    cl_to as cat_to\n".
      "  FROM $page\n".
      "  INNER JOIN $categorylinks\n".
      "  ON page_id=cl_from\n".
      "  WHERE\n".
      "    ( page_id=$id  OR\n".
      "    cl_to=$text ) AND\n".
      "    page_namespace={$NScat}";
    if ($this->debug) $wgOut->addWikiText("<"."pre>$sql<"."/pre>");
    return $sql;
    }
  }
 
  function xyCategoryGraphHook($cat) {
    global $wgOut, $xyCategoriesMaxAge;
    $wgOut->setSquidMaxage( $xyCategoriesMaxAge );
    $title = $cat->getTitle();
    $dbKey = $title->getDBkey();
    $cap = new xyCategoryGraph();
    $age = $cap->cacheAge($dbKey);
    if (!$age || $age > $xyCategoriesMaxAge ) {
      $cap->doQuery($title);
      $cap->doDot($dbKey);
      };
    $cap->showImg($dbKey);
    return true;
    }
 
?>

Error on line 517

edit

Hi everyone,

I installed Graphviz packages (sudo apt-get install graphviz), the WM extension, patched the config files to dot directory (/usr/bin/) and made the folders and chmod to images/xyGraphvizCache

But the extension, XYCategoryBrowser shows the next error:

Strict Standards: Declaration of xyCategoryGraph::getSQLCategoryLinks() should be compatible with xyCategoriesPage::getSQLCategoryLinks($title = NULL) in /opt/lampp/htdocs/wiki/extensions/xyCategoryBrowser/xyCategoryBrowser.php on line 517 87.111.85.83 16:12, 9 December 2012 (UTC)Reply

Output of pages

edit

Hi everyone,

I just installed the extension. It works great. But in my opinion, it would be very valuable it the pages would be printed too. Perhaps in a different form.

With best

Torsten

Possible to provide more installation details for no-shell web server ?

edit

Hello all,

I'm trying to find a categories graphical browser to help me refine my categories on a wiki. It's the first and only MediaWiki I'll ever install. I find your extension, and now, what must I do next ?

  • Install Graphviz - Graph Visualization Software :
    • It seems to be a command-line utility for doing visualization, but what would I do with it on a web server ?
    • There's not even an Installation item in the main menu, and given the Installation notes, I just couldn't figure how to install it,
    • No mention anywhere of installing to a web-server with only browser and FTP access.
  • Download script and copy to extensions.
    • OK for this one.
  • Correct $xyDotPath and $xyCategoriesCache to your needs.
    • OK, "correct them to suit your needs", well...
    • but what are these variables, what do they serve for...
    • and more generally, how am I to guess how to "correct them for my needs" ?
  • Create directory images/xyGraphvizCache
    • OK for this one.
  • Add the following line to LocalSettings.php
    • OK for this one.
  • Maybe configure the style
    • OK for this one.

Thanks in advance for any hint !

--Mutos (talk) 18:37, 18 February 2017 (UTC)Reply


Undefined Method Error

edit

[WPeDBkOMMGAjrrAIcxL4EwAAAAc] /index.php/Special:Xygraphicalcategorybrowser Error from line 112 of /var/www/html/extensions/xyCategoryBrowser/xyAbstractCategoryGraph.php: Call to undefined method Title::newFromRedirect()

Backtrace:

  1. 0 /var/www/html/extensions/xyCategoryBrowser/xyCategoriesSpecialPage.php(52): xyAbstractCategoryGraph->doQuery()
  2. 1 /var/www/html/includes/specialpage/SpecialPage.php(522): xyCategoriesSpecialPage->execute(NULL)
  3. 2 /var/www/html/includes/specialpage/SpecialPageFactory.php(576): SpecialPage->run(NULL)
  4. 3 /var/www/html/includes/MediaWiki.php(283): SpecialPageFactory::executePath(Title, RequestContext)
  5. 4 /var/www/html/includes/MediaWiki.php(851): MediaWiki->performRequest()
  6. 5 /var/www/html/includes/MediaWiki.php(512): MediaWiki->main()
  7. 6 /var/www/html/index.php(43): MediaWiki->run()
  8. 7 {main}

any clue where to look?

Category Redirects not working

edit

in xyAbstractCategoryGraph.php, lines 112 and 113 throw an error

$text = $article->getContent();
$rt = Title::newFromRedirect($text);

Title::newFromRedirect() was deprecated in Mediawiki 1.21. A working change is

$page = $article->getPage();
$rt = $page->getRedirectTarget();

Error when using graphical category browser

edit

Hi

I have just installed this extension. I found the installation a little difficult in that the location of the $xyDotPath and $xyCategoriesCache were not clearly stated.

But now I have that sorted, I am getting the following error:

[80cac35581a6a304ea58b979] /index.php/Special:Xygraphicalcategorybrowser Error from line 112 of D:\wamp64\www\jsp604\extensions\xyCategoryBrowser\xyAbstractCategoryGraph.php: Call to undefined method Article::getContent()

Backtrace:

#0 D:\wamp64\www\extensions\xyCategoryBrowser\xyCategoriesSpecialPage.php(52): xyAbstractCategoryGraph->doQuery()
#1 D:\wamp64\www\includes\specialpage\SpecialPage.php(522): xyCategoriesSpecialPage->execute(NULL)
#2 D:\wamp64\www\includes\specialpage\SpecialPageFactory.php(568): SpecialPage->run(NULL)
#3 D:\wamp64\www\includes\MediaWiki.php(288): SpecialPageFactory::executePath(Title, RequestContext)
#4 D:\wamp64\www\includes\MediaWiki.php(861): MediaWiki->performRequest()
#5 D:\wamp64\www\includes\MediaWiki.php(524): MediaWiki->main()
#6 D:\wamp64\www\index.php(42): MediaWiki->run()
#7 {main}

I am using a Windows Server 2012 r2 (not my idea).

Any ideas are appreciated.

Gary

--Squeak24 (talk) 15:33, 16 October 2018 (UTC)Reply

Return to "Graphical Category Browser" page.