Isis 3 Programmer Reference
ImageTreeWidget.cpp
1#include "ImageTreeWidget.h"
2
3#include <algorithm>
4
5#include <QAction>
6#include <QApplication>
7#include <QDebug>
8#include <QDropEvent>
9#include <QMenu>
10#include <QProgressBar>
11#include <QSettings>
12#include <QScrollBar>
13#include <QTime>
14
15#include "Directory.h"
16#include "IException.h"
17#include "Image.h"
19#include "ImageList.h"
20#include "ImageTreeWidgetItem.h"
21#include "ProgressBar.h"
22
23namespace Isis {
24
33 m_queuedSelectionChanged = false;
34 m_directory = directory;
35
36 QStringList header;
37
38 ImageTreeWidgetItem::TreeColumn col = ImageTreeWidgetItem::NameColumn;
39 while(col < ImageTreeWidgetItem::BlankColumn) {
40 header << ImageTreeWidgetItem::treeColumnToString(col);
41 col = (ImageTreeWidgetItem::TreeColumn)(col + 1);
42 }
43
44 setHeaderLabels(header);
45
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);
57
58 // Read and apply default visibilities from config, if different than defaults
59 QSettings settings(
60 FileName(QString("$HOME/.Isis/%1/fileList.config").arg(QApplication::applicationName()))
61 .expanded(),
62 QSettings::NativeFormat);
63 settings.beginGroup("ColumnsVisible");
64
65 col = ImageTreeWidgetItem::FootprintColumn;
66 while(col < ImageTreeWidgetItem::BlankColumn) {
67 bool visible = !isColumnHidden(col);
68
69 if (settings.value(QString("%1Visible").arg(ImageTreeWidgetItem::treeColumnToString(col)),
70 visible).toBool() != visible) {
71 if (visible)
72 hideColumn(col);
73 else
74 showColumn(col);
75 }
76
77 col = (ImageTreeWidgetItem::TreeColumn)(col + 1);
78 }
79 settings.endGroup();
80
81 setContextMenuPolicy(Qt::DefaultContextMenu);
82
83 setSortingEnabled(true);
84 sortItems(ImageTreeWidgetItem::NameColumn, Qt::AscendingOrder);
85
86 connect(this, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
87 this, SLOT(onItemChanged(QTreeWidgetItem *, int)));
88 connect(this, SIGNAL(itemSelectionChanged()),
89 this, SLOT(onSelectionChanged()));
90
91 // This is set up to do a single selection changed after all selections have changed, instead
92 // of 1 selection changed per 1 changed item.
93 connect(this, SIGNAL(queueSelectionChanged()),
94 this, SLOT(onQueuedSelectionChanged()), Qt::QueuedConnection);
95
96 // Similar issue, but not as bad of a slow-down. Still enough to warrant the effort though.
97 connect(this, SIGNAL(queueReadDisplayProperties()),
98 this, SLOT(onQueuedReadDisplayProperties()), Qt::QueuedConnection);
99
100 setSelectionMode(QAbstractItemView::ExtendedSelection);
101 setDragDropOverwriteMode(false);
102 }
103
104
105 ImageTreeWidget::~ImageTreeWidget() {
106 QAction *contextAction;
107 foreach(contextAction, actions()) {
108 removeAction(contextAction);
109 }
110 }
111
112
113 QList<QAction *> ImageTreeWidget::actions() {
114
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()));
122 }
123 results.append(m_setFileListColsAct);
124
125 return results;
126 }
127
128
129 QTreeWidgetItem *ImageTreeWidget::addGroup(QString imageListName, QString groupName, int index) {
130 if (index >= 0) {
131 disableSort();
132 }
133 QTreeWidgetItem *imageList = imageListTreeItem(imageListName);
134 QTreeWidgetItem *group = createGroup(imageList, groupName, index);
135
136 verticalScrollBar()->setMaximum(verticalScrollBar()->maximum() + 25);
137 return group;
138 }
139
140
141 QTreeWidgetItem *ImageTreeWidget::createGroup(QTreeWidgetItem *imageListItem, QString groupName,
142 int index) {
143 if (!imageListItem)
144 imageListItem = invisibleRootItem();
145
146 if (groupName.isEmpty()) {
147 groupName = QString("Group %1").arg(imageListItem->childCount() + 1);
148 }
149
150 QTreeWidgetItem *result = new QTreeWidgetItem;
151 result->setText(0, groupName);
152 result->setFlags(Qt::ItemIsEditable |
153 Qt::ItemIsUserCheckable |
154 Qt::ItemIsEnabled |
155 Qt::ItemIsSelectable |
156 Qt::ItemIsDragEnabled |
157 Qt::ItemIsDropEnabled);
158 result->setData(0, Qt::UserRole, ImageGroupType);
159
160 if (index == -1) {
161 index = imageListItem->childCount();
162 }
163
164 imageListItem->insertChild(index, result);
165
166 // This needs to be after the insert child call
167 result->setExpanded(true);
168
169 return result;
170 }
171
172
173 QTreeWidgetItem *ImageTreeWidget::createImageListNameItem(QString name) {
174 QTreeWidgetItem *result = new QTreeWidgetItem;
175 result->setText(0, name);
176 result->setData(0, Qt::UserRole, ImageListNameType);
177 result->setExpanded(true);
178
179 return result;
180 }
181
182
183 void ImageTreeWidget::refit() {
184 ImageTreeWidgetItem::TreeColumn col = ImageTreeWidgetItem::NameColumn;
185 while(col < ImageTreeWidgetItem::BlankColumn) {
186 // Resize the name column to the expanded version's data.
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);
192 }
193
194 resizeColumnToContents(col);
195
196 for (int groupIndex = 0; groupIndex < topLevelItemCount(); groupIndex++) {
197 topLevelItem(groupIndex)->setExpanded(expandedStates[groupIndex]);
198 }
199 }
200 else {
201 resizeColumnToContents(col);
202 }
203
204 col = (ImageTreeWidgetItem::TreeColumn)(col + 1);
205 }
206 }
207
208
209 void ImageTreeWidget::disableSort() {
210 sortItems(ImageTreeWidgetItem::BlankColumn, Qt::AscendingOrder);
211 }
212
213
214 void ImageTreeWidget::enqueueReadDisplayProperties(ImageTreeWidgetItem *item) {
215 m_queuedReadDisplayPropertiesItems.append(item);
216
217 if (m_queuedReadDisplayPropertiesItems.count() == 1) {
218 emit queueReadDisplayProperties();
219 }
220 }
221
222
223 QList<QAction *> ImageTreeWidget::getViewActions() {
224 if (m_viewActs.empty()) {
225 ImageTreeWidgetItem::TreeColumn col =
226 ImageTreeWidgetItem::FootprintColumn;
227
228 while(col < ImageTreeWidgetItem::BlankColumn) {
229 QAction *showHide = new QAction("", this);
230 showHide->setData(col);
231
232 connect(showHide, SIGNAL(triggered()),
233 this, SLOT(toggleColumnVisible()));
234
235 m_viewActs.append(showHide);
236
237 col = (ImageTreeWidgetItem::TreeColumn)(col + 1);
238 }
239
240 updateViewActs();
241 }
242
243 return m_viewActs;
244 }
245
246
247 void ImageTreeWidget::updateViewActs() {
248 if (!m_viewActs.empty()) {
249 int viewActIndex = 0;
250 ImageTreeWidgetItem::TreeColumn col =
251 ImageTreeWidgetItem::FootprintColumn;
252
253 while(col < ImageTreeWidgetItem::BlankColumn) {
254 bool visible = !isColumnHidden(col);
255 QAction *showHide = m_viewActs[viewActIndex];
256
257 if (!visible) {
258 showHide->setText("Show " +
259 ImageTreeWidgetItem::treeColumnToString(col) + " Column");
260 }
261 else {
262 showHide->setText("Hide " +
263 ImageTreeWidgetItem::treeColumnToString(col) + " Column");
264 }
265
266 col = (ImageTreeWidgetItem::TreeColumn)(col + 1);
267 viewActIndex ++;
268 }
269 }
270 }
271
272
276 void ImageTreeWidget::setDefaultFileListCols() {
277 QSettings settings(
278 FileName(
279 QString("$HOME/.Isis/%1/fileList.config").arg(QApplication::applicationName()))
280 .expanded(),
281 QSettings::NativeFormat);
282 settings.beginGroup("ColumnsVisible");
283
284 ImageTreeWidgetItem::TreeColumn col =
285 ImageTreeWidgetItem::FootprintColumn;
286
287 while(col < ImageTreeWidgetItem::BlankColumn) {
288 bool visible = !isColumnHidden(col);
289
290 settings.setValue(QString("%1Visible").arg(ImageTreeWidgetItem::treeColumnToString(col)),
291 visible);
292
293 col = (ImageTreeWidgetItem::TreeColumn)(col + 1);
294 }
295
296 settings.endGroup();
297 }
298
299
300 ImageTreeWidgetItem *ImageTreeWidget::prepCube(ImageList *imageList, Image *image) {
301 try {
302 ImageTreeWidgetItem *item = new ImageTreeWidgetItem(imageList, image);
303
304 connect(image->displayProperties(), SIGNAL(destroyed(QObject *)),
305 this, SLOT(imageDeleted(QObject *)));
306 connect(image->displayProperties(), SIGNAL(propertyChanged(DisplayProperties *)),
307 this, SLOT(propertiesChanged(DisplayProperties *)));
308
309 m_displayPropsToTreeItemLookup[image->displayProperties()] = item;
310
311 return item;
312 }
313 catch(IException &e) {
314 e.print();
315 }
316
317 return NULL;
318 }
319
320
321 ImageList ImageTreeWidget::imagesInView() {
322 ImageList results;
323
324 QTreeWidgetItemIterator it(this, QTreeWidgetItemIterator::UserFlag);
325
326 while(*it) {
327 QTreeWidgetItem *item = *it;
328
329 if (item->type() == QTreeWidgetItem::UserType) {
330 ImageTreeWidgetItem *mosItem = (ImageTreeWidgetItem *)item;
331 results.append(mosItem->image());
332 }
333
334 it ++;
335 }
336
337 return results;
338 }
339
340
341 ImageTreeWidget::ImagePosition::ImagePosition() {
342 init();
343 }
344
345
346 ImageTreeWidget::ImagePosition::ImagePosition(int outerIndex, int innerIndex) {
347 init();
348
349 setPosition(outerIndex, innerIndex);
350 }
351
352
353 ImageTreeWidget::ImagePosition::ImagePosition(const ImagePosition &other) :
354 m_group(other.m_group), m_index(other.m_index) {
355 }
356
357
358 ImageTreeWidget::ImagePosition::~ImagePosition() {
359 init();
360 }
361
362
363 void ImageTreeWidget::ImagePosition::setPosition(int group, int index) {
364 if (group >= 0 && index >= 0) {
365 m_group = group;
366 m_index = index;
367 }
368 else {
369 init();
370 }
371 }
372
373
374 int ImageTreeWidget::ImagePosition::group() const {
375 return m_group;
376 }
377
378
379 int ImageTreeWidget::ImagePosition::index() const {
380 return m_index;
381 }
382
383
384 bool ImageTreeWidget::ImagePosition::isValid() const {
385 return (m_group != -1 && m_index != -1);
386 }
387
388
389 void ImageTreeWidget::ImagePosition::swap(ImagePosition &other) {
390 std::swap(m_group, other.m_group);
391 std::swap(m_index, other.m_index);
392 }
393
394
395 bool ImageTreeWidget::ImagePosition::operator<(const ImagePosition &rhs) {
396 bool lessThan = false;
397 if (group() < rhs.group()) {
398 lessThan = true;
399 }
400 else if (group() == rhs.group() && index() < rhs.index()) {
401 lessThan = true;
402 }
403
404 return lessThan;
405 }
406
407
408 ImageTreeWidget::ImagePosition &ImageTreeWidget::ImagePosition::operator=(
409 const ImagePosition &rhs) {
410 ImagePosition copy(rhs);
411 swap(copy);
412
413 return *this;
414 }
415
416
417 void ImageTreeWidget::ImagePosition::init() {
418 m_group = -1;
419 m_index = -1;
420 }
421
422 void ImageTreeWidget::dropEvent(QDropEvent *event) {
423 QTreeWidgetItem *droppedAtItem = itemAt(event->pos());
424
425 if(droppedAtItem) {
426 disableSort();
427 QTreeWidgetItem *droppedAtGroup = droppedAtItem;
428
429 if(droppedAtGroup->type() != QTreeWidgetItem::Type)
430 droppedAtGroup = droppedAtItem->parent();
431
432 bool draggedGroup = groupInList(selectedItems());
433 bool draggedItem = mosaicItemInList(selectedItems());
434
435 // Moving items around...
436 if(draggedItem && !draggedGroup) {
437 int insertPosition = 0;
438
439 if(droppedAtGroup != droppedAtItem) {
440 insertPosition = droppedAtGroup->indexOfChild(droppedAtItem) + 1;
441 }
442
443 QTreeWidgetItem *toBeMoved;
444 foreach(toBeMoved, selectedItems()) {
445 if(toBeMoved != droppedAtItem) {
446 QTreeWidgetItem *parent = toBeMoved->parent();
447
448 // We need to make sure we handle moving a child within the
449 // same group and how that effects the insert position
450 int childOrigIndex = parent->indexOfChild(toBeMoved);
451
452 parent->takeChild(childOrigIndex);
453
454 int actualInsertPos = insertPosition;
455
456 if(parent == droppedAtGroup && childOrigIndex < insertPosition)
457 actualInsertPos --;
458
459 droppedAtGroup->insertChild(actualInsertPos, toBeMoved);
460
461 // This makes multiple items dragged to bottom of group work
462 if(insertPosition != droppedAtGroup->childCount())
463 insertPosition ++;
464 }
465 }
466 }
467 else if(!draggedItem && draggedGroup) {
468 QTreeWidgetItem *toBeMoved;
469
470 foreach(toBeMoved, selectedItems()) {
471 if(toBeMoved != droppedAtGroup) {
472 int dropPosition = indexOfTopLevelItem(droppedAtGroup);
473
474 takeTopLevelItem(indexOfTopLevelItem(toBeMoved));
475 insertTopLevelItem(dropPosition, toBeMoved);
476 }
477 }
478 }
479 }
480 }
481
492//void ImageTreeWidget::dropEvent(QDropEvent *event) {
493// QTreeWidgetItem *droppedAtItem = itemAt(event->pos());
494//
495// if (droppedAtItem) {
496// disableSort();
497// QTreeWidgetItem *droppedAtList = droppedAtItem;
498// QTreeWidgetItem *droppedAtGroup = droppedAtItem;
499//
500// // Try to figure out which list / group they dropped into
501// while (droppedAtList->data(0, Qt::UserRole).toInt() != ImageListNameType &&
502// droppedAtList != invisibleRootItem()) {
503// droppedAtList = droppedAtList->parent();
504//
505// if (!droppedAtList)
506// droppedAtList = invisibleRootItem();
507// }
508//
509// while (droppedAtGroup && droppedAtGroup->data(0, Qt::UserRole).toInt() != ImageGroupType) {
510// droppedAtGroup = droppedAtGroup->parent();
511// }
512//
513// QString droppedListName = droppedAtList->text(0);
514//
515// // Figure out from which list they're moving items from (to verify they aren't moving
516// // between file lists)
517// QTreeWidgetItem *firstItemToBeMoved = NULL;
518// QString draggedListName;
519//
520// if (selectedItems().count()) {
521// firstItemToBeMoved = selectedItems()[0];
522//
523// if (firstItemToBeMoved->data(0, Qt::UserRole).toInt() == ImageGroupType) {
524// draggedListName = firstItemToBeMoved->parent()->text(0);
525// }
526// else if (firstItemToBeMoved->type() == QTreeWidgetItem::UserType) {
527// draggedListName = ((ImageTreeWidgetItem *)firstItemToBeMoved)->imageListName();
528// }
529// else {
530// firstItemToBeMoved = NULL;
531// }
532// }
533//
534// bool draggedGroup = groupInList(selectedItems());
535// bool draggedItem = mosaicItemInList(selectedItems());
536//
537// if (firstItemToBeMoved && (draggedListName == droppedListName || droppedListName.isEmpty())) {
538// // If they dropped images into a list item (but not a group), consider it a new group in
539// // the list
540// if (droppedAtList && !droppedAtGroup && !draggedGroup && draggedItem) {
541// droppedAtGroup = addGroup(droppedListName);
542// }
543//
544// // Moving items around...
545// if (draggedItem && !draggedGroup) {
546// int insertPosition = 0;
547//
548// if (droppedAtGroup != droppedAtItem) {
549// insertPosition = droppedAtGroup->indexOfChild(droppedAtItem) + 1;
550// }
551//
552// QTreeWidgetItem *toBeMoved;
553// foreach(toBeMoved, selectedItems()) {
554// if (toBeMoved != droppedAtItem) {
555// QTreeWidgetItem *parent = toBeMoved->parent();
556//
557// // We need to make sure we handle moving a child within the
558// // same group and how that effects the insert position
559// int childOrigIndex = parent->indexOfChild(toBeMoved);
560//
561// parent->takeChild(childOrigIndex);
562//
563// int actualInsertPos = insertPosition;
564//
565// if (parent == droppedAtGroup && childOrigIndex < insertPosition)
566// actualInsertPos --;
567//
568// droppedAtGroup->insertChild(actualInsertPos, toBeMoved);
569//
570// // This makes multiple items dragged to bottom of group work
571// if (insertPosition != droppedAtGroup->childCount())
572// insertPosition ++;
573// }
574// }
575// }
576// else if (!draggedItem && draggedGroup && droppedAtGroup) {
577// QTreeWidgetItem *toBeMoved;
578//
579// foreach(toBeMoved, selectedItems()) {
580// if (toBeMoved != droppedAtGroup) {
581// int dropPosition = droppedAtList->indexOfChild(droppedAtGroup);
582//
583// droppedAtList->takeChild(droppedAtList->indexOfChild(toBeMoved));
584// droppedAtList->insertChild(dropPosition, toBeMoved);
585// }
586// }
587// }
588// }
589// }
590//}
591
592
597 void ImageTreeWidget::mousePressEvent(QMouseEvent *event) {
598 switch(event->type()) {
599 case QEvent::MouseButtonPress: {
600 if (event->button() == Qt::RightButton &&
601 itemAt(event->pos()) == NULL) {
602 setCurrentItem(NULL);
603 }
604 break;
605 }
606
607 default:
608 break;
609 }
610
611 QTreeWidget::mousePressEvent(event);
612 }
613
614
615 void ImageTreeWidget::contextMenuEvent(QContextMenuEvent *event) {
616 ImageList selectedCubes = selectedDisplays();
617
618 bool selectedGroup = groupInList(selectedItems());
619 bool selectedCube = mosaicItemInList(selectedItems());
620
621 Project *project = NULL;
622
623 if (m_directory)
624 project = m_directory->project();
625
626 QList<QAction *> supportedActions = selectedCubes.supportedActions(project);
627
628 if (m_directory) {
629 supportedActions.append(NULL);
630 supportedActions.append(m_directory->supportedActions(&selectedCubes));
631 }
632
633 QMenu menu;
634 foreach(QAction *action, supportedActions) {
635 if (action != NULL)
636 menu.addAction(action);
637 else
638 menu.addSeparator();
639 }
640
641 menu.addSeparator();
642
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()));
648 }
649
650 if (selectedItems().size() == 1) {
651 QAction *rename = menu.addAction("Rename Group");
652 connect(rename, SIGNAL(triggered()),
653 this, SLOT(renameSelectedGroup()));
654
655 QAction *group = menu.addAction("Insert Group");
656 connect(group, SIGNAL(triggered()),
657 this, SLOT(addGroup()));
658 }
659
660 QAction *removeGroup = NULL;
661
662 if (selectedItems().size() == 1)
663 removeGroup = menu.addAction("Delete Group");
664 else
665 removeGroup = menu.addAction("Delete Groups");
666
667 connect(removeGroup, SIGNAL(triggered()),
668 this, SLOT(deleteSelectedGroups()));
669 }
670
671 if (selectedCube && !selectedGroup) {
672 QAction *close = NULL;
673
674 if (selectedItems().size() == 1)
675 close = menu.addAction("Close Cube");
676 else
677 close = menu.addAction("Close Cubes");
678
679 connect(close, SIGNAL(triggered()),
680 this, SLOT(requestCloseSelected()));
681 }
682
683 if (!selectedCube && !selectedGroup) {
684 QAction *group = menu.addAction("Add Group");
685
686 connect(group, SIGNAL(triggered()),
687 this, SLOT(addGroup()));
688 }
689
690 menu.exec(event->globalPos());
691 }
692
693
701 int index = -1;
702
703 QTreeWidgetItem *newGroupParent = NULL;
704 QString newGroupParentText = "";
705
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]);
711 }
712 else {
713 newGroupParent = invisibleRootItem();
714 index = indexOfTopLevelItem(selectedItems()[0]);
715 }
716 }
717 else if (selectedItems()[0]->data(0, Qt::UserRole).toInt() == ImageListNameType) {
718 newGroupParent = selectedItems()[0];
719 }
720 }
721
722 if (newGroupParent) {
723 newGroupParentText = newGroupParent->text(0);
724 }
725 return addGroup(newGroupParentText, "", index);
726 }
727
728
729 void ImageTreeWidget::deleteSelectedGroups() {
730 // Close the cubes in these groups
731 requestCloseSelected();
732
733 QTreeWidgetItem *toBeDeleted;
734 foreach(toBeDeleted, selectedItems()) {
735 if (toBeDeleted->type() == QTreeWidgetItem::Type) {
736 delete toBeDeleted;
737 }
738 }
739 }
740
741
742 void ImageTreeWidget::imageDeleted(QObject *imageObj) {
743 ImageDisplayProperties *imagedisp = (ImageDisplayProperties *)imageObj;
744 ImageTreeWidgetItem *item = treeItem(imagedisp);
745
746 if (item && item->parent()) {
747 m_displayPropsToTreeItemLookup.remove(imagedisp);
748
749 item->forgetImage();
750 delete item->parent()->takeChild( item->parent()->indexOfChild(item) );
751 }
752 }
753
754
755 void ImageTreeWidget::onItemChanged(QTreeWidgetItem *item, int) {
756 if (item->type() == QTreeWidgetItem::UserType) {
757 ((ImageTreeWidgetItem *)item)->update(true);
758 }
759 }
760
761
762 void ImageTreeWidget::onSelectionChanged() {
763 if (!m_queuedSelectionChanged) {
764 emit queueSelectionChanged();
765 m_queuedSelectionChanged = true;
766 }
767 }
768
769
770 void ImageTreeWidget::onQueuedReadDisplayProperties() {
771 QTreeWidgetItem *newlySelectedItem = NULL;
772
773 foreach (ImageTreeWidgetItem *item, m_queuedReadDisplayPropertiesItems) {
774 bool wasSelected = item->isSelected();
775 item->update(false);
776
777 if (!wasSelected && item->isSelected()) {
778 newlySelectedItem = item;
779 }
780 }
781
782 if (newlySelectedItem) {
783 scrollToItem(newlySelectedItem);
784 }
785
786 m_queuedReadDisplayPropertiesItems.clear();
787 }
788
789
790 void ImageTreeWidget::onQueuedSelectionChanged() {
791 // This boolean is very important to speed. Please test with 50,000+ images if/when considering
792 // removing it.
793 m_queuedSelectionChanged = false;
794
795 QTreeWidgetItemIterator it(this, QTreeWidgetItemIterator::UserFlag);
796
797 while(*it) {
798 QTreeWidgetItem *item = *it;
799
800 if (item->type() == QTreeWidgetItem::UserType) {
801 ImageTreeWidgetItem *imageItem = (ImageTreeWidgetItem *)item;
802 imageItem->update(true);
803 }
804
805 it ++;
806 }
807
808 updateDragAndDropability();
809 }
810
811
812 void ImageTreeWidget::propertiesChanged(DisplayProperties *changed) {
813 enqueueReadDisplayProperties(treeItem(changed));
814 }
815
816
817 void ImageTreeWidget::renameSelectedGroup() {
818 if (selectedItems().size() == 1 &&
819 selectedItems()[0]->type() == QTreeWidgetItem::Type) {
820 QTreeWidgetItem *groupToEdit = selectedItems()[0];
821 editItem(groupToEdit);
822 }
823 }
824
825
826 void ImageTreeWidget::requestCloseSelected() {
827 QTreeWidgetItemIterator it(this, QTreeWidgetItemIterator::UserFlag);
828
829 while(*it) {
830 QTreeWidgetItem *item = *it;
831
832 // We get at least one item of the wrong type
833 if (item->type() == QTreeWidgetItem::UserType) {
834 if (item->isSelected() || item->parent()->isSelected()) {
835 ImageTreeWidgetItem *mosItem = (ImageTreeWidgetItem *)item;
836 mosItem->image()->deleteLater();
837 }
838 }
839
840 it ++;
841 }
842 }
843
844
845 void ImageTreeWidget::toggleColumnVisible() {
846 int column = ((QAction *)sender())->data().toInt();
847 setColumnHidden(column, !isColumnHidden(column));
848
849 if (!m_viewActs.empty())
850 updateViewActs();
851
852 refit();
853 }
854
855
856 void ImageTreeWidget::updateDragAndDropability() {
857 QList<QTreeWidgetItem *> selected = selectedItems();
858 bool selectedGroup = groupInList(selected);
859 bool selectedItem = mosaicItemInList(selected);
860
861 if (selectedGroup && selectedItem) {
862 setDragDropMode(QAbstractItemView::NoDragDrop);
863 }
864 else {
865 setDragDropMode(QAbstractItemView::DragDrop);
866 }
867 }
868
869
870 bool ImageTreeWidget::groupInList(QList<QTreeWidgetItem *> items) {
871 QListIterator<QTreeWidgetItem *> it(items);
872
873 while (it.hasNext()) {
874 QTreeWidgetItem *item = it.next();
875
876 if (item->type() == QTreeWidgetItem::Type)
877 return true;
878 }
879
880 return false;
881 }
882
883
884 bool ImageTreeWidget::mosaicItemInList(QList<QTreeWidgetItem *> items) {
885 QListIterator<QTreeWidgetItem *> it(items);
886
887 while (it.hasNext()) {
888 QTreeWidgetItem *item = it.next();
889
890 if (item->type() == QTreeWidgetItem::UserType)
891 return true;
892 }
893
894 return false;
895 }
896
897 ImageList ImageTreeWidget::selectedDisplays() {
898 ImageList selected;
899 QTreeWidgetItemIterator it(this, QTreeWidgetItemIterator::UserFlag);
900
901 while(*it) {
902 QTreeWidgetItem *item = *it;
903
904 // We get at least one item of the wrong type
905 if (item->type() == QTreeWidgetItem::UserType) {
906 ImageTreeWidgetItem *mosItem = (ImageTreeWidgetItem *)item;
907 if (mosItem->isSelected() || mosItem->parent()->isSelected()) {
908 selected.append(mosItem->image());
909 }
910 }
911
912 it ++;
913 }
914
915 return selected;
916 }
917
918
928 QTreeWidgetItem *result = NULL;
929
930 if (imageListName.isEmpty()) {
931 result = invisibleRootItem();
932 }
933 else {
934 QTreeWidgetItemIterator it(this);
935
936 while(*it && !result) {
937 QTreeWidgetItem *item = *it;
938
939 if (item->data(0, Qt::UserRole).toInt() == ImageListNameType) {
940 if (item->text(0) == imageListName) {
941 result = item;
942 }
943 }
944
945 it ++;
946 }
947 }
948
949 if (!result) {
950 result = createImageListNameItem(imageListName);
951 addTopLevelItem(result);
952 }
953
954 return result;
955 }
956
957
958 ImageTreeWidgetItem *ImageTreeWidget::treeItem(DisplayProperties *displayProps) {
959 return m_displayPropsToTreeItemLookup[displayProps];
960 }
961
962
963 ImageTreeWidgetItem *ImageTreeWidget::treeItem(Image *image) {
964 return treeItem(image->displayProperties());
965 }
966}
QList< QAction * > supportedActions(DataType data)
Returns a list of supported actions for a WorkOrder.
Definition Directory.h:345
Project * project() const
Gets the Project for this directory.
File name manipulation and expansion.
Definition FileName.h:100
Internalizes a list of images and allows for operations on the entire list.
Definition ImageList.h:55
void mousePressEvent(QMouseEvent *event)
This is why we needed to subclass the QTreeWidget class.
QTreeWidgetItem * addGroup()
ImageTreeWidget(Directory *directory=0, QWidget *parent=0)
ImageTreeWidget constructor.
QTreeWidgetItem * imageListTreeItem(QString imageListName)
This will get the image list tree item for the given image list (by name).
The main project for ipce.
Definition Project.h:289
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition IString.cpp:93
bool toBool(const QString &string)
Global function to convert from a string to a boolean.
Definition IString.cpp:38