1#include "ImageTreeWidget.h" 
   10#include <QProgressBar> 
   16#include "IException.h" 
   20#include "ImageTreeWidgetItem.h" 
   21#include "ProgressBar.h" 
   33    m_queuedSelectionChanged = 
false;
 
   34    m_directory = directory;
 
   38    ImageTreeWidgetItem::TreeColumn col = ImageTreeWidgetItem::NameColumn;
 
   39    while(col < ImageTreeWidgetItem::BlankColumn) {
 
   40      header << ImageTreeWidgetItem::treeColumnToString(col);
 
   41      col = (ImageTreeWidgetItem::TreeColumn)(col + 1);
 
   44    setHeaderLabels(header);
 
   46    hideColumn(ImageTreeWidgetItem::ImageColumn);
 
   47    hideColumn(ImageTreeWidgetItem::LabelColumn);
 
   48    hideColumn(ImageTreeWidgetItem::ResolutionColumn);
 
   49    hideColumn(ImageTreeWidgetItem::EmissionAngleColumn);
 
   50    hideColumn(ImageTreeWidgetItem::IncidenceAngleColumn);
 
   51    hideColumn(ImageTreeWidgetItem::PhaseAngleColumn);
 
   52    hideColumn(ImageTreeWidgetItem::AspectRatioColumn);
 
   53    hideColumn(ImageTreeWidgetItem::SampleResolutionColumn);
 
   54    hideColumn(ImageTreeWidgetItem::LineResolutionColumn);
 
   55    hideColumn(ImageTreeWidgetItem::NorthAzimuthColumn);
 
   56    hideColumn(ImageTreeWidgetItem::BlankColumn);
 
   60        FileName(QString(
"$HOME/.Isis/%1/fileList.config").arg(QApplication::applicationName()))
 
   62        QSettings::NativeFormat);
 
   63    settings.beginGroup(
"ColumnsVisible");
 
   65    col = ImageTreeWidgetItem::FootprintColumn;
 
   66    while(col < ImageTreeWidgetItem::BlankColumn) {
 
   67      bool visible = !isColumnHidden(col);
 
   69      if (settings.value(QString(
"%1Visible").arg(ImageTreeWidgetItem::treeColumnToString(col)),
 
   70                         visible).
toBool() != visible) {
 
   77      col = (ImageTreeWidgetItem::TreeColumn)(col + 1);
 
   81    setContextMenuPolicy(Qt::DefaultContextMenu);
 
   83    setSortingEnabled(
true);
 
   84    sortItems(ImageTreeWidgetItem::NameColumn, Qt::AscendingOrder);
 
   88    connect(
this, SIGNAL(itemSelectionChanged()),
 
   89            this, SLOT(onSelectionChanged()));
 
   93    connect(
this, SIGNAL(queueSelectionChanged()),
 
   94            this, SLOT(onQueuedSelectionChanged()), Qt::QueuedConnection);
 
   97    connect(
this, SIGNAL(queueReadDisplayProperties()),
 
   98            this, SLOT(onQueuedReadDisplayProperties()), Qt::QueuedConnection);
 
  100    setSelectionMode(QAbstractItemView::ExtendedSelection);
 
  101    setDragDropOverwriteMode(
false);
 
 
  105  ImageTreeWidget::~ImageTreeWidget() {
 
  107    foreach(contextAction, actions()) {
 
  108      removeAction(contextAction);
 
  113  QList<QAction *> ImageTreeWidget::actions() {
 
  115    QList<QAction *> results;
 
  116    if (!m_setFileListColsAct) {
 
  117      m_setFileListColsAct = 
new QAction(
"Set Current File List &Columns as Default", 
this);
 
  118      m_setFileListColsAct->setWhatsThis(tr(
"Use the currently visible columns in the file list as " 
  119            "the default when no project has been opened"));
 
  120      connect(m_setFileListColsAct, SIGNAL(triggered(
bool)),
 
  121              this, SLOT(setDefaultFileListCols()));
 
  123    results.append(m_setFileListColsAct);
 
  136    verticalScrollBar()->setMaximum(verticalScrollBar()->maximum() + 25);
 
  144      imageListItem = invisibleRootItem();
 
  146    if (groupName.isEmpty()) {
 
  147      groupName = QString(
"Group %1").arg(imageListItem->childCount() + 1);
 
  151    result->setText(0, groupName);
 
  152    result->setFlags(Qt::ItemIsEditable |
 
  153                    Qt::ItemIsUserCheckable |
 
  155                    Qt::ItemIsSelectable |
 
  156                    Qt::ItemIsDragEnabled |
 
  157                    Qt::ItemIsDropEnabled);
 
  158    result->setData(0, Qt::UserRole, ImageGroupType);
 
  161      index = imageListItem->childCount();
 
  164    imageListItem->insertChild(index, result);
 
  167    result->setExpanded(
true);
 
  173  QTreeWidgetItem *ImageTreeWidget::createImageListNameItem(QString name) {
 
  175    result->setText(0, name);
 
  176    result->setData(0, Qt::UserRole, ImageListNameType);
 
  177    result->setExpanded(
true);
 
  183  void ImageTreeWidget::refit() {
 
  184    ImageTreeWidgetItem::TreeColumn col = ImageTreeWidgetItem::NameColumn;
 
  185    while(col < ImageTreeWidgetItem::BlankColumn) {
 
  187      if (col == ImageTreeWidgetItem::NameColumn) {
 
  188        QList<bool> expandedStates;
 
  189        for (
int groupIndex = 0; groupIndex < topLevelItemCount(); groupIndex++) {
 
  190          expandedStates.append(topLevelItem(groupIndex)->isExpanded());
 
  191          topLevelItem(groupIndex)->setExpanded(
true);
 
  194        resizeColumnToContents(col);
 
  196        for (
int groupIndex = 0; groupIndex < topLevelItemCount(); groupIndex++) {
 
  197          topLevelItem(groupIndex)->setExpanded(expandedStates[groupIndex]);
 
  201        resizeColumnToContents(col);
 
  204      col = (ImageTreeWidgetItem::TreeColumn)(col + 1);
 
  209  void ImageTreeWidget::disableSort() {
 
  210    sortItems(ImageTreeWidgetItem::BlankColumn, Qt::AscendingOrder);
 
  214  void ImageTreeWidget::enqueueReadDisplayProperties(ImageTreeWidgetItem *item) {
 
  215    m_queuedReadDisplayPropertiesItems.append(item);
 
  217    if (m_queuedReadDisplayPropertiesItems.count() == 1) {
 
  218      emit queueReadDisplayProperties();
 
  223  QList<QAction *> ImageTreeWidget::getViewActions() {
 
  224    if (m_viewActs.empty()) {
 
  225      ImageTreeWidgetItem::TreeColumn col =
 
  226          ImageTreeWidgetItem::FootprintColumn;
 
  228      while(col < ImageTreeWidgetItem::BlankColumn) {
 
  230        showHide->setData(col);
 
  232        connect(showHide, SIGNAL(triggered()),
 
  233                this, SLOT(toggleColumnVisible()));
 
  235        m_viewActs.append(showHide);
 
  237        col = (ImageTreeWidgetItem::TreeColumn)(col + 1);
 
  247  void ImageTreeWidget::updateViewActs() {
 
  248    if (!m_viewActs.empty()) {
 
  249      int viewActIndex = 0;
 
  250      ImageTreeWidgetItem::TreeColumn col =
 
  251          ImageTreeWidgetItem::FootprintColumn;
 
  253      while(col < ImageTreeWidgetItem::BlankColumn) {
 
  254        bool visible = !isColumnHidden(col);
 
  255        QAction *showHide = m_viewActs[viewActIndex];
 
  258          showHide->setText(
"Show " +
 
  259              ImageTreeWidgetItem::treeColumnToString(col) + 
" Column");
 
  262          showHide->setText(
"Hide " +
 
  263              ImageTreeWidgetItem::treeColumnToString(col) + 
" Column");
 
  266        col = (ImageTreeWidgetItem::TreeColumn)(col + 1);
 
  276  void ImageTreeWidget::setDefaultFileListCols() {
 
  279          QString(
"$HOME/.Isis/%1/fileList.config").arg(QApplication::applicationName()))
 
  281        QSettings::NativeFormat);
 
  282    settings.beginGroup(
"ColumnsVisible");
 
  284    ImageTreeWidgetItem::TreeColumn col =
 
  285        ImageTreeWidgetItem::FootprintColumn;
 
  287    while(col < ImageTreeWidgetItem::BlankColumn) {
 
  288      bool visible = !isColumnHidden(col);
 
  290      settings.setValue(QString(
"%1Visible").arg(ImageTreeWidgetItem::treeColumnToString(col)),
 
  293      col = (ImageTreeWidgetItem::TreeColumn)(col + 1);
 
  300  ImageTreeWidgetItem *ImageTreeWidget::prepCube(ImageList *imageList, Image *image) {
 
  302      ImageTreeWidgetItem *item = 
new ImageTreeWidgetItem(imageList, image);
 
  304      connect(image->displayProperties(), SIGNAL(destroyed(
QObject *)),
 
  305              this, SLOT(imageDeleted(
QObject *)));
 
  306      connect(image->displayProperties(), SIGNAL(propertyChanged(DisplayProperties *)),
 
  307              this, SLOT(propertiesChanged(DisplayProperties *)));
 
  309      m_displayPropsToTreeItemLookup[image->displayProperties()] = item;
 
  313    catch(IException &e) {
 
  321  ImageList ImageTreeWidget::imagesInView() {
 
  324    QTreeWidgetItemIterator it(
this, QTreeWidgetItemIterator::UserFlag);
 
  329      if (item->type() == QTreeWidgetItem::UserType) {
 
  330        ImageTreeWidgetItem *mosItem = (ImageTreeWidgetItem *)item;
 
  331        results.append(mosItem->image());
 
  341  ImageTreeWidget::ImagePosition::ImagePosition() {
 
  346  ImageTreeWidget::ImagePosition::ImagePosition(
int outerIndex, 
int innerIndex) {
 
  349    setPosition(outerIndex, innerIndex);
 
  353  ImageTreeWidget::ImagePosition::ImagePosition(
const ImagePosition &other) :
 
  354      m_group(other.m_group), m_index(other.m_index) {
 
  358  ImageTreeWidget::ImagePosition::~ImagePosition() {
 
  363  void ImageTreeWidget::ImagePosition::setPosition(
int group, 
int index) {
 
  364    if (group >= 0 && index >= 0) {
 
  374  int ImageTreeWidget::ImagePosition::group()
 const {
 
  379  int ImageTreeWidget::ImagePosition::index()
 const {
 
  384  bool ImageTreeWidget::ImagePosition::isValid()
 const {
 
  385    return (m_group != -1 && m_index != -1);
 
  389  void ImageTreeWidget::ImagePosition::swap(ImagePosition &other) {
 
  390    std::swap(m_group, other.m_group);
 
  391    std::swap(m_index, other.m_index);
 
  395  bool ImageTreeWidget::ImagePosition::operator<(
const ImagePosition &rhs) {
 
  396    bool lessThan = 
false;
 
  397    if (group() < rhs.group()) {
 
  400    else if (group() == rhs.group() && index() < rhs.index()) {
 
  408  ImageTreeWidget::ImagePosition &ImageTreeWidget::ImagePosition::operator=(
 
  409      const ImagePosition &rhs) {
 
  410    ImagePosition copy(rhs);
 
  417  void ImageTreeWidget::ImagePosition::init() {
 
  422  void ImageTreeWidget::dropEvent(QDropEvent *event) {
 
  429      if(droppedAtGroup->type() != QTreeWidgetItem::Type)
 
  430        droppedAtGroup = droppedAtItem->parent();
 
  432      bool draggedGroup = groupInList(selectedItems());
 
  433      bool draggedItem = mosaicItemInList(selectedItems());
 
  436      if(draggedItem && !draggedGroup) {
 
  437        int insertPosition = 0;
 
  439        if(droppedAtGroup != droppedAtItem) {
 
  440          insertPosition = droppedAtGroup->indexOfChild(droppedAtItem) + 1;
 
  444        foreach(toBeMoved, selectedItems()) {
 
  445          if(toBeMoved != droppedAtItem) {
 
  450            int childOrigIndex = parent->indexOfChild(toBeMoved);
 
  452            parent->takeChild(childOrigIndex);
 
  454            int actualInsertPos = insertPosition;
 
  456            if(parent == droppedAtGroup && childOrigIndex < insertPosition)
 
  459            droppedAtGroup->insertChild(actualInsertPos, toBeMoved);
 
  462            if(insertPosition != droppedAtGroup->childCount())
 
  467      else if(!draggedItem && draggedGroup) {
 
  470        foreach(toBeMoved, selectedItems()) {
 
  471          if(toBeMoved != droppedAtGroup) {
 
  472            int dropPosition = indexOfTopLevelItem(droppedAtGroup);
 
  474            takeTopLevelItem(indexOfTopLevelItem(toBeMoved));
 
  475            insertTopLevelItem(dropPosition, toBeMoved);
 
  598    switch(event->type()) {
 
  599      case QEvent::MouseButtonPress: {
 
  600        if (event->button() == Qt::RightButton &&
 
  601           itemAt(event->pos()) == NULL) {
 
  602          setCurrentItem(NULL);
 
  611    QTreeWidget::mousePressEvent(event);
 
 
  615  void ImageTreeWidget::contextMenuEvent(QContextMenuEvent *event) {
 
  616    ImageList selectedCubes = selectedDisplays();
 
  618    bool selectedGroup = groupInList(selectedItems());
 
  619    bool selectedCube = mosaicItemInList(selectedItems());
 
  624      project = m_directory->
project();
 
  626    QList<QAction *> supportedActions = selectedCubes.supportedActions(project);
 
  629      supportedActions.append(NULL);
 
  634    foreach(
QAction *action, supportedActions) {
 
  636        menu.addAction(action);
 
  643    if (!selectedCube && selectedGroup) {
 
  644      if (selectedItems().size() == 1 && selectedItems()[0]->childCount()) {
 
  645        QAction *close = menu.addAction(
"Close Cubes in Group");
 
  646        connect(close, SIGNAL(triggered()),
 
  647                this, SLOT(requestCloseSelected()));
 
  650      if (selectedItems().size() == 1) {
 
  651        QAction *rename = menu.addAction(
"Rename Group");
 
  652        connect(rename, SIGNAL(triggered()),
 
  653                this, SLOT(renameSelectedGroup()));
 
  655        QAction *group = menu.addAction(
"Insert Group");
 
  656        connect(group, SIGNAL(triggered()),
 
  662      if (selectedItems().size() == 1)
 
  663        removeGroup = menu.addAction(
"Delete Group");
 
  665        removeGroup = menu.addAction(
"Delete Groups");
 
  667      connect(removeGroup, SIGNAL(triggered()),
 
  668              this, SLOT(deleteSelectedGroups()));
 
  671    if (selectedCube && !selectedGroup) {
 
  674      if (selectedItems().size() == 1)
 
  675        close = menu.addAction(
"Close Cube");
 
  677        close = menu.addAction(
"Close Cubes");
 
  679      connect(close, SIGNAL(triggered()),
 
  680              this, SLOT(requestCloseSelected()));
 
  683    if (!selectedCube && !selectedGroup) {
 
  684      QAction *group = menu.addAction(
"Add Group");
 
  686      connect(group, SIGNAL(triggered()),
 
  690    menu.exec(event->globalPos());
 
  704    QString newGroupParentText = 
"";
 
  706    if (selectedItems().size() == 1) {
 
  707      if (selectedItems()[0]->data(0, Qt::UserRole).
toInt() == ImageGroupType) {
 
  708        newGroupParent = selectedItems()[0]->parent();
 
  709        if (newGroupParent) {
 
  710          index = newGroupParent->indexOfChild(selectedItems()[0]);
 
  713          newGroupParent = invisibleRootItem();
 
  714          index = indexOfTopLevelItem(selectedItems()[0]);
 
  717      else if (selectedItems()[0]->data(0, Qt::UserRole).
toInt() == ImageListNameType) {
 
  718        newGroupParent = selectedItems()[0];
 
  722    if (newGroupParent) {
 
  723      newGroupParentText = newGroupParent->text(0);
 
  725    return addGroup(newGroupParentText, 
"", index);
 
 
  729  void ImageTreeWidget::deleteSelectedGroups() {
 
  731    requestCloseSelected();
 
  734    foreach(toBeDeleted, selectedItems()) {
 
  735      if (toBeDeleted->type() == QTreeWidgetItem::Type) {
 
  742  void ImageTreeWidget::imageDeleted(
QObject *imageObj) {
 
  743    ImageDisplayProperties *imagedisp = (ImageDisplayProperties *)imageObj;
 
  744    ImageTreeWidgetItem *item = treeItem(imagedisp);
 
  746    if (item && item->parent()) {
 
  747      m_displayPropsToTreeItemLookup.remove(imagedisp);
 
  750      delete item->parent()->takeChild( item->parent()->indexOfChild(item) );
 
  756    if (item->type() == QTreeWidgetItem::UserType) {
 
  757      ((ImageTreeWidgetItem *)item)->update(
true);
 
  762  void ImageTreeWidget::onSelectionChanged() {
 
  763    if (!m_queuedSelectionChanged) {
 
  764      emit queueSelectionChanged();
 
  765      m_queuedSelectionChanged = 
true;
 
  770  void ImageTreeWidget::onQueuedReadDisplayProperties() {
 
  773    foreach (ImageTreeWidgetItem *item, m_queuedReadDisplayPropertiesItems) {
 
  774      bool wasSelected = item->isSelected();
 
  777      if (!wasSelected && item->isSelected()) {
 
  778        newlySelectedItem = item;
 
  782    if (newlySelectedItem) {
 
  783      scrollToItem(newlySelectedItem);
 
  786    m_queuedReadDisplayPropertiesItems.clear();
 
  790  void ImageTreeWidget::onQueuedSelectionChanged() {
 
  793    m_queuedSelectionChanged = 
false;
 
  795    QTreeWidgetItemIterator it(
this, QTreeWidgetItemIterator::UserFlag);
 
  800      if (item->type() == QTreeWidgetItem::UserType) {
 
  801        ImageTreeWidgetItem *imageItem = (ImageTreeWidgetItem *)item;
 
  802        imageItem->update(
true);
 
  808    updateDragAndDropability();
 
  812  void ImageTreeWidget::propertiesChanged(DisplayProperties *changed) {
 
  813    enqueueReadDisplayProperties(treeItem(changed));
 
  817  void ImageTreeWidget::renameSelectedGroup() {
 
  818    if (selectedItems().size() == 1 &&
 
  819       selectedItems()[0]->type() == QTreeWidgetItem::Type) {
 
  821      editItem(groupToEdit);
 
  826  void ImageTreeWidget::requestCloseSelected() {
 
  827    QTreeWidgetItemIterator it(
this, QTreeWidgetItemIterator::UserFlag);
 
  833      if (item->type() == QTreeWidgetItem::UserType) {
 
  834        if (item->isSelected() || item->parent()->isSelected()) {
 
  835          ImageTreeWidgetItem *mosItem = (ImageTreeWidgetItem *)item;
 
  836          mosItem->image()->deleteLater();
 
  845  void ImageTreeWidget::toggleColumnVisible() {
 
  846    int column = ((
QAction *)sender())->data().toInt();
 
  847    setColumnHidden(column, !isColumnHidden(column));
 
  849    if (!m_viewActs.empty())
 
  856  void ImageTreeWidget::updateDragAndDropability() {
 
  857    QList<QTreeWidgetItem *> selected = selectedItems();
 
  858    bool selectedGroup = groupInList(selected);
 
  859    bool selectedItem = mosaicItemInList(selected);
 
  861    if (selectedGroup && selectedItem) {
 
  862      setDragDropMode(QAbstractItemView::NoDragDrop);
 
  865      setDragDropMode(QAbstractItemView::DragDrop);
 
  870  bool ImageTreeWidget::groupInList(QList<QTreeWidgetItem *> items) {
 
  871    QListIterator<QTreeWidgetItem *> it(items);
 
  873    while (it.hasNext()) {
 
  876      if (item->type() == QTreeWidgetItem::Type)
 
  884  bool ImageTreeWidget::mosaicItemInList(QList<QTreeWidgetItem *> items) {
 
  885    QListIterator<QTreeWidgetItem *> it(items);
 
  887    while (it.hasNext()) {
 
  890      if (item->type() == QTreeWidgetItem::UserType)
 
  897  ImageList ImageTreeWidget::selectedDisplays() {
 
  899    QTreeWidgetItemIterator it(
this, QTreeWidgetItemIterator::UserFlag);
 
  905      if (item->type() == QTreeWidgetItem::UserType) {
 
  906        ImageTreeWidgetItem *mosItem = (ImageTreeWidgetItem *)item;
 
  907        if (mosItem->isSelected() || mosItem->parent()->isSelected()) {
 
  908          selected.append(mosItem->image());
 
  930    if (imageListName.isEmpty()) {
 
  931      result = invisibleRootItem();
 
  934      QTreeWidgetItemIterator it(
this);
 
  936      while(*it && !result) {
 
  939        if (item->data(0, Qt::UserRole).toInt() == ImageListNameType) {
 
  940          if (item->text(0) == imageListName) {
 
  950      result = createImageListNameItem(imageListName);
 
  951      addTopLevelItem(result);
 
 
  959    return m_displayPropsToTreeItemLookup[displayProps];
 
  963  ImageTreeWidgetItem *ImageTreeWidget::treeItem(Image *image) {
 
  964    return treeItem(image->displayProperties());
 
QList< QAction * > supportedActions(DataType data)
Returns a list of supported actions for a WorkOrder.
Project * project() const
Gets the Project for this directory.
File name manipulation and expansion.
Internalizes a list of images and allows for operations on the entire list.
The main project for ipce.
This is free and unencumbered software released into the public domain.
int toInt(const QString &string)
Global function to convert from a string to an integer.
bool toBool(const QString &string)
Global function to convert from a string to a boolean.