1 // Copyright (C) 2017-2020 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony GEAY (EDF R&D)
21 #include "QRemoteFileBrowser.h"
22 #include "QMachineBrowser.h"
23 #include "QRemoteCopyWidget.h"
26 #include "QFileSystemModel"
27 #include "QVBoxLayout"
30 #include "QMouseEvent"
31 #include "QApplication"
36 #include "QMessageBox"
40 class DirDataStructure;
42 void ListOfDir(DirDataStructure *parent);
44 QRemoteFileBrowser::QRemoteFileBrowser(QWidget *parent):QWidget(parent),_treeView(nullptr),_mb(nullptr)
46 _treeView=new AnotherTreeView(this);
47 QVBoxLayout *lay(new QVBoxLayout(this));
48 _mb=new QMachineBrowser(this);
50 lay->addWidget(_treeView);
51 connect(_mb,SIGNAL(locationChanged()),this,SLOT(onLocationChanged()));
52 connect(_treeView,SIGNAL(modelHasBeenGeneratedSignal(bool)),this,SLOT(locationHasBeenChanged()));
53 connect(_treeView,SIGNAL(somethingChangedDueToFileModif()),this,SLOT(onLocationChanged()));
57 void LoadingThread::run()
59 //std::cout << "start" << std::endl;
60 FileLoader *fl(_mb->generateFileLoader());
61 TopDirDataStructure *fds(new TopDirDataStructure(nullptr,fl));//costly
62 fds->moveToThread(_fatherThread);
63 emit this->letsGenerateModel(fds);
64 //std::cout << "end" << std::endl;
67 void QRemoteFileBrowser::onLocationChanged()
69 _mb->setEnabled(false);
70 _treeView->generateModel(_mb);
73 void QRemoteFileBrowser::locationHasBeenChanged()
75 _mb->setEnabled(true);
78 QRemoteFileTransfer::QRemoteFileTransfer(QWidget *parent):QWidget(parent),_left(nullptr),_right(nullptr)
80 QHBoxLayout *lay(new QHBoxLayout(this));
81 _left=new QRemoteFileBrowser(this);
82 _right=new QRemoteFileBrowser(this);
83 lay->addWidget(_left);
84 lay->addWidget(_right);
87 QString DataStructure::name() const
93 void DataStructure::removeFileArgs(QString& prg, QStringList& args) const
95 const TopDirDataStructure *root(getRoot());
96 root->removeFileArgsImpl(fullName(),prg,args);
99 QString DataStructure::entryForRSyncSrc() const
101 const TopDirDataStructure *root(getRoot());
102 return root->entryForRSync(fullName());
105 QString FileDataStructure::entryForRSyncDest() const
107 const TopDirDataStructure *root(getRoot());
108 return root->entryForRSync(getDirParent()->fullName());
111 QString DirDataStructure::entryForRSyncDest() const
113 const TopDirDataStructure *root(getRoot());
114 return root->entryForRSync(fullName());
119 const TopDirDataStructure *DataStructure::getRoot() const
122 return dynamic_cast<const TopDirDataStructure *>(this);
123 const DataStructure *work(this);
124 const DataStructure *ret(work->getDirParent());
128 return dynamic_cast<const TopDirDataStructure *>(ret);
130 ret=ret->getDirParent();
134 std::vector<const DataStructure *> DataStructure::getItermediateElts(const TopDirDataStructure *tpds) const
136 std::vector<const DataStructure *> ret;
139 const DataStructure *work(this);
140 const DataStructure *cand(work->getDirParent());
147 cand=cand->getDirParent();
151 void LocalFileLoader::fillArgs(const QString& dn, QString& prg, QStringList& args) const
153 prg="ls"; args << "-l" << dn;
156 QString LocalFileLoader::prettyPrint() const
158 return QString("Browsing %1 local directory").arg(getDirName());
161 QString LocalFileLoader::entryForRSync(const QString& fn) const
166 QString LocalFileLoader::getMachine() const
168 return QString("localhost");
171 void LocalFileLoader::removeFileArgs(const QString& filePath, QString& prg, QStringList& args) const
174 args << "-rf" << filePath;
177 void RemoteFileLoader::fillArgs(const QString& dn, QString& prg, QStringList& args) const
179 // find non hidden file recursive. If dn does not exist propagate the error status
180 prg="ssh"; args << _machine << QString("find %1 -maxdepth 1 -regextype egrep -regex '%1/[^\\.].*' | xargs ls -l ; test ${PIPESTATUS[0]} -eq 0").arg(dn);
183 QString RemoteFileLoader::prettyPrint() const
185 return QString("Browsing files in %1 on %2").arg(getDirName()).arg(_machine);
188 QString RemoteFileLoader::entryForRSync(const QString& fn) const
190 return QString("%1:%2").arg(_machine).arg(fn);
193 QString RemoteFileLoader::getMachine() const
198 void RemoteFileLoader::removeFileArgs(const QString& filePath, QString& prg, QStringList& args) const
201 args << _machine << "rm" << "-rf" << filePath;
204 bool LocalFileLoader::load(DirDataStructure *parent) const
206 QProcess *proc(new QProcess);
210 fillArgs(parent->fullName(),prg,args);
212 proc->start(prg,args);
213 static const int timeEllapse(3000);
214 if(!proc->waitForFinished(timeEllapse))
216 if(proc->exitCode()!=0)
218 QByteArray arr(proc->readAll());
220 QList<QByteArray> sarr(arr.split('\n'));
222 QRegularExpression re1("\\s+");
223 QRegularExpression re2("^(d|-)(r|-)(w|-)(x|-)(r|-)(w|-)(x|-)(r|-)(w|-)(x|-)$");
224 foreach(QByteArray arr0,sarr)
226 bool specialCase(ii==0 || ii==sarr.size()-1);
230 QStringList arr1(QString(arr0).split(re1));
233 QRegularExpressionMatch match(re2.match(arr1[0]));
234 if(!match.hasMatch())
236 QDir qd(parent->fullName());
237 if(match.captured(1)=="d")
238 new DirDataStructure(parent,qd.absoluteFilePath(arr1[8]));
239 if(match.captured(1)=="-")
240 new FileDataStructure(parent,qd.absoluteFilePath(arr1[8]));
245 void readStdPart(DirDataStructure *parent, const QList<QByteArray>& arrs, int startLine, int endLine)
247 QRegularExpression re1("\\s+");
248 QRegularExpression re2("^(d|-)(r|-)(w|-)(x|-)(r|-)(w|-)(x|-)(r|-)(w|-)(x|-)$");
249 for(int i=startLine;i<endLine;i++)
251 const QByteArray& arr0(arrs[i]);
252 QStringList arr1(QString(arr0).split(re1));
255 QRegularExpressionMatch match(re2.match(arr1[0]));
256 if(!match.hasMatch())
258 QDir qd(parent->fullName());
259 if(match.captured(1)=="d")
261 //std::cout << "Dir " << qd.absoluteFilePath(arr1[8]) << std::endl;
262 new DirDataStructure(parent,qd.absoluteFilePath(arr1[8]));
264 if(match.captured(1)=="-")
266 //std::cout << "File " << qd.absoluteFilePath(arr1[8]) << std::endl;
267 new FileDataStructure(parent,qd.absoluteFilePath(arr1[8]));
270 parent->markAsLoaded();
273 bool RemoteFileLoader::load(DirDataStructure *parent) const
275 QProcess *proc(new QProcess);
278 fillArgs(parent->fullName(),prg,args);
279 proc->start(prg,args);
280 static const int timeEllapse(3000);
281 if(!proc->waitForFinished(timeEllapse))
283 if(proc->exitCode()!=0)
285 QByteArray arr(proc->readAll());
287 QList<QByteArray> sarr(arr.split('\n'));
290 int sz(sarr.size()),ii(0);
291 std::vector<int> sections(1,0);
292 foreach(QByteArray arr0,sarr)
296 sections.push_back(ii);
299 QRegularExpression re3("^total ([0-9]+)$");
300 std::size_t nbSections(sections.size()-1);
301 for(std::size_t isec=0;isec<nbSections;isec++)
303 int startLine(sections[isec]),endLine(sections[isec+1]);
304 if(startLine==endLine)
306 QString firstLine(sarr[startLine]);
307 if(firstLine.size()!=0)
309 readStdPart(parent,sarr,startLine,endLine);
312 if(endLine-startLine<3)
314 QString almostDn(sarr[startLine+1]);
315 QRegularExpression re4(QString("%1%2(.+\\:)$").arg(parent->fullName()).arg(QDir::separator()));
316 QRegularExpressionMatch m4(re4.match(almostDn));
319 QString dn(almostDn.mid(0,almostDn.size()-1));
320 DirDataStructure *subParent(new DirDataStructure(parent,dn));
321 QString total(sarr[startLine+2]);
322 QRegularExpressionMatch m3(re3.match(total));
325 readStdPart(subParent,sarr,startLine+3,endLine);
328 const QObjectList &cs(parent->children());
329 std::map< QString, QObject *> sorter;
330 foreach(QObject *child,cs)
332 DataStructure *child2(qobject_cast<DataStructure *>(child));
335 sorter[child2->name()]=child2;
336 child2->setParent(nullptr);
338 for(std::map< QString, QObject *>::const_iterator it=sorter.begin();it!=sorter.end();it++)
339 (*it).second->setParent(parent);
343 bool DirDataStructure::load() const
348 ret=getRoot()->getLoader()->load(const_cast<DirDataStructure *>(this));
354 TopDirDataStructure::TopDirDataStructure(QObject *dds, FileLoader *fl):DirDataStructure(dds,fl->getDirName()),_fl(fl),_isOK(true)
360 TopDirDataStructure::~TopDirDataStructure()
365 QString TopDirDataStructure::entryForRSync(const QString& fn) const
367 return _fl->entryForRSync(fn);
370 QString TopDirDataStructure::getMachine() const
372 return _fl->getMachine();
375 void TopDirDataStructure::removeFileArgsImpl(const QString& filePath, QString& prg, QStringList& args) const
377 _fl->removeFileArgs(filePath,prg,args);
380 const DirDataStructure *DataStructure::getDirParent() const
382 const QObject *p(parent());
385 const DirDataStructure *ret(dynamic_cast<const DirDataStructure *>(p));
389 int DirDataStructure::posOf(const DataStructure *ds) const
392 return children().indexOf(const_cast<DataStructure *>(ds));
395 const DataStructure *DirDataStructure::operator[](int pos) const
398 const QObject *obj(children()[pos]);
399 const DataStructure *obj2(dynamic_cast<const DataStructure *>(obj));
403 FileDataStructure::FileDataStructure(DirDataStructure *dds, const QString& name):DataStructure(dds,name)
407 QString FileDataStructure::nameOnDrop() const
409 const DirDataStructure *ds3(getDirParent());
410 return QString("Dir %1 (%2)").arg(ds3->name()).arg(name());
413 void QRemoteFileSystemModel::emitResetModel()
415 emit this->beginResetModel();
416 emit this->endResetModel();
419 QRemoteFileSystemModel::QRemoteFileSystemModel(QObject *parent, FileLoader *fl):QAbstractItemModel(parent),_fds(nullptr)
421 _fds=new TopDirDataStructure(this,fl);
424 QRemoteFileSystemModel::QRemoteFileSystemModel(QObject *parent, TopDirDataStructure *fds):QAbstractItemModel(parent),_fds(fds)
427 _fds->setParent(this);
430 QVariant QRemoteFileSystemModel::headerData(int section, Qt::Orientation orientation, int role) const
432 if(role == Qt::DisplayRole || role == Qt::EditRole)
435 return _fds->getLoader()->prettyPrint();
437 return QAbstractItemModel::headerData(section,orientation,role);
440 QModelIndex QRemoteFileSystemModel::parent(const QModelIndex& child) const
443 return QModelIndex();
444 quintptr pt(child.internalId());
445 DataStructure *ds(reinterpret_cast<DataStructure *>(pt));
447 return QModelIndex();
449 return QModelIndex();
450 const DirDataStructure *father(ds->getDirParent());
452 return QModelIndex();
453 const DirDataStructure *grandFather(father->getDirParent());
454 return createIndex(grandFather->posOf(father),0,const_cast<DataStructure *>(static_cast<const DataStructure *>(father)));
457 QModelIndex QRemoteFileSystemModel::index(int row, int column, const QModelIndex& parent) const
459 quintptr pt(parent.internalId());
462 if(_fds->size()<=row)
463 return QModelIndex();
464 const DataStructure *ds((*_fds)[row]);
465 return createIndex(row,column,const_cast<DataStructure *>(ds));
469 DataStructure *ds0(reinterpret_cast<DataStructure *>(pt));
470 DirDataStructure *ds1(dynamic_cast<DirDataStructure *>(ds0));
471 const DataStructure *ds((*ds1)[row]);
472 return createIndex(row,column,const_cast<DataStructure *>(ds));
476 int QRemoteFileSystemModel::rowCount(const QModelIndex& mi) const
480 quintptr pt(mi.internalId());
481 DataStructure *ds(reinterpret_cast<DataStructure *>(pt));
492 int QRemoteFileSystemModel::columnCount(const QModelIndex&) const
497 QVariant QRemoteFileSystemModel::data(const QModelIndex& index, int role) const
501 if(role==Qt::DisplayRole || role==Qt::EditRole)
503 quintptr pt(index.internalId());
504 DataStructure *ds(reinterpret_cast<DataStructure *>(pt));
505 if(!ds->isSelected())
507 return ds->nameOnDrop();
509 if(role==Qt::ForegroundRole)
511 quintptr pt(index.internalId());
512 DataStructure *ds(reinterpret_cast<DataStructure *>(pt));
513 if(!ds->isSelected())
515 QColor red0(154,18,20);
521 MyTreeView::MyTreeView(QWidget *parent):QTreeView(parent),_sel(NULL),_slider_pos(-1)
523 setAcceptDrops(true);
524 setSelectionMode(QAbstractItemView::ContiguousSelection);
525 connect(this,SIGNAL(expanded(const QModelIndex&)),this,SLOT(itemExpanded(const QModelIndex&)));
526 connect(this,SIGNAL(collapsed(const QModelIndex&)),this,SLOT(itemCollapsed(const QModelIndex&)));
529 void MyTreeView::mousePressEvent(QMouseEvent *event)
531 if(event->button() == Qt::LeftButton)
533 _start_pos=event->pos();
535 QModelIndexList elts(selectedIndexes());
537 QTreeView::mousePressEvent(event);
540 void MyTreeView::mouseReleaseEvent(QMouseEvent *event)
542 QModelIndexList elts(selectedIndexes());
544 QTreeView::mousePressEvent(event);
545 QTreeView::mouseReleaseEvent(event);
548 void MyTreeView::mouseMoveEvent(QMouseEvent *event)
550 if(event->buttons() & Qt::LeftButton)
552 int dist(std::abs(event->pos().x()-_start_pos.x()));//.manhattanLength());
553 if(dist>=QApplication::startDragDistance())
555 QMimeData *mimeData(new SelectionMimeData(selectedIndexes()));
556 QDrag *drag(new QDrag(this));
557 drag->setMimeData(mimeData);
558 if(drag->exec(Qt::CopyAction)==Qt::CopyAction)
566 QTreeView::mouseMoveEvent(event);
569 void MyTreeView::keyPressEvent(QKeyEvent *event)
571 if(event->key()==Qt::Key_Delete)
573 if(!selectedIndexes().isEmpty())
576 QRemoteFileSystemModel *mod(qobject_cast<QRemoteFileSystemModel *>(model()));
578 mach=mod->getMachine();
579 QString txt(QString("On %1 you are about to delete %2 files/dirs. Confirm it ?").arg(mach).arg(selectedIndexes().size()));
580 QMessageBox mb(QMessageBox::Warning,"Confirm deletion of files",txt,QMessageBox::Ok | QMessageBox::No,this);
581 mb.setEscapeButton(QMessageBox::No);
582 mb.setDefaultButton(QMessageBox::No);
585 if(mb.buttonRole(mb.clickedButton())==QMessageBox::AcceptRole)
587 foreach(const QModelIndex& ind,selectedIndexes())
589 quintptr pt(ind.internalId());
590 DataStructure *ds(reinterpret_cast<DataStructure *>(pt));
593 ds->removeFileArgs(prg,args);
595 proc.start(prg,args);
596 bool isOK(proc.waitForFinished());
597 emit this->somethingChangedDueToFileModif();
598 if(isOK && proc.exitCode()==0)
607 QTreeView::keyPressEvent(event);
610 void MyTreeView::dragEnterEvent(QDragEnterEvent *event)
612 MyTreeView *source(qobject_cast<MyTreeView *>(event->source()));
613 if(source && source!=this)
615 _slider_pos=verticalScrollBar()->sliderPosition();
616 event->setDropAction(Qt::CopyAction);
621 void MyTreeView::dragMoveEvent(QDragMoveEvent *event)
623 MyTreeView *source(qobject_cast<MyTreeView *>(event->source()));
624 if(source && source!=this)
626 QModelIndex ind(indexAt(event->pos()));
629 quintptr pt(ind.internalId());
630 DataStructure *ds(reinterpret_cast<DataStructure *>(pt));
639 this->emitResetModel();
641 event->setDropAction(Qt::CopyAction);
643 qApp->processEvents();
649 void MyTreeView::dragLeaveEvent(QDragLeaveEvent *event)
657 this->emitResetModel();
658 QTreeView::dragLeaveEvent(event);
661 void MyTreeView::dropEvent(QDropEvent *event)
663 MyTreeView *source(qobject_cast<MyTreeView *>(event->source()));
664 if(source && source!=this)
667 const QMimeData *data(event->mimeData());
668 const SelectionMimeData *data1(qobject_cast<const SelectionMimeData *>(data));
673 this->emitResetModel();
675 QModelIndex ind(indexAt(event->pos()));
678 const QModelIndexList& listOfSelectedSrcFiles(data1->getSelection());
679 quintptr pt(ind.internalId());
680 DataStructure *ds(reinterpret_cast<DataStructure *>(pt));
681 QRemoteFileSystemModel *srcModel(qobject_cast<QRemoteFileSystemModel *>(source->model()));
682 PerformCopy(this,srcModel,listOfSelectedSrcFiles,ds);
683 emit this->somethingChangedDueToFileModif();
688 this->emitResetModel();
693 event->setDropAction(Qt::MoveAction);
697 this->emitResetModel();
701 QRemoteFileSystemModel *MyTreeView::zeModel()
703 QAbstractItemModel *mod(this->model());
704 QRemoteFileSystemModel *mod2(qobject_cast<QRemoteFileSystemModel *>(mod));
708 void MyTreeView::itemExpanded(const QModelIndex &index)
710 itemExpandedStatus(index,true);
713 void MyTreeView::itemCollapsed(const QModelIndex &index)
715 itemExpandedStatus(index,false);
718 void MyTreeView::itemExpandedStatus(const QModelIndex &index, bool status)
720 quintptr pt(index.internalId());
721 DataStructure *ds(reinterpret_cast<DataStructure *>(pt));
722 DirDataStructure *ds1(dynamic_cast<DirDataStructure *>(ds));
725 ds1->setExpanded(status);
728 void MyTreeView::drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const
730 quintptr pt(index.internalId());
731 DataStructure *ds(reinterpret_cast<DataStructure *>(pt));
732 DirDataStructure *ds1(dynamic_cast<DirDataStructure *>(ds));
734 (const_cast<MyTreeView *>(this))->setExpanded(index,ds1->isExpanded());
735 QTreeView::drawBranches(painter,rect,index);
738 void MyTreeView::paintEvent(QPaintEvent *event)
740 QTreeView::paintEvent(event);
743 verticalScrollBar()->setSliderPosition(_slider_pos);
747 void MyTreeView::emitResetModel()
749 this->zeModel()->emitResetModel();
752 AnotherTreeView::AnotherTreeView(QWidget *parent):QWidget(parent),_timerId(-1),_angle(0),_painter(nullptr),_tw(nullptr),_th(nullptr)
754 QVBoxLayout *lay(new QVBoxLayout(this));
755 _tw=new MyTreeView(this);
757 setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
758 connect(_tw,SIGNAL(somethingChangedDueToFileModif()),this,SIGNAL(somethingChangedDueToFileModif()));
762 void AnotherTreeView::goGenerate(TopDirDataStructure *fds)
764 LoadingThread *s2(qobject_cast<LoadingThread *>(sender()));
767 QRemoteFileSystemModel *model(new QRemoteFileSystemModel(_tw,fds));
768 s2->setGeneratedModel(model);
771 void AnotherTreeView::generateModel(QMachineBrowser *mb)
774 _th=new LoadingThread(QThread::currentThread(),mb);
775 connect(_th,SIGNAL(letsGenerateModel(TopDirDataStructure *)),this,SLOT(goGenerate(TopDirDataStructure *)));
776 connect(_th,SIGNAL(finished()),this,SLOT(modelHasBeenGenerated()));
777 _timerId=this->startTimer(50);
779 _painter=new AnotherTreeViewWaitPainter;
783 AnotherTreeView::~AnotherTreeView()
788 void AnotherTreeView::modelHasBeenGenerated()
791 QRemoteFileSystemModel *model(_th->generatedModel());
793 QAbstractItemModel *oldModel(_tw->model());
796 _tw->setModel(model);
800 this->killTimer(_timerId);
804 _painter=new AnotherTreeViewNothingPainter;
807 emit this->modelHasBeenGeneratedSignal(model->isOK());
812 void AnotherTreeViewWaitPainter::paint(AnotherTreeView *atv, QPaintEvent *event) const
814 QSize sz3(atv->width(),atv->height());
815 int width0(sz3.width()),height0(sz3.height());
816 int radius(std::min(width0,height0)/2);
817 QRect refRect((width0-radius)/2,(height0-radius)/2,radius,radius);
818 QPainter painter(atv);
819 QColor red(154,18,20);
820 QRadialGradient grad(refRect.center(),radius);
821 grad.setColorAt(0.f,red);
822 grad.setColorAt(0.5f,Qt::white);
823 painter.setBrush(grad);
824 painter.drawPie(refRect,atv->getAngle(),90*16);
827 void AnotherTreeViewNothingPainter::paint(AnotherTreeView *atv, QPaintEvent *event) const
829 QPainter painter(atv);
831 static const int WARN_Y=176,WARN_X=200;
832 const float RATIO(float(WARN_X)/float(WARN_Y));
834 int width0(atv->width()),height0(atv->height());
835 //QPen(QColor(255,203,189)
836 if(float(width0)>RATIO*float(height0))
837 painter.setViewport(int(width0-RATIO*float(height0))/2,0,height0*RATIO,height0);
839 painter.setViewport(0,(float(height0)-width0/RATIO)/2,width0,width0/RATIO);//width-height/RATIO
840 painter.setRenderHint(QPainter::Antialiasing,true);
841 painter.setWindow(0,0,WARN_X,WARN_Y);
843 painter.setPen(QPen(QColor(255,203,189),SZP,Qt::SolidLine,Qt::RoundCap));
844 painter.drawLine(QPoint(100,13),QPoint(11,164));
845 painter.drawLine(QPoint(11,164),QPoint(185,164));
846 painter.drawLine(QPoint(185,164),QPoint(100,13));
847 QColor lightBlack(200,200,200);
848 painter.setBrush(QBrush(lightBlack));
849 painter.setPen(QPen(lightBlack,2,Qt::SolidLine,Qt::RoundCap));
850 painter.drawEllipse(87,47,24,24);
851 painter.drawEllipse(93,105,12,12);
852 painter.drawEllipse(90,129,18,18);
853 const QPoint points[4]={QPoint(87,59),QPoint(93,111),QPoint(105,111),QPoint(111,59)};
854 painter.drawPolygon(points,4);
856 /*int width0(atv->width()),height0(atv->height());
857 int radius(std::min(width0,height0)/2);
858 QRect refRect((width0-radius)/2,(height0-radius)/2,radius,radius);
859 QPainter painter(atv);
860 QColor red(154,18,20);
861 painter.setBrush(QBrush(red));
862 painter.drawPie(refRect,0,45*16);*/
865 QSize AnotherTreeView::sizeHint() const
867 return _tw->sizeHint();
870 QSize AnotherTreeView::minimumSizeHint() const
875 void AnotherTreeView::paintEvent(QPaintEvent *event)
879 QWidget::paintEvent(event);
883 _painter->paint(this,event);
886 void AnotherTreeView::timerEvent(QTimerEvent *e)
888 if(e->timerId()!=_timerId)