QvisFilePanel.C 123 KB
Newer Older
hrchilds's avatar
hrchilds committed
1 2
/*****************************************************************************
*
3
* Copyright (c) 2000 - 2013, Lawrence Livermore National Security, LLC
hrchilds's avatar
hrchilds committed
4
* Produced at the Lawrence Livermore National Laboratory
5
* LLNL-CODE-442911
hrchilds's avatar
hrchilds committed
6 7
* All rights reserved.
*
8
* This file is  part of VisIt. For  details, see https://visit.llnl.gov/.  The
hrchilds's avatar
hrchilds committed
9 10 11 12 13 14 15 16 17 18
* full copyright notice is contained in the file COPYRIGHT located at the root
* of the VisIt distribution or at http://www.llnl.gov/visit/copyright.html.
*
* Redistribution  and  use  in  source  and  binary  forms,  with  or  without
* modification, are permitted provided that the following conditions are met:
*
*  - Redistributions of  source code must  retain the above  copyright notice,
*    this list of conditions and the disclaimer below.
*  - Redistributions in binary form must reproduce the above copyright notice,
*    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
19 20 21
*    documentation and/or other materials provided with the distribution.
*  - Neither the name of  the LLNS/LLNL nor the names of  its contributors may
*    be used to endorse or promote products derived from this software without
hrchilds's avatar
hrchilds committed
22 23 24 25 26
*    specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
27 28 29
* ARE  DISCLAIMED. IN  NO EVENT  SHALL LAWRENCE  LIVERMORE NATIONAL  SECURITY,
* LLC, THE  U.S.  DEPARTMENT OF  ENERGY  OR  CONTRIBUTORS BE  LIABLE  FOR  ANY
* DIRECT,  INDIRECT,   INCIDENTAL,   SPECIAL,   EXEMPLARY,  OR   CONSEQUENTIAL
hrchilds's avatar
hrchilds committed
30 31 32 33 34 35 36 37 38
* DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
* SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
* CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
* LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
* OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*****************************************************************************/

hrchilds's avatar
hrchilds committed
39
#include <visitstream.h>
hrchilds's avatar
hrchilds committed
40

whitlocb's avatar
whitlocb committed
41
#include <QComboBox>
42 43
#include <QDebug>
#include <QContextMenuEvent>
44
#include <QHeaderView>
whitlocb's avatar
whitlocb committed
45
#include <QLabel>
46
#include <QMenu>
whitlocb's avatar
whitlocb committed
47 48 49 50 51 52
#include <QTreeWidget>
#include <QTreeWidgetItem> 
#include <QLayout>
#include <QPushButton>
#include <QLineEdit> 
#include <QTimer>
hrchilds's avatar
hrchilds committed
53 54

#include <QvisFilePanel.h>
hrchilds's avatar
hrchilds committed
55
#include <QvisAnimationSlider.h>
hrchilds's avatar
hrchilds committed
56
#include <QvisVCRControl.h>
whitlocb's avatar
whitlocb committed
57
#include <QvisFilePanelItem.h>
hrchilds's avatar
hrchilds committed
58

hrchilds's avatar
hrchilds committed
59 60 61
#include <DatabaseCorrelation.h>
#include <DatabaseCorrelationList.h>
#include <DebugStream.h>
hrchilds's avatar
hrchilds committed
62 63
#include <FileServerList.h>
#include <GlobalAttributes.h>
hrchilds's avatar
hrchilds committed
64
#include <KeyframeAttributes.h>
hrchilds's avatar
hrchilds committed
65
#include <NameSimplifier.h>
hrchilds's avatar
hrchilds committed
66 67
#include <Plot.h>
#include <PlotList.h>
hrchilds's avatar
hrchilds committed
68
#include <WindowInformation.h>
hrchilds's avatar
hrchilds committed
69
#include <Utility.h>
hrchilds's avatar
hrchilds committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
#include <ViewerProxy.h>
#include <avtDatabaseMetaData.h>

// Include the XPM files used for the icons.
#include <icons/database.xpm>
#include <icons/folder.xpm>
#include <icons/computer.xpm>

// ****************************************************************************
// Class: FileTree
//
// Purpose:
//   This class is used internally to represent a file tree that can undergo
//   reduce operations in order to simplify the tree.
//
// Notes:      FileTree::FileTreeNode is an internal class that is used to
//             help represent the file tree's nodes.
//
// Programmer: Brad Whitlock
// Creation:   Thu Mar 22 16:47:19 PST 2001
//
// Modifications:
//   Brad Whitlock, Mon Aug 26 16:32:05 PST 2002
//   I changed the code so it can handle different kinds of file separators.
//
//   Brad Whitlock, Wed May 14 15:38:40 PST 2003
//   I added support for virtual databases being expanded by default.
//
hrchilds's avatar
hrchilds committed
98 99
//   Brad Whitlock, Thu Aug 5 17:36:02 PST 2004
//   I added methods to look for long node names.
100
//
whitlocb's avatar
whitlocb committed
101 102
//   Cyrus Harrison, Tue Jul  1 14:28:23 PDT 2008
//   Initial Qt4 Port.
hrchilds's avatar
hrchilds committed
103
//
hrchilds's avatar
hrchilds committed
104 105
// ****************************************************************************

whitlocb's avatar
whitlocb committed
106

hrchilds's avatar
hrchilds committed
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
class FileTree
{
public:
    class FileTreeNode
    {
    public:
        static const int ROOT_NODE;
        static const int PATH_NODE;
        static const int FILE_NODE;
        static const int DATABASE_NODE;

        FileTreeNode(int nodeT = FILE_NODE);
        ~FileTreeNode();
        FileTreeNode *Add(int nType, const std::string &name,
                          const QualifiedFilename &fName, char separator);
        bool Reduce();
        FileTreeNode *Find(const std::string &path);
        int Size() const;
        bool HasChildrenOfType(int type);
hrchilds's avatar
hrchilds committed
126
        bool HasNodeNameExceeding(int len) const;
whitlocb's avatar
whitlocb committed
127 128
        void AddElementsToTreeItem(QTreeWidgetItem *item, int &fileIndex,
                                   bool addRoot,
hrchilds's avatar
hrchilds committed
129
                                   const QPixmap &folderPixmap,
whitlocb's avatar
whitlocb committed
130
                                   const QPixmap &dbPixmap,
hrchilds's avatar
hrchilds committed
131
                                   QvisFilePanel *filePanel);
132

whitlocb's avatar
whitlocb committed
133 134 135 136
        void AddElementsToTree(QTreeWidget *tree, int &fileIndex,
                               const QPixmap &folderPixmap,
                               const QPixmap &databasePixmap,
                               QvisFilePanel *filePanel);
hrchilds's avatar
hrchilds committed
137 138 139 140 141 142 143 144
        QString NumberedFilename(int fileIndex) const;

        std::string separator_str()
        {
            char str[2] = {separator, '\0'};
            return std::string(str);
        }

hrchilds's avatar
hrchilds committed
145 146
        void Print(ostream &os, const std::string &indent) const;

hrchilds's avatar
hrchilds committed
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
        char              separator;
        int               nodeType;
        std::string       nodeName;
        QualifiedFilename fileName;
        int               numChildren;
        FileTreeNode      **children;
    private:
        void Destroy();
    };

    FileTree(QvisFilePanel *fp);
    ~FileTree();

    void Add(const QualifiedFilename &fileName, char separator);
    void Reduce();
    int  Size() const;
    bool TreeContainsDirectories() const;
hrchilds's avatar
hrchilds committed
164
    bool HasNodeNameExceeding(int len) const;
hrchilds's avatar
hrchilds committed
165

whitlocb's avatar
whitlocb committed
166
    void AddElementsToTreeItem(QTreeWidgetItem *item, int &fileIndex,
hrchilds's avatar
hrchilds committed
167
                               const QPixmap &folderPixmap,
whitlocb's avatar
whitlocb committed
168 169 170 171
                               const QPixmap &dbPixmap);
    void AddElementsToTree(QTreeWidget *tree, int &fileIndex,
                           const QPixmap &folderPixmap,
                           const QPixmap &databasePixmap);
hrchilds's avatar
hrchilds committed
172 173

    friend ostream &operator << (ostream &os, const FileTree &t);
hrchilds's avatar
hrchilds committed
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
private:
    std::string separator_str()
    {
        char str[2] = {separator, '\0'};
        return std::string(str);
    }

    char           separator;
    FileTreeNode  *root;
    QvisFilePanel *filePanel;
};

const int FileTree::FileTreeNode::ROOT_NODE     = 0;
const int FileTree::FileTreeNode::PATH_NODE     = 1;
const int FileTree::FileTreeNode::FILE_NODE     = 2;
const int FileTree::FileTreeNode::DATABASE_NODE = 3;

