/* This file is part of KolourPicker Copyright (c) 2001 Malte Starostik This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. $Id$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kolourpicker.h" #include "kolourpicker.moc" #include // Applet initialization function extern "C" { KDE_EXPORT KPanelApplet* init(TQWidget *parent, const TQString& configFile) { TDEGlobal::locale()->insertCatalogue("kolourpicker"); return new KolourPicker(configFile, KPanelApplet::Normal, KPanelApplet::About, parent, "kolourpicker"); } } KolourPicker::KolourPicker(const TQString& configFile, Type type, int actions, TQWidget *parent, const char *name) : KPanelApplet(configFile, type, actions, parent, name), m_picking(0) { TDEAboutData *about = new TDEAboutData("kolourpicker", I18N_NOOP("Color Picker"), "v0.1", I18N_NOOP("An applet to pick color values from anywhere on the screen"), TDEAboutData::License_GPL_V2, "(c) 2001 Malte Starostik"); about->addAuthor("Malte Starostik", I18N_NOOP("Original Author"), "malte@kde.org"); m_instance = new TDEInstance(about); TDEConfig *conf = config(); conf->setGroup("General"); TQStringList history = conf->readListEntry("History"); for (TQStringList::ConstIterator it = history.begin(); it != history.end(); ++it) m_history.append(TQColor(*it)); setBackgroundOrigin(AncestorOrigin); m_colourButton = new SimpleButton(this); m_colourButton->setPixmap(SmallIcon("colorpicker")); m_colourButton->setFixedSize(20, 20); TQToolTip::add(m_colourButton, i18n("Pick a color")); connect(m_colourButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotPick())); m_historyButton = new SimpleButton(this); m_historyButton->setFixedSize(20, 20); if (m_history.count()) m_historyButton->setPixmap(colorPixmap(m_history.last())); else { m_historyButton->setPixmap(colorPixmap(TQColor())); m_historyButton->setEnabled(false); } TQToolTip::add(m_historyButton, i18n("History")); connect(m_historyButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotHistory())); } KolourPicker::~KolourPicker() { TDEGlobal::locale()->removeCatalogue("kolourpicker"); } int KolourPicker::heightForWidth(int width) const { return (width > 40) ? 22 : 44; } int KolourPicker::widthForHeight(int height) const { return (height > 40) ? 22 : 44; } void KolourPicker::about() { TDEAboutApplication dlg(m_instance->aboutData()); dlg.exec(); } void KolourPicker::slotPick() { m_picking = true; grabMouse(crossCursor); grabKeyboard(); } void KolourPicker::slotHistory() { TDEPopupMenu popup; popup.insertTitle(SmallIcon("colorize"), i18n("History")); TQPtrList subMenus; subMenus.setAutoDelete(true); for (TQValueList::ConstIterator it = m_history.fromLast(); it != m_history.end(); --it) { TQPopupMenu *sub = copyPopup(*it, false); subMenus.append(sub); popup.insertItem(colorPixmap(*it), TQString("%1, %2, %3").arg((*it).red()).arg((*it).green()).arg((*it).blue()), sub); } popup.insertSeparator(); int clear = popup.insertItem(SmallIcon("history_clear"), i18n("&Clear History")); int id = popup.exec(TQCursor::pos()); if (id == clear) { m_history.clear(); m_historyButton->setEnabled(false); arrangeButtons(); TDEConfig *conf = config(); conf->setGroup("General"); conf->writeEntry("History", TQStringList()); conf->sync(); } else if (id != -1) setClipboard(popup.findItem(id)->text()); } void KolourPicker::mouseReleaseEvent(TQMouseEvent *e) { if (m_picking) { m_picking = false; releaseMouse(); releaseKeyboard(); TQWidget *desktop = TQT_TQWIDGET(TQApplication::desktop()); TQPixmap pm = TQPixmap::grabWindow(desktop->winId(), e->globalPos().x(), e->globalPos().y(), 1, 1); TQImage img = pm.convertToImage(); TQColor color(img.pixel(0, 0)); // eventually remove a dupe TQValueListIterator dupe = m_history.find(color); if (dupe != m_history.end()) m_history.remove(dupe); m_history.append(color); while (m_history.count() >= 10) m_history.remove(m_history.begin()); m_historyButton->setEnabled(true); arrangeButtons(); TQStringList history; for (TQValueList::ConstIterator it = m_history.begin(); it != m_history.end(); ++it) { history.append((*it).name()); } TDEConfig *conf = config(); conf->setGroup("General"); conf->writeEntry("History", history); conf->sync(); m_historyButton->setPixmap(colorPixmap(color)); TQPopupMenu *popup = copyPopup(color, true); int id = popup->exec(e->globalPos()); if (id != -1) setClipboard( popup->findItem(id)->text() ); delete popup; } else KPanelApplet::mouseReleaseEvent(e); } // set both clipboard and selection void KolourPicker::setClipboard(const TQString& text) { TQClipboard *clip = TQApplication::clipboard(); bool oldMode = clip->selectionModeEnabled(); clip->setSelectionMode(true); clip->setText(text); clip->setSelectionMode(false); clip->setText(text); clip->setSelectionMode( oldMode ); } void KolourPicker::keyPressEvent(TQKeyEvent *e) { if (m_picking) { if (e->key() == Key_Escape) { m_picking = false; releaseMouse(); releaseKeyboard(); } e->accept(); return; } KPanelApplet::keyPressEvent(e); } void KolourPicker::resizeEvent(TQResizeEvent *) { arrangeButtons(); } void KolourPicker::arrangeButtons() { int h, w, p; if (orientation() ==Qt::Horizontal) { h = height(); if (h > 40) { // vertical layout p = (h - 40)/3; m_colourButton->setGeometry(2, p, 20, 20); m_historyButton->setGeometry(2, 2*p+20, 20, 20); } else { // horizontal layout p = (h - 20)/2; m_colourButton->setGeometry(2, p, 20, 20); m_historyButton->setGeometry(24, p, 20, 20); } } else { w = width(); if (w > 40) { // horizontal layout p = (w - 40)/3; m_colourButton->setGeometry(p, 2, 20, 20); m_historyButton->setGeometry(2*p+20, 2, 20, 20); } else { // vertical layout p = (w - 20)/2; m_colourButton->setGeometry(p, 2, 20, 20); m_historyButton->setGeometry(p, 24, 20, 20); } } updateGeometry(); } TQPopupMenu *KolourPicker::copyPopup(const TQColor &c, bool title) const { TDEPopupMenu *popup = new TDEPopupMenu; if (title) popup->insertTitle(colorPixmap(c), i18n("Copy Color Value")); TQString value; // r, g, b value.sprintf("%u, %u, %u", c.red(), c.green(), c.blue()); popup->insertItem(SmallIcon("text"), value); // HTML, lower case hex chars value.sprintf("#%.2x%.2x%.2x", c.red(), c.green(), c.blue()); popup->insertItem(SmallIcon("text-html"), value); if (value.find(TQRegExp("[a-f]")) >= 0) { // HTML, upper case hex chars value.sprintf("#%.2X%.2X%.2X", c.red(), c.green(), c.blue()); popup->insertItem(SmallIcon("text-html"), value); } // lower case hex chars value.sprintf( "%.2x%.2x%.2x", c.red(), c.green(), c.blue() ); popup->insertItem( SmallIcon( "text-html" ), value ); if ( value.find( TQRegExp( "[a-f]" ) ) >= 0 ) { // upper case hex chars value.sprintf( "%.2X%.2X%.2X", c.red(), c.green(), c.blue() ); popup->insertItem( SmallIcon( "text-html" ), value ); } // Color name TQStringList names = colorNames(c.red(), c.green(), c.blue()); for (TQStringList::ConstIterator it = names.begin(); it != names.end(); ++it) popup->insertItem(SmallIcon("text"), *it); return popup; } #define AAFACTOR 4 TQPixmap KolourPicker::colorPixmap(const TQColor &c) const { int x, y, dx, dy, d; TQImage img(16 * AAFACTOR, 16 * AAFACTOR, 32); img.setAlphaBuffer(true); img.fill(0); for (x = 0; x < img.width(); x++) for (y = 0; y < img.height(); y++) { dx = 1 + x - 15 * AAFACTOR / 2; dy = 1 + y - 15 * AAFACTOR / 2; d = dx * dx + dy * dy; if (d < (36 * AAFACTOR * AAFACTOR)) img.setPixel(x, y, c.pixel()); else if (d < (56.25 * AAFACTOR * AAFACTOR)) img.setPixel(x, y, tqRgba(128, 128, 128, 255)); } TQBitmap mask(16, 16); mask.fill(TQt::color0); TQPainter p(&mask); p.setPen(TQt::NoPen); p.setBrush(TQt::color1); p.drawEllipse(0, 0, 15, 15); p.end(); TQPixmap pm = TQPixmap(img.smoothScale(16, 16)); pm.setMask(mask); return pm; } const TQStringList &KolourPicker::colorNames(int r, int g, int b) const { static TQStringList NullList; if (m_colorNames.isEmpty()) { TQFile f("/usr/lib/X11/rgb.txt"); if (!f.open(IO_ReadOnly)) return NullList; TQTextStream str(&f); TQString red, green, blue; while (!str.atEnd()) { str >> red; if (red.simplifyWhiteSpace()[0].latin1() == '!') { str.readLine(); continue; } str >> green >> blue; const_cast(this)->m_colorNames[(red.toInt() << 16) + (green.toInt() << 8) + blue.toInt()] .append(str.readLine().simplifyWhiteSpace()); } } return m_colorNames[(r << 16) + (g << 8) + b]; }