|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
|
|
|
|
|
|
|
|
This program 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 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
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "utils.h"
|
|
|
|
#include "utils_p.h"
|
|
|
|
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqimage.h>
|
|
|
|
#include <tqwmatrix.h>
|
|
|
|
#include <tqiconset.h>
|
|
|
|
#include <tqbitmap.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kcursor.h>
|
|
|
|
#include <tdeapplication.h>
|
|
|
|
#include <kpixmap.h>
|
|
|
|
#include <kiconeffect.h>
|
|
|
|
#include <kpixmapeffect.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
|
|
|
|
#if defined(TQ_WS_WIN)
|
|
|
|
# include <win32_utils.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
using namespace KexiUtils;
|
|
|
|
|
|
|
|
DelayedCursorHandler::DelayedCursorHandler()
|
|
|
|
: startedOrActive(false)
|
|
|
|
{
|
|
|
|
connect(&timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(show()));
|
|
|
|
}
|
|
|
|
void DelayedCursorHandler::start(bool noDelay) {
|
|
|
|
startedOrActive = true;
|
|
|
|
timer.start(noDelay ? 0 : 1000, true);
|
|
|
|
}
|
|
|
|
void DelayedCursorHandler::stop() {
|
|
|
|
startedOrActive = false;
|
|
|
|
timer.stop();
|
|
|
|
TQApplication::restoreOverrideCursor();
|
|
|
|
}
|
|
|
|
void DelayedCursorHandler::show() {
|
|
|
|
TQApplication::setOverrideCursor( KCursor::waitCursor(), true/*replace*/ );
|
|
|
|
}
|
|
|
|
|
|
|
|
DelayedCursorHandler _delayedCursorHandler;
|
|
|
|
|
|
|
|
void KexiUtils::setWaitCursor(bool noDelay) {
|
|
|
|
if (kapp->guiEnabled())
|
|
|
|
_delayedCursorHandler.start(noDelay);
|
|
|
|
}
|
|
|
|
void KexiUtils::removeWaitCursor() {
|
|
|
|
if (kapp->guiEnabled())
|
|
|
|
_delayedCursorHandler.stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
WaitCursor::WaitCursor(bool noDelay)
|
|
|
|
{
|
|
|
|
setWaitCursor(noDelay);
|
|
|
|
}
|
|
|
|
|
|
|
|
WaitCursor::~WaitCursor()
|
|
|
|
{
|
|
|
|
removeWaitCursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
WaitCursorRemover::WaitCursorRemover()
|
|
|
|
{
|
|
|
|
m_reactivateCursor = _delayedCursorHandler.startedOrActive;
|
|
|
|
_delayedCursorHandler.stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
WaitCursorRemover::~WaitCursorRemover()
|
|
|
|
{
|
|
|
|
if (m_reactivateCursor)
|
|
|
|
_delayedCursorHandler.start(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
TQString KexiUtils::fileDialogFilterString(const KMimeType::Ptr& mime, bool kdeFormat)
|
|
|
|
{
|
|
|
|
if (mime==0)
|
|
|
|
return TQString();
|
|
|
|
|
|
|
|
TQString str;
|
|
|
|
if (kdeFormat) {
|
|
|
|
if (mime->patterns().isEmpty())
|
|
|
|
str = "*";
|
|
|
|
else
|
|
|
|
str = mime->patterns().join(" ");
|
|
|
|
str += "|";
|
|
|
|
}
|
|
|
|
str += mime->comment();
|
|
|
|
if (!mime->patterns().isEmpty() || !kdeFormat) {
|
|
|
|
str += " (";
|
|
|
|
if (mime->patterns().isEmpty())
|
|
|
|
str += "*";
|
|
|
|
else
|
|
|
|
str += mime->patterns().join("; ");
|
|
|
|
str += ")";
|
|
|
|
}
|
|
|
|
if (kdeFormat)
|
|
|
|
str += "\n";
|
|
|
|
else
|
|
|
|
str += ";;";
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KexiUtils::fileDialogFilterString(const TQString& mimeString, bool kdeFormat)
|
|
|
|
{
|
|
|
|
KMimeType::Ptr ptr = KMimeType::mimeType(mimeString);
|
|
|
|
return fileDialogFilterString( ptr, kdeFormat );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KexiUtils::fileDialogFilterStrings(const TQStringList& mimeStrings, bool kdeFormat)
|
|
|
|
{
|
|
|
|
TQString ret;
|
|
|
|
TQStringList::ConstIterator endIt = mimeStrings.constEnd();
|
|
|
|
for(TQStringList::ConstIterator it = mimeStrings.constBegin(); it != endIt; ++it)
|
|
|
|
ret += fileDialogFilterString(*it, kdeFormat);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQColor KexiUtils::blendedColors(const TQColor& c1, const TQColor& c2, int factor1, int factor2)
|
|
|
|
{
|
|
|
|
return TQColor(
|
|
|
|
int( (c1.red()*factor1+c2.red()*factor2)/(factor1+factor2) ),
|
|
|
|
int( (c1.green()*factor1+c2.green()*factor2)/(factor1+factor2) ),
|
|
|
|
int( (c1.blue()*factor1+c2.blue()*factor2)/(factor1+factor2) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQColor KexiUtils::contrastColor(const TQColor& c)
|
|
|
|
{
|
|
|
|
int g = tqGray( c.rgb() );
|
|
|
|
if (g>110)
|
|
|
|
return c.dark(200);
|
|
|
|
else if (g>80)
|
|
|
|
return c.light(150);
|
|
|
|
else if (g>20)
|
|
|
|
return c.light(300);
|
|
|
|
return TQt::gray;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQColor KexiUtils::bleachedColor(const TQColor& c, int factor)
|
|
|
|
{
|
|
|
|
int h, s, v;
|
|
|
|
c.getHsv( &h, &s, &v );
|
|
|
|
TQColor c2;
|
|
|
|
if (factor < 100)
|
|
|
|
factor = 100;
|
|
|
|
if (s>=250 && v>=250) //for colors like cyan or red, make the result more white
|
|
|
|
s = TQMAX(0, s - factor - 50);
|
|
|
|
else if (s<=5 && s<=5)
|
|
|
|
v += factor-50;
|
|
|
|
c2.setHsv(h, s, TQMIN(255,v + factor-100));
|
|
|
|
return c2;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQIconSet KexiUtils::colorizeIconToTextColor(const TQPixmap& icon, const TQPalette& palette)
|
|
|
|
{
|
|
|
|
TQPixmap pm(
|
|
|
|
TDEIconEffect().apply( icon, TDEIconEffect::Colorize, 1.0f, palette.active().buttonText(), false ) );
|
|
|
|
|
|
|
|
KPixmap kpm(pm);
|
|
|
|
return TQIconSet(
|
|
|
|
KPixmapEffect::fade( kpm, 0.33, palette.active().button() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQPixmap KexiUtils::emptyIcon(TDEIcon::Group iconGroup)
|
|
|
|
{
|
|
|
|
TQPixmap noIcon( IconSize( iconGroup ), IconSize( iconGroup ) );
|
|
|
|
TQBitmap bmpNoIcon(noIcon.size());
|
|
|
|
bmpNoIcon.fill(TQt::color0);
|
|
|
|
noIcon.setMask(bmpNoIcon);
|
|
|
|
return noIcon;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiUtils::serializeMap(const TQMap<TQString,TQString>& map, const TQByteArray& array)
|
|
|
|
{
|
|
|
|
TQDataStream ds(array, IO_WriteOnly);
|
|
|
|
ds << map;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiUtils::serializeMap(const TQMap<TQString,TQString>& map, TQString& string)
|
|
|
|
{
|
|
|
|
TQByteArray array;
|
|
|
|
TQDataStream ds(array, IO_WriteOnly);
|
|
|
|
ds << map;
|
|
|
|
kdDebug() << array[3] << " " << array[4] << " " << array[5] << endl;
|
|
|
|
const uint size = array.size();
|
|
|
|
string = TQString();
|
|
|
|
string.reserve(size);
|
|
|
|
for (uint i=0; i<size; i++) {
|
|
|
|
string[i]=TQChar(ushort(array[i]+1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQMap<TQString,TQString> KexiUtils::deserializeMap(const TQByteArray& array)
|
|
|
|
{
|
|
|
|
TQMap<TQString,TQString> map;
|
|
|
|
TQDataStream ds(array, IO_ReadOnly);
|
|
|
|
ds >> map;
|
|
|
|
return map;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQMap<TQString,TQString> KexiUtils::deserializeMap(const TQString& string)
|
|
|
|
{
|
|
|
|
const uint size = string.length();
|
|
|
|
TQCString cstr(string.latin1());
|
|
|
|
TQByteArray array( size );
|
|
|
|
for (uint i=0; i<size; i++) {
|
|
|
|
array[i] = char(string[i].unicode()-1);
|
|
|
|
}
|
|
|
|
TQMap<TQString,TQString> map;
|
|
|
|
TQDataStream ds(array, IO_ReadOnly);
|
|
|
|
ds >> map;
|
|
|
|
return map;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KexiUtils::stringToFileName(const TQString& string)
|
|
|
|
{
|
|
|
|
TQString _string(string);
|
|
|
|
_string.replace(TQRegExp("[\\\\/:\\*?\"<>|]"), " ");
|
|
|
|
return _string.simplifyWhiteSpace();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiUtils::simpleCrypt(TQString& string)
|
|
|
|
{
|
|
|
|
for (uint i=0; i<string.length(); i++)
|
|
|
|
string[i] = TQChar( string[i].unicode() + 47 + i );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiUtils::simpleDecrypt(TQString& string)
|
|
|
|
{
|
|
|
|
for (uint i=0; i<string.length(); i++)
|
|
|
|
string[i] = TQChar( string[i].unicode() - 47 - i );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiUtils::drawPixmap( TQPainter& p, int lineWidth, const TQRect& rect,
|
|
|
|
const TQPixmap& pixmap, int alignment, bool scaledContents, bool keepAspectRatio)
|
|
|
|
{
|
|
|
|
if (pixmap.isNull())
|
|
|
|
return;
|
|
|
|
|
|
|
|
const bool fast = pixmap.width()>1000 && pixmap.height()>800; //fast drawing needed
|
|
|
|
const int w = rect.width()-lineWidth-lineWidth;
|
|
|
|
const int h = rect.height()-lineWidth-lineWidth;
|
|
|
|
//! @todo we can optimize drawing by drawing rescaled pixmap here
|
|
|
|
//! and performing detailed painting later (using TQTimer)
|
|
|
|
TQPixmap pixmapBuffer;
|
|
|
|
TQPainter p2;
|
|
|
|
TQPainter *target;
|
|
|
|
if (fast) {
|
|
|
|
target = &p;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
//moved pixmapBuffer.resize(rect.size()-TQSize(lineWidth, lineWidth));
|
|
|
|
//moved p2.begin(&pm, p.device());
|
|
|
|
target = &p2;
|
|
|
|
}
|
|
|
|
//! @todo only create buffered pixmap of the minimum size and then do not fillRect()
|
|
|
|
// target->fillRect(0,0,rect.width(),rect.height(), backgroundColor);
|
|
|
|
|
|
|
|
TQPoint pos;
|
|
|
|
if (scaledContents) {
|
|
|
|
if (keepAspectRatio) {
|
|
|
|
TQImage img(pixmap.convertToImage());
|
|
|
|
img = img.smoothScale(w, h, TQ_ScaleMin);
|
|
|
|
pos = rect.topLeft(); //0, 0);
|
|
|
|
if (img.width() < w) {
|
|
|
|
int hAlign = TQApplication::horizontalAlignment( alignment );
|
|
|
|
if ( hAlign & TQt::AlignRight )
|
|
|
|
pos.setX(pos.x() + w-img.width());
|
|
|
|
else if ( hAlign & TQt::AlignHCenter )
|
|
|
|
pos.setX(pos.x() + w/2-img.width()/2);
|
|
|
|
}
|
|
|
|
else if (img.height() < h) {
|
|
|
|
if ( alignment & TQt::AlignBottom )
|
|
|
|
pos.setY(pos.y() + h-img.height());
|
|
|
|
else if ( alignment & TQt::AlignVCenter )
|
|
|
|
pos.setY(pos.y() + h/2-img.height()/2);
|
|
|
|
}
|
|
|
|
pixmapBuffer.convertFromImage(img);
|
|
|
|
if (!fast) {
|
|
|
|
p2.begin(TQT_TQPAINTDEVICE(&pixmapBuffer), p.device());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
target->drawPixmap(pos, pixmapBuffer);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!fast) {
|
|
|
|
pixmapBuffer.resize(rect.size()-TQSize(lineWidth, lineWidth));
|
|
|
|
p2.begin(TQT_TQPAINTDEVICE(&pixmapBuffer), p.device());
|
|
|
|
p2.drawPixmap(TQRect(rect.x(), rect.y(), w, h), pixmap);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
target->drawPixmap(TQRect(rect.x() + lineWidth, rect.y() + lineWidth, w, h), pixmap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
int hAlign = TQApplication::horizontalAlignment( alignment );
|
|
|
|
if ( hAlign & TQt::AlignRight )
|
|
|
|
pos.setX(pos.x() + w-pixmap.width());
|
|
|
|
else if ( hAlign & TQt::AlignHCenter )
|
|
|
|
pos.setX(pos.x() + w/2-pixmap.width()/2);
|
|
|
|
else //left, etc.
|
|
|
|
pos.setX(pos.x());
|
|
|
|
|
|
|
|
if ( alignment & TQt::AlignBottom )
|
|
|
|
pos.setY(pos.y() + h-pixmap.height());
|
|
|
|
else if ( alignment & TQt::AlignVCenter )
|
|
|
|
pos.setY(pos.y() + h/2-pixmap.height()/2);
|
|
|
|
else //top, etc.
|
|
|
|
pos.setY(pos.y());
|
|
|
|
// target->drawPixmap(pos, pixmap);
|
|
|
|
// if (!fast)
|
|
|
|
// p2.begin(&pixmapBuffer, p.device());
|
|
|
|
p.drawPixmap(lineWidth+pos.x(), lineWidth+pos.y(), pixmap);
|
|
|
|
}
|
|
|
|
if (scaledContents && !fast && p.isActive()) {
|
|
|
|
p2.end();
|
|
|
|
bitBlt( p.device(),
|
|
|
|
// pos.x(),
|
|
|
|
// pos.y(),
|
|
|
|
(int)p.worldMatrix().dx() + rect.x() + lineWidth + pos.x(),
|
|
|
|
(int)p.worldMatrix().dy() + rect.y() + lineWidth + pos.y(),
|
|
|
|
&pixmapBuffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KexiUtils::ptrToStringInternal(void* ptr, uint size)
|
|
|
|
{
|
|
|
|
TQString str;
|
|
|
|
unsigned char* cstr_ptr = (unsigned char*)&ptr;
|
|
|
|
for (uint i=0; i<size; i++) {
|
|
|
|
TQString s;
|
|
|
|
s.sprintf("%2.2x", cstr_ptr[i]);
|
|
|
|
str.append( s );
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* KexiUtils::stringToPtrInternal(const TQString& str, uint size)
|
|
|
|
{
|
|
|
|
TQByteArray array(size);
|
|
|
|
if ((str.length()/2)<size)
|
|
|
|
return 0;
|
|
|
|
bool ok;
|
|
|
|
for (uint i=0; i<size; i++) {
|
|
|
|
array[i]=(unsigned char)(str.mid(i*2, 2).toUInt(&ok, 16));
|
|
|
|
if (!ok)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return *(void**)(array.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiUtils::setFocusWithReason(TQWidget* widget, TQFocusEvent::Reason reason)
|
|
|
|
{
|
|
|
|
TQEvent fe( TQEvent::FocusIn );
|
|
|
|
TQT_TQFOCUSEVENT(&fe)->setReason(reason);
|
|
|
|
TQApplication::sendEvent( widget, &fe );
|
|
|
|
TQT_TQFOCUSEVENT(&fe)->resetReason();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiUtils::unsetFocusWithReason(TQWidget* widget, TQFocusEvent::Reason reason)
|
|
|
|
{
|
|
|
|
TQEvent fe( TQEvent::FocusOut );
|
|
|
|
TQT_TQFOCUSEVENT(&fe)->setReason(reason);
|
|
|
|
TQApplication::sendEvent( widget, &fe );
|
|
|
|
TQT_TQFOCUSEVENT(&fe)->resetReason();
|
|
|
|
}
|
|
|
|
|
|
|
|
CopyFileResult KexiUtils::copyFile(const TQString& src, const TQString& dest)
|
|
|
|
{
|
|
|
|
#ifdef TQ_WS_WIN
|
|
|
|
int res = fcopy( TQFile::encodeName( src ), TQFile::encodeName( dest ) );
|
|
|
|
if (res == fcopy_src_err)
|
|
|
|
return CopyReadError;
|
|
|
|
else if (res == fcopy_dest_err)
|
|
|
|
return CopyWriteError;
|
|
|
|
|
|
|
|
return CopySuccess;
|
|
|
|
#else
|
|
|
|
# define _fcopy_BUFLEN 1024*32
|
|
|
|
char _fcopy_buf[_fcopy_BUFLEN];
|
|
|
|
FILE *in, *out;
|
|
|
|
int c_in=0, c_out=0;
|
|
|
|
CopyFileResult res=CopySuccess;
|
|
|
|
|
|
|
|
in=fopen(TQFile::encodeName( src ), "rb");
|
|
|
|
if (!in)
|
|
|
|
return CopyReadError;
|
|
|
|
out=fopen(TQFile::encodeName( dest ), "wb");
|
|
|
|
if (!out)
|
|
|
|
return CopyWriteError;
|
|
|
|
while (!feof(in) && !ferror(in) && !ferror(out)) {
|
|
|
|
c_in=fread(_fcopy_buf, 1, _fcopy_BUFLEN, in);
|
|
|
|
if (ferror(in) || c_in==0)
|
|
|
|
break;
|
|
|
|
c_out=fwrite(_fcopy_buf, 1, c_in, out);
|
|
|
|
if (ferror(out) || c_in!=c_out)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ferror(in))
|
|
|
|
res=CopyReadError;
|
|
|
|
else if (ferror(out))
|
|
|
|
res=CopyWriteError;
|
|
|
|
else if (c_in!=c_out)
|
|
|
|
res=CopyWriteError;
|
|
|
|
fclose(in);
|
|
|
|
fclose(out);
|
|
|
|
return res;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "utils_p.moc"
|