///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: QvisFilePanel::QvisFilePanel
//
// Purpose: 
//   Constructor for the QvisFilePanel class.
//
// Arguments:
//   parent     : A pointer to the widget's parent widget.
//   name       : The widget's name.
//
// Programmer: Brad Whitlock
// Creation:   Thu Aug 31 10:35:07 PDT 2000
//
// Modifications:
//   Brad Whitlock, Thu Mar 22 11:24:16 PDT 2001
//   Added code to create the folder pixmap.
//
//   Brad Whitlock, Thu Feb 28 14:01:20 PST 2002
//   Connected slots for collapse and expand.
//
//   Jeremy Meredith, Mon Aug 19 16:22:44 PDT 2002
//   Initialized globalAtts.
//
//   Brad Whitlock, Fri May 16 12:28:49 PDT 2003
//   Initialized displayInfo.
//
hrchilds's avatar
hrchilds committed
219 220 221
//   Brad Whitlock, Mon Oct 13 15:24:56 PST 2003
//   Initialized timeStateFormat.
//
hrchilds's avatar
hrchilds committed
222 223 224
//   Brad Whitlock, Tue Dec 30 14:32:32 PST 2003
//   I made it use QvisAnimationSlider.
//
hrchilds's avatar
hrchilds committed
225 226 227
//   Brad Whitlock, Tue Jan 27 18:14:38 PST 2004
//   I renamed some slots and added the active time slider.
//
hrchilds's avatar
hrchilds committed
228 229 230
//   Brad Whitlock, Tue Apr 6 14:07:34 PST 2004
//   I added allowFileSelectionChange.
//
hrchilds's avatar
hrchilds committed
231 232 233
//   Brad Whitlock, Tue Apr 27 12:11:29 PDT 2004
//   I improved the spacing for newer versions of Qt.
//
hrchilds's avatar
hrchilds committed
234 235 236 237 238
//   Jeremy Meredith, Wed Oct 13 20:38:30 PDT 2004
//   Prevent the header of the file list from being clicked.  Leaving it
//   enabled allows changing of the sort and in some circumstances broke
//   time sequences.  ('5391)
//
whitlocb's avatar
whitlocb committed
239 240 241 242 243 244
//   Brad Whitlock, Fri May 30 14:22:50 PDT 2008
//   Qt 4.
//
//   Cyrus Harrison, Tue Jul  1 14:28:23 PDT 2008
//   Initial Qt4 Port.
//
245 246 247
//    Cyrus Harrison, Tue Apr 14 13:35:54 PDT 2009
//    Added creation & setup of filePopupMenu.
//
248 249 250
//   Jeremy Meredith, Fri Nov  6 11:40:46 EST 2009
//   File panel selected files list now starts out hidden.
//
251 252 253
//   Cyrus Harrison, Mon Mar 15 11:57:22 PDT 2010
//   Moved timeslider controls into a QvisTimeSliderControlWidget.
//
hrchilds's avatar
hrchilds committed
254 255
// ****************************************************************************

whitlocb's avatar
whitlocb committed
256
QvisFilePanel::QvisFilePanel(QWidget *parent) :
257 258
   QGroupBox(tr("Selected Files"),parent), SimpleObserver(), GUIBase(), 
   displayInfo(),
hrchilds's avatar
hrchilds committed
259
   timeStateFormat()
hrchilds's avatar
hrchilds committed
260
{
hrchilds's avatar
hrchilds committed
261
    allowFileSelectionChange = true;
hrchilds's avatar
hrchilds committed
262

hrchilds's avatar
hrchilds committed
263 264 265
    // Create the top layout that will contain the widgets.
    QVBoxLayout *topLayout = new QVBoxLayout(this);
    topLayout->setSpacing(5);
266
    topLayout->setMargin(5);
267

whitlocb's avatar
whitlocb committed
268
    fileTree = new QTreeWidget(this);
269 270
    fileTree->header()->hide();

hrchilds's avatar
hrchilds committed
271
    // Create the selected file list.
whitlocb's avatar
whitlocb committed
272 273
    fileTree->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    fileTree->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
274

whitlocb's avatar
whitlocb committed
275 276
    connect(fileTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *,int)),
            this, SLOT(openFileDblClick(QTreeWidgetItem *)));
277 278 279 280 281
    /*
    connect(fileListView, 
            SIGNAL(rightButtonClicked(QListViewItem *,const QPoint &,int)),
            this, 
            SLOT(showFilePopup(QListViewItem *, const QPoint &, int)));
282
    */
whitlocb's avatar
whitlocb committed
283 284 285 286 287 288
    connect(fileTree, SIGNAL(currentItemChanged(QTreeWidgetItem *,QTreeWidgetItem *)),
            this, SLOT(highlightFile(QTreeWidgetItem *)));
    connect(fileTree, SIGNAL(itemExpanded(QTreeWidgetItem *)),
            this, SLOT(fileExpanded(QTreeWidgetItem *)));
    connect(fileTree, SIGNAL(itemCollapsed(QTreeWidgetItem *)),
            this, SLOT(fileCollapsed(QTreeWidgetItem *)));
289

whitlocb's avatar
whitlocb committed
290
    topLayout->addWidget(fileTree, 10);
hrchilds's avatar
hrchilds committed
291 292

    // Create the file opening buttons.
whitlocb's avatar
whitlocb committed
293 294 295
    QHBoxLayout *buttonLayout = new QHBoxLayout(0);
    buttonLayout->setMargin(0);
    topLayout->addLayout(buttonLayout);
hrchilds's avatar
hrchilds committed
296
    topLayout->setStretchFactor(buttonLayout, 10);
whitlocb's avatar
whitlocb committed
297
    openButton = new QPushButton(tr("Open"));
hrchilds's avatar
hrchilds committed
298 299 300 301
    openButton->setEnabled(false);
    connect(openButton, SIGNAL(clicked()), this, SLOT(openFile()));
    buttonLayout->addWidget(openButton);

whitlocb's avatar
whitlocb committed
302
    replaceButton = new QPushButton(tr("Replace"));
hrchilds's avatar
hrchilds committed
303 304 305 306
    replaceButton->setEnabled(false);
    connect(replaceButton, SIGNAL(clicked()), this, SLOT(replaceFile()));
    buttonLayout->addWidget(replaceButton);

whitlocb's avatar
whitlocb committed
307
    overlayButton = new QPushButton(tr("Overlay"));
hrchilds's avatar
hrchilds committed
308 309 310 311
    overlayButton->setEnabled(false);
    connect(overlayButton, SIGNAL(clicked()), this, SLOT(overlayFile()));
    buttonLayout->addWidget(overlayButton);

312 313 314 315 316 317
    filePopupMenu = new QMenu(this);
    openAct    = filePopupMenu->addAction(tr("&Open"));
    replaceAct = filePopupMenu->addAction(tr("&Replace"));
    replaceSelectedAct = filePopupMenu->addAction(tr("Replace &Selected"));
    overlayAct = filePopupMenu->addAction(tr("&Overlay"));
    closeAct   = filePopupMenu->addAction(tr("&Close"));
318

hrchilds's avatar
hrchilds committed
319 320 321 322 323 324 325 326
    // Create the computer pixmap.
    computerPixmap = new QPixmap(computer_xpm);
    // Create the database pixmap.
    databasePixmap = new QPixmap(database_xpm);
    // Create the folder pixmap and add it to the pixmap cache.
    folderPixmap = new QPixmap(folder_xpm);

    // Initialize the attached subjects
hrchilds's avatar
hrchilds committed
327
    windowInfo = NULL;
328

hrchilds's avatar
hrchilds committed
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
}

// ****************************************************************************
// Method: QvisFilePanel::~QvisFilePanel
//
// Purpose: 
//   Destructor for the QvisFilePanel class.
//
// Programmer: Brad Whitlock
// Creation:   Thu Aug 31 10:36:46 PDT 2000
//
// Modifications:
//   Brad Whitlock, Fri Feb 1 14:28:06 PST 2002
//   Added code to delete the widget's pixmaps.
//
hrchilds's avatar
hrchilds committed
344 345 346
//   Brad Whitlock, Sun Jan 25 01:10:56 PDT 2004
//   I made it use windowInfo instead of globalAtts.
//
hrchilds's avatar
hrchilds committed
347 348 349 350 351 352 353
// ****************************************************************************

QvisFilePanel::~QvisFilePanel()
{
    if(fileServer)
        fileServer->Detach(this);

hrchilds's avatar
hrchilds committed
354 355
    if(windowInfo)
        windowInfo->Detach(this);
hrchilds's avatar
hrchilds committed
356 357 358 359 360 361 362

    // Delete the pixmaps.
    delete computerPixmap;
    delete databasePixmap;
    delete folderPixmap;
}

