Widgets.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2004 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 #ifndef _PreComp_
00026 # include <QColorDialog>
00027 # include <QDesktopWidget>
00028 # include <QDialogButtonBox>
00029 # include <QDrag>
00030 # include <QKeyEvent>
00031 # include <QMimeData>
00032 # include <QPainter>
00033 # include <QPlainTextEdit>
00034 # include <QStylePainter>
00035 # include <QToolTip>
00036 #endif
00037 
00038 #include <Base/Exception.h>
00039 #include <Base/Interpreter.h>
00040 
00041 #include "Widgets.h"
00042 #include "Application.h"
00043 #include "Action.h"
00044 #include "PrefWidgets.h"
00045 
00046 using namespace Gui;
00047 
00051 CommandIconView::CommandIconView ( QWidget * parent )
00052   : QListWidget(parent)
00053 {
00054     connect(this, SIGNAL (currentItemChanged(QListWidgetItem *, QListWidgetItem *)), 
00055             this, SLOT (onSelectionChanged(QListWidgetItem *, QListWidgetItem *)) );
00056 }
00057 
00061 CommandIconView::~CommandIconView ()
00062 {
00063 }
00064 
00068 void CommandIconView::startDrag ( Qt::DropActions supportedActions )
00069 {
00070     QList<QListWidgetItem*> items = selectedItems();
00071     QByteArray itemData;
00072     QDataStream dataStream(&itemData, QIODevice::WriteOnly);
00073 
00074     QPixmap pixmap;
00075     dataStream << items.count();
00076     for (QList<QListWidgetItem*>::ConstIterator it = items.begin(); it != items.end(); ++it) {
00077         if (it == items.begin())
00078             pixmap = qVariantValue<QPixmap>((*it)->data(Qt::UserRole));
00079         dataStream << (*it)->text();
00080     }
00081 
00082     QMimeData *mimeData = new QMimeData;
00083     mimeData->setData(QString::fromAscii("text/x-action-items"), itemData);
00084 
00085     QDrag *drag = new QDrag(this);
00086     drag->setMimeData(mimeData);
00087     drag->setHotSpot(QPoint(pixmap.width()/2, pixmap.height()/2));
00088     drag->setPixmap(pixmap);
00089     drag->start(Qt::MoveAction);
00090 }
00091 
00097 void CommandIconView::onSelectionChanged(QListWidgetItem * item, QListWidgetItem *)
00098 {
00099     if (item)
00100         emitSelectionChanged(item->toolTip());
00101 }
00102 
00103 // ------------------------------------------------------------------------------
00104 
00105 /* TRANSLATOR Gui::AccelLineEdit */
00106 
00111 AccelLineEdit::AccelLineEdit ( QWidget * parent )
00112   : QLineEdit(parent)
00113 {
00114     setText(tr("none"));
00115 }
00116 
00120 void AccelLineEdit::keyPressEvent ( QKeyEvent * e)
00121 {
00122     QString txt;
00123     setText(tr("none"));
00124 
00125     int key = e->key();
00126     Qt::KeyboardModifiers state = e->modifiers();
00127 
00128     if (key == Qt::Key_Control)
00129         return;
00130     else if (key == Qt::Key_Shift)
00131         return;
00132     else if (key == Qt::Key_Alt)
00133         return;
00134     else if (state == Qt::NoModifier && key == Qt::Key_Backspace)
00135         return; // clears the edit field
00136 
00137     switch(state)
00138     {
00139     case Qt::ControlModifier:
00140         {
00141             QKeySequence ks(Qt::CTRL+key);
00142             txt += (QString)(ks);
00143             setText(txt);
00144         }   break;
00145     case Qt::AltModifier:
00146         {
00147             QKeySequence ks(Qt::ALT+key);
00148             txt += (QString)(ks);
00149             setText(txt);
00150         }   break;
00151     case Qt::ShiftModifier:
00152         {
00153             QKeySequence ks(Qt::SHIFT+key);
00154             txt += (QString)(ks);
00155             setText(txt);
00156         }   break;
00157     case Qt::ControlModifier+Qt::AltModifier:
00158         {
00159             QKeySequence ks(Qt::CTRL+Qt::ALT+key);
00160             txt += (QString)(ks);
00161             setText(txt);
00162         }   break;
00163     case Qt::ControlModifier+Qt::ShiftModifier:
00164         {
00165             QKeySequence ks(Qt::CTRL+Qt::SHIFT+key);
00166             txt += (QString)(ks);
00167             setText(txt);
00168         }   break;
00169     case Qt::ShiftModifier+Qt::AltModifier:
00170         {
00171             QKeySequence ks(Qt::SHIFT+Qt::ALT+key);
00172             txt += (QString)(ks);
00173             setText(txt);
00174         }   break;
00175     case Qt::ControlModifier+Qt::AltModifier+Qt::ShiftModifier:
00176         {
00177             QKeySequence ks(Qt::CTRL+Qt::ALT+Qt::SHIFT+key);
00178             txt += (QString)(ks);
00179             setText(txt);
00180         }   break;
00181     default:
00182         {
00183             QKeySequence ks(key);
00184             txt += (QString)(ks);
00185             setText(txt);
00186         }   break;
00187     }
00188 }
00189 
00190 // ------------------------------------------------------------------------------
00191 
00192 /* TRANSLATOR Gui::CheckListDialog */
00193 
00201 CheckListDialog::CheckListDialog( QWidget* parent, Qt::WFlags fl )
00202     : QDialog( parent, fl )
00203 {
00204     ui.setupUi(this);
00205 }
00206 
00210 CheckListDialog::~CheckListDialog()
00211 {
00212     // no need to delete child widgets, Qt does it all for us
00213 }
00214 
00218 void CheckListDialog::setCheckableItems( const QStringList& items )
00219 {
00220     for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it ) {
00221         QTreeWidgetItem* item = new QTreeWidgetItem(ui.treeWidget);
00222         item->setText(0, *it);
00223         item->setCheckState(0, Qt::Unchecked);
00224     }
00225 }
00226 
00231 void CheckListDialog::setCheckableItems( const QList<CheckListItem>& items )
00232 {
00233     for ( QList<CheckListItem>::ConstIterator it = items.begin(); it != items.end(); ++it ) {
00234         QTreeWidgetItem* item = new QTreeWidgetItem(ui.treeWidget);
00235         item->setText(0, (*it).first);
00236         item->setCheckState(0, ( (*it).second ? Qt::Checked : Qt::Unchecked));
00237     }
00238 }
00239 
00243 QStringList CheckListDialog::getCheckedItems() const
00244 {
00245     return checked;
00246 }
00247 
00251 void CheckListDialog::accept ()
00252 {
00253     QTreeWidgetItemIterator it(ui.treeWidget, QTreeWidgetItemIterator::Checked);
00254     while (*it) {
00255         checked.push_back((*it)->text(0));
00256         ++it;
00257     }
00258 
00259     QDialog::accept();
00260 }
00261 
00262 // ------------------------------------------------------------------------------
00263 
00264 namespace Gui {
00265 struct ColorButtonP
00266 {
00267     QColor old, col;
00268     QPointer<QColorDialog> cd;
00269     bool allowChange;
00270     bool drawFrame;
00271     bool modal;
00272 
00273     ColorButtonP() : cd(0), allowChange(true), drawFrame(true), modal(true)
00274     {
00275     }
00276 };
00277 }
00278 
00282 ColorButton::ColorButton(QWidget* parent)
00283     : QPushButton(parent)
00284 {
00285     d = new ColorButtonP();
00286     d->col = palette().color(QPalette::Active,QPalette::Midlight);
00287     connect(this, SIGNAL(clicked()), SLOT(onChooseColor()));
00288 }
00289 
00293 ColorButton::~ColorButton()
00294 {
00295     delete d;
00296 }
00297 
00301 void ColorButton::setColor(const QColor& c)
00302 {
00303     d->col = c;
00304     update();
00305 }
00306 
00310 QColor ColorButton::color() const
00311 {
00312     return d->col;
00313 }
00314 
00315 void ColorButton::setAllowChangeColor(bool ok)
00316 {
00317     d->allowChange = ok;
00318 }
00319 
00320 bool ColorButton::allowChangeColor() const
00321 {
00322     return d->allowChange;
00323 }
00324 
00325 void ColorButton::setDrawFrame(bool ok)
00326 {
00327     d->drawFrame = ok;
00328 }
00329 
00330 bool ColorButton::drawFrame() const
00331 {
00332     return d->drawFrame;
00333 }
00334 
00335 void ColorButton::setModal(bool b)
00336 {
00337     d->modal = b;
00338 }
00339 
00340 bool ColorButton::isModal() const
00341 {
00342     return d->modal;
00343 }
00344 
00348 void ColorButton::paintEvent (QPaintEvent * e)
00349 {
00350     // first paint the complete button
00351     QPushButton::paintEvent(e);
00352 
00353     // repaint the rectangle area
00354     QPalette::ColorGroup group = isEnabled() ? hasFocus() ? QPalette::Active : QPalette::Inactive : QPalette::Disabled;
00355     QColor pen = palette().color(group,QPalette::ButtonText);
00356     {
00357         QPainter paint(this);
00358         paint.setPen(pen);
00359 
00360         if (d->drawFrame) {
00361             paint.setBrush(QBrush(d->col));
00362             paint.drawRect(5, 5, width()-10, height()-10);
00363         }
00364         else {
00365             paint.fillRect(5, 5, width()-10, height()-10, QBrush(d->col));
00366         }
00367     }
00368 
00369     // overpaint the rectangle to paint icon and text 
00370     QStyleOptionButton opt;
00371     opt.init(this);
00372     opt.text = text();
00373     opt.icon = icon();
00374     opt.iconSize = iconSize();
00375 
00376     QStylePainter p(this);
00377     p.drawControl(QStyle::CE_PushButtonLabel, opt);
00378 }
00379 
00383 void ColorButton::onChooseColor()
00384 {
00385     if (!d->allowChange)
00386         return;
00387 #if QT_VERSION >= 0x040500
00388     if (d->modal) {
00389 #endif
00390         QColor c = QColorDialog::getColor(d->col, this);
00391         if (c.isValid()) {
00392             setColor(c);
00393             changed();
00394         }
00395 #if QT_VERSION >= 0x040500
00396     }
00397     else {
00398         if (d->cd.isNull()) {
00399             d->old = d->col;
00400             d->cd = new QColorDialog(d->col, this);
00401             d->cd->setAttribute(Qt::WA_DeleteOnClose);
00402             connect(d->cd, SIGNAL(rejected()),
00403                     this, SLOT(onRejected()));
00404             connect(d->cd, SIGNAL(currentColorChanged(const QColor &)),
00405                     this, SLOT(onColorChosen(const QColor&)));
00406         }
00407         d->cd->show();
00408     }
00409 #endif
00410 }
00411 
00412 void ColorButton::onColorChosen(const QColor& c)
00413 {
00414     setColor(c);
00415     changed();
00416 }
00417 
00418 void ColorButton::onRejected()
00419 {
00420     setColor(d->old);
00421     changed();
00422 }
00423 
00424 // ------------------------------------------------------------------------------
00425 
00426 UrlLabel::UrlLabel(QWidget * parent, Qt::WFlags f)
00427   : QLabel(parent, f)
00428 {
00429     _url = QString::fromAscii("http://localhost");
00430     setToolTip(this->_url);
00431 }
00432 
00433 UrlLabel::~UrlLabel()
00434 {
00435 }
00436 
00437 void UrlLabel::enterEvent ( QEvent * )
00438 {
00439     setCursor(Qt::PointingHandCursor);
00440 }
00441 
00442 void UrlLabel::leaveEvent ( QEvent * )
00443 {
00444     setCursor(Qt::ArrowCursor);
00445 }
00446 
00447 void UrlLabel::mouseReleaseEvent (QMouseEvent *)
00448 {
00449     // The webbrowser Python module allows to start the system browser in an OS-independent way
00450     Base::PyGILStateLocker lock;
00451     PyObject* module = PyImport_ImportModule("webbrowser");
00452     if (module) {
00453         // get the methods dictionary and search for the 'open' method
00454         PyObject* dict = PyModule_GetDict(module);
00455         PyObject* func = PyDict_GetItemString(dict, "open");
00456         if (func) {
00457             PyObject* args = Py_BuildValue("(s)", (const char*)this->_url.toAscii());
00458             PyObject* result = PyEval_CallObject(func,args);
00459             // decrement the args and module reference
00460             Py_XDECREF(result);
00461             Py_DECREF(args);
00462             Py_DECREF(module);
00463         }
00464     }
00465 }
00466 
00467 QString UrlLabel::url() const
00468 {
00469     return this->_url;
00470 }
00471 
00472 void UrlLabel::setUrl(const QString& u)
00473 {
00474     this->_url = u;
00475     setToolTip(this->_url);
00476 }
00477 
00478 // --------------------------------------------------------------------
00479 
00480 /* TRANSLATOR Gui::LabelButton */
00481 
00485 LabelButton::LabelButton (QWidget * parent)
00486   : QWidget(parent)
00487 {
00488     QHBoxLayout *layout = new QHBoxLayout(this);
00489     layout->setMargin(0);
00490     layout->setSpacing(1);
00491 
00492     label = new QLabel(this);
00493     label->setAutoFillBackground(true);
00494     layout->addWidget(label);
00495 
00496     button = new QPushButton(QLatin1String("..."), this);
00497     layout->addWidget(button);
00498 
00499     connect(button, SIGNAL(clicked()), this, SLOT(browse()));
00500 }
00501 
00502 LabelButton::~LabelButton()
00503 {
00504 }
00505 
00506 void LabelButton::resizeEvent(QResizeEvent* e)
00507 {
00508     button->setFixedWidth(e->size().height());
00509 }
00510 
00511 QLabel *LabelButton::getLabel() const
00512 {
00513     return label;
00514 }
00515 
00516 QPushButton *LabelButton::getButton() const
00517 {
00518     return button;
00519 }
00520 
00521 QVariant LabelButton::value() const
00522 {
00523     return _val;
00524 }
00525 
00526 void LabelButton::setValue(const QVariant& val)
00527 {
00528     _val = val;
00529     showValue(_val);
00530     valueChanged(_val);
00531 }
00532 
00533 // ----------------------------------------------------------------------
00534 
00535 ToolTip* ToolTip::inst = 0;
00536 
00537 ToolTip* ToolTip::instance()
00538 {
00539     if (!inst)
00540         inst = new ToolTip();
00541     return inst;
00542 }
00543 
00544 ToolTip::ToolTip() : installed(false), hidden(true)
00545 {
00546 }
00547 
00548 ToolTip::~ToolTip()
00549 {
00550 }
00551 
00552 void ToolTip::installEventFilter()
00553 {
00554     if (this->installed)
00555         return;
00556     qApp->installEventFilter(this);
00557     this->installed = true;
00558 }
00559 
00560 void ToolTip::removeEventFilter()
00561 {
00562     if (!this->installed)
00563         return;
00564     qApp->removeEventFilter(this);
00565     this->installed = false;
00566 }
00567 
00568 void ToolTip::showText(const QPoint & pos, const QString & text, QWidget * w)
00569 {
00570     ToolTip* tip = instance();
00571     if (!text.isEmpty()) {
00572         // install this object to filter timer events for the tooltip label
00573         tip->installEventFilter();
00574         tip->pos = pos;
00575         tip->text = text;
00576         tip->w = w;
00577         // show text with a short delay
00578         tip->tooltipTimer.start(80, tip);
00579     }
00580     else {
00581         // do immediately
00582         QToolTip::showText(pos, text, w);
00583     }
00584 }
00585 
00586 void ToolTip::timerEvent(QTimerEvent *e)
00587 {
00588     if (e->timerId() == tooltipTimer.timerId()) {
00589         QToolTip::showText(pos, text, w);
00590         tooltipTimer.stop();
00591         displayTime.restart();
00592     }
00593 }
00594 
00595 bool ToolTip::eventFilter(QObject* o, QEvent*e)
00596 {
00597     // This is a trick to circumvent that the tooltip gets hidden immediately
00598     // after it gets visible. We just filter out all timer events to keep the
00599     // label visible.
00600     if (o->inherits("QLabel")) {
00601         QLabel* label = qobject_cast<QLabel*>(o);
00602         // Ignore the timer events to prevent from being closed
00603         if (label->windowFlags() & Qt::ToolTip) {
00604             if (e->type() == QEvent::Show) {
00605                 this->hidden = false;
00606             }
00607             else if (e->type() == QEvent::Hide) {
00608                 removeEventFilter();
00609                 this->hidden = true;
00610             }
00611             else if (e->type() == QEvent::Timer && 
00612                 !this->hidden && displayTime.elapsed() < 5000) {
00613                 return true;
00614             }
00615         }
00616     }
00617     return false;
00618 }
00619 
00620 // ----------------------------------------------------------------------
00621 
00622 StatusWidget::StatusWidget(QWidget* parent)
00623   : QWidget(parent, Qt::Dialog | Qt::FramelessWindowHint)
00624 {
00625     //setWindowModality(Qt::ApplicationModal);
00626     label = new QLabel(this);
00627     label->setAlignment(Qt::AlignCenter);
00628 
00629     QGridLayout* gridLayout = new QGridLayout(this);
00630     gridLayout->setSpacing(6);
00631     gridLayout->setMargin(9);
00632     gridLayout->addWidget(label, 0, 0, 1, 1);
00633 }
00634 
00635 StatusWidget::~StatusWidget()
00636 {
00637 }
00638 
00639 void StatusWidget::setStatusText(const QString& s)
00640 {
00641     label->setText(s);
00642 }
00643 
00644 QSize StatusWidget::sizeHint () const
00645 {
00646     return QSize(250,100);
00647 }
00648 
00649 void StatusWidget::showEvent(QShowEvent*)
00650 {
00651     adjustPosition(parentWidget());
00652 }
00653 
00654 void StatusWidget::hideEvent(QHideEvent*)
00655 {
00656 }
00657 
00658 // taken from QDialog::adjustPosition(QWidget*)
00659 void StatusWidget::adjustPosition(QWidget* w)
00660 {
00661     QPoint p(0, 0);
00662     int extraw = 0, extrah = 0, scrn = 0;
00663     if (w)
00664         w = w->window();
00665     QRect desk;
00666     if (w) {
00667         scrn = QApplication::desktop()->screenNumber(w);
00668     } else if (QApplication::desktop()->isVirtualDesktop()) {
00669         scrn = QApplication::desktop()->screenNumber(QCursor::pos());
00670     } else {
00671         scrn = QApplication::desktop()->screenNumber(this);
00672     }
00673     desk = QApplication::desktop()->availableGeometry(scrn);
00674 
00675     QWidgetList list = QApplication::topLevelWidgets();
00676     for (int i = 0; (extraw == 0 || extrah == 0) && i < list.size(); ++i) {
00677         QWidget * current = list.at(i);
00678         if (current->isVisible()) {
00679             int framew = current->geometry().x() - current->x();
00680             int frameh = current->geometry().y() - current->y();
00681 
00682             extraw = qMax(extraw, framew);
00683             extrah = qMax(extrah, frameh);
00684         }
00685     }
00686 
00687     // sanity check for decoration frames. With embedding, we
00688     // might get extraordinary values
00689     if (extraw == 0 || extrah == 0 || extraw >= 10 || extrah >= 40) {
00690         extrah = 40;
00691         extraw = 10;
00692     }
00693 
00694 
00695     if (w) {
00696         // Use mapToGlobal rather than geometry() in case w might
00697         // be embedded in another application
00698         QPoint pp = w->mapToGlobal(QPoint(0,0));
00699         p = QPoint(pp.x() + w->width()/2,
00700                     pp.y() + w->height()/ 2);
00701     } else {
00702         // p = middle of the desktop
00703         p = QPoint(desk.x() + desk.width()/2, desk.y() + desk.height()/2);
00704     }
00705 
00706     // p = origin of this
00707     p = QPoint(p.x()-width()/2 - extraw,
00708                 p.y()-height()/2 - extrah);
00709 
00710 
00711     if (p.x() + extraw + width() > desk.x() + desk.width())
00712         p.setX(desk.x() + desk.width() - width() - extraw);
00713     if (p.x() < desk.x())
00714         p.setX(desk.x());
00715 
00716     if (p.y() + extrah + height() > desk.y() + desk.height())
00717         p.setY(desk.y() + desk.height() - height() - extrah);
00718     if (p.y() < desk.y())
00719         p.setY(desk.y());
00720 
00721     move(p);
00722 }
00723 
00724 // --------------------------------------------------------------------
00725 
00726 LabelEditor::LabelEditor (QWidget * parent)
00727   : QWidget(parent)
00728 {
00729     QHBoxLayout *layout = new QHBoxLayout(this);
00730     layout->setMargin(0);
00731     layout->setSpacing(2);
00732 
00733     lineEdit = new QLineEdit(this);
00734     layout->addWidget(lineEdit);
00735 
00736     connect(lineEdit, SIGNAL(textChanged(const QString &)),
00737             this, SIGNAL(textChanged(const QString &)));
00738 
00739     button = new QPushButton(QLatin1String("..."), this);
00740     button->setFixedWidth(2*button->fontMetrics().width(QLatin1String(" ... ")));
00741     layout->addWidget(button);
00742 
00743     connect(button, SIGNAL(clicked()), this, SLOT(changeText()));
00744 
00745     setFocusProxy(lineEdit);
00746 }
00747 
00748 LabelEditor::~LabelEditor()
00749 {
00750 }
00751 
00752 QString LabelEditor::text() const
00753 {
00754     return lineEdit->text();
00755 }
00756 
00757 void LabelEditor::setText(const QString& s)
00758 {
00759     lineEdit->setText(s);
00760 }
00761 
00762 void LabelEditor::changeText()
00763 {
00764     QDialog dlg(this);
00765     QVBoxLayout* hboxLayout = new QVBoxLayout(&dlg);
00766     QDialogButtonBox* buttonBox = new QDialogButtonBox(&dlg);
00767     buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Close);
00768 
00769     QPlainTextEdit *edit = new QPlainTextEdit(&dlg);
00770     edit->setPlainText(this->lineEdit->text());
00771     
00772     hboxLayout->addWidget(edit);
00773     hboxLayout->addWidget(buttonBox);
00774     connect(buttonBox, SIGNAL(accepted()), &dlg, SLOT(accept()));
00775     connect(buttonBox, SIGNAL(rejected()), &dlg, SLOT(reject()));
00776     if (dlg.exec() == QDialog::Accepted) {
00777         this->lineEdit->setText(edit->toPlainText());
00778     }
00779 }
00780 
00784 void LabelEditor::setButtonText(const QString& txt)
00785 {
00786     button->setText(txt);
00787     int w1 = 2*button->fontMetrics().width(txt);
00788     int w2 = 2*button->fontMetrics().width(QLatin1String(" ... "));
00789     button->setFixedWidth((w1 > w2 ? w1 : w2));
00790 }
00791 
00795 QString LabelEditor::buttonText() const
00796 {
00797     return button->text();
00798 }
00799 
00800 #include "moc_Widgets.cpp"

Generated on Wed Nov 23 19:01:02 2011 for FreeCAD by  doxygen 1.6.1