// @(#)root/gui:$Name: $:$Id: TGFSContainer.cxx,v 1.10 2002/11/15 13:24:59 brun Exp $
// Author: Fons Rademakers 19/01/98
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
/**************************************************************************
This source is based on Xclass95, a Win95-looking GUI toolkit.
Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.
Xclass95 is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
**************************************************************************/
//////////////////////////////////////////////////////////////////////////
// //
// TGFileIcon, TGFileEntry, TGFSContainer //
// //
// Utility classes used by the file selection dialog (TGFSDialog). //
// //
//////////////////////////////////////////////////////////////////////////
#ifndef WIN32
#ifndef R__LYNXOS
#include <sys/stat.h>
#endif
#include <pwd.h>
#ifndef __VMS
#include <grp.h>
#endif
#endif
#ifdef GDK_WIN32
#include <sys/stat.h>
#endif
#include "TGFSContainer.h"
#include "TGPicture.h"
#include "TGMsgBox.h"
#include "TGMimeTypes.h"
#include "TRegexp.h"
#include "TList.h"
#include "TSystem.h"
ClassImp(TGFileContainer)
//______________________________________________________________________________
class TGFSFrameElement : public TGFrameElement {
public:
TGFileContainer *fContainer;
Bool_t IsSortable() const { return kTRUE; }
Int_t Compare(const TObject *obj) const;
};
//______________________________________________________________________________
Int_t TGFSFrameElement::Compare(const TObject *obj) const
{
// Sort frame elements in file selection list view container.
int type1, type2;
TGFileItem *f1 = (TGFileItem *) fFrame;
TGFileItem *f2 = (TGFileItem *) ((TGFrameElement *) obj)->fFrame;
switch (fContainer->fSortType) {
default:
case kSortByName:
return strcmp(f1->GetItemName()->GetString(), f2->GetItemName()->GetString());
case kSortByType:
//--- this is not exactly what I want...
type1 = f1->GetType();
type2 = f2->GetType();
//--- use posix macros
#ifndef WIN32
if (S_ISDIR(type1)) type1 = 1;
#if defined(S_IFLNK)
else if ((type1 & S_IFMT) == S_IFLNK) type1 = 2;
#endif
#if defined(S_IFSOCK)
else if ((type1 & S_IFMT) == S_IFSOCK) type1 = 3;
#endif
else if (S_ISFIFO(type1)) type1 = 4;
else if (S_ISREG(type1) && (type1 & S_IXUSR)) type1 = 5;
else type1 = 6;
if (S_ISDIR(type2)) type2 = 1;
#if defined(S_IFLNK)
else if ((type2 & S_IFMT) == S_IFLNK) type2 = 2;
#endif
#if defined(S_IFSOCK)
else if ((type2 & S_IFMT) == S_IFSOCK) type2 = 3;
#endif
else if (S_ISFIFO(type2)) type2 = 4;
else if (S_ISREG(type2) && (type2 & S_IXUSR)) type2 = 5;
else type2 = 6;
#else
#ifndef GDK_WIN32
Error("Compare", "not yet implemented for Win32");
#else
if (type1 & _S_IFDIR) type1 = 1;
else if ((type1 & _S_IFREG) && (type1 & S_IEXEC)) type1 = 5;
else type1 = 6;
if (type2 & _S_IFDIR) type2 = 1;
else if ((type2 & _S_IFREG) && (type2 & S_IEXEC)) type2 = 5;
else type2 = 6;
#endif
#endif
if (type1 < type2) return -1;
if (type1 > type2) return 1;
return strcmp(f1->GetItemName()->GetString(), f2->GetItemName()->GetString());
case kSortBySize:
if (f1->GetSize() < f2->GetSize()) return -1;
if (f1->GetSize() > f2->GetSize()) return 1;
return strcmp(f1->GetItemName()->GetString(), f2->GetItemName()->GetString());
}
}
//______________________________________________________________________________
Bool_t TViewUpdateTimer::Notify()
{
fContainer->HandleTimer(0);
Reset();
return kFALSE;
}
//______________________________________________________________________________
void TGFileIcon::DoRedraw()
{
// Draw icon.
TGIcon::DoRedraw();
if (fLpic) fLpic->Draw(fId, fgBckgndGC(), 0, 0);
}
//______________________________________________________________________________
TGFileItem::TGFileItem(const TGWindow *p,
const TGPicture *bpic, const TGPicture *blpic,
const TGPicture *spic, const TGPicture *slpic,
TGString *name, Int_t type, ULong_t size, Int_t uid,
Int_t gid, EListViewMode viewMode, UInt_t options,
ULong_t back) :
TGLVEntry(p, bpic, spic, name, 0, viewMode, options, back)
{
// Create a list view item.
char tmp[256];
ULong_t fsize, bsize;
fLcurrent =
fBlpic = blpic;
fSlpic = slpic;
fViewMode = (EListViewMode) -1;
SetViewMode(viewMode);
fType = type;
fSize = size;
fUid = uid;
fGid = gid;
// FIXME: hack...
fIsLink = (blpic != 0);
fSubnames = new TGString* [5];
#ifndef WIN32
// file type
sprintf(tmp, "%c%c%c%c%c%c%c%c%c%c",
(fIsLink ?
'l' :
(S_ISREG(type) ?
'-' :
(S_ISDIR(type) ?
'd' :
(S_ISCHR(type) ?
'c' :
(S_ISBLK(type) ?
'b' :
(S_ISFIFO(type) ?
'p' :
(S_ISSOCK(type) ?
's' : '?' ))))))),
((type & S_IRUSR) ? 'r' : '-'),
((type & S_IWUSR) ? 'w' : '-'),
((type & S_ISUID) ? 's' : ((type & S_IXUSR) ? 'x' : '-')),
((type & S_IRGRP) ? 'r' : '-'),
((type & S_IWGRP) ? 'w' : '-'),
((type & S_ISGID) ? 's' : ((type & S_IXGRP) ? 'x' : '-')),
((type & S_IROTH) ? 'r' : '-'),
((type & S_IWOTH) ? 'w' : '-'),
((type & S_ISVTX) ? 't' : ((type & S_IXOTH) ? 'x' : '-')));
fSubnames[0] = new TGString(tmp);
// file size
fsize = bsize = fSize;
if (fsize > 1024) {
fsize /= 1024;
if (fsize > 1024) {
// 3.7MB is more informative than just 3MB
sprintf(tmp, "%ld.%ldM", fsize/1024, (fsize%1024)/103);
} else {
sprintf(tmp, "%ld.%ldK", bsize/1024, (bsize%1024)/103);
}
} else {
sprintf(tmp, "%ld", bsize);
}
fSubnames[1] = new TGString(tmp);
#ifndef R__VMS
{
struct group *grp;
struct passwd *pwd;
char tmp[256];
pwd = getpwuid(fUid);
if (pwd) {
fSubnames[2] = new TGString(pwd->pw_name);
} else {
sprintf(tmp, "%d", fUid);
fSubnames[2] = new TGString(tmp);
}
grp = getgrgid(fGid);
if (grp) {
fSubnames[3] = new TGString(grp->gr_name);
} else {
sprintf(tmp, "%d", fGid);
fSubnames[3] = new TGString(tmp);
}
}
#else
//***NEED TO FIND A ROUTINE IN VMS THAT DOES THE SAME THING AS GETPWUID
#endif
fSubnames[4] = 0;
int i;
for (i = 0; fSubnames[i] != 0; ++i)
;
fCtw = new int[i];
for (i = 0; fSubnames[i] != 0; ++i)
fCtw[i] = gVirtualX->TextWidth(fFontStruct, fSubnames[i]->GetString(),
fSubnames[i]->GetLength());
#else
#ifndef GDK_WIN32
Error("TGFileItem", "not yet implemented for Win32");
#else
char *temp;
sprintf(tmp, "%c%c%c%c",
(fIsLink ?
'l' :
((type & _S_IFREG) ?
'-' :
((type & _S_IFDIR) ?
'd' : '?'))),
((type & _S_IREAD) ? 'r' : '-'),
((type & S_IWRITE) ? 'w' : '-'),
((type & S_IEXEC) ? 'x' : '-'));
fSubnames[0] = new TGString(tmp);
// file size
fsize = bsize = fSize;
if (fsize > 1024) {
fsize /= 1024;
if (fsize > 1024) {
// 3.7MB is more informative than just 3MB
sprintf(tmp, "%ld.%ldM", fsize/1024, (fsize%1024)/103);
} else {
sprintf(tmp, "%ld.%ldK", bsize/1024, (bsize%1024)/103);
}
} else {
sprintf(tmp, "%ld", bsize);
}
fSubnames[1] = new TGString(tmp);
if (temp = getenv("USERNAME"))
fSubnames[2] = new TGString(temp);
else
fSubnames[2] = new TGString("user");
fSubnames[3] = new TGString("group");
fSubnames[4] = 0;
int i;
for (i = 0; fSubnames[i] != 0; ++i)
;
fCtw = new int[i];
for (i = 0; fSubnames[i] != 0; ++i)
fCtw[i] = gVirtualX->TextWidth(fFontStruct, fSubnames[i]->GetString(),
fSubnames[i]->GetLength());
#endif
#endif
}
//______________________________________________________________________________
void TGFileItem::SetViewMode(EListViewMode viewMode)
{
// Set container item view mode.
TGLVEntry::SetViewMode(viewMode);
if (viewMode == kLVLargeIcons)
fLcurrent = fBlpic;
else
fLcurrent = fSlpic;
if (fClient) fClient->NeedRedraw(this);
}
//______________________________________________________________________________
void TGFileItem::DoRedraw()
{
// Draw list view container item.
int ix, iy;
TGLVEntry::DoRedraw();
if (!fLcurrent) return;
if (fViewMode == kLVLargeIcons) {
ix = (fWidth - fLcurrent->GetWidth()) >> 1;
iy = 0;
} else {
ix = 0;
iy = (fHeight - fLcurrent->GetHeight()) >> 1;
}
fLcurrent->Draw(fId, fNormGC, ix, iy);
}
//______________________________________________________________________________
TGFileContainer::TGFileContainer(const TGWindow *p, UInt_t w, UInt_t h,
UInt_t options, ULong_t back) :
TGLVContainer(p, w, h, options, back)
{
// Create a list view container which will hold the contents of
// the current directory.
fSortType = kSortByName;
fFilter = 0;
fDirectory = gSystem->WorkingDirectory();
fRefresh = new TViewUpdateTimer(this, 1000);
gSystem->AddTimer(fRefresh);
fFolder_s = fClient->GetPicture("folder_s.xpm");
fFolder_t = fClient->GetPicture("folder_t.xpm");
fApp_s = fClient->GetPicture("app_s.xpm");
fApp_t = fClient->GetPicture("app_t.xpm");
fDoc_s = fClient->GetPicture("doc_s.xpm");
fDoc_t = fClient->GetPicture("doc_t.xpm");
fSlink_s = fClient->GetPicture("slink_s.xpm");
fSlink_t = fClient->GetPicture("slink_t.xpm");
if (!fFolder_s || !fFolder_t ||
!fApp_s || !fApp_t ||
!fDoc_s || !fDoc_t ||
!fSlink_s || !fSlink_t)
Error("TGFileContainer", "required pixmap(s) missingn");
}
//______________________________________________________________________________
TGFileContainer::TGFileContainer(TGCanvas *p, UInt_t options, ULong_t back) :
TGLVContainer(p,options, back)
{
// Create a list view container which will hold the contents of
// the current directory.
fSortType = kSortByName;
fFilter = 0;
fDirectory = gSystem->WorkingDirectory();
fRefresh = new TViewUpdateTimer(this, 1000);
gSystem->AddTimer(fRefresh);
fFolder_s = fClient->GetPicture("folder_s.xpm");
fFolder_t = fClient->GetPicture("folder_t.xpm");
fApp_s = fClient->GetPicture("app_s.xpm");
fApp_t = fClient->GetPicture("app_t.xpm");
fDoc_s = fClient->GetPicture("doc_s.xpm");
fDoc_t = fClient->GetPicture("doc_t.xpm");
fSlink_s = fClient->GetPicture("slink_s.xpm");
fSlink_t = fClient->GetPicture("slink_t.xpm");
if (!fFolder_s || !fFolder_t ||
!fApp_s || !fApp_t ||
!fDoc_s || !fDoc_t ||
!fSlink_s || !fSlink_t)
Error("TGFileContainer", "required pixmap(s) missingn");
}
//______________________________________________________________________________
TGFileContainer::~TGFileContainer()
{
// Delete list view file container.
if (fRefresh) delete fRefresh;
if (fFilter) delete fFilter;
fClient->FreePicture(fFolder_s);
fClient->FreePicture(fFolder_t);
fClient->FreePicture(fApp_s);
fClient->FreePicture(fApp_t);
fClient->FreePicture(fDoc_s);
fClient->FreePicture(fDoc_t);
fClient->FreePicture(fSlink_s);
fClient->FreePicture(fSlink_t);
}
//______________________________________________________________________________
void TGFileContainer::AddFrame(TGFrame *f, TGLayoutHints *l)
{
// Add frame to the composite frame.
TGFSFrameElement *nw;
nw = new TGFSFrameElement;
nw->fFrame = f;
nw->fLayout = l ? l : fgDefaultHints;
nw->fState = 1;
nw->fContainer = this;
fList->Add(nw);
}
//______________________________________________________________________________
Bool_t TGFileContainer::HandleTimer(TTimer *)
{
// Refresh container contents. Check every 5 seconds to see if the
// directory modification date has changed.
#ifndef WIN32
struct stat sbuf;
if (stat(fDirectory.Data(), &sbuf) == 0)
if (fMtime != (ULong_t)sbuf.st_mtime) DisplayDirectory();
#else
#ifndef GDK_WIN32
Error("HandleTImer", "not yet implemented for Win32");
#else
struct stat sbuf;
if (stat(fDirectory.Data(), &sbuf) == 0)
if (fMtime != (ULong_t)sbuf.st_mtime) DisplayDirectory();
#endif
#endif
return kTRUE;
}
//______________________________________________________________________________
void TGFileContainer::SetFilter(const char *filter)
{
// Set file selection filter.
if (fFilter) delete fFilter;
fFilter = new TRegexp(filter, kTRUE);
}
//______________________________________________________________________________
void TGFileContainer::Sort(EFSSortMode sortType)
{
// Sort file system list view container according to sortType.
fSortType = sortType;
fList->Sort();
TGCanvas *canvas = (TGCanvas *) this->GetParent()->GetParent();
canvas->Layout();
}
//______________________________________________________________________________
void TGFileContainer::GetFilePictures(const TGPicture **pic,
const TGPicture **lpic, Int_t file_type, Bool_t is_link,
const char *name, Bool_t small)
{
// Determine the file picture for the given file type.
*pic = fClient->GetMimeTypeList()->GetIcon(name, small);
if (*pic == 0) {
*pic = small ? fDoc_t : fDoc_s;
#ifndef WIN32
if (S_ISREG(file_type) && (file_type) & S_IXUSR)
*pic = small ? fApp_t : fApp_s;
if (S_ISDIR(file_type))
*pic = small ? fFolder_t : fFolder_s;
#else
#ifndef GDK_WIN32
Error("GetFilePictures", "not yet implemented for Win32");
#else
if ((file_type & _S_IFREG) && (file_type & _S_IEXEC))
*pic = small ? fApp_t : fApp_s;
if (file_type & _S_IFDIR)
*pic = small ? fFolder_t : fFolder_s;
#endif
#endif
}
if (is_link)
*lpic = small ? fSlink_t : fSlink_s;
else
*lpic = 0;
}
//______________________________________________________________________________
void TGFileContainer::ChangeDirectory(const char *path)
{
// Change current directory.
TString savdir = gSystem->WorkingDirectory();
gSystem->ChangeDirectory(fDirectory.Data()); // so path of ".." will work
if (gSystem->ChangeDirectory(path)) {
fDirectory = gSystem->WorkingDirectory();
gSystem->ChangeDirectory(savdir.Data());
DisplayDirectory();
}
}
//______________________________________________________________________________
void TGFileContainer::DisplayDirectory()
{
// Display the contents of the current directory in the container.
// This can be used to refresh the contents of the window.
RemoveAll();
CreateFileList();
// This automatically calls layout
Sort(fSortType);
// Make TGExplorerMainFrame display total objects in status bar
SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_SELCHANGED),
fTotal, fSelected);
MapSubwindows();
}
//______________________________________________________________________________
void TGFileContainer::CreateFileList()
{
// This function creates the file list from current dir.
TString savdir = gSystem->WorkingDirectory();
if (!gSystem->ChangeDirectory(fDirectory.Data())) return;
#ifndef WIN32
struct stat sbuf;
if (stat(".", &sbuf) == 0) fMtime = sbuf.st_mtime;
#else
#ifndef GDK_WIN32
Error("CreateFileList", "not yet implemented for Win32");
return;
#else
struct stat sbuf;
if (stat(".", &sbuf) == 0) fMtime = sbuf.st_mtime;
#endif
#endif
void *dirp;
if ((dirp = gSystem->OpenDirectory(".")) == 0) {
gSystem->ChangeDirectory(savdir.Data());
return;
}
const char *name;
while ((name = gSystem->GetDirEntry(dirp)) != 0) {
if (strcmp(name, ".") && strcmp(name, ".."))
AddFile(name);
}
gSystem->FreeDirectory(dirp);
gSystem->ChangeDirectory(savdir.Data());
}
//______________________________________________________________________________
TGFileItem *TGFileContainer::AddFile(const char *name)
{
// Add file in container.
Bool_t is_link;
Int_t type, uid, gid;
ULong_t size;
TString filename;
TGFileItem *item = 0;
const TGPicture *pic, *lpic, *spic, *slpic;
#ifndef WIN32
struct stat sbuf;
#else
#ifndef GDK_WIN32
Error("AddFile", "not yet implemented for Win32");
return item;
#else
struct stat sbuf;
#endif
#endif
type = 0;
size = 0;
uid = 0;
gid = 0;
#ifndef WIN32
#ifndef R__VMS
is_link = kFALSE;
if (lstat(name, &sbuf) == 0) {
is_link = S_ISLNK(sbuf.st_mode);
type = sbuf.st_mode;
size = sbuf.st_size;
uid = sbuf.st_uid;
gid = sbuf.st_gid;
if (is_link) {
if (stat(name, &sbuf) == 0) {
type = sbuf.st_mode;
size = sbuf.st_size;
}
}
} else {
char msg[256];
sprintf(msg, "Can't read file attributes of \"%s\": %s.",
name, gSystem->GetError());
new TGMsgBox(fClient->GetRoot(), GetMainFrame(),
"Error", msg, kMBIconStop, kMBOk);
return item;
}
filename = name;
if (S_ISDIR(type) || fFilter == 0 ||
(fFilter && filename.Index(*fFilter) != kNPOS)) {
GetFilePictures(&pic, &lpic, type, is_link, name, kFALSE);
GetFilePictures(&spic, &slpic, type, is_link, name, kTRUE);
item = new TGFileItem(this, pic, lpic, spic, slpic, new TGString(name),
type, size, uid, gid, fViewMode);
AddItem(item);
fTotal++;
}
#endif
#else
#ifdef GDK_WIN32
is_link = kFALSE;
if (stat(name, &sbuf) == 0) {
is_link = kFALSE;
type = sbuf.st_mode;
size = sbuf.st_size;
uid = sbuf.st_uid;
gid = sbuf.st_gid;
if (is_link) {
if (stat(name, &sbuf) == 0) {
type = sbuf.st_mode;
size = sbuf.st_size;
}
}
} else {
char msg[256];
sprintf(msg, "Can't read file attributes of \"%s\": %s.",
name, gSystem->GetError());
new TGMsgBox(fClient->GetRoot(), GetMainFrame(),
"Error", msg, kMBIconStop, kMBOk);
return item;
}
filename = name;
if ((type & _S_IFDIR) || fFilter == 0 ||
(fFilter && filename.Index(*fFilter) != kNPOS)) {
GetFilePictures(&pic, &lpic, type, is_link, name, kFALSE);
GetFilePictures(&spic, &slpic, type, is_link, name, kTRUE);
item = new TGFileItem(this, pic, lpic, spic, slpic, new TGString(name),
type, size, uid, gid, fViewMode);
AddItem(item);
fTotal++;
}
#endif
#endif
return item;
}
ROOT page - Class index - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.