hrchilds's avatar
hrchilds committed
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
// ****************************************************************************
// Method: QvisFilePanel::SetTimeStateFormat
//
// Purpose: 
//   Sets the display mode for the file panel. We can make it display files
//   using cycle information or we can make it use time information.
//
// Arguments: 
//   m : The new timestate display mode.
//
// Notes:      This method resets the text on the expanded databases, which
//             are open databases with more than one time state, so that
//             they show time using the new timestate display mode.
//
// Programmer: Brad Whitlock
// Creation:   Mon Oct 13 16:15:46 PST 2003
//
// Modifications:
hrchilds's avatar
hrchilds committed
381 382 383 384
//   Brad Whitlock, Mon Dec 29 10:13:15 PDT 2003
//   I added code to help determine how labels are displayed if a database is
//   virtual.
//
hrchilds's avatar
hrchilds committed
385 386 387
//   Brad Whitlock, Sun Jan 25 01:28:55 PDT 2004
//   I added support for multiple time sliders.
//
hrchilds's avatar
hrchilds committed
388 389 390
//   Mark C. Miller, Wed Aug  2 19:58:44 PDT 2006
//   Changed interface to FileServerList::GetMetaData
//
391 392 393 394
//   Mark C. Miller, Fri Aug 10 23:11:55 PDT 2007
//   Propogated knowledge that item was updated with metadata that was forced
//   to get accurate cycles/times.
//
whitlocb's avatar
whitlocb committed
395 396
//   Cyrus Harrison, Tue Jul  1 16:04:25 PDT 2008
//   Initial Qt4 Port.
397 398 399 400
//
//   Cyrus Harrison, Mon Mar 15 11:57:22 PDT 2010
//   Updated b/c timeslider controls were removed.
//
hrchilds's avatar
hrchilds committed
401 402 403 404 405 406 407 408 409 410 411
// ****************************************************************************

void
QvisFilePanel::SetTimeStateFormat(const TimeFormat &m)
{
    if(m != timeStateFormat)
    {
        timeStateFormat = m;

        // Count the number of items in the fileListView. I didn't see a way to
        // count them all without traversing them all.
whitlocb's avatar
whitlocb committed
412 413
        int i = 0;
        int count = 0;
414

hrchilds's avatar
hrchilds committed
415 416 417 418
        // Create an array to store pointers to all of the items. We save the
        // pointers in an array because later when we expand databases, we
        // can't traverse using an iterator because as we add items, the
        // iterator is invalidated.
whitlocb's avatar
whitlocb committed
419 420 421 422 423
        QList<QvisFilePanelItem*> items;
        QTreeWidgetItemIterator it(fileTree);
        for ( ; *it; ++it )
            items.append((QvisFilePanelItem*)*it);
        count = items.count();
hrchilds's avatar
hrchilds committed
424

whitlocb's avatar
whitlocb committed
425 426 427
        // If there are no items, return early.
        if(count < 1)
            return;
428

hrchilds's avatar
hrchilds committed
429 430 431 432 433
        //
        // Iterate through the items and expand them if they are databases.
        //
        for(i = 0; i < count; ++i)
        {
whitlocb's avatar
whitlocb committed
434
            QvisFilePanelItem *item = items[i];
hrchilds's avatar
hrchilds committed
435 436 437 438 439
            if(item != 0)
            {
                if(HaveFileInformation(item->file))
                {
                    // See if the file is a database
hrchilds's avatar
hrchilds committed
440 441 442 443 444
                    const avtDatabaseMetaData *md =
                        fileServer->GetMetaData(item->file,
                                                GetStateForSource(item->file),
                                                FileServerList::ANY_STATE,
                                               !FileServerList::GET_NEW_MD);
hrchilds's avatar
hrchilds committed
445 446
                    if(md != 0 && md->GetNumStates() > 1)
                    {
whitlocb's avatar
whitlocb committed
447
                        int j, maxts = qMin(md->GetNumStates(), item->childCount());
448

whitlocb's avatar
whitlocb committed
449
                        QTreeWidgetItemIterator it(item); ++it;
hrchilds's avatar
hrchilds committed
450 451 452
                        bool useVirtualDBInfo = DisplayVirtualDBInformation(item->file);

                        // Set the label so that it shows the right values.
hrchilds's avatar
hrchilds committed
453 454
                        for(j = 0; j < maxts; ++j, ++it)
                        {
whitlocb's avatar
whitlocb committed
455
                             (*it)->setText(0, CreateItemLabel(md, j,
hrchilds's avatar
hrchilds committed
456
                                 useVirtualDBInfo));
hrchilds's avatar
hrchilds committed
457
                        }
whitlocb's avatar
whitlocb committed
458

459 460
                        item->timeStateHasBeenForced =
                            fileServer->GetForceReadAllCyclesTimes();
hrchilds's avatar
hrchilds committed
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
                    }
                }
            }
        }
    }
}

// ****************************************************************************
// Method: QvisFilePanel::GetTimeStateFormat
//
// Purpose: 
//   Returns the time state format.
//
// Returns:    The time state format.
//
// Programmer: Brad Whitlock
// Creation:   Mon Oct 13 17:19:20 PST 2003
//
// Modifications:
//   
// ****************************************************************************

const TimeFormat &
QvisFilePanel::GetTimeStateFormat() const
{
    return timeStateFormat;
}

hrchilds's avatar
hrchilds committed
489 490 491 492 493 494 495 496 497 498 499
// ****************************************************************************
// Method: QvisFilePanel::Update
//
// Purpose: 
//   This method tells the widget to update itself when the subject
//   changes.
//
// Programmer: Brad Whitlock
// Creation:   Thu Aug 31 10:37:19 PDT 2000
//
// Modifications:
hrchilds's avatar
hrchilds committed
500 501 502
//   Brad Whitlock, Sun Jan 25 01:28:23 PDT 2004
//   I made it use windowInfo instead of globalAtts.
//
503 504 505
//   Cyrus Harrison, Mon Mar 15 11:57:22 PDT 2010
//   Changed UpdateAnimationControls to UpdateWindowInfo.
//
hrchilds's avatar
hrchilds committed
506 507 508 509 510
// ****************************************************************************

void
QvisFilePanel::Update(Subject *TheChangedSubject)
{
hrchilds's avatar
hrchilds committed
511
    if(fileServer == 0 || windowInfo == 0)
hrchilds's avatar
hrchilds committed
512 513 514 515
        return;

    if(TheChangedSubject == fileServer)
        UpdateFileList(false);
hrchilds's avatar
hrchilds committed
516
    else if(TheChangedSubject == windowInfo)
517
        UpdateWindowInfo(false);
hrchilds's avatar
hrchilds committed
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
}

// ****************************************************************************
// Method: QvisFilePanel::UpdateFileList
//
// Purpose: 
//   This method updates the widget to reflect the new state stored
//   in the FileServerList that this widget is watching.
//
// Arguments:
//   doAll : Whether or not to update everything. If this is false,
//           then it should pay attention to what attributes actually
//           changed.
//
// Programmer: Brad Whitlock
// Creation:   Thu Aug 31 10:38:11 PDT 2000
//
// Modifications:
hrchilds's avatar
hrchilds committed
536 537
//   Brad Whitlock, Sun Jan 25 01:29:46 PDT 2004
//   I moved the guts into RepopulateFileList.
hrchilds's avatar
hrchilds committed
538
//
hrchilds's avatar
hrchilds committed
539 540 541 542 543
// ****************************************************************************

void
QvisFilePanel::UpdateFileList(bool doAll)
{
hrchilds's avatar
hrchilds committed
544
    if(fileServer == 0 || windowInfo == 0)
hrchilds's avatar
hrchilds committed
545 546 547 548 549
        return;

    // If the appliedFileList has changed, update the appliedFile list.
    if(fileServer->AppliedFileListChanged() || doAll)
    {
550
        RepopulateFileList();
hrchilds's avatar
hrchilds committed
551 552 553
    }
    else if(fileServer->FileChanged())
    {
554 555 556 557
        // Expand any databases that we know about. This just means that we add
        // the extra information that databases have, we don't expand the tree
        // until we enter UpdateFileSelection.
        ExpandDatabases();
hrchilds's avatar
hrchilds committed
558

559 560
        // Highlight the selected file.
        UpdateFileSelection();
hrchilds's avatar
hrchilds committed
561 562 563
        // Set the enabled state for the animation controls.
    }
}
hrchilds's avatar
hrchilds committed
564

