/*************************************************************************** * Copyright (C) 2003 by S�astien Laot * * slaout@linux62.org * * * * 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; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tools.h" TQMemArray StopWatch::starts; TQMemArray StopWatch::totals; TQMemArray StopWatch::counts; void StopWatch::start(uint id) { if (id >= starts.size()) { totals.resize(id + 1); counts.resize(id + 1); for (uint i = starts.size(); i <= id; i++) { totals[i] = 0; counts[i] = 0; } starts.resize(id + 1); } starts[id] = TQTime::currentTime(); } void StopWatch::check(uint id) { if (id >= starts.size()) return; double time = starts[id].msecsTo(TQTime::currentTime()) / 1000.0; totals[id] += time; counts[id]++; kdDebug() << k_funcinfo << "Timer_" << id << ": " << time << " s [" << counts[id] << " times, total: " << totals[id] << " s, average: " << totals[id] / counts[id] << " s]" << endl; } TQString Tools::textToHTML(const TQString &text) { if (text.isEmpty()) return "

"; if (/*text.isEmpty() ||*/ text == " " || text == " ") return "

 

"; // convertFromPlainText() replace "\n\n" by "

\n

": we don't want that TQString htmlString = TQStyleSheet::convertFromPlainText(text, TQStyleSheetItem::WhiteSpaceNormal); return htmlString.replace("

\n", "
\n
\n").replace("\n

", "\n"); // Don't replace first and last tags } TQString Tools::textToHTMLWithoutP(const TQString &text) { // textToHTML(text) return "

HTMLizedText

". We remove the strating "

" and ending

" TQString HTMLizedText = textToHTML(text); return HTMLizedText.mid(3, HTMLizedText.length() - 3 - 4); } TQString Tools::htmlToParagraph(const TQString &html) { TQString result = html; bool startedBySpan = false; // Remove the start tag, all the and the start // Because can contain style="..." parameter, we transform it to int pos = result.find("\n", each tag can be separated by space characters (%s) // "

" can be omitted (eg. if the HTML doesn't contain paragraph but tables), as well as "" (optinal) pos = result.find(TQRegExp("(?:(?:

[\\s\\n\\r\\t]*)*[\\s\\n\\r\\t]*)*", false)); // Case unsensitive if (pos != -1) result = result.left(pos); if (startedBySpan) result += "
"; return result.replace("

", "

").replace("

