47 ClassImp(TGFileContainer);
49 class TViewUpdateTimer :
public TTimer {
52 TGFileContainer *fContainer;
55 TViewUpdateTimer(TGFileContainer *t, Long_t ms) : TTimer(ms, kTRUE) { fContainer = t; }
61 class TGFileIcon :
public TGIcon {
64 const TGPicture *fLpic;
66 virtual void DoRedraw();
69 TGFileIcon(
const TGWindow *p,
const TGPicture *pic,
const TGPicture *lpic,
70 UInt_t options = kChildFrame, Pixel_t back = GetWhitePixel()) :
71 TGIcon(p, pic, 0, 0, options, back) { fLpic = lpic; }
78 class TGFSFrameElement :
public TGFrameElement {
80 TGFileContainer *fContainer;
82 Bool_t IsSortable()
const {
return kTRUE; }
83 Int_t Compare(
const TObject *obj)
const;
89 Int_t TGFSFrameElement::Compare(
const TObject *obj)
const
93 TGFileItem *f1 = (TGFileItem *) fFrame;
94 TGFileItem *f2 = (TGFileItem *) ((TGFrameElement *) obj)->fFrame;
96 switch (fContainer->fSortType) {
100 type1 = f1->GetType();
101 type2 = f2->GetType();
104 if (R_ISDIR(type1)) type1 = 1;
107 if (R_ISDIR(type2)) type2 = 1;
110 if (type1 < type2)
return -1;
111 if (type1 > type2)
return 1;
112 return strcmp(f1->GetItemName()->GetString(),
113 f2->GetItemName()->GetString());
116 if (f1->GetUid() != f2->GetUid()) {
117 if (f1->GetUid() < f2->GetUid())
124 type1 = f1->GetType();
125 type2 = f2->GetType();
128 if (R_ISDIR(type1)) type1 = 1;
131 if (R_ISDIR(type2)) type2 = 1;
134 if (type1 < type2)
return -1;
135 if (type1 > type2)
return 1;
136 return strcmp(f1->GetItemName()->GetString(),
137 f2->GetItemName()->GetString());
140 if (f1->GetGid() != f2->GetGid()) {
141 if (f1->GetGid() < f2->GetGid())
148 type1 = f1->GetType();
149 type2 = f2->GetType();
152 if (R_ISDIR(type1)) type1 = 1;
155 if (R_ISDIR(type2)) type2 = 1;
158 if (type1 < type2)
return -1;
159 if (type1 > type2)
return 1;
160 return strcmp(f1->GetItemName()->GetString(),
161 f2->GetItemName()->GetString());
166 type1 = f1->GetType();
167 type2 = f2->GetType();
171 if (R_ISDIR(type1)) type1 = 1;
172 else if (R_ISLNK(type1)) type1 = 2;
173 else if (R_ISSOCK(type1)) type1 = 3;
174 else if (R_ISFIFO(type1)) type1 = 4;
175 else if (R_ISREG(type1) && (type1 & kS_IXUSR)) type1 = 5;
178 if (R_ISDIR(type2)) type2 = 1;
179 else if (R_ISLNK(type2)) type2 = 2;
180 else if (R_ISSOCK(type2)) type2 = 3;
181 else if (R_ISFIFO(type2)) type2 = 4;
182 else if (R_ISREG(type2) && (type2 & kS_IXUSR)) type2 = 5;
185 if (type1 < type2)
return -1;
186 if (type1 > type2)
return 1;
187 return strcmp(f1->GetItemName()->GetString(),
188 f2->GetItemName()->GetString());
191 if (f1->GetSize() < f2->GetSize())
return -1;
192 if (f1->GetSize() > f2->GetSize())
return 1;
193 return strcmp(f1->GetItemName()->GetString(),
194 f2->GetItemName()->GetString());
197 time_t loctimeF1 = (time_t) f1->GetModTime();
199 struct tm tmF1 = *localtime(&loctimeF1);
201 time_t loctimeF2 = (time_t) f2->GetModTime();
203 struct tm tmF2 = *localtime(&loctimeF2);
205 if ( tmF1.tm_year != tmF2.tm_year )
206 return (tmF1.tm_year < tmF2.tm_year) ? +1 : -1;
207 else if ( tmF1.tm_mon != tmF2.tm_mon )
208 return (tmF1.tm_mon < tmF2.tm_mon) ? +1 : -1;
209 else if ( tmF1.tm_mday != tmF2.tm_mday )
210 return (tmF1.tm_mday < tmF2.tm_mday) ? +1 : -1;
211 else if ( tmF1.tm_hour != tmF2.tm_hour )
212 return (tmF1.tm_hour < tmF2.tm_hour) ? +1 : -1;
213 else if ( tmF1.tm_min != tmF2.tm_min )
214 return (tmF1.tm_min < tmF2.tm_min) ? +1 : -1;
215 else if ( tmF1.tm_sec != tmF2.tm_sec )
216 return (tmF1.tm_sec < tmF2.tm_sec) ? +1 : -1;
226 Bool_t TViewUpdateTimer::Notify()
228 fContainer->HandleTimer(0);
237 void TGFileIcon::DoRedraw()
240 if (fLpic) fLpic->Draw(fId, GetBckgndGC()(), 0, 0);
247 TGFileItem::TGFileItem(
const TGWindow *p,
248 const TGPicture *bpic,
const TGPicture *blpic,
249 const TGPicture *spic,
const TGPicture *slpic,
250 TGString *name, Int_t type, Long64_t size, Int_t uid,
251 Int_t gid, Long_t modtime, EListViewMode viewMode,
252 UInt_t options, ULong_t back) :
253 TGLVEntry(p, bpic, spic, name, 0, viewMode, options, back)
261 buf.fMtime = modtime;
262 buf.fIsLink = (blpic != 0);
264 Init(blpic, slpic, buf, viewMode);
270 TGFileItem::TGFileItem(
const TGWindow *p,
271 const TGPicture *bpic,
const TGPicture *blpic,
272 const TGPicture *spic,
const TGPicture *slpic,
273 TGString *name, FileStat_t &stat, EListViewMode viewMode,
274 UInt_t options, ULong_t back) :
275 TGLVEntry(p, bpic, spic, name, 0, viewMode, options, back)
277 Init(blpic, slpic, stat, viewMode);
283 void TGFileItem::Init(
const TGPicture *blpic,
const TGPicture *slpic,
284 FileStat_t &stat, EListViewMode viewMode)
287 Long64_t fsize, bsize;
291 fDNDData.fDataLength = 0;
292 fDNDData.fDataType = 0;
297 fViewMode = (EListViewMode) -1;
298 SetViewMode(viewMode);
304 fModTime = stat.fMtime;
305 fIsLink = stat.fIsLink;
307 fSubnames =
new TGString* [6];
310 snprintf(tmp,
sizeof(tmp),
"%c%c%c%c%c%c%c%c%c%c",
325 ((fType & kS_IRUSR) ?
'r' :
'-'),
326 ((fType & kS_IWUSR) ?
'w' :
'-'),
327 ((fType & kS_ISUID) ?
's' : ((fType & kS_IXUSR) ?
'x' :
'-')),
328 ((fType & kS_IRGRP) ?
'r' :
'-'),
329 ((fType & kS_IWGRP) ?
'w' :
'-'),
330 ((fType & kS_ISGID) ?
's' : ((fType & kS_IXGRP) ?
'x' :
'-')),
331 ((fType & kS_IROTH) ?
'r' :
'-'),
332 ((fType & kS_IWOTH) ?
'w' :
'-'),
333 ((fType & kS_ISVTX) ?
't' : ((fType & kS_IXOTH) ?
'x' :
'-')));
334 fSubnames[0] =
new TGString(tmp);
337 fsize = bsize = fSize;
342 snprintf(tmp,
sizeof(tmp),
"%lld.%lldM", fsize/1024, (fsize%1024)/103);
344 snprintf(tmp,
sizeof(tmp),
"%lld.%lldK", bsize/1024, (bsize%1024)/103);
347 snprintf(tmp,
sizeof(tmp),
"%lld", bsize);
349 fSubnames[1] =
new TGString(tmp);
352 struct UserGroup_t *user_group;
354 user_group = gSystem->GetUserInfo(fUid);
356 fSubnames[2] =
new TGString(user_group->fUser);
357 fSubnames[3] =
new TGString(user_group->fGroup);
360 fSubnames[2] =
new TGString(TString::Format(
"%d", fUid));
361 fSubnames[3] =
new TGString(TString::Format(
"%d", fGid));
366 time_t loctime = (time_t) fModTime;
367 newtime = localtime(&loctime);
369 snprintf(tmp,
sizeof(tmp),
"%d-%02d-%02d %02d:%02d", newtime->tm_year + 1900,
370 newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour,
372 fSubnames[4] =
new TGString(tmp);
375 fSubnames[4] =
new TGString(
"1901-01-01 00:00");
380 for (i = 0; fSubnames[i] != 0; ++i)
384 for (i = 0; fSubnames[i] != 0; ++i)
385 fCtw[i] = gVirtualX->TextWidth(fFontStruct, fSubnames[i]->GetString(),
386 fSubnames[i]->GetLength());
394 TGFileItem::~TGFileItem()
402 void TGFileItem::SetViewMode(EListViewMode viewMode)
404 TGLVEntry::SetViewMode(viewMode);
406 if (viewMode == kLVLargeIcons)
411 if (fClient) fClient->NeedRedraw(
this);
417 void TGFileItem::DoRedraw()
421 TGLVEntry::DoRedraw();
422 if (!fLcurrent)
return;
424 if (fViewMode == kLVLargeIcons) {
425 ix = (fWidth - fLcurrent->GetWidth()) >> 1;
429 iy = (fHeight - fLcurrent->GetHeight()) >> 1;
432 fLcurrent->Draw(fId, fNormGC, ix, iy);
440 TGFileContainer::TGFileContainer(
const TGWindow *p, UInt_t w, UInt_t h,
441 UInt_t options, ULong_t back) :
442 TGLVContainer(p, w, h, options, back)
444 fSortType = kSortByName;
447 fDirectory = gSystem->WorkingDirectory();
448 fRefresh =
new TViewUpdateTimer(
this, 1000);
449 gSystem->AddTimer(fRefresh);
450 fCachePictures = kTRUE;
451 fDisplayStat = kTRUE;
452 fCleanups =
new TList;
454 fFolder_s = fClient->GetPicture(
"folder_s.xpm");
455 fFolder_t = fClient->GetPicture(
"folder_t.xpm");
456 fApp_s = fClient->GetPicture(
"app_s.xpm");
457 fApp_t = fClient->GetPicture(
"app_t.xpm");
458 fDoc_s = fClient->GetPicture(
"doc_s.xpm");
459 fDoc_t = fClient->GetPicture(
"doc_t.xpm");
460 fSlink_s = fClient->GetPicture(
"slink_s.xpm");
461 fSlink_t = fClient->GetPicture(
"slink_t.xpm");
463 if (!fFolder_s || !fFolder_t ||
464 !fApp_s || !fApp_t ||
465 !fDoc_s || !fDoc_t ||
466 !fSlink_s || !fSlink_t)
467 Error(
"TGFileContainer",
"required pixmap(s) missing\n");
476 TGFileContainer::TGFileContainer(TGCanvas *p, UInt_t options, ULong_t back) :
477 TGLVContainer(p,options, back)
479 fSortType = kSortByName;
482 fDirectory = gSystem->WorkingDirectory();
483 fRefresh =
new TViewUpdateTimer(
this, 1000);
484 gSystem->AddTimer(fRefresh);
485 fCachePictures = kTRUE;
486 fDisplayStat = kTRUE;
487 fCleanups =
new TList;
489 fFolder_s = fClient->GetPicture(
"folder_s.xpm");
490 fFolder_t = fClient->GetPicture(
"folder_t.xpm");
491 fApp_s = fClient->GetPicture(
"app_s.xpm");
492 fApp_t = fClient->GetPicture(
"app_t.xpm");
493 fDoc_s = fClient->GetPicture(
"doc_s.xpm");
494 fDoc_t = fClient->GetPicture(
"doc_t.xpm");
495 fSlink_s = fClient->GetPicture(
"slink_s.xpm");
496 fSlink_t = fClient->GetPicture(
"slink_t.xpm");
498 if (!fFolder_s || !fFolder_t ||
499 !fApp_s || !fApp_t ||
500 !fDoc_s || !fDoc_t ||
501 !fSlink_s || !fSlink_t)
502 Error(
"TGFileContainer",
"required pixmap(s) missing\n");
510 TGFileContainer::~TGFileContainer()
512 if (fRefresh)
delete fRefresh;
513 if (fFilter)
delete fFilter;
514 fClient->FreePicture(fFolder_s);
515 fClient->FreePicture(fFolder_t);
516 fClient->FreePicture(fApp_s);
517 fClient->FreePicture(fApp_t);
518 fClient->FreePicture(fDoc_s);
519 fClient->FreePicture(fDoc_t);
520 fClient->FreePicture(fSlink_s);
521 fClient->FreePicture(fSlink_t);
524 TIter nextp(fCleanups);
525 while ((pic = (TGPicture *)nextp())) {
526 fClient->GetPicturePool()->FreePicture(pic);
536 void TGFileContainer::AddFrame(TGFrame *f, TGLayoutHints *l)
538 TGFSFrameElement *nw;
540 nw =
new TGFSFrameElement;
542 nw->fLayout = l ? l : fgDefaultHints;
544 nw->fContainer =
this;
552 Bool_t TGFileContainer::HandleTimer(TTimer *)
556 if (gSystem->GetPathInfo(fDirectory, sbuf) == 0)
557 if (fMtime != (ULong_t)sbuf.fMtime) DisplayDirectory();
565 void TGFileContainer::SetFilter(
const char *filter)
567 if (fFilter)
delete fFilter;
568 fFilter =
new TRegexp(filter, kTRUE);
574 void TGFileContainer::Sort(EFSSortMode sortType)
576 fSortType = sortType;
580 TGCanvas *canvas = (TGCanvas *) this->GetParent()->GetParent();
587 void TGFileContainer::GetFilePictures(
const TGPicture **pic,
588 const TGPicture **lpic, Int_t file_type, Bool_t is_link,
589 const char *name, Bool_t )
591 static TString cached_ext;
592 static const TGPicture *cached_spic = 0;
593 static const TGPicture *cached_lpic = 0;
594 const char *ext = name ? strrchr(name,
'.') : 0;
598 if (fCachePictures && ext && cached_spic && cached_lpic && (cached_ext == ext)) {
601 if (!is_link)
return;
604 if (R_ISREG(file_type)) {
606 if (is_link && fname.EndsWith(
".lnk")) {
607 fname.Remove(fname.Length()-4);
609 *pic = fClient->GetMimeTypeList()->GetIcon(fname.Data(), kTRUE);
610 *lpic = fClient->GetMimeTypeList()->GetIcon(fname.Data(), kFALSE);
613 if (!*lpic) *lpic = *pic;
618 if (!is_link)
return;
629 if (R_ISREG(file_type) && (file_type) & kS_IXUSR) {
633 if (R_ISDIR(file_type)) {
642 img1 = TImage::Create();
644 img1->SetImage(((
const TGPicture *)*pic)->GetPicture(),
645 ((
const TGPicture *)*pic)->GetMask());
646 img2 = TImage::Open(
"slink_t.xpm");
647 if (img2) img1->Merge(img2);
648 lnk_name = ((
const TGPicture *)*pic)->GetName();
649 lnk_name.Prepend(
"lnk_");
650 *pic = fClient->GetPicturePool()->GetPicture(lnk_name.Data(),
651 img1->GetPixmap(), img1->GetMask());
652 fCleanups->Add(((TObject *)*pic));
653 if (img2)
delete img2;
656 img1 = TImage::Create();
658 img1->SetImage(((
const TGPicture *)*lpic)->GetPicture(),
659 ((
const TGPicture *)*lpic)->GetMask());
660 img2 = TImage::Open(
"slink_s.xpm");
661 if (img2) img1->Merge(img2);
662 lnk_name = ((
const TGPicture *)*lpic)->GetName();
663 lnk_name.Prepend(
"lnk_");
664 *lpic = fClient->GetPicturePool()->GetPicture(lnk_name.Data(),
665 img1->GetPixmap(), img1->GetMask());
666 fCleanups->Add(((TObject *)*lpic));
667 if (img2)
delete img2;
685 void TGFileContainer::ChangeDirectory(
const char *path)
687 TString savdir = gSystem->WorkingDirectory();
688 gSystem->ChangeDirectory(fDirectory.Data());
689 char *exppath = gSystem->ExpandPathName(path);
690 if (gSystem->ChangeDirectory(exppath)) {
691 fDirectory = gSystem->WorkingDirectory();
692 gSystem->ChangeDirectory(savdir.Data());
702 void TGFileContainer::DisplayDirectory()
711 SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_SELCHANGED),
720 void TGFileContainer::CreateFileList()
722 TString savdir = gSystem->WorkingDirectory();
723 if (!gSystem->ChangeDirectory(fDirectory.Data()))
return;
726 if (gSystem->GetPathInfo(
".", sbuf) == 0)
727 fMtime = sbuf.fMtime;
730 if ((dirp = gSystem->OpenDirectory(
".")) == 0) {
731 gSystem->ChangeDirectory(savdir.Data());
736 while ((name = gSystem->GetDirEntry(dirp)) != 0 && fDisplayStat) {
737 if (strcmp(name,
".") && strcmp(name,
".."))
739 gSystem->ProcessEvents();
741 gSystem->FreeDirectory(dirp);
743 gSystem->ChangeDirectory(savdir.Data());
749 TGFileItem *TGFileContainer::AddFile(
const char *name,
const TGPicture *ipic,
750 const TGPicture *ilpic)
753 TGFileItem *item = 0;
754 const TGPicture *spic, *slpic;
755 TGPicture *pic, *lpic;
759 if (gSystem->GetPathInfo(name, sbuf)) {
761 Info(
"AddFile",
"Broken symlink of %s.", name);
764 msg.Form(
"Can't read file attributes of \"%s\": %s.",
765 name, gSystem->GetError());
766 new TGMsgBox(fClient->GetDefaultRoot(), GetMainFrame(),
767 "Error", msg.Data(), kMBIconStop, kMBOk);
773 if (R_ISDIR(sbuf.fMode) || fFilter == 0 ||
774 (fFilter && filename.Index(*fFilter) != kNPOS)) {
780 GetFilePictures(&spic, &slpic, sbuf.fMode, sbuf.fIsLink, name, kTRUE);
783 pic = (TGPicture*)spic; pic->AddReference();
784 lpic = (TGPicture*)slpic; lpic->AddReference();
786 item =
new TGFileItem(
this, lpic, slpic, spic, pic,
787 new TGString(gSystem->BaseName(name)),
798 TGFileItem *TGFileContainer::AddRemoteFile(TObject *obj,
const TGPicture *ipic,
799 const TGPicture *ilpic)
802 TGFileItem *item = 0;
803 const TGPicture *spic, *slpic;
804 TGPicture *pic, *lpic;
808 TRemoteObject *robj = (TRemoteObject *)obj;
810 robj->GetFileStat(&sbuf);
811 filename = robj->GetName();
813 if (R_ISDIR(sbuf.fMode) || fFilter == 0 ||
814 (fFilter && filename.Index(*fFilter) != kNPOS)) {
820 GetFilePictures(&spic, &slpic, sbuf.fMode, sbuf.fIsLink, filename, kTRUE);
823 pic = (TGPicture*)spic; pic->AddReference();
824 lpic = (TGPicture*)slpic; lpic->AddReference();
826 item =
new TGFileItem(
this, lpic, slpic, spic, pic,
new TGString(filename),
836 void TGFileContainer::StopRefreshTimer()
838 if (fRefresh)
delete fRefresh;
845 void TGFileContainer::StartRefreshTimer(ULong_t msec)
847 fRefresh =
new TViewUpdateTimer(
this, msec);
848 gSystem->AddTimer(fRefresh);
854 void TGFileContainer::SavePrimitive(std::ostream &out, Option_t *option )
856 if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
859 out << std::endl <<
" // container frame" << std::endl;
860 out <<
" TGFileContainer *";
862 if ((fParent->GetParent())->InheritsFrom(TGCanvas::Class())) {
863 out << GetName() <<
" = new TGFileContainer(" << GetCanvas()->GetName();
865 out << GetName() <<
" = new TGFileContainer(" << fParent->GetName();
866 out <<
"," << GetWidth() <<
"," << GetHeight();
869 if (fBackground == GetDefaultFrameBackground()) {
870 if (GetOptions() == kSunkenFrame) {
871 out <<
");" << std::endl;
873 out <<
"," << GetOptionString() <<
");" << std::endl;
876 out <<
"," << GetOptionString() <<
",ucolor);" << std::endl;
878 if (option && strstr(option,
"keep_names"))
879 out <<
" " << GetName() <<
"->SetName(\"" << GetName() <<
"\");" << std::endl;
880 out <<
" " << GetCanvas()->GetName() <<
"->SetContainer("
881 << GetName() <<
");" << std::endl;
882 out <<
" " << GetName() <<
"->DisplayDirectory();" << std::endl;
883 out <<
" " << GetName() <<
"->AddFile("<< quote <<
".." << quote <<
");" << std::endl;
884 out <<
" " << GetName() <<
"->StopRefreshTimer();" << std::endl;