hrchilds's avatar
hrchilds committed
565 566 567 568 569 570 571 572 573 574 575
// ****************************************************************************
// Method: QvisFilePanel::RepopulateFileList
//
// Purpose: 
//   Clears out the selected files and refills the list with the new list
//   of selected files.
//
// Programmer: Brad Whitlock
// Creation:   Fri Jan 30 11:54:15 PDT 2004
//
// Modifications:
hrchilds's avatar
hrchilds committed
576 577 578 579
//   Brad Whitlock, Wed Jul 28 17:22:59 PST 2004
//   Added code to force file lists that have MT databases always have a root
//   so they can be collapsed.
//
hrchilds's avatar
hrchilds committed
580 581 582 583
//   Brad Whitlock, Thu Aug 5 17:36:33 PST 2004
//   I added code to detect when node names are long and set the horizontal
//   scrollbar mode of the listview appropriately.
//
hrchilds's avatar
hrchilds committed
584
//   Mark C. Miller, Wed Aug  2 19:58:44 PDT 2006
cyrush's avatar
cyrush committed
585 586
//   Changed interface to FileServerList::GetMetaData
//
whitlocb's avatar
whitlocb committed
587 588 589
//   Cyrus Harrison, Tue Jul  1 14:28:23 PDT 2008
//   Initial Qt4 Port.
//
cyrush's avatar
cyrush committed
590 591 592
//   Cyrus Harrison, Thu Dec  4 09:13:50 PST 2008
//   Removed unnecssary todo comment.
//
hrchilds's avatar
hrchilds committed
593
// ****************************************************************************
hrchilds's avatar
hrchilds committed
594

hrchilds's avatar
hrchilds committed
595 596 597 598 599
void
QvisFilePanel::RepopulateFileList()
{
    const QualifiedFilenameVector &f = fileServer->GetAppliedFileList();
    // Holds pointers to the list item for each host.
whitlocb's avatar
whitlocb committed
600
    std::map<std::string, QTreeWidgetItem *> hostMap;
hrchilds's avatar
hrchilds committed
601 602 603

    // Go through all of the files and build a list of unique hosts.
    bool hostOtherThanLocalHost = false;
hrchilds's avatar
hrchilds committed
604
    bool someFilesHaveMultipleTimeStates = false;
hrchilds's avatar
hrchilds committed
605 606 607
    QualifiedFilenameVector::const_iterator pos;
    for(pos = f.begin(); pos != f.end(); ++pos)
    {
hrchilds's avatar
hrchilds committed
608
        // Populate the hostMap variable.
hrchilds's avatar
hrchilds committed
609
        if(pos->host.size() > 0)
hrchilds's avatar
hrchilds committed
610
        {
hrchilds's avatar
hrchilds committed
611 612
            // Add an entry for the host.
            hostMap[pos->host] = 0;
hrchilds's avatar
hrchilds committed
613

hrchilds's avatar
hrchilds committed
614 615 616 617
            // See if the host is not localhost.
            if(pos->host != std::string("localhost"))
                hostOtherThanLocalHost = true;
        }
hrchilds's avatar
hrchilds committed
618 619 620 621 622 623 624 625 626 627 628

        // See if the current file is MT
        if(!someFilesHaveMultipleTimeStates)
        {
            if(pos->IsVirtual())
            {
                someFilesHaveMultipleTimeStates = true;
            }
            else if(fileServer->HaveOpenedFile(*pos))
            {
                const avtDatabaseMetaData *md =
hrchilds's avatar
hrchilds committed
629 630 631 632
                    fileServer->GetMetaData(*pos,
                                    GetStateForSource(*pos),
                                    FileServerList::ANY_STATE,
                                   !FileServerList::GET_NEW_MD);
hrchilds's avatar
hrchilds committed
633 634 635 636
                if(md != 0 && md->GetNumStates() > 1)
                    someFilesHaveMultipleTimeStates = true;
            }
        }
hrchilds's avatar
hrchilds committed
637
    }
hrchilds's avatar
hrchilds committed
638

hrchilds's avatar
hrchilds committed
639
    // Clear out the fileListView widget.
whitlocb's avatar
whitlocb committed
640
    fileTree->clear();
hrchilds's avatar
hrchilds committed
641

whitlocb's avatar
whitlocb committed
642
    QvisFilePanelItem::resetNodeNumber();
hrchilds's avatar
hrchilds committed
643
    // Reset the node numbers that will be used to create the nodes.
whitlocb's avatar
whitlocb committed
644
    //QvisListViewFileItem::resetNodeNumber();
hrchilds's avatar
hrchilds committed
645

hrchilds's avatar
hrchilds committed
646
    // Assume that we want automatic scrollbars instead of always having them.
whitlocb's avatar
whitlocb committed
647
    Qt::ScrollBarPolicy hScrollMode = Qt::ScrollBarAsNeeded;
hrchilds's avatar
hrchilds committed
648

hrchilds's avatar
hrchilds committed
649 650 651
    // If there are multiple hosts or just one and it is not localhost,
    // add nodes in the file tree for the host. This makes sure that it
    // is always clear which host a file came from.
whitlocb's avatar
whitlocb committed
652

hrchilds's avatar
hrchilds committed
653 654
    if(hostMap.size() > 1)
    {
whitlocb's avatar
whitlocb committed
655
        std::map<std::string, QTreeWidgetItem *>::iterator hpos;
hrchilds's avatar
hrchilds committed
656 657 658

        // Create the root for the host list.
        QualifiedFilename rootName("Hosts", "(root)", "(root)");
whitlocb's avatar
whitlocb committed
659 660 661 662
        QTreeWidgetItem *root = new QvisFilePanelItem(fileTree,
                                                      QString(tr("Hosts")),
                                                      rootName,
                                                      QvisFilePanelItem::ROOT_NODE);
hrchilds's avatar
hrchilds committed
663 664 665 666 667 668 669

        // Always expand the root node.
        AddExpandedFile(rootName);

        // Create all of the host listview items.
        int fileIndex = 1;
        for(hpos = hostMap.begin(); hpos != hostMap.end(); ++hpos)
hrchilds's avatar
hrchilds committed
670
        {
hrchilds's avatar
hrchilds committed
671 672 673
            char separator = fileServer->GetSeparator(hpos->first);
            QualifiedFilename hostOnly(hpos->first, "(host)", "(host)");
            hostOnly.separator = separator;
whitlocb's avatar
whitlocb committed
674 675 676 677 678 679
            
            QTreeWidgetItem *newFile = new QvisFilePanelItem(root, 
                                                             QString(hpos->first.c_str()),
                                                             hostOnly,
                                                             QvisFilePanelItem::HOST_NODE);
            newFile->setIcon(0,*computerPixmap);
hrchilds's avatar
hrchilds committed
680 681 682
            // Add the widget to the host map.
            hpos->second = newFile;

hrchilds's avatar
hrchilds committed
683 684 685 686
            // Add the files to the file tree and reduce it.
            FileTree files(this);
            for(pos = f.begin(); pos != f.end(); ++pos)
            {
hrchilds's avatar
hrchilds committed
687 688
                if(pos->host == hpos->first)
                    files.Add(*pos, separator);
hrchilds's avatar
hrchilds committed
689 690 691
            }
            files.Reduce();

hrchilds's avatar
hrchilds committed
692 693 694
            // If there are any nodes with long names then we should have
            // scrollbars in the selected files list.
            if(files.HasNodeNameExceeding(30))
whitlocb's avatar
whitlocb committed
695
                hScrollMode = Qt::ScrollBarAlwaysOn;
hrchilds's avatar
hrchilds committed
696

hrchilds's avatar
hrchilds committed
697 698
            // Add all the elements in the files list to the host list
            // view item.
whitlocb's avatar
whitlocb committed
699 700
            files.AddElementsToTreeItem(newFile, fileIndex,
                                        *folderPixmap, *databasePixmap);
hrchilds's avatar
hrchilds committed
701
        }
hrchilds's avatar
hrchilds committed
702 703 704 705 706 707 708 709 710 711 712
    }
    else
    {
        // Add the files to the file tree and reduce it.
        FileTree files(this);
        for(pos = f.begin(); pos != f.end(); ++pos)
        {
            char separator = fileServer->GetSeparator(pos->host);
            files.Add(*pos, separator);
        }
        files.Reduce();
hrchilds's avatar
hrchilds committed
713

hrchilds's avatar
hrchilds committed
714 715
        // debug1 << "File Tree:\n" << files << endl << endl;

hrchilds's avatar
hrchilds committed
716 717 718
        // If there are any nodes with long names then we should have
        // scrollbars in the selected files list.
        if(files.HasNodeNameExceeding(30))
whitlocb's avatar
whitlocb committed
719
            hScrollMode = Qt::ScrollBarAlwaysOn;
hrchilds's avatar
hrchilds committed
720

hrchilds's avatar
hrchilds committed
721 722 723
        // If there are top level directories in the file tree, then we
        // need to create a node for the host.
        if(files.TreeContainsDirectories() ||
hrchilds's avatar
hrchilds committed
724 725
           hostOtherThanLocalHost ||
           someFilesHaveMultipleTimeStates)
hrchilds's avatar
hrchilds committed
726 727 728
        {
            // Create the root for the host list.
            QualifiedFilename rootName(f[0].host, "(host)", "(host)");
whitlocb's avatar
whitlocb committed
729 730 731 732 733
            QTreeWidgetItem *root = new QvisFilePanelItem(fileTree, 
                                                          QString(f[0].host.c_str()),
                                                          rootName,
                                                          QvisFilePanelItem::ROOT_NODE);
            root->setIcon(0, *computerPixmap);
hrchilds's avatar
hrchilds committed
734

hrchilds's avatar
hrchilds committed
735 736
            // Make sure that the host is expanded.
            AddExpandedFile(rootName);
hrchilds's avatar
hrchilds committed
737

hrchilds's avatar
hrchilds committed
738
            int fileIndex = 1;
whitlocb's avatar
whitlocb committed
739 740
            files.AddElementsToTreeItem(root, fileIndex, *folderPixmap,
                                        *databasePixmap);
hrchilds's avatar
hrchilds committed
741 742 743 744 745
        }
        else
        {
            // Traverse the file tree and make widgets for the items in it.
            int fileIndex = 1;
whitlocb's avatar
whitlocb committed
746 747
            files.AddElementsToTree(fileTree, fileIndex, *folderPixmap,
                                     *databasePixmap);
hrchilds's avatar
hrchilds committed
748
        }
hrchilds's avatar
hrchilds committed
749 750
    }

hrchilds's avatar
hrchilds committed
751 752 753
    //
    // Set the list view's scrollbar mode.
    //
whitlocb's avatar
whitlocb committed
754
    bool hScrollModeChanged = (hScrollMode != fileTree->horizontalScrollBarPolicy());
hrchilds's avatar
hrchilds committed
755
    if(hScrollModeChanged)
whitlocb's avatar
whitlocb committed
756
        fileTree->setHorizontalScrollBarPolicy(hScrollMode);
hrchilds's avatar
hrchilds committed
757

hrchilds's avatar
hrchilds committed
758 759 760 761
    // Expand any databases that we know about. This just means that we add
    // the extra information that databases have, we don't expand the tree
    // until we enter UpdateFileSelection.
    ExpandDatabases();
hrchilds's avatar
hrchilds committed
762

hrchilds's avatar
hrchilds committed
763 764
    // Highlight the selected file.
    UpdateFileSelection();
hrchilds's avatar
hrchilds committed
765 766 767
}