", ""); } // The following is adapted from KStringHanlder::tagURLs // The adaptation lies in the change to urlEx // Thanks to Richard Heck TQString Tools::tagURLs(const TQString &text) { TQRegExp urlEx("(www\\.(?!\\.)|([a-zA-z]+)://)[\\d\\w\\./,:_~\\?=&;#@\\-\\+\\%\\$]+[\\d\\w/]"); TQString richText(text); int urlPos = 0; int urlLen; while ((urlPos = urlEx.search(richText, urlPos)) >= 0) { urlLen = urlEx.matchedLength(); TQString href = richText.mid(urlPos, urlLen); // TQt doesn't support (?<=pattern) so we do it here if ((urlPos > 0) && richText[urlPos-1].isLetterOrNumber()) { urlPos++; continue; } TQString anchor = "" + href + ""; richText.replace(urlPos, urlLen, anchor); urlPos += anchor.length(); } return richText; } TQString Tools::htmlToText(const TQString &html) { TQString text = htmlToParagraph(html); text.remove("\n"); text.replace("", "\n"); text.replace("", "\n"); text.replace("", "\n"); text.replace("", "\n"); text.replace("", "\n"); text.replace("", "\n"); text.replace("", "\n"); text.replace("", "\n"); text.replace("", "\n"); text.replace("

", " "); text.replace("","\n"); text.replace("","\n"); text.replace("","\n"); text.replace("", "\n"); text.replace("", " "); text.replace("", " "); text.replace("
", "\n"); text.replace("
","\n"); // FIXME: Format tags better, if possible // TODO: Replace é and co. by theire equivalent! // To manage tags: int pos = 0; int pos2; TQString tag, tag3; // To manage lists: int deep = 0; // The deep of the current line in imbriqued lists TQValueStack ul; // true if current list is a
    one, false if it's an
      one TQValueStack lines; // The line number if it is an
        list // We're removing every other tags, or replace them in the case of li: while ( (pos = text.find("<"), pos) != -1 ) { // What is the current tag? tag = text.mid(pos + 1, 2); tag3 = text.mid(pos + 1, 3); // Lists work: if (tag == "ul") { deep++; ul.push(true); lines.push(-1); } else if (tag == "ol") { deep++; ul.push(false); lines.push(0); } else if (tag3 == "/ul" || tag3 == "/ol") { deep--; ul.pop(); lines.pop(); } // Where the tag closes? pos2 = text.find(">"); if (pos2 != -1) { // Remove the tag: text.remove(pos, pos2 - pos + 1); // And replace li with "* ", "x. "... without forbidding to indent that: if (tag == "li") { // How many spaces before the line (indentation): TQString spaces = ""; for (int i = 1; i < deep; i++) spaces += " "; // The bullet or number of the line: TQString bullet = "* "; if (ul.top() == false) { lines.push(lines.pop() + 1); bullet = TQString::number(lines.top()) + ". "; } // Insertion: text.insert(pos, spaces + bullet); } if ( (tag3 == "/ul" || tag3 == "/ol") && deep == 0 ) text.insert(pos, "\n"); // Empty line before and after a set of lists } ++pos; } text.replace(">", ">"); text.replace("<", "<"); text.replace(""", "\""); text.replace(" ", " "); text.replace("&", "&"); // CONVERT IN LAST!! return text; } TQString Tools::cssFontDefinition(const TQFont &font, bool onlyFontFamily) { // The font definition: TQString definition = TQString(font.italic() ? "italic " : "") + TQString(font.bold() ? "bold " : "") + TQString::number(TQFontInfo(font).pixelSize()) + "px "; // Then, try to match the font name with a standard CSS font family: TQString genericFont = ""; if (definition.contains("serif", false) || definition.contains("roman", false)) genericFont = "serif"; // No "else if" because "sans serif" must be counted as "sans". So, the order between "serif" and "sans" is important if (definition.contains("sans", false) || definition.contains("arial", false) || definition.contains("helvetica", false)) genericFont = "sans-serif"; if (definition.contains("mono", false) || definition.contains("courier", false) || definition.contains("typewriter", false) || definition.contains("console", false) || definition.contains("terminal", false) || definition.contains("news", false)) genericFont = "monospace"; // Eventually add the generic font family to the definition: TQString fontDefinition = "\"" + font.family() + "\""; if (!genericFont.isEmpty()) fontDefinition += ", " + genericFont; if (onlyFontFamily) return fontDefinition; return definition + fontDefinition; } TQString Tools::stripEndWhiteSpaces(const TQString &string) { uint length = string.length(); uint i; for (i = length; i > 0; --i) if (!string[i-1].isSpace()) break; if (i == 0) return ""; else return string.left(i); } bool Tools::isWebColor(const TQColor &color) { int r = color.red(); // The 216 web colors are those colors whose RGB (Red, Green, Blue) int g = color.green(); // values are all in the set (0, 51, 102, 153, 204, 255). int b = color.blue(); return ( ( r == 0 || r == 51 || r == 102 || r == 153 || r == 204 || r == 255 ) && ( g == 0 || g == 51 || g == 102 || g == 153 || g == 204 || g == 255 ) && ( b == 0 || b == 51 || b == 102 || b == 153 || b == 204 || b == 255 ) ); } TQColor Tools::mixColor(const TQColor &color1, const TQColor &color2) { TQColor mixedColor; mixedColor.setRgb( (color1.red() + color2.red()) / 2, (color1.green() + color2.green()) / 2, (color1.blue() + color2.blue()) / 2 ); return mixedColor; } bool Tools::tooDark(const TQColor &color) { int dontCare, value; color.getHsv(/*hue:*/&dontCare, /*saturation:*/&dontCare, &value); return value < 175; } // TODO: Use it for all indentPixmap() TQPixmap Tools::normalizePixmap(const TQPixmap &pixmap, int width, int height) { if (height <= 0) height = width; if (pixmap.isNull() || (pixmap.width() == width && pixmap.height() == height)) return pixmap; return pixmap; } TQPixmap Tools::indentPixmap(const TQPixmap &source, int depth, int deltaX) { // Verify if it is possible: if (depth <= 0 || source.isNull()) return source; // Compute the number of pixels to indent: if (deltaX <= 0) deltaX = 2 * source.width() / 3; int indent = depth * deltaX; // Create the images: TQImage resultImage(indent + source.width(), source.height(), 32); TQImage sourceImage = source.convertToImage(); resultImage.setAlphaBuffer(true); // Clear the indent part (the left part) by making it fully transparent: uint *p; for (int row = 0; row < resultImage.height(); ++row) { for (int column = 0; column < resultImage.width(); ++column) { p = (uint *)resultImage.scanLine(row) + column; *p = 0; // tqRgba(0, 0, 0, 0) } } // Copy the source image byte per byte to the right part: uint *q; for (int row = 0; row < sourceImage.height(); ++row) { for (int column = 0; column < sourceImage.width(); ++column) { p = (uint *)resultImage.scanLine(row) + indent + column; q = (uint *)sourceImage.scanLine(row) + column; *p = *q; } } // And return the result: TQPixmap result; result.convertFromImage(resultImage); return result; } #include void Tools::deleteRecursively(const TQString &folderOrFile) { if (folderOrFile.isEmpty()) return; TQFileInfo fileInfo(folderOrFile); if (fileInfo.isDir()) { // Delete the child files: TQDir dir(folderOrFile, TQString(), TQDir::Name | TQDir::IgnoreCase, TQDir::All | TQDir::Hidden); TQStringList list = dir.entryList(); for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it ) if ( *it != "." && *it != ".." ) deleteRecursively(folderOrFile + "/" + *it); // And then delete the folder: dir.rmdir(folderOrFile); } else // Delete the file: TQFile::remove(folderOrFile); } TQString Tools::fileNameForNewFile(const TQString &wantedName, const TQString &destFolder) { TQString fileName = wantedName; TQString fullName = destFolder + fileName; TQString extension = ""; int number = 2; TQDir dir; // First check if the file do not exists yet (simplier and more often case) dir = TQDir(fullName); if ( ! dir.exists(fullName) ) return fileName; // Find the file extension, if it exists : Split fileName in fileName and extension // Example : fileName == "note5-3.txt" => fileName = "note5-3" and extension = ".txt" int extIndex = fileName.findRev('.'); if (extIndex != -1 && extIndex != int(fileName.length()-1)) { // Extension found and fileName do not ends with '.' ! extension = fileName.mid(extIndex); fileName.truncate(extIndex); } // else fileName = fileName and extension = "" // Find the file number, if it exists : Split fileName in fileName and number // Example : fileName == "note5-3" => fileName = "note5" and number = 3 int extNumber = fileName.findRev('-'); if (extNumber != -1 && extNumber != int(fileName.length()-1)) { // Number found and fileName do not ends with '-' ! bool isANumber; int theNumber = fileName.mid(extNumber + 1).toInt(&isANumber); if (isANumber) { number = theNumber; fileName.truncate(extNumber); } // else : } // else fileName = fileName and number = 2 (because if the file already exists, the genereated name is at last the 2nd) TQString finalName; for (/*int number = 2*/; ; ++number) { // TODO: FIXME: If overflow ??? finalName = fileName + "-" + TQString::number(number) + extension; fullName = destFolder + finalName; dir = TQDir(fullName); if ( ! dir.exists(fullName) ) break; } return finalName; } // TODO: Move it from NoteFactory /*TQString NoteFactory::iconForURL(const KURL &url) { TQString icon = KMimeType::iconForURL(url.url()); if ( url.protocol() == "mailto" ) icon = "message"; return icon; }*/ bool Tools::isAFileCut(TQMimeSource *source) { if (source->provides("application/x-kde-cutselection")) { TQByteArray array = source->encodedData("application/x-kde-cutselection"); return !array.isEmpty() && TQCString(array.data(), array.size() + 1).at(0) == '1'; } else return false; } void Tools::printChildren(TQObject* parent) { const TQObjectList objs = parent->childrenListObject(); TQObjectListIt it(objs); TQObject *obj; while((obj = it.current())!= 0){ ++it; kdDebug() << k_funcinfo << obj->className() << ": " << obj->name() << endl; } }