main.cpp

The program, all in one file - Magnus Homann, 2009-07-28 03:00 PM

Download (6.47 KB)

 
1
#include <QApplication>
2
#include <QVBoxLayout>
3
#include <QMainWindow>
4
#include <QTreeWidget>
5
#include <QWidget>
6
#include <QStringList>
7
#include <QTreeWidgetItem>
8
#include <QString>
9
#include <QMouseEvent>
10
#include <QLine>
11
#include <QPalette>
12
#include <QResizeEvent>
13
#include <QPoint>
14
#include <QDebug>
15

    
16

    
17
enum LEGEND_ITEM_TYPE
18
{
19
  LEGEND_GROUP                = QTreeWidgetItem::UserType + 0,
20
  LEGEND_LAYER                = QTreeWidgetItem::UserType + 1,
21
  LEGEND_PROPERTY_GROUP       = QTreeWidgetItem::UserType + 2,
22
  LEGEND_PROPERTY_ITEM        = QTreeWidgetItem::UserType + 3,
23
  LEGEND_SYMBOL_GROUP         = QTreeWidgetItem::UserType + 4,
24
  LEGEND_SYMBOL_ITEM          = QTreeWidgetItem::UserType + 5,
25
  LEGEND_VECTOR_SYMBOL_ITEM   = QTreeWidgetItem::UserType + 6,
26
  LEGEND_LAYER_FILE_GROUP     = QTreeWidgetItem::UserType + 7,
27
  LEGEND_LAYER_FILE           = QTreeWidgetItem::UserType + 8
28
} ;
29

    
30
class TreeWidget : public QTreeWidget
31
{
32
    Q_OBJECT
33
    public:
34
    TreeWidget(QWidget *parent = 0)
35
      : QTreeWidget(parent), dragging(false), dragged(NULL), dropOn(NULL)
36
    {
37
      line = new QWidget(viewport());
38
      hideLine();
39
      line->setAutoFillBackground(true);
40
      QPalette pal = line->palette();
41
      pal.setColor(line->backgroundRole(), Qt::blue);
42
      line->setPalette(pal);
43
      setColumnCount(2);
44
      setHeaderLabels(QStringList() << "Name" << "Info");
45
      setRootIsDecorated(true);
46
      int i = 0;
47
      for (; i<5; ++i) {
48
        new QTreeWidgetItem(invisibleRootItem(), QStringList(QString("Item %1").arg(i)) << QString("Layer"));
49
      }
50
      QTreeWidgetItem *group1 = new QTreeWidgetItem(invisibleRootItem(), QStringList(QString("Item %1").arg(i++)) << QString("Group"), LEGEND_GROUP);
51
      for (; i<9; ++i) {
52
        new QTreeWidgetItem(group1, QStringList(QString("Item %1").arg(i)) << QString("Layer"));
53
      }
54
      QTreeWidgetItem *group2 = new QTreeWidgetItem(invisibleRootItem(), QStringList(QString("Item %1").arg(i++)) << QString("Group"), LEGEND_GROUP);
55
      for (; i<13; ++i) {
56
        new QTreeWidgetItem(group2, QStringList(QString("Item %1").arg(i)) << QString("Layer"));
57
      }
58
      setDragDropMode(NoDragDrop);
59
    }
60
    void mousePressEvent(QMouseEvent *e)
61
    {
62
      if (e->button() == Qt::LeftButton) {
63
        lastPress = e->pos();
64
        QTreeWidgetItem *item = itemAt(e->pos());
65
        dragged = item;
66
      }
67
      QTreeWidget::mousePressEvent(e);
68
    }
69

    
70
    void mouseMoveEvent(QMouseEvent *e)
71
    {
72
      if (dragging) {
73
        QTreeWidgetItem *item = itemAt(e->pos());
74
        if (item) {
75
          dropOn = item;
76
          int item_top = visualItemRect(item).top();
77
          int item_bottom = visualItemRect(item).bottom();
78
          int item_middle = ( item_top + item_bottom + 1 ) / 2;
79
          int item_left =  visualItemRect(item).left();
80
          if (dropOn != dragged ) {
81
            if (e->pos().y() < item_middle )
82
            {
83
              showLine(item_top+1, item_left);
84
              dropBottom = false;
85
            }
86
            else
87
            {
88
              showLine(item_bottom-2, item_left);
89
              dropBottom = true;
90
            }
91
            // dropBottom doesn't care if dropping onto itself.
92
          }
93
          else
94
          {
95
            hideLine();
96
          }
97
        } else if (e->pos().y() >= 0) {
98
          dropOn = NULL; // Means after items
99
          showLine(visualItemRect( lastVisibleItem() ).bottom() + 1, 0);
100
        } else {
101
          dropOn = NULL;
102
          hideLine();
103
        }
104
        e->accept();
105
      } else if (e->buttons() == Qt::LeftButton
106
      && (e->pos() - lastPress).manhattanLength() >= QApplication::startDragDistance()) {
107
        line->show();
108
        dragging = true;
109
      } else {
110
        QTreeWidget::mouseMoveEvent(e);
111
      }
112
    }
113

    
114
    void hideLine()
115
    {
116
      line->setGeometry(0, -100, 1, 1);
117
    }
118

    
119
    void showLine(int y, int left)
120
    {
121
      line->setGeometry(left, y, viewport()->width(), 2);
122
    }
123

    
124
    void mouseReleaseEvent(QMouseEvent *e)
125
    {
126
      if (dragging) {
127
        hideLine();
128
        if (dragged && !(dragged == dropOn) && !isDescendantOf( dragged, dropOn ) )
129
        {
130
          QTreeWidgetItem *draggedParent = dragged->parent() ?  dragged->parent() : invisibleRootItem();
131
          clearSelection();
132
          draggedParent->removeChild(dragged);
133
          if ( dropOn )
134
          {
135
            // We're dropping on something
136
            QTreeWidgetItem *dropOnParent = dropOn->parent() ?  dropOn->parent() : invisibleRootItem();
137

    
138
            if ( dropBottom )
139
            {
140
              // Releasing event in bottom half of object. If group, insert into, else after.
141
              if (dropOn->type() == LEGEND_GROUP )
142
              {
143
                // Drop into
144
                dropOn->insertChild(0, dragged);
145
              }
146
              else
147
              {
148
                // Drop after
149
                dropOnParent->insertChild(dropOnParent->indexOfChild( dropOn ) + 1, dragged);
150
              }
151
            }
152
            else
153
            {
154
              // Releasing event in top half of object. Insert before, always
155
              dropOnParent->insertChild(dropOnParent->indexOfChild( dropOn ), dragged);
156
            }
157
          }
158
          else
159
          {
160
            // We're not dropping on something, add last of the top level items.
161
            invisibleRootItem()->insertChild(invisibleRootItem()->childCount(), dragged);
162
          }
163

    
164
          setCurrentItem(dragged);
165
        }
166
        dropOn = dragged = NULL;
167
        dragging = false;
168
        e->accept();
169
      } else {
170
        QTreeWidget::mouseReleaseEvent(e);
171
      }
172
    }
173

    
174
    QTreeWidgetItem *lastVisibleItem()
175
    {
176
      QTreeWidgetItem *current;
177
      QTreeWidgetItem *next;
178

    
179
      current = topLevelItem( topLevelItemCount() - 1 );
180
      while ( ( next = itemBelow( current ) ) )
181
      {
182
        current = next;
183
      }
184
      return current;
185
    }
186

    
187
    bool isDescendantOf(QTreeWidgetItem *parent, QTreeWidgetItem *child)
188
    {
189
      // Search depth first
190
      if ( parent && child )
191
      {
192
        if ( parent == child->parent() )
193
        {
194
          return true;
195
        }
196
        for( int i = 0; i < parent->childCount(); i++ )
197
        {
198
          if ( isDescendantOf( parent->child(i), child ) )
199
          {
200
            return true;
201
          }
202
        }
203
      }
204
      return false;
205
    }
206

    
207
  private:
208
    QWidget *line;
209
    QPoint lastPress;
210
    bool dragging;
211
    bool dropBottom;
212
    QTreeWidgetItem *dragged, *dropOn;
213
};
214

    
215
#include "main.moc"
216

    
217

    
218
int main(int argc, char **argv)
219
{
220
  QApplication a(argc, argv);
221
  TreeWidget w;
222
  w.show();
223
  return a.exec();
224
}
225