// ****************************************************************************
768
// Method: QvisFilePanel::UpdateWindowInfo
hrchilds's avatar
hrchilds committed
769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796
//
// Purpose: 
//   This method is called when the GlobalAttributes subject that this
//   widget watches is updated.
//
// Arguments:
//   doAll : A flag indicating whether to ignore any partial selection.
//
// Programmer: Brad Whitlock
// Creation:   Tue Sep 26 16:04:38 PST 2000
//
// Modifications:
//   Brad Whitlock, Tue Aug 21 16:53:13 PST 2001
//   Moved the cycle/time code into a sub-function.
//
//   Eric Brugger, Fri Nov  2 17:07:24 PST 2001
//   I added code to handle the current file changing.
//
//   Eric Brugger, Mon Dec 16 13:05:01 PST 2002
//   I seperated the concepts of state and frame, since they are no longer
//   equivalent with keyframe support.
//
//   Brad Whitlock, Thu Mar 20 11:11:14 PDT 2003
//   I changed the ordering of fields in GlobalAttributes.
//
//   Brad Whitlock, Thu May 15 13:19:13 PST 2003
//   I changed the call to FileServer::OpenFile.
//
hrchilds's avatar
hrchilds committed
797 798 799
//   Brad Whitlock, Wed Jul 2 15:58:47 PST 2003
//   I added exception handling code for when the metadata cannot be read.
//
hrchilds's avatar
hrchilds committed
800 801 802
//   Brad Whitlock, Tue Sep 9 15:40:40 PST 2003
//   I made it return early if the slider is down.
//
hrchilds's avatar
hrchilds committed
803 804 805 806 807 808 809
//   Brad Whitlock, Mon Dec 8 15:39:56 PST 2003
//   I changed the code so the file server's open file is never changed unless
//   it is changed to the same file that is open. The purpose of that is to
//   expand databases that we previously displayed as a single file (like
//   .visit files). This also allows the selected files list to show the active
//   time state for the database.
//
hrchilds's avatar
hrchilds committed
810 811 812
//   Brad Whitlock, Tue Dec 30 14:31:03 PST 2003
//   I made it use the animation slider instead of sliderDown.
//
hrchilds's avatar
hrchilds committed
813 814 815 816
//   Brad Whitlock, Sat Jan 24 22:53:05 PST 2004
//   I made it use the new time and file scheme. I also added code to set
//   the values in the new activeTimeSlider combobox.
//
hrchilds's avatar
hrchilds committed
817 818 819 820 821 822
//   Brad Whitlock, Fri Mar 18 13:39:02 PST 2005
//   I improved how the time slider names are shortened so all of the sources
//   are taken into account, which can make it easier to distinguish between
//   time sliders when there are multiple time sliders whose names only
//   differ by the path to their database.
//
whitlocb's avatar
whitlocb committed
823 824 825
//   Brad Whitlock, Mon Dec 17 11:02:28 PST 2007
//   Made it use ids.
//
826 827 828
//   Cyrus Harrison, Fri Mar 12 09:46:31 PST 2010
//   Renamed from UpdateAnimationControls.
//
829 830 831 832
//   Hank Childs, Mon Nov  1 17:26:38 PDT 2010
//   Catch an exception.  Will crash the GUI when restoring sessions from
//   non-existent hosts otherwise.
//
hrchilds's avatar
hrchilds committed
833 834 835
// ****************************************************************************

void
836
QvisFilePanel::UpdateWindowInfo(bool doAll)
hrchilds's avatar
hrchilds committed
837
{
838
    if(fileServer == 0 || windowInfo == 0)
hrchilds's avatar
hrchilds committed
839 840
        return;

841
    TRY
hrchilds's avatar
hrchilds committed
842
    {
843 844 845
        //
        // Try and find a correlation for the active time slider.
        //
hkrishna's avatar
hkrishna committed
846
        //int activeTS = windowInfo->GetActiveTimeSlider();
847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
    
        // activeSource changed.  Update the file server.
        if(windowInfo->IsSelected(WindowInformation::ID_activeSource) || doAll)
        {
            OpenActiveSourceInFileServer();
        }
    
        //
        // If the active source, time slider, or time slider states change then
        // we need to update the file selection. Note - without this code, the
        // file selection never updates from what the user clicked.
        //
        if(windowInfo->IsSelected(WindowInformation::ID_activeSource) ||
           windowInfo->IsSelected(WindowInformation::ID_activeTimeSlider) ||
           windowInfo->IsSelected(WindowInformation::ID_timeSliderCurrentStates) ||
           doAll)
        {
            ExpandDatabases();
            // Highlight the selected file.
            UpdateFileSelection();
        }
hrchilds's avatar
hrchilds committed
868
    }
869
    CATCHALL
hrchilds's avatar
hrchilds committed
870
    {
871
        debug1 << "Unable to update window info." << endl;
hrchilds's avatar
hrchilds committed
872
    }
873
    ENDTRY
874 875
}

hrchilds's avatar
hrchilds committed
876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904

// ****************************************************************************
// Method: QvisFilePanel::ExpandDatabases
//
// Purpose: 
//   This method traverses the listviewitem tree and looks for the
//   selected file. When it finds the selected file, it turns it into
//   a database if the file has more than 1 state.
//
// Programmer: Brad Whitlock
// Creation:   Tue Sep 26 11:11:04 PDT 2000
//
// Modifications:
//   Brad Whitlock, Thu Oct 19 13:17:31 PST 2000
//   I removed a NULL pointer reference.
//
//   Brad Whitlock, Wed Mar 21 00:54:50 PDT 2001
//   Changed a call to the QvisListViewFileItem constructor.
//
//   Brad Whitlock, Thu Feb 28 13:39:38 PST 2002
//   Removed unnecessary recursion.
//
//   Brad Whitlock, Tue Mar 25 16:03:16 PST 2003
//   I added code to handle virtual databases.
//
//   Brad Whitlock, Wed May 14 16:19:50 PST 2003
//   I changed how we iterate though the items and I moved most of the
//   code to a new method.
//
hrchilds's avatar
hrchilds committed
905 906 907 908
//   Brad Whitlock, Wed Sep 17 18:18:50 PST 2003
//   Fixed a small bug with how the cycles are displayed when we have a
//   virtual file that does not have all of the cycle numbers.
//
hrchilds's avatar
hrchilds committed
909 910
//   Mark C. Miller, Wed Aug  2 19:58:44 PDT 2006
//   Changed interface to FileServerList::GetMetaData
911 912 913 914 915 916
//
//   Mark C. Miller, Fri Aug 10 23:11:55 PDT 2007
//   Checked to see if item has had its time/state forced and if not, but
//   the file server is currently forcing, set showing correct file info to
//   false. Also, Propogate knowledge that item was updated with metadata
//   that was forced to get accurate cycles/times.
hrchilds's avatar
hrchilds committed
917 918 919 920 921
// ****************************************************************************

