Page MenuHomePhorge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/kdeui/widgets/kcharselect.cpp b/kdeui/widgets/kcharselect.cpp
index adb2d3dcbf..70c0103bfe 100644
--- a/kdeui/widgets/kcharselect.cpp
+++ b/kdeui/widgets/kcharselect.cpp
@@ -1,900 +1,900 @@
/* This file is part of the KDE libraries
Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kcharselect.h"
#include "kcharselect_p.h"
#include <QActionEvent>
#include <QDoubleSpinBox>
#include <QHeaderView>
#include <QBoxLayout>
#include <QShortcut>
#include <QSplitter>
#include <QPushButton>
#include <QToolButton>
#include <kicon.h>
#include <kcombobox.h>
#include <kdebug.h>
#include <kdialog.h>
#include <klocale.h>
#include <klineedit.h>
#include <ktextbrowser.h>
#include <kfontcombobox.h>
#include <kactioncollection.h>
#include <kstandardaction.h>
K_GLOBAL_STATIC(KCharSelectData, s_data)
class KCharSelectTablePrivate
{
public:
KCharSelectTablePrivate(KCharSelectTable *q): q(q), model(0)
{}
KCharSelectTable *q;
QFont font;
KCharSelectItemModel *model;
QList<QChar> chars;
QChar chr;
void _k_resizeCells();
void _k_doubleClicked(const QModelIndex & index);
void _k_slotSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected);
};
class KCharSelect::KCharSelectPrivate
{
public:
struct HistoryItem
{
QChar c;
bool fromSearch;
QString searchString;
};
enum { MaxHistoryItems = 100 };
KCharSelectPrivate(KCharSelect *q)
: q(q)
,searchLine(0)
,searchMode(false)
,historyEnabled(false)
,inHistory(0)
,actions(NULL)
{
}
KCharSelect *q;
QToolButton *backButton;
QToolButton *forwardButton;
KLineEdit* searchLine;
KFontComboBox *fontCombo;
QSpinBox *fontSizeSpinBox;
QComboBox *sectionCombo;
QComboBox *blockCombo;
KCharSelectTable *charTable;
KTextBrowser *detailBrowser;
bool searchMode; //a search is active
bool historyEnabled;
int inHistory; //index of current char in history
QList<HistoryItem> history;
KActionCollection* actions;
QString createLinks(QString s);
void historyAdd(const QChar &c, bool fromSearch, const QString &searchString);
void showFromHistory(int index);
void updateBackForwardButtons();
void _k_activateSearchLine();
void _k_back();
void _k_forward();
void _k_fontSelected();
void _k_updateCurrentChar(const QChar &c);
void _k_slotUpdateUnicode(const QChar &c);
void _k_sectionSelected(int index);
void _k_blockSelected(int index);
void _k_searchEditChanged();
void _k_search();
void _k_linkClicked(QUrl url);
};
/******************************************************************/
/* Class: KCharSelectTable */
/******************************************************************/
KCharSelectTable::KCharSelectTable(QWidget *parent, const QFont &_font)
: QTableView(parent), d(new KCharSelectTablePrivate(this))
{
d->font = _font;
setTabKeyNavigation(false);
setSelectionMode(QAbstractItemView::SingleSelection);
QPalette _palette;
_palette.setColor(backgroundRole(), palette().color(QPalette::Base));
setPalette(_palette);
verticalHeader()->setVisible(false);
verticalHeader()->setResizeMode(QHeaderView::Custom);
horizontalHeader()->setVisible(false);
horizontalHeader()->setResizeMode(QHeaderView::Custom);
setFocusPolicy(Qt::StrongFocus);
setDragEnabled(true);
setAcceptDrops(true);
setDropIndicatorShown(false);
setDragDropMode(QAbstractItemView::DragDrop);
connect(this, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(_k_doubleClicked(QModelIndex)));
d->_k_resizeCells();
}
KCharSelectTable::~KCharSelectTable()
{
delete d;
}
void KCharSelectTable::setFont(const QFont &_font)
{
QTableView::setFont(_font);
d->font = _font;
if (d->model) d->model->setFont(_font);
d->_k_resizeCells();
}
QChar KCharSelectTable::chr()
{
return d->chr;
}
QFont KCharSelectTable::font() const
{
return d->font;
}
QList<QChar> KCharSelectTable::displayedChars() const
{
return d->chars;
}
void KCharSelectTable::setChar(const QChar &c)
{
int pos = d->chars.indexOf(c);
if (pos != -1) {
setCurrentIndex(model()->index(pos / model()->columnCount(), pos % model()->columnCount()));
}
}
void KCharSelectTable::setContents(QList<QChar> chars)
{
d->chars = chars;
KCharSelectItemModel *m = d->model;
d->model = new KCharSelectItemModel(chars, d->font, this);
setModel(d->model);
d->_k_resizeCells();
QItemSelectionModel *selectionModel = new QItemSelectionModel(d->model);
setSelectionModel(selectionModel);
setSelectionBehavior(QAbstractItemView::SelectItems);
setSelectionMode(QAbstractItemView::SingleSelection);
connect(selectionModel, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(_k_slotSelectionChanged(const QItemSelection &, const QItemSelection &)));
connect(d->model, SIGNAL(showCharRequested(QChar)), this, SIGNAL(showCharRequested(QChar)));
delete m; // this should hopefully delete aold selection models too, since it is the parent of them (didn't track, if there are setParent calls somewhere. Check that (jowenn)
}
void KCharSelectTable::scrollTo(const QModelIndex & index, ScrollHint hint)
{
// this prevents horizontal scrolling when selecting a character in the last column
if (index.isValid() && index.column() != 0) {
QTableView::scrollTo(d->model->index(index.row(), 0), hint);
} else {
QTableView::scrollTo(index, hint);
}
}
void KCharSelectTablePrivate::_k_slotSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected)
{
Q_UNUSED(deselected);
if (!model || selected.indexes().isEmpty())
return;
QVariant temp = model->data(selected.indexes().at(0), KCharSelectItemModel::CharacterRole);
if (temp.type() != QVariant::Char)
return;
QChar c = temp.toChar();
chr = c;
emit q->focusItemChanged(c);
}
void KCharSelectTable::resizeEvent(QResizeEvent * e)
{
QTableView::resizeEvent(e);
if (e->size().width() != e->oldSize().width()) {
d->_k_resizeCells();
}
}
void KCharSelectTablePrivate::_k_resizeCells()
{
if (!q->model()) return;
static_cast<KCharSelectItemModel*>(q->model())->updateColumnCount(q->viewport()->size().width());
QChar oldChar = q->chr();
const int new_w = q->viewport()->size().width() / q->model()->columnCount(QModelIndex());
const int columns = q->model()->columnCount(QModelIndex());
const int rows = q->model()->rowCount(QModelIndex());
q->setUpdatesEnabled(false);
QHeaderView* hv = q->horizontalHeader();
int spaceLeft = q->viewport()->size().width() % new_w + 1;
for (int i = 0;i <= columns;i++) {
if (i < spaceLeft) {
hv->resizeSection(i, new_w + 1);
} else {
hv->resizeSection(i, new_w);
}
}
hv = q->verticalHeader();
#ifdef Q_WS_WIN
int new_h = QFontMetrics(font).lineSpacing() + 1;
#else
int new_h = QFontMetrics(font).xHeight() * 3;
#endif
if (new_h < 5 || new_h < 4 + QFontMetrics(font).height()) {
new_h = qMax(5, 4 + QFontMetrics(font).height());
}
for (int i = 0;i < rows;i++) {
hv->resizeSection(i, new_h);
}
q->setUpdatesEnabled(true);
q->setChar(oldChar);
}
void KCharSelectTablePrivate::_k_doubleClicked(const QModelIndex & index)
{
QChar c = model->data(index, KCharSelectItemModel::CharacterRole).toChar();
if (s_data->isPrint(c)) {
emit q->activated(c);
}
}
void KCharSelectTable::keyPressEvent(QKeyEvent *e)
{
if (d->model)
switch (e->key()) {
case Qt::Key_Space:
emit activated(' ');
return;
break;
case Qt::Key_Enter: case Qt::Key_Return: {
if (!currentIndex().isValid()) return;
QChar c = d->model->data(currentIndex(), KCharSelectItemModel::CharacterRole).toChar();
if (s_data->isPrint(c)) {
emit activated(c);
}
}
return;
break;
}
QTableView::keyPressEvent(e);
}
/******************************************************************/
/* Class: KCharSelect */
/******************************************************************/
#ifndef KDE_NO_DEPRECATED
KCharSelect::KCharSelect(QWidget *parent, const Controls controls)
: QWidget(parent), d(new KCharSelectPrivate(this))
{
- init(controls, NULL);
+ initWidget(controls, NULL);
}
#endif
KCharSelect::KCharSelect(
QWidget *parent
,KActionCollection *collection
,const Controls controls)
: QWidget(parent), d(new KCharSelectPrivate(this))
{
- init(controls, collection);
+ initWidget(controls, collection);
}
-void KCharSelect::init(const Controls controls, KActionCollection *collection)
+void KCharSelect::initWidget(const Controls controls, KActionCollection *collection)
{
if (collection==NULL) {
d->actions = new KActionCollection(this);
d->actions->addAssociatedWidget(this);
} else {
d->actions = collection;
}
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->setMargin(0);
if (SearchLine & controls) {
QHBoxLayout *searchLayout = new QHBoxLayout();
mainLayout->addLayout(searchLayout);
d->searchLine = new KLineEdit(this);
searchLayout->addWidget(d->searchLine);
d->searchLine->setClickMessage(i18n("Enter a search term or character here"));
d->searchLine->setClearButtonShown(true);
d->searchLine->setToolTip(i18n("Enter a search term or character here"));
KStandardAction::find(this, SLOT(_k_activateSearchLine()), d->actions);
connect(d->searchLine, SIGNAL(textChanged(QString)), this, SLOT(_k_searchEditChanged()));
connect(d->searchLine, SIGNAL(returnPressed()), this, SLOT(_k_search()));
}
if ((SearchLine & controls) && ((FontCombo & controls) || (FontSize & controls) || (BlockCombos & controls))) {
QFrame* line = new QFrame(this);
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
mainLayout->addWidget(line);
}
QHBoxLayout *comboLayout = new QHBoxLayout();
d->backButton = new QToolButton(this);
comboLayout->addWidget(d->backButton);
d->backButton->setEnabled(false);
d->backButton->setText(i18nc("Goes to previous character", "Previous in History"));
d->backButton->setIcon(KIcon("go-previous"));
d->backButton->setToolTip(i18n("Previous Character in History"));
d->forwardButton = new QToolButton(this);
comboLayout->addWidget(d->forwardButton);
d->forwardButton->setEnabled(false);
d->forwardButton->setText(i18nc("Goes to next character", "Next in History"));
d->forwardButton->setIcon(KIcon("go-next"));
d->forwardButton->setToolTip(i18n("Next Character in History"));
KStandardAction::back(d->backButton, SLOT(animateClick()), d->actions);
KStandardAction::forward(d->forwardButton, SLOT(animateClick()), d->actions);
connect(d->backButton, SIGNAL(clicked()), this, SLOT(_k_back()));
connect(d->forwardButton, SIGNAL(clicked()), this, SLOT(_k_forward()));
d->sectionCombo = new KComboBox(this);
d->sectionCombo->setToolTip(i18n("Select a category"));
comboLayout->addWidget(d->sectionCombo);
d->blockCombo = new KComboBox(this);
d->blockCombo->setToolTip(i18n("Select a block to be displayed"));
d->blockCombo->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
comboLayout->addWidget(d->blockCombo, 1);
d->sectionCombo->addItems(s_data->sectionList());
d->blockCombo->setMinimumWidth(QFontMetrics(QWidget::font()).averageCharWidth() * 25);
connect(d->sectionCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(_k_sectionSelected(int)));
connect(d->blockCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(_k_blockSelected(int)));
d->fontCombo = new KFontComboBox(this);
comboLayout->addWidget(d->fontCombo);
d->fontCombo->setEditable(true);
d->fontCombo->resize(d->fontCombo->sizeHint());
d->fontCombo->setToolTip(i18n("Set font"));
d->fontSizeSpinBox = new QSpinBox(this);
comboLayout->addWidget(d->fontSizeSpinBox);
d->fontSizeSpinBox->setValue(QWidget::font().pointSize());
d->fontSizeSpinBox->setRange(1, 400);
d->fontSizeSpinBox->setSingleStep(1);
d->fontSizeSpinBox->setToolTip(i18n("Set font size"));
connect(d->fontCombo, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(_k_fontSelected()));
connect(d->fontSizeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(_k_fontSelected()));
if ((HistoryButtons & controls) || (FontCombo & controls) || (FontSize & controls) || (BlockCombos & controls)) {
mainLayout->addLayout(comboLayout);
}
if (!(HistoryButtons & controls)) {
d->backButton->hide();
d->forwardButton->hide();
}
if (!(FontCombo & controls)) {
d->fontCombo->hide();
}
if (!(FontSize & controls)) {
d->fontSizeSpinBox->hide();
}
if (!(BlockCombos & controls)) {
d->sectionCombo->hide();
d->blockCombo->hide();
}
QSplitter *splitter = new QSplitter(this);
if ((CharacterTable & controls) || (DetailBrowser & controls)) {
mainLayout->addWidget(splitter);
} else {
splitter->hide();
}
d->charTable = new KCharSelectTable(this, QFont());
if (CharacterTable & controls) {
splitter->addWidget(d->charTable);
d->charTable->setFocus(Qt::OtherFocusReason);
} else {
d->charTable->hide();
}
const QSize sz(200, 200);
d->charTable->resize(sz);
d->charTable->setMinimumSize(sz);
d->charTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setCurrentFont(QFont());
connect(d->charTable, SIGNAL(focusItemChanged(const QChar &)), this, SLOT(_k_updateCurrentChar(const QChar &)));
connect(d->charTable, SIGNAL(activated(const QChar &)), this, SIGNAL(charSelected(const QChar &)));
connect(d->charTable, SIGNAL(focusItemChanged(const QChar &)),
this, SIGNAL(currentCharChanged(const QChar &)));
connect(d->charTable, SIGNAL(showCharRequested(QChar)), this, SLOT(setCurrentChar(QChar)));
d->detailBrowser = new KTextBrowser(this);
if (DetailBrowser & controls) {
splitter->addWidget(d->detailBrowser);
} else {
d->detailBrowser->hide();
}
d->detailBrowser->setOpenLinks(false);
connect(d->detailBrowser, SIGNAL(anchorClicked(QUrl)), this, SLOT(_k_linkClicked(QUrl)));
setFocusPolicy(Qt::StrongFocus);
setFocusProxy(d->charTable);
d->_k_sectionSelected(0);
d->_k_blockSelected(0);
setCurrentChar(0x0);
d->historyEnabled = true;
}
KCharSelect::~KCharSelect()
{
delete d;
}
QSize KCharSelect::sizeHint() const
{
return QWidget::sizeHint();
}
void KCharSelect::setCurrentFont(const QFont &_font)
{
d->fontCombo->setCurrentFont(_font);
d->fontSizeSpinBox->setValue(_font.pointSize());
d->_k_fontSelected();
}
QChar KCharSelect::currentChar() const
{
return d->charTable->chr();
}
QFont KCharSelect::currentFont() const
{
return d->charTable->font();
}
QList<QChar> KCharSelect::displayedChars() const
{
return d->charTable->displayedChars();
}
void KCharSelect::setCurrentChar(const QChar &c)
{
bool oldHistoryEnabled = d->historyEnabled;
d->historyEnabled = false;
int block = s_data->blockIndex(c);
int section = s_data->sectionIndex(block);
d->sectionCombo->setCurrentIndex(section);
int index = d->blockCombo->findData(block);
if (index != -1) {
d->blockCombo->setCurrentIndex(index);
}
d->historyEnabled = oldHistoryEnabled;
d->charTable->setChar(c);
}
void KCharSelect::KCharSelectPrivate::historyAdd(const QChar &c, bool fromSearch, const QString &searchString)
{
//kDebug() << "about to add char" << c << "fromSearch" << fromSearch << "searchString" << searchString;
if (!historyEnabled) {
return;
}
if (!history.isEmpty() && c == history.last().c) {
//avoid duplicates
return;
}
//behave like a web browser, i.e. if user goes back from B to A then clicks C, B is forgotten
while (!history.isEmpty() && inHistory != history.count() - 1) {
history.removeLast();
}
while (history.size() >= MaxHistoryItems) {
history.removeFirst();
}
HistoryItem item;
item.c = c;
item.fromSearch = fromSearch;
item.searchString = searchString;
history.append(item);
inHistory = history.count() - 1;
updateBackForwardButtons();
}
void KCharSelect::KCharSelectPrivate::showFromHistory(int index)
{
Q_ASSERT(index >= 0 && index < history.count());
Q_ASSERT(index != inHistory);
inHistory = index;
updateBackForwardButtons();
const HistoryItem &item = history[index];
//kDebug() << "index" << index << "char" << item.c << "fromSearch" << item.fromSearch
// << "searchString" << item.searchString;
//avoid adding an item from history into history again
bool oldHistoryEnabled = historyEnabled;
historyEnabled = false;
if (item.fromSearch) {
if (searchLine->text() != item.searchString) {
searchLine->setText(item.searchString);
_k_search();
}
charTable->setChar(item.c);
} else {
searchLine->clear();
q->setCurrentChar(item.c);
}
historyEnabled = oldHistoryEnabled;
}
void KCharSelect::KCharSelectPrivate::updateBackForwardButtons()
{
backButton->setEnabled(inHistory > 0);
forwardButton->setEnabled(inHistory < history.count() - 1);
}
void KCharSelect::KCharSelectPrivate::_k_activateSearchLine()
{
searchLine->setFocus();
searchLine->selectAll();
}
void KCharSelect::KCharSelectPrivate::_k_back()
{
Q_ASSERT(inHistory > 0);
showFromHistory(inHistory - 1);
}
void KCharSelect::KCharSelectPrivate::_k_forward()
{
Q_ASSERT(inHistory + 1 < history.count());
showFromHistory(inHistory + 1);
}
void KCharSelect::KCharSelectPrivate::_k_fontSelected()
{
QFont font = fontCombo->currentFont();
font.setPointSize(fontSizeSpinBox->value());
charTable->setFont(font);
emit q->currentFontChanged(font);
}
void KCharSelect::KCharSelectPrivate::_k_updateCurrentChar(const QChar &c)
{
if (searchMode) {
//we are in search mode. make the two comboboxes show the section & block for this character.
//(when we are not in search mode the current character always belongs to the current section & block.)
int block = s_data->blockIndex(c);
int section = s_data->sectionIndex(block);
sectionCombo->setCurrentIndex(section);
int index = blockCombo->findData(block);
if (index != -1) {
blockCombo->setCurrentIndex(index);
}
}
if( searchLine)
historyAdd(c, searchMode, searchLine->text());
_k_slotUpdateUnicode(c);
}
void KCharSelect::KCharSelectPrivate::_k_slotUpdateUnicode(const QChar &c)
{
QString html = "<p>" + i18n("Character:") + ' ' + s_data->display(c, charTable->font()) + ' ' +
s_data->formatCode(c.unicode()) + "<br />";
QString name = s_data->name(c);
if (!name.isEmpty()) {
//is name ever empty? </p> should always be there...
html += i18n("Name: ") + Qt::escape(name) + "</p>";
}
QStringList aliases = s_data->aliases(c);
QStringList notes = s_data->notes(c);
QList<QChar> seeAlso = s_data->seeAlso(c);
QStringList equivalents = s_data->equivalents(c);
QStringList approxEquivalents = s_data->approximateEquivalents(c);
if (!(aliases.isEmpty() && notes.isEmpty() && seeAlso.isEmpty() && equivalents.isEmpty() && approxEquivalents.isEmpty())) {
html += "<p><b>" + i18n("Annotations and Cross References") + "</b></p>";
}
if (!aliases.isEmpty()) {
html += "<p style=\"margin-bottom: 0px;\">" + i18n("Alias names:") + "</p><ul style=\"margin-top: 0px;\">";
foreach(const QString &alias, aliases) {
html += "<li>" + Qt::escape(alias) + "</li>";
}
html += "</ul>";
}
if (!notes.isEmpty()) {
html += "<p style=\"margin-bottom: 0px;\">" + i18n("Notes:") + "</p><ul style=\"margin-top: 0px;\">";
foreach(const QString &note, notes) {
html += "<li>" + createLinks(Qt::escape(note)) + "</li>";
}
html += "</ul>";
}
if (!seeAlso.isEmpty()) {
html += "<p style=\"margin-bottom: 0px;\">" + i18n("See also:") + "</p><ul style=\"margin-top: 0px;\">";
foreach(const QChar &c2, seeAlso) {
html += "<li><a href=\"" + QString::number(c2.unicode(), 16) + "\">";
if (s_data->isPrint(c2)) {
html += "&#" + QString::number(c2.unicode()) + "; ";
}
html += s_data->formatCode(c2.unicode()) + ' ' + Qt::escape(s_data->name(c2)) + "</a></li>";
}
html += "</ul>";
}
if (!equivalents.isEmpty()) {
html += "<p style=\"margin-bottom: 0px;\">" + i18n("Equivalents:") + "</p><ul style=\"margin-top: 0px;\">";
foreach(const QString &equivalent, equivalents) {
html += "<li>" + createLinks(Qt::escape(equivalent)) + "</li>";
}
html += "</ul>";
}
if (!approxEquivalents.isEmpty()) {
html += "<p style=\"margin-bottom: 0px;\">" + i18n("Approximate equivalents:") + "</p><ul style=\"margin-top: 0px;\">";
foreach(const QString &approxEquivalent, approxEquivalents) {
html += "<li>" + createLinks(Qt::escape(approxEquivalent)) + "</li>";
}
html += "</ul>";
}
QStringList unihan = s_data->unihanInfo(c);
if (unihan.count() == 7) {
html += "<p><b>" + i18n("CJK Ideograph Information") + "</b></p><p>";
bool newline = true;
if (!unihan[0].isEmpty()) {
html += i18n("Definition in English: ") + unihan[0];
newline = false;
}
if (!unihan[2].isEmpty()) {
if (!newline) html += "<br>";
html += i18n("Mandarin Pronunciation: ") + unihan[2];
newline = false;
}
if (!unihan[1].isEmpty()) {
if (!newline) html += "<br>";
html += i18n("Cantonese Pronunciation: ") + unihan[1];
newline = false;
}
if (!unihan[6].isEmpty()) {
if (!newline) html += "<br>";
html += i18n("Japanese On Pronunciation: ") + unihan[6];
newline = false;
}
if (!unihan[5].isEmpty()) {
if (!newline) html += "<br>";
html += i18n("Japanese Kun Pronunciation: ") + unihan[5];
newline = false;
}
if (!unihan[3].isEmpty()) {
if (!newline) html += "<br>";
html += i18n("Tang Pronunciation: ") + unihan[3];
newline = false;
}
if (!unihan[4].isEmpty()) {
if (!newline) html += "<br>";
html += i18n("Korean Pronunciation: ") + unihan[4];
newline = false;
}
html += "</p>";
}
html += "<p><b>" + i18n("General Character Properties") + "</b><br>";
html += i18n("Block: ") + s_data->block(c) + "<br>";
html += i18n("Unicode category: ") + s_data->categoryText(s_data->category(c)) + "</p>";
QByteArray utf8 = QString(c).toUtf8();
html += "<p><b>" + i18n("Various Useful Representations") + "</b><br>";
html += i18n("UTF-8:");
foreach(unsigned char c, utf8)
html += ' ' + s_data->formatCode(c, 2, "0x");
html += "<br>" + i18n("UTF-16: ") + s_data->formatCode(c.unicode(), 4, "0x") + "<br>";
html += i18n("C octal escaped UTF-8: ");
foreach(unsigned char c, utf8)
html += s_data->formatCode(c, 3, "\\", 8);
html += "<br>" + i18n("XML decimal entity:") + " &amp;#" + QString::number(c.unicode()) + ";</p>";
detailBrowser->setHtml(html);
}
QString KCharSelect::KCharSelectPrivate::createLinks(QString s)
{
QRegExp rx("\\b([\\dABCDEF]{4})\\b");
QStringList chars;
int pos = 0;
while ((pos = rx.indexIn(s, pos)) != -1) {
chars << rx.cap(1);
pos += rx.matchedLength();
}
QSet<QString> chars2 = QSet<QString>::fromList(chars);
foreach(const QString &c, chars2) {
int unicode = c.toInt(0, 16);
QString link = "<a href=\"" + c + "\">";
if (s_data->isPrint(QChar(unicode))) {
link += "&#" + QString::number(unicode) + ";&nbsp;";
}
link += "U+" + c + ' ';
link += Qt::escape(s_data->name(QChar(unicode))) + "</a>";
s.replace(c, link);
}
return s;
}
void KCharSelect::KCharSelectPrivate::_k_sectionSelected(int index)
{
blockCombo->clear();
QList<int> blocks = s_data->sectionContents(index);
foreach(int block, blocks) {
blockCombo->addItem(s_data->blockName(block), QVariant(block));
}
blockCombo->setCurrentIndex(0);
}
void KCharSelect::KCharSelectPrivate::_k_blockSelected(int index)
{
if (index == -1) {
//the combo box has been cleared and is about to be filled again (because the section has changed)
return;
}
if (searchMode) {
//we are in search mode, so don't fill the table with this block.
return;
}
int block = blockCombo->itemData(index).toInt();
const QList<QChar> contents = s_data->blockContents(block);
if(contents.count() <= index) {
return;
}
charTable->setContents(contents);
emit q->displayedCharsChanged();
charTable->setChar(contents[0]);
}
void KCharSelect::KCharSelectPrivate::_k_searchEditChanged()
{
if (searchLine->text().isEmpty()) {
sectionCombo->setEnabled(true);
blockCombo->setEnabled(true);
//upon leaving search mode, keep the same character selected
searchMode = false;
QChar c = charTable->chr();
bool oldHistoryEnabled = historyEnabled;
historyEnabled = false;
_k_blockSelected(blockCombo->currentIndex());
historyEnabled = oldHistoryEnabled;
q->setCurrentChar(c);
} else {
sectionCombo->setEnabled(false);
blockCombo->setEnabled(false);
int length = searchLine->text().length();
if (length >= 3) {
_k_search();
}
}
}
void KCharSelect::KCharSelectPrivate::_k_search()
{
if (searchLine->text().isEmpty()) {
return;
}
searchMode = true;
const QList<QChar> contents = s_data->find(searchLine->text());
charTable->setContents(contents);
emit q->displayedCharsChanged();
if (!contents.isEmpty()) {
charTable->setChar(contents[0]);
}
}
void KCharSelect::KCharSelectPrivate::_k_linkClicked(QUrl url)
{
QString hex = url.toString();
if (hex.size() > 4) {
return;
}
int unicode = hex.toInt(0, 16);
searchLine->clear();
q->setCurrentChar(QChar(unicode));
}
////
QVariant KCharSelectItemModel::data(const QModelIndex &index, int role) const
{
int pos = m_columns * (index.row()) + index.column();
if (!index.isValid() || pos < 0 || pos >= m_chars.size()
|| index.row() < 0 || index.column() < 0) {
if (role == Qt::BackgroundColorRole) {
return QVariant(qApp->palette().color(QPalette::Button));
}
return QVariant();
}
QChar c = m_chars[pos];
if (role == Qt::ToolTipRole) {
QString result = s_data->display(c, m_font) + "<br />" + Qt::escape(s_data->name(c)) + "<br />" +
i18n("Unicode code point:") + ' ' + s_data->formatCode(c.unicode()) + "<br />" +
i18nc("Character", "In decimal:") + ' ' + QString::number(c.unicode());
return QVariant(result);
} else if (role == Qt::TextAlignmentRole)
return QVariant(Qt::AlignHCenter | Qt::AlignVCenter);
else if (role == Qt::DisplayRole) {
if (s_data->isPrint(c))
return QVariant(c);
return QVariant();
} else if (role == Qt::BackgroundColorRole) {
QFontMetrics fm = QFontMetrics(m_font);
if (fm.inFont(c) && s_data->isPrint(c))
return QVariant(qApp->palette().color(QPalette::Base));
else
return QVariant(qApp->palette().color(QPalette::Button));
} else if (role == Qt::FontRole)
return QVariant(m_font);
else if (role == CharacterRole) {
return QVariant(c);
}
return QVariant();
}
#include "moc_kcharselect.cpp"
#include "moc_kcharselect_p.cpp"
diff --git a/kdeui/widgets/kcharselect.h b/kdeui/widgets/kcharselect.h
index 4c69969c84..490632df53 100644
--- a/kdeui/widgets/kcharselect.h
+++ b/kdeui/widgets/kcharselect.h
@@ -1,221 +1,221 @@
/* This file is part of the KDE libraries
Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef kcharselect_h
#define kcharselect_h
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QWidget>
#include <kglobal.h>
#include <kdeui_export.h>
class KActionCollection;
class QFont;
class QUrl;
/**
* @short Character selection widget
*
* This widget allows the user to select a character of a
* specified font and to browse Unicode information
*
* \image html kcharselect.png "Character Selection Widget"
*
* You can specify the font whose characters should be displayed via
* setCurrentFont(). Using the Controls argument in the contructor
* you can create a compact version of KCharSelect if there is not enough
* space and if you don't need all features.
*
* KCharSelect displays one Unicode block at a time and provides
* categorized access to them. Unicode character names and further details,
* including cross references, are displayed. Additionally, there is a search
* to find characters.
*
* To get the current selected character, use the currentChar()
* method. You can set the character which should be displayed with
* setCurrentChar().
*
* @author Reginald Stadlbauer <reggie@kde.org>
* @author Daniel Laidig <d.laidig@gmx.de>
*/
class KDEUI_EXPORT KCharSelect : public QWidget
{
Q_OBJECT
Q_PROPERTY(QFont currentFont READ currentFont WRITE setCurrentFont)
Q_PROPERTY(QChar currentChar READ currentChar WRITE setCurrentChar)
Q_PROPERTY(QList<QChar> displayedChars READ displayedChars)
public:
/**
* Flags to set the shown widgets
*/
enum Control {
/**
* Shows the search widgets
*/
SearchLine = 0x01,
/**
* Shows the font combo box
*/
FontCombo = 0x02,
/**
* Shows the font size spin box
*/
FontSize = 0x04,
/**
* Shows the category/block selection combo boxes
*/
BlockCombos = 0x08,
/**
* Shows the actual table
*/
CharacterTable = 0x10,
/**
* Shows the detail browser
*/
DetailBrowser = 0x20,
/**
* Shows the Back/Forward buttons
*/
HistoryButtons = 0x40,
/**
* Shows everything
*/
AllGuiElements = 65535
};
Q_DECLARE_FLAGS(Controls,
Control)
/** @deprecated */
#ifndef KDE_NO_DEPRECATED
KDE_CONSTRUCTOR_DEPRECATED explicit KCharSelect(
QWidget *parent,
const Controls controls = AllGuiElements);
#endif
/**
* Constructor. @p controls can be used to show a custom set of widgets.
*
* The widget uses the following actions:
* - KStandardActions::find() (edit_find)
* - KStandardActions::back() (go_back)
* - KStandardActions::forward() (go_forward)
*
* If you provide a KActionCollection, this will be populated with the above actions,
* which you can then manually trigger or place in menus and toolbars.
*
* @param parent the parent widget for this KCharSelect (see QWidget documentation)
* @param collection if this is not @c null, KCharSelect will place its actions into this
* collection
* @param controls selects the visible controls on the KCharSelect widget
*
* @since 4.2
*/
explicit KCharSelect(
QWidget *parent,
KActionCollection *collection,
const Controls controls = AllGuiElements);
~KCharSelect();
/**
* Reimplemented.
*/
virtual QSize sizeHint() const;
/**
* Returns the currently selected character.
*/
QChar currentChar() const;
/**
* Returns the currently displayed font.
*/
QFont currentFont() const;
/**
* Returns a list of currently displayed characters.
*/
QList<QChar> displayedChars() const;
public Q_SLOTS:
/**
* Highlights the character @p c. If the character is not displayed, the block is changed.
*
* @param c the character to highlight
*/
void setCurrentChar(const QChar &c);
/**
* Sets the font which is displayed to @p font
*
* @param font the display font for the widget
*/
void setCurrentFont(const QFont &font);
Q_SIGNALS:
/**
* A new font is selected or the font size changed.
*
* @param font the new font
*/
void currentFontChanged(const QFont &font);
/**
* The current character is changed.
*
* @param c the new character
*/
void currentCharChanged(const QChar &c);
/**
* The currently displayed characters are changed (search results or block).
*/
void displayedCharsChanged();
/**
* A character is selected to be inserted somewhere.
*
* @param c the selected character
*/
void charSelected(const QChar &c);
private:
Q_PRIVATE_SLOT(d, void _k_activateSearchLine())
Q_PRIVATE_SLOT(d, void _k_back())
Q_PRIVATE_SLOT(d, void _k_forward())
Q_PRIVATE_SLOT(d, void _k_fontSelected())
Q_PRIVATE_SLOT(d, void _k_updateCurrentChar(const QChar &c))
Q_PRIVATE_SLOT(d, void _k_slotUpdateUnicode(const QChar &c))
Q_PRIVATE_SLOT(d, void _k_sectionSelected(int index))
Q_PRIVATE_SLOT(d, void _k_blockSelected(int index))
Q_PRIVATE_SLOT(d, void _k_searchEditChanged())
Q_PRIVATE_SLOT(d, void _k_search())
Q_PRIVATE_SLOT(d, void _k_linkClicked(QUrl))
class KCharSelectPrivate;
KCharSelectPrivate* const d;
- void init(const Controls, KActionCollection *);
+ void initWidget(const Controls, KActionCollection *);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(KCharSelect::Controls)
#endif
diff --git a/kdeui/widgets/kcombobox.cpp b/kdeui/widgets/kcombobox.cpp
index 9217145341..945a078542 100644
--- a/kdeui/widgets/kcombobox.cpp
+++ b/kdeui/widgets/kcombobox.cpp
@@ -1,399 +1,399 @@
/* This file is part of the KDE libraries
Copyright (c) 2000,2001 Dawit Alemayehu <adawit@kde.org>
Copyright (c) 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
Copyright (c) 2000 Stefan Schimanski <1Stein@gmx.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License (LGPL) as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kcombobox.h"
#include <QClipboard>
#include <QLineEdit>
#include <QMenu>
#include <QApplication>
#include <QActionEvent>
#include <kselectaction.h>
#include <kcompletionbox.h>
#include <kcursor.h>
#include <kiconloader.h>
#include <kicontheme.h>
#include <klineedit.h>
#include <klocale.h>
#include <kurl.h>
#include <kicon.h>
#include <kdebug.h>
class KComboBox::KComboBoxPrivate
{
public:
KComboBoxPrivate() : klineEdit(0L), trapReturnKey(false)
{
}
~KComboBoxPrivate()
{
}
KLineEdit *klineEdit;
bool trapReturnKey;
};
KComboBox::KComboBox( QWidget *parent )
: QComboBox( parent ), d(new KComboBoxPrivate)
{
- init();
+ initWidget();
}
KComboBox::KComboBox( bool rw, QWidget *parent )
: QComboBox( parent ), d(new KComboBoxPrivate)
{
- init();
+ initWidget();
setEditable( rw );
}
KComboBox::~KComboBox()
{
delete d;
}
-void KComboBox::init()
+void KComboBox::initWidget()
{
// Permanently set some parameters in the parent object.
QComboBox::setAutoCompletion( false );
// Enable context menu by default if widget
// is editable.
if (lineEdit()) {
lineEdit()->setContextMenuPolicy( Qt::DefaultContextMenu );
}
}
bool KComboBox::contains( const QString& _text ) const
{
if ( _text.isEmpty() )
return false;
const int itemCount = count();
for (int i = 0; i < itemCount; ++i )
{
if ( itemText(i) == _text )
return true;
}
return false;
}
int KComboBox::cursorPosition() const
{
return ( lineEdit() ) ? lineEdit()->cursorPosition() : -1;
}
void KComboBox::setAutoCompletion( bool autocomplete )
{
if ( d->klineEdit )
{
if ( autocomplete )
{
d->klineEdit->setCompletionMode( KGlobalSettings::CompletionAuto );
setCompletionMode( KGlobalSettings::CompletionAuto );
}
else
{
d->klineEdit->setCompletionMode( KGlobalSettings::completionMode() );
setCompletionMode( KGlobalSettings::completionMode() );
}
}
}
bool KComboBox::autoCompletion() const
{
return completionMode() == KGlobalSettings::CompletionAuto;
}
#ifndef KDE_NO_DEPRECATED
void KComboBox::setContextMenuEnabled( bool showMenu )
{
if( d->klineEdit )
d->klineEdit->setContextMenuEnabled( showMenu );
}
#endif
void KComboBox::setUrlDropsEnabled( bool enable )
{
if ( d->klineEdit )
d->klineEdit->setUrlDropsEnabled( enable );
}
bool KComboBox::urlDropsEnabled() const
{
return d->klineEdit && d->klineEdit->urlDropsEnabled();
}
void KComboBox::setCompletedText( const QString& text, bool marked )
{
if ( d->klineEdit )
d->klineEdit->setCompletedText( text, marked );
}
void KComboBox::setCompletedText( const QString& text )
{
if ( d->klineEdit )
d->klineEdit->setCompletedText( text );
}
void KComboBox::makeCompletion( const QString& text )
{
if( d->klineEdit )
d->klineEdit->makeCompletion( text );
else // read-only combo completion
{
if( text.isNull() || !view() )
return;
view()->keyboardSearch(text);
}
}
void KComboBox::rotateText( KCompletionBase::KeyBindingType type )
{
if ( d->klineEdit )
d->klineEdit->rotateText( type );
}
// Not needed anymore
bool KComboBox::eventFilter( QObject* o, QEvent* ev )
{
return QComboBox::eventFilter( o, ev );
}
void KComboBox::setTrapReturnKey( bool grab )
{
d->trapReturnKey = grab;
if ( d->klineEdit )
d->klineEdit->setTrapReturnKey( grab );
else
qWarning("KComboBox::setTrapReturnKey not supported with a non-KLineEdit.");
}
bool KComboBox::trapReturnKey() const
{
return d->trapReturnKey;
}
void KComboBox::setEditUrl( const KUrl& url )
{
QComboBox::setEditText( url.prettyUrl() );
}
void KComboBox::addUrl( const KUrl& url )
{
QComboBox::addItem( url.prettyUrl() );
}
void KComboBox::addUrl( const QIcon& icon, const KUrl& url )
{
QComboBox::addItem( icon, url.prettyUrl() );
}
void KComboBox::insertUrl( int index, const KUrl& url )
{
QComboBox::insertItem( index, url.prettyUrl() );
}
void KComboBox::insertUrl( int index, const QIcon& icon, const KUrl& url )
{
QComboBox::insertItem( index, icon, url.prettyUrl() );
}
void KComboBox::changeUrl( int index, const KUrl& url )
{
QComboBox::setItemText( index, url.prettyUrl() );
}
void KComboBox::changeUrl( int index, const QIcon& icon, const KUrl& url )
{
QComboBox::setItemIcon( index, icon );
QComboBox::setItemText( index, url.prettyUrl() );
}
void KComboBox::setCompletedItems( const QStringList& items, bool autosubject )
{
if ( d->klineEdit )
d->klineEdit->setCompletedItems( items, autosubject );
}
KCompletionBox * KComboBox::completionBox( bool create )
{
if ( d->klineEdit )
return d->klineEdit->completionBox( create );
return 0;
}
// QWidget::create() turns off mouse-Tracking which would break auto-hiding
void KComboBox::create( WId id, bool initializeWindow, bool destroyOldWindow )
{
QComboBox::create( id, initializeWindow, destroyOldWindow );
KCursor::setAutoHideCursor( lineEdit(), true, true );
}
void KComboBox::wheelEvent( QWheelEvent *ev )
{
// Not necessary anymore
QComboBox::wheelEvent( ev );
}
QSize KComboBox::minimumSizeHint() const
{
QSize size = QComboBox::minimumSizeHint();
if (isEditable() && d->klineEdit) {
// if it's a KLineEdit and it's editable add the clear button size
// to the minimum size hint, otherwise looks ugly because the
// clear button will cover the last 2/3 letters of the biggest entry
QSize bs = d->klineEdit->clearButtonUsedSize();
if (bs.isValid()) {
size.rwidth() += bs.width();
size.rheight() = qMax(size.height(), bs.height());
}
}
return size;
}
void KComboBox::setLineEdit( QLineEdit *edit )
{
if ( !isEditable() && edit &&
!qstrcmp( edit->metaObject()->className(), "QLineEdit" ) )
{
// uic generates code that creates a read-only KComboBox and then
// calls combo->setEditable( true ), which causes QComboBox to set up
// a dumb QLineEdit instead of our nice KLineEdit.
// As some KComboBox features rely on the KLineEdit, we reject
// this order here.
delete edit;
KLineEdit* kedit = new KLineEdit( this );
if ( isEditable() ) {
kedit->setClearButtonShown( true );
}
edit = kedit;
}
QComboBox::setLineEdit( edit );
d->klineEdit = qobject_cast<KLineEdit*>( edit );
setDelegate( d->klineEdit );
// Connect the returnPressed signal for both Q[K]LineEdits'
if (edit)
connect( edit, SIGNAL( returnPressed() ), SIGNAL( returnPressed() ));
if ( d->klineEdit )
{
// someone calling KComboBox::setEditable( false ) destroys our
// lineedit without us noticing. And KCompletionBase::delegate would
// be a dangling pointer then, so prevent that. Note: only do this
// when it is a KLineEdit!
connect( edit, SIGNAL( destroyed() ), SLOT( lineEditDeleted() ));
connect( d->klineEdit, SIGNAL( returnPressed( const QString& )),
SIGNAL( returnPressed( const QString& ) ));
connect( d->klineEdit, SIGNAL( completion( const QString& )),
SIGNAL( completion( const QString& )) );
connect( d->klineEdit, SIGNAL( substringCompletion( const QString& )),
SIGNAL( substringCompletion( const QString& )) );
connect( d->klineEdit,
SIGNAL( textRotation( KCompletionBase::KeyBindingType )),
SIGNAL( textRotation( KCompletionBase::KeyBindingType )) );
connect( d->klineEdit,
SIGNAL( completionModeChanged( KGlobalSettings::Completion )),
SIGNAL( completionModeChanged( KGlobalSettings::Completion)));
connect( d->klineEdit,
SIGNAL( aboutToShowContextMenu( QMenu * )),
SIGNAL( aboutToShowContextMenu( QMenu * )) );
connect( d->klineEdit,
SIGNAL( completionBoxActivated( const QString& )),
SIGNAL( activated( const QString& )) );
d->klineEdit->setTrapReturnKey( d->trapReturnKey );
}
}
void KComboBox::setCurrentItem( const QString& item, bool insert, int index )
{
int sel = -1;
const int itemCount = count();
for (int i = 0; i < itemCount; ++i)
{
if (itemText(i) == item)
{
sel = i;
break;
}
}
if (sel == -1 && insert)
{
if (index >= 0) {
insertItem(index, item);
sel = index;
} else {
addItem(item);
sel = count() - 1;
}
}
setCurrentIndex(sel);
}
void KComboBox::lineEditDeleted()
{
// yes, we need those ugly casts due to the multiple inheritance
// sender() is guaranteed to be a KLineEdit (see the connect() to the
// destroyed() signal
const KCompletionBase *base = static_cast<const KCompletionBase*>( static_cast<const KLineEdit*>( sender() ));
// is it our delegate, that is destroyed?
if ( base == delegate() )
setDelegate( 0L );
}
void KComboBox::setEditable(bool editable)
{
if (editable) {
// Create a KLineEdit instead of a QLineEdit
// Compared to QComboBox::setEditable, we might be missing the SH_ComboBox_Popup code though...
// If a style needs this, then we'll need to call QComboBox::setEditable and then setLineEdit again
KLineEdit *edit = new KLineEdit( this );
edit->setClearButtonShown( true );
setLineEdit( edit );
} else {
QComboBox::setEditable(editable);
}
}
diff --git a/kdeui/widgets/kcombobox.h b/kdeui/widgets/kcombobox.h
index 2b5f89f8a9..f0ec099851 100644
--- a/kdeui/widgets/kcombobox.h
+++ b/kdeui/widgets/kcombobox.h
@@ -1,539 +1,539 @@
/* This file is part of the KDE libraries
Copyright (c) 2000,2001 Dawit Alemayehu <adawit@kde.org>
Copyright (c) 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License (LGPL) as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KCOMBOBOX_H
#define KCOMBOBOX_H
#include <QComboBox>
#include <kcompletion.h>
#include <kicon.h>
class QLineEdit;
class QMenu;
class KCompletionBox;
class KUrl;
/*
* ### KDE 5: On all methods that it is said that a prettyUrl will be used, it
* would be nice to add a flag to the method for forcing the pretty
* url or not. (ereslibre)
*/
/**
* @short An enhanced combo box.
*
* A combined button, line-edit and a popup list widget.
*
* \b Detail \n
*
* This widget inherits from QComboBox and implements the following
* additional functionalities: a completion object that provides both automatic
* and manual text completion as well as text rotation features, configurable
* key-bindings to activate these features, and a popup-menu item that can be
* used to allow the user to change the text completion mode on the fly.
*
* To support these new features KComboBox emits a few additional signals
* such as completion( const QString& ) and textRotation( KeyBindingType ).
* The completion signal can be connected to a slot that will assist the user in
* filling out the remaining text while the rotation signal can be used to traverse
* through all possible matches whenever text completion results in multiple matches.
* Additionally, a returnPressed() and a returnPressed( const QString& )
* signals are emitted when the user presses the Enter/Return key.
*
* KCombobox by default creates a completion object when you invoke the
* completionObject( bool ) member function for the first time or
* explicitly use setCompletionObject( KCompletion*, bool ) to assign your
* own completion object. Additionally, to make this widget more functional,
* KComboBox will by default handle text rotation and completion events
* internally whenever a completion object is created through either one of the
* methods mentioned above. If you do not need this functionality, simply use
* KCompletionBase::setHandleSignals(bool) or alternatively set the boolean
* parameter in the @p setCompletionObject call to false.
*
* Beware: The completion object can be deleted on you, especially if a call
* such as setEditable(false) is made. Store the pointer at your own risk,
* and consider using QGuardedPtr<KCompletion>.
*
* The default key-bindings for completion and rotation is determined from the
* global settings in KStandardShortcut. These values, however, can be overridden
* locally by invoking KCompletionBase::setKeyBinding(). The values can
* easily be reverted back to the default setting, by simply calling
* useGlobalSettings(). An alternate method would be to default individual
* key-bindings by usning setKeyBinding() with the default second argument.
*
* A non-editable combobox only has one completion mode, @p CompletionAuto.
* Unlike an editable combobox the CompletionAuto mode, works by matching
* any typed key with the first letter of entries in the combobox. Please note
* that if you call setEditable( false ) to change an editable combobox to a
* non-editable one, the text completion object associated with the combobox will
* no longer exist unless you created the completion object yourself and assigned
* it to this widget or you called setAutoDeleteCompletionObject( false ). In other
* words do not do the following:
*
* \code
* KComboBox* combo = new KComboBox(true, this);
* KCompletion* comp = combo->completionObject();
* combo->setEditable( false );
* comp->clear(); // CRASH: completion object does not exist anymore.
* \endcode
*
*
* A read-only KComboBox will have the same background color as a
* disabled KComboBox, but its foreground color will be the one used for
* the read-write mode. This differs from QComboBox's implementation
* and is done to give visual distinction between the three different modes:
* disabled, read-only, and read-write.
*
* \b Usage \n
*
* To enable the basic completion feature:
*
* \code
* KComboBox *combo = new KComboBox( true, this );
* KCompletion *comp = combo->completionObject();
* // Connect to the return pressed signal - optional
* connect(combo,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&)));
*
* // Provide the to be completed strings. Note that those are separate from the combo's
* // contents.
* comp->insertItems( someQStringList );
* \endcode
*
* To use your own completion object:
*
* \code
* KComboBox *combo = new KComboBox( this );
* KUrlCompletion *comp = new KUrlCompletion();
* combo->setCompletionObject( comp );
* // Connect to the return pressed signal - optional
* connect(combo,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&)));
* \endcode
*
* Note that you have to either delete the allocated completion object
* when you don't need it anymore, or call
* setAutoDeleteCompletionObject( true );
*
* Miscellaneous function calls:
*
* \code
* // Tell the widget not to handle completion and rotation
* combo->setHandleSignals( false );
* // Set your own completion key for manual completions.
* combo->setKeyBinding( KCompletionBase::TextCompletion, Qt::End );
* \endcode
*
* \image html kcombobox.png "KDE Combo Boxes, one non-editable, one editable with KUrlCompletion"
*
* @author Dawit Alemayehu <adawit@kde.org>
*/
class KDEUI_EXPORT KComboBox : public QComboBox, public KCompletionBase //krazy:exclude=qclasses
{
Q_OBJECT
Q_PROPERTY( bool autoCompletion READ autoCompletion WRITE setAutoCompletion )
Q_PROPERTY( bool urlDropsEnabled READ urlDropsEnabled WRITE setUrlDropsEnabled )
Q_PROPERTY( bool trapReturnKey READ trapReturnKey WRITE setTrapReturnKey )
public:
/**
* Constructs a read-only or rather select-only combo box with a
* parent object and a name.
*
* @param parent The parent object of this widget
*/
explicit KComboBox( QWidget *parent=0 );
/**
* Constructs a "read-write" or "read-only" combo box depending on
* the value of the first argument( @p rw ) with a parent, a
* name.
*
* @param rw When @p true, widget will be editable.
* @param parent The parent object of this widget.
*/
explicit KComboBox( bool rw, QWidget *parent=0 );
/**
* Destructor.
*/
virtual ~KComboBox();
/**
* Deprecated to reflect Qt api changes
* @deprecated
*/
#ifndef KDE_NO_DEPRECATED
KDEUI_DEPRECATED void insertURL( const KUrl& url, int index = -1 )
{ insertUrl( index < 0 ? count() : index, url ); }
KDEUI_DEPRECATED void insertURL( const QPixmap& pixmap, const KUrl& url, int index = -1 )
{ insertUrl( index < 0 ? count() : index, QIcon(pixmap), url ); }
KDEUI_DEPRECATED void changeURL( const KUrl& url, int index )
{ changeUrl( index, url ); }
KDEUI_DEPRECATED void changeURL( const QPixmap& pixmap, const KUrl& url, int index )
{ changeUrl( index, QIcon(pixmap), url ); }
#endif
/**
* Sets @p url into the edit field of the combobox. It uses
* KUrl::prettyUrl() so that the url is properly decoded for
* displaying.
*/
void setEditUrl( const KUrl& url );
/**
* Appends @p url to the combobox.
* KUrl::prettyUrl() is used so that the url is properly decoded
* for displaying.
*/
void addUrl( const KUrl& url );
/**
* Appends @p url with the icon &p icon to the combobox.
* KUrl::prettyUrl() is used so that the url is properly decoded
* for displaying.
*/
void addUrl( const QIcon& icon, const KUrl& url );
/**
* Inserts @p url at position @p index into the combobox.
* KUrl::prettyUrl() is used so that the url is properly decoded
* for displaying.
*/
void insertUrl( int index, const KUrl& url );
/**
* Inserts @p url with the pixmap &p pixmap at position @p index into
* the combobox. KUrl::prettyUrl() is used so that the url is
* properly decoded for displaying.
*/
void insertUrl( int index, const QIcon& icon, const KUrl& url );
/**
* Replaces the item at position @p index with @p url.
* KUrl::prettyUrl() is used so that the url is properly decoded
* for displaying.
*/
void changeUrl( int index, const KUrl& url );
/**
* Replaces the item at position @p index with @p url and icon @p icon.
* KUrl::prettyUrl() is used so that the url is properly decoded
* for displaying.
*/
void changeUrl( int index , const QIcon& icon, const KUrl& url);
/**
* Returns the current cursor position.
*
* This method always returns a -1 if the combo-box is @em not
* editable (read-write).
*
* @return Current cursor position.
*/
int cursorPosition() const;
/**
* Re-implemented from QComboBox.
*
* If @p true, the completion mode will be set to automatic.
* Otherwise, it is defaulted to the global setting. This
* method has been replaced by the more comprehensive
* setCompletionMode().
*
* @param autocomplete Flag to enable/disable automatic completion mode.
*/
virtual void setAutoCompletion( bool autocomplete );
/**
* Re-implemented from QComboBox.
*
* Returns @p true if the current completion mode is set
* to automatic. See its more comprehensive replacement
* completionMode().
*
* @return @p true when completion mode is automatic.
*/
bool autoCompletion() const;
/**
* Enables or disable the popup (context) menu.
*
* This method only works if this widget is editable, i.e. read-write and
* allows you to enable/disable the context menu. It does nothing if invoked
* for a none-editable combo-box.
*
* By default, the context menu is created if this widget is editable.
* Call this function with the argument set to false to disable the popup
* menu.
*
* @param showMenu If @p true, show the context menu.
* @deprecated use setContextMenuPolicy
*/
#ifndef KDE_NO_DEPRECATED
virtual KDEUI_DEPRECATED void setContextMenuEnabled( bool showMenu );
#endif
/**
* Enables/Disables handling of URL drops. If enabled and the user
* drops an URL, the decoded URL will be inserted. Otherwise the default
* behavior of QComboBox is used, which inserts the encoded URL.
*
* @param enable If @p true, insert decoded URLs
*/
void setUrlDropsEnabled( bool enable );
/**
* Returns @p true when decoded URL drops are enabled
*/
bool urlDropsEnabled() const;
/**
* Convenience method which iterates over all items and checks if
* any of them is equal to @p text.
*
* If @p text is an empty string, @p false
* is returned.
*
* @return @p true if an item with the string @p text is in the combobox.
*/
bool contains( const QString& text ) const;
/**
* By default, KComboBox recognizes Key_Return and Key_Enter
* and emits the returnPressed() signals, but it also lets the
* event pass, for example causing a dialog's default-button to
* be called.
*
* Call this method with @p trap equal to true to make KComboBox
* stop these events. The signals will still be emitted of course.
*
* Only affects read-writable comboboxes.
*
* @see setTrapReturnKey()
*/
void setTrapReturnKey( bool trap );
/**
* @return @p true if keyevents of Key_Return or Key_Enter will
* be stopped or if they will be propagated.
*
* @see setTrapReturnKey ()
*/
bool trapReturnKey() const;
/**
* Re-implemented for internal reasons. API not affected.
*/
virtual bool eventFilter( QObject *, QEvent * );
/**
* @returns the completion-box, that is used in completion mode
* KGlobalSettings::CompletionPopup and KGlobalSettings::CompletionPopupAuto.
* This method will create a completion-box by calling
* KLineEdit::completionBox, if none is there, yet.
*
* @param create Set this to false if you don't want the box to be created
* i.e. to test if it is available.
*/
KCompletionBox * completionBox( bool create = true );
/**
* Re-implemented for internal reasons. API remains unaffected.
* Note that QComboBox::setLineEdit is not virtual in Qt4, do not
* use a KComboBox in a QComboBox pointer.
*
* NOTE: Only editable comboboxes can have a line editor. As such
* any attempt to assign a line-edit to a non-editable combobox will
* simply be ignored.
*/
virtual void setLineEdit( QLineEdit * );
/**
* "Re-implemented" so that setEditable(true) creates a KLineEdit
* instead of QLineEdit.
*
* Note that QComboBox::setEditable is not virtual, so do not
* use a KComboBox in a QComboBox pointer.
*/
void setEditable(bool editable);
Q_SIGNALS:
/**
* Emitted when the user presses the Enter key.
*
* Note that this signal is only emitted when the widget is editable.
*/
void returnPressed();
/**
* Emitted when the user presses the Enter key.
*
* The argument is the current text being edited. This signal is just like
* returnPressed() except it contains the current text as its argument.
*
* Note that this signal is only emitted when the
* widget is editable.
*/
void returnPressed( const QString& );
/**
* Emitted when the completion key is pressed.
*
* The argument is the current text being edited.
*
* Note that this signal is @em not available when the widget is non-editable
* or the completion mode is set to @p KGlobalSettings::CompletionNone.
*/
void completion( const QString& );
/**
* Emitted when the shortcut for substring completion is pressed.
*/
void substringCompletion( const QString& );
/**
* Emitted when the text rotation key-bindings are pressed.
*
* The argument indicates which key-binding was pressed. In this case this
* can be either one of four values: @p PrevCompletionMatch,
* @p NextCompletionMatch, @p RotateUp or @p RotateDown. See
* KCompletionBase::setKeyBinding() for details.
*
* Note that this signal is @em NOT emitted if the completion
* mode is set to CompletionNone.
*/
void textRotation( KCompletionBase::KeyBindingType );
/**
* Emitted whenever the completion mode is changed by the user
* through the context menu.
*/
void completionModeChanged( KGlobalSettings::Completion );
/**
* Emitted before the context menu is displayed.
*
* The signal allows you to add your own entries into the context menu.
* Note that you MUST NOT store the pointer to the QPopupMenu since it is
* created and deleted on demand. Otherwise, you can crash your app.
*
* @param p the context menu about to be displayed
*/
void aboutToShowContextMenu( QMenu * p );
public Q_SLOTS:
/**
* Iterates through all possible matches of the completed text
* or the history list.
*
* Depending on the value of the argument, this function either
* iterates through the history list of this widget or the all
* possible matches in whenever multiple matches result from a
* text completion request. Note that the all-possible-match
* iteration will not work if there are no previous matches, i.e.
* no text has been completed and the *nix shell history list
* rotation is only available if the insertion policy for this
* widget is set either @p QComobBox::AtTop or @p QComboBox::AtBottom.
* For other insertion modes whatever has been typed by the user
* when the rotation event was initiated will be lost.
*
* @param type The key-binding invoked.
*/
void rotateText( KCompletionBase::KeyBindingType type );
/**
* Sets the completed text in the line-edit appropriately.
*
* This function is an implementation for
* KCompletionBase::setCompletedText.
*/
virtual void setCompletedText( const QString& );
/**
* Sets @p items into the completion-box if completionMode() is
* CompletionPopup. The popup will be shown immediately.
*/
void setCompletedItems( const QStringList& items, bool autosubject = true );
/**
* Selects the first item that matches @p item. If there is no such item,
* it is inserted at position @p index if @p insert is true. Otherwise,
* no item is selected.
*/
void setCurrentItem( const QString& item, bool insert = false, int index = -1 );
protected Q_SLOTS:
/**
* Completes text according to the completion mode.
*
* Note: this method is @p not invoked if the completion mode is
* set to CompletionNone. Also if the mode is set to @p CompletionShell
* and multiple matches are found, this method will complete the
* text to the first match with a beep to inidicate that there are
* more matches. Then any successive completion key event iterates
* through the remaining matches. This way the rotation functionality
* is left to iterate through the list as usual.
*/
virtual void makeCompletion( const QString& );
protected:
/*
* This function simply sets the lineedit text and
* highlights the text appropriately if the boolean
* value is set to true.
*
* @param
* @param
*/
virtual void setCompletedText( const QString& /* */, bool /*marked*/ );
/**
* Reimplemented for internal reasons, the API is not affected.
*/
virtual void create( WId = 0, bool initializeWindow = true,
bool destroyOldWindow = true );
virtual void wheelEvent( QWheelEvent *ev );
virtual QSize minimumSizeHint() const;
private Q_SLOTS:
void lineEditDeleted();
private:
/**
* Initializes the variables upon construction.
*/
- void init();
+ void initWidget();
private:
class KComboBoxPrivate;
KComboBoxPrivate* const d;
};
#endif
diff --git a/kdeui/widgets/kdatepicker.cpp b/kdeui/widgets/kdatepicker.cpp
index 35f9627332..1e6f0de580 100644
--- a/kdeui/widgets/kdatepicker.cpp
+++ b/kdeui/widgets/kdatepicker.cpp
@@ -1,671 +1,671 @@
/* -*- C++ -*-
This file is part of the KDE libraries
Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
(C) 1998-2001 Mirko Boehm (mirko@kde.org)
(C) 2007 John Layt <john@layt.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kdatepicker.h"
#include "kdatepicker_p.h"
#include "kdatetable.h"
#include <QApplication>
#include <QFont>
#include <QLayout>
#include <QKeyEvent>
#include <QMenu>
#include <QPainter>
#include <QStyle>
#include <QToolButton>
#include <QDoubleValidator>
#include <kcalendarsystem.h>
#include <klocalizeddate.h>
#include <kcombobox.h>
#include <kdebug.h>
#include <kdialog.h>
#include <kglobal.h>
#include <kicon.h>
#include <kiconloader.h>
#include <klineedit.h>
#include <knotification.h>
#include "moc_kdatepicker.cpp"
#include "moc_kdatepicker_p.cpp"
// Week numbers are defined by ISO 8601
// See http://www.merlyn.demon.co.uk/weekinfo.htm for details
KDatePickerPrivateYearSelector::KDatePickerPrivateYearSelector(
const KCalendarSystem *cal, const QDate &currentDate, QWidget* parent )
: QLineEdit( parent ), val( new QIntValidator( this ) ), result( 0 )
{
calendar = cal;
oldDate = currentDate;
QFont font;
font = KGlobalSettings::generalFont();
setFont( font );
setFrame( false );
val->setRange( calendar->year( calendar->earliestValidDate() ),
calendar->year( calendar->latestValidDate() ) );
setValidator( val );
connect( this, SIGNAL( returnPressed() ), SLOT( yearEnteredSlot() ) );
}
void KDatePickerPrivateYearSelector::yearEnteredSlot()
{
bool ok;
int newYear;
QDate newDate;
// check if entered value is a number
newYear = text().toInt( &ok );
if( !ok ) {
KNotification::beep();
return;
}
// check if new year will lead to a valid date
if ( calendar->setDate( newDate, newYear, calendar->month( oldDate ), calendar->day( oldDate ) ) ) {
result = newYear;
emit( closeMe( 1 ) );
} else {
KNotification::beep();
}
}
int KDatePickerPrivateYearSelector::year()
{
return result;
}
void KDatePickerPrivateYearSelector::setYear( int year )
{
setText( QString::number( year ) );
}
class KDatePicker::KDatePickerPrivate
{
public:
KDatePickerPrivate( KDatePicker *q ) :
q( q ), closeButton( 0L ), selectWeek( 0L ), todayButton( 0 ), navigationLayout( 0 )
{
}
void fillWeeksCombo();
QDate validDateInYearMonth( int year, int month );
/// the date table
KDatePicker *q;
QToolButton *closeButton;
KComboBox *selectWeek;
QToolButton *todayButton;
QBoxLayout *navigationLayout;
/// the year forward button
QToolButton *yearForward;
/// the year backward button
QToolButton *yearBackward;
/// the month forward button
QToolButton *monthForward;
/// the month backward button
QToolButton *monthBackward;
/// the button for selecting the month directly
QToolButton *selectMonth;
/// the button for selecting the year directly
QToolButton *selectYear;
/// the line edit to enter the date directly
QLineEdit *line;
/// the validator for the line edit:
KDateValidator *val;
/// the date table
KDateTable *table;
/// the widest month string in pixels:
QSize maxMonthRect;
/// the font size for the widget
int fontsize;
};
void KDatePicker::KDatePickerPrivate::fillWeeksCombo()
{
// every year can have a different number of weeks
// it could be that we had 53,1..52 and now 1..53 which is the same number but different
// so always fill with new values
// We show all week numbers for all weeks between first day of year to last day of year
// This of course can be a list like 53,1,2..52
KLocalizedDate thisDate( q->date(), q->calendar() );
int thisYear = thisDate.year();
KLocalizedDate day = thisDate.firstDayOfYear();
KLocalizedDate lastDayOfYear = thisDate.lastDayOfYear();
selectWeek->clear();
// Starting from the first day in the year, loop through the year a week at a time
// adding an entry to the week combo for each week in the year
for ( ; day.isValid() && day <= lastDayOfYear; day.addDaysTo( day.daysInWeek() ) ) {
// Get the ISO week number for the current day and what year that week is in
// e.g. 1st day of this year may fall in week 53 of previous year
int weekYear = thisYear;
day.week( &weekYear );
QString weekString = i18n( "Week %1", day.formatDate( KLocale::Week, KLocale::ShortNumber ) );
// show that this is a week from a different year
if ( weekYear != thisYear ) {
weekString += '*';
}
// when the week is selected, go to the same weekday as the one
// that is currently selected in the date table
QDate targetDate = day.addDays( thisDate.dayOfWeek() - day.dayOfWeek() ).date();
selectWeek->addItem( weekString, targetDate );
// make sure that the week of the lastDayOfYear is always inserted: in Chinese calendar
// system, this is not always the case
if ( day < lastDayOfYear &&
day.daysDifference( lastDayOfYear ) < day.daysInWeek() &&
lastDayOfYear.week() != day.week() ) {
day = lastDayOfYear.addDays( - thisDate.daysInWeek() );
}
}
}
QDate KDatePicker::KDatePickerPrivate::validDateInYearMonth( int year, int month )
{
QDate newDate;
// Try to create a valid date in this year and month
// First try the first of the month, then try last of month
if ( q->calendar()->isValid( year, month, 1 ) ) {
q->calendar()->setDate( newDate, year, month, 1 );
} else if ( q->calendar()->isValid( year, month + 1, 1 ) ) {
q->calendar()->setDate( newDate, year, month, 1 );
q->calendar()->addDays( newDate, -1 );
} else {
newDate = QDate::fromJulianDay( 0 );
}
return newDate;
}
KDatePicker::KDatePicker( QWidget* parent ) : QFrame( parent ), d( new KDatePickerPrivate( this ) )
{
- init( QDate::currentDate() );
+ initWidget( QDate::currentDate() );
}
KDatePicker::KDatePicker( const QDate& date_, QWidget* parent )
: QFrame( parent ), d( new KDatePickerPrivate( this ) )
{
- init( date_ );
+ initWidget( date_ );
}
-void KDatePicker::init( const QDate &date_ )
+void KDatePicker::initWidget( const QDate &date_ )
{
QBoxLayout * topLayout = new QVBoxLayout( this );
topLayout->setSpacing( 0 );
topLayout->setMargin( 0 );
d->navigationLayout = new QHBoxLayout();
d->navigationLayout->setSpacing( 0 );
d->navigationLayout->setMargin( 0 );
topLayout->addLayout( d->navigationLayout );
d->navigationLayout->addStretch();
d->yearBackward = new QToolButton( this );
d->yearBackward->setAutoRaise( true );
d->navigationLayout->addWidget( d->yearBackward );
d->monthBackward = new QToolButton( this );
d->monthBackward ->setAutoRaise( true );
d->navigationLayout->addWidget( d->monthBackward );
d->navigationLayout->addSpacing( KDialog::spacingHint() );
d->selectMonth = new QToolButton( this );
d->selectMonth ->setAutoRaise( true );
d->navigationLayout->addWidget( d->selectMonth );
d->selectYear = new QToolButton( this );
d->selectYear->setCheckable( true );
d->selectYear->setAutoRaise( true );
d->navigationLayout->addWidget( d->selectYear );
d->navigationLayout->addSpacing( KDialog::spacingHint() );
d->monthForward = new QToolButton( this );
d->monthForward ->setAutoRaise( true );
d->navigationLayout->addWidget( d->monthForward );
d->yearForward = new QToolButton( this );
d->yearForward ->setAutoRaise( true );
d->navigationLayout->addWidget( d->yearForward );
d->navigationLayout->addStretch();
d->line = new KLineEdit( this );
d->val = new KDateValidator( this );
d->table = new KDateTable( this );
setFocusProxy( d->table );
d->fontsize = KGlobalSettings::generalFont().pointSize();
if ( d->fontsize == -1 ) {
d->fontsize = QFontInfo( KGlobalSettings::generalFont() ).pointSize();
}
d->fontsize++; // Make a little bigger
d->selectWeek = new KComboBox( this ); // read only week selection
d->selectWeek->setFocusPolicy( Qt::NoFocus );
d->todayButton = new QToolButton( this );
d->todayButton->setIcon( KIcon( "go-jump-today" ) );
d->yearForward->setToolTip( i18n( "Next year" ) );
d->yearBackward->setToolTip( i18n( "Previous year" ) );
d->monthForward->setToolTip( i18n( "Next month" ) );
d->monthBackward->setToolTip( i18n( "Previous month" ) );
d->selectWeek->setToolTip( i18n( "Select a week" ) );
d->selectMonth->setToolTip( i18n( "Select a month" ) );
d->selectYear->setToolTip( i18n( "Select a year" ) );
d->todayButton->setToolTip( i18n( "Select the current day" ) );
// -----
setFontSize( d->fontsize );
d->line->setValidator( d->val );
d->line->installEventFilter( this );
if ( QApplication::isRightToLeft() ) {
d->yearForward->setIcon( KIcon( QLatin1String( "arrow-left-double" ) ) );
d->yearBackward->setIcon( KIcon( QLatin1String( "arrow-right-double" ) ) );
d->monthForward->setIcon( KIcon( QLatin1String( "arrow-left" ) ) );
d->monthBackward->setIcon( KIcon( QLatin1String( "arrow-right" ) ) );
} else {
d->yearForward->setIcon( KIcon( QLatin1String( "arrow-right-double" ) ) );
d->yearBackward->setIcon( KIcon( QLatin1String( "arrow-left-double" ) ) );
d->monthForward->setIcon( KIcon( QLatin1String( "arrow-right" ) ) );
d->monthBackward->setIcon( KIcon( QLatin1String( "arrow-left" ) ) );
}
connect( d->table, SIGNAL( dateChanged( const QDate& ) ), SLOT( dateChangedSlot( const QDate& ) ) );
connect( d->table, SIGNAL( tableClicked() ), SLOT( tableClickedSlot() ) );
connect( d->monthForward, SIGNAL( clicked() ), SLOT( monthForwardClicked() ) );
connect( d->monthBackward, SIGNAL( clicked() ), SLOT( monthBackwardClicked() ) );
connect( d->yearForward, SIGNAL( clicked() ), SLOT( yearForwardClicked() ) );
connect( d->yearBackward, SIGNAL( clicked() ), SLOT( yearBackwardClicked() ) );
connect( d->selectWeek, SIGNAL( activated( int ) ), SLOT( weekSelected( int ) ) );
connect( d->todayButton, SIGNAL( clicked() ), SLOT( todayButtonClicked() ) );
connect( d->selectMonth, SIGNAL( clicked() ), SLOT( selectMonthClicked() ) );
connect( d->selectYear, SIGNAL( toggled( bool ) ), SLOT( selectYearClicked() ) );
connect( d->line, SIGNAL( returnPressed() ), SLOT( lineEnterPressed() ) );
topLayout->addWidget( d->table );
QBoxLayout * bottomLayout = new QHBoxLayout();
bottomLayout->setMargin( 0 );
bottomLayout->setSpacing( 0 );
topLayout->addLayout( bottomLayout );
bottomLayout->addWidget( d->todayButton );
bottomLayout->addWidget( d->line );
bottomLayout->addWidget( d->selectWeek );
d->table->setDate( date_ );
dateChangedSlot( date_ ); // needed because table emits changed only when newDate != oldDate
}
KDatePicker::~KDatePicker()
{
delete d;
}
bool KDatePicker::eventFilter( QObject *o, QEvent *e )
{
if ( e->type() == QEvent::KeyPress ) {
QKeyEvent * k = ( QKeyEvent * )e;
if ( ( k->key() == Qt::Key_PageUp ) ||
( k->key() == Qt::Key_PageDown ) ||
( k->key() == Qt::Key_Up ) ||
( k->key() == Qt::Key_Down ) ) {
QApplication::sendEvent( d->table, e );
d->table->setFocus();
return true; // eat event
}
}
return QFrame::eventFilter( o, e );
}
void KDatePicker::resizeEvent( QResizeEvent* e )
{
QWidget::resizeEvent( e );
}
void KDatePicker::dateChangedSlot( const QDate &date_ )
{
KLocalizedDate thisDate( date_, calendar() );
d->line->setText( thisDate.formatDate( KLocale::ShortDate ) );
d->selectMonth->setText( thisDate.formatDate( KLocale::Month, KLocale::LongName ) );
d->fillWeeksCombo();
// calculate the item num in the week combo box; normalize selected day so as if 1.1. is the first day of the week
KLocalizedDate firstDay = thisDate.firstDayOfYear();
// If we cannot successfully create the 1st of the year, this can only mean that
// the 1st is before the earliest valid date in the current calendar system, so use
// the earliestValidDate as the first day.
// In particular covers the case of Gregorian where 1/1/-4713 is not a valid QDate
d->selectWeek->setCurrentIndex( ( thisDate.dayOfYear() + firstDay.dayOfWeek() - 2 ) /
thisDate.daysInWeek() );
d->selectYear->setText( thisDate.formatDate( KLocale::Year, KLocale::LongNumber ) );
emit( dateChanged( date_ ) );
}
void KDatePicker::tableClickedSlot()
{
emit( dateSelected( date() ) );
emit( tableClicked() );
}
const QDate & KDatePicker::date() const
{
return d->table->date();
}
bool KDatePicker::setDate( const QDate &date_ )
{
// the table setDate does validity checking for us
// this also emits dateChanged() which then calls our dateChangedSlot()
return d->table->setDate( date_ );
}
const KCalendarSystem *KDatePicker::calendar() const
{
return d->table->calendar();
}
bool KDatePicker::setCalendar( KCalendarSystem *calendar )
{
return d->table->setCalendar( calendar );
}
bool KDatePicker::setCalendar( const QString &calendarType )
{
return d->table->setCalendar( calendarType );
}
bool KDatePicker::setCalendarSystem( KLocale::CalendarSystem calendarSystem )
{
return d->table->setCalendarSystem( calendarSystem );
}
void KDatePicker::monthForwardClicked()
{
if ( ! setDate( calendar()->addMonths( date(), 1 ) ) ) {
KNotification::beep();
}
d->table->setFocus();
}
void KDatePicker::monthBackwardClicked()
{
if ( ! setDate( calendar()->addMonths( date(), -1 ) ) ) {
KNotification::beep();
}
d->table->setFocus();
}
void KDatePicker::yearForwardClicked()
{
if ( ! setDate( calendar()->addYears( d->table->date(), 1 ) ) ) {
KNotification::beep();
}
d->table->setFocus();
}
void KDatePicker::yearBackwardClicked()
{
if ( ! setDate( calendar()->addYears( d->table->date(), -1 ) ) ) {
KNotification::beep();
}
d->table->setFocus();
}
void KDatePicker::weekSelected( int index )
{
QDate targetDay = d->selectWeek->itemData( index ).toDateTime().date();
if ( ! setDate( targetDay ) ) {
KNotification::beep();
}
d->table->setFocus();
}
void KDatePicker::selectMonthClicked()
{
KLocalizedDate thisDate( date(), calendar() );
d->table->setFocus();
QMenu popup( d->selectMonth );
// Populate the pick list with all the month names, this may change by year
// JPL do we need to do somethng here for months that fall outside valid range?
for ( int m = 1; m <= thisDate.monthsInYear(); m++ ) {
popup.addAction( calendar()->monthName( m, thisDate.year() ) )->setData( m );
}
QAction *item = popup.actions()[ thisDate.month() - 1 ];
// if this happens the above should already given an assertion
if ( item ) {
popup.setActiveAction( item );
}
// cancelled
if ( ( item = popup.exec( d->selectMonth->mapToGlobal( QPoint( 0, 0 ) ), item ) ) == 0 ) {
return;
}
// We need to create a valid date in the month selected so we can find out how many days are
// in the month.
KLocalizedDate newDate( thisDate.year(), item->data().toInt(), 1, calendar() );
// If we have succeeded in creating a date in the new month, then try to create the new date,
// checking we don't set a day after the last day of the month
newDate.setDate( newDate.year(), newDate.month(), qMin( thisDate.day(), newDate.daysInMonth() ) );
// Set the date, if it's invalid in any way then alert user and don't update
if ( ! setDate( newDate.date() ) ) {
KNotification::beep();
}
}
void KDatePicker::selectYearClicked()
{
if ( !d->selectYear->isChecked() )
return;
KLocalizedDate thisDate( date(), calendar() );
KPopupFrame *popup = new KPopupFrame( this );
KDatePickerPrivateYearSelector *picker = new KDatePickerPrivateYearSelector( calendar(), date(), popup );
picker->resize( picker->sizeHint() );
picker->setYear( thisDate.year() );
picker->selectAll();
popup->setMainWidget( picker );
connect( picker, SIGNAL( closeMe( int ) ), popup, SLOT( close( int ) ) );
picker->setFocus();
if( popup->exec( d->selectYear->mapToGlobal( QPoint( 0, d->selectMonth->height() ) ) ) ) {
// We need to create a valid date in the year/month selected so we can find out how many
// days are in the month.
KLocalizedDate newDate( picker->year(), thisDate.month(), 1, calendar() );
// If we have succeeded in creating a date in the new month, then try to create the new
// date, checking we don't set a day after the last day of the month
newDate.setDate( newDate.year(), newDate.month(), qMin( thisDate.day(), newDate.daysInMonth() ) );
// Set the date, if it's invalid in any way then alert user and don't update
if ( ! setDate( newDate.date() ) ) {
KNotification::beep();
}
}
delete popup;
d->selectYear->setChecked( false );
}
void KDatePicker::uncheckYearSelector()
{
d->selectYear->setChecked(false);
d->selectYear->update();
}
// ####### KDE4: setEnabled isn't virtual anymore, so this isn't polymorphic.
// Better reimplement changeEvent() instead.
void KDatePicker::setEnabled( bool enable )
{
QWidget * const widgets[] = {
d->yearForward, d->yearBackward, d->monthForward, d->monthBackward,
d->selectMonth, d->selectYear,
d->line, d->table, d->selectWeek, d->todayButton
};
const int Size = sizeof( widgets ) / sizeof( widgets[0] );
int count;
for( count = 0; count < Size; ++count ) {
widgets[count]->setEnabled( enable );
}
d->table->setFocus();
}
KDateTable *KDatePicker::dateTable() const
{
return d->table;
}
void KDatePicker::lineEnterPressed()
{
QDate newDate = calendar()->readDate( d->line->text() );
if ( calendar()->isValid( newDate ) ) {
emit( dateEntered( newDate ) );
setDate( newDate );
d->table->setFocus();
} else {
KNotification::beep();
}
}
void KDatePicker::todayButtonClicked()
{
setDate( QDate::currentDate() );
d->table->setFocus();
}
QSize KDatePicker::sizeHint() const
{
return QWidget::sizeHint();
}
void KDatePicker::setFontSize( int s )
{
QWidget * const buttons[] = {
d->selectMonth,
d->selectYear,
};
const int NoOfButtons = sizeof( buttons ) / sizeof( buttons[0] );
int count;
QFont font;
QRect r;
// -----
d->fontsize = s;
for( count = 0; count < NoOfButtons; ++count ) {
font = buttons[count]->font();
font.setPointSize( s );
buttons[count]->setFont( font );
}
d->table->setFontSize( s );
QFontMetrics metrics( d->selectMonth->fontMetrics() );
QString longestMonth;
for ( int i = 1; ; ++i ) {
QString str = calendar()->monthName( i, calendar()->year( date() ), KCalendarSystem::LongName );
if ( str.isNull() ) {
break;
}
r = metrics.boundingRect( str );
if ( r.width() > d->maxMonthRect.width() ) {
d->maxMonthRect.setWidth( r.width() );
longestMonth = str;
}
if ( r.height() > d->maxMonthRect.height() ) {
d->maxMonthRect.setHeight( r.height() );
}
}
QStyleOptionToolButton opt;
opt.initFrom( d->selectMonth );
opt.text = longestMonth;
// stolen from QToolButton
QSize textSize = metrics.size( Qt::TextShowMnemonic, longestMonth );
textSize.setWidth( textSize.width() + metrics.width( QLatin1Char(' ') ) * 2 );
int w = textSize.width();
int h = textSize.height();
opt.rect.setHeight( h ); // PM_MenuButtonIndicator depends on the height
QSize metricBound = style()->sizeFromContents(
QStyle::CT_ToolButton, &opt, QSize( w, h ), d->selectMonth
).expandedTo( QApplication::globalStrut() );
d->selectMonth->setMinimumSize( metricBound );
}
int KDatePicker::fontSize() const
{
return d->fontsize;
}
void KDatePicker::setCloseButton( bool enable )
{
if ( enable == ( d->closeButton != 0L ) ) {
return;
}
if ( enable ) {
d->closeButton = new QToolButton( this );
d->closeButton->setAutoRaise( true );
d->navigationLayout->addSpacing( KDialog::spacingHint() );
d->navigationLayout->addWidget( d->closeButton );
d->closeButton->setToolTip( i18nc( "@action:button", "Close" ) );
d->closeButton->setIcon( SmallIcon( "window-close" ) );
connect( d->closeButton, SIGNAL( clicked() ),
topLevelWidget(), SLOT( close() ) );
} else {
delete d->closeButton;
d->closeButton = 0L;
}
updateGeometry();
}
bool KDatePicker::hasCloseButton() const
{
return ( d->closeButton );
}
diff --git a/kdeui/widgets/kdatepicker.h b/kdeui/widgets/kdatepicker.h
index d45b8cbbbc..fd969640ec 100644
--- a/kdeui/widgets/kdatepicker.h
+++ b/kdeui/widgets/kdatepicker.h
@@ -1,226 +1,226 @@
/* -*- C++ -*-
This file is part of the KDE libraries
Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
(C) 1998-2001 Mirko Boehm (mirko@kde.org)
(C) 2007 John Layt <john@layt.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KDATEPICKER_H
#define KDATEPICKER_H
#include <kdeui_export.h>
#include <QtCore/QDateTime>
#include <QFrame>
#include <klocale.h>
class QLineEdit;
class KDateTable;
class KCalendarSystem;
/**
* @short A date selection widget.
*
* Provides a widget for calendar date input.
*
* Different from the
* previous versions, it now emits two types of signals, either
* dateSelected() or dateEntered() (see documentation for both
* signals).
*
* A line edit has been added in the newer versions to allow the user
* to select a date directly by entering numbers like 19990101
* or 990101.
*
* \image html kdatepicker.png "KDE Date Widget"
*
* @author Tim Gilman, Mirko Boehm
*
**/
class KDEUI_EXPORT KDatePicker: public QFrame
{
Q_OBJECT
Q_PROPERTY( QDate date READ date WRITE setDate NOTIFY dateChanged USER true )
//FIXME Q_PROPERTY( KCalendarSystem calendar READ calendar WRITE setCalendar USER true )
Q_PROPERTY( bool closeButton READ hasCloseButton WRITE setCloseButton )
Q_PROPERTY( int fontSize READ fontSize WRITE setFontSize )
public:
/**
* The constructor. The current date will be displayed initially.
**/
explicit KDatePicker( QWidget *parent = 0 );
/**
* The constructor. The given date will be displayed initially.
**/
explicit KDatePicker( const QDate &dt, QWidget *parent = 0 );
/**
* The destructor.
**/
virtual ~KDatePicker();
/** The size hint for date pickers. The size hint recommends the
* minimum size of the widget so that all elements may be placed
* without clipping. This sometimes looks ugly, so when using the
* size hint, try adding 28 to each of the reported numbers of
* pixels.
**/
QSize sizeHint() const;
/**
* Sets the date.
*
* @returns @p false and does not change anything if the date given is invalid.
**/
bool setDate( const QDate& date );
/**
* @returns the selected date.
*/
const QDate &date() const;
/**
* Returns the currently selected calendar system.
*
* @returns a KCalendarSystem object
*/
const KCalendarSystem *calendar() const;
/**
* Changes the calendar system to use. Can use its own local locale if set.
*
* @param calendar the calendar system object to use, defaults to global
*
* @return @c true if the calendar system was successfully set, @c false otherwise
*/
bool setCalendar( KCalendarSystem *calendar = 0 );
/**
* Changes the calendar system to use. Will always use global locale.
*
* @param calendarType the calendar system type to use
*
* @return @c true if the calendar system was successfully set, @c false otherwise
*/
bool setCalendar( const QString &calendarType );
/**
* @since 4.6
*
* Changes the calendar system to use. Will always use global locale.
*
* @param calendarSystem the calendar system to use
* @return @c true if the calendar system was successfully set, @c false otherwise
*/
bool setCalendarSystem( KLocale::CalendarSystem calendarSystem );
/**
* Enables or disables the widget.
**/
void setEnabled( bool enable );
/**
* @returns the KDateTable widget child of this KDatePicker
* widget.
*/
KDateTable *dateTable() const;
/**
* Sets the font size of the widgets elements.
**/
void setFontSize( int );
/**
* Returns the font size of the widget elements.
*/
int fontSize() const;
/**
* By calling this method with @p enable = true, KDatePicker will show
* a little close-button in the upper button-row. Clicking the
* close-button will cause the KDatePicker's topLevelWidget()'s close()
* method being called. This is mostly useful for toplevel datepickers
* without a window manager decoration.
* @see hasCloseButton
*/
void setCloseButton( bool enable );
/**
* @returns true if a KDatePicker shows a close-button.
* @see setCloseButton
*/
bool hasCloseButton() const;
protected:
/// to catch move keyEvents when QLineEdit has keyFocus
virtual bool eventFilter( QObject *o, QEvent *e );
/// the resize event
virtual void resizeEvent( QResizeEvent* );
protected Q_SLOTS:
void dateChangedSlot( const QDate& date );
void tableClickedSlot();
void monthForwardClicked();
void monthBackwardClicked();
void yearForwardClicked();
void yearBackwardClicked();
void selectMonthClicked();
void selectYearClicked();
void uncheckYearSelector();
void lineEnterPressed();
void todayButtonClicked();
void weekSelected( int );
Q_SIGNALS:
/** This signal is emitted each time the selected date is changed.
* Usually, this does not mean that the date has been entered,
* since the date also changes, for example, when another month is
* selected.
* @see dateSelected
*/
void dateChanged( const QDate &date );
/** This signal is emitted each time a day has been selected by
* clicking on the table (hitting a day in the current month). It
* has the same meaning as dateSelected() in older versions of
* KDatePicker.
*/
void dateSelected( const QDate &date );
/** This signal is emitted when enter is pressed and a VALID date
* has been entered before into the line edit. Connect to both
* dateEntered() and dateSelected() to receive all events where the
* user really enters a date.
*/
void dateEntered( const QDate &date );
/** This signal is emitted when the day has been selected by
* clicking on it in the table.
*/
void tableClicked();
private:
- void init( const QDate &date );
+ void initWidget( const QDate &date );
class KDatePickerPrivate;
friend class KDatePickerPrivate;
KDatePickerPrivate *const d;
};
#endif // KDATEPICKER_H
diff --git a/kdeui/widgets/kdatetable.cpp b/kdeui/widgets/kdatetable.cpp
index 4808d3143f..e06ef3c3eb 100644
--- a/kdeui/widgets/kdatetable.cpp
+++ b/kdeui/widgets/kdatetable.cpp
@@ -1,962 +1,962 @@
/* -*- C++ -*-
This file is part of the KDE libraries
Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
(C) 1998-2001 Mirko Boehm (mirko@kde.org)
(C) 2007 John Layt <john@layt.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kdatetable.h"
#include <kconfig.h>
#include <kcolorscheme.h>
#include <kglobal.h>
#include <kglobalsettings.h>
#include <kdebug.h>
#include <knotification.h>
#include <kcalendarsystem.h>
#include <klocalizeddate.h>
#include <kshortcut.h>
#include <kstandardshortcut.h>
#include "kdatepicker.h"
#include "kmenu.h"
#include "kactioncollection.h"
#include "kaction.h"
#include <kdeversion.h>
#include <QtCore/QDate>
#include <QtCore/QCharRef>
#include <QPen>
#include <QPainter>
#include <QStyle>
#include <QStyleOptionViewItem>
#include <QDialog>
#include <QActionEvent>
#include <QtCore/QHash>
#include <QApplication>
#include <assert.h>
#include <cmath>
class KDateTable::KDateTablePrivate
{
public:
KDateTablePrivate( KDateTable *q ): q( q )
{
m_popupMenuEnabled = false;
m_useCustomColors = false;
m_hoveredPos = -1;
setDate( QDate::currentDate() );
}
~KDateTablePrivate()
{
}
void setDate( const QDate& date );
void nextMonth();
void previousMonth();
void beginningOfMonth();
void endOfMonth();
void beginningOfWeek();
void endOfWeek();
KDateTable *q;
/**
* The font size of the displayed text.
*/
int fontsize;
/**
* The currently selected date.
*/
KLocalizedDate m_date;
// Need to keep a QDate copy as the "const QDate &date() const;" method returns a reference
// and returning m_date.date() creates a temporary leading to crashes. Doh!
QDate m_refDate;
/**
* The weekday number of the first day in the month [1..daysInWeek()].
*/
int m_weekDayFirstOfMonth;
/**
* The number of days in the current month.
*/
int m_numDaysThisMonth;
/**
* Save the size of the largest used cell content.
*/
QRectF m_maxCell;
/**
* How many week rows we are to draw.
*/
int m_numWeekRows;
/**
* How many day columns we are to draw, i.e. days in a week.
*/
int m_numDayColumns;
bool m_popupMenuEnabled;
bool m_useCustomColors;
struct DatePaintingMode
{
QColor fgColor;
QColor bgColor;
BackgroundMode bgMode;
};
QHash <int, DatePaintingMode*> m_customPaintingModes;
int m_hoveredPos;
};
class KPopupFrame::KPopupFramePrivate
{
public:
KPopupFramePrivate( KPopupFrame *q );
~KPopupFramePrivate();
KPopupFrame *q;
/**
* The result. It is returned from exec() when the popup window closes.
*/
int result;
/**
* The only subwidget that uses the whole dialog window.
*/
QWidget *main;
// ### KDE 5: Remove this, add a hideEvent() reimplementation instead.
class OutsideClickCatcher;
OutsideClickCatcher *outsideClickCatcher;
};
class KPopupFrame::KPopupFramePrivate::OutsideClickCatcher
: public QObject
{
public:
OutsideClickCatcher(QObject *parent = 0)
: QObject(parent), m_popup(0) { }
~OutsideClickCatcher() { }
void setPopupFrame(KPopupFrame *popup)
{
m_popup = popup;
popup->installEventFilter(this);
}
KPopupFrame *m_popup;
bool eventFilter(QObject *object, QEvent *event)
{
Q_UNUSED(object);
// To catch outside clicks, it is sufficient to check for
// hide events on Qt::Popup type widgets
if (event->type() == QEvent::Hide && m_popup) {
// do not set d->result here, because the popup
// hides itself after leaving the event loop.
emit m_popup->leaveModality();
}
return false;
}
};
KPopupFrame::KPopupFramePrivate::KPopupFramePrivate( KPopupFrame *q ):
q( q ),
result( 0 ), // rejected
main( 0 ),
outsideClickCatcher(new OutsideClickCatcher)
{
outsideClickCatcher->setPopupFrame(q);
}
KPopupFrame::KPopupFramePrivate::~KPopupFramePrivate()
{
delete outsideClickCatcher;
}
class KDateValidator::KDateValidatorPrivate
{
public:
KDateValidatorPrivate( KDateValidator *q ): q( q )
{
}
~KDateValidatorPrivate()
{
}
KDateValidator *q;
};
KDateValidator::KDateValidator( QWidget *parent ) : QValidator( parent ), d( 0 )
{
}
QValidator::State KDateValidator::validate( QString &text, int &unused ) const
{
Q_UNUSED( unused );
QDate temp;
// ----- everything is tested in date():
return date( text, temp );
}
QValidator::State KDateValidator::date( const QString &text, QDate &d ) const
{
//FIXME This is wrong if the widget is not using the global!
QDate tmp = KGlobal::locale()->readDate( text );
if ( KGlobal::locale()->calendar()->isValid( tmp ) ) {
d = tmp;
return Acceptable;
} else {
return QValidator::Intermediate;
}
}
void KDateValidator::fixup( QString& ) const
{
}
KDateTable::KDateTable( const QDate& date, QWidget* parent )
: QWidget( parent ),
d( new KDateTablePrivate( this ) )
{
- init( date );
+ initWidget( date );
}
KDateTable::KDateTable( QWidget *parent )
: QWidget( parent ),
d( new KDateTablePrivate( this ) )
{
- init( QDate::currentDate() );
+ initWidget( QDate::currentDate() );
}
KDateTable::~KDateTable()
{
delete d;
}
-void KDateTable::init( const QDate &date )
+void KDateTable::initWidget( const QDate &date )
{
d->m_numWeekRows = 7;
setFontSize( 10 );
setFocusPolicy( Qt::StrongFocus );
setBackgroundRole(QPalette::Base);
setAutoFillBackground(true);
initAccels();
setAttribute(Qt::WA_Hover, true);
setDate( date );
}
void KDateTable::initAccels()
{
KActionCollection * localCollection = new KActionCollection( this );
KAction* next = localCollection->addAction( QLatin1String( "next" ) );
next->setShortcuts( KStandardShortcut::next() );
connect( next, SIGNAL( triggered( bool ) ), SLOT( nextMonth() ) );
KAction* prior = localCollection->addAction( QLatin1String( "prior" ) );
prior->setShortcuts( KStandardShortcut::prior() );
connect( prior, SIGNAL( triggered( bool ) ), SLOT( previousMonth() ) );
KAction* beginMonth = localCollection->addAction( QLatin1String( "beginMonth" ) );
beginMonth->setShortcuts( KStandardShortcut::begin() );
connect( beginMonth, SIGNAL( triggered( bool ) ), SLOT( beginningOfMonth() ) );
KAction* endMonth = localCollection->addAction( QLatin1String( "endMonth" ) );
endMonth->setShortcuts( KStandardShortcut::end() );
connect( endMonth, SIGNAL( triggered( bool ) ), SLOT( endOfMonth() ) );
KAction* beginWeek = localCollection->addAction( QLatin1String( "beginWeek" ) );
beginWeek->setShortcuts( KStandardShortcut::beginningOfLine() );
connect( beginWeek, SIGNAL( triggered( bool ) ), SLOT( beginningOfWeek() ) );
KAction* endWeek = localCollection->addAction( "endWeek" );
endWeek->setShortcuts( KStandardShortcut::endOfLine() );
connect( endWeek, SIGNAL( triggered( bool ) ), SLOT( endOfWeek() ) );
localCollection->readSettings();
localCollection->addAssociatedWidget( this );
foreach (QAction* action, localCollection->actions()) {
action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
}
}
int KDateTable::posFromDate( const QDate &date )
{
int initialPosition = calendar()->day( date );
int offset = ( d->m_weekDayFirstOfMonth - calendar()->weekStartDay() + d->m_numDayColumns ) % d->m_numDayColumns;
// make sure at least one day of the previous month is visible.
// adjust this < 1 if more days should be forced visible:
if ( offset < 1 ) {
offset += d->m_numDayColumns;
}
return initialPosition + offset;
}
QDate KDateTable::dateFromPos( int position )
{
int offset = ( d->m_weekDayFirstOfMonth - calendar()->weekStartDay() + d->m_numDayColumns ) % d->m_numDayColumns;
// make sure at least one day of the previous month is visible.
// adjust this < 1 if more days should be forced visible:
if ( offset < 1 ) {
offset += d->m_numDayColumns;
}
return d->m_date.firstDayOfMonth().addDays( position - offset ).date();
}
void KDateTable::paintEvent( QPaintEvent *e )
{
QPainter p( this );
KColorScheme colorScheme(palette().currentColorGroup(), KColorScheme::View);
const QRect &rectToUpdate = e->rect();
double cellWidth = width() / ( double ) d->m_numDayColumns;
double cellHeight = height() / ( double ) d->m_numWeekRows;
int leftCol = ( int )std::floor( rectToUpdate.left() / cellWidth );
int topRow = ( int )std::floor( rectToUpdate.top() / cellHeight );
int rightCol = ( int )std::ceil( rectToUpdate.right() / cellWidth );
int bottomRow = ( int )std::ceil( rectToUpdate.bottom() / cellHeight );
bottomRow = qMin( bottomRow, d->m_numWeekRows - 1 );
rightCol = qMin( rightCol, d->m_numDayColumns - 1 );
if ( layoutDirection() == Qt::RightToLeft ) {
p.translate( ( d->m_numDayColumns - leftCol - 1 ) * cellWidth, topRow * cellHeight );
} else {
p.translate( leftCol * cellWidth, topRow * cellHeight );
}
for ( int i = leftCol; i <= rightCol; ++i ) {
for ( int j = topRow; j <= bottomRow; ++j ) {
paintCell( &p, j, i, colorScheme );
p.translate( 0, cellHeight );
}
if ( layoutDirection() == Qt::RightToLeft ) {
p.translate( -cellWidth, 0 );
} else {
p.translate( cellWidth, 0 );
}
p.translate( 0, -cellHeight * ( bottomRow - topRow + 1 ) );
}
}
void KDateTable::paintCell( QPainter *painter, int row, int col, const KColorScheme &colorScheme )
{
double w = ( width() / ( double ) d->m_numDayColumns ) - 1;
double h = ( height() / ( double ) d->m_numWeekRows ) - 1;
QRectF cell = QRectF( 0, 0, w, h );
QString cellText;
QPen pen;
QColor cellBackgroundColor, cellTextColor;
QFont cellFont = KGlobalSettings::generalFont();
bool workingDay = false;
int cellWeekDay, pos;
BackgroundMode cellBackgroundMode = RectangleMode;
//Calculate the position of the cell in the grid
pos = d->m_numDayColumns * ( row - 1 ) + col;
//Calculate what day of the week the cell is
if ( col + calendar()->weekStartDay() <= d->m_numDayColumns ) {
cellWeekDay = col + calendar()->weekStartDay();
} else {
cellWeekDay = col + calendar()->weekStartDay() - d->m_numDayColumns;
}
//FIXME This is wrong if the widget is not using the global!
//See if cell day is normally a working day
if ( KGlobal::locale()->workingWeekStartDay() <= KGlobal::locale()->workingWeekEndDay() ) {
if ( cellWeekDay >= KGlobal::locale()->workingWeekStartDay() &&
cellWeekDay <= KGlobal::locale()->workingWeekEndDay() ) {
workingDay = true;
}
} else {
if ( cellWeekDay >= KGlobal::locale()->workingWeekStartDay() ||
cellWeekDay <= KGlobal::locale()->workingWeekEndDay() ) {
workingDay = true;
}
}
if( row == 0 ) {
//We are drawing a header cell
//If not a normal working day, then use "do not work today" color
if ( workingDay ) {
cellTextColor = palette().color(QPalette::WindowText);
} else {
KColorScheme colorScheme(palette().currentColorGroup(), KColorScheme::Window);
cellTextColor = colorScheme.foreground(KColorScheme::NegativeText).color();
}
cellBackgroundColor = palette().color(QPalette::Window);
//Set the text to the short day name and bold it
cellFont.setBold( true );
cellText = calendar()->weekDayName( cellWeekDay, KCalendarSystem::ShortDayName );
} else {
//We are drawing a day cell
//Calculate the date the cell represents
//Copy current date to get same calendar system & locale
KLocalizedDate cellDate = d->m_date;
cellDate = dateFromPos( pos );
bool validDay = cellDate.isValid();
// Draw the day number in the cell, if the date is not valid then we don't want to show it
if ( validDay ) {
cellText = cellDate.formatDate( KLocale::Day, KLocale::ShortNumber );
} else {
cellText = "";
}
if( ! validDay || cellDate.month() != d->m_date.month() ) {
// we are either
// ° painting an invalid day
// ° painting a day of the previous month or
// ° painting a day of the following month or
cellBackgroundColor = palette().color(backgroundRole());
cellTextColor = colorScheme.foreground(KColorScheme::InactiveText).color();
} else {
//Paint a day of the current month
// Background Colour priorities will be (high-to-low):
// * Selected Day Background Colour
// * Customized Day Background Colour
// * Normal Day Background Colour
// Background Shape priorities will be (high-to-low):
// * Customized Day Shape
// * Normal Day Shape
// Text Colour priorities will be (high-to-low):
// * Customized Day Colour
// * Day of Pray Colour (Red letter)
// * Selected Day Colour
// * Normal Day Colour
//Determine various characteristics of the cell date
bool selectedDay = ( cellDate == date() );
bool currentDay = ( cellDate == QDate::currentDate() );
bool dayOfPray = ( cellDate.dayOfWeek() == calendar()->locale()->weekDayOfPray() );
bool customDay = ( d->m_useCustomColors && d->m_customPaintingModes.contains(cellDate.toJulianDay()) );
//Default values for a normal cell
cellBackgroundColor = palette().color( backgroundRole() );
cellTextColor = palette().color( foregroundRole() );
// If we are drawing the current date, then draw it bold and active
if ( currentDay ) {
cellFont.setBold( true );
cellTextColor = colorScheme.foreground(KColorScheme::ActiveText).color();
}
// if we are drawing the day cell currently selected in the table
if ( selectedDay ) {
// set the background to highlighted
cellBackgroundColor = palette().color( QPalette::Highlight );
cellTextColor = palette().color( QPalette::HighlightedText );
}
//If custom colors or shape are required for this date
if ( customDay ) {
KDateTablePrivate::DatePaintingMode * mode = d->m_customPaintingModes[cellDate.toJulianDay()];
if ( mode->bgMode != NoBgMode ) {
cellBackgroundMode = mode->bgMode;
if (!selectedDay) cellBackgroundColor = mode->bgColor;
}
cellTextColor = mode->fgColor;
}
//If the cell day is the day of religious observance, then always color text red unless Custom overrides
if ( ! customDay && dayOfPray ) {
KColorScheme colorScheme(palette().currentColorGroup(),
selectedDay ? KColorScheme::Selection : KColorScheme::View);
cellTextColor = colorScheme.foreground(KColorScheme::NegativeText).color();
}
}
}
//Draw the background
if (row == 0) {
painter->setPen( cellBackgroundColor );
painter->setBrush( cellBackgroundColor );
painter->drawRect( cell );
} else if (cellBackgroundColor != palette().color(backgroundRole()) || pos == d->m_hoveredPos) {
QStyleOptionViewItemV4 opt;
opt.initFrom(this);
opt.rect = cell.toRect();
if (cellBackgroundColor != palette().color(backgroundRole())) {
opt.palette.setBrush(QPalette::Highlight, cellBackgroundColor);
opt.state |= QStyle::State_Selected;
}
if (pos == d->m_hoveredPos && opt.state & QStyle::State_Enabled) {
opt.state |= QStyle::State_MouseOver;
} else {
opt.state &= ~QStyle::State_MouseOver;
}
opt.showDecorationSelected = true;
opt.viewItemPosition = QStyleOptionViewItemV4::OnlyOne;
style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, this);
}
//Draw the text
painter->setPen( cellTextColor );
painter->setFont( cellFont );
painter->drawText( cell, Qt::AlignCenter, cellText, &cell );
//Draw the base line
if (row == 0) {
painter->setPen( palette().color(foregroundRole()) );
painter->drawLine( QPointF( 0, h ), QPointF( w, h ) );
}
// If the day cell we just drew is bigger than the current max cell sizes,
// then adjust the max to the current cell
if ( cell.width() > d->m_maxCell.width() ) d->m_maxCell.setWidth( cell.width() );
if ( cell.height() > d->m_maxCell.height() ) d->m_maxCell.setHeight( cell.height() );
}
void KDateTable::KDateTablePrivate::nextMonth()
{
// setDate does validity checking for us
q->setDate( m_date.addMonths( 1 ).date() );
}
void KDateTable::KDateTablePrivate::previousMonth()
{
// setDate does validity checking for us
q->setDate( m_date.addMonths( -1 ).date() );
}
void KDateTable::KDateTablePrivate::beginningOfMonth()
{
// setDate does validity checking for us
q->setDate( m_date.firstDayOfMonth().date() );
}
void KDateTable::KDateTablePrivate::endOfMonth()
{
// setDate does validity checking for us
q->setDate( m_date.lastDayOfMonth().date() );
}
// JPL Do these make the assumption that first day of week is weekday 1? As it may not be.
void KDateTable::KDateTablePrivate::beginningOfWeek()
{
// setDate does validity checking for us
q->setDate( m_date.addDays( 1 - m_date.dayOfWeek() ).date() );
}
// JPL Do these make the assumption that first day of week is weekday 1? As it may not be.
void KDateTable::KDateTablePrivate::endOfWeek()
{
// setDate does validity checking for us
q->setDate( m_date.addDays( m_date.daysInWeek() - m_date.dayOfWeek() ).date() );
}
void KDateTable::keyPressEvent( QKeyEvent *e )
{
switch( e->key() ) {
case Qt::Key_Up:
// setDate does validity checking for us
setDate( d->m_date.addDays( - d->m_numDayColumns ).date() );
break;
case Qt::Key_Down:
// setDate does validity checking for us
setDate( d->m_date.addDays( d->m_numDayColumns ).date() );
break;
case Qt::Key_Left:
// setDate does validity checking for us
setDate( d->m_date.addDays( -1 ).date() );
break;
case Qt::Key_Right:
// setDate does validity checking for us
setDate( d->m_date.addDays( 1 ).date() );
break;
case Qt::Key_Minus:
// setDate does validity checking for us
setDate( d->m_date.addDays( -1 ).date() );
break;
case Qt::Key_Plus:
// setDate does validity checking for us
setDate( d->m_date.addDays( 1 ).date() );
break;
case Qt::Key_N:
// setDate does validity checking for us
setDate( QDate::currentDate() );
break;
case Qt::Key_Return:
case Qt::Key_Enter:
emit tableClicked();
break;
case Qt::Key_Control:
case Qt::Key_Alt:
case Qt::Key_Meta:
case Qt::Key_Shift:
// Don't beep for modifiers
break;
default:
if ( !e->modifiers() ) { // hm
KNotification::beep();
}
}
}
void KDateTable::setFontSize( int size )
{
QFontMetricsF metrics( fontMetrics() );
QRectF rect;
// ----- store rectangles:
d->fontsize = size;
// ----- find largest day name:
d->m_maxCell.setWidth( 0 );
d->m_maxCell.setHeight( 0 );
for( int weekday = 1; weekday <= d->m_date.daysInWeek(); ++weekday ) {
rect = metrics.boundingRect( calendar()->weekDayName( weekday, KCalendarSystem::ShortDayName ) );
d->m_maxCell.setWidth( qMax( d->m_maxCell.width(), rect.width() ) );
d->m_maxCell.setHeight( qMax( d->m_maxCell.height(), rect.height() ) );
}
// ----- compare with a real wide number and add some space:
rect = metrics.boundingRect( QLatin1String( "88" ) );
d->m_maxCell.setWidth( qMax( d->m_maxCell.width() + 2, rect.width() ) );
d->m_maxCell.setHeight( qMax( d->m_maxCell.height() + 4, rect.height() ) );
}
void KDateTable::wheelEvent ( QWheelEvent * e )
{
setDate( d->m_date.addMonths( -( int )( e->delta() / 120 ) ).date() );
e->accept();
}
bool KDateTable::event(QEvent *ev)
{
switch (ev->type()) {
case QEvent::HoverMove:
{
QHoverEvent *e = static_cast<QHoverEvent *>(ev);
const int row = e->pos().y() * d->m_numWeekRows / height();
int col;
if ( layoutDirection() == Qt::RightToLeft ) {
col = d->m_numDayColumns - ( e->pos().x() * d->m_numDayColumns / width() ) - 1;
} else {
col = e->pos().x() * d->m_numDayColumns / width();
}
const int pos = row < 1 ? -1 : (d->m_numDayColumns * (row - 1)) + col;
if (pos != d->m_hoveredPos) {
d->m_hoveredPos = pos;
update();
}
break;
}
case QEvent::HoverLeave:
if (d->m_hoveredPos != -1) {
d->m_hoveredPos = -1;
update();
}
break;
default:
break;
}
return QWidget::event(ev);
}
void KDateTable::mousePressEvent( QMouseEvent *e )
{
if( e->type() != QEvent::MouseButtonPress ) { // the KDatePicker only reacts on mouse press events:
return;
}
if( !isEnabled() ) {
KNotification::beep();
return;
}
int row, col, pos, temp;
QPoint mouseCoord = e->pos();
row = mouseCoord.y() * d->m_numWeekRows / height();
if ( layoutDirection() == Qt::RightToLeft ) {
col = d->m_numDayColumns - ( mouseCoord.x() * d->m_numDayColumns / width() ) - 1;
} else {
col = mouseCoord.x() * d->m_numDayColumns / width();
}
if( row < 1 || col < 0 ) { // the user clicked on the frame of the table
return;
}
// Rows and columns are zero indexed. The (row - 1) below is to avoid counting
// the row with the days of the week in the calculation.
// old selected date:
temp = posFromDate( date() );
// new position and date
pos = ( d->m_numDayColumns * ( row - 1 ) ) + col;
QDate clickedDate = dateFromPos( pos );
// set the new date. If it is in the previous or next month, the month will
// automatically be changed, no need to do that manually...
// validity checking done inside setDate
setDate( clickedDate );
// This could be optimized to only call update over the regions
// of old and new cell, but 99% of times there is also a call to
// setDate that already calls update() so no need to optimize that
// much here
update();
emit tableClicked();
if ( e->button() == Qt::RightButton && d->m_popupMenuEnabled ) {
KMenu * menu = new KMenu();
menu->addTitle( d->m_date.formatDate() );
emit aboutToShowContextMenu( menu, clickedDate );
menu->popup( e->globalPos() );
}
}
void KDateTable::KDateTablePrivate::setDate( const QDate& date )
{
m_date.setDate( date );
m_refDate = date;
m_weekDayFirstOfMonth = m_date.firstDayOfMonth().dayOfWeek();
m_numDaysThisMonth = m_date.daysInMonth();
m_numDayColumns = m_date.daysInWeek();
}
bool KDateTable::setDate( const QDate& toDate )
{
if ( !calendar()->isValid( toDate ) ) {
return false;
}
if ( toDate == date() ) {
return true;
}
QDate oldDate = date();
d->setDate( toDate );
emit( dateChanged( date(), oldDate ) );
emit( dateChanged( date() ) );
update();
return true;
}
const QDate &KDateTable::date() const
{
return d->m_refDate;
}
const KCalendarSystem *KDateTable::calendar() const
{
return d->m_date.calendar();
}
bool KDateTable::setCalendar( KCalendarSystem *newCalendar )
{
QDate oldDate = date();
d->m_date = KLocalizedDate( oldDate, newCalendar );
return setDate( oldDate );
}
bool KDateTable::setCalendar( const QString &newCalendarType )
{
return setCalendarSystem( KCalendarSystem::calendarSystem( newCalendarType ) );
}
bool KDateTable::setCalendarSystem( KLocale::CalendarSystem newCalendarSystem )
{
d->m_date.setCalendarSystem( newCalendarSystem );
return true;
}
void KDateTable::focusInEvent( QFocusEvent *e )
{
QWidget::focusInEvent( e );
}
void KDateTable::focusOutEvent( QFocusEvent *e )
{
QWidget::focusOutEvent( e );
}
QSize KDateTable::sizeHint() const
{
if( d->m_maxCell.height() > 0 && d->m_maxCell.width() > 0 ) {
return QSize( qRound( d->m_maxCell.width() * d->m_numDayColumns ),
( qRound( d->m_maxCell.height() + 2 ) * d->m_numWeekRows ) );
} else {
kDebug() << "KDateTable::sizeHint: obscure failure - " << endl;
return QSize( -1, -1 );
}
}
void KDateTable::setPopupMenuEnabled( bool enable )
{
d->m_popupMenuEnabled = enable;
}
bool KDateTable::popupMenuEnabled() const
{
return d->m_popupMenuEnabled;
}
void KDateTable::setCustomDatePainting( const QDate &date, const QColor &fgColor, BackgroundMode bgMode, const QColor &bgColor )
{
if ( !fgColor.isValid() ) {
unsetCustomDatePainting( date );
return;
}
KDateTablePrivate::DatePaintingMode *mode = new KDateTablePrivate::DatePaintingMode;
mode->bgMode = bgMode;
mode->fgColor = fgColor;
mode->bgColor = bgColor;
d->m_customPaintingModes.insert( date.toJulianDay(), mode );
d->m_useCustomColors = true;
update();
}
void KDateTable::unsetCustomDatePainting( const QDate &date )
{
d->m_customPaintingModes.remove( date.toJulianDay() );
if ( d->m_customPaintingModes.isEmpty() ) d->m_useCustomColors = false;
update();
}
// JPL Shouldn't this be in own file as is used in a couple of places? Or moved to private in KDE5?
KPopupFrame::KPopupFrame( QWidget* parent )
: QFrame( parent, Qt::Popup ), d( new KPopupFramePrivate( this ) )
{
setFrameStyle( QFrame::Box | QFrame::Raised );
setMidLineWidth( 2 );
}
KPopupFrame::~KPopupFrame()
{
delete d;
}
void KPopupFrame::keyPressEvent( QKeyEvent* e )
{
if( e->key() == Qt::Key_Escape ) {
d->result = 0; // rejected
emit leaveModality();
//qApp->exit_loop();
}
}
void KPopupFrame::close( int r )
{
d->result = r;
emit leaveModality();
//qApp->exit_loop();
}
void KPopupFrame::setMainWidget( QWidget *m )
{
d->main = m;
if( d->main ) {
resize( d->main->width() + 2 * frameWidth(), d->main->height() + 2 * frameWidth() );
}
}
void KPopupFrame::resizeEvent( QResizeEvent *e )
{
Q_UNUSED( e );
if( d->main ) {
d->main->setGeometry( frameWidth(), frameWidth(),
width() - 2 * frameWidth(), height() - 2 * frameWidth() );
}
}
void KPopupFrame::popup( const QPoint &pos )
{
// Make sure the whole popup is visible.
QRect desktopGeometry = KGlobalSettings::desktopGeometry( pos );
int x = pos.x();
int y = pos.y();
int w = width();
int h = height();
if ( x + w > desktopGeometry.x() + desktopGeometry.width() ) {
x = desktopGeometry.width() - w;
}
if ( y + h > desktopGeometry.y() + desktopGeometry.height() ) {
y = desktopGeometry.height() - h;
}
if ( x < desktopGeometry.x() ) {
x = 0;
}
if ( y < desktopGeometry.y() ) {
y = 0;
}
// Pop the thingy up.
move( x, y );
show();
d->main->setFocus();
}
int KPopupFrame::exec( const QPoint &pos )
{
popup( pos );
repaint();
d->result = 0; // rejected
QEventLoop eventLoop;
connect( this, SIGNAL( leaveModality() ),
&eventLoop, SLOT( quit() ) );
eventLoop.exec();
hide();
return d->result;
}
int KPopupFrame::exec( int x, int y )
{
return exec( QPoint( x, y ) );
}
#include "moc_kdatetable.cpp"
diff --git a/kdeui/widgets/kdatetable.h b/kdeui/widgets/kdatetable.h
index 7de10fa819..733185d471 100644
--- a/kdeui/widgets/kdatetable.h
+++ b/kdeui/widgets/kdatetable.h
@@ -1,324 +1,324 @@
/* -*- C++ -*-
This file is part of the KDE libraries
Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
(C) 1998-2001 Mirko Boehm (mirko@kde.org)
(C) 2007 John Layt <john@layt.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KDATETABLE_H
#define KDATETABLE_H
#include <kdeui_export.h>
#include <QValidator>
#include <QLineEdit>
#include <QtCore/QDateTime>
#include <klocale.h>
class KMenu;
class KCalendarSystem;
class KColorScheme;
/**
* Frame with popup menu behavior.
* @author Tim Gilman, Mirko Boehm
*/
class KDEUI_EXPORT KPopupFrame : public QFrame
{
Q_OBJECT
protected:
/**
* Catch key press events.
*/
virtual void keyPressEvent( QKeyEvent *e );
public Q_SLOTS:
/**
* Close the popup window. This is called from the main widget, usually.
* @p r is the result returned from exec().
*/
void close( int r );
public:
/**
* The contructor. Creates a dialog without buttons.
*/
KPopupFrame( QWidget *parent = 0 );
/**
* The destructor
*/
~KPopupFrame();
/**
* Set the main widget. You cannot set the main widget from the constructor,
* since it must be a child of the frame itselfes.
* Be careful: the size is set to the main widgets size. It is up to you to
* set the main widgets correct size before setting it as the main
* widget.
*/
void setMainWidget( QWidget* m );
/**
* The resize event. Simply resizes the main widget to the whole
* widgets client size.
*/
virtual void resizeEvent( QResizeEvent *resize );
/**
* Open the popup window at position pos.
*/
void popup( const QPoint &pos );
/**
* Execute the popup window.
*/
int exec( const QPoint &p );
/**
* Execute the popup window.
*/
int exec( int x, int y );
Q_SIGNALS:
void leaveModality();
private:
class KPopupFramePrivate;
friend class KPopupFramePrivate;
KPopupFramePrivate * const d;
Q_DISABLE_COPY( KPopupFrame )
};
/**
* Validates user-entered dates.
*/
class KDEUI_EXPORT KDateValidator : public QValidator
{
public:
KDateValidator( QWidget *parent = 0 );
virtual State validate( QString &text, int &e ) const;
virtual void fixup ( QString &input ) const;
State date( const QString &text, QDate &date ) const;
private:
class KDateValidatorPrivate;
friend class KDateValidatorPrivate;
KDateValidatorPrivate * const d;
};
/**
* Date selection table.
* This is a support class for the KDatePicker class. It just
* draws the calendar table without titles, but could theoretically
* be used as a standalone.
*
* When a date is selected by the user, it emits a signal:
* dateSelected(QDate)
*
* \image html kdatetable.png "KDE Date Selection Table"
*
* @internal
* @author Tim Gilman, Mirko Boehm
*/
class KDEUI_EXPORT KDateTable : public QWidget
{
Q_OBJECT
Q_PROPERTY( QDate date READ date WRITE setDate )
//FIXME Q_PROPERTY( KCalendarSystem calendar READ calendar WRITE setCalendar USER true )
Q_PROPERTY( bool popupMenu READ popupMenuEnabled WRITE setPopupMenuEnabled )
public:
/**
* The constructor.
*/
explicit KDateTable( QWidget* parent = 0 );
/**
* The constructor.
*/
explicit KDateTable( const QDate&, QWidget *parent = 0 );
/**
* The destructor.
*/
~KDateTable();
/**
* Returns a recommended size for the widget.
* To save some time, the size of the largest used cell content is
* calculated in each paintCell() call, since all calculations have
* to be done there anyway. The size is stored in maxCell. The
* sizeHint() simply returns a multiple of maxCell.
*/
virtual QSize sizeHint() const;
/**
* Set the font size of the date table.
*/
void setFontSize( int size );
/**
* Select and display this date.
*/
bool setDate( const QDate &date );
// KDE5 remove the const & from the returned QDate
/**
* @returns the selected date.
*/
const QDate &date() const;
/**
* Returns the currently selected calendar system.
*
* @return a KCalendarSystem object
*/
const KCalendarSystem *calendar() const;
/**
* Changes the calendar system to use. Can use its own local locale if set.
*
* @param calendar the calendar system object to use, defaults to global
*
* @return @c true if the calendar system was successfully set, @c false otherwise
*/
bool setCalendar( KCalendarSystem *calendar = 0 );
/**
* Changes the calendar system to use. Will always use global locale.
*
* @param calendarType the calendar system type to use
*
* @return @c true if the calendar system was successfully set, @c false otherwise
*/
bool setCalendar( const QString &calendarType );
/**
* @since 4.6
*
* Changes the calendar system to use. Will always use global locale.
*
* @param calendarSystem the calendar system to use
* @return @c true if the calendar system was successfully set, @c false otherwise
*/
bool setCalendarSystem( KLocale::CalendarSystem calendarSystem );
/**
* Enables a popup menu when right clicking on a date.
*
* When it's enabled, this object emits a aboutToShowContextMenu signal
* where you can fill in the menu items.
*/
void setPopupMenuEnabled( bool enable );
/**
* Returns if the popup menu is enabled or not
*/
bool popupMenuEnabled() const;
enum BackgroundMode { NoBgMode = 0, RectangleMode, CircleMode };
/**
* Makes a given date be painted with a given foregroundColor, and background
* (a rectangle, or a circle/ellipse) in a given color.
*/
void setCustomDatePainting( const QDate &date, const QColor &fgColor,
BackgroundMode bgMode = NoBgMode, const QColor &bgColor = QColor() );
/**
* Unsets the custom painting of a date so that the date is painted as usual.
*/
void unsetCustomDatePainting( const QDate &date );
protected:
/**
* calculate the position of the cell in the matrix for the given date.
* The result is the 0-based index.
*/
virtual int posFromDate( const QDate &date );
/**
* calculate the date that is displayed at a given cell in the matrix. pos is the
* 0-based index in the matrix. Inverse function to posForDate().
*/
virtual QDate dateFromPos( int pos );
virtual void paintEvent( QPaintEvent *e );
/**
* React on mouse clicks that select a date.
*/
virtual void mousePressEvent( QMouseEvent *e );
virtual void wheelEvent( QWheelEvent *e );
virtual void keyPressEvent( QKeyEvent *e );
virtual void focusInEvent( QFocusEvent *e );
virtual void focusOutEvent( QFocusEvent *e );
/**
* Cell highlight on mouse hovering
*/
virtual bool event(QEvent *e);
Q_SIGNALS:
/**
* The selected date changed.
*/
void dateChanged( const QDate &date );
/**
* This function behaves essentially like the one above.
* The selected date changed.
* @param cur The current date
* @param old The date before the date was changed
*/
void dateChanged( const QDate &cur, const QDate &old );
/**
* A date has been selected by clicking on the table.
*/
void tableClicked();
/**
* A popup menu for a given date is about to be shown (as when the user
* right clicks on that date and the popup menu is enabled). Connect
* the slot where you fill the menu to this signal.
*/
void aboutToShowContextMenu( KMenu *menu, const QDate &date );
private:
Q_PRIVATE_SLOT( d, void nextMonth() )
Q_PRIVATE_SLOT( d, void previousMonth() )
Q_PRIVATE_SLOT( d, void beginningOfMonth() )
Q_PRIVATE_SLOT( d, void endOfMonth() )
Q_PRIVATE_SLOT( d, void beginningOfWeek() )
Q_PRIVATE_SLOT( d, void endOfWeek() )
private:
class KDateTablePrivate;
friend class KDateTablePrivate;
KDateTablePrivate * const d;
- void init( const QDate &date );
+ void initWidget( const QDate &date );
void initAccels();
void paintCell( QPainter *painter, int row, int col, const KColorScheme &colorScheme );
Q_DISABLE_COPY( KDateTable )
};
#endif // KDATETABLE_H
diff --git a/kdeui/widgets/kdatetimewidget.cpp b/kdeui/widgets/kdatetimewidget.cpp
index 84c2633288..b2544706ba 100644
--- a/kdeui/widgets/kdatetimewidget.cpp
+++ b/kdeui/widgets/kdatetimewidget.cpp
@@ -1,96 +1,96 @@
/* This file is part of the KDE libraries
Copyright (C) 2002 Hans Petter bieker <bieker@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kdatetimewidget.h"
#include <QtCore/QDate>
#include <QLayout>
#include <QTimeEdit>
#include <kdebug.h>
#include "kdatewidget.h"
#include "kdialog.h"
class KDateTimeWidget::KDateTimeWidgetPrivate
{
public:
KDateWidget * dateWidget;
QTimeEdit * timeWidget;
};
KDateTimeWidget::KDateTimeWidget(QWidget * parent)
: QWidget(parent)
, d( new KDateTimeWidgetPrivate )
{
- init();
+ initWidget();
}
KDateTimeWidget::KDateTimeWidget(const QDateTime & datetime,
QWidget * parent)
: QWidget(parent)
, d( new KDateTimeWidgetPrivate )
{
- init();
+ initWidget();
setDateTime(datetime);
}
KDateTimeWidget::~KDateTimeWidget()
{
delete d;
}
-void KDateTimeWidget::init()
+void KDateTimeWidget::initWidget()
{
QHBoxLayout *layout = new QHBoxLayout(this);
layout->setMargin(0);
d->dateWidget = new KDateWidget(this);
d->timeWidget = new QTimeEdit(this);
layout->addWidget( d->dateWidget );
layout->addWidget( d->timeWidget );
connect(d->dateWidget, SIGNAL(changed(QDate)),
SLOT(slotValueChanged()));
connect(d->timeWidget, SIGNAL(timeChanged(const QTime &)),
SLOT(slotValueChanged()));
}
void KDateTimeWidget::setDateTime(const QDateTime & datetime)
{
d->dateWidget->setDate(datetime.date());
d->timeWidget->setTime(datetime.time());
}
QDateTime KDateTimeWidget::dateTime() const
{
return QDateTime(d->dateWidget->date(), d->timeWidget->time());
}
void KDateTimeWidget::slotValueChanged()
{
QDateTime datetime(d->dateWidget->date(),
d->timeWidget->time());
kDebug() << "slotValueChanged(): " << datetime << "\n";
emit valueChanged(datetime);
}
diff --git a/kdeui/widgets/kdatetimewidget.h b/kdeui/widgets/kdatetimewidget.h
index 445164cd48..eecf564190 100644
--- a/kdeui/widgets/kdatetimewidget.h
+++ b/kdeui/widgets/kdatetimewidget.h
@@ -1,91 +1,91 @@
/* This file is part of the KDE libraries
Copyright (C) 2002 Hans Petter bieker <bieker@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KDATETIMEWIDGET
#define KDATETIMEWIDGET
#include <kdeui_export.h>
#include <QWidget>
class QDateTime;
/**
* @short A combination of a date and a time selection widget.
*
* This widget can be used to display or allow user selection of date and time.
*
* @see KDateWidget
*
* \image html kdatetimewidget.png "KDE Date Time Widget"
*
* @author Hans Petter Bieker <bieker@kde.org>
*/
class KDEUI_EXPORT KDateTimeWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY( QDateTime dateTime READ dateTime WRITE setDateTime NOTIFY valueChanged USER true )
public:
/**
* Constructs a date and time selection widget.
*/
explicit KDateTimeWidget(QWidget * parent = 0);
/**
* Constructs a date and time selection widget with the initial date and
* time set to @p datetime.
*/
explicit KDateTimeWidget(const QDateTime & datetime,
QWidget * parent = 0);
/**
* Destructs the date and time selection widget.
*/
virtual ~KDateTimeWidget();
/**
* Returns the currently selected date and time.
*/
QDateTime dateTime() const;
public Q_SLOTS:
/**
* Changes the selected date and time to @p datetime.
*/
void setDateTime(const QDateTime & datetime);
Q_SIGNALS:
/**
* Emitted whenever the date or time of the widget
* is changed, either with setDateTime() or via user selection.
*/
void valueChanged(const QDateTime & datetime);
private:
- void init();
+ void initWidget();
private Q_SLOTS:
void slotValueChanged();
private:
class KDateTimeWidgetPrivate;
KDateTimeWidgetPrivate * const d;
};
#endif
diff --git a/kdeui/widgets/kdatewidget.cpp b/kdeui/widgets/kdatewidget.cpp
index 98a77c86b9..f6c7c79930 100644
--- a/kdeui/widgets/kdatewidget.cpp
+++ b/kdeui/widgets/kdatewidget.cpp
@@ -1,184 +1,184 @@
/* This file is part of the KDE libraries
Copyright (C) 2001 Waldo Bastian (bastian@kde.org)
Copyright 2007, 2010 John Layt <john@layt.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kdatewidget.h"
#include <QtCore/QDate>
#include <QLayout>
#include <QLineEdit>
#include <QDoubleSpinBox>
#include <kcombobox.h>
#include "kcalendarsystem.h"
#include "klocalizeddate.h"
#include "kdialog.h"
#include "kglobal.h"
class KDateWidgetSpinBox : public QSpinBox
{
public:
KDateWidgetSpinBox( int min, int max, QWidget *parent ) : QSpinBox( parent )
{
setRange( qMin( min, max ), qMax( min, max ) );
setSingleStep( 1 );
lineEdit()->setAlignment( Qt::AlignRight );
}
};
class KDateWidget::KDateWidgetPrivate
{
public:
KDateWidgetSpinBox *m_day;
KComboBox *m_month;
KDateWidgetSpinBox *m_year;
KLocalizedDate m_date;
// Need to keep a QDate copy as the "const QDate &date() const;" method returns a reference
// and returning m_date.date() creates a temporary leading to crashes. Doh!
QDate m_refDate;
};
KDateWidget::KDateWidget( QWidget *parent ) : QWidget( parent ), d( new KDateWidgetPrivate )
{
- init( QDate::currentDate() );
+ initWidget( QDate::currentDate() );
}
KDateWidget::KDateWidget( const QDate &date, QWidget *parent )
: QWidget( parent ), d( new KDateWidgetPrivate )
{
- init( date );
+ initWidget( date );
}
-void KDateWidget::init( const QDate &date )
+void KDateWidget::initWidget( const QDate &date )
{
QHBoxLayout *layout = new QHBoxLayout( this );
layout->setMargin( 0 );
layout->setSpacing( KDialog::spacingHint() );
d->m_day = new KDateWidgetSpinBox( 1, 31, this );
d->m_month = new KComboBox( this );
d->m_year = new KDateWidgetSpinBox( calendar()->year( calendar()->earliestValidDate() ),
calendar()->year( calendar()->latestValidDate() ), this );
layout->addWidget( d->m_day );
layout->addWidget( d->m_month );
layout->addWidget( d->m_year );
connect( d->m_day, SIGNAL( valueChanged( int ) ), this, SLOT( slotDateChanged() ) );
connect( d->m_month, SIGNAL( activated( int ) ), this, SLOT( slotDateChanged() ) );
connect( d->m_year, SIGNAL( valueChanged( int ) ), this, SLOT( slotDateChanged() ) );
setFocusProxy(d->m_day);
setFocusPolicy(Qt::StrongFocus);
if ( calendar()->isValid( date ) ) {
setDate( date );
} else {
setDate( QDate::currentDate() );
}
}
KDateWidget::~KDateWidget()
{
delete d;
}
bool KDateWidget::setDate( const QDate &date )
{
if ( calendar()->isValid( date ) ) {
bool dayBlocked = d->m_day->blockSignals( true );
bool monthBlocked = d->m_month->blockSignals( true );
bool yearBlocked = d->m_year->blockSignals( true );
d->m_date.setDate( date );
d->m_refDate = date;
d->m_day->setMaximum( d->m_date.daysInMonth() );
d->m_day->setValue( d->m_date.day() );
d->m_month->clear();
d->m_month->setMaxVisibleItems( d->m_date.monthsInYear() );
for ( int m = 1; m <= d->m_date.monthsInYear(); ++m ) {
d->m_month->addItem( calendar()->monthName( m, d->m_date.year() ) );
}
d->m_month->setCurrentIndex( d->m_date.month() - 1 );
d->m_year->setValue( d->m_date.year() );
d->m_day->blockSignals( dayBlocked );
d->m_month->blockSignals( monthBlocked );
d->m_year->blockSignals( yearBlocked );
emit changed( d->m_refDate );
return true;
}
return false;
}
const QDate& KDateWidget::date() const
{
return d->m_refDate;
}
void KDateWidget::slotDateChanged( )
{
KLocalizedDate date;
int y, m, day;
y = d->m_year->value();
y = qMin( qMax( y, calendar()->year( calendar()->earliestValidDate() ) ),
calendar()->year( calendar()->latestValidDate() ) );
date.setDate( y, 1, 1 );
m = d->m_month->currentIndex() + 1;
m = qMin( qMax( m, 1 ), date.monthsInYear() );
date.setDate( y, m, 1 );
day = d->m_day->value();
day = qMin( qMax( day, 1 ), date.daysInMonth() );
date.setDate( y, m, day );
setDate( date.date() );
}
const KCalendarSystem *KDateWidget::calendar() const
{
return d->m_date.calendar();
}
bool KDateWidget::setCalendar( KCalendarSystem *newCalendar )
{
QDate oldDate = date();
d->m_date = KLocalizedDate( oldDate, newCalendar );
return setDate( oldDate );
}
bool KDateWidget::setCalendar( const QString &newCalendarType )
{
return setCalendarSystem( KCalendarSystem::calendarSystem( newCalendarType ) );
}
bool KDateWidget::setCalendarSystem( KLocale::CalendarSystem newCalendarSystem )
{
d->m_date.setCalendarSystem( newCalendarSystem );
return true;
}
diff --git a/kdeui/widgets/kdatewidget.h b/kdeui/widgets/kdatewidget.h
index 603014c788..715a7138a9 100644
--- a/kdeui/widgets/kdatewidget.h
+++ b/kdeui/widgets/kdatewidget.h
@@ -1,133 +1,133 @@
/* This file is part of the KDE libraries
Copyright (C) 2001 Waldo Bastian (bastian@kde.org)
Copyright (c) 2007 John Layt <john@layt.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KDATEWIDGET_H
#define KDATEWIDGET_H
#include <kdeui_export.h>
#include <QWidget>
#include "klocale.h"
class KCalendarSystem;
class QDate;
/**
* @short A date selection widget.
*
* This widget can be used to display or allow user selection of a date.
*
* \image html kdatewidget.png "KDE Date Widget"
*
* @see KDatePicker
*
* @author Waldo Bastian <bastian@kde.org>, John Layt <john@layt.net>
*/
class KDEUI_EXPORT KDateWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY( QDate date READ date WRITE setDate NOTIFY changed USER true )
//FIXME Q_PROPERTY( KCalendarSystem calendar READ calendar WRITE setCalendar USER true )
public:
/**
* Constructs a date selection widget.
*/
explicit KDateWidget( QWidget *parent = 0 );
/**
* Constructs a date selection widget with the initial date set to @p date.
*/
explicit KDateWidget( const QDate &date, QWidget *parent = 0 );
/**
* Destructs the date selection widget.
*/
virtual ~KDateWidget();
// KDE5 remove const &
/**
* Returns the currently selected date.
*/
const QDate& date() const;
/**
* Changes the selected date to @p date.
*
* @return @c true if the date was successfully set, @c false otherwise
*/
bool setDate( const QDate &date );
/**
* Returns the currently selected calendar system.
*
* @return a KCalendarSystem object
*/
const KCalendarSystem *calendar() const;
/**
* Changes the calendar system to use. Can use its own local locale if set.
*
* @param calendar the calendar system object to use, defaults to global
*
* @return @c true if the calendar system was successfully set, @c false otherwise
*/
bool setCalendar( KCalendarSystem *calendar = 0 );
/**
* Changes the calendar system to use. Will always use global locale.
*
* @param calendarType the calendar system type to use
*
* @return @c true if the calendar system was successfully set, @c false otherwise
*/
bool setCalendar( const QString &calendarType );
/**
* @since 4.6
*
* Changes the calendar system to use. Will always use global locale.
*
* @param calendarSystem the calendar system to use
* @return @c true if the calendar system was successfully set, @c false otherwise
*/
bool setCalendarSystem( KLocale::CalendarSystem calendarSystem );
Q_SIGNALS:
/**
* Emitted whenever the date of the widget
* is changed, either with setDate() or via user selection.
*/
void changed( const QDate& date );
protected:
- void init( const QDate& date );
+ void initWidget( const QDate& date );
protected Q_SLOTS:
void slotDateChanged();
private:
class KDateWidgetPrivate;
KDateWidgetPrivate * const d;
};
#endif // KDATEWIDGET_H
diff --git a/kdeui/widgets/khistorycombobox.cpp b/kdeui/widgets/khistorycombobox.cpp
index 6f042cc380..032285fe41 100644
--- a/kdeui/widgets/khistorycombobox.cpp
+++ b/kdeui/widgets/khistorycombobox.cpp
@@ -1,447 +1,447 @@
/* This file is part of the KDE libraries
Copyright (c) 2000,2001 Dawit Alemayehu <adawit@kde.org>
Copyright (c) 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
Copyright (c) 2000 Stefan Schimanski <1Stein@gmx.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License (LGPL) as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "khistorycombobox.h"
#include <QAbstractItemView>
#include <QApplication>
#include <QKeyEvent>
#include <QMenu>
#include <QWheelEvent>
#include <klocale.h>
#include <knotification.h>
#include <kpixmapprovider.h>
#include <kstandardshortcut.h>
#include <kicontheme.h>
#include <kicon.h>
#include <kdebug.h>
class KHistoryComboBox::Private
{
public:
Private(KHistoryComboBox *q): q(q), myPixProvider(0) {}
KHistoryComboBox *q;
/**
* The current position (index) in the combobox, used for Up and Down
*/
int myIterateIndex;
/**
* The text typed before Up or Down was pressed.
*/
QString myText;
/**
* Indicates that the user at least once rotated Up through the entire list
* Needed to allow going back after rotation.
*/
bool myRotated;
KPixmapProvider *myPixProvider;
};
// we are always read-write
KHistoryComboBox::KHistoryComboBox( QWidget *parent )
: KComboBox( true, parent ), d(new Private(this))
{
- init( true ); // using completion
+ initWidget( true ); // using completion
}
// we are always read-write
KHistoryComboBox::KHistoryComboBox( bool useCompletion,
QWidget *parent )
: KComboBox( true, parent ), d(new Private(this))
{
- init( useCompletion );
+ initWidget( useCompletion );
}
-void KHistoryComboBox::init( bool useCompletion )
+void KHistoryComboBox::initWidget( bool useCompletion )
{
// Set a default history size to something reasonable, Qt sets it to INT_MAX by default
setMaxCount( 50 );
if ( useCompletion )
completionObject()->setOrder( KCompletion::Weighted );
setInsertPolicy( NoInsert );
d->myIterateIndex = -1;
d->myRotated = false;
d->myPixProvider = 0L;
// obey HISTCONTROL setting
QByteArray histControl = qgetenv("HISTCONTROL");
if ( histControl == "ignoredups" || histControl == "ignoreboth" )
setDuplicatesEnabled( false );
connect(this, SIGNAL(aboutToShowContextMenu(QMenu*)), SLOT(addContextMenuItems(QMenu*)));
connect(this, SIGNAL(activated(int)), SLOT(slotReset()));
connect(this, SIGNAL(returnPressed(QString)), SLOT(slotReset()));
// We want slotSimulateActivated to be called _after_ QComboBoxPrivate::_q_returnPressed
// otherwise there's a risk of emitting activated twice (slotSimulateActivated will find
// the item, after some app's slotActivated inserted the item into the combo).
connect(this, SIGNAL(returnPressed(QString)), SLOT(slotSimulateActivated(QString)), Qt::QueuedConnection);
}
KHistoryComboBox::~KHistoryComboBox()
{
delete d->myPixProvider;
delete d;
}
void KHistoryComboBox::setHistoryItems( const QStringList &items )
{
setHistoryItems(items, false);
}
void KHistoryComboBox::setHistoryItems( const QStringList &items,
bool setCompletionList )
{
QStringList insertingItems = items;
KComboBox::clear();
// limit to maxCount()
const int itemCount = insertingItems.count();
const int toRemove = itemCount - maxCount();
if (toRemove >= itemCount) {
insertingItems.clear();
} else {
for (int i = 0; i < toRemove; ++i)
insertingItems.pop_front();
}
insertItems( insertingItems );
if ( setCompletionList && useCompletion() ) {
// we don't have any weighting information here ;(
KCompletion *comp = completionObject();
comp->setOrder( KCompletion::Insertion );
comp->setItems( insertingItems );
comp->setOrder( KCompletion::Weighted );
}
clearEditText();
}
QStringList KHistoryComboBox::historyItems() const
{
QStringList list;
const int itemCount = count();
for ( int i = 0; i < itemCount; ++i )
list.append( itemText( i ) );
return list;
}
bool KHistoryComboBox::useCompletion() const
{
return compObj();
}
void KHistoryComboBox::clearHistory()
{
const QString temp = currentText();
KComboBox::clear();
if ( useCompletion() )
completionObject()->clear();
setEditText( temp );
}
void KHistoryComboBox::addContextMenuItems( QMenu* menu )
{
if ( menu )
{
menu->addSeparator();
QAction* clearHistory = menu->addAction( KIcon("edit-clear-history"), i18n("Clear &History"), this, SLOT( slotClear()));
if (!count())
clearHistory->setEnabled(false);
}
}
void KHistoryComboBox::addToHistory( const QString& item )
{
if ( item.isEmpty() || (count() > 0 && item == itemText(0) )) {
return;
}
bool wasCurrent = false;
// remove all existing items before adding
if ( !duplicatesEnabled() ) {
int i = 0;
int itemCount = count();
while ( i < itemCount ) {
if ( itemText( i ) == item ) {
if ( !wasCurrent )
wasCurrent = ( i == currentIndex() );
removeItem( i );
--itemCount;
} else {
++i;
}
}
}
// now add the item
if ( d->myPixProvider )
insertItem( 0, d->myPixProvider->pixmapFor(item, KIconLoader::SizeSmall), item);
else
insertItem( 0, item );
if ( wasCurrent )
setCurrentIndex( 0 );
const bool useComp = useCompletion();
const int last = count() - 1; // last valid index
const int mc = maxCount();
const int stopAt = qMax(mc, 0);
for (int rmIndex = last; rmIndex >= stopAt; --rmIndex) {
// remove the last item, as long as we are longer than maxCount()
// remove the removed item from the completionObject if it isn't
// anymore available at all in the combobox.
const QString rmItem = itemText( rmIndex );
removeItem( rmIndex );
if ( useComp && !contains( rmItem ) )
completionObject()->removeItem( rmItem );
}
if ( useComp )
completionObject()->addItem( item );
}
bool KHistoryComboBox::removeFromHistory( const QString& item )
{
if ( item.isEmpty() )
return false;
bool removed = false;
const QString temp = currentText();
int i = 0;
int itemCount = count();
while ( i < itemCount ) {
if ( item == itemText( i ) ) {
removed = true;
removeItem( i );
--itemCount;
} else {
++i;
}
}
if ( removed && useCompletion() )
completionObject()->removeItem( item );
setEditText( temp );
return removed;
}
// going up in the history, rotating when reaching QListBox::count()
//
// Note: this differs from QComboBox because "up" means ++index here,
// to simulate the way shell history works (up goes to the most
// recent item). In QComboBox "down" means ++index, to match the popup...
//
void KHistoryComboBox::rotateUp()
{
// save the current text in the lineedit
// (This is also where this differs from standard up/down in QComboBox,
// where a single keypress can make you lose your typed text)
if ( d->myIterateIndex == -1 )
d->myText = currentText();
++d->myIterateIndex;
// skip duplicates/empty items
const int last = count() - 1; // last valid index
const QString currText = currentText();
while ( d->myIterateIndex < last &&
(currText == itemText( d->myIterateIndex ) ||
itemText( d->myIterateIndex ).isEmpty()) )
++d->myIterateIndex;
if ( d->myIterateIndex >= count() ) {
d->myRotated = true;
d->myIterateIndex = -1;
// if the typed text is the same as the first item, skip the first
if ( count() > 0 && d->myText == itemText(0) )
d->myIterateIndex = 0;
setEditText( d->myText );
} else {
setCurrentIndex(d->myIterateIndex);
}
}
// going down in the history, no rotation possible. Last item will be
// the text that was in the lineedit before Up was called.
void KHistoryComboBox::rotateDown()
{
// save the current text in the lineedit
if ( d->myIterateIndex == -1 )
d->myText = currentText();
--d->myIterateIndex;
const QString currText = currentText();
// skip duplicates/empty items
while ( d->myIterateIndex >= 0 &&
(currText == itemText( d->myIterateIndex ) ||
itemText( d->myIterateIndex ).isEmpty()) )
--d->myIterateIndex;
if ( d->myIterateIndex < 0 ) {
if ( d->myRotated && d->myIterateIndex == -2 ) {
d->myRotated = false;
d->myIterateIndex = count() - 1;
setEditText( itemText(d->myIterateIndex) );
}
else { // bottom of history
if ( d->myIterateIndex == -2 ) {
KNotification::event( "Textcompletion: No Match" ,
i18n("No further items in the history."),
QPixmap() , this, KNotification::DefaultEvent);
}
d->myIterateIndex = -1;
if ( currentText() != d->myText )
setEditText( d->myText );
}
} else {
setCurrentIndex(d->myIterateIndex);
}
}
void KHistoryComboBox::keyPressEvent( QKeyEvent *e )
{
int event_key = e->key() | e->modifiers();
if ( KStandardShortcut::rotateUp().contains(event_key) )
rotateUp();
else if ( KStandardShortcut::rotateDown().contains(event_key) )
rotateDown();
else
KComboBox::keyPressEvent( e );
}
void KHistoryComboBox::wheelEvent( QWheelEvent *ev )
{
// Pass to poppable listbox if it's up
QAbstractItemView* const iv = view();
if ( iv && iv->isVisible() )
{
QApplication::sendEvent( iv, ev );
return;
}
// Otherwise make it change the text without emitting activated
if ( ev->delta() > 0 ) {
rotateUp();
} else {
rotateDown();
}
ev->accept();
}
void KHistoryComboBox::slotReset()
{
d->myIterateIndex = -1;
d->myRotated = false;
}
void KHistoryComboBox::setPixmapProvider( KPixmapProvider *prov )
{
if ( d->myPixProvider == prov )
return;
delete d->myPixProvider;
d->myPixProvider = prov;
// re-insert all the items with/without pixmap
// I would prefer to use changeItem(), but that doesn't honor the pixmap
// when using an editable combobox (what we do)
if ( count() > 0 ) {
QStringList items( historyItems() );
clear();
insertItems( items );
}
}
void KHistoryComboBox::insertItems( const QStringList& items )
{
QStringList::ConstIterator it = items.constBegin();
const QStringList::ConstIterator itEnd = items.constEnd();
while ( it != itEnd ) {
const QString item = *it;
if ( !item.isEmpty() ) { // only insert non-empty items
if ( d->myPixProvider )
addItem( d->myPixProvider->pixmapFor(item, KIconLoader::SizeSmall),
item );
else
addItem( item );
}
++it;
}
}
void KHistoryComboBox::slotClear()
{
clearHistory();
emit cleared();
}
void KHistoryComboBox::slotSimulateActivated( const QString& text )
{
/* With the insertion policy NoInsert, which we use by default,
Qt doesn't emit activated on typed text if the item is not already there,
which is perhaps reasonable. Generate the signal ourselves if that's the case.
*/
if ((insertPolicy() == NoInsert && findText(text, Qt::MatchFixedString|Qt::MatchCaseSensitive) == -1)) {
emit activated(text);
}
/*
Qt also doesn't emit it if the box is full, and policy is not
InsertAtCurrent
*/
else if (insertPolicy() != InsertAtCurrent && count() >= maxCount()) {
emit activated(text);
}
}
KPixmapProvider *KHistoryComboBox::pixmapProvider() const
{
return d->myPixProvider;
}
void KHistoryComboBox::reset()
{
slotReset();
}
diff --git a/kdeui/widgets/khistorycombobox.h b/kdeui/widgets/khistorycombobox.h
index a6dfc7ae71..a88ec95144 100644
--- a/kdeui/widgets/khistorycombobox.h
+++ b/kdeui/widgets/khistorycombobox.h
@@ -1,282 +1,282 @@
/* This file is part of the KDE libraries
Copyright (c) 2000,2001 Dawit Alemayehu <adawit@kde.org>
Copyright (c) 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License (LGPL) as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KHistoryComboBoxBOX_H
#define KHistoryComboBoxBOX_H
#include <kcombobox.h>
class KPixmapProvider;
/**
* @short A combobox for offering a history and completion
*
* A combobox which implements a history like a unix shell. You can navigate
* through all the items by using the Up or Down arrows (configurable of
* course). Additionally, weighted completion is available. So you should
* load and save the completion list to preserve the weighting between
* sessions.
*
* KHistoryComboBox obeys the HISTCONTROL environment variable to determine
* whether duplicates in the history should be tolerated in
* addToHistory() or not. During construction of KHistoryComboBox,
* duplicates will be disabled when HISTCONTROL is set to "ignoredups" or
* "ignoreboth". Otherwise, duplicates are enabled by default.
*
* \image html khistorycombobox.png "KDE History Combo Box"
*
* @author Carsten Pfeiffer <pfeiffer@kde.org>
*/
class KDEUI_EXPORT KHistoryComboBox : public KComboBox
{
Q_OBJECT
Q_PROPERTY( QStringList historyItems READ historyItems WRITE setHistoryItems )
public:
/**
* Constructs a "read-write" combobox. A read-only history combobox
* doesn't make much sense, so it is only available as read-write.
* Completion will be used automatically for the items in the combo.
*
* The insertion-policy is set to NoInsert, you have to add the items
* yourself via the slot addToHistory. If you want every item added,
* use
*
* \code
* connect( combo, SIGNAL( activated( const QString& )),
* combo, SLOT( addToHistory( const QString& )));
* \endcode
*
* Use QComboBox::setMaxCount() to limit the history.
*
* @p parent the parent object of this widget.
*/
explicit KHistoryComboBox( QWidget *parent = 0 );
/**
* Same as the previous constructor, but additionally has the option
* to specify whether you want to let KHistoryComboBox handle completion
* or not. If set to @p true, KHistoryComboBox will sync the completion to the
* contents of the combobox.
*/
explicit KHistoryComboBox( bool useCompletion, QWidget *parent = 0 );
/**
* Destructs the combo, the completion-object and the pixmap-provider
*/
~KHistoryComboBox();
/**
* Inserts @p items into the combobox. @p items might get
* truncated if it is longer than maxCount()
*
* @see historyItems
*/
void setHistoryItems( const QStringList &items );
/**
* Inserts @p items into the combobox. @p items might get
* truncated if it is longer than maxCount()
*
* Set @p setCompletionList to true, if you don't have a list of
* completions. This tells KHistoryComboBox to use all the items for the
* completion object as well.
* You won't have the benefit of weighted completion though, so normally
* you should do something like
* \code
* KConfigGroup config(KGlobal::config(), "somegroup");
*
* // load the history and completion list after creating the history combo
* QStringList list;
* list = config.readEntry("Completion list", QStringList());
* combo->completionObject()->setItems(list);
* list = config.readEntry("History list", QStringList());
* combo->setHistoryItems(list);
*
* [...]
*
* // save the history and completion list when the history combo is
* // destroyed
* QStringList list;
* KConfigGroup config(KGlobal::config(), "somegroup");
* list = combo->completionObject()->items();
* config.writeEntry("Completion list", list);
* list = combo->historyItems();
* config.writeEntry("History list", list);
* \endcode
*
* Be sure to use different names for saving with KConfig if you have more
* than one KHistoryComboBox.
*
* Note: When @p setCompletionList is true, the items are inserted into the
* KCompletion object with mode KCompletion::Insertion and the mode is set
* to KCompletion::Weighted afterwards.
*
* @see historyItems
* @see KComboBox::completionObject
* @see KCompletion::setItems
* @see KCompletion::items
*/
void setHistoryItems( const QStringList &items, bool setCompletionList );
/**
* Returns the list of history items. Empty, when this is not a read-write
* combobox.
*
* @see setHistoryItems
*/
QStringList historyItems() const;
/**
* Removes all items named @p item.
*
* @return @p true if at least one item was removed.
*
* @see addToHistory
*/
bool removeFromHistory( const QString& item );
/**
* Sets a pixmap provider, so that items in the combobox can have a pixmap.
* KPixmapProvider is just an abstract class with the one pure virtual
* method KPixmapProvider::pixmapFor(). This method is called whenever
* an item is added to the KHistoryComboBoxBox. Implement it to return your
* own custom pixmaps, or use the KUrlPixmapProvider from libkio,
* which uses KMimeType::pixmapForUrl to resolve icons.
*
* Set @p prov to 0L if you want to disable pixmaps. Default no pixmaps.
*
* @see pixmapProvider
*/
void setPixmapProvider( KPixmapProvider *prov );
/**
* @returns the current pixmap provider.
* @see setPixmapProvider
* @see KPixmapProvider
*/
KPixmapProvider * pixmapProvider() const;
/**
* Resets the current position of the up/down history. Call this
* when you manually call setCurrentItem() or clearEdit().
*/
void reset();
using QComboBox::insertItems;
public Q_SLOTS:
/**
* Adds an item to the end of the history list and to the completion list.
* If maxCount() is reached, the first item of the list will be
* removed.
*
* If the last inserted item is the same as @p item, it will not be
* inserted again.
*
* If duplicatesEnabled() is false, any equal existing item will be
* removed before @p item is added.
*
* Note: By using this method and not the Q and KComboBox insertItem()
* methods, you make sure that the combobox stays in sync with the
* completion. It would be annoying if completion would give an item
* not in the combobox, and vice versa.
*
* @see removeFromHistory
* @see QComboBox::setDuplicatesEnabled
*/
void addToHistory( const QString& item );
/**
* Clears the history and the completion list.
*/
void clearHistory();
Q_SIGNALS:
/**
* Emitted when the history was cleared by the entry in the popup menu.
*/
void cleared();
protected:
/**
* Handling key-events, the shortcuts to rotate the items.
*/
virtual void keyPressEvent( QKeyEvent * );
/**
* Handling wheel-events, to rotate the items.
*/
virtual void wheelEvent( QWheelEvent *ev );
/**
* Inserts @p items into the combo, honoring pixmapProvider()
* Does not update the completionObject.
*
* Note: duplicatesEnabled() is not honored here.
*
* Called from setHistoryItems() and setPixmapProvider()
*/
void insertItems( const QStringList& items );
/**
* @returns if we can modify the completion object or not.
*/
bool useCompletion() const;
private Q_SLOTS:
/**
* Resets the iterate index to -1
*/
void slotReset();
/**
* Called from the popupmenu,
* calls clearHistory() and emits cleared()
*/
void slotClear();
/**
* Appends our own context menu entry.
*/
void addContextMenuItems( QMenu* );
/**
* Used to emit the activated(QString) signal when enter is pressed
*/
void slotSimulateActivated( const QString& );
private:
- void init( bool useCompletion );
+ void initWidget( bool useCompletion );
void rotateUp();
void rotateDown();
private:
class Private;
friend class Private;
Private* const d;
Q_DISABLE_COPY(KHistoryComboBox)
};
#endif
diff --git a/kdeui/widgets/klineedit.cpp b/kdeui/widgets/klineedit.cpp
index b837499f86..caf90dafe8 100644
--- a/kdeui/widgets/klineedit.cpp
+++ b/kdeui/widgets/klineedit.cpp
@@ -1,1882 +1,1882 @@
/* This file is part of the KDE libraries
Copyright (C) 1997 Sven Radej (sven.radej@iname.com)
Copyright (c) 1999 Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com>
Copyright (c) 1999 Preston Brown <pbrown@kde.org>
Re-designed for KDE 2.x by
Copyright (c) 2000, 2001 Dawit Alemayehu <adawit@kde.org>
Copyright (c) 2000, 2001 Carsten Pfeiffer <pfeiffer@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License (LGPL) as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later
version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "klineedit.h"
#include "klineedit_p.h"
#include <kaction.h>
#include <kapplication.h>
#include <kauthorized.h>
#include <kconfig.h>
#include <kconfiggroup.h>
#include <kcursor.h>
#include <kdebug.h>
#include <kcompletionbox.h>
#include <kicontheme.h>
#include <kicon.h>
#include <klocale.h>
#include <kmenu.h>
#include <kstandardaction.h>
#include <kstandardshortcut.h>
#include <QtCore/QTimer>
#include <QClipboard>
#include <QStyleOption>
#include <QToolTip>
class KLineEditStyle;
class KLineEditPrivate
{
public:
KLineEditPrivate(KLineEdit* qq)
: q(qq)
{
completionBox = 0L;
handleURLDrops = true;
grabReturnKeyEvents = false;
userSelection = true;
autoSuggest = false;
disableRestoreSelection = false;
enableSqueezedText = false;
drawClickMsg = false;
enableClickMsg = false;
threeStars = false;
completionRunning = false;
if (!s_initialized) {
KConfigGroup config( KGlobal::config(), "General" );
s_backspacePerformsCompletion = config.readEntry("Backspace performs completion", false);
s_initialized = true;
}
clearButton = 0;
clickInClear = false;
wideEnoughForClear = true;
// i18n: Placeholder text in line edit widgets is the text appearing
// before any user input, briefly explaining to the user what to type
// (e.g. "Enter search pattern").
// By default the text is set in italic, which may not be appropriate
// for some languages and scripts (e.g. for CJK ideographs).
QString metaMsg = i18nc("Italic placeholder text in line edits: 0 no, 1 yes", "1");
italicizePlaceholder = (metaMsg.trimmed() != QString('0'));
}
~KLineEditPrivate()
{
// causes a weird crash in KWord at least, so let Qt delete it for us.
// delete completionBox;
delete style.data();
}
void _k_slotSettingsChanged(int category)
{
Q_UNUSED(category);
if (clearButton) {
clearButton->setAnimationsEnabled(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects);
}
}
void _k_textChanged(const QString &txt)
{
// COMPAT (as documented): emit userTextChanged whenever textChanged is emitted
// KDE5: remove userTextChanged signal, textEdited does the same...
if (!completionRunning && (txt != userText)) {
userText = txt;
#ifndef KDE_NO_DEPRECATED
emit q->userTextChanged(txt);
#endif
}
}
// Call this when a completion operation changes the lineedit text
// "as if it had been edited by the user".
void _k_updateUserText(const QString &txt)
{
if (!completionRunning && (txt != userText)) {
userText = txt;
q->setModified(true);
#ifndef KDE_NO_DEPRECATED
emit q->userTextChanged(txt);
#endif
emit q->textEdited(txt);
emit q->textChanged(txt);
}
}
// This is called when the lineedit is readonly.
// Either from setReadOnly() itself, or when we realize that
// we became readonly and setReadOnly() wasn't called (because it's not virtual)
// Typical case: comboBox->lineEdit()->setReadOnly(true)
void adjustForReadOnly()
{
if (style && style.data()->m_overlap) {
style.data()->m_overlap = 0;
}
}
/**
* Checks whether we should/should not consume a key used as a shortcut.
* This makes it possible to handle shortcuts in the focused widget before any
* window-global QAction is triggered.
*/
bool overrideShortcut(const QKeyEvent* e);
static bool s_initialized;
static bool s_backspacePerformsCompletion; // Configuration option
QColor previousHighlightColor;
QColor previousHighlightedTextColor;
bool userSelection: 1;
bool autoSuggest : 1;
bool disableRestoreSelection: 1;
bool handleURLDrops:1;
bool grabReturnKeyEvents:1;
bool enableSqueezedText:1;
bool completionRunning:1;
int squeezedEnd;
int squeezedStart;
QPalette::ColorRole bgRole;
QString squeezedText;
QString userText;
QString clickMessage;
bool enableClickMsg:1;
bool drawClickMsg:1;
bool threeStars:1;
bool possibleTripleClick :1; // set in mousePressEvent, deleted in tripleClickTimeout
bool clickInClear:1;
bool wideEnoughForClear:1;
KLineEditButton *clearButton;
QWeakPointer<KLineEditStyle> style;
QString lastStyleClass;
KCompletionBox *completionBox;
bool italicizePlaceholder:1;
QAction *noCompletionAction, *shellCompletionAction, *autoCompletionAction, *popupCompletionAction, *shortAutoCompletionAction, *popupAutoCompletionAction, *defaultAction;
QMap<KGlobalSettings::Completion, bool> disableCompletionMap;
KLineEdit* q;
};
QStyle *KLineEditStyle::style() const
{
if (m_subStyle) {
return m_subStyle.data();
}
return KdeUiProxyStyle::style();
}
QRect KLineEditStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
{
if (element == SE_LineEditContents) {
KLineEditStyle *unconstThis = const_cast<KLineEditStyle *>(this);
if (m_sentinel) {
// we are recursing: we're wrapping a style that wraps us!
unconstThis->m_subStyle.clear();
}
unconstThis->m_sentinel = true;
QStyle *s = m_subStyle ? m_subStyle.data() : style();
QRect rect = s->subElementRect(SE_LineEditContents, option, widget);
unconstThis->m_sentinel = false;
if (option->direction == Qt::LeftToRight) {
return rect.adjusted(0, 0, -m_overlap, 0);
} else {
return rect.adjusted(m_overlap, 0, 0, 0);
}
}
return KdeUiProxyStyle::subElementRect(element, option, widget);
}
bool KLineEditPrivate::s_backspacePerformsCompletion = false;
bool KLineEditPrivate::s_initialized = false;
KLineEdit::KLineEdit( const QString &string, QWidget *parent )
: QLineEdit( string, parent ), d(new KLineEditPrivate(this))
{
- init();
+ initWidget();
}
KLineEdit::KLineEdit( QWidget *parent )
: QLineEdit( parent ), d(new KLineEditPrivate(this))
{
- init();
+ initWidget();
}
KLineEdit::~KLineEdit ()
{
delete d;
}
-void KLineEdit::init()
+void KLineEdit::initWidget()
{
d->possibleTripleClick = false;
d->bgRole = backgroundRole();
// Enable the context menu by default.
QLineEdit::setContextMenuPolicy( Qt::DefaultContextMenu );
KCursor::setAutoHideCursor( this, true, true );
KGlobalSettings::Completion mode = completionMode();
d->autoSuggest = (mode == KGlobalSettings::CompletionMan ||
mode == KGlobalSettings::CompletionPopupAuto ||
mode == KGlobalSettings::CompletionAuto);
connect( this, SIGNAL(selectionChanged()), this, SLOT(slotRestoreSelectionColors()));
connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)), this, SLOT(_k_slotSettingsChanged(int)));
const QPalette p = palette();
if ( !d->previousHighlightedTextColor.isValid() )
d->previousHighlightedTextColor=p.color(QPalette::Normal,QPalette::HighlightedText);
if ( !d->previousHighlightColor.isValid() )
d->previousHighlightColor=p.color(QPalette::Normal,QPalette::Highlight);
d->style = new KLineEditStyle(this);
setStyle(d->style.data());
connect(this, SIGNAL(textChanged(QString)), this, SLOT(_k_textChanged(QString)));
}
QString KLineEdit::clickMessage() const
{
return d->clickMessage;
}
void KLineEdit::setClearButtonShown(bool show)
{
if (show) {
if (d->clearButton) {
return;
}
d->clearButton = new KLineEditButton(this);
d->clearButton->setObjectName("KLineEditButton");
d->clearButton->setCursor( Qt::ArrowCursor );
d->clearButton->setToolTip( i18nc( "@action:button Clear current text in the line edit", "Clear text" ) );
updateClearButtonIcon(text());
updateClearButton();
connect(this, SIGNAL(textChanged(QString)), this, SLOT(updateClearButtonIcon(QString)));
} else {
disconnect(this, SIGNAL(textChanged(QString)), this, SLOT(updateClearButtonIcon(QString)));
delete d->clearButton;
d->clearButton = 0;
d->clickInClear = false;
if (d->style) {
d->style.data()->m_overlap = 0;
}
}
}
bool KLineEdit::isClearButtonShown() const
{
return d->clearButton != 0;
}
QSize KLineEdit::clearButtonUsedSize() const
{
QSize s;
if (d->clearButton) {
const int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this);
s = d->clearButton->sizeHint();
s.rwidth() += frameWidth;
}
return s;
}
// Decides whether to show or hide the icon; called when the text changes
void KLineEdit::updateClearButtonIcon(const QString& text)
{
if (!d->clearButton) {
return;
}
if (isReadOnly()) {
d->adjustForReadOnly();
return;
}
// set proper icon if necessary
if (d->clearButton->pixmap().isNull()) {
const int clearButtonState = KIconLoader::DefaultState;
if (layoutDirection() == Qt::LeftToRight) {
d->clearButton->setPixmap(SmallIcon("edit-clear-locationbar-rtl", 0, clearButtonState));
} else {
d->clearButton->setPixmap(SmallIcon("edit-clear-locationbar-ltr", 0, clearButtonState));
}
}
// trigger animation
if (d->wideEnoughForClear && text.length() > 0) {
d->clearButton->animateVisible(true);
} else {
d->clearButton->animateVisible(false);
}
}
// Determine geometry of clear button. Called initially, and on resizeEvent.
void KLineEdit::updateClearButton()
{
if (!d->clearButton) {
return;
}
if (isReadOnly()) {
d->adjustForReadOnly();
return;
}
const QSize geom = size();
const int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth,0,this);
const int buttonWidth = d->clearButton->sizeHint().width();
const QSize newButtonSize(buttonWidth, geom.height());
const QFontMetrics fm(font());
const int em = fm.width("m");
// make sure we have enough room for the clear button
// no point in showing it if we can't also see a few characters as well
const bool wideEnough = geom.width() > 4 * em + buttonWidth + frameWidth;
if (newButtonSize != d->clearButton->size()) {
d->clearButton->resize(newButtonSize);
}
if (d->style) {
d->style.data()->m_overlap = wideEnough ? buttonWidth + frameWidth : 0;
}
if (layoutDirection() == Qt::LeftToRight ) {
d->clearButton->move(geom.width() - frameWidth - buttonWidth - 1, 0);
} else {
d->clearButton->move(frameWidth + 1, 0);
}
if (wideEnough != d->wideEnoughForClear) {
// we may (or may not) have been showing the button, but now our
// positiong on that matter has shifted, so let's ensure that it
// is properly visible (or not)
d->wideEnoughForClear = wideEnough;
updateClearButtonIcon(text());
}
}
void KLineEdit::setCompletionMode( KGlobalSettings::Completion mode )
{
KGlobalSettings::Completion oldMode = completionMode();
if ( oldMode != mode && (oldMode == KGlobalSettings::CompletionPopup ||
oldMode == KGlobalSettings::CompletionPopupAuto ) &&
d->completionBox && d->completionBox->isVisible() )
d->completionBox->hide();
// If the widgets echo mode is not Normal, no completion
// feature will be enabled even if one is requested.
if ( echoMode() != QLineEdit::Normal )
mode = KGlobalSettings::CompletionNone; // Override the request.
if ( kapp && !KAuthorized::authorize("lineedit_text_completion") )
mode = KGlobalSettings::CompletionNone;
if ( mode == KGlobalSettings::CompletionPopupAuto ||
mode == KGlobalSettings::CompletionAuto ||
mode == KGlobalSettings::CompletionMan )
d->autoSuggest = true;
else
d->autoSuggest = false;
KCompletionBase::setCompletionMode( mode );
}
void KLineEdit::setCompletionModeDisabled( KGlobalSettings::Completion mode, bool disable )
{
d->disableCompletionMap[ mode ] = disable;
}
void KLineEdit::setCompletedText( const QString& t, bool marked )
{
if ( !d->autoSuggest )
return;
const QString txt = text();
if ( t != txt )
{
setText(t);
if ( marked )
setSelection(t.length(), txt.length()-t.length());
setUserSelection(false);
}
else
setUserSelection(true);
}
void KLineEdit::setCompletedText( const QString& text )
{
KGlobalSettings::Completion mode = completionMode();
const bool marked = ( mode == KGlobalSettings::CompletionAuto ||
mode == KGlobalSettings::CompletionMan ||
mode == KGlobalSettings::CompletionPopup ||
mode == KGlobalSettings::CompletionPopupAuto );
setCompletedText( text, marked );
}
void KLineEdit::rotateText( KCompletionBase::KeyBindingType type )
{
KCompletion* comp = compObj();
if ( comp &&
(type == KCompletionBase::PrevCompletionMatch ||
type == KCompletionBase::NextCompletionMatch ) )
{
QString input;
if (type == KCompletionBase::PrevCompletionMatch)
input = comp->previousMatch();
else
input = comp->nextMatch();
// Skip rotation if previous/next match is null or the same text
if ( input.isEmpty() || input == displayText() )
return;
setCompletedText( input, hasSelectedText() );
}
}
void KLineEdit::makeCompletion( const QString& text )
{
KCompletion *comp = compObj();
KGlobalSettings::Completion mode = completionMode();
if ( !comp || mode == KGlobalSettings::CompletionNone )
return; // No completion object...
const QString match = comp->makeCompletion( text );
if ( mode == KGlobalSettings::CompletionPopup ||
mode == KGlobalSettings::CompletionPopupAuto )
{
if ( match.isEmpty() )
{
if ( d->completionBox )
{
d->completionBox->hide();
d->completionBox->clear();
}
}
else
setCompletedItems( comp->allMatches() );
}
else // Auto, ShortAuto (Man) and Shell
{
// all other completion modes
// If no match or the same match, simply return without completing.
if ( match.isEmpty() || match == text )
return;
if ( mode != KGlobalSettings::CompletionShell )
setUserSelection(false);
if ( d->autoSuggest )
setCompletedText( match );
}
}
void KLineEdit::setReadOnly(bool readOnly)
{
// Do not do anything if nothing changed...
if (readOnly == isReadOnly ()) {
return;
}
QLineEdit::setReadOnly(readOnly);
if (readOnly) {
d->bgRole = backgroundRole();
setBackgroundRole(QPalette::Window);
if (d->enableSqueezedText && d->squeezedText.isEmpty()) {
d->squeezedText = text();
setSqueezedText();
}
if (d->clearButton) {
d->clearButton->animateVisible(false);
d->adjustForReadOnly();
}
} else {
if (!d->squeezedText.isEmpty()) {
setText(d->squeezedText);
d->squeezedText.clear();
}
setBackgroundRole(d->bgRole);
updateClearButton();
}
}
void KLineEdit::setSqueezedText( const QString &text)
{
setSqueezedTextEnabled(true);
setText(text);
}
void KLineEdit::setSqueezedTextEnabled( bool enable )
{
d->enableSqueezedText = enable;
}
bool KLineEdit::isSqueezedTextEnabled() const
{
return d->enableSqueezedText;
}
void KLineEdit::setText( const QString& text )
{
if( d->enableClickMsg )
{
d->drawClickMsg = text.isEmpty();
update();
}
if( d->enableSqueezedText && isReadOnly() )
{
d->squeezedText = text;
setSqueezedText();
return;
}
QLineEdit::setText( text );
}
void KLineEdit::setSqueezedText()
{
d->squeezedStart = 0;
d->squeezedEnd = 0;
const QString fullText = d->squeezedText;
const QFontMetrics fm(fontMetrics());
const int labelWidth = size().width() - 2*style()->pixelMetric(QStyle::PM_DefaultFrameWidth) - 2;
const int textWidth = fm.width(fullText);
if (textWidth > labelWidth)
{
// start with the dots only
QString squeezedText = "...";
int squeezedWidth = fm.width(squeezedText);
// estimate how many letters we can add to the dots on both sides
int letters = fullText.length() * (labelWidth - squeezedWidth) / textWidth / 2;
squeezedText = fullText.left(letters) + "..." + fullText.right(letters);
squeezedWidth = fm.width(squeezedText);
if (squeezedWidth < labelWidth)
{
// we estimated too short
// add letters while text < label
do
{
letters++;
squeezedText = fullText.left(letters) + "..." + fullText.right(letters);
squeezedWidth = fm.width(squeezedText);
} while (squeezedWidth < labelWidth);
letters--;
squeezedText = fullText.left(letters) + "..." + fullText.right(letters);
}
else if (squeezedWidth > labelWidth)
{
// we estimated too long
// remove letters while text > label
do
{
letters--;
squeezedText = fullText.left(letters) + "..." + fullText.right(letters);
squeezedWidth = fm.width(squeezedText);
} while (squeezedWidth > labelWidth);
}
if (letters < 5)
{
// too few letters added -> we give up squeezing
QLineEdit::setText(fullText);
}
else
{
QLineEdit::setText(squeezedText);
d->squeezedStart = letters;
d->squeezedEnd = fullText.length() - letters;
}
setToolTip( fullText );
}
else
{
QLineEdit::setText(fullText);
this->setToolTip( "" );
QToolTip::showText(pos(), QString()); // hide
}
setCursorPosition(0);
}
void KLineEdit::copy() const
{
if( !copySqueezedText(true))
QLineEdit::copy();
}
bool KLineEdit::copySqueezedText(bool clipboard) const
{
if (!d->squeezedText.isEmpty() && d->squeezedStart)
{
KLineEdit *that = const_cast<KLineEdit *>(this);
if (!that->hasSelectedText())
return false;
int start = selectionStart(), end = start + selectedText().length();
if (start >= d->squeezedStart+3)
start = start - 3 - d->squeezedStart + d->squeezedEnd;
else if (start > d->squeezedStart)
start = d->squeezedStart;
if (end >= d->squeezedStart+3)
end = end - 3 - d->squeezedStart + d->squeezedEnd;
else if (end > d->squeezedStart)
end = d->squeezedEnd;
if (start == end)
return false;
QString t = d->squeezedText;
t = t.mid(start, end - start);
disconnect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0);
QApplication::clipboard()->setText( t, clipboard ? QClipboard::Clipboard : QClipboard::Selection );
connect( QApplication::clipboard(), SIGNAL(selectionChanged()), this,
SLOT(_q_clipboardChanged()) );
return true;
}
return false;
}
void KLineEdit::resizeEvent( QResizeEvent * ev )
{
if (!d->squeezedText.isEmpty())
setSqueezedText();
updateClearButton();
QLineEdit::resizeEvent(ev);
}
void KLineEdit::keyPressEvent( QKeyEvent *e )
{
const int key = e->key() | e->modifiers();
if ( KStandardShortcut::copy().contains( key ) )
{
copy();
return;
}
else if ( KStandardShortcut::paste().contains( key ) )
{
// TODO:
// we should restore the original text (not autocompleted), otherwise the paste
// will get into troubles Bug: 134691
if( !isReadOnly() )
paste();
return;
}
else if ( KStandardShortcut::pasteSelection().contains( key ) )
{
QString text = QApplication::clipboard()->text( QClipboard::Selection);
insert( text );
deselect();
return;
}
else if ( KStandardShortcut::cut().contains( key ) )
{
if( !isReadOnly() )
cut();
return;
}
else if ( KStandardShortcut::undo().contains( key ) )
{
if( !isReadOnly() )
undo();
return;
}
else if ( KStandardShortcut::redo().contains( key ) )
{
if( !isReadOnly() )
redo();
return;
}
else if ( KStandardShortcut::deleteWordBack().contains( key ) )
{
cursorWordBackward(true);
if ( hasSelectedText() )
del();
e->accept();
return;
}
else if ( KStandardShortcut::deleteWordForward().contains( key ) )
{
// Workaround for QT bug where
cursorWordForward(true);
if ( hasSelectedText() )
del();
e->accept();
return;
}
else if ( KStandardShortcut::backwardWord().contains( key ) )
{
cursorWordBackward(false);
e->accept();
return;
}
else if ( KStandardShortcut::forwardWord().contains( key ) )
{
cursorWordForward(false);
e->accept();
return;
}
else if ( KStandardShortcut::beginningOfLine().contains( key ) )
{
home(false);
e->accept();
return;
}
else if ( KStandardShortcut::endOfLine().contains( key ) )
{
end(false);
e->accept();
return;
}
// Filter key-events if EchoMode is normal and
// completion mode is not set to CompletionNone
if ( echoMode() == QLineEdit::Normal &&
completionMode() != KGlobalSettings::CompletionNone )
{
if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
const bool trap = (d->completionBox && d->completionBox->isVisible());
const bool stopEvent = (trap || (d->grabReturnKeyEvents &&
(e->modifiers() == Qt::NoButton ||
e->modifiers() == Qt::KeypadModifier)));
if (stopEvent) {
emit QLineEdit::returnPressed();
e->accept();
}
emit returnPressed( displayText() );
if (trap) {
d->completionBox->hide();
deselect();
setCursorPosition(text().length());
}
// Eat the event if the user asked for it, or if a completionbox was visible
if (stopEvent) {
return;
}
}
const KeyBindingMap keys = getKeyBindings();
const KGlobalSettings::Completion mode = completionMode();
const bool noModifier = (e->modifiers() == Qt::NoButton ||
e->modifiers() == Qt::ShiftModifier ||
e->modifiers() == Qt::KeypadModifier);
if ( (mode == KGlobalSettings::CompletionAuto ||
mode == KGlobalSettings::CompletionPopupAuto ||
mode == KGlobalSettings::CompletionMan) && noModifier )
{
if ( !d->userSelection && hasSelectedText() &&
( e->key() == Qt::Key_Right || e->key() == Qt::Key_Left ) &&
e->modifiers()==Qt::NoButton )
{
const QString old_txt = text();
d->disableRestoreSelection = true;
const int start = selectionStart();
deselect();
QLineEdit::keyPressEvent ( e );
const int cPosition=cursorPosition();
setText(old_txt);
// keep cursor at cPosition
setSelection(old_txt.length(), cPosition - old_txt.length());
if (e->key() == Qt::Key_Right && cPosition > start )
{
//the user explicitly accepted the autocompletion
d->_k_updateUserText(text());
}
d->disableRestoreSelection = false;
return;
}
if ( e->key() == Qt::Key_Escape )
{
if (hasSelectedText() && !d->userSelection )
{
del();
setUserSelection(true);
}
// Don't swallow the Escape press event for the case
// of dialogs, which have Escape associated to Cancel
e->ignore();
return;
}
}
if ( (mode == KGlobalSettings::CompletionAuto ||
mode == KGlobalSettings::CompletionMan) && noModifier )
{
const QString keycode = e->text();
if ( !keycode.isEmpty() && (keycode.unicode()->isPrint() ||
e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete ) )
{
const bool hasUserSelection=d->userSelection;
const bool hadSelection=hasSelectedText();
bool cursorNotAtEnd=false;
const int start = selectionStart();
const int cPos = cursorPosition();
// When moving the cursor, we want to keep the autocompletion as an
// autocompletion, so we want to process events at the cursor position
// as if there was no selection. After processing the key event, we
// can set the new autocompletion again.
if ( hadSelection && !hasUserSelection && start>cPos )
{
del();
setCursorPosition(cPos);
cursorNotAtEnd=true;
}
d->disableRestoreSelection = true;
QLineEdit::keyPressEvent ( e );
d->disableRestoreSelection = false;
QString txt = text();
int len = txt.length();
if ( !hasSelectedText() && len /*&& cursorPosition() == len */)
{
if ( e->key() == Qt::Key_Backspace )
{
if ( hadSelection && !hasUserSelection && !cursorNotAtEnd )
{
backspace();
txt = text();
len = txt.length();
}
if (!d->s_backspacePerformsCompletion || !len) {
d->autoSuggest = false;
}
}
if (e->key() == Qt::Key_Delete )
d->autoSuggest=false;
doCompletion(txt);
if( (e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete) )
d->autoSuggest=true;
e->accept();
}
return;
}
}
else if (( mode == KGlobalSettings::CompletionPopup ||
mode == KGlobalSettings::CompletionPopupAuto ) &&
noModifier && !e->text().isEmpty() )
{
const QString old_txt = text();
const bool hasUserSelection=d->userSelection;
const bool hadSelection=hasSelectedText();
bool cursorNotAtEnd=false;
const int start = selectionStart();
const int cPos = cursorPosition();
const QString keycode = e->text();
// When moving the cursor, we want to keep the autocompletion as an
// autocompletion, so we want to process events at the cursor position
// as if there was no selection. After processing the key event, we
// can set the new autocompletion again.
if (hadSelection && !hasUserSelection && start>cPos &&
( (!keycode.isEmpty() && keycode.unicode()->isPrint()) ||
e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete ) )
{
del();
setCursorPosition(cPos);
cursorNotAtEnd=true;
}
const int selectedLength=selectedText().length();
d->disableRestoreSelection = true;
QLineEdit::keyPressEvent ( e );
d->disableRestoreSelection = false;
if (( selectedLength != selectedText().length() ) && !hasUserSelection )
slotRestoreSelectionColors(); // and set userSelection to true
QString txt = text();
int len = txt.length();
if ( ( txt != old_txt || txt != e->text() ) && len/* && ( cursorPosition() == len || force )*/ &&
( (!keycode.isEmpty() && keycode.unicode()->isPrint()) ||
e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete) )
{
if ( e->key() == Qt::Key_Backspace )
{
if ( hadSelection && !hasUserSelection && !cursorNotAtEnd )
{
backspace();
txt = text();
len = txt.length();
}
if (!d->s_backspacePerformsCompletion) {
d->autoSuggest = false;
}
}
if (e->key() == Qt::Key_Delete )
d->autoSuggest=false;
if ( d->completionBox )
d->completionBox->setCancelledText( txt );
doCompletion(txt);
if ( (e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete ) &&
mode == KGlobalSettings::CompletionPopupAuto )
d->autoSuggest=true;
e->accept();
}
else if (!len && d->completionBox && d->completionBox->isVisible())
d->completionBox->hide();
return;
}
else if ( mode == KGlobalSettings::CompletionShell )
{
// Handles completion.
KShortcut cut;
if ( keys[TextCompletion].isEmpty() )
cut = KStandardShortcut::shortcut(KStandardShortcut::TextCompletion);
else
cut = keys[TextCompletion];
if ( cut.contains( key ) )
{
// Emit completion if the completion mode is CompletionShell
// and the cursor is at the end of the string.
const QString txt = text();
const int len = txt.length();
if ( cursorPosition() == len && len != 0 )
{
doCompletion(txt);
return;
}
}
else if ( d->completionBox )
d->completionBox->hide();
}
// handle rotation
if ( mode != KGlobalSettings::CompletionNone )
{
// Handles previous match
KShortcut cut;
if ( keys[PrevCompletionMatch].isEmpty() )
cut = KStandardShortcut::shortcut(KStandardShortcut::PrevCompletion);
else
cut = keys[PrevCompletionMatch];
if ( cut.contains( key ) )
{
if ( emitSignals() )
emit textRotation( KCompletionBase::PrevCompletionMatch );
if ( handleSignals() )
rotateText( KCompletionBase::PrevCompletionMatch );
return;
}
// Handles next match
if ( keys[NextCompletionMatch].isEmpty() )
cut = KStandardShortcut::shortcut(KStandardShortcut::NextCompletion);
else
cut = keys[NextCompletionMatch];
if ( cut.contains( key ) )
{
if ( emitSignals() )
emit textRotation( KCompletionBase::NextCompletionMatch );
if ( handleSignals() )
rotateText( KCompletionBase::NextCompletionMatch );
return;
}
}
// substring completion
if ( compObj() )
{
KShortcut cut;
if ( keys[SubstringCompletion].isEmpty() )
cut = KStandardShortcut::shortcut(KStandardShortcut::SubstringCompletion);
else
cut = keys[SubstringCompletion];
if ( cut.contains( key ) )
{
if ( emitSignals() )
emit substringCompletion( text() );
if ( handleSignals() )
{
setCompletedItems( compObj()->substringCompletion(text()));
e->accept();
}
return;
}
}
}
const int selectedLength = selectedText().length();
// Let QLineEdit handle any other keys events.
QLineEdit::keyPressEvent ( e );
if ( selectedLength != selectedText().length() )
slotRestoreSelectionColors(); // and set userSelection to true
}
void KLineEdit::mouseDoubleClickEvent( QMouseEvent* e )
{
if ( e->button() == Qt::LeftButton )
{
d->possibleTripleClick=true;
QTimer::singleShot( QApplication::doubleClickInterval(),this,
SLOT(tripleClickTimeout()) );
}
QLineEdit::mouseDoubleClickEvent( e );
}
void KLineEdit::mousePressEvent( QMouseEvent* e )
{
if ( (e->button() == Qt::LeftButton ||
e->button() == Qt::MidButton ) &&
d->clearButton ) {
d->clickInClear = ( d->clearButton == childAt(e->pos()) || d->clearButton->underMouse() );
if ( d->clickInClear ) {
d->possibleTripleClick = false;
}
}
if ( e->button() == Qt::LeftButton && d->possibleTripleClick ) {
selectAll();
e->accept();
return;
}
// if middle clicking and if text is present in the clipboard then clear the selection
// to prepare paste operation
if ( e->button() == Qt::MidButton ) {
if ( hasSelectedText() ) {
if ( QApplication::clipboard()->text( QClipboard::Selection ).length() >0 ) {
backspace();
}
}
}
QLineEdit::mousePressEvent( e );
}
void KLineEdit::mouseReleaseEvent( QMouseEvent* e )
{
if ( d->clickInClear ) {
if ( d->clearButton == childAt(e->pos()) || d->clearButton->underMouse() ) {
QString newText;
if ( e->button() == Qt::MidButton ) {
newText = QApplication::clipboard()->text( QClipboard::Selection );
setText( newText );
} else {
setSelection(0, text().size());
del();
emit clearButtonClicked();
}
emit textChanged( newText );
}
d->clickInClear = false;
e->accept();
return;
}
QLineEdit::mouseReleaseEvent( e );
if (QApplication::clipboard()->supportsSelection() ) {
if ( e->button() == Qt::LeftButton ) {
// Fix copying of squeezed text if needed
copySqueezedText( false );
}
}
}
void KLineEdit::tripleClickTimeout()
{
d->possibleTripleClick=false;
}
QMenu* KLineEdit::createStandardContextMenu()
{
QMenu *popup = QLineEdit::createStandardContextMenu();
if( !isReadOnly() )
{
// FIXME: This code depends on Qt's action ordering.
const QList<QAction *> actionList = popup->actions();
enum { UndoAct, RedoAct, Separator1, CutAct, CopyAct, PasteAct, DeleteAct, ClearAct,
Separator2, SelectAllAct, NCountActs };
QAction *separatorAction = 0L;
// separator we want is right after Delete right now.
const int idx = actionList.indexOf( actionList[DeleteAct] ) + 1;
if ( idx < actionList.count() )
separatorAction = actionList.at( idx );
if ( separatorAction )
{
KAction *clearAllAction = KStandardAction::clear( this, SLOT( clear() ), this) ;
if ( text().isEmpty() )
clearAllAction->setEnabled( false );
popup->insertAction( separatorAction, clearAllAction );
}
}
KIconTheme::assignIconsToContextMenu( KIconTheme::TextEditor, popup->actions () );
// If a completion object is present and the input
// widget is not read-only, show the Text Completion
// menu item.
if ( compObj() && !isReadOnly() && KAuthorized::authorize("lineedit_text_completion") )
{
QMenu *subMenu = popup->addMenu( KIcon("text-completion"), i18nc("@title:menu", "Text Completion") );
connect( subMenu, SIGNAL( triggered ( QAction* ) ),
this, SLOT( completionMenuActivated( QAction* ) ) );
popup->addSeparator();
QActionGroup* ag = new QActionGroup( this );
d->noCompletionAction = ag->addAction( i18nc("@item:inmenu Text Completion", "None"));
d->shellCompletionAction = ag->addAction( i18nc("@item:inmenu Text Completion", "Manual") );
d->autoCompletionAction = ag->addAction( i18nc("@item:inmenu Text Completion", "Automatic") );
d->popupCompletionAction = ag->addAction( i18nc("@item:inmenu Text Completion", "Dropdown List") );
d->shortAutoCompletionAction = ag->addAction( i18nc("@item:inmenu Text Completion", "Short Automatic") );
d->popupAutoCompletionAction = ag->addAction( i18nc("@item:inmenu Text Completion", "Dropdown List && Automatic"));
subMenu->addActions( ag->actions() );
//subMenu->setAccel( KStandardShortcut::completion(), ShellCompletion );
d->shellCompletionAction->setCheckable( true );
d->noCompletionAction->setCheckable( true );
d->popupCompletionAction->setCheckable( true );
d->autoCompletionAction->setCheckable( true );
d->shortAutoCompletionAction->setCheckable( true );
d->popupAutoCompletionAction->setCheckable( true );
d->shellCompletionAction->setEnabled( !d->disableCompletionMap[ KGlobalSettings::CompletionShell ] );
d->noCompletionAction->setEnabled( !d->disableCompletionMap[ KGlobalSettings::CompletionNone ] );
d->popupCompletionAction->setEnabled( !d->disableCompletionMap[ KGlobalSettings::CompletionPopup ] );
d->autoCompletionAction->setEnabled( !d->disableCompletionMap[ KGlobalSettings::CompletionAuto ] );
d->shortAutoCompletionAction->setEnabled( !d->disableCompletionMap[ KGlobalSettings::CompletionMan ] );
d->popupAutoCompletionAction->setEnabled( !d->disableCompletionMap[ KGlobalSettings::CompletionPopupAuto ] );
const KGlobalSettings::Completion mode = completionMode();
d->noCompletionAction->setChecked( mode == KGlobalSettings::CompletionNone );
d->shellCompletionAction->setChecked( mode == KGlobalSettings::CompletionShell );
d->popupCompletionAction->setChecked( mode == KGlobalSettings::CompletionPopup );
d->autoCompletionAction->setChecked( mode == KGlobalSettings::CompletionAuto );
d->shortAutoCompletionAction->setChecked( mode == KGlobalSettings::CompletionMan );
d->popupAutoCompletionAction->setChecked( mode == KGlobalSettings::CompletionPopupAuto );
const KGlobalSettings::Completion defaultMode = KGlobalSettings::completionMode();
if ( mode != defaultMode && !d->disableCompletionMap[ defaultMode ] )
{
subMenu->addSeparator();
d->defaultAction = subMenu->addAction( i18nc("@item:inmenu Text Completion", "Default") );
}
}
return popup;
}
void KLineEdit::contextMenuEvent( QContextMenuEvent *e )
{
if ( QLineEdit::contextMenuPolicy() != Qt::DefaultContextMenu )
return;
QMenu *popup = createStandardContextMenu();
// ### do we really need this? Yes, Please do not remove! This
// allows applications to extend the popup menu without having to
// inherit from this class! (DA)
emit aboutToShowContextMenu( popup );
popup->exec(e->globalPos());
delete popup;
}
void KLineEdit::completionMenuActivated( QAction *act)
{
KGlobalSettings::Completion oldMode = completionMode();
if( act == d->noCompletionAction )
{
setCompletionMode( KGlobalSettings::CompletionNone );
}
else if( act == d->shellCompletionAction)
{
setCompletionMode( KGlobalSettings::CompletionShell );
}
else if( act == d->autoCompletionAction)
{
setCompletionMode( KGlobalSettings::CompletionAuto );
}
else if( act == d->popupCompletionAction)
{
setCompletionMode( KGlobalSettings::CompletionPopup );
}
else if( act == d->shortAutoCompletionAction)
{
setCompletionMode( KGlobalSettings::CompletionMan );
}
else if( act == d->popupAutoCompletionAction)
{
setCompletionMode( KGlobalSettings::CompletionPopupAuto );
}
else if( act == d->defaultAction )
{
setCompletionMode( KGlobalSettings::completionMode() );
}
else
return;
if ( oldMode != completionMode() )
{
if ( (oldMode == KGlobalSettings::CompletionPopup ||
oldMode == KGlobalSettings::CompletionPopupAuto ) &&
d->completionBox && d->completionBox->isVisible() )
d->completionBox->hide();
emit completionModeChanged( completionMode() );
}
}
void KLineEdit::dropEvent(QDropEvent *e)
{
if( d->handleURLDrops )
{
const KUrl::List urlList = KUrl::List::fromMimeData( e->mimeData() );
if ( !urlList.isEmpty() )
{
// Let's replace the current text with the dropped URL(s), rather than appending.
// Makes more sense in general (#188129), e.g. konq location bar and kurlrequester
// can only hold one url anyway. OK this code supports multiple urls being dropped,
// but that's not the common case [and it breaks if they contain spaces... this is why
// kfiledialog uses double quotes around filenames in multiple-selection mode]...
//
// Anyway, if some apps prefer "append" then we should have a
// setUrlDropsSupport( {NoUrlDrops, SingleUrlDrops, MultipleUrlDrops} )
// where Single replaces and Multiple appends.
QString dropText;
//QString dropText = text();
KUrl::List::ConstIterator it;
for( it = urlList.begin() ; it != urlList.end() ; ++it )
{
if(!dropText.isEmpty())
dropText+=' ';
dropText += (*it).prettyUrl();
}
setText(dropText);
setCursorPosition(dropText.length());
e->accept();
return;
}
}
QLineEdit::dropEvent(e);
}
bool KLineEdit::event( QEvent* ev )
{
KCursor::autoHideEventFilter( this, ev );
if ( ev->type() == QEvent::ShortcutOverride )
{
QKeyEvent *e = static_cast<QKeyEvent *>( ev );
if (d->overrideShortcut(e)) {
ev->accept();
}
} else if (ev->type() == QEvent::ApplicationPaletteChange
|| ev->type() == QEvent::PaletteChange) {
// Assume the widget uses the application's palette
QPalette p = QApplication::palette();
d->previousHighlightedTextColor=p.color(QPalette::Normal,QPalette::HighlightedText);
d->previousHighlightColor=p.color(QPalette::Normal,QPalette::Highlight);
setUserSelection(d->userSelection);
} else if (ev->type() == QEvent::StyleChange) {
// since we have our own style and it relies on this style to Get Things Right,
// if a style is set specifically on the widget (which would replace our own style!)
// hang on to this special style and re-instate our own style.
//FIXME: Qt currently has a grave bug where already deleted QStyleSheetStyle objects
// will get passed back in if we set a new style on it here. remove the qstrmcp test
// when this is fixed in Qt (or a better approach is found)
if (!qobject_cast<KLineEditStyle *>(style()) &&
qstrcmp(style()->metaObject()->className(), "QStyleSheetStyle") != 0 &&
QLatin1String(style()->metaObject()->className()) != d->lastStyleClass) {
KLineEditStyle *kleStyle = d->style.data();
if (!kleStyle) {
d->style = kleStyle = new KLineEditStyle(this);
}
kleStyle->m_subStyle = style();
// this guards against "wrap around" where another style, e.g. QStyleSheetStyle,
// is setting the style on QEvent::StyleChange
d->lastStyleClass = QLatin1String(style()->metaObject()->className());
setStyle(kleStyle);
d->lastStyleClass.clear();
}
}
return QLineEdit::event( ev );
}
void KLineEdit::setUrlDropsEnabled(bool enable)
{
d->handleURLDrops=enable;
}
bool KLineEdit::urlDropsEnabled() const
{
return d->handleURLDrops;
}
void KLineEdit::setTrapReturnKey( bool grab )
{
d->grabReturnKeyEvents = grab;
}
bool KLineEdit::trapReturnKey() const
{
return d->grabReturnKeyEvents;
}
void KLineEdit::setUrl( const KUrl& url )
{
setText( url.prettyUrl() );
}
void KLineEdit::setCompletionBox( KCompletionBox *box )
{
if ( d->completionBox )
return;
d->completionBox = box;
if ( handleSignals() )
{
connect( d->completionBox, SIGNAL(currentTextChanged( const QString& )),
SLOT(_k_slotCompletionBoxTextChanged( const QString& )) );
connect( d->completionBox, SIGNAL(userCancelled( const QString& )),
SLOT(userCancelled( const QString& )) );
connect( d->completionBox, SIGNAL(activated(QString)),
SIGNAL(completionBoxActivated(QString)) );
connect( d->completionBox, SIGNAL(activated(QString)),
SIGNAL(textEdited(QString)) );
}
}
/*
* Set the line edit text without changing the modified flag. By default
* calling setText resets the modified flag to false.
*/
static void setEditText(KLineEdit* edit, const QString& text)
{
if (!edit) {
return;
}
const bool wasModified = edit->isModified();
edit->setText(text);
edit->setModified(wasModified);
}
void KLineEdit::userCancelled(const QString & cancelText)
{
if ( completionMode() != KGlobalSettings::CompletionPopupAuto )
{
setEditText(this, cancelText);
}
else if (hasSelectedText() )
{
if (d->userSelection)
deselect();
else
{
d->autoSuggest=false;
const int start = selectionStart() ;
const QString s = text().remove(selectionStart(), selectedText().length());
setEditText(this, s);
setCursorPosition(start);
d->autoSuggest=true;
}
}
}
bool KLineEditPrivate::overrideShortcut(const QKeyEvent* e)
{
KShortcut scKey;
const int key = e->key() | e->modifiers();
const KLineEdit::KeyBindingMap keys = q->getKeyBindings();
if (keys[KLineEdit::TextCompletion].isEmpty())
scKey = KStandardShortcut::shortcut(KStandardShortcut::TextCompletion);
else
scKey = keys[KLineEdit::TextCompletion];
if (scKey.contains( key ))
return true;
if (keys[KLineEdit::NextCompletionMatch].isEmpty())
scKey = KStandardShortcut::shortcut(KStandardShortcut::NextCompletion);
else
scKey = keys[KLineEdit::NextCompletionMatch];
if (scKey.contains( key ))
return true;
if (keys[KLineEdit::PrevCompletionMatch].isEmpty())
scKey = KStandardShortcut::shortcut(KStandardShortcut::PrevCompletion);
else
scKey = keys[KLineEdit::PrevCompletionMatch];
if (scKey.contains( key ))
return true;
// Override all the text manupilation accelerators...
if ( KStandardShortcut::copy().contains( key ) )
return true;
else if ( KStandardShortcut::paste().contains( key ) )
return true;
else if ( KStandardShortcut::cut().contains( key ) )
return true;
else if ( KStandardShortcut::undo().contains( key ) )
return true;
else if ( KStandardShortcut::redo().contains( key ) )
return true;
else if (KStandardShortcut::deleteWordBack().contains( key ))
return true;
else if (KStandardShortcut::deleteWordForward().contains( key ))
return true;
else if (KStandardShortcut::forwardWord().contains( key ))
return true;
else if (KStandardShortcut::backwardWord().contains( key ))
return true;
else if (KStandardShortcut::beginningOfLine().contains( key ))
return true;
else if (KStandardShortcut::endOfLine().contains( key ))
return true;
// Shortcut overrides for shortcuts that QLineEdit handles
// but doesn't dare force as "stronger than kaction shortcuts"...
else if (e->matches(QKeySequence::SelectAll)) {
return true;
}
#ifdef Q_WS_X11
else if (key == Qt::CTRL + Qt::Key_E || key == Qt::CTRL + Qt::Key_U)
return true;
#endif
if (completionBox && completionBox->isVisible ())
{
const int key = e->key();
const Qt::KeyboardModifiers modifiers = e->modifiers();
if ((key == Qt::Key_Backtab || key == Qt::Key_Tab) &&
(modifiers == Qt::NoModifier || (modifiers & Qt::ShiftModifier)))
{
return true;
}
}
return false;
}
void KLineEdit::setCompletedItems( const QStringList& items, bool autoSuggest )
{
QString txt;
if ( d->completionBox && d->completionBox->isVisible() ) {
// The popup is visible already - do the matching on the initial string,
// not on the currently selected one.
txt = completionBox()->cancelledText();
} else {
txt = text();
}
if ( !items.isEmpty() &&
!(items.count() == 1 && txt == items.first()) )
{
// create completion box if non-existent
completionBox();
if ( d->completionBox->isVisible() )
{
QListWidgetItem* currentItem = d->completionBox->currentItem();
QString currentSelection;
if ( currentItem != 0 ) {
currentSelection = currentItem->text();
}
d->completionBox->setItems( items );
const QList<QListWidgetItem*> matchedItems = d->completionBox->findItems(currentSelection, Qt::MatchExactly);
QListWidgetItem* matchedItem = matchedItems.isEmpty() ? 0 : matchedItems.first();
if (matchedItem) {
const bool blocked = d->completionBox->blockSignals( true );
d->completionBox->setCurrentItem( matchedItem );
d->completionBox->blockSignals( blocked );
} else {
d->completionBox->setCurrentRow(-1);
}
}
else // completion box not visible yet -> show it
{
if ( !txt.isEmpty() )
d->completionBox->setCancelledText( txt );
d->completionBox->setItems( items );
d->completionBox->popup();
}
if ( d->autoSuggest && autoSuggest )
{
const int index = items.first().indexOf( txt );
const QString newText = items.first().mid( index );
setUserSelection(false); // can be removed? setCompletedText sets it anyway
setCompletedText(newText,true);
}
}
else
{
if ( d->completionBox && d->completionBox->isVisible() )
d->completionBox->hide();
}
}
KCompletionBox * KLineEdit::completionBox( bool create )
{
if ( create && !d->completionBox ) {
setCompletionBox( new KCompletionBox( this ) );
d->completionBox->setObjectName("completion box");
d->completionBox->setFont(font());
}
return d->completionBox;
}
void KLineEdit::setCompletionObject( KCompletion* comp, bool hsig )
{
KCompletion *oldComp = compObj();
if ( oldComp && handleSignals() )
disconnect( oldComp, SIGNAL( matches( const QStringList& )),
this, SLOT( setCompletedItems( const QStringList& )));
if ( comp && hsig )
connect( comp, SIGNAL( matches( const QStringList& )),
this, SLOT( setCompletedItems( const QStringList& )));
KCompletionBase::setCompletionObject( comp, hsig );
}
// QWidget::create() turns off mouse-Tracking which would break auto-hiding
void KLineEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
{
QLineEdit::create( id, initializeWindow, destroyOldWindow );
KCursor::setAutoHideCursor( this, true, true );
}
void KLineEdit::setUserSelection(bool userSelection)
{
//if !d->userSelection && userSelection we are accepting a completion,
//so trigger an update
if (!d->userSelection && userSelection)
{
d->_k_updateUserText(text());
}
QPalette p = palette();
if (userSelection)
{
p.setColor(QPalette::Highlight, d->previousHighlightColor);
p.setColor(QPalette::HighlightedText, d->previousHighlightedTextColor);
}
else
{
QColor color=p.color(QPalette::Disabled, QPalette::Text);
p.setColor(QPalette::HighlightedText, color);
color=p.color(QPalette::Active, QPalette::Base);
p.setColor(QPalette::Highlight, color);
}
d->userSelection=userSelection;
setPalette(p);
}
void KLineEdit::slotRestoreSelectionColors()
{
if (d->disableRestoreSelection)
return;
setUserSelection(true);
}
void KLineEdit::clear()
{
setText( QString() );
}
void KLineEdit::_k_slotCompletionBoxTextChanged( const QString& text )
{
if (!text.isEmpty())
{
setText( text );
setModified(true);
end( false ); // force cursor at end
}
}
QString KLineEdit::originalText() const
{
if ( d->enableSqueezedText && isReadOnly() )
return d->squeezedText;
return text();
}
QString KLineEdit::userText() const
{
return d->userText;
}
bool KLineEdit::autoSuggest() const
{
return d->autoSuggest;
}
void KLineEdit::paintEvent( QPaintEvent *ev )
{
if (echoMode() == Password && d->threeStars) {
// ### hack alert!
// QLineEdit has currently no hooks to modify the displayed string.
// When we call setText(), an update() is triggered and we get
// into an infinite recursion.
// Qt offers the setUpdatesEnabled() method, but when we re-enable
// them, update() is triggered, and we get into the same recursion.
// To work around this problem, we set/clear the internal Qt flag which
// marks the updatesDisabled state manually.
setAttribute(Qt::WA_UpdatesDisabled, true);
blockSignals(true);
const QString oldText = text();
const bool isModifiedState = isModified(); // save modified state because setText resets it
setText(oldText + oldText + oldText);
QLineEdit::paintEvent(ev);
setText(oldText);
setModified(isModifiedState);
blockSignals(false);
setAttribute(Qt::WA_UpdatesDisabled, false);
} else {
QLineEdit::paintEvent( ev );
}
if (d->enableClickMsg && d->drawClickMsg && !hasFocus() && text().isEmpty()) {
QPainter p(this);
QFont f = font();
f.setItalic(d->italicizePlaceholder);
p.setFont(f);
QColor color(palette().color(foregroundRole()));
color.setAlphaF(0.5);
p.setPen(color);
QStyleOptionFrame opt;
initStyleOption(&opt);
QRect cr = style()->subElementRect(QStyle::SE_LineEditContents, &opt, this);
// this is copied/adapted from QLineEdit::paintEvent
const int verticalMargin(1);
const int horizontalMargin(2);
int left, top, right, bottom;
getTextMargins( &left, &top, &right, &bottom );
cr.adjust( left, top, -right, -bottom );
p.setClipRect(cr);
QFontMetrics fm = fontMetrics();
Qt::Alignment va = alignment() & Qt::AlignVertical_Mask;
int vscroll;
switch (va & Qt::AlignVertical_Mask)
{
case Qt::AlignBottom:
vscroll = cr.y() + cr.height() - fm.height() - verticalMargin;
break;
case Qt::AlignTop:
vscroll = cr.y() + verticalMargin;
break;
default:
vscroll = cr.y() + (cr.height() - fm.height() + 1) / 2;
break;
}
QRect lineRect(cr.x() + horizontalMargin, vscroll, cr.width() - 2*horizontalMargin, fm.height());
p.drawText(lineRect, Qt::AlignLeft|Qt::AlignVCenter, d->clickMessage);
}
}
void KLineEdit::focusInEvent( QFocusEvent *ev )
{
if ( d->enableClickMsg && d->drawClickMsg )
{
d->drawClickMsg = false;
update();
}
QLineEdit::focusInEvent( ev );
}
void KLineEdit::focusOutEvent( QFocusEvent *ev )
{
if ( d->enableClickMsg && text().isEmpty() )
{
d->drawClickMsg = true;
update();
}
QLineEdit::focusOutEvent( ev );
}
void KLineEdit::setClickMessage( const QString &msg )
{
d->enableClickMsg = !msg.isEmpty();
d->clickMessage = msg;
d->drawClickMsg = text().isEmpty();
update();
}
#ifndef KDE_NO_DEPRECATED
void KLineEdit::setContextMenuEnabled( bool showMenu )
{
QLineEdit::setContextMenuPolicy( showMenu ? Qt::DefaultContextMenu : Qt::NoContextMenu );
}
#endif
#ifndef KDE_NO_DEPRECATED
bool KLineEdit::isContextMenuEnabled() const
{
return ( contextMenuPolicy() == Qt::DefaultContextMenu );
}
#endif
void KLineEdit::setPasswordMode(bool b)
{
if(b)
{
KConfigGroup cg(KGlobal::config(), "Passwords");
const QString val = cg.readEntry("EchoMode", "OneStar");
if (val == "NoEcho")
setEchoMode(NoEcho);
else {
d->threeStars = (val == "ThreeStars");
setEchoMode(Password);
}
}
else
{
setEchoMode( Normal );
}
}
bool KLineEdit::passwordMode() const
{
return echoMode() == NoEcho || echoMode() == Password;
}
void KLineEdit::doCompletion(const QString& txt)
{
if (emitSignals()) {
emit completion(txt); // emit when requested...
}
d->completionRunning = true;
if (handleSignals()) {
makeCompletion(txt); // handle when requested...
}
d->completionRunning = false;
}
#include "moc_klineedit.cpp"
#include "moc_klineedit_p.cpp"
diff --git a/kdeui/widgets/klineedit.h b/kdeui/widgets/klineedit.h
index 567a717c9b..d2756df000 100644
--- a/kdeui/widgets/klineedit.h
+++ b/kdeui/widgets/klineedit.h
@@ -1,675 +1,675 @@
/* This file is part of the KDE libraries
This class was originally inspired by Torben Weis'
fileentry.cpp for KFM II.
Copyright (C) 1997 Sven Radej <sven.radej@iname.com>
Copyright (c) 1999 Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com>
Copyright (c) 1999 Preston Brown <pbrown@kde.org>
Completely re-designed:
Copyright (c) 2000,2001 Dawit Alemayehu <adawit@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License (LGPL) as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later
version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KLINEEDIT_H
#define KLINEEDIT_H
#include <QLineEdit>
#include <kcompletion.h>
class QAction;
class QMenu;
class KCompletionBox;
class KUrl;
class KLineEditPrivate;
/**
* An enhanced QLineEdit widget for inputting text.
*
* \b Detail \n
*
* This widget inherits from QLineEdit and implements the following
* additional functionalities: a completion object that provides both
* automatic and manual text completion as well as multiple match iteration
* features, configurable key-bindings to activate these features and a
* popup-menu item that can be used to allow the user to set text completion
* modes on the fly based on their preference.
*
* To support these new features KLineEdit also emits a few more
* additional signals. These are: completion( const QString& ),
* textRotation( KeyBindingType ), and returnPressed( const QString& ).
* The completion signal can be connected to a slot that will assist the
* user in filling out the remaining text. The text rotation signal is
* intended to be used to iterate through the list of all possible matches
* whenever there is more than one match for the entered text. The
* @p returnPressed( const QString& ) signals are the same as QLineEdit's
* except it provides the current text in the widget as its argument whenever
* appropriate.
*
* This widget by default creates a completion object when you invoke
* the completionObject( bool ) member function for the first time or
* use setCompletionObject( KCompletion*, bool ) to assign your own
* completion object. Additionally, to make this widget more functional,
* KLineEdit will by default handle the text rotation and completion
* events internally when a completion object is created through either one
* of the methods mentioned above. If you do not need this functionality,
* simply use KCompletionBase::setHandleSignals( bool ) or set the
* boolean parameter in the above functions to false.
*
* The default key-bindings for completion and rotation is determined
* from the global settings in KStandardShortcut. These values, however,
* can be overridden locally by invoking KCompletionBase::setKeyBinding().
* The values can easily be reverted back to the default setting, by simply
* calling useGlobalSettings(). An alternate method would be to default
* individual key-bindings by using setKeyBinding() with the default
* second argument.
*
* If @p EchoMode for this widget is set to something other than @p QLineEdit::Normal,
* the completion mode will always be defaulted to KGlobalSettings::CompletionNone.
* This is done purposefully to guard against protected entries such as passwords being
* cached in KCompletion's list. Hence, if the @p EchoMode is not QLineEdit::Normal, the
* completion mode is automatically disabled.
*
* A read-only KLineEdit will have the same background color as a
* disabled KLineEdit, but its foreground color will be the one used
* for the read-write mode. This differs from QLineEdit's implementation
* and is done to give visual distinction between the three different modes:
* disabled, read-only, and read-write.
*
* KLineEdit has also a password mode which depends of globals KDE settings. Use
* KLineEdit::setPasswordMode instead of QLineEdit::echoMode property to have a password field.
*
* \b Usage \n
*
* To enable the basic completion feature:
*
* \code
* KLineEdit *edit = new KLineEdit( this );
* KCompletion *comp = edit->completionObject();
* // Connect to the return pressed signal - optional
* connect(edit,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&)));
* \endcode
*
* To use a customized completion objects or your
* own completion object:
*
* \code
* KLineEdit *edit = new KLineEdit( this );
* KUrlCompletion *comp = new KUrlCompletion();
* edit->setCompletionObject( comp );
* // Connect to the return pressed signal - optional
* connect(edit,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&)));
* \endcode
*
* Note if you specify your own completion object you have to either delete
* it when you don't need it anymore, or you can tell KLineEdit to delete it
* for you:
* \code
* edit->setAutoDeleteCompletionObject( true );
* \endcode
*
* <b>Miscellaneous function calls :</b>\n
*
* \code
* // Tell the widget to not handle completion and iteration automatically.
* edit->setHandleSignals( false );
*
* // Set your own key-bindings for a text completion mode.
* edit->setKeyBinding( KCompletionBase::TextCompletion, Qt::End );
*
* // Hide the context (popup) menu
* edit->setContextMenuPolicy( Qt::NoContextMenu );
*
* // Default the key-bindings back to the default system settings.
* edit->useGlobalKeyBindings();
* \endcode
*
* \image html klineedit.png "KDE Line Edit Widgets with clear-button and clickMessage"
*
* @author Dawit Alemayehu <adawit@kde.org>
*/
class KDEUI_EXPORT KLineEdit : public QLineEdit, public KCompletionBase //krazy:exclude=qclasses
{
friend class KComboBox;
friend class KLineEditStyle;
Q_OBJECT
#ifndef KDE_NO_DEPRECATED
Q_PROPERTY( bool contextMenuEnabled READ isContextMenuEnabled WRITE setContextMenuEnabled )
#endif
Q_PROPERTY( bool urlDropsEnabled READ urlDropsEnabled WRITE setUrlDropsEnabled )
Q_PROPERTY( bool trapEnterKeyEvent READ trapReturnKey WRITE setTrapReturnKey )
Q_PROPERTY( bool squeezedTextEnabled READ isSqueezedTextEnabled WRITE setSqueezedTextEnabled )
Q_PROPERTY( QString clickMessage READ clickMessage WRITE setClickMessage )
Q_PROPERTY( bool showClearButton READ isClearButtonShown WRITE setClearButtonShown )
Q_PROPERTY( bool passwordMode READ passwordMode WRITE setPasswordMode )
public:
/**
* Constructs a KLineEdit object with a default text, a parent,
* and a name.
*
* @param string Text to be shown in the edit widget.
* @param parent The parent widget of the line edit.
*/
explicit KLineEdit( const QString &string, QWidget *parent = 0 );
/**
* Constructs a line edit
* @param parent The parent widget of the line edit.
*/
explicit KLineEdit( QWidget *parent = 0 );
/**
* Destructor.
*/
virtual ~KLineEdit ();
/**
* Sets @p url into the lineedit. It uses KUrl::prettyUrl() so
* that the url is properly decoded for displaying.
*/
void setUrl( const KUrl& url );
/**
* Re-implemented from KCompletionBase for internal reasons.
*
* This function is re-implemented in order to make sure that
* the EchoMode is acceptable before we set the completion mode.
*
* See KCompletionBase::setCompletionMode
*/
virtual void setCompletionMode( KGlobalSettings::Completion mode );
/**
* Disables completion modes by makeing them non-checkable.
*
* The context menu allows to change the completion mode.
* This method allows to disable some modes.
*/
void setCompletionModeDisabled( KGlobalSettings::Completion mode, bool disable = true );
/**
* Enables/disables the popup (context) menu.
*
* This method only works if this widget is editable, i.e. read-write and
* allows you to enable/disable the context menu. It does nothing if invoked
* for a none-editable combo-box.
*
* By default, the context menu is created if this widget is editable.
* Call this function with the argument set to false to disable the popup
* menu.
*
* @param showMenu If @p true, show the context menu.
* @deprecated use setContextMenuPolicy
*/
#ifndef KDE_NO_DEPRECATED
virtual KDEUI_DEPRECATED void setContextMenuEnabled( bool showMenu );
#endif
/**
* Returns @p true when the context menu is enabled.
* @deprecated use contextMenuPolicy
*/
#ifndef KDE_NO_DEPRECATED
KDEUI_DEPRECATED bool isContextMenuEnabled() const;
#endif
/**
* Enables/Disables handling of URL drops. If enabled and the user
* drops an URL, the decoded URL will be inserted. Otherwise the default
* behavior of QLineEdit is used, which inserts the encoded URL.
*
* @param enable If @p true, insert decoded URLs
*/
void setUrlDropsEnabled( bool enable );
/**
* Returns @p true when decoded URL drops are enabled
*/
bool urlDropsEnabled() const;
/**
* By default, KLineEdit recognizes @p Key_Return and @p Key_Enter and emits
* the returnPressed() signals, but it also lets the event pass,
* for example causing a dialog's default-button to be called.
*
* Call this method with @p trap = @p true to make @p KLineEdit stop these
* events. The signals will still be emitted of course.
*
* @see trapReturnKey()
*/
void setTrapReturnKey( bool trap );
/**
* @returns @p true if keyevents of @p Key_Return or
* @p Key_Enter will be stopped or if they will be propagated.
*
* @see setTrapReturnKey ()
*/
bool trapReturnKey() const;
/**
* @returns the completion-box, that is used in completion mode
* KGlobalSettings::CompletionPopup.
* This method will create a completion-box if none is there, yet.
*
* @param create Set this to false if you don't want the box to be created
* i.e. to test if it is available.
*/
KCompletionBox * completionBox( bool create = true ); // KDE5 TODO: make virtual, so konq can reimplement i
/**
* Reimplemented for internal reasons, the API is not affected.
*/
virtual void setCompletionObject( KCompletion *, bool hsig = true );
/**
* Reimplemented for internal reasons, the API is not affected.
*/
virtual void copy() const;
/**
* Enable text squeezing whenever the supplied text is too long.
* Only works for "read-only" mode.
*
* Note that once text squeezing is enabled, QLineEdit::text()
* and QLineEdit::displayText() return the squeezed text. If
* you want the original text, use @ref originalText.
*
* @see QLineEdit
*/
void setSqueezedTextEnabled( bool enable );
/**
* Returns true if text squeezing is enabled.
* This is only valid when the widget is in read-only mode.
*/
bool isSqueezedTextEnabled() const;
/**
* Returns the original text if text squeezing is enabled.
* If the widget is not in "read-only" mode, this function
* returns the same thing as QLineEdit::text().
*
* @see QLineEdit
*/
QString originalText() const;
/**
* Returns the text as given by the user (i.e. not autocompleted)
* if the widget has autocompletion disabled, this function
* returns the same as QLineEdit::text().
* @since 4.2.2
*/
QString userText() const;
/**
* Set the completion-box to be used in completion mode
* KGlobalSettings::CompletionPopup.
* This will do nothing if a completion-box already exists.
*
* @param box The KCompletionBox to set
*/
void setCompletionBox( KCompletionBox *box );
/**
* This makes the line edit display a grayed-out hinting text as long as
* the user didn't enter any text. It is often used as indication about
* the purpose of the line edit.
*/
void setClickMessage( const QString &msg );
/**
* @return the message set with setClickMessage
*/
QString clickMessage() const;
/**
* This makes the line edit display an icon on one side of the line edit
* which, when clicked, clears the contents of the line edit.
* This is useful for such things as location or search bars.
**/
void setClearButtonShown(bool show);
/**
* @return whether or not the clear button is shown
**/
bool isClearButtonShown() const;
/**
* @return the size used by the clear button
* @since KDE 4.1
**/
QSize clearButtonUsedSize() const;
/**
* Do completion now. This is called automatically when typing a key for instance.
* Emits completion() and/or calls makeCompletion(), depending on
* emitSignals and handleSignals.
*
* @since 4.2.1
*/
void doCompletion(const QString& txt);
Q_SIGNALS:
/**
* Emitted whenever the completion box is activated.
*/
void completionBoxActivated (const QString &);
/**
* Emitted when the user presses the return key.
*
* The argument is the current text. Note that this
* signal is @em not emitted if the widget's @p EchoMode is set to
* QLineEdit::EchoMode.
*/
void returnPressed( const QString& );
/**
* Emitted when the completion key is pressed.
*
* Please note that this signal is @em not emitted if the
* completion mode is set to @p CompletionNone or @p EchoMode is
* @em normal.
*/
void completion( const QString& );
/**
* Emitted when the shortcut for substring completion is pressed.
*/
void substringCompletion( const QString& );
/**
* Emitted when the text is changed NOT by the suggested autocompletion:
* either when the user is physically typing keys, or when the text is changed programmatically,
* for example, by calling setText().
* But not when automatic completion changes the text temporarily.
*
* @since 4.2.2
* @deprecated since 4.5. You probably want to connect to textEdited() instead,
* which is emitted whenever the text is actually changed by the user
* (by typing or accepting autocompletion), without side effects from
* suggested autocompletion either. userTextChanged isn't needed anymore.
*/
#ifndef KDE_NO_DEPRECATED
QT_MOC_COMPAT void userTextChanged( const QString & );
#endif
/**
* Emitted when the text rotation key-bindings are pressed.
*
* The argument indicates which key-binding was pressed.
* In KLineEdit's case this can be either one of two values:
* PrevCompletionMatch or NextCompletionMatch. See
* KCompletionBase::setKeyBinding for details.
*
* Note that this signal is @em not emitted if the completion
* mode is set to @p KGlobalSettings::CompletionNone or @p echoMode() is @em not normal.
*/
void textRotation( KCompletionBase::KeyBindingType );
/**
* Emitted when the user changed the completion mode by using the
* popupmenu.
*/
void completionModeChanged( KGlobalSettings::Completion );
/**
* Emitted before the context menu is displayed.
*
* The signal allows you to add your own entries into the
* the context menu that is created on demand.
*
* NOTE: Do not store the pointer to the QMenu
* provided through since it is created and deleted
* on demand.
*
* @param p the context menu about to be displayed
*/
void aboutToShowContextMenu(QMenu* menu);
/**
* Emitted when the user clicked on the clear button
*/
void clearButtonClicked();
public Q_SLOTS:
/**
* Sets the lineedit to read-only. Similar to QLineEdit::setReadOnly
* but also takes care of the background color, and the clear button.
*/
virtual void setReadOnly(bool);
/**
* Iterates through all possible matches of the completed text or
* the history list.
*
* This function simply iterates over all possible matches in case
* multiple matches are found as a result of a text completion request.
* It will have no effect if only a single match is found.
*
* @param type The key-binding invoked.
*/
void rotateText( KCompletionBase::KeyBindingType type );
/**
* See KCompletionBase::setCompletedText.
*/
virtual void setCompletedText( const QString& );
/**
* Same as the above function except it allows you to temporarily
* turn off text completion in CompletionPopupAuto mode.
*
*
* @param items list of completion matches to be shown in the completion box.
* @param autoSuggest true if you want automatic text completion (suggestion) enabled.
*/
void setCompletedItems( const QStringList& items, bool autoSuggest = true );
/**
* Reimplemented to workaround a buggy QLineEdit::clear()
* (changing the clipboard to the text we just had in the lineedit)
*/
virtual void clear(); // ### KDE 5: check if still required
/**
* Squeezes @p text into the line edit.
* This can only be used with read-only line-edits.
*/
void setSqueezedText( const QString &text);
/**
* Re-implemented to enable text squeezing. API is not affected.
*/
virtual void setText ( const QString& );
/**
* @brief set the line edit in password mode.
* this change the EchoMode according to KDE preferences.
* @param b true to set in password mode
*/
void setPasswordMode( bool b = true );
/**
* @return returns true if the lineedit is set to password mode echoing
*/
bool passwordMode( ) const;
protected Q_SLOTS:
/**
* Completes the remaining text with a matching one from
* a given list.
*/
virtual void makeCompletion( const QString& );
/**
* Resets the current displayed text.
* Call this function to revert a text completion if the user
* cancels the request. Mostly applies to popup completions.
*/
void userCancelled(const QString & cancelText);
protected:
/**
* Re-implemented for internal reasons. API not affected.
*/
virtual bool event( QEvent * );
/**
* Re-implemented for internal reasons. API not affected.
*
* See QLineEdit::resizeEvent().
*/
virtual void resizeEvent( QResizeEvent * );
/**
* Re-implemented for internal reasons. API not affected.
*
* See QLineEdit::keyPressEvent().
*/
virtual void keyPressEvent( QKeyEvent * );
/**
* Re-implemented for internal reasons. API not affected.
*
* See QLineEdit::mousePressEvent().
*/
virtual void mousePressEvent( QMouseEvent * );
/**
* Re-implemented for internal reasons. API not affected.
*
* See QLineEdit::mouseReleaseEvent().
*/
virtual void mouseReleaseEvent( QMouseEvent * );
/**
* Re-implemented for internal reasons. API not affected.
*
* See QWidget::mouseDoubleClickEvent().
*/
virtual void mouseDoubleClickEvent( QMouseEvent * );
/**
* Re-implemented for internal reasons. API not affected.
*
* See QLineEdit::contextMenuEvent().
*/
virtual void contextMenuEvent( QContextMenuEvent * );
/**
* Re-implemented for internal reasons. API not affected.
*
* See QLineEdit::createStandardContextMenu().
*/
QMenu* createStandardContextMenu();
/**
* Re-implemented to handle URI drops.
*
* See QLineEdit::dropEvent().
*/
virtual void dropEvent( QDropEvent * );
/**
* This function simply sets the lineedit text and
* highlights the text appropriately if the boolean
* value is set to true.
*
* @param text
* @param marked
*/
virtual void setCompletedText( const QString& /*text*/, bool /*marked*/ );
/**
* Sets the widget in userSelection mode or in automatic completion
* selection mode. This changes the colors of selections.
*/
void setUserSelection( bool userSelection );
/**
* Reimplemented for internal reasons, the API is not affected.
*/
virtual void create( WId = 0, bool initializeWindow = true,
bool destroyOldWindow = true );
/**
* Whether in current state text should be auto-suggested
*/
bool autoSuggest() const;
virtual void paintEvent( QPaintEvent *ev );
virtual void focusInEvent( QFocusEvent *ev );
virtual void focusOutEvent( QFocusEvent *ev );
private Q_SLOTS:
void completionMenuActivated( QAction *act );
void tripleClickTimeout(); // resets possibleTripleClick
void slotRestoreSelectionColors();
void _k_slotCompletionBoxTextChanged( const QString& text );
/**
* updates the icon of the clear button on text change
**/
void updateClearButtonIcon(const QString&);
private:
/**
* Initializes variables. Called from the constructors.
*/
- void init();
+ void initWidget();
bool copySqueezedText( bool clipboard ) const;
/**
* Properly sets the squeezed text whenever the widget is
* created or resized.
*/
void setSqueezedText ();
/**
* updates the geometry of the clear button on resize events
**/
void updateClearButton();
private:
friend class KLineEditPrivate;
KLineEditPrivate *const d;
Q_PRIVATE_SLOT( d, void _k_slotSettingsChanged( int category ) )
Q_PRIVATE_SLOT( d, void _k_textChanged(const QString&) )
};
#endif
diff --git a/kdeui/widgets/knuminput.cpp b/kdeui/widgets/knuminput.cpp
index 9efdb51cdd..e70b3f111d 100644
--- a/kdeui/widgets/knuminput.cpp
+++ b/kdeui/widgets/knuminput.cpp
@@ -1,1088 +1,1088 @@
/* This file is part of the KDE libraries
* Initial implementation:
* Copyright (c) 1997 Patrick Dowler <dowler@morgul.fsh.uvic.ca>
* Rewritten and maintained by:
* Copyright (c) 2000 Dirk Mueller <mueller@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "knuminput.h"
#include <config.h>
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <cmath>
#include <QApplication>
#include <QLabel>
#include <QLineEdit>
#include <QResizeEvent>
#include <QSlider>
#include <kdebug.h>
#include <kdialog.h>
#include <klocalizedstring.h>
static inline int calcDiffByTen(int x, int y)
{
// calculate ( x - y ) / 10 without overflowing ints:
return (x / 10) - (y / 10) + (x % 10 - y % 10) / 10;
}
// ----------------------------------------------------------------------------
class KNumInputPrivate
{
public:
KNumInputPrivate(KNumInput *q, KNumInput *below = 0) :
q(q),
previousNumInput(0),
nextNumInput(0),
column1Width(0),
column2Width(0),
label(0),
slider(0),
labelAlignment(0)
{
if (below) {
nextNumInput = below->d->nextNumInput;
previousNumInput = below;
below->d->nextNumInput = q;
if (nextNumInput) {
nextNumInput->d->previousNumInput = q;
}
}
}
static KNumInputPrivate *get(const KNumInput *i) {
return i->d;
}
KNumInput *q;
KNumInput* previousNumInput, *nextNumInput;
int column1Width, column2Width;
QLabel* label;
QSlider* slider;
QSize sliderSize, labelSize;
Qt::Alignment labelAlignment;
};
#define K_USING_KNUMINPUT_P(_d) KNumInputPrivate *_d = KNumInputPrivate::get(this)
KNumInput::KNumInput(QWidget* parent)
: QWidget(parent), d(new KNumInputPrivate(this))
{
setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed));
setFocusPolicy(Qt::StrongFocus);
}
#ifndef KDE_NO_DEPRECATED
KNumInput::KNumInput(QWidget* parent, KNumInput* below)
: QWidget(parent), d(new KNumInputPrivate(this, below))
{
setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed));
setFocusPolicy(Qt::StrongFocus);
}
#endif
KNumInput::~KNumInput()
{
if (d->previousNumInput) {
d->previousNumInput->d->nextNumInput = d->nextNumInput;
}
if (d->nextNumInput) {
d->nextNumInput->d->previousNumInput = d->previousNumInput;
}
delete d;
}
QSlider *KNumInput::slider() const
{
return d->slider;
}
bool KNumInput::showSlider() const
{
return d->slider;
}
void KNumInput::setLabel(const QString & label, Qt::Alignment a)
{
if (label.isEmpty()) {
delete d->label;
d->label = 0;
d->labelAlignment = 0;
} else {
if (!d->label) {
d->label = new QLabel(this);
}
d->label->setText(label);
d->label->setObjectName("KNumInput::QLabel");
d->label->setAlignment(a);
// if no vertical alignment set, use Top alignment
if (!(a & (Qt::AlignTop | Qt::AlignBottom | Qt::AlignVCenter))) {
a |= Qt::AlignTop;
}
d->labelAlignment = a;
}
layout(true);
}
QString KNumInput::label() const
{
return d->label ? d->label->text() : QString();
}
void KNumInput::layout(bool deep)
{
int w1 = d->column1Width;
int w2 = d->column2Width;
// label sizeHint
d->labelSize = (d->label ? d->label->sizeHint() : QSize(0, 0));
if (d->label && (d->labelAlignment & Qt::AlignVCenter)) {
d->column1Width = d->labelSize.width() + 4;
} else {
d->column1Width = 0;
}
// slider sizeHint
d->sliderSize = (d->slider ? d->slider->sizeHint() : QSize(0, 0));
doLayout();
if (!deep) {
d->column1Width = w1;
d->column2Width = w2;
return;
}
w2 = d->column2Width;
KNumInput* p = d->previousNumInput;
while (p) {
p->doLayout();
w1 = qMax(w1, p->d->column1Width);
w2 = qMax(w2, p->d->column2Width);
p = p->d->previousNumInput;
}
p = d->nextNumInput;
while (p) {
p->doLayout();
w1 = qMax(w1, p->d->column1Width);
w2 = qMax(w2, p->d->column2Width);
p = p->d->nextNumInput;
}
p = this;
while (p) {
p->d->column1Width = w1;
p->d->column2Width = w2;
p = p->d->previousNumInput;
}
p = d->nextNumInput;
while (p) {
p->d->column1Width = w1;
p->d->column2Width = w2;
p = p->d->nextNumInput;
}
// kDebug() << "w1 " << w1 << " w2 " << w2;
}
QSize KNumInput::sizeHint() const
{
return minimumSizeHint();
}
void KNumInput::setSteps(int minor, int major)
{
if (d->slider) {
d->slider->setSingleStep(minor);
d->slider->setPageStep(major);
}
}
// ----------------------------------------------------------------------------
class KIntSpinBox::KIntSpinBoxPrivate
{
public:
KIntSpinBoxPrivate(KIntSpinBox *q, int val_base = 10): q(q), val_base(val_base)
{
connect(q, SIGNAL(valueChanged(int)), q, SLOT(updateSuffix(int)));
}
void updateSuffix(int value)
{
if (!pluralSuffix.isEmpty()) {
KLocalizedString s = pluralSuffix;
q->setSuffix(s.subs(value).toString());
}
}
KIntSpinBox *q;
int val_base;
KLocalizedString pluralSuffix;
};
KIntSpinBox::KIntSpinBox(QWidget *parent)
: QSpinBox(parent), d(new KIntSpinBoxPrivate(this))
{
setValue(0);
}
KIntSpinBox::~KIntSpinBox()
{
delete d;
}
KIntSpinBox::KIntSpinBox(int lower, int upper, int singleStep, int value, QWidget *parent, int base)
: QSpinBox(parent), d(new KIntSpinBoxPrivate(this, base))
{
setRange(lower, upper);
setSingleStep(singleStep);
setValue(value);
}
void KIntSpinBox::setBase(int base)
{
d->val_base = base;
}
int KIntSpinBox::base() const
{
return d->val_base;
}
QString KIntSpinBox::textFromValue(int v) const
{
return QString::number(v, d->val_base);
}
int KIntSpinBox::valueFromText(const QString &text) const
{
bool ok;
QString theText = text;
if (theText.startsWith(prefix())) {
theText.remove(0, prefix().length());
}
if (theText.endsWith(suffix())) {
theText.chop(suffix().length());
}
return theText.trimmed().toInt(&ok, d->val_base);
}
void KIntSpinBox::setEditFocus(bool mark)
{
lineEdit()->setFocus();
if (mark) {
lineEdit()->selectAll();
}
}
void KIntSpinBox::setSuffix(const KLocalizedString& suffix)
{
d->pluralSuffix = suffix;
if (suffix.isEmpty())
setSuffix(QString());
else
d->updateSuffix(value());
}
// ----------------------------------------------------------------------------
class KIntNumInput::KIntNumInputPrivate
{
public:
KIntNumInput *q;
int referencePoint;
short blockRelative;
KIntSpinBox* intSpinBox;
QSize intSpinBoxSize;
KIntNumInputPrivate(KIntNumInput *q, int r)
: q(q),
referencePoint(r),
blockRelative(0) {}
};
#ifndef KDE_NO_DEPRECATED
KIntNumInput::KIntNumInput(KNumInput* below, int val, QWidget *parent, int _base)
: KNumInput(parent, below)
, d(new KIntNumInputPrivate(this, val))
{
- init(val, _base);
+ initWidget(val, _base);
}
#endif
KIntNumInput::KIntNumInput(QWidget *parent)
: KNumInput(parent)
, d(new KIntNumInputPrivate(this, 0))
{
- init(0, 10);
+ initWidget(0, 10);
}
KIntNumInput::KIntNumInput(int val, QWidget *parent, int _base)
: KNumInput(parent)
, d(new KIntNumInputPrivate(this, val))
{
- init(val, _base);
+ initWidget(val, _base);
}
QSpinBox *KIntNumInput::spinBox() const
{
return d->intSpinBox;
}
-void KIntNumInput::init(int val, int _base)
+void KIntNumInput::initWidget(int val, int _base)
{
d->intSpinBox = new KIntSpinBox(INT_MIN, INT_MAX, 1, val, this, _base);
d->intSpinBox->setObjectName("KIntNumInput::KIntSpinBox");
// the KIntValidator is broken beyond believe for
// spinboxes which have suffix or prefix texts, so
// better don't use it unless absolutely necessary
if (_base != 10) {
kWarning() << "WARNING: Validation is broken in KIntNumInput! Needs to be fixed.";
// d->intSpinBox->setValidator(new KIntValidator(this, _base, "KNumInput::KIntValidator"));
}
connect(d->intSpinBox, SIGNAL(valueChanged(int)), SLOT(spinValueChanged(int)));
connect(this, SIGNAL(valueChanged(int)),
SLOT(slotEmitRelativeValueChanged(int)));
setFocusProxy(d->intSpinBox);
layout(true);
}
void KIntNumInput::setReferencePoint(int ref)
{
// clip to valid range:
ref = qMin(maximum(), qMax(minimum(), ref));
d->referencePoint = ref;
}
int KIntNumInput::referencePoint() const
{
return d->referencePoint;
}
void KIntNumInput::spinValueChanged(int val)
{
K_USING_KNUMINPUT_P(priv);
if (priv->slider) {
priv->slider->setValue(val);
}
emit valueChanged(val);
}
void KIntNumInput::slotEmitRelativeValueChanged(int value)
{
if (d->blockRelative || !d->referencePoint) {
return;
}
emit relativeValueChanged(double(value) / double(d->referencePoint));
}
void KIntNumInput::setSliderEnabled(bool slider)
{
K_USING_KNUMINPUT_P(priv);
if (slider) {
if (!priv->slider) {
priv->slider = new QSlider(Qt::Horizontal, this);
connect(priv->slider, SIGNAL(valueChanged(int)),
d->intSpinBox, SLOT(setValue(int)));
priv->slider->setTickPosition(QSlider::TicksBelow);
layout(true);
}
const int value = d->intSpinBox->value();
priv->slider->setRange(d->intSpinBox->minimum(), d->intSpinBox->maximum());
priv->slider->setPageStep(d->intSpinBox->singleStep());
priv->slider->setValue(value);
// calculate (upper-lower)/10 without overflowing int's:
const int major = calcDiffByTen(d->intSpinBox->maximum(), d->intSpinBox->minimum());
priv->slider->setSingleStep(d->intSpinBox->singleStep());
priv->slider->setPageStep(qMax(1, major));
priv->slider->setTickInterval(major);
} else {
if (priv->slider) {
layout(true);
}
delete priv->slider;
priv->slider = 0;
}
}
void KIntNumInput::setRange(int lower, int upper, int singleStep)
{
if (upper < lower || singleStep <= 0) {
kWarning() << "WARNING: KIntNumInput::setRange() called with bad arguments. Ignoring call...";
return;
}
d->intSpinBox->setMinimum(lower);
d->intSpinBox->setMaximum(upper);
d->intSpinBox->setSingleStep(singleStep);
singleStep = d->intSpinBox->singleStep(); // maybe QRangeControl didn't like our lineStep?
// check that reference point is still inside valid range:
setReferencePoint(referencePoint());
layout(true);
// update slider information if it's shown
K_USING_KNUMINPUT_P(priv);
setSliderEnabled(priv->slider);
}
#ifndef KDE_NO_DEPRECATED
void KIntNumInput::setRange(int lower, int upper, int singleStep, bool slider)
{
setRange(lower, upper, singleStep);
setSliderEnabled(slider);
}
#endif
void KIntNumInput::setMinimum(int min)
{
setRange(min, d->intSpinBox->maximum(), d->intSpinBox->singleStep());
}
int KIntNumInput::minimum() const
{
return d->intSpinBox->minimum();
}
void KIntNumInput::setMaximum(int max)
{
setRange(d->intSpinBox->minimum(), max, d->intSpinBox->singleStep());
}
int KIntNumInput::maximum() const
{
return d->intSpinBox->maximum();
}
int KIntNumInput::singleStep() const
{
return d->intSpinBox->singleStep();
}
void KIntNumInput::setSingleStep(int singleStep)
{
d->intSpinBox->setSingleStep(singleStep);
}
void KIntNumInput::setSuffix(const QString &suffix)
{
d->intSpinBox->setSuffix(suffix);
layout(true);
}
void KIntNumInput::setSuffix(const KLocalizedString& suffix)
{
d->intSpinBox->setSuffix(suffix);
layout(true);
}
QString KIntNumInput::suffix() const
{
return d->intSpinBox->suffix();
}
void KIntNumInput::setPrefix(const QString &prefix)
{
d->intSpinBox->setPrefix(prefix);
layout(true);
}
QString KIntNumInput::prefix() const
{
return d->intSpinBox->prefix();
}
void KIntNumInput::setEditFocus(bool mark)
{
d->intSpinBox->setEditFocus(mark);
}
QSize KIntNumInput::minimumSizeHint() const
{
K_USING_KNUMINPUT_P(priv);
ensurePolished();
int w;
int h;
h = qMax(d->intSpinBoxSize.height(), priv->sliderSize.height());
// if in extra row, then count it here
if (priv->label && (priv->labelAlignment & (Qt::AlignBottom | Qt::AlignTop))) {
h += 4 + priv->labelSize.height();
} else {
// label is in the same row as the other widgets
h = qMax(h, priv->labelSize.height() + 2);
}
w = priv->slider ? priv->slider->sizeHint().width() + KDialog::spacingHint() : 0;
w += priv->column1Width + priv->column2Width;
if (priv->labelAlignment & (Qt::AlignTop | Qt::AlignBottom)) {
w = qMax(w, priv->labelSize.width() + 4);
}
return QSize(w, h);
}
void KIntNumInput::doLayout()
{
K_USING_KNUMINPUT_P(priv);
d->intSpinBoxSize = d->intSpinBox->sizeHint();
priv->column2Width = d->intSpinBoxSize.width();
if (priv->label) {
priv->label->setBuddy(d->intSpinBox);
}
}
void KIntNumInput::resizeEvent(QResizeEvent* e)
{
K_USING_KNUMINPUT_P(priv);
int w = priv->column1Width;
int h = 0;
if (priv->label && (priv->labelAlignment & Qt::AlignTop)) {
priv->label->setGeometry(0, 0, e->size().width(), priv->labelSize.height());
h += priv->labelSize.height() + KDialog::spacingHint();
}
if (priv->label && (priv->labelAlignment & Qt::AlignVCenter)) {
priv->label->setGeometry(0, 0, w, d->intSpinBoxSize.height());
}
if (qApp->layoutDirection() == Qt::RightToLeft) {
d->intSpinBox->setGeometry(w, h, priv->slider ? priv->column2Width : qMax(priv->column2Width, e->size().width() - w), d->intSpinBoxSize.height());
w += priv->column2Width + KDialog::spacingHint();
if (priv->slider) {
priv->slider->setGeometry(w, h, e->size().width() - w, d->intSpinBoxSize.height() + KDialog::spacingHint());
}
} else if (priv->slider) {
priv->slider->setGeometry(w, h, e->size().width() - (w + priv->column2Width + KDialog::spacingHint()), d->intSpinBoxSize.height() + KDialog::spacingHint());
d->intSpinBox->setGeometry(w + priv->slider->size().width() + KDialog::spacingHint(), h, priv->column2Width, d->intSpinBoxSize.height());
} else {
d->intSpinBox->setGeometry(w, h, qMax(priv->column2Width, e->size().width() - w), d->intSpinBoxSize.height());
}
h += d->intSpinBoxSize.height() + 2;
if (priv->label && (priv->labelAlignment & Qt::AlignBottom)) {
priv->label->setGeometry(0, h, priv->labelSize.width(), priv->labelSize.height());
}
}
KIntNumInput::~KIntNumInput()
{
delete d;
}
void KIntNumInput::setValue(int val)
{
d->intSpinBox->setValue(val);
// slider value is changed by spinValueChanged
}
void KIntNumInput::setRelativeValue(double r)
{
if (!d->referencePoint) {
return;
}
++d->blockRelative;
setValue(qRound(d->referencePoint * r + 0.5));
--d->blockRelative;
}
double KIntNumInput::relativeValue() const
{
if (!d->referencePoint) {
return 0;
}
return double(value()) / double(d->referencePoint);
}
int KIntNumInput::value() const
{
return d->intSpinBox->value();
}
void KIntNumInput::setSpecialValueText(const QString& text)
{
d->intSpinBox->setSpecialValueText(text);
layout(true);
}
QString KIntNumInput::specialValueText() const
{
return d->intSpinBox->specialValueText();
}
void KIntNumInput::setLabel(const QString & label, Qt::Alignment a)
{
K_USING_KNUMINPUT_P(priv);
KNumInput::setLabel(label, a);
if (priv->label) {
priv->label->setBuddy(d->intSpinBox);
}
}
// ----------------------------------------------------------------------------
class KDoubleNumInput::KDoubleNumInputPrivate
{
public:
KDoubleNumInputPrivate(double r)
: spin(0),
referencePoint(r),
blockRelative(0),
exponentRatio(1.0) {}
QDoubleSpinBox * spin;
double referencePoint;
short blockRelative;
QSize editSize;
QString specialValue;
double exponentRatio;
};
KDoubleNumInput::KDoubleNumInput(QWidget *parent)
: KNumInput(parent)
, d(new KDoubleNumInputPrivate(0.0))
{
- init(0.0, 0.0, 9999.0, 0.01, 2);
+ initWidget(0.0, 0.0, 9999.0, 0.01, 2);
}
KDoubleNumInput::KDoubleNumInput(double lower, double upper, double value, QWidget *parent,
double singleStep, int precision)
: KNumInput(parent)
, d(new KDoubleNumInputPrivate(value))
{
- init(value, lower, upper, singleStep, precision);
+ initWidget(value, lower, upper, singleStep, precision);
}
#ifndef KDE_NO_DEPRECATED
KDoubleNumInput::KDoubleNumInput(KNumInput *below,
double lower, double upper, double value, QWidget *parent,
double singleStep, int precision)
: KNumInput(parent, below)
, d(new KDoubleNumInputPrivate(value))
{
- init(value, lower, upper, singleStep, precision);
+ initWidget(value, lower, upper, singleStep, precision);
}
#endif
KDoubleNumInput::~KDoubleNumInput()
{
delete d;
}
QString KDoubleNumInput::specialValueText() const
{
return d->specialValue;
}
-void KDoubleNumInput::init(double value, double lower, double upper,
+void KDoubleNumInput::initWidget(double value, double lower, double upper,
double singleStep, int precision)
{
d->spin = new QDoubleSpinBox(this);
d->spin->setRange(lower, upper);
d->spin->setSingleStep(singleStep);
d->spin->setValue(value);
d->spin->setDecimals(precision);
d->spin->setObjectName("KDoubleNumInput::QDoubleSpinBox");
setFocusProxy(d->spin);
connect(d->spin, SIGNAL(valueChanged(double)),
this, SIGNAL(valueChanged(double)));
connect(this, SIGNAL(valueChanged(double)),
this, SLOT(slotEmitRelativeValueChanged(double)));
updateLegacyMembers();
layout(true);
}
void KDoubleNumInput::updateLegacyMembers()
{
d->specialValue = specialValueText();
}
double KDoubleNumInput::mapSliderToSpin(int val) const
{
K_USING_KNUMINPUT_P(priv);
// map [slidemin,slidemax] to [spinmin,spinmax]
const double spinmin = d->spin->minimum();
const double spinmax = d->spin->maximum();
const double slidemin = priv->slider->minimum(); // cast int to double to avoid
const double slidemax = priv->slider->maximum(); // overflow in rel denominator
const double rel = (double(val) - slidemin) / (slidemax - slidemin);
Q_ASSERT(d->exponentRatio > 0.0);
return spinmin + pow(rel, d->exponentRatio ) * (spinmax - spinmin);
}
void KDoubleNumInput::sliderMoved(int val)
{
d->spin->setValue(mapSliderToSpin(val));
}
void KDoubleNumInput::spinBoxChanged(double val)
{
K_USING_KNUMINPUT_P(priv);
const double spinmin = d->spin->minimum();
const double spinmax = d->spin->maximum();
const double slidemin = priv->slider->minimum(); // cast int to double to avoid
const double slidemax = priv->slider->maximum(); // overflow in rel denominator
Q_ASSERT(d->exponentRatio > 0.0);
const double rel = pow((val - spinmin) / (spinmax - spinmin) , 1.0 / d->exponentRatio);
if (priv->slider) {
priv->slider->blockSignals(true);
priv->slider->setValue(qRound(slidemin + rel * (slidemax - slidemin)));
priv->slider->blockSignals(false);
}
}
void KDoubleNumInput::slotEmitRelativeValueChanged(double value)
{
if (!d->referencePoint) {
return;
}
emit relativeValueChanged(value / d->referencePoint);
}
QSize KDoubleNumInput::minimumSizeHint() const
{
K_USING_KNUMINPUT_P(priv);
ensurePolished();
int w;
int h;
h = qMax(d->editSize.height(), priv->sliderSize.height());
// if in extra row, then count it here
if (priv->label && (priv->labelAlignment & (Qt::AlignBottom | Qt::AlignTop))) {
h += 4 + priv->labelSize.height();
} else {
// label is in the same row as the other widgets
h = qMax(h, priv->labelSize.height() + 2);
}
w = priv->slider ? priv->slider->sizeHint().width() + KDialog::spacingHint() : 0;
w += priv->column1Width + priv->column2Width;
if (priv->labelAlignment & (Qt::AlignTop | Qt::AlignBottom)) {
w = qMax(w, priv->labelSize.width() + 4);
}
return QSize(w, h);
}
void KDoubleNumInput::resizeEvent(QResizeEvent* e)
{
K_USING_KNUMINPUT_P(priv);
int w = priv->column1Width;
int h = 0;
if (priv->label && (priv->labelAlignment & Qt::AlignTop)) {
priv->label->setGeometry(0, 0, e->size().width(), priv->labelSize.height());
h += priv->labelSize.height() + 4;
}
if (priv->label && (priv->labelAlignment & Qt::AlignVCenter)) {
priv->label->setGeometry(0, 0, w, d->editSize.height());
}
if (qApp->layoutDirection() == Qt::RightToLeft) {
d->spin->setGeometry(w, h, priv->slider ? priv->column2Width
: e->size().width() - w, d->editSize.height());
w += priv->column2Width + KDialog::spacingHint();
if (priv->slider)
priv->slider->setGeometry(w, h, e->size().width() - w, d->editSize.height() + KDialog::spacingHint());
} else if (priv->slider) {
priv->slider->setGeometry(w, h, e->size().width() -
(priv->column1Width + priv->column2Width + KDialog::spacingHint()),
d->editSize.height() + KDialog::spacingHint());
d->spin->setGeometry(w + priv->slider->width() + KDialog::spacingHint(), h,
priv->column2Width, d->editSize.height());
} else {
d->spin->setGeometry(w, h, e->size().width() - w, d->editSize.height());
}
h += d->editSize.height() + 2;
if (priv->label && (priv->labelAlignment & Qt::AlignBottom)) {
priv->label->setGeometry(0, h, priv->labelSize.width(), priv->labelSize.height());
}
}
void KDoubleNumInput::doLayout()
{
K_USING_KNUMINPUT_P(priv);
d->editSize = d->spin->sizeHint();
priv->column2Width = d->editSize.width();
}
void KDoubleNumInput::setValue(double val)
{
d->spin->setValue(val);
}
void KDoubleNumInput::setRelativeValue(double r)
{
if (!d->referencePoint) {
return;
}
++d->blockRelative;
setValue(r * d->referencePoint);
--d->blockRelative;
}
void KDoubleNumInput::setReferencePoint(double ref)
{
// clip to valid range:
ref = qMin(maximum(), qMax(minimum(), ref));
d->referencePoint = ref;
}
void KDoubleNumInput::setRange(double lower, double upper, double singleStep,
bool slider)
{
K_USING_KNUMINPUT_P(priv);
if (priv->slider) {
// don't update the slider to avoid an endless recursion
QDoubleSpinBox * spin = d->spin;
disconnect(spin, SIGNAL(valueChanged(double)),
priv->slider, SLOT(setValue(int)));
}
d->spin->setRange(lower, upper);
d->spin->setSingleStep(singleStep);
setSliderEnabled(slider);
setReferencePoint(referencePoint());
layout(true);
updateLegacyMembers();
}
void KDoubleNumInput::setSliderEnabled(bool enabled)
{
K_USING_KNUMINPUT_P(priv);
if (enabled) {
QDoubleSpinBox * spin = d->spin;
const double range = spin->maximum() - spin->minimum();
const double steps = range * pow(10.0, spin->decimals());
if (!priv->slider) {
priv->slider = new QSlider(Qt::Horizontal, this);
priv->slider->setTickPosition(QSlider::TicksBelow);
// feedback line: when one moves, the other moves, too:
connect(priv->slider, SIGNAL(valueChanged(int)),
SLOT(sliderMoved(int)));
layout(true);
}
if (steps > 1000 || d->exponentRatio != 1.0) {
priv->slider->setRange(0, 1000);
priv->slider->setSingleStep(1);
priv->slider->setPageStep(50);
} else {
const int singleSteps = qRound(steps);
priv->slider->setRange(0, singleSteps);
priv->slider->setSingleStep(1);
const int pageSteps = qBound(1, singleSteps / 20, 10);
priv->slider->setPageStep(pageSteps);
}
spinBoxChanged(spin->value());
connect(spin, SIGNAL(valueChanged(double)), SLOT(spinBoxChanged(double)));
} else {
if (priv->slider) {
layout(true);
}
delete priv->slider;
priv->slider = 0;
}
}
void KDoubleNumInput::setMinimum(double min)
{
K_USING_KNUMINPUT_P(priv);
setRange(min, maximum(), d->spin->singleStep(), priv->slider);
}
double KDoubleNumInput::minimum() const
{
return d->spin->minimum();
}
void KDoubleNumInput::setMaximum(double max)
{
K_USING_KNUMINPUT_P(priv);
setRange(minimum(), max, d->spin->singleStep(), priv->slider);
}
double KDoubleNumInput::maximum() const
{
return d->spin->maximum();
}
double KDoubleNumInput::singleStep() const
{
return d->spin->singleStep();
}
void KDoubleNumInput::setSingleStep(double singleStep)
{
d->spin->setSingleStep(singleStep);
}
double KDoubleNumInput::value() const
{
return d->spin->value();
}
double KDoubleNumInput::relativeValue() const
{
if (!d->referencePoint) {
return 0;
}
return value() / d->referencePoint;
}
double KDoubleNumInput::referencePoint() const
{
return d->referencePoint;
}
QString KDoubleNumInput::suffix() const
{
return d->spin->suffix();
}
QString KDoubleNumInput::prefix() const
{
return d->spin->prefix();
}
void KDoubleNumInput::setSuffix(const QString &suffix)
{
d->spin->setSuffix(suffix);
layout(true);
}
void KDoubleNumInput::setPrefix(const QString &prefix)
{
d->spin->setPrefix(prefix);
layout(true);
}
void KDoubleNumInput::setDecimals(int decimals)
{
d->spin->setDecimals(decimals);
layout(true);
}
int KDoubleNumInput::decimals() const
{
return d->spin->decimals();
}
void KDoubleNumInput::setSpecialValueText(const QString& text)
{
d->spin->setSpecialValueText(text);
layout(true);
updateLegacyMembers();
}
void KDoubleNumInput::setLabel(const QString & label, Qt::Alignment a)
{
K_USING_KNUMINPUT_P(priv);
KNumInput::setLabel(label, a);
if (priv->label) {
priv->label->setBuddy(d->spin);
}
}
double KDoubleNumInput::exponentRatio() const
{
return d->exponentRatio;
}
void KDoubleNumInput::setExponentRatio(double dbl)
{
Q_ASSERT(dbl > 0.0);
if(dbl > 0.0) {
d->exponentRatio = dbl;
spinBoxChanged( d->spin->value() ); // used to reset the value of the slider
} else {
kError() << "ExponentRatio need to be strictly positive.";
}
}
#include "moc_knuminput.cpp"
diff --git a/kdeui/widgets/knuminput.h b/kdeui/widgets/knuminput.h
index 0c91bdbf94..06d1ebdc28 100644
--- a/kdeui/widgets/knuminput.h
+++ b/kdeui/widgets/knuminput.h
@@ -1,800 +1,800 @@
/* This file is part of the KDE libraries
* Copyright (c) 1997 Patrick Dowler <dowler@morgul.fsh.uvic.ca>
* Copyright (c) 2000 Dirk Mueller <mueller@kde.org>
* Copyright (c) 2002 Marc Mutz <mutz@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef K_NUMINPUT_H
#define K_NUMINPUT_H
#include <kdeui_export.h>
#include <QWidget>
#include <QSpinBox>
class QSlider;
class QSpinBox;
class QValidator;
class KIntSpinBox;
class KNumInputPrivate;
class KLocalizedString;
/**
* You need to inherit from this class if you want to implement K*NumInput
* for a different variable type
*
*/
class KDEUI_EXPORT KNumInput : public QWidget
{
Q_OBJECT
Q_PROPERTY( QString label READ label WRITE setLabel )
public:
/**
* Default constructor
* @param parent If parent is 0, the new widget becomes a top-level
* window. If parent is another widget, this widget becomes a child
* window inside parent. The new widget is deleted when its parent is deleted.
*/
explicit KNumInput(QWidget* parent=0);
/**
* @param below A pointer to another KNumInput.
* @param parent parent widget
* \deprecated - use the version without the below parameter instead
*/
#ifndef KDE_NO_DEPRECATED
KDEUI_DEPRECATED KNumInput(QWidget *parent, KNumInput* below);
#endif
/**
* Destructor
*/
~KNumInput();
/**
* Sets the text and alignment of the main description label.
*
* @param label The text of the label.
* Use QString() to remove an existing one.
*
* @param a The alignment of the label (Qt::Alignment).
* Default is @p Qt:AlignLeft | @p Qt:AlignTop.
*
* The vertical alignment flags have special meaning with this
* widget:
*
* @li @p Qt:AlignTop The label is placed above the edit/slider
* @li @p Qt:AlignVCenter The label is placed left beside the edit
* @li @p Qt:AlignBottom The label is placed below the edit/slider
*
*/
virtual void setLabel(const QString & label, Qt::Alignment a = Qt::AlignLeft | Qt::AlignTop);
/**
* @return the text of the label.
*/
QString label() const;
/**
* @return if the num input has a slider.
*/
bool showSlider() const;
/**
* Sets the spacing of tickmarks for the slider.
*
* @param minor Minor tickmark separation.
* @param major Major tickmark separation.
*/
void setSteps(int minor, int major);
/**
* Returns a size which fits the contents of the control.
*
* @return the preferred size necessary to show the control
*/
virtual QSize sizeHint() const;
protected:
/**
* @return the slider widget.
* @internal
*/
QSlider *slider() const;
/**
* Call this function whenever you change something in the geometry
* of your KNumInput child.
*
*/
void layout(bool deep);
/**
* You need to overwrite this method and implement your layout
* calculations there.
*
* See KIntNumInput::doLayout and KDoubleNumInput::doLayout implementation
* for details.
*
*/
virtual void doLayout() = 0;
private:
friend class KNumInputPrivate;
KNumInputPrivate * const d;
Q_DISABLE_COPY(KNumInput)
};
/* ------------------------------------------------------------------------ */
/**
* @short An input widget for integer numbers, consisting of a spinbox and a slider.
*
* KIntNumInput combines a QSpinBox and optionally a QSlider
* with a label to make an easy to use control for setting some integer
* parameter. This is especially nice for configuration dialogs,
* which can have many such combinated controls.
*
* The slider is created only when the user specifies a range
* for the control using the setRange function or when the user
* calls setSliderEnabled.
*
* A special feature of KIntNumInput, designed specifically for
* the situation when there are several KIntNumInputs in a column,
* is that you can specify what portion of the control is taken by the
* QSpinBox (the remaining portion is used by the slider). This makes
* it very simple to have all the sliders in a column be the same size.
*
* It uses KIntValidator validator class. KIntNumInput enforces the
* value to be in the given range, and can display it in any base
* between 2 and 36.
*
* \image html kintnuminput.png "KDE Int Number Input Spinbox"
*/
class KDEUI_EXPORT KIntNumInput : public KNumInput
{
Q_OBJECT
Q_PROPERTY( int value READ value WRITE setValue NOTIFY valueChanged USER true )
Q_PROPERTY( int minimum READ minimum WRITE setMinimum )
Q_PROPERTY( int maximum READ maximum WRITE setMaximum )
Q_PROPERTY( int singleStep READ singleStep WRITE setSingleStep )
Q_PROPERTY( int referencePoint READ referencePoint WRITE setReferencePoint )
Q_PROPERTY( double relativeValue READ relativeValue WRITE setRelativeValue )
Q_PROPERTY( QString suffix READ suffix WRITE setSuffix )
Q_PROPERTY( QString prefix READ prefix WRITE setPrefix )
Q_PROPERTY( QString specialValueText READ specialValueText WRITE setSpecialValueText )
Q_PROPERTY( bool sliderEnabled READ showSlider WRITE setSliderEnabled )
public:
/**
* Constructs an input control for integer values
* with base 10 and initial value 0.
*/
explicit KIntNumInput(QWidget *parent=0);
/**
* Constructor
* It constructs a QSpinBox that allows the input of integer numbers
* in the range of -INT_MAX to +INT_MAX. To set a descriptive label,
* use setLabel(). To enforce the value being in a range and optionally to
* attach a slider to it, use setRange().
*
* @param value initial value for the control
* @param base numeric base used for display
* @param parent parent QWidget
*/
explicit KIntNumInput(int value, QWidget *parent=0,int base = 10);
/**
* Constructor
*
* the difference to the one above is the "below" parameter. It tells
* this instance that it is visually put below some other KNumInput widget.
* Note that these two KNumInput's need not to have the same parent widget
* or be in the same layout group.
* The effect is that it'll adjust its layout in correspondence
* with the layout of the other KNumInput's (you can build an arbitrary long
* chain).
*
* @param below append KIntNumInput to the KNumInput chain
* @param value initial value for the control
* @param base numeric base used for display
* @param parent parent QWidget
*
* \deprecated use the version without the below parameter instead.
*/
#ifndef KDE_NO_DEPRECATED
KDEUI_DEPRECATED KIntNumInput(KNumInput* below, int value, QWidget *parent, int base = 10);
#endif
/**
* Destructor
*
*
*/
virtual ~KIntNumInput();
/**
* @return the current value.
*/
int value() const;
/**
* @return the curent value in units of the referencePoint.
*/
double relativeValue() const;
/**
* @return the current reference point
*/
int referencePoint() const;
/**
* @return the suffix displayed behind the value.
* @see setSuffix()
*/
QString suffix() const;
/**
* @return the prefix displayed in front of the value.
* @see setPrefix()
*/
QString prefix() const;
/**
* @return the string displayed for a special value.
* @see setSpecialValueText()
*/
QString specialValueText() const;
/**
* Sets the allowed input range and the step size for the slider and the
* spin box.
*
* @param min minimum value
* @param max maximum value
* @param step step size
*/
void setRange(int min, int max, int singleStep=1);
/**
* @deprecated Use the other setRange function and setSliderEnabled instead
*/
#ifndef KDE_NO_DEPRECATED
KDEUI_DEPRECATED void setRange(int min, int max, int singleStep, bool slider);
#endif
/**
* @param enabled Show the slider
* @default enabled
*/
void setSliderEnabled(bool enabled=true);
/**
* Sets the minimum value.
*/
void setMinimum(int min);
/**
* @return the minimum value.
*/
int minimum() const;
/**
* Sets the maximum value.
*/
void setMaximum(int max);
/**
* @return the maximum value.
*/
int maximum() const;
/**
* @return the step of the spin box
*/
int singleStep() const;
/**
* @return the step of the spin box
*/
void setSingleStep(int step);
/**
* Sets the special value text. If set, the SpinBox will display
* this text instead of the numeric value whenever the current
* value is equal to minVal(). Typically this is used for indicating
* that the choice has a special (default) meaning.
*/
void setSpecialValueText(const QString& text);
virtual void setLabel(const QString & label, Qt::Alignment a = Qt::AlignLeft | Qt::AlignTop);
/**
* This method returns the minimum size necessary to display the
* control. The minimum size is enough to show all the labels
* in the current font (font change may invalidate the return value).
*
* @return the minimum size necessary to show the control
*/
virtual QSize minimumSizeHint() const;
public Q_SLOTS:
/**
* Sets the value of the control.
*/
void setValue(int);
/**
* Sets the value in units of the referencePoint
*/
void setRelativeValue(double);
/**
* Sets the reference point for relativeValue.
*/
void setReferencePoint(int);
/**
* Sets the suffix to @p suffix.
* Use QString() to disable this feature.
* Formatting has to be provided (e.g. a space separator between the
* prepended @p value and the suffix's text has to be provided
* as the first character in the suffix).
*
* @see QSpinBox::setSuffix(), #setPrefix()
*/
void setSuffix(const QString &suffix);
/**
* Sets the suffix to @p suffix.
* Use this to add a plural-aware suffix, e.g. by using ki18np("singular", "plural").
*
* @since 4.3
*/
void setSuffix(const KLocalizedString &suffix);
/**
* Sets the prefix to @p prefix.
* Use QString() to disable this feature.
* Formatting has to be provided (see above).
*
* @see QSpinBox::setPrefix(), #setSuffix()
*/
void setPrefix(const QString &prefix);
/**
* sets focus to the edit widget and marks all text in if mark == true
*
*/
void setEditFocus( bool mark = true );
Q_SIGNALS:
/**
* Emitted every time the value changes (by calling setValue() or
* by user interaction).
*/
void valueChanged(int);
/**
* Emitted whenever valueChanged is. Contains the change
* relative to the referencePoint.
*/
void relativeValueChanged(double);
private Q_SLOTS:
void spinValueChanged(int);
void slotEmitRelativeValueChanged(int);
protected:
/**
* @return the spin box widget.
* @internal
*/
QSpinBox *spinBox() const;
virtual void doLayout();
void resizeEvent ( QResizeEvent * );
private:
- void init(int value, int _base);
+ void initWidget(int value, int _base);
private:
class KIntNumInputPrivate;
friend class KIntNumInputPrivate;
KIntNumInputPrivate * const d;
Q_DISABLE_COPY(KIntNumInput)
};
/* ------------------------------------------------------------------------ */
class KDoubleLine;
/**
* @short An input control for real numbers, consisting of a spinbox and a slider.
*
* KDoubleNumInput combines a QSpinBox and optionally a QSlider
* with a label to make an easy to use control for setting some float
* parameter. This is especially nice for configuration dialogs,
* which can have many such combinated controls.
*
* The slider is created only when the user specifies a range
* for the control using the setRange function with the slider
* parameter set to "true".
*
* A special feature of KDoubleNumInput, designed specifically for
* the situation when there are several instances in a column,
* is that you can specify what portion of the control is taken by the
* QSpinBox (the remaining portion is used by the slider). This makes
* it very simple to have all the sliders in a column be the same size.
*
* \image html kdoublenuminput.png "KDE Double Number Input Spinbox"
*
* @see KIntNumInput
*/
class KDEUI_EXPORT KDoubleNumInput : public KNumInput
{
Q_OBJECT
Q_PROPERTY( double value READ value WRITE setValue NOTIFY valueChanged USER true )
Q_PROPERTY( double minimum READ minimum WRITE setMinimum )
Q_PROPERTY( double maximum READ maximum WRITE setMaximum )
Q_PROPERTY( double singleStep READ singleStep WRITE setSingleStep )
Q_PROPERTY( QString suffix READ suffix WRITE setSuffix )
Q_PROPERTY( QString prefix READ prefix WRITE setPrefix )
Q_PROPERTY( QString specialValueText READ specialValueText WRITE setSpecialValueText )
Q_PROPERTY( int decimals READ decimals WRITE setDecimals )
Q_PROPERTY( double referencePoint READ referencePoint WRITE setReferencePoint )
Q_PROPERTY( double relativeValue READ relativeValue WRITE setRelativeValue )
Q_PROPERTY( bool sliderEnabled READ showSlider WRITE setSliderEnabled )
Q_PROPERTY( double exponentRatio READ exponentRatio WRITE setExponentRatio )
public:
/**
* Constructs an input control for double values
* with initial value 0.00.
*/
explicit KDoubleNumInput(QWidget *parent = 0);
/**
* Constructor
*
* @param lower lower boundary value
* @param upper upper boundary value
* @param value initial value for the control
* @param singleStep step size to use for up/down arrow clicks
* @param precision number of digits after the decimal point
* @param parent parent QWidget
*/
KDoubleNumInput(double lower, double upper, double value, QWidget *parent=0,double singleStep=0.01,
int precision=2);
/**
* destructor
*/
virtual ~KDoubleNumInput();
/**
* Constructor
*
* the difference here is the "below" parameter. It tells this
* instance that it is visually put below some other KNumInput
* widget. Note that these two KNumInput's need not to have the
* same parent widget or be in the same layout group. The effect
* is that it'll adjust its layout in correspondence with the
* layout of the other KNumInput's (you can build an arbitrary long
* chain).
*
* @param below append KDoubleNumInput to the KDoubleNumInput chain
* @param lower lower boundary value
* @param upper upper boundary value
* @param value initial value for the control
* @param singleStep step size to use for up/down arrow clicks
* @param precision number of digits after the decimal point
* @param parent parent QWidget
*
* \deprecated use the version without below instead
*/
#ifndef KDE_NO_DEPRECATED
KDEUI_DEPRECATED KDoubleNumInput(KNumInput* below,
double lower, double upper, double value, QWidget *parent=0,double singleStep=0.02,
int precision=2);
#endif
/**
* @return the current value.
*/
double value() const;
/**
* @return the suffix.
* @see setSuffix()
*/
QString suffix() const;
/**
* @return the prefix.
* @see setPrefix()
*/
QString prefix() const;
/**
* @return number of decimals.
* @see setDecimals()
*/
int decimals() const;
/**
* @return the string displayed for a special value.
* @see setSpecialValueText()
*/
QString specialValueText() const;
/**
* @param min minimum value
* @param max maximum value
* @param singleStep step size for the QSlider
* @param slider whether the slider is created or not
*/
void setRange(double min, double max, double singleStep=1, bool slider=true);
/**
* @param enabled Show the slider
* @default enabled
*/
void setSliderEnabled(bool enabled);
/**
* Sets the minimum value.
*/
void setMinimum(double min);
/**
* @return the minimum value.
*/
double minimum() const;
/**
* Sets the maximum value.
*/
void setMaximum(double max);
/**
* @return the maximum value.
*/
double maximum() const;
/**
* @return the step of the spin box
*/
double singleStep() const;
/**
* @return the step of the spin box
*/
void setSingleStep(double singleStep);
/**
* Specifies the number of digits to use.
*/
void setDecimals(int decimals);
#ifndef KDE_NO_DEPRECATED
KDEUI_DEPRECATED void setPrecision(int precision) { setDecimals(precision); }
#endif
/**
* @return the reference point for relativeValue calculation
*/
double referencePoint() const;
/**
* @return the current value in units of referencePoint.
*/
double relativeValue() const;
/**
* Sets the special value text. If set, the spin box will display
* this text instead of the numeric value whenever the current
* value is equal to minVal(). Typically this is used for indicating
* that the choice has a special (default) meaning.
*/
void setSpecialValueText(const QString& text);
virtual void setLabel(const QString & label, Qt::Alignment a = Qt::AlignLeft | Qt::AlignTop);
virtual QSize minimumSizeHint() const;
/**
* @return the value of the exponent use to map the slider to the
* spin box.
*/
double exponentRatio() const;
/**
* @param dbl the value of the exponent use to map the slider to the
* spin box (dbl need to be strictly positive).
*/
void setExponentRatio(double dbl);
public Q_SLOTS:
/**
* Sets the value of the control.
*/
void setValue(double);
/**
* Sets the value in units of referencePoint.
*/
void setRelativeValue(double);
/**
* Sets the reference Point to @p ref. It @p ref == 0, emitting of
* relativeValueChanged is blocked and relativeValue
* just returns 0.
*/
void setReferencePoint(double ref);
/**
* Sets the suffix to be displayed to @p suffix. Use QString() to disable
* this feature. Note that the suffix is attached to the value without any
* spacing. So if you prefer to display a space separator, set suffix
* to something like " cm".
* @see setSuffix()
*/
void setSuffix(const QString &suffix);
/**
* Sets the prefix to be displayed to @p prefix. Use QString() to disable
* this feature. Note that the prefix is attached to the value without any
* spacing.
* @see setPrefix()
*/
void setPrefix(const QString &prefix);
Q_SIGNALS:
/**
* Emitted every time the value changes (by calling setValue() or
* by user interaction).
*/
void valueChanged(double);
/**
* This is an overloaded member function, provided for
* convenience. It essentially behaves like the above function.
*
* Contains the value in units of referencePoint.
*/
void relativeValueChanged(double);
private Q_SLOTS:
void sliderMoved(int);
void spinBoxChanged(double);
void slotEmitRelativeValueChanged(double);
protected:
virtual void doLayout();
void resizeEvent ( QResizeEvent * );
friend class KDoubleLine;
private:
- void init(double value, double lower, double upper,
+ void initWidget(double value, double lower, double upper,
double singleStep, int precision);
double mapSliderToSpin(int) const;
void updateLegacyMembers();
private:
class KDoubleNumInputPrivate;
friend class KDoubleNumInputPrivate;
KDoubleNumInputPrivate * const d;
Q_DISABLE_COPY(KDoubleNumInput)
};
/* ------------------------------------------------------------------------ */
/**
* @short A QSpinBox with support for arbitrary base numbers.
*
* A QSpinBox with support for arbitrary base numbers
* (e.g. hexadecimal).
*
* The class provides an easy interface to use other
* numeric systems than the decimal.
*
* \image html kintspinbox.png "KDE Integer Input Spinboxes with hexadecimal and binary input"
*/
class KDEUI_EXPORT KIntSpinBox : public QSpinBox
{
Q_OBJECT
Q_PROPERTY( int base READ base WRITE setBase )
public:
/**
* Constructor.
*
* Constructs a widget with an integer inputline with a little scrollbar
* and a slider, with minimal value 0, maximal value 99, step 1, base 10
* and initial value 0.
*/
explicit KIntSpinBox( QWidget *parent = 0 );
/**
* Constructor.
*
* Constructs a widget with an integer inputline with a little scrollbar
* and a slider.
*
* @param lower The lowest valid value.
* @param upper The greatest valid value.
* @param singleStep The step size of the scrollbar.
* @param value The actual value.
* @param base The base of the used number system.
* @param parent The parent of the widget.
*/
KIntSpinBox(int lower, int upper, int singleStep, int value, QWidget *parent,int base = 10);
/**
* Destructor.
*/
virtual ~KIntSpinBox();
/**
* Sets the base in which the numbers in the spin box are represented.
*/
void setBase(int base);
/**
* @return the base in which numbers in the spin box are represented.
*/
int base() const;
/**
* sets focus and optionally marks all text
*
*/
void setEditFocus(bool mark);
/**
* Sets the suffix to @p suffix.
* Use this to add a plural-aware suffix, e.g. by using ki18np("singular", "plural").
*
* @since 4.3
*/
void setSuffix(const KLocalizedString &suffix);
using QSpinBox::setSuffix;
protected:
/**
* Overloaded the method in QSpinBox
* to make use of the base given in the constructor.
*/
virtual QString textFromValue(int) const;
/**
* Overloaded the method in QSpinBox
* to make use of the base given in the constructor.
*/
virtual int valueFromText(const QString &text) const;
private:
class KIntSpinBoxPrivate;
friend class KIntSpinBoxPrivate;
KIntSpinBoxPrivate *const d;
Q_DISABLE_COPY(KIntSpinBox)
Q_PRIVATE_SLOT(d, void updateSuffix(int))
};
#endif // K_NUMINPUT_H
diff --git a/kdeui/widgets/kpushbutton.cpp b/kdeui/widgets/kpushbutton.cpp
index a4770a743e..5464cfbfe9 100644
--- a/kdeui/widgets/kpushbutton.cpp
+++ b/kdeui/widgets/kpushbutton.cpp
@@ -1,378 +1,378 @@
/* This file is part of the KDE libraries
Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kpushbutton.h"
#include <QStyleOptionToolButton>
#include <QStylePainter>
#include <QDrag>
#include <QActionEvent>
#include <QMenu>
#include <QtCore/QPointer>
#include <QStyle>
#include <QtCore/QTimer>
#include <config.h>
#include <kconfig.h>
#include <kglobal.h>
#include <kglobalsettings.h>
#include <kguiitem.h>
#include <kicon.h>
#include "kauthaction.h"
#include "kauthactionwatcher.h"
static bool s_useIcons = false;
class KPushButton::KPushButtonPrivate
{
public:
KPushButtonPrivate(KPushButton *_parent) : parent(_parent), m_dragEnabled( false ), authAction(0)
{
}
KPushButton *parent;
KGuiItem item;
KStandardGuiItem::StandardItem itemType;
QPointer<QMenu> delayedMenu;
QTimer * delayedMenuTimer;
bool m_dragEnabled;
QPoint startPos;
KAuth::Action *authAction;
// TODO: Remove whenever QIcon overlays will get fixed
QIcon oldIcon;
void slotSettingsChanged( int );
void slotPressedInternal();
void slotClickedInternal();
void authStatusChanged(int status);
void slotDelayedMenuTimeout();
void readSettings();
};
void KPushButton::KPushButtonPrivate::slotSettingsChanged( int /* category */ )
{
readSettings();
parent->setIcon( item.icon() );
}
void KPushButton::KPushButtonPrivate::slotPressedInternal()
{
if (!delayedMenu.isNull()) {
if (delayedMenuTimer==0) {
delayedMenuTimer=new QTimer(parent);
delayedMenuTimer->setSingleShot(true);
connect(delayedMenuTimer,SIGNAL(timeout()),parent,SLOT(slotDelayedMenuTimeout()));
}
const int delay=parent->style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, parent);
delayedMenuTimer->start((delay<=0) ? 150:delay);
}
}
void KPushButton::KPushButtonPrivate::slotClickedInternal()
{
if (delayedMenuTimer)
delayedMenuTimer->stop();
if (authAction) {
KAuth::Action::AuthStatus s = authAction->earlyAuthorize();
switch(s) {
case KAuth::Action::Denied:
parent->setEnabled(false);
break;
case KAuth::Action::Authorized:
emit parent->authorized(authAction);
break;
default:
break;
}
}
}
void KPushButton::KPushButtonPrivate::slotDelayedMenuTimeout() {
delayedMenuTimer->stop();
if (!delayedMenu.isNull()) {
parent->setMenu(delayedMenu);
parent->showMenu();
parent->setMenu(0);
}
}
void KPushButton::KPushButtonPrivate::authStatusChanged(int status)
{
KAuth::Action::AuthStatus s = (KAuth::Action::AuthStatus)status;
switch(s) {
case KAuth::Action::Authorized:
parent->setEnabled(true);
if(!oldIcon.isNull()) {
parent->setIcon(oldIcon);
oldIcon = KIcon();
}
break;
case KAuth::Action::AuthRequired:
parent->setEnabled(true);
oldIcon = KIcon(parent->icon());
parent->setIcon(KIcon("dialog-password"));
break;
default:
parent->setEnabled(false);
if(!oldIcon.isNull()) {
parent->setIcon(oldIcon);
oldIcon = KIcon();
}
}
}
void KPushButton::KPushButtonPrivate::readSettings()
{
s_useIcons = KGlobalSettings::showIconsOnPushButtons();
}
KPushButton::KPushButton( QWidget *parent )
: QPushButton( parent ), d( new KPushButtonPrivate(this) )
{
- init( KGuiItem( "" ) );
+ initWidget( KGuiItem( "" ) );
}
KPushButton::KPushButton( const QString &text, QWidget *parent )
: QPushButton( parent ), d( new KPushButtonPrivate(this) )
{
- init( KGuiItem( text ) );
+ initWidget( KGuiItem( text ) );
}
KPushButton::KPushButton( const QIcon &icon, const QString &text,
QWidget *parent )
: QPushButton( text, parent ), d( new KPushButtonPrivate(this) )
{
- init( KGuiItem( text, icon ) );
+ initWidget( KGuiItem( text, icon ) );
}
KPushButton::KPushButton( const KGuiItem &item, QWidget *parent )
: QPushButton( parent ), d( new KPushButtonPrivate(this) )
{
- init( item );
+ initWidget( item );
}
KPushButton::~KPushButton()
{
delete d;
}
-void KPushButton::init( const KGuiItem &item )
+void KPushButton::initWidget( const KGuiItem &item )
{
d->item = item;
d->itemType = (KStandardGuiItem::StandardItem) 0;
d->delayedMenuTimer=0;
connect(this,SIGNAL(pressed()), this, SLOT(slotPressedInternal()));
connect(this,SIGNAL(clicked()), this, SLOT(slotClickedInternal()));
// call QPushButton's implementation since we don't need to
// set the GUI items text or check the state of the icon set
QPushButton::setText( d->item.text() );
static bool initialized = false;
if ( !initialized ) {
d->readSettings();
initialized = true;
}
setIcon( d->item.icon() );
setToolTip( item.toolTip() );
setWhatsThis(item.whatsThis());
connect( KGlobalSettings::self(), SIGNAL( settingsChanged(int) ),
SLOT( slotSettingsChanged(int) ) );
}
bool KPushButton::isDragEnabled() const
{
return d->m_dragEnabled;
}
void KPushButton::setGuiItem( const KGuiItem& item )
{
d->item = item;
// call QPushButton's implementation since we don't need to
// set the GUI items text or check the state of the icon set
QPushButton::setText( d->item.text() );
setIcon( d->item.icon() );
setToolTip( d->item.toolTip() );
setEnabled( d->item.isEnabled() );
setWhatsThis( d->item.whatsThis() );
}
void KPushButton::setGuiItem( KStandardGuiItem::StandardItem item )
{
setGuiItem( KStandardGuiItem::guiItem(item) );
d->itemType = item;
}
KStandardGuiItem::StandardItem KPushButton::guiItem() const
{
return d->itemType;
}
void KPushButton::setText( const QString &text )
{
QPushButton::setText(text);
// we need to re-evaluate the icon set when the text
// is removed, or when it is supplied
if (text.isEmpty() != d->item.text().isEmpty())
setIcon(d->item.icon());
d->item.setText(text);
}
void KPushButton::setIcon( const QIcon &icon )
{
d->item.setIcon(icon);
if ( s_useIcons || text().isEmpty() )
QPushButton::setIcon( icon );
else
QPushButton::setIcon( QIcon() );
}
void KPushButton::setDragEnabled( bool enable )
{
d->m_dragEnabled = enable;
}
void KPushButton::mousePressEvent( QMouseEvent *e )
{
if ( d->m_dragEnabled )
d->startPos = e->pos();
QPushButton::mousePressEvent( e );
}
void KPushButton::mouseMoveEvent( QMouseEvent *e )
{
if ( !d->m_dragEnabled )
{
QPushButton::mouseMoveEvent( e );
return;
}
if ( (e->buttons() & Qt::LeftButton) &&
(e->pos() - d->startPos).manhattanLength() >
KGlobalSettings::dndEventDelay() )
{
startDrag();
setDown( false );
}
}
QDrag * KPushButton::dragObject()
{
return 0;
}
void KPushButton::startDrag()
{
QDrag *d = dragObject();
if ( d )
d->start();
}
void KPushButton::setDelayedMenu(QMenu *delayedMenu)
{
d->delayedMenu=delayedMenu;
}
QMenu* KPushButton::delayedMenu()
{
return d->delayedMenu;
}
KAuth::Action *KPushButton::authAction() const
{
return d->authAction;
}
void KPushButton::setAuthAction(const QString &actionName)
{
if (actionName.isEmpty()) {
setAuthAction(0);
} else {
setAuthAction(new KAuth::Action(actionName));
}
}
void KPushButton::setAuthAction(KAuth::Action *action)
{
if (d->authAction == action) {
return;
}
if (d->authAction) {
disconnect(d->authAction->watcher(), SIGNAL(statusChanged(int)),
this, SLOT(authStatusChanged(int)));
//delete d->authAction;
d->authAction = 0;
if (!d->oldIcon.isNull()) {
setIcon(d->oldIcon);
d->oldIcon = KIcon();
}
}
if (action != 0) {
d->authAction = action;
// Set the parent widget
d->authAction->setParentWidget(this);
connect(d->authAction->watcher(), SIGNAL(statusChanged(int)),
this, SLOT(authStatusChanged(int)));
d->authStatusChanged(d->authAction->status());
}
}
QSize KPushButton::sizeHint() const
{
const bool tempSetMenu = !menu() && d->delayedMenu;
if (tempSetMenu)
const_cast<KPushButton *>(this)->setMenu(d->delayedMenu);
const QSize sz = QPushButton::sizeHint();
if (tempSetMenu)
const_cast<KPushButton *>(this)->setMenu(0);
return sz;
}
void KPushButton::paintEvent( QPaintEvent * )
{
QStylePainter p(this);
QStyleOptionButton option;
initStyleOption(&option);
if (d->delayedMenu)
option.features |= QStyleOptionButton::HasMenu;
p.drawControl(QStyle::CE_PushButton, option);
}
#include "moc_kpushbutton.cpp"
diff --git a/kdeui/widgets/kpushbutton.h b/kdeui/widgets/kpushbutton.h
index 526e099176..26cc8f135c 100644
--- a/kdeui/widgets/kpushbutton.h
+++ b/kdeui/widgets/kpushbutton.h
@@ -1,226 +1,226 @@
/* This file is part of the KDE libraries
Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KPUSHBUTTON_H
#define KPUSHBUTTON_H
#include <QPushButton>
#include <kstandardguiitem.h>
class QDrag;
class QMenu;
namespace KAuth {
class Action;
}
/**
* @brief A QPushButton with drag-support and KGuiItem support
*
* This is nothing but a QPushButton with drag-support and KGuiItem support.
* You must call #setDragEnabled (true) and override the virtual method
* dragObject() to specify the QDragObject to be used.
*
* \image html kpushbutton.png "KDE Push Button"
*
* @author Carsten Pfeiffer <pfeiffer@kde.org>
*/
class KDEUI_EXPORT KPushButton : public QPushButton
{
Q_OBJECT
Q_PROPERTY(bool isDragEnabled READ isDragEnabled WRITE setDragEnabled)
public:
/**
* Default constructor.
*/
explicit KPushButton( QWidget *parent = 0 );
/**
* Constructor, that sets the button-text to @p text
*/
explicit KPushButton( const QString &text, QWidget *parent = 0 );
/**
* Constructor, that sets an icon and the button-text to @p text
*/
KPushButton( const QIcon &icon, const QString &text, QWidget *parent = 0 );
/**
* Constructor that takes a KGuiItem for the text, the icon, the tooltip
* and the what's this help
*/
explicit KPushButton( const KGuiItem &item, QWidget *parent = 0 );
/**
* Destructs the button.
*/
~KPushButton();
/**
* Enables/disables drag-support. Default is disabled.
*/
void setDragEnabled( bool enable );
/**
* @returns if drag support is enabled or not.
*/
bool isDragEnabled() const;
/**
* Sets the KGuiItem for this button.
*/
void setGuiItem( const KGuiItem& item );
/**
* Sets the standard KGuiItem for this button.
*/
void setGuiItem( KStandardGuiItem::StandardItem item );
/**
* Reads the standard KGuiItem for this button.
*/
KStandardGuiItem::StandardItem guiItem() const;
/**
* Sets the Icon Set for this button. It also takes into account the
* KGlobalSettings::showIconsOnPushButtons() setting.
*/
void setIcon( const QIcon &icon );
/**
* Sets the text of the button
*/
void setText( const QString &text );
/**
* Sets a delayed popup menu
* for consistency, since menu() isn't virtual
*/
void setDelayedMenu(QMenu *delayed_menu);
/**
* returns a delayed popup menu
* since menu() isn't virtual
*/
QMenu *delayedMenu();
/**
* Reimplemented to add arrow for delayed menu
* @since 4.4
*/
virtual QSize sizeHint() const;
/**
* Returns the action object associated with this button, or 0 if it does not have one
*
* @returns the KAuth::Action associated with this button.
*/
KAuth::Action *authAction() const;
/**
* Sets the action object associated with this button
*
* By setting a KAuth::Action, this button will become associated with it, and
* whenever it gets clicked, it will trigger the authorization and execution process
* for the action. The signal activated will also be emitted whenever the button gets
* clicked and the action gets authorized. Pass 0 to this function to disassociate the button
*
* @param action the KAuth::Action to associate with this button.
*/
void setAuthAction(KAuth::Action *action);
/**
* Sets the action object associated with this button
*
* Overloaded member to allow creating the action by name
*
* @param actionName the name of the action to associate
*/
void setAuthAction(const QString &actionName);
protected:
/**
* Reimplement this and return the QDrag object that should be used
* for the drag. Remember to give it "this" as parent.
*
* Default implementation returns 0, so that no drag is initiated.
*/
virtual QDrag * dragObject();
/**
* Reimplemented to add drag-support
*/
virtual void mousePressEvent( QMouseEvent * );
/**
* Reimplemented to add drag-support
*/
virtual void mouseMoveEvent( QMouseEvent * );
/**
* Reimplemented to add arrow for delayed menu
* @since 4.4
*/
virtual void paintEvent( QPaintEvent * );
/**
* Starts a drag (dragCopy() by default) using dragObject()
*/
virtual void startDrag();
Q_SIGNALS:
/**
* Signal emitted when the button is triggered and authorized
*
* If the button needs authorization, whenever the user triggers it,
* the authorization process automatically begins.
* If it succeeds, this signal is emitted. The KAuth::Action object is provided for convenience
* if you have multiple Action objects, but of course it's always the same set with
* setAuthAction().
*
* WARNING: If your button needs authorization you should connect eventual slots processing
* stuff to this signal, and NOT clicked. Clicked will be emitted even if the user has not
* been authorized
*
* @param action The object set with setAuthAction()
*/
void authorized(KAuth::Action *action);
private:
/**
* Internal.
* Initialize the KPushButton instance
*/
- void init( const KGuiItem &item );
+ void initWidget( const KGuiItem &item );
private:
class KPushButtonPrivate;
KPushButtonPrivate * const d;
Q_PRIVATE_SLOT(d, void slotSettingsChanged( int ))
Q_PRIVATE_SLOT(d, void slotPressedInternal())
Q_PRIVATE_SLOT(d, void slotClickedInternal())
Q_PRIVATE_SLOT(d, void slotDelayedMenuTimeout())
Q_PRIVATE_SLOT(d, void authStatusChanged(int))
};
#endif // KPUSHBUTTON_H
diff --git a/kdeui/widgets/kruler.cpp b/kdeui/widgets/kruler.cpp
index 76da85b7a7..993c2fd4a4 100644
--- a/kdeui/widgets/kruler.cpp
+++ b/kdeui/widgets/kruler.cpp
@@ -1,774 +1,774 @@
/* This file is part of the KDE libraries
Copyright (C) 1998 Jörg Habenicht (j.habenicht@europemail.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kruler.h"
#include <QFont>
#include <QPolygon>
#include <QStylePainter>
#define INIT_VALUE 0
#define INIT_MIN_VALUE 0
#define INIT_MAX_VALUE 100
#define INIT_TINY_MARK_DISTANCE 1
#define INIT_LITTLE_MARK_DISTANCE 5
#define INIT_MIDDLE_MARK_DISTANCE (INIT_LITTLE_MARK_DISTANCE * 2)
#define INIT_BIG_MARK_DISTANCE (INIT_LITTLE_MARK_DISTANCE * 10)
#define INIT_SHOW_TINY_MARK false
#define INIT_SHOW_LITTLE_MARK true
#define INIT_SHOW_MEDIUM_MARK true
#define INIT_SHOW_BIG_MARK true
#define INIT_SHOW_END_MARK true
#define INIT_SHOW_POINTER true
#define INIT_SHOW_END_LABEL true
#define INIT_PIXEL_PER_MARK (double)10.0 /* distance between 2 base marks in pixel */
#define INIT_OFFSET (-20)
#define INIT_LENGTH_FIX true
#define INIT_END_OFFSET 0
#define FIX_WIDTH 20 /* widget width in pixel */
#define LINE_END (FIX_WIDTH - 3)
#define END_MARK_LENGTH (FIX_WIDTH - 6)
#define END_MARK_X2 LINE_END
#define END_MARK_X1 (END_MARK_X2 - END_MARK_LENGTH)
#define BIG_MARK_LENGTH (END_MARK_LENGTH*3/4)
#define BIG_MARK_X2 LINE_END
#define BIG_MARK_X1 (BIG_MARK_X2 - BIG_MARK_LENGTH)
#define MIDDLE_MARK_LENGTH (END_MARK_LENGTH/2)
#define MIDDLE_MARK_X2 LINE_END
#define MIDDLE_MARK_X1 (MIDDLE_MARK_X2 - MIDDLE_MARK_LENGTH)
#define LITTLE_MARK_LENGTH (MIDDLE_MARK_LENGTH/2)
#define LITTLE_MARK_X2 LINE_END
#define LITTLE_MARK_X1 (LITTLE_MARK_X2 - LITTLE_MARK_LENGTH)
#define BASE_MARK_LENGTH (LITTLE_MARK_LENGTH/2)
#define BASE_MARK_X2 LINE_END
#define BASE_MARK_X1 (BASE_MARK_X2 - BASE_MARK_LENGTH)
#define LABEL_SIZE 8
#define END_LABEL_X 4
#define END_LABEL_Y (END_LABEL_X + LABEL_SIZE - 2)
#undef PROFILING
#ifdef PROFILING
# include <qdatetime.h>
#endif
class KRuler::KRulerPrivate
{
public:
int endOffset_length; /* marks the offset at the end of the ruler
* i.e. right side at horizontal and down side
* at vertical rulers.
* the ruler end mark is moved endOffset_length
* ticks away from the widget end.
* positive offset moves end mark inside the ruler.
* if lengthFix is true, endOffset_length holds the
* length of the ruler.
*/
int fontWidth; // ONLY valid for vertical rulers
QAbstractSlider range;
Qt::Orientation dir;
int tmDist;
int lmDist;
int mmDist;
int bmDist;
int offset;
bool showtm : 1; /* show tiny, little, medium, big, endmarks */
bool showlm : 1;
bool showmm : 1;
bool showbm : 1;
bool showem : 1;
bool showpointer : 1;
bool showEndL : 1;
bool lengthFix : 1;
double ppm; /* pixel per mark */
QString endlabel;
};
KRuler::KRuler(QWidget *parent)
: QAbstractSlider(parent)
, d( new KRulerPrivate )
{
setRange(INIT_MIN_VALUE, INIT_MAX_VALUE);
setPageStep(10);
setValue(INIT_VALUE);
- init(Qt::Horizontal);
+ initWidget(Qt::Horizontal);
setFixedHeight(FIX_WIDTH);
}
KRuler::KRuler(Qt::Orientation orient,
QWidget *parent, Qt::WFlags f)
: QAbstractSlider(parent)
, d( new KRulerPrivate )
{
setRange(INIT_MIN_VALUE, INIT_MAX_VALUE);
setPageStep(10);
setValue(INIT_VALUE);
setWindowFlags(f);
- init(orient);
+ initWidget(orient);
if (orient == Qt::Horizontal)
setFixedHeight(FIX_WIDTH);
else
setFixedWidth(FIX_WIDTH);
}
KRuler::KRuler(Qt::Orientation orient, int widgetWidth,
QWidget *parent, Qt::WFlags f)
: QAbstractSlider(parent)
, d( new KRulerPrivate )
{
setRange(INIT_MIN_VALUE, INIT_MAX_VALUE);
setPageStep(10);
setValue(INIT_VALUE);
setWindowFlags(f);
- init(orient);
+ initWidget(orient);
if (orient == Qt::Horizontal)
setFixedHeight(widgetWidth);
else
setFixedWidth(widgetWidth);
}
-void KRuler::init(Qt::Orientation orientation)
+void KRuler::initWidget(Qt::Orientation orientation)
{
#ifdef __GNUC__
#warning FIXME setFrameStyle(WinPanel | Raised);
#endif
d->showpointer = INIT_SHOW_POINTER;
d->showEndL = INIT_SHOW_END_LABEL;
d->lengthFix = INIT_LENGTH_FIX;
d->endOffset_length = INIT_END_OFFSET;
d->tmDist = INIT_TINY_MARK_DISTANCE;
d->lmDist = INIT_LITTLE_MARK_DISTANCE;
d->mmDist = INIT_MIDDLE_MARK_DISTANCE;
d->bmDist = INIT_BIG_MARK_DISTANCE;
d->offset= INIT_OFFSET;
d->showtm = INIT_SHOW_TINY_MARK;
d->showlm = INIT_SHOW_LITTLE_MARK;
d->showmm = INIT_SHOW_MEDIUM_MARK;
d->showbm = INIT_SHOW_BIG_MARK;
d->showem = INIT_SHOW_END_MARK;
d->ppm = INIT_PIXEL_PER_MARK;
d->dir = orientation;
}
KRuler::~KRuler()
{
delete d;
}
#ifndef KDE_NO_DEPRECATED
void
KRuler::setMinValue(int value)
{
setMinimum(value);
}
#endif
#ifndef KDE_NO_DEPRECATED
int
KRuler::minValue() const
{ return minimum(); }
#endif
#ifndef KDE_NO_DEPRECATED
void
KRuler::setMaxValue(int value)
{
setMaximum(value);
}
#endif
#ifndef KDE_NO_DEPRECATED
int
KRuler::maxValue() const
{ return maximum(); }
#endif
void
KRuler::setTinyMarkDistance(int dist)
{
if (dist != d->tmDist) {
d->tmDist = dist;
update(contentsRect());
}
}
int
KRuler::tinyMarkDistance() const
{ return d->tmDist; }
void
KRuler::setLittleMarkDistance(int dist)
{
if (dist != d->lmDist) {
d->lmDist = dist;
update(contentsRect());
}
}
int
KRuler::littleMarkDistance() const
{ return d->lmDist; }
void
KRuler::setMediumMarkDistance(int dist)
{
if (dist != d->mmDist) {
d->mmDist = dist;
update(contentsRect());
}
}
int
KRuler::mediumMarkDistance() const
{ return d->mmDist; }
void
KRuler::setBigMarkDistance(int dist)
{
if (dist != d->bmDist) {
d->bmDist = dist;
update(contentsRect());
}
}
int
KRuler::bigMarkDistance() const
{ return d->bmDist; }
void
KRuler::setShowTinyMarks(bool show)
{
if (show != d->showtm) {
d->showtm = show;
update(contentsRect());
}
}
bool
KRuler::showTinyMarks() const
{
return d->showtm;
}
void
KRuler::setShowLittleMarks(bool show)
{
if (show != d->showlm) {
d->showlm = show;
update(contentsRect());
}
}
bool
KRuler::showLittleMarks() const
{
return d->showlm;
}
void
KRuler::setShowMediumMarks(bool show)
{
if (show != d->showmm) {
d->showmm = show;
update(contentsRect());
}
}
bool
KRuler::showMediumMarks() const
{
return d->showmm;
}
void
KRuler::setShowBigMarks(bool show)
{
if (show != d->showbm) {
d->showbm = show;
update(contentsRect());
}
}
bool
KRuler::showBigMarks() const
{
return d->showbm;
}
void
KRuler::setShowEndMarks(bool show)
{
if (show != d->showem) {
d->showem = show;
update(contentsRect());
}
}
bool
KRuler::showEndMarks() const
{
return d->showem;
}
void
KRuler::setShowPointer(bool show)
{
if (show != d->showpointer) {
d->showpointer = show;
update(contentsRect());
}
}
bool
KRuler::showPointer() const
{
return d->showpointer;
}
void
KRuler::setFrameStyle(int)
{
#ifdef __GNUC__
#warning implement me (jowenn)
#endif
}
void
KRuler::setShowEndLabel(bool show)
{
if (d->showEndL != show) {
d->showEndL = show;
update(contentsRect());
}
}
bool
KRuler::showEndLabel() const
{
return d->showEndL;
}
void
KRuler::setEndLabel(const QString& label)
{
d->endlabel = label;
// premeasure the fontwidth and save it
if (d->dir == Qt::Vertical) {
QFont font = this->font();
font.setPointSize(LABEL_SIZE);
QFontMetrics fm(font);
d->fontWidth = fm.width(d->endlabel);
}
update(contentsRect());
}
QString KRuler::endLabel() const
{
return d->endlabel;
}
void
KRuler::setRulerMetricStyle(KRuler::MetricStyle style)
{
switch (style) {
default: /* fall through */
case Custom:
return;
case Pixel:
setLittleMarkDistance(1);
setMediumMarkDistance(5);
setBigMarkDistance(10);
setShowTinyMarks(false);
setShowLittleMarks(true);
setShowMediumMarks(true);
setShowBigMarks(true);
setShowEndMarks(true);
update(contentsRect());
setPixelPerMark(10.0);
break;
case Inch:
setTinyMarkDistance(1);
setLittleMarkDistance(2);
setMediumMarkDistance(4);
setBigMarkDistance(8);
setShowTinyMarks(true);
setShowLittleMarks(true);
setShowMediumMarks(true);
setShowBigMarks(true);
setShowEndMarks(true);
update(contentsRect());
setPixelPerMark(9.0);
break;
case Millimetres: /* fall through */
case Centimetres: /* fall through */
case Metres:
setLittleMarkDistance(1);
setMediumMarkDistance(5);
setBigMarkDistance(10);
setShowTinyMarks(false);
setShowLittleMarks(true);
setShowMediumMarks(true);
setShowBigMarks(true);
setShowEndMarks(true);
update(contentsRect());
setPixelPerMark(3.0);
}
switch (style) {
case Pixel:
setEndLabel(QLatin1String("pixel"));
break;
case Inch:
setEndLabel(QLatin1String("inch"));
break;
case Millimetres:
setEndLabel(QLatin1String("mm"));
break;
case Centimetres:
setEndLabel(QLatin1String("cm"));
break;
case Metres:
setEndLabel(QLatin1String("m"));
default: /* never reached, see above switch */
/* empty command */;
}
// if the style changes one of the values,
// update would have been called inside the methods
// -> no update() call needed here !
}
void
KRuler::setPixelPerMark(double rate)
{ // never compare floats against each other :)
d->ppm = rate;
update(contentsRect());
}
double
KRuler::pixelPerMark() const
{ return d->ppm; }
void
KRuler::setLength(int length)
{
int tmp;
if (d->lengthFix) {
tmp = length;
}
else {
tmp = width() - length;
}
if (tmp != d->endOffset_length) {
d->endOffset_length = tmp;
update(contentsRect());
}
}
int
KRuler::length() const
{
if (d->lengthFix) {
return d->endOffset_length;
}
return (width() - d->endOffset_length);
}
void
KRuler::setLengthFixed(bool fix)
{
d->lengthFix = fix;
}
bool
KRuler::lengthFixed() const
{
return d->lengthFix;
}
void
KRuler::setOffset(int _offset)
{// debug("set offset %i", _offset);
if (d->offset != _offset) {
d->offset = _offset;
update(contentsRect());
}
}
int
KRuler::offset() const
{ return d->offset; }
int
KRuler::endOffset() const
{
if (d->lengthFix) {
return (width() - d->endOffset_length);
}
return d->endOffset_length;
}
void
KRuler::slideUp(int count)
{
if (count) {
d->offset += count;
update(contentsRect());
}
}
void
KRuler::slideDown(int count)
{
if (count) {
d->offset -= count;
update(contentsRect());
}
}
void
KRuler::slotNewValue(int _value)
{
int oldvalue = value();
if (oldvalue == _value) {
return;
}
// setValue(_value);
setValue(_value);
if (value() == oldvalue) {
return;
}
// get the rectangular of the old and the new ruler pointer
// and repaint only him
if (d->dir == Qt::Horizontal) {
QRect oldrec(-5+oldvalue,10, 11,6);
QRect newrec(-5+_value,10, 11,6);
repaint( oldrec.unite(newrec) );
}
else {
QRect oldrec(10,-5+oldvalue, 6,11);
QRect newrec(10,-5+_value, 6,11);
repaint( oldrec.unite(newrec) );
}
}
void
KRuler::slotNewOffset(int _offset)
{
if (d->offset != _offset) {
//setOffset(_offset);
d->offset = _offset;
repaint(contentsRect());
}
}
void
KRuler::slotEndOffset(int offset)
{
int tmp;
if (d->lengthFix) {
tmp = width() - offset;
}
else {
tmp = offset;
}
if (d->endOffset_length != tmp) {
d->endOffset_length = tmp;
repaint(contentsRect());
}
}
void
KRuler::paintEvent(QPaintEvent * /*e*/)
{
// debug ("KRuler::drawContents, %s",(horizontal==dir)?"horizontal":"vertical");
QStylePainter p(this);
#ifdef PROFILING
QTime time;
time.start();
for (int profile=0; profile<10; profile++) {
#endif
int value = this->value(),
minval = minimum(),
maxval;
if (d->dir == Qt::Horizontal) {
maxval = maximum()
+ d->offset
- (d->lengthFix?(height()-d->endOffset_length):d->endOffset_length);
}
else
{
maxval = maximum()
+ d->offset
- (d->lengthFix?(width()-d->endOffset_length):d->endOffset_length);
}
//ioffsetval = value-offset;
// pixelpm = (int)ppm;
// left = clip.left(),
// right = clip.right();
double f, fend,
offsetmin=(double)(minval-d->offset),
offsetmax=(double)(maxval-d->offset),
fontOffset = (((double)minval)>offsetmin)?(double)minval:offsetmin;
// draw labels
QFont font = p.font();
font.setPointSize(LABEL_SIZE);
p.setFont( font );
// draw littlemarklabel
// draw mediummarklabel
// draw bigmarklabel
// draw endlabel
if (d->showEndL) {
if (d->dir == Qt::Horizontal) {
p.translate( fontOffset, 0 );
p.drawText( END_LABEL_X, END_LABEL_Y, d->endlabel );
}
else { // rotate text +pi/2 and move down a bit
//QFontMetrics fm(font);
#ifdef KRULER_ROTATE_TEST
p.rotate( -90.0 + rotate );
p.translate( -8.0 - fontOffset - d->fontWidth + xtrans,
ytrans );
#else
p.rotate( -90.0 );
p.translate( -8.0 - fontOffset - d->fontWidth, 0.0 );
#endif
p.drawText( END_LABEL_X, END_LABEL_Y, d->endlabel );
}
p.resetMatrix();
}
// draw the tiny marks
if (d->showtm) {
fend = d->ppm*d->tmDist;
for ( f=offsetmin; f<offsetmax; f+=fend ) {
if (d->dir == Qt::Horizontal) {
p.drawLine((int)f, BASE_MARK_X1, (int)f, BASE_MARK_X2);
}
else {
p.drawLine(BASE_MARK_X1, (int)f, BASE_MARK_X2, (int)f);
}
}
}
if (d->showlm) {
// draw the little marks
fend = d->ppm*d->lmDist;
for ( f=offsetmin; f<offsetmax; f+=fend ) {
if (d->dir == Qt::Horizontal) {
p.drawLine((int)f, LITTLE_MARK_X1, (int)f, LITTLE_MARK_X2);
}
else {
p.drawLine(LITTLE_MARK_X1, (int)f, LITTLE_MARK_X2, (int)f);
}
}
}
if (d->showmm) {
// draw medium marks
fend = d->ppm*d->mmDist;
for ( f=offsetmin; f<offsetmax; f+=fend ) {
if (d->dir == Qt::Horizontal) {
p.drawLine((int)f, MIDDLE_MARK_X1, (int)f, MIDDLE_MARK_X2);
}
else {
p.drawLine(MIDDLE_MARK_X1, (int)f, MIDDLE_MARK_X2, (int)f);
}
}
}
if (d->showbm) {
// draw big marks
fend = d->ppm*d->bmDist;
for ( f=offsetmin; f<offsetmax; f+=fend ) {
if (d->dir == Qt::Horizontal) {
p.drawLine((int)f, BIG_MARK_X1, (int)f, BIG_MARK_X2);
}
else {
p.drawLine(BIG_MARK_X1, (int)f, BIG_MARK_X2, (int)f);
}
}
}
if (d->showem) {
// draw end marks
if (d->dir == Qt::Horizontal) {
p.drawLine(minval-d->offset, END_MARK_X1, minval-d->offset, END_MARK_X2);
p.drawLine(maxval-d->offset, END_MARK_X1, maxval-d->offset, END_MARK_X2);
}
else {
p.drawLine(END_MARK_X1, minval-d->offset, END_MARK_X2, minval-d->offset);
p.drawLine(END_MARK_X1, maxval-d->offset, END_MARK_X2, maxval-d->offset);
}
}
// draw pointer
if (d->showpointer) {
QPolygon pa(4);
if (d->dir == Qt::Horizontal) {
pa.setPoints(3, value-5, 10, value+5, 10, value/*+0*/,15);
}
else {
pa.setPoints(3, 10, value-5, 10, value+5, 15, value/*+0*/);
}
p.setBrush( p.background().color() );
p.drawPolygon( pa );
}
#ifdef PROFILING
}
int elapsed = time.elapsed();
debug("paint time %i",elapsed);
#endif
}
diff --git a/kdeui/widgets/kruler.h b/kdeui/widgets/kruler.h
index 59c333d283..fb3a04b26c 100644
--- a/kdeui/widgets/kruler.h
+++ b/kdeui/widgets/kruler.h
@@ -1,431 +1,431 @@
/* -*- c++ -*- */
/* This file is part of the KDE libraries
Copyright (C) 1998 Jörg Habenicht (j.habenicht@europemail.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KRULER_H
#define KRULER_H
#include <kdeui_export.h>
#include <QAbstractSlider>
/**
* A ruler widget.
*
* The vertical ruler looks similar to this:
*
*\code
* meters inches
*
* ------ <--- end mark ---> ------
* -- -
* -- <---little mark---> --
* -- -
* -- ---
* --- <---medium mark -
* -- --
* -- tiny mark----> -
* -- ----
* -- -
* ---- <-----big mark --
* -- -
* |>-- <--ruler pointer--> |>--
*
* \endcode
*
* There are tiny marks, little marks, medium marks, and big marks along the
* ruler.
*
* To receive mouse clicks or mouse moves,
* the class has to be overloaded.
*
* For performance reasons, the public methods don't call QWidget::repaint().
* (Slots do, see documentation below.)
* All the changed settings will be painted once after leaving
* to the main event loop.
* For performance painting the slot methods should be used,
* they do a fast QWidget::repaint() call after changing the values.
* For setting multiple values like minValue(), maxValue(), offset() etc.
* using the public methods is recommended
* so the widget will be painted only once when entering the main event loop.
*
* \image html kruler.png "KDE Ruler Widget"
*
* @short A ruler widget.
* @author Jörg Habenicht
*/
class KDEUI_EXPORT KRuler : public QAbstractSlider
{
Q_OBJECT
Q_PROPERTY( bool showTinyMarks READ showTinyMarks WRITE setShowTinyMarks )
Q_PROPERTY( bool showLittleMarks READ showLittleMarks WRITE setShowLittleMarks )
Q_PROPERTY( bool showMediumMarks READ showMediumMarks WRITE setShowMediumMarks )
Q_PROPERTY( bool showBigMarks READ showBigMarks WRITE setShowBigMarks )
Q_PROPERTY( bool showPointer READ showPointer WRITE setShowPointer )
Q_PROPERTY( bool showEndLabel READ showEndLabel WRITE setShowEndLabel )
Q_PROPERTY( int tinyMarkDistance READ tinyMarkDistance WRITE setTinyMarkDistance )
Q_PROPERTY( int littleMarkDistance READ littleMarkDistance WRITE setLittleMarkDistance )
Q_PROPERTY( int mediumMarkDistance READ mediumMarkDistance WRITE setBigMarkDistance )
Q_PROPERTY( int bigMarkDistance READ bigMarkDistance WRITE setBigMarkDistance )
Q_PROPERTY( double pixelPerMark READ pixelPerMark WRITE setPixelPerMark )
Q_PROPERTY( bool lengthFixed READ lengthFixed WRITE setLengthFixed )
Q_PROPERTY( QString endLabel READ endLabel WRITE setEndLabel )
Q_ENUMS( MetricStyle )
Q_PROPERTY( int length READ length WRITE setLength )
Q_PROPERTY( int offset READ offset )
Q_PROPERTY( int endOffset READ endOffset )
public:
/*
#define KRULER_ROTATE_TEST KRULER_ROTATE_TEST
#undef KRULER_ROTATE_TEST
#ifdef KRULER_ROTATE_TEST
double xtrans, ytrans, rotate;
# warning tmporaer variablen eingeschaltet
#endif
*/
/**
* The types of units used.
**/
enum MetricStyle { Custom=0, Pixel, Inch, Millimetres, Centimetres, Metres };
/**
* The style (or look) of the ruler.
**/
// enum PaintStyle { Flat, Raised, Sunken };
/**
* Constructs a horizontal ruler.
*/
explicit KRuler(QWidget *parent=0);
/**
* Constructs a ruler with orientation @p orient.
*
* @p parent and @p f are passed to QFrame.
* The default look is a raised widget
* but may be changed with the inherited QFrame methods.
*
* @param orient Orientation of the ruler.
* @param parent Will be handed over to QFrame.
* @param f Will be handed over to QFrame.
*
**/
explicit KRuler(Qt::Orientation orient, QWidget *parent=0, Qt::WFlags f=0);
/**
* Constructs a ruler with orientation @p orient and initial width @p widgetWidth.
*
* The width sets the fixed width of the widget. This is useful if you
* want to draw the ruler bigger or smaller than the default size.
* Note: The size of the marks doesn't change.
* @p parent and @p f are passed to QFrame.
*
* @param orient Orientation of the ruler.
* @param widgetWidth Fixed width of the widget.
* @param parent Will be handed over to QFrame.
* @param f Will be handed over to QFrame.
*
*/
KRuler(Qt::Orientation orient, int widgetWidth, QWidget *parent=0,
Qt::WFlags f=0);
/**
* Destructor.
*/
~KRuler();
/**
* Sets the minimal value of the ruler pointer (default is 0).
*
* This method calls update() so that the widget is painted after leaving
* to the main event loop.
*
**/
#ifndef KDE_NO_DEPRECATED
KDEUI_DEPRECATED void setMinValue(int);
#endif
/**
* Returns the minimal value of the ruler pointer.
**/
#ifndef KDE_NO_DEPRECATED
KDEUI_DEPRECATED int minValue() const;
#endif
/**
* Sets the maximum value of the ruler pointer (default is 100).
*
* This method calls update() so that the widget is painted after leaving
* to the main event loop.
*/
#ifndef KDE_NO_DEPRECATED
KDEUI_DEPRECATED void setMaxValue(int);
#endif
/**
* Returns the maximal value of the ruler pointer.
*/
#ifndef KDE_NO_DEPRECATED
KDEUI_DEPRECATED int maxValue() const;
#endif
/**
* Sets the distance between tiny marks.
*
* This is mostly used in the English system (inches) with distance of 1.
*/
void setTinyMarkDistance(int);
/**
* Returns the distance between tiny marks.
**/
int tinyMarkDistance() const;
/**
* Sets the distance between little marks.
*
* The default value is 1 in the metric system and 2 in the English (inches) system.
*/
void setLittleMarkDistance(int);
/**
* Returns the distance between little marks.
*/
int littleMarkDistance() const;
/**
* Sets the distance between medium marks.
*
* For English (inches) styles it defaults to twice the little mark distance.
* For metric styles it defaults to five times the little mark distance.
**/
void setMediumMarkDistance(int);
int mediumMarkDistance() const;
/**
* Sets distance between big marks.
*
* For English (inches) or metric styles it is twice the medium mark distance.
**/
void setBigMarkDistance(int);
/**
* Returns the distance between big marks.
**/
int bigMarkDistance() const;
/**
* Shows/hides tiny marks.
**/
void setShowTinyMarks(bool);
bool showTinyMarks() const;
/**
* Shows/hides little marks.
**/
void setShowLittleMarks(bool);
bool showLittleMarks() const;
/**
* Shows/hides medium marks.
**/
void setShowMediumMarks(bool);
bool showMediumMarks() const;
/**
* Shows/hides big marks.
**/
void setShowBigMarks(bool);
bool showBigMarks() const;
/**
* Shows/hides end marks.
**/
void setShowEndMarks(bool);
bool showEndMarks() const;
/**
* Shows/hides the pointer.
*/
void setShowPointer(bool);
bool showPointer() const;
void setFrameStyle(int);
/**
* Show/hide number values of the little marks.
*
* Default is @p false.
**/
// void setShowLittleMarkLabel(bool);
/**
* Show/hide number values of the medium marks.
*
* Default is @p false.
**/
// void setShowMediumMarkLabel(bool);
/**
* Show/hide number values of the big marks.
*
* Default is @p false.
**/
// void showBigMarkLabel(bool);
/**
* Show/hide number values of the end marks.
*
* Default is @p false.
**/
void setShowEndLabel(bool);
bool showEndLabel() const;
/**
* Sets the label this is drawn at the beginning of the visible part
* of the ruler to @p label
**/
void setEndLabel(const QString&);
QString endLabel() const;
/**
* Sets up the necessary tasks for the provided styles.
*
* A convenience method.
**/
void setRulerMetricStyle(KRuler::MetricStyle);
/**
* Sets the number of pixels between two base marks.
*
* Calling this method stretches or shrinks your ruler.
*
* For pixel display ( MetricStyle) the value is 10.0 marks
* per pixel ;-)
* For English (inches) it is 9.0, and for centimetres ~2.835 -> 3.0 .
* If you want to magnify your part of display, you have to
* adjust the mark distance @p here.
* Notice: The double type is only supported to give the possibility
* of having some double values.
* It should be used with care. Using values below 10.0
* shows visible jumps of markpositions (e.g. 2.345).
* Using whole numbers is highly recommended.
* To use @p int values use setPixelPerMark((int)your_int_value);
* default: 1 mark per 10 pixels
*/
void setPixelPerMark(double rate);
/**
* Returns the number of pixels between two base marks.
**/
double pixelPerMark() const;
/**
* Sets the length of the ruler, i.e. the difference between
* the begin mark and the end mark of the ruler.
*
* Same as (width() - offset())
*
* when the length is not locked, it gets adjusted with the
* length of the widget.
*/
void setLength(int);
int length() const;
/**
* Locks the length of the ruler, i.e. the difference between
* the two end marks doesn't change when the widget is resized.
*
* @param fix fixes the length, if true
*/
void setLengthFixed(bool fix);
bool lengthFixed() const;
/**
* Sets the number of pixels by which the ruler may slide up or left.
* The number of pixels moved is realive to the previous position.
* The Method makes sense for updating a ruler, which is working with
* a scrollbar.
*
* This doesn't affect the position of the ruler pointer.
* Only the visible part of the ruler is moved.
*
* @param count Number of pixel moving up or left relative to the previous position
**/
void slideUp(int count = 1);
/**
* Sets the number of pixels by which the ruler may slide down or right.
* The number of pixels moved is realive to the previous position.
* The Method makes sense for updating a ruler, which is working with
* a scrollbar.
*
* This doesn't affect the position of the ruler pointer.
* Only the visible part of the ruler is moved.
*
* @param count Number of pixel moving up or left relative to the previous position
**/
void slideDown(int count = 1);
/**
* Sets the ruler slide offset.
*
* This is like slideup() or slidedown() with an absolute offset
* from the start of the ruler.
*
* @param offset Number of pixel to move the ruler up or left from the beginning
**/
void setOffset(int offset);
/**
* Returns the current ruler offset.
**/
int offset() const;
int endOffset() const;
public Q_SLOTS:
/**
* Sets the pointer to a new position.
*
* The offset is NOT updated.
* QWidget::repaint() is called afterwards.
**/
void slotNewValue(int);
/**
* Sets the ruler marks to a new position.
*
* The pointer is NOT updated.
* QWidget::repaint() is called afterwards.
**/
void slotNewOffset(int);
void slotEndOffset(int);
protected:
virtual void paintEvent(QPaintEvent *);
private:
- void init(Qt::Orientation orientation);
+ void initWidget(Qt::Orientation orientation);
private:
class KRulerPrivate;
KRulerPrivate * const d;
};
#endif

File Metadata

Mime Type
text/x-diff
Expires
Fri, Nov 1, 9:10 AM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
10075593
Default Alt Text
(355 KB)

Event Timeline