File indexing completed on 2024-04-28 05:51:09

0001 /*
0002  *  SPDX-FileCopyrightText: 2002-2003 Jesper K. Pedersen <blackie@kde.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-only
0005  **/
0006 
0007 #include "kmultiformlistbox-multivisible.h"
0008 
0009 #include <QBitmap>
0010 #include <QPushButton>
0011 #include <QVBoxLayout>
0012 
0013 #include <KMessageBox>
0014 
0015 #include "ccp.h"
0016 #include "indexWindow.h"
0017 #include "kmultiformlistboxfactory.h"
0018 
0019 const int indexButtonWidth = 16;
0020 const int indexButtonHeight = 12;
0021 const uchar indexButtonBits[] = {0x00, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x04, 0x02, 0x04, 0x02, 0xc4, 0x8a,
0022                                  0x24, 0x53, 0x14, 0x22, 0x14, 0x22, 0x24, 0x53, 0xce, 0x8a, 0x00, 0x00};
0023 
0024 KMultiFormListBoxMultiVisible::KMultiFormListBoxMultiVisible(KMultiFormListBoxFactory *fact, QWidget *parent)
0025     : QScrollArea(parent)
0026 {
0027     factory = fact;
0028 
0029     // Initialize the element list
0030     elms = new WidgetList();
0031 
0032     QWidget *widget = new QWidget();
0033     layout = new QVBoxLayout(widget);
0034     layout->setSpacing(0);
0035     layout->setContentsMargins(0, 0, 0, 0);
0036     setWidget(widget);
0037     setWidgetResizable(true);
0038 }
0039 
0040 //----------------------------------------------------------------------
0041 // This function returns a list of the elements in the KMultiFormListBox widget.
0042 //----------------------------------------------------------------------
0043 KMultiFormListBoxEntryList KMultiFormListBoxMultiVisible::elements()
0044 {
0045     KMultiFormListBoxEntryList res;
0046     for (QWidget *child : *elms) {
0047         if (child->objectName() != QStringLiteral("separator")) {
0048             res.append((KMultiFormListBoxEntry *)child);
0049         }
0050     }
0051     return res;
0052 }
0053 
0054 //----------------------------------------------------------------------
0055 // This function is called whenever the KMultiFormListBox widget is resized. It is
0056 // necessary to ensure that the content of the clipper is resized.
0057 //----------------------------------------------------------------------
0058 void KMultiFormListBoxMultiVisible::resizeEvent(QResizeEvent *e)
0059 {
0060     // The call of the super class ensures that the outer border is updated.
0061     QScrollArea::resizeEvent(e);
0062 
0063     updateClipperContent();
0064 }
0065 
0066 void KMultiFormListBoxMultiVisible::updateClipperContent()
0067 {
0068     // Extract the current size of the clipper
0069     /*
0070     int ClipperWidth = clipper()->size().width();
0071     int ClipperHeight = clipper()->size().height();
0072 
0073     // Initialize the calculation of the size of the new clipper.
0074     int totalHeight = 0;
0075     int maxWidth = ClipperWidth;
0076     int count = 0;
0077 
0078     // calculate the required size.
0079     for (QWidget *child : *elms) {
0080       maxWidth = qMax(maxWidth, child->sizeHint().width());
0081       if ( child->objectName() != "separator" ) {
0082         totalHeight += child->sizeHint().height();
0083         count++;
0084       }
0085       else {
0086         totalHeight += child->size().height();
0087       }
0088     }
0089 
0090     // Calculate the extra height for the elements.
0091     int extra = 0;
0092     if (totalHeight < ClipperHeight && count != 0) {
0093       extra = (ClipperHeight - totalHeight) / count;
0094       totalHeight = ClipperHeight;
0095     }
0096 
0097     // Now place the elements in the clipper.
0098     int yPos = 0;
0099     for (QWidget *child2 : *elms) {
0100       int h;
0101       if ( child2->objectName() != "separator" ) {
0102         h = child2->sizeHint().height();
0103         h += extra;
0104       }
0105       else {
0106         h = child2->size().height();
0107       }
0108 
0109       moveChild(child2, 0,yPos);
0110 
0111       child2->resize(maxWidth,h);
0112       yPos += h;
0113     }
0114     */
0115 
0116     // Finally call the resize procedure for the clipper to ensure that the
0117     // new sizes is shown properly.
0118     // resizeContents(maxWidth, totalHeight);
0119 }
0120 
0121 void KMultiFormListBoxMultiVisible::addElement()
0122 {
0123     addElement(nullptr);
0124 }
0125 
0126 void KMultiFormListBoxMultiVisible::addElement(KMultiFormListBoxEntry *after)
0127 {
0128     KMultiFormListBoxEntry *elm = factory->create(widget());
0129     insertElmIntoWidget(elm, after);
0130 }
0131 
0132 void KMultiFormListBoxMultiVisible::append(KMultiFormListBoxEntry *elm)
0133 {
0134     elm->setParent(widget());
0135     insertElmIntoWidget(elm, nullptr);
0136 }
0137 
0138 void KMultiFormListBoxMultiVisible::delElement(QWidget *elm)
0139 {
0140     int index = elms->indexOf(elm);
0141     QWidget *next = elms->at(index + 1);
0142     if (next->objectName() != QStringLiteral("separator")) {
0143         elms->removeOne(next);
0144         layout->removeWidget(next);
0145     }
0146 
0147     elms->removeOne(elm);
0148     layout->removeWidget(elm);
0149 
0150     updateClipperContent();
0151 }
0152 
0153 void KMultiFormListBoxMultiVisible::delAnElement()
0154 {
0155     delElement(elms->at(0));
0156 }
0157 
0158 void KMultiFormListBoxMultiVisible::insertElmIntoWidget(KMultiFormListBoxEntry *elm, KMultiFormListBoxEntry *after)
0159 {
0160     // Bind the index button if it exists.
0161     if (elm->indexButton()) {
0162         elm->indexButton()->setIcon(static_cast<QIcon>(QBitmap::fromData(QSize(indexButtonWidth, indexButtonHeight), indexButtonBits, QImage::Format_MonoLSB)));
0163         connect(elm->indexButton(), &QAbstractButton::clicked, elm, &KMultiFormListBoxEntry::acceptIndexButton);
0164         connect(elm, &KMultiFormListBoxEntry::gotoIndex, this, &KMultiFormListBoxMultiVisible::showIndexList);
0165     }
0166 
0167     // Find the location to insert the new element.
0168     int index = elms->count();
0169     if (after) {
0170         index = elms->indexOf(after);
0171     }
0172 
0173     // Now show the new element.
0174     elms->insert(index, elm);
0175     layout->insertWidget(index, elm);
0176     elm->show();
0177     ensureWidgetVisible(elm, 0, 0);
0178     // addChild(elm,0,0); // updateClipperContent will place the child correctly.
0179 
0180     QWidget *sep = factory->separator(widget());
0181     if (sep != nullptr) {
0182         sep->setObjectName(QStringLiteral("separator"));
0183         sep->show();
0184         layout->insertWidget(index + 1, sep); // updateClipperContent will place the child correctly.
0185         elms->insert(index + 1, sep);
0186     }
0187 
0188     updateClipperContent();
0189 
0190     showWidget(elm); // scroll to show the new widget.
0191 
0192     // install cut'n'paste functionallity
0193     new CCP(this, elm);
0194 }
0195 
0196 //----------------------------------------------------------------------
0197 // This function shows the list of available Idx elements.
0198 //----------------------------------------------------------------------
0199 void KMultiFormListBoxMultiVisible::showIndexList(KMultiFormListBoxEntry *elm)
0200 {
0201     indexWindow *menu = new indexWindow();
0202 
0203     // Insert the elements into the menu item.
0204     for (QWidget *child : *elms) {
0205         if (child->objectName() != QStringLiteral("separator")) {
0206             QString txt = ((KMultiFormListBoxEntry *)child)->idxString();
0207             menu->insertItem(txt);
0208         }
0209     }
0210 
0211     // Calculate the location of the window
0212     QPoint start;
0213     int width;
0214     elm->indexWindowPos(&start, &width);
0215 
0216     // Show the window.
0217     int index = menu->exec(start, width);
0218 
0219     if (index != -1) {
0220         for (QWidget *child : *elms) {
0221             if (child->objectName() != QLatin1String("separator")) {
0222                 if (index == 0) {
0223                     showWidget((KMultiFormListBoxEntry *)child);
0224                     break;
0225                 }
0226                 index--;
0227             }
0228         }
0229     }
0230     delete menu;
0231 }
0232 
0233 //----------------------------------------------------------------------
0234 // Scroll to the loaction of the given KMultiFormListBoxEntry element.
0235 //----------------------------------------------------------------------
0236 void KMultiFormListBoxMultiVisible::showWidget(KMultiFormListBoxEntry *elm)
0237 {
0238     ensureWidgetVisible(elm);
0239 }
0240 
0241 void KMultiFormListBoxMultiVisible::cut(KMultiFormListBoxEntry *elm)
0242 {
0243     if (countElements(elms) == 1) {
0244         KMessageBox::information(this, i18n("Due to a bug, it is not possible to remove the last element."), i18n("Internal Error"));
0245         return;
0246     }
0247 
0248     QDataStream stream(&clipboard, QIODeviceBase::WriteOnly);
0249 
0250     stream.setVersion(QDataStream::Qt_3_1);
0251     factory->toStream(elm, stream);
0252     delElement(elm);
0253 }
0254 
0255 void KMultiFormListBoxMultiVisible::copy(KMultiFormListBoxEntry *elm)
0256 {
0257     QDataStream stream(&clipboard, QIODeviceBase::WriteOnly);
0258 
0259     stream.setVersion(QDataStream::Qt_3_1);
0260     factory->toStream(elm, stream);
0261 }
0262 
0263 void KMultiFormListBoxMultiVisible::paste(KMultiFormListBoxEntry *oldElm)
0264 {
0265     if (clipboard.isEmpty()) {
0266         KMessageBox::information(this, i18n("There is no element on the clipboard to paste in."));
0267         return;
0268     }
0269 
0270     KMultiFormListBoxEntry *newElm = factory->create(widget());
0271     QDataStream stream(&clipboard, QIODeviceBase::ReadOnly);
0272 
0273     stream.setVersion(QDataStream::Qt_3_1);
0274     factory->fromStream(stream, newElm);
0275     insertElmIntoWidget(newElm, oldElm);
0276 }
0277 
0278 int KMultiFormListBoxMultiVisible::countElements(WidgetList *elms)
0279 {
0280     int count = 0;
0281 
0282     for (QWidget *child : *elms) {
0283         if (dynamic_cast<const KMultiFormListBoxEntry *>(child)) {
0284             count++;
0285         }
0286     }
0287 
0288     return count;
0289 }
0290 
0291 #include "moc_kmultiformlistbox-multivisible.cpp"