void
QvisFilePanel::ExpandDatabases()
{
922
debug5 << "In QvisFilePanel::ExpandDatabases " << endl;
923

whitlocb's avatar
whitlocb committed
924 925
    int i = 0;
    int count = 0;
926

whitlocb's avatar
whitlocb committed
927
    // Create a list to store pointers to all of the items. We save the
hrchilds's avatar
hrchilds committed
928 929 930
    // pointers in an array because later when we expand databases, we
    // can't traverse using an iterator because as we add items, the
    // iterator is invalidated.
whitlocb's avatar
whitlocb committed
931 932 933 934 935 936
    QList<QvisFilePanelItem*> items;
    QTreeWidgetItemIterator itr(fileTree);
    while(*itr) 
    {
        items.append((QvisFilePanelItem*)*itr);
        ++itr;
937
    }
whitlocb's avatar
whitlocb committed
938
    count = items.count();
939

whitlocb's avatar
whitlocb committed
940 941 942
    // If there are no items, return early.
    if(count < 1)
        return;
hrchilds's avatar
hrchilds committed
943 944 945 946

    //
    // Iterate through the items and expand them if they are databases.
    //
hrchilds's avatar
hrchilds committed
947 948
    int nDBWithDifferentNStates = 0;

hrchilds's avatar
hrchilds committed
949 950
    for(i = 0; i < count; ++i)
    {
whitlocb's avatar
whitlocb committed
951
        QvisFilePanelItem *item = items[i];
hrchilds's avatar
hrchilds committed
952

hrchilds's avatar
hrchilds committed
953 954
        if(item != 0)
        {
whitlocb's avatar
whitlocb committed
955
            if(item->childCount() == 0)
hrchilds's avatar
hrchilds committed
956
            {
hrchilds's avatar
hrchilds committed
957 958
                if(item->timeState == -1)
                    ExpandDatabaseItem(item);
hrchilds's avatar
hrchilds committed
959
            }
hrchilds's avatar
hrchilds committed
960
            else if(HaveFileInformation(item->file))
hrchilds's avatar
hrchilds committed
961 962
            {
                // See if the file is a database
hrchilds's avatar
hrchilds committed
963 964 965 966 967
                const avtDatabaseMetaData *md =
                    fileServer->GetMetaData(item->file,
                                            GetStateForSource(item->file),
                                            FileServerList::ANY_STATE,
                                           !FileServerList::GET_NEW_MD);
hrchilds's avatar
hrchilds committed
968 969
                if(md != 0 && md->GetNumStates() > 1)
                {
whitlocb's avatar
whitlocb committed
970 971
                    if (fileServer->GetForceReadAllCyclesTimes() &&
                        !item->timeStateHasBeenForced)
972 973
                        SetFileShowsCorrectData(item->file, false);

hrchilds's avatar
hrchilds committed
974
                    if(md->GetNumStates() != item->childCount())
hrchilds's avatar
hrchilds committed
975
                    {
hrchilds's avatar
hrchilds committed
976 977 978 979 980 981 982
                        //
                        // We likely have a virtual database that has multiple time states
                        // per file. It would be a pain to fix it here so just note that
                        // it happened and do an update later.
                        //
                        ++nDBWithDifferentNStates;
                        SetFileShowsCorrectData(item->file, false);
hrchilds's avatar
hrchilds committed
983
                    }
hrchilds's avatar
hrchilds committed
984 985 986 987
                    else if(!FileShowsCorrectData(item->file))
                    {
                        bool useVirtualDBInfo = DisplayVirtualDBInformation(item->file);
                        int j;
988

whitlocb's avatar
whitlocb committed
989
                        QTreeWidgetItemIterator it(item); ++it;
hrchilds's avatar
hrchilds committed
990 991
                        for(j = 0; j < item->childCount(); ++j, ++it)
                        {
whitlocb's avatar
whitlocb committed
992 993
                            // Reset the label so that it shows the right values.
                            (*it)->setText(0, CreateItemLabel(md, j,useVirtualDBInfo)); 
hrchilds's avatar
hrchilds committed
994
                        }
hrchilds's avatar
hrchilds committed
995

hrchilds's avatar
hrchilds committed
996 997 998
                        // Remember that the item now has the correct information
                        // displayed through its children.
                        SetFileShowsCorrectData(item->file, true);
whitlocb's avatar
whitlocb committed
999 1000
                        item->timeStateHasBeenForced =
                            fileServer->GetForceReadAllCyclesTimes();
hrchilds's avatar
hrchilds committed
1001
                    }
hrchilds's avatar
hrchilds committed
1002
                }
1003
            }
hrchilds's avatar
hrchilds committed
1004 1005 1006
        }
    }

hrchilds's avatar
hrchilds committed
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
    //
    // If we had databases for which we were not showing the correct number of time
    // states update the file list later from the event loop so we have the
    // opportunity to correct the problem without having to try and do it in this
    // method.
    //
    if(nDBWithDifferentNStates > 0)
    {
        QTimer::singleShot(100, this, SLOT(internalUpdateFileList()));
    }
hrchilds's avatar
hrchilds committed
1017 1018 1019 1020 1021
}

// ****************************************************************************
// Method: QvisFilePanel::ExpandDatabaseItem
//
1022
// Purpose:
hrchilds's avatar
hrchilds committed
1023 1024 1025 1026 1027 1028 1029 1030 1031
//   Expands the item into a database if it is a database.
//
// Arguments:
//   item : The item to be expanded.
//
// Programmer: Brad Whitlock
// Creation:   Thu May 15 09:46:37 PDT 2003
//
// Modifications:
hrchilds's avatar
hrchilds committed
1032 1033 1034 1035
//   Brad Whitlock, Wed Sep 17 18:20:07 PST 2003
//   I corrected an error with how the cycle is displayed for virtual files
//   that don't know all of the cycles.
//
hrchilds's avatar
hrchilds committed
1036 1037 1038
//   Brad Whitlock, Mon Oct 13 15:37:56 PST 2003
//   Moved code into CreateItemLabel method.
//
hrchilds's avatar
hrchilds committed
1039 1040 1041 1042
//   Brad Whitlock, Fri Oct 24 14:12:45 PST 2003
//   Fixed a bug that caused expanded databases to sometimes get the wrong
//   database in their child time states.
//
hrchilds's avatar
hrchilds committed
1043 1044 1045 1046
//   Brad Whitlock, Mon Dec 29 11:34:42 PDT 2003
//   I changed the code so we can correctly display virtual databases that
//   have multiple time states per file.
//
hrchilds's avatar
hrchilds committed
1047 1048 1049 1050
//   Brad Whitlock, Tue Apr 6 12:23:11 PDT 2004
//   I changed the code so it sets the time state for files that we've
//   never seen before to 0 so it is not the default -1.
//
whitlocb's avatar
whitlocb committed
1051 1052 1053
//   Cyrus Harrison, Tue Jul  1 16:04:25 PDT 2008
//   Initial Qt4 Port.
// 
hrchilds's avatar
hrchilds committed
1054 1055 1056
// ****************************************************************************

void
whitlocb's avatar
whitlocb committed
1057
QvisFilePanel::ExpandDatabaseItem(QvisFilePanelItem *item)
hrchilds's avatar
hrchilds committed
1058 1059 1060 1061 1062 1063
{
    //
    // It could be that this method is being called on the child timestate of 
    // a previously expanded database. If that is the case, then the parent
    // will exist and it will have the same filename as the item.
    //
whitlocb's avatar
whitlocb committed
1064
    QvisFilePanelItem *parent = (QvisFilePanelItem *)item->parent();
hrchilds's avatar
hrchilds committed
1065 1066 1067 1068 1069
    if(parent != 0 && parent->file == item->file)
        return;

    if(fileServer->HaveOpenedFile(item->file))
    {
hrchilds's avatar
hrchilds committed
1070 1071 1072 1073 1074 1075 1076
        ExpandDatabaseItemUsingMetaData(item);
    }
    else if(item->file.IsVirtual())
    {
        ExpandDatabaseItemUsingVirtualDBDefinition(item);
    }
}
hrchilds's avatar
hrchilds committed
1077

