1 /* BEGIN_COMMON_COPYRIGHT_HEADER
2 * (c)LGPL2+
3 *
4 * LXQt - a lightweight, Qt based, desktop toolset
5 * https://lxqt.org
6 *
7 * Copyright: 2010-2011 Razor team
8 * Authors:
9 * Alexander Sokoloff <sokoloff.a@gmail.com>
10 *
11 * This program or library is free software; you can redistribute it
12 * and/or modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20
21 * You should have received a copy of the GNU Lesser General
22 * Public License along with this library; if not, write to the
23 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 * Boston, MA 02110-1301 USA
25 *
26 * END_COMMON_COPYRIGHT_HEADER */
27
28
29 #include "lxqtpanellayout.h"
30 #include <QSize>
31 #include <QWidget>
32 #include <QEvent>
33 #include <QCursor>
34 #include <QApplication>
35 #include <QDebug>
36 #include <QPoint>
37 #include <QMouseEvent>
38 #include <QtAlgorithms>
39 #include <QPoint>
40 #include <QMouseEvent>
41 #include <QPropertyAnimation>
42 #include "plugin.h"
43 #include "lxqtpanellimits.h"
44 #include "ilxqtpanelplugin.h"
45 #include "lxqtpanel.h"
46 #include "pluginmoveprocessor.h"
47 #include <QToolButton>
48 #include <QStyle>
49
50 #define ANIMATION_DURATION 250
51
52 class ItemMoveAnimation : public QVariantAnimation
53 {
54 public:
ItemMoveAnimation(QLayoutItem * item)55 ItemMoveAnimation(QLayoutItem *item) :
56 mItem(item)
57 {
58 setEasingCurve(QEasingCurve::OutBack);
59 setDuration(ANIMATION_DURATION);
60 }
61
updateCurrentValue(const QVariant & current)62 void updateCurrentValue(const QVariant ¤t) override
63 {
64 mItem->setGeometry(current.toRect());
65 }
66
67 private:
68 QLayoutItem* mItem;
69
70 };
71
72
73 struct LayoutItemInfo
74 {
75 LayoutItemInfo(QLayoutItem *layoutItem=nullptr);
76 QLayoutItem *item;
77 QRect geometry;
78 bool separate{false};
79 bool expandable{false};
80 };
81
82
LayoutItemInfo(QLayoutItem * layoutItem)83 LayoutItemInfo::LayoutItemInfo(QLayoutItem *layoutItem):
84 item(layoutItem)
85 {
86 if (!item)
87 return;
88
89 Plugin *p = qobject_cast<Plugin*>(item->widget());
90 if (p)
91 {
92 separate = p->isSeparate();
93 expandable = p->isExpandable();
94 return;
95 }
96 }
97
98
99
100 /************************************************
101 This is logical plugins grid, it's same for
102 horizontal and vertical panel. Plugins keeps as:
103
104 <---LineCount-->
105 + ---+----+----+
106 | P1 | P2 | P3 |
107 +----+----+----+
108 | P4 | P5 | |
109 +----+----+----+
110 ...
111 +----+----+----+
112 | PN | | |
113 +----+----+----+
114 ************************************************/
115 class LayoutItemGrid
116 {
117 public:
118 explicit LayoutItemGrid();
119 ~LayoutItemGrid();
120
121 void addItem(QLayoutItem *item);
count() const122 int count() const { return mItems.count(); }
itemAt(int index) const123 QLayoutItem *itemAt(int index) const { return mItems[index]; }
124 QLayoutItem *takeAt(int index);
125
126
127 const LayoutItemInfo &itemInfo(int row, int col) const;
128 LayoutItemInfo &itemInfo(int row, int col);
129
130 void update();
131
lineSize() const132 int lineSize() const { return mLineSize; }
133 void setLineSize(int value);
134
colCount() const135 int colCount() const { return mColCount; }
136 void setColCount(int value);
137
usedColCount() const138 int usedColCount() const { return mUsedColCount; }
139
rowCount() const140 int rowCount() const { return mRowCount; }
141
invalidate()142 void invalidate() { mValid = false; }
isValid() const143 bool isValid() const { return mValid; }
144
sizeHint() const145 QSize sizeHint() const { return mSizeHint; }
146
horiz() const147 bool horiz() const { return mHoriz; }
148 void setHoriz(bool value);
149
150 void clear();
151 void rebuild();
152
isExpandable() const153 bool isExpandable() const { return mExpandable; }
expandableSize() const154 int expandableSize() const { return mExpandableSize; }
155
156 void moveItem(int from, int to);
157
158 private:
159 QVector<LayoutItemInfo> mInfoItems;
160 int mColCount;
161 int mUsedColCount;
162 int mRowCount;
163 bool mValid;
164 int mExpandableSize;
165 int mLineSize;
166
167 QSize mSizeHint;
168 QSize mMinSize;
169 bool mHoriz;
170
171 int mNextRow;
172 int mNextCol;
173 bool mExpandable;
174 QList<QLayoutItem*> mItems;
175
176 void doAddToGrid(QLayoutItem *item);
177 };
178
179
180 /************************************************
181
182 ************************************************/
LayoutItemGrid()183 LayoutItemGrid::LayoutItemGrid()
184 {
185 mLineSize = 0;
186 mHoriz = true;
187 clear();
188 }
189
~LayoutItemGrid()190 LayoutItemGrid::~LayoutItemGrid()
191 {
192 qDeleteAll(mItems);
193 }
194
195
196 /************************************************
197
198 ************************************************/
clear()199 void LayoutItemGrid::clear()
200 {
201 mRowCount = 0;
202 mNextRow = 0;
203 mNextCol = 0;
204 mInfoItems.resize(0);
205 mValid = false;
206 mExpandable = false;
207 mExpandableSize = 0;
208 mUsedColCount = 0;
209 mSizeHint = QSize(0,0);
210 mMinSize = QSize(0,0);
211 }
212
213
214 /************************************************
215
216 ************************************************/
rebuild()217 void LayoutItemGrid::rebuild()
218 {
219 clear();
220
221 for(QLayoutItem *item : qAsConst(mItems))
222 {
223 doAddToGrid(item);
224 }
225 }
226
227
228 /************************************************
229
230 ************************************************/
addItem(QLayoutItem * item)231 void LayoutItemGrid::addItem(QLayoutItem *item)
232 {
233 doAddToGrid(item);
234 mItems.append(item);
235 }
236
237
238 /************************************************
239
240 ************************************************/
doAddToGrid(QLayoutItem * item)241 void LayoutItemGrid::doAddToGrid(QLayoutItem *item)
242 {
243 LayoutItemInfo info(item);
244
245 if (info.separate && mNextCol > 0)
246 {
247 mNextCol = 0;
248 mNextRow++;
249 }
250
251 int cnt = (mNextRow + 1 ) * mColCount;
252 if (mInfoItems.count() <= cnt)
253 mInfoItems.resize(cnt);
254
255 int idx = mNextRow * mColCount + mNextCol;
256 mInfoItems[idx] = info;
257 mUsedColCount = qMax(mUsedColCount, mNextCol + 1);
258 mExpandable = mExpandable || info.expandable;
259 mRowCount = qMax(mRowCount, mNextRow+1);
260
261 if (info.separate || mNextCol >= mColCount-1)
262 {
263 mNextRow++;
264 mNextCol = 0;
265 }
266 else
267 {
268 mNextCol++;
269 }
270
271 invalidate();
272 }
273
274
275 /************************************************
276
277 ************************************************/
takeAt(int index)278 QLayoutItem *LayoutItemGrid::takeAt(int index)
279 {
280 QLayoutItem *item = mItems.takeAt(index);
281 rebuild();
282 return item;
283 }
284
285
286 /************************************************
287
288 ************************************************/
moveItem(int from,int to)289 void LayoutItemGrid::moveItem(int from, int to)
290 {
291 mItems.move(from, to);
292 rebuild();
293 }
294
295
296 /************************************************
297
298 ************************************************/
itemInfo(int row,int col) const299 const LayoutItemInfo &LayoutItemGrid::itemInfo(int row, int col) const
300 {
301 return mInfoItems[row * mColCount + col];
302 }
303
304
305 /************************************************
306
307 ************************************************/
itemInfo(int row,int col)308 LayoutItemInfo &LayoutItemGrid::itemInfo(int row, int col)
309 {
310 return mInfoItems[row * mColCount + col];
311 }
312
313
314 /************************************************
315
316 ************************************************/
update()317 void LayoutItemGrid::update()
318 {
319 mExpandableSize = 0;
320 mSizeHint = QSize(0,0);
321
322 if (mHoriz)
323 {
324 mSizeHint.setHeight(mLineSize * mColCount);
325 int x = 0;
326 for (int r=0; r<mRowCount; ++r)
327 {
328 int y = 0;
329 int rw = 0;
330 for (int c=0; c<mColCount; ++c)
331 {
332 LayoutItemInfo &info = itemInfo(r, c);
333 if (!info.item)
334 continue;
335
336 QSize sz = info.item->sizeHint();
337 info.geometry = QRect(QPoint(x,y), sz);
338 y += sz.height();
339 rw = qMax(rw, sz.width());
340 }
341 x += rw;
342
343 if (itemInfo(r, 0).expandable)
344 mExpandableSize += rw;
345
346 mSizeHint.setWidth(x);
347 mSizeHint.rheight() = qMax(mSizeHint.rheight(), y);
348 }
349 }
350 else
351 {
352 mSizeHint.setWidth(mLineSize * mColCount);
353 int y = 0;
354 for (int r=0; r<mRowCount; ++r)
355 {
356 int x = 0;
357 int rh = 0;
358 for (int c=0; c<mColCount; ++c)
359 {
360 LayoutItemInfo &info = itemInfo(r, c);
361 if (!info.item)
362 continue;
363
364 QSize sz = info.item->sizeHint();
365 info.geometry = QRect(QPoint(x,y), sz);
366 x += sz.width();
367 rh = qMax(rh, sz.height());
368 }
369 y += rh;
370
371 if (itemInfo(r, 0).expandable)
372 mExpandableSize += rh;
373
374 mSizeHint.setHeight(y);
375 mSizeHint.rwidth() = qMax(mSizeHint.rwidth(), x);
376 }
377 }
378
379 mValid = true;
380 }
381
382
383 /************************************************
384
385 ************************************************/
setLineSize(int value)386 void LayoutItemGrid::setLineSize(int value)
387 {
388 mLineSize = qMax(1, value);
389 invalidate();
390 }
391
392
393 /************************************************
394
395 ************************************************/
setColCount(int value)396 void LayoutItemGrid::setColCount(int value)
397 {
398 mColCount = qMax(1, value);
399 rebuild();
400 }
401
402 /************************************************
403
404 ************************************************/
setHoriz(bool value)405 void LayoutItemGrid::setHoriz(bool value)
406 {
407 mHoriz = value;
408 invalidate();
409 }
410
411
412
413 /************************************************
414
415 ************************************************/
LXQtPanelLayout(QWidget * parent)416 LXQtPanelLayout::LXQtPanelLayout(QWidget *parent) :
417 QLayout(parent),
418 mLeftGrid(new LayoutItemGrid()),
419 mRightGrid(new LayoutItemGrid()),
420 mPosition(ILXQtPanel::PositionBottom),
421 mAnimate(false)
422 {
423 setContentsMargins(0, 0, 0, 0);
424 }
425
426
427 /************************************************
428
429 ************************************************/
~LXQtPanelLayout()430 LXQtPanelLayout::~LXQtPanelLayout()
431 {
432 delete mLeftGrid;
433 delete mRightGrid;
434 }
435
436
437 /************************************************
438
439 ************************************************/
addItem(QLayoutItem * item)440 void LXQtPanelLayout::addItem(QLayoutItem *item)
441 {
442 LayoutItemGrid *grid = mRightGrid;
443
444 Plugin *p = qobject_cast<Plugin*>(item->widget());
445 if (p && p->alignment() == Plugin::AlignLeft)
446 grid = mLeftGrid;
447
448 grid->addItem(item);
449 }
450
451
452 /************************************************
453
454 ************************************************/
globalIndexToLocal(int index,LayoutItemGrid ** grid,int * gridIndex)455 void LXQtPanelLayout::globalIndexToLocal(int index, LayoutItemGrid **grid, int *gridIndex)
456 {
457 if (index < mLeftGrid->count())
458 {
459 *grid = mLeftGrid;
460 *gridIndex = index;
461 return;
462 }
463
464 *grid = mRightGrid;
465 *gridIndex = index - mLeftGrid->count();
466 }
467
468 /************************************************
469
470 ************************************************/
globalIndexToLocal(int index,LayoutItemGrid ** grid,int * gridIndex) const471 void LXQtPanelLayout::globalIndexToLocal(int index, LayoutItemGrid **grid, int *gridIndex) const
472 {
473 if (index < mLeftGrid->count())
474 {
475 *grid = mLeftGrid;
476 *gridIndex = index;
477 return;
478 }
479
480 *grid = mRightGrid;
481 *gridIndex = index - mLeftGrid->count();
482 }
483
484
485 /************************************************
486
487 ************************************************/
itemAt(int index) const488 QLayoutItem *LXQtPanelLayout::itemAt(int index) const
489 {
490 if (index < 0 || index >= count())
491 return nullptr;
492
493 LayoutItemGrid *grid=nullptr;
494 int idx=0;
495 globalIndexToLocal(index, &grid, &idx);
496
497 return grid->itemAt(idx);
498 }
499
500
501 /************************************************
502
503 ************************************************/
takeAt(int index)504 QLayoutItem *LXQtPanelLayout::takeAt(int index)
505 {
506 if (index < 0 || index >= count())
507 return nullptr;
508
509 LayoutItemGrid *grid=nullptr;
510 int idx=0;
511 globalIndexToLocal(index, &grid, &idx);
512
513 return grid->takeAt(idx);
514 }
515
516
517 /************************************************
518
519 ************************************************/
count() const520 int LXQtPanelLayout::count() const
521 {
522 return mLeftGrid->count() + mRightGrid->count();
523 }
524
525
526 /************************************************
527
528 ************************************************/
moveItem(int from,int to,bool withAnimation)529 void LXQtPanelLayout::moveItem(int from, int to, bool withAnimation)
530 {
531 if (from != to)
532 {
533 LayoutItemGrid *fromGrid=nullptr;
534 int fromIdx=0;
535 globalIndexToLocal(from, &fromGrid, &fromIdx);
536
537 LayoutItemGrid *toGrid=nullptr;
538 int toIdx=0;
539 globalIndexToLocal(to, &toGrid, &toIdx);
540
541 if (fromGrid == toGrid)
542 {
543 fromGrid->moveItem(fromIdx, toIdx);
544 }
545 else
546 {
547 QLayoutItem *item = fromGrid->takeAt(fromIdx);
548 toGrid->addItem(item);
549 //recalculate position because we removed from one and put to another grid
550 LayoutItemGrid *toGridAux=nullptr;
551 globalIndexToLocal(to, &toGridAux, &toIdx);
552 Q_ASSERT(toGrid == toGridAux); //grid must be the same (if not something is wrong with our logic)
553 toGrid->moveItem(toGridAux->count()-1, toIdx);
554 }
555 }
556
557 mAnimate = withAnimation;
558 invalidate();
559 }
560
561
562 /************************************************
563
564 ************************************************/
sizeHint() const565 QSize LXQtPanelLayout::sizeHint() const
566 {
567 if (!mLeftGrid->isValid())
568 mLeftGrid->update();
569
570 if (!mRightGrid->isValid())
571 mRightGrid->update();
572
573 QSize ls = mLeftGrid->sizeHint();
574 QSize rs = mRightGrid->sizeHint();
575
576 if (isHorizontal())
577 {
578 return QSize(ls.width() + rs.width(),
579 qMax(ls.height(), rs.height()));
580 }
581 else
582 {
583 return QSize(qMax(ls.width(), rs.width()),
584 ls.height() + rs.height());
585 }
586 }
587
588
589 /************************************************
590
591 ************************************************/
setGeometry(const QRect & geometry)592 void LXQtPanelLayout::setGeometry(const QRect &geometry)
593 {
594 if (!mLeftGrid->isValid())
595 mLeftGrid->update();
596
597 if (!mRightGrid->isValid())
598 mRightGrid->update();
599
600 QRect my_geometry{geometry};
601 my_geometry -= contentsMargins();
602 if (count())
603 {
604 if (isHorizontal())
605 setGeometryHoriz(my_geometry);
606 else
607 setGeometryVert(my_geometry);
608 }
609
610 mAnimate = false;
611 QLayout::setGeometry(my_geometry);
612 }
613
614
615 /************************************************
616
617 ************************************************/
setItemGeometry(QLayoutItem * item,const QRect & geometry,bool withAnimation)618 void LXQtPanelLayout::setItemGeometry(QLayoutItem *item, const QRect &geometry, bool withAnimation)
619 {
620 Plugin *plugin = qobject_cast<Plugin*>(item->widget());
621 if (withAnimation && plugin)
622 {
623 ItemMoveAnimation* animation = new ItemMoveAnimation(item);
624 animation->setStartValue(item->geometry());
625 animation->setEndValue(geometry);
626 animation->start(animation->DeleteWhenStopped);
627 }
628 else
629 {
630 item->setGeometry(geometry);
631 }
632 }
633
634
635 /************************************************
636
637 ************************************************/
setGeometryHoriz(const QRect & geometry)638 void LXQtPanelLayout::setGeometryHoriz(const QRect &geometry)
639 {
640 const bool visual_h_reversed = parentWidget() && parentWidget()->isRightToLeft();
641 // Calc expFactor for expandable plugins like TaskBar.
642 double expFactor;
643 {
644 int expWidth = mLeftGrid->expandableSize() + mRightGrid->expandableSize();
645 int nonExpWidth = mLeftGrid->sizeHint().width() - mLeftGrid->expandableSize() +
646 mRightGrid->sizeHint().width() - mRightGrid->expandableSize();
647 expFactor = expWidth ? ((1.0 * geometry.width() - nonExpWidth) / expWidth) : 1;
648 }
649
650 // Calc baselines for plugins like button.
651 QVector<int> baseLines(qMax(mLeftGrid->colCount(), mRightGrid->colCount()));
652 const int bh = geometry.height() / baseLines.count();
653 const int base_center = bh >> 1;
654 const int height_remain = 0 < bh ? geometry.height() % baseLines.size() : 0;
655 {
656 int base = geometry.top();
657 for (auto i = baseLines.begin(), i_e = baseLines.end(); i_e != i; ++i, base += bh)
658 {
659 *i = base;
660 }
661 }
662
663 #if 0
664 qDebug() << "** LXQtPanelLayout::setGeometryHoriz **************";
665 qDebug() << "geometry: " << geometry;
666
667 qDebug() << "Left grid";
668 qDebug() << " cols:" << mLeftGrid->colCount() << " rows:" << mLeftGrid->rowCount();
669 qDebug() << " usedCols" << mLeftGrid->usedColCount();
670
671 qDebug() << "Right grid";
672 qDebug() << " cols:" << mRightGrid->colCount() << " rows:" << mRightGrid->rowCount();
673 qDebug() << " usedCols" << mRightGrid->usedColCount();
674 #endif
675
676
677 // Left aligned plugins.
678 int left=geometry.left();
679 for (int r=0; r<mLeftGrid->rowCount(); ++r)
680 {
681 int rw = 0;
682 int remain = height_remain;
683 for (int c=0; c<mLeftGrid->usedColCount(); ++c)
684 {
685 const LayoutItemInfo &info = mLeftGrid->itemInfo(r, c);
686 if (info.item)
687 {
688 QRect rect;
689 if (info.separate)
690 {
691 rect.setLeft(left);
692 rect.setTop(geometry.top());
693 rect.setHeight(geometry.height());
694
695 if (info.expandable)
696 rect.setWidth(info.geometry.width() * expFactor);
697 else
698 rect.setWidth(info.geometry.width());
699 }
700 else
701 {
702 int height = bh + (0 < remain-- ? 1 : 0);
703 if (!info.item->expandingDirections().testFlag(Qt::Orientation::Vertical))
704 height = qMin(info.geometry.height(), height);
705 height = qMin(geometry.height(), height);
706 rect.setHeight(height);
707 rect.setWidth(qMin(info.geometry.width(), geometry.width()));
708 if (height < bh)
709 rect.moveCenter(QPoint(0, baseLines[c] + base_center));
710 else
711 rect.moveTop(baseLines[c]);
712 rect.moveLeft(left);
713 }
714
715 rw = qMax(rw, rect.width());
716 if (visual_h_reversed)
717 rect.moveLeft(geometry.left() + geometry.right() - rect.x() - rect.width() + 1);
718 setItemGeometry(info.item, rect, mAnimate);
719 }
720 }
721 left += rw;
722 }
723
724 // Right aligned plugins.
725 int right=geometry.right();
726 for (int r=mRightGrid->rowCount()-1; r>=0; --r)
727 {
728 int rw = 0;
729 int remain = height_remain;
730 for (int c=0; c<mRightGrid->usedColCount(); ++c)
731 {
732 const LayoutItemInfo &info = mRightGrid->itemInfo(r, c);
733 if (info.item)
734 {
735 QRect rect;
736 if (info.separate)
737 {
738 rect.setTop(geometry.top());
739 rect.setHeight(geometry.height());
740
741 if (info.expandable)
742 rect.setWidth(info.geometry.width() * expFactor);
743 else
744 rect.setWidth(info.geometry.width());
745
746 rect.moveRight(right);
747 }
748 else
749 {
750 int height = bh + (0 < remain-- ? 1 : 0);
751 if (!info.item->expandingDirections().testFlag(Qt::Orientation::Vertical))
752 height = qMin(info.geometry.height(), height);
753 height = qMin(geometry.height(), height);
754 rect.setHeight(height);
755 rect.setWidth(qMin(info.geometry.width(), geometry.width()));
756 if (height < bh)
757 rect.moveCenter(QPoint(0, baseLines[c] + base_center));
758 else
759 rect.moveTop(baseLines[c]);
760 rect.moveRight(right);
761 }
762
763 rw = qMax(rw, rect.width());
764 if (visual_h_reversed)
765 rect.moveLeft(geometry.left() + geometry.right() - rect.x() - rect.width() + 1);
766 setItemGeometry(info.item, rect, mAnimate);
767 }
768 }
769 right -= rw;
770 }
771 }
772
773
774 /************************************************
775
776 ************************************************/
setGeometryVert(const QRect & geometry)777 void LXQtPanelLayout::setGeometryVert(const QRect &geometry)
778 {
779 const bool visual_h_reversed = parentWidget() && parentWidget()->isRightToLeft();
780 // Calc expFactor for expandable plugins like TaskBar.
781 double expFactor;
782 {
783 int expHeight = mLeftGrid->expandableSize() + mRightGrid->expandableSize();
784 int nonExpHeight = mLeftGrid->sizeHint().height() - mLeftGrid->expandableSize() +
785 mRightGrid->sizeHint().height() - mRightGrid->expandableSize();
786 expFactor = expHeight ? ((1.0 * geometry.height() - nonExpHeight) / expHeight) : 1;
787 }
788
789 // Calc baselines for plugins like button.
790 QVector<int> baseLines(qMax(mLeftGrid->colCount(), mRightGrid->colCount()));
791 const int bw = geometry.width() / baseLines.count();
792 const int base_center = bw >> 1;
793 const int width_remain = 0 < bw ? geometry.width() % baseLines.size() : 0;
794 {
795 int base = geometry.left();
796 for (auto i = baseLines.begin(), i_e = baseLines.end(); i_e != i; ++i, base += bw)
797 {
798 *i = base;
799 }
800 }
801
802 #if 0
803 qDebug() << "** LXQtPanelLayout::setGeometryVert **************";
804 qDebug() << "geometry: " << geometry;
805
806 qDebug() << "Left grid";
807 qDebug() << " cols:" << mLeftGrid->colCount() << " rows:" << mLeftGrid->rowCount();
808 qDebug() << " usedCols" << mLeftGrid->usedColCount();
809
810 qDebug() << "Right grid";
811 qDebug() << " cols:" << mRightGrid->colCount() << " rows:" << mRightGrid->rowCount();
812 qDebug() << " usedCols" << mRightGrid->usedColCount();
813 #endif
814
815 // Top aligned plugins.
816 int top=geometry.top();
817 for (int r=0; r<mLeftGrid->rowCount(); ++r)
818 {
819 int rh = 0;
820 int remain = width_remain;
821 for (int c=0; c<mLeftGrid->usedColCount(); ++c)
822 {
823 const LayoutItemInfo &info = mLeftGrid->itemInfo(r, c);
824 if (info.item)
825 {
826 QRect rect;
827 if (info.separate)
828 {
829 rect.moveTop(top);
830 rect.setLeft(geometry.left());
831 rect.setWidth(geometry.width());
832
833 if (info.expandable)
834 rect.setHeight(info.geometry.height() * expFactor);
835 else
836 rect.setHeight(info.geometry.height());
837 }
838 else
839 {
840 rect.setHeight(qMin(info.geometry.height(), geometry.height()));
841 int width = bw + (0 < remain-- ? 1 : 0);
842 if (!info.item->expandingDirections().testFlag(Qt::Orientation::Horizontal))
843 width = qMin(info.geometry.width(), width);
844 width = qMin(geometry.width(), width);
845 rect.setWidth(width);
846 if (width < bw)
847 rect.moveCenter(QPoint(baseLines[c] + base_center, 0));
848 else
849 rect.moveLeft(baseLines[c]);
850 rect.moveTop(top);
851 }
852
853 rh = qMax(rh, rect.height());
854 if (visual_h_reversed)
855 rect.moveLeft(geometry.left() + geometry.right() - rect.x() - rect.width() + 1);
856 setItemGeometry(info.item, rect, mAnimate);
857 }
858 }
859 top += rh;
860 }
861
862
863 // Bottom aligned plugins.
864 int bottom=geometry.bottom();
865 for (int r=mRightGrid->rowCount()-1; r>=0; --r)
866 {
867 int rh = 0;
868 int remain = width_remain;
869 for (int c=0; c<mRightGrid->usedColCount(); ++c)
870 {
871 const LayoutItemInfo &info = mRightGrid->itemInfo(r, c);
872 if (info.item)
873 {
874 QRect rect;
875 if (info.separate)
876 {
877 rect.setLeft(geometry.left());
878 rect.setWidth(geometry.width());
879
880 if (info.expandable)
881 rect.setHeight(info.geometry.height() * expFactor);
882 else
883 rect.setHeight(info.geometry.height());
884 rect.moveBottom(bottom);
885 }
886 else
887 {
888 rect.setHeight(qMin(info.geometry.height(), geometry.height()));
889 int width = bw + (0 < remain-- ? 1 : 0);
890 if (!info.item->expandingDirections().testFlag(Qt::Orientation::Horizontal))
891 width = qMin(info.geometry.width(), width);
892 width = qMin(geometry.width(), width);
893 rect.setWidth(width);
894 if (width < bw)
895 rect.moveCenter(QPoint(baseLines[c] + base_center, 0));
896 else
897 rect.moveLeft(baseLines[c]);
898 rect.moveBottom(bottom);
899 }
900
901 rh = qMax(rh, rect.height());
902 if (visual_h_reversed)
903 rect.moveLeft(geometry.left() + geometry.right() - rect.x() - rect.width() + 1);
904 setItemGeometry(info.item, rect, mAnimate);
905 }
906 }
907 bottom -= rh;
908 }
909 }
910
911
912 /************************************************
913
914 ************************************************/
invalidate()915 void LXQtPanelLayout::invalidate()
916 {
917 mLeftGrid->invalidate();
918 mRightGrid->invalidate();
919 mMinPluginSize = QSize();
920 QLayout::invalidate();
921 }
922
923
924 /************************************************
925
926 ************************************************/
lineCount() const927 int LXQtPanelLayout::lineCount() const
928 {
929 return mLeftGrid->colCount();
930 }
931
932
933 /************************************************
934
935 ************************************************/
setLineCount(int value)936 void LXQtPanelLayout::setLineCount(int value)
937 {
938 mLeftGrid->setColCount(value);
939 mRightGrid->setColCount(value);
940 invalidate();
941 }
942
943
944 /************************************************
945
946 ************************************************/
rebuild()947 void LXQtPanelLayout::rebuild()
948 {
949 mLeftGrid->rebuild();
950 mRightGrid->rebuild();
951 }
952
953
954 /************************************************
955
956 ************************************************/
lineSize() const957 int LXQtPanelLayout::lineSize() const
958 {
959 return mLeftGrid->lineSize();
960 }
961
962
963 /************************************************
964
965 ************************************************/
setLineSize(int value)966 void LXQtPanelLayout::setLineSize(int value)
967 {
968 mLeftGrid->setLineSize(value);
969 mRightGrid->setLineSize(value);
970 invalidate();
971 }
972
973
974 /************************************************
975
976 ************************************************/
setPosition(ILXQtPanel::Position value)977 void LXQtPanelLayout::setPosition(ILXQtPanel::Position value)
978 {
979 mPosition = value;
980 mLeftGrid->setHoriz(isHorizontal());
981 mRightGrid->setHoriz(isHorizontal());
982 }
983
984
985 /************************************************
986
987 ************************************************/
isHorizontal() const988 bool LXQtPanelLayout::isHorizontal() const
989 {
990 return mPosition == ILXQtPanel::PositionTop ||
991 mPosition == ILXQtPanel::PositionBottom;
992 }
993
994
995 /************************************************
996
997 ************************************************/
itemIsSeparate(QLayoutItem * item)998 bool LXQtPanelLayout::itemIsSeparate(QLayoutItem *item)
999 {
1000 if (!item)
1001 return true;
1002
1003 Plugin *p = qobject_cast<Plugin*>(item->widget());
1004 if (!p)
1005 return true;
1006
1007 return p->isSeparate();
1008 }
1009
1010
1011 /************************************************
1012
1013 ************************************************/
startMovePlugin()1014 void LXQtPanelLayout::startMovePlugin()
1015 {
1016 Plugin *plugin = qobject_cast<Plugin*>(sender());
1017 if (plugin)
1018 {
1019 // We have not memoryleaks there.
1020 // The processor will be automatically deleted when stopped.
1021 PluginMoveProcessor *moveProcessor = new PluginMoveProcessor(this, plugin);
1022 moveProcessor->start();
1023 connect(moveProcessor, &PluginMoveProcessor::finished, this, &LXQtPanelLayout::finishMovePlugin);
1024 }
1025 }
1026
1027
1028 /************************************************
1029
1030 ************************************************/
finishMovePlugin()1031 void LXQtPanelLayout::finishMovePlugin()
1032 {
1033 PluginMoveProcessor *moveProcessor = qobject_cast<PluginMoveProcessor*>(sender());
1034 if (moveProcessor)
1035 {
1036 Plugin *plugin = moveProcessor->plugin();
1037 int n = indexOf(plugin);
1038 plugin->setAlignment(n<mLeftGrid->count() ? Plugin::AlignLeft : Plugin::AlignRight);
1039 emit pluginMoved(plugin);
1040 }
1041 }
1042
1043 /************************************************
1044
1045 ************************************************/
moveUpPlugin(Plugin * plugin)1046 void LXQtPanelLayout::moveUpPlugin(Plugin * plugin)
1047 {
1048 const int i = indexOf(plugin);
1049 if (0 < i)
1050 moveItem(i, i - 1, true);
1051 }
1052
1053 /************************************************
1054
1055 ************************************************/
addPlugin(Plugin * plugin)1056 void LXQtPanelLayout::addPlugin(Plugin * plugin)
1057 {
1058 connect(plugin, &Plugin::startMove, this, &LXQtPanelLayout::startMovePlugin);
1059
1060 const int prev_count = count();
1061 addWidget(plugin);
1062
1063 //check actual position
1064 const int pos = indexOf(plugin);
1065 if (prev_count > pos)
1066 moveItem(pos, prev_count, false);
1067 }
1068