hrchilds's avatar
hrchilds committed
1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091
// ****************************************************************************
// Method: QvisFilePanel::ExpandDatabaseItemUsingMetaData
//
// Purpose: 
//   Expands a database item as a database, which means that it uses the
//   number of time states to display the database.
//
// Arguments:
//   item : The item to expand.
//
// Programmer: Brad Whitlock
// Creation:   Mon Dec 29 12:22:41 PDT 2003
//
// Modifications:
hrchilds's avatar
hrchilds committed
1092 1093 1094
//   Brad Whitlock, Tue Apr 6 12:22:24 PDT 2004
//   I made it set files with 1 time state to have their time state be 0.
//
hrchilds's avatar
hrchilds committed
1095 1096
//   Mark C. Miller, Wed Aug  2 19:58:44 PDT 2006
//   Changed interface to FileServerList::GetMetaData
1097 1098 1099 1100
//   Mark C. Miller, Fri Aug 10 23:11:55 PDT 2007
//
//   Propogated knowledge that item was updated with metadata that was forced
//   to get accurate cycles/times.
whitlocb's avatar
whitlocb committed
1101 1102 1103 1104
//
//   Cyrus Harrison, Tue Jul  1 16:04:25 PDT 2008
//   Initial Qt4 Port.
// 
hrchilds's avatar
hrchilds committed
1105
// ****************************************************************************
hrchilds's avatar
hrchilds committed
1106

hrchilds's avatar
hrchilds committed
1107
void
whitlocb's avatar
whitlocb committed
1108
QvisFilePanel::ExpandDatabaseItemUsingMetaData(QvisFilePanelItem *item)
hrchilds's avatar
hrchilds committed
1109 1110
{
    // See if the file is a database
hrchilds's avatar
hrchilds committed
1111 1112 1113 1114 1115
    const avtDatabaseMetaData *md =
        fileServer->GetMetaData(item->file,
                                GetStateForSource(item->file),
                                FileServerList::ANY_STATE,
                               !FileServerList::GET_NEW_MD);
hrchilds's avatar
hrchilds committed
1116 1117 1118
    if(md != 0)
    {
        if(md->GetNumStates() > 1)
hrchilds's avatar
hrchilds committed
1119
        {
whitlocb's avatar
whitlocb committed
1120
            fileTree->blockSignals(true);
hrchilds's avatar
hrchilds committed
1121 1122 1123
            bool useVirtualDBInfo = DisplayVirtualDBInformation(item->file);
            for(int i = 0; i < md->GetNumStates(); ++i)
            {
whitlocb's avatar
whitlocb committed
1124 1125 1126 1127 1128
                QvisFilePanelItem *fi = new QvisFilePanelItem(
                                   item, 
                                   CreateItemLabel(md, i, useVirtualDBInfo),
                                   item->file, QvisFilePanelItem::FILE_NODE, i);
                fi->setExpanded(false);
hrchilds's avatar
hrchilds committed
1129
            }
whitlocb's avatar
whitlocb committed
1130 1131
            item->timeStateHasBeenForced =
                fileServer->GetForceReadAllCyclesTimes();
hrchilds's avatar
hrchilds committed
1132

hrchilds's avatar
hrchilds committed
1133
            // Set the database pixmap.
whitlocb's avatar
whitlocb committed
1134 1135
            item->setIcon(0, *databasePixmap);
            fileTree->blockSignals(false);
hrchilds's avatar
hrchilds committed
1136

hrchilds's avatar
hrchilds committed
1137 1138 1139 1140 1141 1142 1143 1144
            // Remember that the item now has the correct information
            // displayed through its children.
            SetFileShowsCorrectData(item->file, true);
        }
#if 0
        else
            item->timeState = 0;
#endif
hrchilds's avatar
hrchilds committed
1145
    }
hrchilds's avatar
hrchilds committed
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
}

// ****************************************************************************
// Method: QvisFilePanel::ExpandDatabaseItemUsingVirtualDBDefinition
//
// Purpose: 
//   Expands a database item as a virtual database when possible. Otherwise, if
//   the virtual database has more time states than files, it is displayed
//   as a database.
//
// Arguments:
//   item : The item that gets expanded.
//
// Programmer: Brad Whitlock
// Creation:   Mon Dec 29 12:23:37 PDT 2003
//
// Modifications:
whitlocb's avatar
whitlocb committed
1163 1164 1165
//   Cyrus Harrison, Tue Jul  1 16:04:25 PDT 2008
//   Initial Qt4 Port.
// 
hrchilds's avatar
hrchilds committed
1166 1167 1168
// ****************************************************************************

void
whitlocb's avatar
whitlocb committed
1169
QvisFilePanel::ExpandDatabaseItemUsingVirtualDBDefinition(QvisFilePanelItem *item)
hrchilds's avatar
hrchilds committed
1170 1171
{
    if(DisplayVirtualDBInformation(item->file))
hrchilds's avatar
hrchilds committed
1172
    {
whitlocb's avatar
whitlocb committed
1173
        fileTree->blockSignals(true);
hrchilds's avatar
hrchilds committed
1174 1175 1176 1177

        // Get the virtual file definition instead of reading the metadata.
        stringVector files(fileServer->GetVirtualFileDefinition(item->file));

hkrishna's avatar
hkrishna committed
1178
        for(size_t i = 0; i < files.size(); ++i)
hrchilds's avatar
hrchilds committed
1179 1180
        {
            QString label(files[i].c_str());
whitlocb's avatar
whitlocb committed
1181 1182 1183
            QvisFilePanelItem *fi = new QvisFilePanelItem(item, label, item->file,
                                                  QvisFilePanelItem::FILE_NODE, i);
            fi->setExpanded(false);
hrchilds's avatar
hrchilds committed
1184 1185 1186
        }

        // Set the database pixmap.
whitlocb's avatar
whitlocb committed
1187 1188
        item->setIcon(0, *databasePixmap);
        fileTree->blockSignals(false);
hrchilds's avatar
hrchilds committed
1189 1190 1191

        // Remember that the item does not have the correct information
        // displayed through its children since we have not opened it yet.
hrchilds's avatar
hrchilds committed
1192
        SetFileShowsCorrectData(item->file, false);
hrchilds's avatar
hrchilds committed
1193
    }
hrchilds's avatar
hrchilds committed
1194 1195 1196 1197 1198 1199
    else if(item->file.IsVirtual())
    {
        // The database is virtual but it must have more time states than
        // files so we should expand it as a database.
        ExpandDatabaseItemUsingMetaData(item);
    }
hrchilds's avatar
hrchilds committed
1200 1201
}

hrchilds's avatar
hrchilds committed
1202 1203 1204 1205 1206 1207 1208 1209 1210
// ****************************************************************************
// Method: QvisFilePanel::CreateItemLabel
//
// Purpose: 
//   Creates the label for the item at the requested database timestate.
//
// Arguments:
//   md : The metadata to use when computing the label.
//   ts : The timestate to use when computing the label.
hrchilds's avatar
hrchilds committed
1211 1212
//   useVirtualDBInformation : Whether or not to use virtual DB information
//                             if it is available.
hrchilds's avatar
hrchilds committed
1213 1214 1215 1216 1217 1218 1219 1220 1221
//
// Returns:    A string to use in the file panel to help display the file.
//
// Note:       
//
// Programmer: Brad Whitlock
// Creation:   Mon Oct 13 15:42:17 PST 2003
//
// Modifications:
hrchilds's avatar
hrchilds committed
1222 1223 1224 1225
//   Brad Whitlock, Mon Dec 29 10:15:24 PDT 2003
//   I added the useVirtualDBInformation argument so we can force this method
//   to ignore the fact that a database may be virtual.
//
hrchilds's avatar
hrchilds committed
1226 1227 1228
// ****************************************************************************

QString
hrchilds's avatar
hrchilds committed
1229 1230
QvisFilePanel::CreateItemLabel(const avtDatabaseMetaData *md, int ts,
    bool useVirtualDBInformation)
hrchilds's avatar
hrchilds committed
1231
{
1232
    QString label, space(" ");
hrchilds's avatar
hrchilds committed
1233 1234 1235

    if(timeStateFormat.GetDisplayMode() == TimeFormat::Cycles)
    {
hkrishna's avatar
hkrishna committed
1236
        int cycle = ((size_t)ts < md->GetCycles().size()) ? md->GetCycles()[ts] : ts;
hrchilds's avatar
hrchilds committed
1237
        if(useVirtualDBInformation && md->GetIsVirtualDatabase())
hrchilds's avatar
hrchilds committed
1238 1239 1240
        {
            QualifiedFilename name(md->GetTimeStepNames()[ts]);
            label = QString(name.filename.c_str()) +
1241
                    space + QString(tr("cycle")) + space + FormattedCycleString(cycle);
hrchilds's avatar
hrchilds committed
1242 1243
        }
        else
1244
            label = QString(tr("cycle")) + space + FormattedCycleString(cycle);
hrchilds's avatar
hrchilds committed
1245 1246 1247
    }
    else if(timeStateFormat.GetDisplayMode() == TimeFormat::Times)
    {
hkrishna's avatar
hkrishna committed
1248 1249
        double t = ((size_t)ts < md->GetTimes().size()) ? md->GetTimes()[ts] : double(ts);
        bool   accurate = ((size_t)ts < md->GetTimes().size()) ?
hrchilds's avatar
hrchilds committed
1250
                          md->IsTimeAccurate(ts) : false;
hrchilds's avatar
hrchilds committed
1251
        if(useVirtualDBInformation && md->GetIsVirtualDatabase())
hrchilds's avatar
hrchilds committed
1252 1253 1254 1255
        {
            QualifiedFilename name(md->GetTimeStepNames()[ts]);

            label = QString(name.filename.c_str()) +
1256
                    space + QString(tr("time")) + space + FormattedTimeString(t, accurate);
hrchilds's avatar
hrchilds committed
1257 1258
        }
        else
1259
            label = QString(tr("time")) + space + FormattedTimeString(t, accurate);
hrchilds's avatar
hrchilds committed
1260 1261 1262
    }
    else if(timeStateFormat.GetDisplayMode() == TimeFormat::CyclesAndTimes)
    {
hkrishna's avatar
hkrishna committed
1263 1264 1265
        int    cycle = ((size_t)ts < md->GetCycles().size()) ? md->GetCycles()[ts] : ts;
        double t = ((size_t)ts < md->GetTimes().size()) ? md->GetTimes()[ts] : double(ts);
        bool   accurate = ((size_t)ts < md->GetTimes().size()) ?
hrchilds's avatar
hrchilds committed
1266
                          md->IsTimeAccurate(ts) : false;
hrchilds's avatar
hrchilds committed
1267
        if(useVirtualDBInformation && md->GetIsVirtualDatabase())
hrchilds's avatar
hrchilds committed
1268 1269 1270 1271
        {
            QualifiedFilename name(md->GetTimeStepNames()[ts]);

            label = QString(name.filename.c_str()) +
1272 1273
                    space + QString(tr("cycle")) + space + FormattedCycleString(cycle) +
                    space + space + QString(tr("time")) + space + FormattedTimeString(t, accurate);
hrchilds's avatar
hrchilds committed
1274 1275 1276
        }
        else
        {
1277 1278
            label = QString(tr("cycle")) + space + FormattedCycleString(cycle) +
                    space + space + QString(tr("time")) + space + FormattedTimeString(t, accurate);
hrchilds's avatar
hrchilds committed
1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340
        }
    }

    return label;
}

// ****************************************************************************
// Method: QvisFilePanel::FormattedCycleString
//
// Purpose: 
//   Returns a formatted cycle string.
//
// Arguments:
//   cycle : The cycle that we want to convert to a string.
//
// Returns:    A formatted cycle string.
//
// Note:       
//
// Programmer: Brad Whitlock
// Creation:   Tue Oct 14 11:31:42 PDT 2003
//
// Modifications:
//   
// ****************************************************************************

QString
QvisFilePanel::FormattedCycleString(const int cycle) const
{
    QString retval;
    retval.sprintf("%04d", cycle);
    return retval;
}

// ****************************************************************************
// Method: QvisFilePanel::FormattedTimeString
//
// Purpose: 
//   Returns a formatted time string.
//
// Arguments:
//   t        : The time value to format.
//   accurate : Whether the time can be believed. If it can't then we return
//              a question mark string.
//
// Returns:    A formatted time string.
//
// Programmer: Brad Whitlock
// Creation:   Mon Oct 13 16:03:37 PST 2003
//
// Modifications:
//   
// ****************************************************************************

QString
QvisFilePanel::FormattedTimeString(const double t, bool accurate) const
{
    QString retval("?");
    if(accurate)
    {
        QString formatString;
        formatString.sprintf("%%.%dg", timeStateFormat.GetPrecision());
whitlocb's avatar
whitlocb committed
1341
        retval.sprintf(formatString.toStdString().c_str(), t);
hrchilds's avatar
hrchilds committed
1342 1343 1344 1345
    }
    return retval;
}

hrchilds's avatar
hrchilds committed
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359
// ****************************************************************************
// Method: QvisFilePanel::DisplayVirtualDBInformation
//
// Purpose: 
//   Returns whether or not we should display a virtual database as a
//   virtual database. Sometimes, virtual databases have more states than
//   files. In that case, we want to show them as databases instead of
//   virtual databases.
//
// Programmer: Brad Whitlock
// Creation:   Mon Dec 29 11:28:59 PDT 2003
//
// Modifications:
//   
hrchilds's avatar
hrchilds committed
1360 1361
//   Mark C. Miller, Wed Aug  2 19:58:44 PDT 2006
//   Changed interface to FileServerList::GetMetaData
hrchilds's avatar
hrchilds committed
1362 1363 1364 1365 1366 1367 1368
// ****************************************************************************

bool
QvisFilePanel::DisplayVirtualDBInformation(const QualifiedFilename &file) const
{
    bool retval = true;

hrchilds's avatar
hrchilds committed
1369 1370 1371 1372
    const avtDatabaseMetaData *md =
        fileServer->GetMetaData(file, GetStateForSource(file),
                                FileServerList::ANY_STATE,
                               !FileServerList::GET_NEW_MD);
hrchilds's avatar
hrchilds committed
1373 1374 1375 1376 1377 1378 1379 1380 1381
    if(md != 0 && md->GetNumStates() > 1 && md->GetIsVirtualDatabase())
    {
        int nts = fileServer->GetVirtualFileDefinitionSize(file);
        retval = (nts == md->GetNumStates());
    }

    return retval;
}

hrchilds's avatar
hrchilds committed
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
// ****************************************************************************
// Method: QvisFilePanel::UpdateFileSelection
//
// Purpose: 
//   Highlights the selected file in the file list view.
//
// Programmer: Brad Whitlock
// Creation:   Wed Sep 13 11:48:35 PDT 2000
//
// Modifications:
//   Brad Whitlock, Tue Mar 20 23:39:14 PST 2001
//   Changed code so it takes directories into account.
//
//   Brad Whitlock, Thu Feb 28 13:34:11 PST 2002
//   Rewrote it so it handles preservation of tree expansion.
//
//   Eric Brugger, Mon Dec 16 13:05:01 PST 2002
//   I seperated the concepts of state and frame, since they are no longer
//   equivalent with keyframe support.
//
//   Brad Whitlock, Wed Apr 2 10:13:12 PDT 2003
//   I made it try and use the metadata for the open file instead of the
//   globalAtts which are not reliable.
//
hrchilds's avatar
hrchilds committed
1406 1407 1408
//   Brad Whitlock, Sat Jan 24 21:38:48 PST 2004
//   I modified it to use the active time slider and database correlation.
//
hrchilds's avatar
hrchilds committed
1409 1410 1411 1412
//   Brad Whitlock, Tue Apr 6 14:05:42 PST 2004
//   I changed it so it returns early if we're not allowing file
//   selection changes.
//
hrchilds's avatar
hrchilds committed
1413 1414 1415
//   Brad Whitlock, Mon Dec 20 16:19:23 PST 2004
//   Added code to update the state of the Replace button.
//
whitlocb's avatar
whitlocb committed
1416 1417 1418
//   Cyrus Harrison, Tue Jul  1 16:04:25 PDT 2008
//   Initial Qt4 Port.
// 
cyrush's avatar
cyrush committed
1419 1420 1421
//   Cyrus Harrison, Thu Dec  4 08:09:20 PST 2008
//   Made sure the current item is visible via scroll to item. 
// 
1422 1423 1424 1425 1426 1427 1428 1429 1430
//   Jeremy Meredith, Tue Feb  5 16:00:12 EST 2013
//   This can take a while if we have lots and lots of time steps.
//   Don't update the selection if the file panel is not visible.  We
//   will force it to update when we make the file panel visible
//   again.  (Following the mantra of minimal change, at the moment,
//   this is the only action I have added this check to, as it is the
//   only one causing performance issues, even though one might argue
//   other methods should have the same bypass check.)
//
hrchilds's avatar
hrchilds committed
1431 1432 1433 1434 1435
// ****************************************************************************

void
QvisFilePanel::UpdateFileSelection()
{
1436 1437 1438
    if (!isVisible())
        return;

hrchilds's avatar
hrchilds committed
1439 1440
    // Set the text for the open file button.
    if(fileServer->GetOpenFile().Empty())
1441
        openButton->setText(tr("Open"));
hrchilds's avatar
hrchilds committed
1442 1443
    else
    {
1444
        openButton->setText(tr("ReOpen"));
hrchilds's avatar
hrchilds committed
1445 1446 1447 1448 1449
        openButton->setEnabled(true);
    }

    // If the file changed, then we have to update the selected item.
    blockSignals(true);