diff options
Diffstat (limited to 'kcontrol/background')
28 files changed, 8342 insertions, 0 deletions
diff --git a/kcontrol/background/CMakeLists.txt b/kcontrol/background/CMakeLists.txt new file mode 100644 index 000000000..2dfc7ba3f --- /dev/null +++ b/kcontrol/background/CMakeLists.txt @@ -0,0 +1,66 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +if( BUILD_KCONTROL OR BUILD_KDESKTOP OR BUILD_TDM ) + + include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/libkonq + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${LIBART_INCLUDE_DIRS} + ) + + link_directories( + ${TQT_LIBRARY_DIRS} + ${LIBART_LIBRARY_DIRS} + ) + + ##### bgnd (static) ############################# + + tde_add_library( bgnd STATIC_PIC AUTOMOC + SOURCES bgrender.cpp bgsettings.cpp KCrossBGRender.cc + LINK ${LIBART_LIBRARIES} + ) + +endif( ) + + +if( BUILD_KCONTROL ) + + add_subdirectory( pics ) + + ##### other data ################################ + + install( FILES background.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} ) + + + ##### kcm_background (module) ################### + + tde_add_kpart( kcm_background AUTOMOC + SOURCES main.cpp + LINK kcmbgnd-static bgnd-static tdenewstuff-shared + DESTINATION ${PLUGIN_INSTALL_DIR} + ) + + + ##### kcmbgnd (static) ########################## + + tde_add_library( kcmbgnd STATIC_PIC AUTOMOC + SOURCES + bgdialog.cpp bgdialog_ui.ui bgwallpaper_ui.ui + bgwallpaper.cpp bgadvanced_ui.ui bgadvanced.cpp + bgmonitor.cpp + ) + +endif( ) diff --git a/kcontrol/background/KCrossBGRender.cc b/kcontrol/background/KCrossBGRender.cc new file mode 100644 index 000000000..489e98d1b --- /dev/null +++ b/kcontrol/background/KCrossBGRender.cc @@ -0,0 +1,363 @@ +/* + * Copyright (C) 2008 Danilo Cesar Lemes de Paula <[email protected]> + * Copyright (C) 2008 Gustavo Boiko <[email protected]> + * Mandriva Conectiva + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <tqdom.h> +#include <tqfile.h> + +#include <kdebug.h> + +#include "KCrossBGRender.h" +#include <tqapplication.h> +#include <kimageeffect.h> + + +KCrossBGRender::KCrossBGRender(int desk, int screen, bool drawBackgroundPerScreen, TDEConfig *config): KBackgroundRenderer(desk,screen,drawBackgroundPerScreen,config) +{ + useCrossEfect = false; + if ( wallpaperList()[0].endsWith("xml",false) ) { + initCrossFade(wallpaperList()[0]); + } +} + + +void KCrossBGRender::initCrossFade(TQString xmlFile) +{ + useCrossEfect = true; + if (xmlFile.isEmpty()){ + useCrossEfect = false; + return; + } + secs = 0; + timeList.empty(); + + // read the XMLfile + TQDomDocument xmldoc = TQDomDocument(xmlFile); + TQFile file( xmlFile ); + if ( !file.open( IO_ReadOnly ) ) { + useCrossEfect = false; + return; + } + if ( !xmldoc.setContent( &file ) ) { + useCrossEfect = false; + file.close(); + return; + } + file.close(); + + TQDomElement docElem = xmldoc.documentElement(); + TQDomNode n = docElem.firstChild(); + while( !n.isNull() ) { + TQDomElement e = n.toElement(); // try to convert the node to an element. + if( !e.isNull() ) { + if (e.tagName() == "starttime") { + createStartTime(e); + } else if (e.tagName() == "transition") { + createTransition(e); + } else if (e.tagName() == "static") { + createStatic(e); + } + } + n = n.nextSibling(); + } + + // Setting "now" state + setCurrentEvent(true); + pix = getCurrentPixmap(); + + useCrossEfect = true; +} + + +KCrossBGRender::~KCrossBGRender(){ +} + +TQPixmap KCrossBGRender::pixmap() { + fixEnabled(); + if (!useCrossEfect){ + TQPixmap p = KBackgroundRenderer::pixmap(); + kdDebug() << "Inherited " << p.size() << endl; + if (p.width() == 0 && p.height() == 0){ + p.convertFromImage(image()); + } + return p; + } + + return pix; +} + +bool KCrossBGRender::needWallpaperChange(){ + if (!useCrossEfect) { + return KBackgroundRenderer::needWallpaperChange(); + } + + bool forceChange = setCurrentEvent(); // If we change the current state + if (forceChange){ // do not matter what hapens + actualPhase = 0; // we need to change background + return true; + } + + // Return false if it's not a transition + if (!current.transition) { + return false; + } + + double timeLeft, timeTotal; + TQTime now = TQTime::currentTime(); + + timeLeft = now.secsTo(current.etime); + if (timeLeft < 0) { + timeLeft += 86400; // before midnight + } + timeTotal = current.stime.secsTo(current.etime); + if (timeTotal < 0) { + timeTotal += 86400; + } + + double passed = timeTotal - timeLeft; + double timeCell = timeTotal/60; //Time cell size + + //kdDebug() << "\ntimeleft:" << timeLeft << " timeTotal:" << timeTotal + // << "\npassed:" << passed << " timeCell:" << timeCell + // << "\nactualPhase: " << actualPhase << endl; + + int aux = passed/timeCell; + if(actualPhase != aux){ + //kdDebug() << "needWallpaperChange() => returned true" << endl; + actualPhase = passed/timeCell; + return true; + } + + //kdDebug() << "needWallpaperChange() => returned false" << endl; + return false; +} + +/* + * This method change the enabledEffect flag to TRUE of FALSE, according + * with multiWallpaperMode and FileName (it needs to be a XML) + */ +void KCrossBGRender::fixEnabled(){ + + + TQString w = wallpaperList()[0]; + useCrossEfect = false; + if(multiWallpaperMode() == Random || multiWallpaperMode() == InOrder){ + + if ( w != xmlFileName ){ + // New XML File + xmlFileName = w; + if (w.endsWith("xml",false)){ + initCrossFade(wallpaperList()[0]); + //useCrossEfect = true; + }else{ + // Not, it's not a xml file + useCrossEfect = false; + } + }else if (w.endsWith("xml",false)){ + //xmlFile doesn't change + //but it's there + useCrossEfect = true; + }else{ + // it's not a XML file + useCrossEfect = false; + } + } +} + +void KCrossBGRender::changeWallpaper(bool init){ + + + + fixEnabled(); + + if (!useCrossEfect){ + KBackgroundRenderer::changeWallpaper(init); + return; + } + + pix = getCurrentPixmap(); + + +} + + +bool KCrossBGRender::setCurrentEvent(bool init){ + TQTime now = TQTime::currentTime(); + + + //Verify if is need to change + if (!(init || now <= current.stime || now >= current.etime )) { + return false; + } + + TQValueList<KBGCrossEvent>::iterator it; + for ( it = timeList.begin(); it != timeList.end(); ++it ){ + + // Look for time + if ( ((*it).stime <= now && now <= (*it).etime) || //normal situation + ((*it).etime <= (*it).stime && (now >= (*it).stime || + now <= (*it).etime) ) ) + { + current = *it; + actualPhase = 0; + + //kdDebug() << "Cur: " << current.stime << "< now <" << current.etime << endl; + return true; + } + } + + return false; +} + +TQPixmap KCrossBGRender::getCurrentPixmap() +{ + float alpha; + TQPixmap ret; + TQImage tmp; + TQImage p1; + if (!tmp.load(current.pix1)) + return TQPixmap(); + + // scale the pixmap to fit in the screen + //p1 = TQPixmap(QApplication::desktop()->screenGeometry().size()); + //TQPainter p(&p1); + //p.drawPixmap(p1.rect(), tmp); + // + p1 = tmp.smoothScale(TQApplication::desktop()->screenGeometry().size()); + + if (current.transition){ + TQTime now = TQTime::currentTime(); + double timeLeft,timeTotal; + + TQImage p2; + + if (!tmp.load(current.pix2) ) + return NULL; + + p2 = tmp.smoothScale(TQApplication::desktop()->screenGeometry().size()); + //TQPainter p(&p2); + //p.drawPixmap(p2.rect(), tmp); + + timeLeft = now.secsTo(current.etime); + if (timeLeft < 0) + timeLeft += 86400; + timeTotal = current.stime.secsTo(current.etime); + if (timeTotal < 0) + timeTotal += 86400; + + alpha = (timeTotal - timeLeft)/timeTotal; + + //ret = crossFade(p2,p1,alpha); + tmp = KImageEffect::blend(p2,p1,alpha); + ret.convertFromImage(tmp); + return ret; + }else{ + ret.convertFromImage(p1); + return ret; + } + + +} + +void KCrossBGRender::createStartTime(TQDomElement docElem) +{ + int hour; + int minutes; + + TQDomNode n = docElem.firstChild(); + while( !n.isNull() ) { + TQDomElement e = n.toElement(); + if( !e.isNull() ) { + if (e.tagName() == "hour"){ + hour = e.text().toInt(); + }else if ( e.tagName() == "minute" ){ + minutes = e.text().toInt(); + } + + } + + n = n.nextSibling(); + } + secs = hour*60*60 + minutes*60; +} +void KCrossBGRender::createTransition(TQDomElement docElem) +{ + int duration; + TQString from; + TQString to; + + TQDomNode n = docElem.firstChild(); + while( !n.isNull() ) { + TQDomElement e = n.toElement(); + if( !e.isNull() ) { + if (e.tagName() == "duration"){ + duration = e.text().toFloat(); + }else if ( e.tagName() == "from" ){ + from = e.text(); + } + else if ( e.tagName() == "to" ){ + to = e.text(); + } + + } + n = n.nextSibling(); + } + TQTime startTime(0,0,0); + startTime = startTime.addSecs(secs); + TQTime endTime(0,0,0); + endTime = endTime.addSecs(secs+duration); + + secs += duration; + + KBGCrossEvent l = {true, from, to, startTime,endTime}; + + timeList.append(l); + +} +void KCrossBGRender::createStatic(TQDomElement docElem) +{ + int duration; + TQString file; + + TQDomNode n = docElem.firstChild(); + while( !n.isNull() ) { + TQDomElement e = n.toElement(); + if( !e.isNull() ) { + if (e.tagName() == "duration"){ + duration = e.text().toFloat(); + }else if ( e.tagName() == "file" ){ + file = e.text(); + } + + } + n = n.nextSibling(); + } + + TQTime startTime(0,0,0); + startTime = startTime.addSecs(secs); + TQTime endTime(0,0,0); + endTime = endTime.addSecs(secs+duration); + + secs += duration; + + KBGCrossEvent l = {false, file, NULL, startTime,endTime}; + timeList.append(l); +} + +#include "KCrossBGRender.moc" diff --git a/kcontrol/background/KCrossBGRender.h b/kcontrol/background/KCrossBGRender.h new file mode 100644 index 000000000..f3c2f0931 --- /dev/null +++ b/kcontrol/background/KCrossBGRender.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2008 Danilo Cesar Lemes de Paula <[email protected]> + * Copyright (C) 2008 Gustavo Boiko <[email protected]> + * Mandriva Conectiva + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. +*/ + +#ifndef __KCROSSBGRENDER_H__ +#define __KCROSSBGRENDER_H__ + + +#include <tqvaluelist.h> +#include <tqpixmap.h> +#include <tqvaluelist.h> +#include <tqdatetime.h> + +#include "bgrender.h" + +class TQDomElement; + +typedef struct crossEvent{ + bool transition; + TQString pix1; + TQString pix2; + TQTime stime; //start time + TQTime etime; //end time +} KBGCrossEvent; + + +class KCrossBGRender: public KBackgroundRenderer{ + +TQ_OBJECT + +public: + KCrossBGRender(int desk, int screen, bool drawBackgroundPerScreen, TDEConfig *config=0); + ~KCrossBGRender(); + + bool needWallpaperChange(); + void changeWallpaper(bool init=false); + TQPixmap pixmap(); + bool usingCrossXml(){return useCrossEfect;}; + + +private: + TQPixmap pix; + int secs; + TQString xmlFileName; + bool useCrossEfect; + + int actualPhase; + + void createStartTime(TQDomElement e); + void createTransition(TQDomElement e); + void createStatic(TQDomElement e); + bool setCurrentEvent(bool init = false); + void initCrossFade(TQString xml); + void fixEnabled(); + TQPixmap getCurrentPixmap(); + KBGCrossEvent current; + TQValueList<KBGCrossEvent> timeList; +}; + +#endif // __KCROSSBGRENDER_H__ diff --git a/kcontrol/background/Makefile.am b/kcontrol/background/Makefile.am new file mode 100644 index 000000000..9c6990d17 --- /dev/null +++ b/kcontrol/background/Makefile.am @@ -0,0 +1,27 @@ +SUBDIRS = . pics + +AM_CPPFLAGS = -I$(top_srcdir)/libkonq $(all_includes) + +kde_module_LTLIBRARIES = kcm_background.la + +kcm_background_la_SOURCES = main.cpp +kcm_background_la_LDFLAGS = $(KDE_RPATH) -module -avoid-version $(all_libraries) -no-undefined +kcm_background_la_LIBADD = libkcmbgnd.la libbgnd.la $(LIB_TDEFILE) $(LIB_TDENEWSTUFF) + +METASOURCES = AUTO + +noinst_HEADERS = main.h \ + bgrender.h bgsettings.h \ + bgdialog.h bgadvanced.h bgwallpaper.h bgdefaults.h bgmonitor.h + +noinst_LTLIBRARIES = libbgnd.la libkcmbgnd.la +libbgnd_la_SOURCES = bgrender.cpp bgsettings.cpp +libkcmbgnd_la_SOURCES = bgdialog.cpp bgdialog_ui.ui bgwallpaper_ui.ui \ + bgwallpaper.cpp bgadvanced_ui.ui bgadvanced.cpp bgmonitor.cpp + +main.lo: bgdialog_ui.h + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kcmbackground.pot + +xdg_apps_DATA = background.desktop diff --git a/kcontrol/background/background.desktop b/kcontrol/background/background.desktop new file mode 100644 index 000000000..1c289a8a9 --- /dev/null +++ b/kcontrol/background/background.desktop @@ -0,0 +1,240 @@ +[Desktop Entry] +Exec=tdecmshell background +Icon=background +Type=Application +X-DocPath=kcontrol/background/index.html + + +X-TDE-Library=background +X-TDE-FactoryName=background +X-TDE-ParentApp=kcontrol + +Name=Background +Name[af]=Agtergrond +Name[ar]=الخلفية +Name[az]=Arxa plan +Name[be]=Фон +Name[bg]=Фон на екрана +Name[bn]=পটভূমি +Name[br]=Drekleur +Name[bs]=Pozadina +Name[ca]=Fons +Name[cs]=Pozadí +Name[csb]=Spòdlé +Name[cy]=Cefndir +Name[da]=Baggrund +Name[de]=Hintergrund +Name[el]=Φόντο +Name[eo]=Fono +Name[es]=Fondo +Name[et]=Taust +Name[eu]=Atzeko planoa +Name[fa]=زمینه +Name[fi]=Tausta +Name[fr]=Fond d'écran +Name[fy]=Eftergrûn +Name[ga]=Cúlra +Name[gl]=Fondo +Name[he]=רקע +Name[hi]=पृष्ठभूमि +Name[hr]=Pozadina +Name[hu]=Háttér +Name[id]=Latarbelakang +Name[is]=Bakgrunnur +Name[it]=Sfondo +Name[ja]=背景 +Name[ka]=ფონი +Name[kk]=Аясы +Name[km]=ផ្ទៃខាងក្រោយ +Name[lo]=ພື້ນຫລັງ +Name[lt]=Fonas +Name[lv]=Fons +Name[mk]=Подлога +Name[mn]=Дэвсгэр +Name[ms]=Latar Belakang +Name[nb]=Bakgrunn +Name[nds]=Achtergrund +Name[ne]=पृष्ठभूमि +Name[nl]=Achtergrond +Name[nn]=Bakgrunn +Name[nso]=Bokamorago +Name[oc]=Fons +Name[pa]=ਪਿੱਠਭੂਮੀ +Name[pl]=Tło +Name[pt]=Fundo do Ecrã +Name[pt_BR]=Fundo de tela +Name[ro]=Fundal +Name[ru]=Фон +Name[rw]=Mburabuzi +Name[se]=Duogáš +Name[sk]=Pozadie +Name[sl]=Ozadje +Name[sr]=Позадина +Name[sr@Latn]=Pozadina +Name[ss]=Lingemuva +Name[sv]=Bakgrund +Name[ta]=பின்னணி +Name[tg]=Пасзамина +Name[th]=พื้นหลัง +Name[tr]=Arkaplan +Name[tt]=Asyaq +Name[uk]=Тло +Name[uz]=Orqa fon +Name[uz@cyrillic]=Орқа фон +Name[ven]=Zwangamurahu +Name[vi]=Ảnh nền +Name[wa]=Fond +Name[xh]=Indawo yangasemva +Name[zh_CN]=背景 +Name[zh_TW]=背景 +Name[zu]=Inkundla yangemuva + +Comment=Change the background settings +Comment[af]=Verander die agtergrond instellings +Comment[ar]=تغيير تعيينات الخلفية +Comment[az]=Arxa plan qurğularını dəyişdirin +Comment[be]=Змяняе настаўленні фону +Comment[bg]=Настройване фона на работния плот +Comment[bn]=পটভূমি সেটিংস পরিবর্তন করুন +Comment[br]=Kemmañ kefluniadur an drekleur +Comment[bs]=Promijenite postavke pozadine +Comment[ca]=Canvia l'arranjament de la configuració del fons +Comment[cs]=Změna nastavení pozadí +Comment[csb]=Ùstôw spódkù +Comment[cy]=Newid gosodiadau'r cefndir +Comment[da]=Ændr baggrundsindstillinger +Comment[de]=Hintergrundeinstellungen ändern +Comment[el]=Αλλάξτε τις ρυθμίσεις του φόντου +Comment[eo]=Ŝanĝu la agordon de la fono +Comment[es]=Modificación de las preferencias del fondo +Comment[et]=Töölaua tausta seaded +Comment[eu]=Aldatu atzeko planoaren ezarpenak +Comment[fa]=تغییر تنظیمات زمینه +Comment[fi]=Muuta taustan asetuksia +Comment[fr]=Configuration du fond d'écran +Comment[fy]=Eftergrûnynstellings wizigje +Comment[ga]=Athraigh socruithe an chúlra +Comment[gl]=Cambiar as opcións do fondo +Comment[he]=שינוי הגדרות הרקע +Comment[hi]=पृष्ठभूमि सेटिंग बदलें +Comment[hr]=Promjena postavki pozadine +Comment[hu]=A háttérbeállítások megváltoztatása +Comment[id]=Ubah pengaturan latar belakang +Comment[is]=Stillingar bakgrunns +Comment[it]=Cambia le impostazioni dello sfondo +Comment[ja]=背景の設定を変更 +Comment[ka]=ფონის კონფიგურაციის შეცვლა +Comment[kk]=Үстел аясын түрлендіру +Comment[km]=ផ្លាស់ប្តូរការកំណត់ផ្ទៃខាងក្រោយ +Comment[lo]=ຕັ້ງຄ່າພື້ນຫລັງ +Comment[lt]=Keisti fono parinktis +Comment[lv]=Mainīt fona parametrus +Comment[mk]=Изменете ги поставувањата на подлогата +Comment[mn]=Дэвсгэр өөрчилөх +Comment[ms]=Ubah seting latar belakang +Comment[mt]=Ibdel il-konfigurazzjoni tal-isfond +Comment[nb]=Endre bakgrunnsinnstillingene +Comment[nds]=Achtergrundinstellen ännern +Comment[ne]=पृष्ठभूमि सेटिङ परिवर्तन गर्नुहोस् +Comment[nl]=Achtergrondinstellingen wijzigen +Comment[nn]=Endra bakgrunnsinnstillingane +Comment[nso]=Fetosa dipeakanyo tsa bokamorago +Comment[pa]=ਪਿੱਠਭੂਮੀ ਸੈਟਿੰਗ ਤਬਦੀਲ +Comment[pl]=Ustawienia tła +Comment[pt]=Alterar a configuração do fundo +Comment[pt_BR]=Muda as configurações do fundo da tela +Comment[ro]=Configurează setările fundalului +Comment[ru]=Настройка фона рабочего стола +Comment[rw]=Guhindura amagenamiterere ya mbuganyuma +Comment[se]=Rievdat duogášheivehusaid +Comment[sk]=Nastavenie pozadia +Comment[sl]=Spremeni nastavitve ozadja +Comment[sr]=Измена поставки позадине +Comment[sr@Latn]=Izmena postavki pozadine +Comment[ss]=Tjintja kuhleleka kwelingemuva +Comment[sv]=Anpassa bakgrundsinställningar +Comment[ta]=பின்னனி அமைப்பை மாற்று +Comment[tg]=Таъғири танзимоти пасзамина +Comment[th]=เปลี่ยนการตั้งค่าพื้นหลัง +Comment[tr]=Arkaplan ayarlarını değiştirir +Comment[tt]=Asyaq caylawın üzgärtü +Comment[uk]=Зміна параметрів тла +Comment[uz]=Orqa fonning moslamalarini oʻzgartirish +Comment[uz@cyrillic]=Орқа фоннинг мосламаларини ўзгартириш +Comment[ven]=Shandukisani mavhekanyele anga murahu +Comment[vi]=Thay đổi thiết lập ảnh nền +Comment[wa]=Candjî les apontiaedjes do fond del waitroûle +Comment[xh]=Tshintsha izicwangciso zendawo yangasemva +Comment[zh_CN]=更改背景设置 +Comment[zh_TW]=改變背景設定 +Comment[zu]=Shintsha izilungiselelo zendawo yangemuva + +Keywords=background;desktops;colors;colours;images;wallpapers;blending;balance;cache;multiple wallpapers;pixmap; +Keywords[az]=arxa plan;masa üstü;rənglər;rənglər;rəsmlər;divar kağızları;qarışdırma;denge;ön yaddaş;çoxlu divar kağızları;pixmap; +Keywords[be]=фон;працоўныя сталы;колеры;відарысы;малюнкі;шпалеры;баланс;кэш;некалькі шпалераў;background;desktops;colors;colours;images;wallpapers;blending;balance;cache;multiple wallpapers;pixmap; +Keywords[bg]=фон; изображение; работен; плот; работен плот; background; desktops; colors; colours; images; wallpapers; blending; balance; cache; multiple wallpapers; pixmap; +Keywords[ca]=fons;escriptoris;colors;colors;imatges;paper pintat;barreja;balanç;cau;múltiples papers pintats;mapa de píxels; +Keywords[cs]=Pozadí;Plochy;Barvy;Obrázky;Tapety;Směšování;Vyvážení;Cache;Pixmapa; +Keywords[csb]=spódk;spòdlé;pùltë;biurka;farwë;òbrôzczi;tapetë;mieszanié;pòdrãcznô pamiãc;wielorazowé tapetë;bitmapa; +Keywords[cy]=cefndir;penbwrdd;lliwiau;lliwiau;delweddau;papurau w?l;cymysgu;cydbwys;storfa;papurau w?l lluosog;picsfap; +Keywords[da]=baggrund;desktoppe;farver;billeder;tapeter;blanding;balance;cache;flere tapeter;billede; +Keywords[de]=Hintergrund;Arbeitsflächen;Desktop;Farben;Bilder;Hintergrundbilder;Überblendung;Pixmap;Cache;Zwischenspeicher; +Keywords[el]=φόντο;επιφάνειες εργασίας;χρώματα;χρώματα;εικόνες;ταπετσαρίες;εξομάλυνση;ισορροπία;λανθάνουσα μνήμη;πολλαπλές ταπετσαρίες;pixmap; +Keywords[en_GB]=background;desktops;colours;images;wallpapers;blending;balance;cache;multiple wallpapers;pixmap; +Keywords[eo]=fono;tabuloj;koloroj;bildoj;tapetoj;kolorŝanĝo;tenejo;rastrobildo; +Keywords[es]=fondo;escritorios;colores;imágenes;tapices;mezcla;equilibrio;caché;tapices múltiples;mapa de píxeles;pixmap; +Keywords[et]=taust;töölaud;töölauad;värvid;pildid;taustapildid;üleminek;tasakaal;vahemälu;pikselrastrid; +Keywords[eu]=atzeko planoa;mahaigainak;kolorea;koloreak;irudiak;hormapaperak;nahasketa; oreka;katxea;hormapaper anitz;pixel mapa; +Keywords[fa]=زمینه، رومیزیها، رنگها، رنگها، تصاویر، کاغذهای دیواری، مخلوط، توازن، نهانگاه، کاغذ دیواریهای متعدد، نگاشت بیت; +Keywords[fi]=tausta;työpöydät;värit;kuvat;taustakuvat;sekoitus;välimuisti;useat taustakuvat;kuvakartat; +Keywords[fr]=fond d'écran;fond;bureau;couleur;image;papier peint;image de fond;dégradé;cache;papiers peints multiples; +Keywords[fy]=eftergrûn;buroblêden;kleur;kleuren;ôfbyldingen;behang;ferminge; balâns;lyts ûnthâld;meardere ôfbyldingen;pixmap;grafysk; +Keywords[ga]=cúlra;deasca;dathanna;íomhánna;cúlbhrait;cumasc;cothrom;taisce;cúlbhrait iomadúla;mapa picteilíní; +Keywords[gl]=fondo;escritórios;cores;imaxes;papeis tapiz;balance;cache;múltiples papeis tapiz;mapa de píxels; +Keywords[he]=רקע;תמונות;background;desktops;colors;colours;images;wallpapers;blending;balance;cache;multiple;wallpapers;pixmapפטים;עירוב;איזון;מטמון;טפטים;מרובים;צבעים;שולחנות עבודה; ; +Keywords[hi]=पृष्ठभूमि;डेस्कटॉप;रंग;अनेक रंग;छवि;वालपेपर;ब्लेंडिंग;बैलेंस;कैश;अनेक वालपेपर;पिक्समैप; +Keywords[hr]=background;desktops;colors;colours;images;wallpapers;blending;balance;cache;multiple wallpapers;pixmap;pozadina; radna površina;boje;boja;slike;slika radne površine;preklapanje;prozirnost;balans;pohrana;višestruke slike radne površine; +Keywords[hu]=háttér;asztalok;színek;képek;tapéták;színkeverés;egyensúly;gyorstár;több tapéta;pixmap; +Keywords[is]=bakgrunnur;skjáborð;litir;myndir;veggfóður;blöndun;jafnvægi;skyndiminni;mörg veggfóður;mynd;punktamynd;bitamynd; +Keywords[it]=sfondo;desktop;colori;immagini;immagini di sfondo;sfumature;bilanciamento;cache;sfondi multipli; +Keywords[ja]=背景;色;色付け;画像;壁紙;ブレンディング;バランス;キャッシュ;複数の壁紙;ピクスマップ; +Keywords[km]=ផ្ទៃខាងក្រោយ;ផ្ទៃតុ;ពណ៌;រូបភាព;ក្រដាសបិទជញ្ជាំង;ច្របល់;តុល្យភាព;ឃ្លាំងសម្ងាត់;ក្រដាសបិទជញ្ជាំងច្រើន;pixmap; +Keywords[lt]=background;fonas;desktops;darbastaliai;colors;spalvos;colours;images;paveiksliukai;wallpapers;apmušalai;blending;balance;perėjimas;cache;kešas;krepšys;multiple wallpapers;pixmap;taškinė grafika; +Keywords[lv]=fons;darbvirsmas;krāsu;krāsas;attēli;tapetes;saplūstošas;balanss;kešs;daudzas tapetes;piksmapi; +Keywords[mk]=background;desktops;colors;colours;images;wallpapers;blending;balance;cache;multiple wallpapers;pixmap;подлога;позадина;површини;бои;слики;позадини;мешање;рамнотежа;кеш;повеќе подлоги;повеќе позадини; +Keywords[mn]=Дэвсгэр;Ажлын талбар;Desktop;Өнгө;Зураг;Дэвсгэр зураг;Анивчилт;Тэнцвэр;түр хадгалагч;pixmap; +Keywords[nb]=bakgrunn;skrivebord;farger;bilder;bakgrunnsbilder;flere bakgrunnsbilder; +Keywords[nds]=Achtergrund;Schriefdischen;Klören;Biller;wallpapers;blending;balance;Twischenspieker;multiple wallpapers;pixmap; +Keywords[ne]=पृष्ठभूमि;डेस्कटप;रङ;रङ;छवि; क्यास;छवि;बहुविध वालपेपर;सन्तुलन;ब्लेन्डिङ पिक्सम्याप; +Keywords[nl]=achtergrond;desktops;bureaubladen;kleur;kleuren;afbeeldingen;behang;wallpapers;gradiënt;vermenging;balans;cache;meerdere afbeeldingen;pixmap;graphics; +Keywords[nn]=bakgrunn;skrivebord;fargar;bilete;bakgrunnsbilete;overgang;balanse;fleire bakgrunnsbilete; +Keywords[nso]=bokamorago;di-desktop;mebala;mebala;ponagalo;wallpapers;blending;lekalekanya;polokelo;wallpapers tsa bontshi;pixmap; +Keywords[pa]=background;desktops;colors;colours;images;wallpapers;blending;balance;cache;multiple wallpapers;pixmap; ਵਾਲਪੇਪਰ; ਰੰਗ; ਚਿੱਤਰ; ਪਿੱਠਭੂਮੀ; +Keywords[pl]=tło;pulpity;biurka;kolory;obrazki;tapety;mieszanie;równowaga;pamięć podręczna;wielokrotne tapety;mapa bitowa; +Keywords[pt]=fundo;ecrãs;cores;imagens;papéis de parede;mistura;balanceamento;cache;múltiplos;imagem; +Keywords[pt_BR]=fundo;áreas de trabalho;cores;imagens;papel de parede;mistura;balanço;cache;múltiplos papéis de parede;pixmap; +Keywords[ro]=fundal;ecrane;culori;imagini;multiplu;amestecare;balans;cache;pixmap; +Keywords[ru]=background;desktops;colors;colours;images;wallpapers;blending;balance;cache;multiple wallpapers;pixmap;фон;изображение;обои;рабочий стол; +Keywords[rw]=Mbuganyuma;ibiro;amabara;amabara;amashusho;impapurorukuta;ivanga;iringaniza;ubwihisho;impapurorukuta zitandukanye;ikaritapigisi; +Keywords[se]=duogáš;čállinbeavddit;ivnnit;govat;duogášgovat;seaguheapmi;balánsa;máŋgá duogášgova; +Keywords[sk]=pozadie;plochy;farby;obrázky;tapety;blending;rovnováha;cache;viacnásobné tapety;pixmap; +Keywords[sl]=ozadje;namizja;barve;slike;tapete;več tapet;blending;pixmap; +Keywords[sr]=позадина;радне површине;боје;слике;позадинске слике;претапање;баланс;кеш;вишеструке позадинске слике; +Keywords[sr@Latn]=pozadina;radne površine;boje;slike;pozadinske slike;pretapanje;balans;keš;višestruke pozadinske slike; +Keywords[sv]=bakgrund;skrivbord;färger;bilder;skrivbordsunderlägg;blandning;balans;cache;flera skrivbordsunderlägg;pixmapp; +Keywords[ta]=பின்னணி;மேல்மேசை;வண்ணங்கள்;வண்ணங்கள்;சித்திரங்கள்;பின்னணி சித்திரங்கள்;கலத்தல்;மீதி;தற்காலிக;பலவகையான பின்னணி சித்திரங்கள்;பிக்ஸ்மாப்; +Keywords[tg]=background;desktops;colors;colours;images;wallpapers;blending;balance;cache;multiple wallpapers;pixmap; пасзамина; +Keywords[th]=พื้นหลัง;พื้นที่ทำงาน;สี;ชุดสี;ภาพ;ภาพพื้นหลัง;สมดุล;แคช;พื้นหลังหลายภาพ;บิตแมพ; +Keywords[tr]=artalan;masaüstü;renkler;renkler;resimler;duvar kağıtları;karıştırma;denge;ön bellek;çoklu duvar kağıtları;pixmap; +Keywords[uk]=тло;стільниці;кольори;зображення;шпалери;перехід;баланс;кеш;декілька шпалери;pixmap;стільниці; +Keywords[uz]=orqa fon;ish stollari;ranglar;rasmlar;wallpapers;blending;balance;kesh;multiple wallpapers;pixmap; +Keywords[uz@cyrillic]=орқа фон;иш столлари;ранглар;расмлар;wallpapers;блендинг;balance;кэш;multiple wallpapers;pixmap; +Keywords[ven]=murahu;desikithopo;mivhala;zwifanyiso;mabammbiri a luvhondoni;tanganisa;linganisa;cache;mabammbiri a luvhondoni manzhi;tsumbamashango ya phikisi; +Keywords[vi]=nền;màn hình nền;màu;màu sắc;ảnh;ảnh nền;trộn;cân bằng;đệm;nhiều ảnh nền;mảng ảnh; +Keywords[wa]=fond;sicribannes;coleurs;imaedjes;fond del waitroûle;maxhî;balance;muchete;sacwantes fonds d' waitroûle;pixmap; +Keywords[xh]=indawo yangasemva;desktops;imibala;imibala;imifanekiso;amaphepha odonga;uxubo;isikali;indawo efihlakeleyo yokufihla izixhobo;amaphepha odonga amaninzi;imaphu ye pix; +Keywords[zh_CN]=background;desktops;colors;colours;images;wallpapers;blending;balance;cache;multiple wallpapers;pixmap;背景;桌面;颜色;图像;墙纸;混色;平衡;缓冲;多个墙纸;位图; +Keywords[zh_TW]=background;desktops;colors;colours;images;wallpapers;blending;balance;cache;multiple wallpapers;pixmap;背景;桌面;顏色;影像;桌布;混色;平衡;緩衝;多個桌布;位圖; +Keywords[zu]=inkundla yangemuva;ama-desktop;imibala;imibala;izithombe;amaphepha ezindonga;ukuxubanisa;ukulinganisa;cache;amaphepha ezindonga eziningi;pixmap; + +Categories=Qt;TDE;X-TDE-settings-looknfeel; diff --git a/kcontrol/background/bgadvanced.cpp b/kcontrol/background/bgadvanced.cpp new file mode 100644 index 000000000..697836797 --- /dev/null +++ b/kcontrol/background/bgadvanced.cpp @@ -0,0 +1,507 @@ +/* vi: ts=8 sts=4 sw=4 + + This file is part of the KDE project, module kcmbackground. + + Copyright (C) 1999 Geert Jansen <[email protected]> + Copyright (C) 2003 Waldo Bastian <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <tqbuttongroup.h> +#include <tqcheckbox.h> +#include <tqheader.h> +#include <tqlabel.h> +#include <tqlayout.h> +#include <tqlineedit.h> +#include <tqcombobox.h> +#include <tqpushbutton.h> +#include <tqslider.h> +#include <tqspinbox.h> +#include <tqwhatsthis.h> + +#include <tdeconfig.h> +#include <kcolorbutton.h> +#include <tdelocale.h> +#include <tdemessagebox.h> +#include <kpixmap.h> +#include <kstandarddirs.h> +#include <twin.h> + +#include "bgrender.h" +#include "bgadvanced.h" +#include "bgadvanced_ui.h" + +#include <X11/Xlib.h> + +/**** BGAdvancedDialog ****/ + +static TQCString desktopConfigname() +{ + int desktop=0; + if (tqt_xdisplay()) + desktop = DefaultScreen(tqt_xdisplay()); + TQCString name; + if (desktop == 0) + name = "kdesktoprc"; + else + name.sprintf("kdesktop-screen-%drc", desktop); + + return name; +} + + +BGAdvancedDialog::BGAdvancedDialog(KBackgroundRenderer *_r, + TQWidget *parent, + bool m_multidesktop) + : KDialogBase(parent, "BGAdvancedDialog", + true, i18n("Advanced Background Settings"), + Ok | Cancel, Ok, true), + r(_r) +{ + dlg = new BGAdvancedBase(this); + setMainWidget(dlg); + + dlg->m_listPrograms->header()->setStretchEnabled ( true, 1 ); + dlg->m_listPrograms->setAllColumnsShowFocus(true); + + connect(dlg->m_listPrograms, TQT_SIGNAL(clicked(TQListViewItem *)), + TQT_SLOT(slotProgramItemClicked(TQListViewItem *))); + + // Load programs + TQStringList lst = KBackgroundProgram::list(); + TQStringList::Iterator it; + for (it=lst.begin(); it != lst.end(); ++it) + addProgram(*it); + + if (m_multidesktop) + { + TDEConfig cfg(desktopConfigname(), false, false); + cfg.setGroup( "General" ); + if (!cfg.readBoolEntry( "Enabled", true )) + { + dlg->m_groupIconText->hide(); + } + + dlg->m_spinCache->setSteps(512, 1024); + dlg->m_spinCache->setRange(0, 40960); + dlg->m_spinCache->setSpecialValueText(i18n("Unlimited")); + dlg->m_spinCache->setSuffix(i18n(" KB")); + + connect(dlg->m_buttonAdd, TQT_SIGNAL(clicked()), + TQT_SLOT(slotAdd())); + connect(dlg->m_buttonRemove, TQT_SIGNAL(clicked()), + TQT_SLOT(slotRemove())); + connect(dlg->m_buttonModify, TQT_SIGNAL(clicked()), + TQT_SLOT(slotModify())); + + connect(dlg->m_listPrograms, TQT_SIGNAL(doubleClicked(TQListViewItem *)), + TQT_SLOT(slotProgramItemDoubleClicked(TQListViewItem *))); + } + else + { + dlg->m_buttonAdd->hide(); + dlg->m_buttonRemove->hide(); + dlg->m_buttonModify->hide(); + dlg->m_groupIconText->hide(); + dlg->m_groupCache->hide(); + } + + connect( dlg->m_cbProgram, TQT_SIGNAL(toggled(bool)), + TQT_SLOT(slotEnableProgram(bool))); + + m_backgroundMode = m_oldBackgroundMode = r->backgroundMode(); + if (m_oldBackgroundMode == KBackgroundSettings::Program) + m_oldBackgroundMode = KBackgroundSettings::Flat; + + dlg->adjustSize(); + updateUI(); +} + +void BGAdvancedDialog::makeReadOnly() +{ + dlg->m_cbProgram->setEnabled(false); + dlg->m_listPrograms->setEnabled(false); +} + +void BGAdvancedDialog::setCacheSize(int s) +{ + dlg->m_spinCache->setValue(s); +} + +int BGAdvancedDialog::cacheSize() +{ + return dlg->m_spinCache->value(); +} + +TQColor BGAdvancedDialog::textColor() +{ + return dlg->m_colorText->color(); +} + +void BGAdvancedDialog::setTextColor(const TQColor &color) +{ + dlg->m_colorText->setColor(color); +} + +TQColor BGAdvancedDialog::textBackgroundColor() +{ + return dlg->m_cbSolidTextBackground->isChecked() ? + dlg->m_colorTextBackground->color() : TQColor(); +} + +void BGAdvancedDialog::setTextBackgroundColor(const TQColor &color) +{ + dlg->m_colorTextBackground->blockSignals(true); + dlg->m_cbSolidTextBackground->blockSignals(true); + if (color.isValid()) + { + dlg->m_cbSolidTextBackground->setChecked(true); + dlg->m_colorTextBackground->setColor(color); + dlg->m_colorTextBackground->setEnabled(true); + } + else + { + dlg->m_cbSolidTextBackground->setChecked(false); + dlg->m_colorTextBackground->setColor(Qt::white); + dlg->m_colorTextBackground->setEnabled(false); + } + dlg->m_colorTextBackground->blockSignals(false); + dlg->m_cbSolidTextBackground->blockSignals(false); +} + +bool BGAdvancedDialog::shadowEnabled() +{ + return dlg->m_cbShadow->isChecked(); +} + +void BGAdvancedDialog::setShadowEnabled(bool enabled) +{ + dlg->m_cbShadow->setChecked(enabled); +} + +void BGAdvancedDialog::setTextLines(int lines) +{ + dlg->m_spinTextLines->setValue(lines); +} + +int BGAdvancedDialog::textLines() const +{ + return dlg->m_spinTextLines->value(); +} + +void BGAdvancedDialog::setTextWidth(int width) +{ + dlg->m_spinTextWidth->setValue(width); +} + +int BGAdvancedDialog::textWidth() const +{ + return dlg->m_spinTextWidth->value(); +} + +void BGAdvancedDialog::updateUI() +{ + TQString prog = r->KBackgroundProgram::name(); + + dlg->m_cbProgram->blockSignals(true); + if ((r->backgroundMode() == KBackgroundSettings::Program) + && !prog.isEmpty()) + { + dlg->m_cbProgram->setChecked(true); + dlg->m_listPrograms->setEnabled(true); + dlg->m_buttonAdd->setEnabled(true); + dlg->m_buttonRemove->setEnabled(true); + dlg->m_buttonModify->setEnabled(true); + selectProgram(prog); + } + else + { + dlg->m_cbProgram->setChecked(false); + dlg->m_listPrograms->setEnabled(false); + dlg->m_buttonAdd->setEnabled(false); + dlg->m_buttonRemove->setEnabled(false); + dlg->m_buttonModify->setEnabled(false); + } + dlg->m_cbProgram->blockSignals(false); +} + +void BGAdvancedDialog::removeProgram(const TQString &name) +{ + if (m_programItems.find(name)) + { + delete m_programItems[name]; + m_programItems.remove(name); + } +} + +void BGAdvancedDialog::addProgram(const TQString &name) +{ + removeProgram(name); + + KBackgroundProgram prog(name); + if (prog.command().isEmpty() || (prog.isGlobal() && !prog.isAvailable())) + return; + + TQListViewItem *item = new TQListViewItem(dlg->m_listPrograms); + item->setText(0, prog.name()); + item->setText(1, prog.comment()); + item->setText(2, i18n("%1 min.").arg(prog.refresh())); + + m_programItems.insert(name, item); +} + +void BGAdvancedDialog::selectProgram(const TQString &name) +{ + if (m_programItems.find(name)) + { + TQListViewItem *item = m_programItems[name]; + dlg->m_listPrograms->ensureItemVisible(item); + dlg->m_listPrograms->setSelected(item, true); + m_selectedProgram = name; + } +} + +void BGAdvancedDialog::slotAdd() +{ + KProgramEditDialog dlg; + dlg.exec(); + if (dlg.result() == TQDialog::Accepted) + { + TQString program = dlg.program(); + addProgram(program); + selectProgram(program); + } +} + +void BGAdvancedDialog::slotRemove() +{ + if (m_selectedProgram.isEmpty()) + return; + + KBackgroundProgram prog(m_selectedProgram); + if (prog.isGlobal()) + { + KMessageBox::sorry(this, + i18n("Unable to remove the program: the program is global " + "and can only be removed by the system administrator."), + i18n("Cannot Remove Program")); + return; + } + if (KMessageBox::warningContinueCancel(this, + i18n("Are you sure you want to remove the program `%1'?") + .arg(prog.name()), + i18n("Remove Background Program"), + i18n("&Remove")) != KMessageBox::Continue) + return; + + prog.remove(); + removeProgram(m_selectedProgram); + m_selectedProgram = TQString::null; +} + +/* + * Modify a program. + */ +void BGAdvancedDialog::slotModify() +{ + if (m_selectedProgram.isEmpty()) + return; + + KProgramEditDialog dlg(m_selectedProgram); + dlg.exec(); + if (dlg.result() == TQDialog::Accepted) + { + TQString program = dlg.program(); + if (program != m_selectedProgram) + { + KBackgroundProgram prog(m_selectedProgram); + prog.remove(); + removeProgram(m_selectedProgram); + } + addProgram(dlg.program()); + selectProgram(dlg.program()); + } +} + +void BGAdvancedDialog::slotProgramItemClicked(TQListViewItem *item) +{ + if (item) + m_selectedProgram = item->text(0); + slotProgramChanged(); +} + +void BGAdvancedDialog::slotProgramItemDoubleClicked(TQListViewItem *item) +{ + slotProgramItemClicked(item); + slotModify(); +} + +void BGAdvancedDialog::slotProgramChanged() +{ + if (dlg->m_cbProgram->isChecked() && !m_selectedProgram.isEmpty()) + m_backgroundMode = KBackgroundSettings::Program; + else + m_backgroundMode = m_oldBackgroundMode; +} + +void BGAdvancedDialog::slotEnableProgram(bool b) +{ + dlg->m_listPrograms->setEnabled(b); + if (b) + { + dlg->m_listPrograms->blockSignals(true); + TQListViewItem *cur = dlg->m_listPrograms->currentItem(); + dlg->m_listPrograms->setSelected(cur, true); + dlg->m_listPrograms->ensureItemVisible(cur); + dlg->m_listPrograms->blockSignals(false); + slotProgramItemClicked(cur); + } + else + { + slotProgramChanged(); + } +} + +TQString BGAdvancedDialog::backgroundProgram() const +{ + return m_selectedProgram; +} + +int BGAdvancedDialog::backgroundMode() const +{ + return m_backgroundMode; +} + +/**** KProgramEditDialog ****/ + +KProgramEditDialog::KProgramEditDialog(const TQString &program, TQWidget *parent, char *name) + : KDialogBase(parent, name, true, i18n("Configure Background Program"), + Ok | Cancel, Ok, true) +{ + TQFrame *frame = makeMainWidget(); + + TQGridLayout *grid = new TQGridLayout(frame, 6, 2, 0, spacingHint()); + grid->addColSpacing(1, 300); + + TQLabel *lbl = new TQLabel(i18n("&Name:"), frame); + grid->addWidget(lbl, 0, 0); + m_NameEdit = new TQLineEdit(frame); + lbl->setBuddy(m_NameEdit); + grid->addWidget(m_NameEdit, 0, 1); + + lbl = new TQLabel(i18n("Co&mment:"), frame); + grid->addWidget(lbl, 1, 0); + m_CommentEdit = new TQLineEdit(frame); + lbl->setBuddy(m_CommentEdit); + grid->addWidget(m_CommentEdit, 1, 1); + + lbl = new TQLabel(i18n("Comman&d:"), frame); + grid->addWidget(lbl, 2, 0); + m_CommandEdit = new TQLineEdit(frame); + lbl->setBuddy(m_CommandEdit); + grid->addWidget(m_CommandEdit, 2, 1); + + lbl = new TQLabel(i18n("&Preview cmd:"), frame); + grid->addWidget(lbl, 3, 0); + m_PreviewEdit = new TQLineEdit(frame); + lbl->setBuddy(m_PreviewEdit); + grid->addWidget(m_PreviewEdit, 3, 1); + + lbl = new TQLabel(i18n("&Executable:"), frame); + grid->addWidget(lbl, 4, 0); + m_ExecEdit = new TQLineEdit(frame); + lbl->setBuddy(m_ExecEdit); + grid->addWidget(m_ExecEdit, 4, 1); + + lbl = new TQLabel(i18n("&Refresh time:"), frame); + grid->addWidget(lbl, 5, 0); + m_RefreshEdit = new TQSpinBox(frame); + m_RefreshEdit->setRange(5, 60); + m_RefreshEdit->setSteps(5, 10); + m_RefreshEdit->setSuffix(i18n(" min")); + m_RefreshEdit->setFixedSize(m_RefreshEdit->sizeHint()); + lbl->setBuddy(m_RefreshEdit); + grid->addWidget(m_RefreshEdit, 5, 1, Qt::AlignLeft); + + m_Program = program; + if (m_Program.isEmpty()) { + KBackgroundProgram prog(i18n("New Command")); + int i = 1; + while (!prog.command().isEmpty()) + prog.load(i18n("New Command <%1>").arg(i++)); + m_NameEdit->setText(prog.name()); + m_NameEdit->setSelection(0, 100); + m_RefreshEdit->setValue(15); + return; + } + + // Fill in the fields + m_NameEdit->setText(m_Program); + KBackgroundProgram prog(m_Program); + m_CommentEdit->setText(prog.comment()); + m_ExecEdit->setText(prog.executable()); + m_CommandEdit->setText(prog.command()); + m_PreviewEdit->setText(prog.previewCommand()); + m_RefreshEdit->setValue(prog.refresh()); +} + + +TQString KProgramEditDialog::program()const +{ + return m_NameEdit->text(); +} + +void KProgramEditDialog::slotOk() +{ + TQString s = m_NameEdit->text(); + if (s.isEmpty()) { + KMessageBox::sorry(this, i18n("You did not fill in the `Name' field.\n" + "This is a required field.")); + return; + } + + KBackgroundProgram prog(s); + if ((s != m_Program) && !prog.command().isEmpty()) { + int ret = KMessageBox::warningContinueCancel(this, + i18n("There is already a program with the name `%1'.\n" + "Do you want to overwrite it?").arg(s),TQString::null,i18n("Overwrite")); + if (ret != KMessageBox::Continue) + return; + } + + if (m_ExecEdit->text().isEmpty()) { + KMessageBox::sorry(this, i18n("You did not fill in the `Executable' field.\n" + "This is a required field.")); + return; + } + if (m_CommandEdit->text().isEmpty()) { + KMessageBox::sorry(this, i18n("You did not fill in the `Command' field.\n" + "This is a required field.")); + return; + } + + prog.setComment(m_CommentEdit->text()); + prog.setExecutable(m_ExecEdit->text()); + prog.setCommand(m_CommandEdit->text()); + prog.setPreviewCommand(m_PreviewEdit->text()); + prog.setRefresh(m_RefreshEdit->value()); + + prog.writeSettings(); + accept(); +} + + +#include "bgadvanced.moc" diff --git a/kcontrol/background/bgadvanced.h b/kcontrol/background/bgadvanced.h new file mode 100644 index 000000000..cc1ba7bf1 --- /dev/null +++ b/kcontrol/background/bgadvanced.h @@ -0,0 +1,121 @@ +/* vi: ts=8 sts=4 sw=4 + + This file is part of the KDE project, module kcmbackground. + + Copyright (C) 1999 Geert Jansen <[email protected]> + Copyright (C) 2003 Waldo Bastian <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 BGADVANCED_H +#define BGADVANCED_H + +#include <tqdict.h> +#include <tqlistview.h> +#include <tqstringlist.h> + +#include <kdialogbase.h> + +class TQLineEdit; +class TQSpinBox; + +class BGAdvancedBase; +class KBackgroundRenderer; +class KBackgroundProgram; + +class BGAdvancedDialog : public KDialogBase +{ + Q_OBJECT +public: + BGAdvancedDialog(KBackgroundRenderer *_r, TQWidget *parent, bool m_multidesktop); + + void setCacheSize(int s); + int cacheSize(); + TQColor textColor(); + void setTextColor(const TQColor &color); + TQColor textBackgroundColor(); + void setTextBackgroundColor(const TQColor &color); + bool shadowEnabled(); + void setShadowEnabled(bool enabled); + void setTextLines(int lines); + int textLines() const; + void setTextWidth(int width); + int textWidth() const; + + void updateUI(); + + void makeReadOnly(); + + TQString backgroundProgram() const; + int backgroundMode() const; + +public slots: + void slotAdd(); + void slotRemove(); + void slotModify(); + +protected: + void addProgram(const TQString &name); + void removeProgram(const TQString &name); + void selectProgram(const TQString &name); + +protected slots: + void slotProgramItemClicked(TQListViewItem *item); + void slotProgramItemDoubleClicked(TQListViewItem *item); + void slotProgramChanged(); + void slotEnableProgram(bool b); + +private: + KBackgroundRenderer *r; + + BGAdvancedBase *dlg; + + TQWidget *m_pMonitor; + TQDict<TQListViewItem> m_programItems; + TQString m_selectedProgram; + int m_oldBackgroundMode; + int m_backgroundMode; +}; + +/** + * Dialog to edit a background program. + */ +class KProgramEditDialog: public KDialogBase +{ + Q_OBJECT + +public: + KProgramEditDialog(const TQString &program=TQString::null, TQWidget *parent=0L, + char *name=0L); + + /** The program name is here in case the user changed it */ + TQString program()const; + +public slots: + void slotOk(); + +private: + TQString m_Program; + TQLineEdit *m_NameEdit, *m_CommentEdit; + TQLineEdit *m_ExecEdit, *m_CommandEdit; + TQLineEdit *m_PreviewEdit; + TQSpinBox *m_RefreshEdit; + KBackgroundProgram *m_Prog; +}; + + +#endif + diff --git a/kcontrol/background/bgadvanced_ui.ui b/kcontrol/background/bgadvanced_ui.ui new file mode 100644 index 000000000..34f8f9db5 --- /dev/null +++ b/kcontrol/background/bgadvanced_ui.ui @@ -0,0 +1,462 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>BGAdvancedBase</class> +<widget class="TQWidget"> + <property name="name"> + <cstring>BGAdvancedBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>511</width> + <height>454</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="TQButtonGroup"> + <property name="name"> + <cstring>m_groupProgram</cstring> + </property> + <property name="title"> + <string>Background Program</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <widget class="TQPushButton" row="1" column="1"> + <property name="name"> + <cstring>m_buttonAdd</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>&Add...</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qt> +<p>Click here if you want to add a program to the listbox. This button opens a dialog where you are asked to give details about the program you want to run. To successfully add a program, you must know if it is compatible, the name of the executable file and, if necessary, its options.</p> +<p>You usually can get the available options to a suitable program by typing in a terminal emulator the name of the executable file plus --help (foobar --help).</p> +</qt></string> + </property> + </widget> + <widget class="TQPushButton" row="2" column="1"> + <property name="name"> + <cstring>m_buttonRemove</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>&Remove</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Click here to remove programs from this list. Please note that it does not remove the program from your system, it only removes it from the available options in the background drawing programs list.</string> + </property> + </widget> + <widget class="TQPushButton" row="3" column="1"> + <property name="name"> + <cstring>m_buttonModify</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>&Modify...</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qt> +<p>Click here to modify the programs options. You usually can get the available options to a suitable program by typing in a terminal emulator the name of the executable file plus --help. (example: kwebdesktop --help).</p> +<p>One useful example is the program kwebdesktop. It draws a web page on the background of your desktop. You can use this program by selecting it on the listbox on the right, but it will draw a predefined web page. To change the web page it renders, select the kwebdesktop program on the listbox, then click here. A dialog will appear, allowing you to change the web page by replacing the old address (URL) with a new one.</p> +</qt></string> + </property> + </widget> + <spacer row="4" column="1"> + <property name="name"> + <cstring>spacer</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="TQListView" row="1" column="0" rowspan="4" colspan="1"> + <column> + <property name="text"> + <string>Program</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Comment</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Refresh</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>m_listPrograms</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimumSize"> + <size> + <width>400</width> + <height>0</height> + </size> + </property> + <property name="whatsThis" stdset="0"> + <string><qt> +<p>Select from this listbox the program you want to use to draw your desktop background.</p> +<p>The <b>Program</b> column shows the name of the program.<br> +The <b>Comment</b> column brings a short description.<br> +The <b>Refresh</b> column indicates the time interval between redraws of the desktop.</p> +<p>The <b>K Web Desktop</b> program (kwebdesktop) is worth noting: it draws a specified page of the web in your desktop. You can modify it, and the webpage it draws by selecting it here, then clicking on the <b>Modify</b> button.<br> +You can also add new compliant programs. To do that, click on the <b>Add</b> button.<br> +You can also remove programs from this list clicking on the <b>Remove</b> button. Please note that it does not remove the program from your system, it only removes it from the available options in this listbox.</p> +</qt></string> + </property> + </widget> + <widget class="TQCheckBox" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_cbProgram</cstring> + </property> + <property name="text"> + <string>Use the following program for drawing the background:</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Check here if you want to allow a program to draw your desktop background. Below you can find the list of programs currently available for drawing the background. You may use one of the available programs, add new ones or modify the existing ones to fit your needs.</string> + </property> + </widget> + </grid> + </widget> + <widget class="TQGroupBox"> + <property name="name"> + <cstring>m_groupIconText</cstring> + </property> + <property name="title"> + <string>Background Icon Text</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KColorButton" row="0" column="1"> + <property name="name"> + <cstring>m_colorText</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string></string> + </property> + <property name="whatsThis" stdset="0"> + <string>Click here to change the color of the desktop font.</string> + </property> + </widget> + <widget class="TQLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel6</cstring> + </property> + <property name="text"> + <string>&Text color:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_colorText</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>Click here to change the color of the desktop font.</string> + </property> + </widget> + <spacer row="0" column="2" rowspan="2" colspan="1"> + <property name="name"> + <cstring>spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>220</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KColorButton" row="1" column="1"> + <property name="name"> + <cstring>m_colorTextBackground</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string></string> + </property> + <property name="whatsThis" stdset="0"> + <string>Click here to select the solid background color. Choose a different color from the background text color to assure readability.</string> + </property> + </widget> + <widget class="TQCheckBox" row="1" column="0"> + <property name="name"> + <cstring>m_cbSolidTextBackground</cstring> + </property> + <property name="text"> + <string>&Use solid color behind text:</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Check here if you want to use a solid background color. This is useful to ensure that the desktop text will be identifiable against all background colors and wallpapers, or in other words, that a background or wallpaper will not make a desktop text of a similar color difficult to read.</string> + </property> + </widget> + <widget class="TQCheckBox" row="2" column="0"> + <property name="name"> + <cstring>m_cbShadow</cstring> + </property> + <property name="text"> + <string>&Enable shadow</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Check here to enable a shadow outline around the desktop font. This also improves the readability of the desktop text against backgrounds of a similar color.</string> + </property> + </widget> + <widget class="TQLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel6_2</cstring> + </property> + <property name="text"> + <string>&Lines for icon text:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_colorText</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>Choose here the maximum number of text lines below an icon on the desktop. Longer text will be truncated at the end of the last line.</string> + </property> + </widget> + <widget class="TQSpinBox" row="3" column="1"> + <property name="name"> + <cstring>m_spinTextLines</cstring> + </property> + <property name="suffix"> + <string></string> + </property> + <property name="value"> + <number>0</number> + </property> + <property name="whatsThis" stdset="0"> + <string>Choose here the maximum number of text lines below an icon on the desktop. Longer text will be truncated at the end of the last line.</string> + </property> + </widget> + <widget class="TQSpinBox" row="4" column="1"> + <property name="name"> + <cstring>m_spinTextWidth</cstring> + </property> + <property name="suffix"> + <string></string> + </property> + <property name="specialValueText"> + <string>Auto</string> + </property> + <property name="maxValue"> + <number>99999</number> + </property> + <property name="value"> + <number>0</number> + </property> + <property name="whatsThis" stdset="0"> + <string>Choose here the maximum width of text lines (in pixel) below an icon on the desktop. If set to 'Auto' a default width based on the current font is used.</string> + </property> + </widget> + <widget class="TQLabel" row="4" column="0"> + <property name="name"> + <cstring>textLabel6_2_2</cstring> + </property> + <property name="text"> + <string>&Width for icon text:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_colorText</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>Choose here the maximum width of text lines (in pixel) below an icon on the desktop. If set to 'Auto' a default width based on the current font is used.</string> + </property> + </widget> + </grid> + </widget> + <widget class="TQButtonGroup"> + <property name="name"> + <cstring>m_groupCache</cstring> + </property> + <property name="title"> + <string>Memory Usage</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <widget class="TQLabel"> + <property name="name"> + <cstring>m_lblCache</cstring> + </property> + <property name="text"> + <string>Size of background cache:</string> + </property> + <property name="whatsThis" stdset="0"> + <string>In this box you can enter how much memory TDE should use for caching the background(s). If you have different backgrounds for the different desktops caching can make switching desktops smoother at the expense of higher memory use.</string> + </property> + </widget> + <widget class="TQSpinBox"> + <property name="name"> + <cstring>m_spinCache</cstring> + </property> + <property name="suffix"> + <string> k</string> + </property> + <property name="whatsThis" stdset="0"> + <string>In this box you can enter how much memory TDE should use for caching the background(s). If you have different backgrounds for the different desktops caching can make switching desktops smoother at the expense of higher memory use.</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>m_cbProgram</sender> + <signal>toggled(bool)</signal> + <receiver>m_buttonAdd</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>m_cbProgram</sender> + <signal>toggled(bool)</signal> + <receiver>m_buttonRemove</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>m_cbProgram</sender> + <signal>toggled(bool)</signal> + <receiver>m_buttonModify</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>m_cbProgram</sender> + <signal>toggled(bool)</signal> + <receiver>m_listPrograms</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>m_cbSolidTextBackground</sender> + <signal>toggled(bool)</signal> + <receiver>m_colorTextBackground</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>m_cbProgram</tabstop> + <tabstop>m_listPrograms</tabstop> + <tabstop>m_buttonAdd</tabstop> + <tabstop>m_buttonRemove</tabstop> + <tabstop>m_buttonModify</tabstop> + <tabstop>m_colorText</tabstop> + <tabstop>m_cbSolidTextBackground</tabstop> + <tabstop>m_colorTextBackground</tabstop> + <tabstop>m_cbShadow</tabstop> + <tabstop>m_spinCache</tabstop> +</tabstops> +<includes> + <include location="global" impldecl="in implementation">kdialog.h</include> +</includes> +<layoutdefaults spacing="3" margin="6"/> +<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/> +<includehints> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> +</includehints> +</UI> diff --git a/kcontrol/background/bgdefaults.h b/kcontrol/background/bgdefaults.h new file mode 100644 index 000000000..d64c6e546 --- /dev/null +++ b/kcontrol/background/bgdefaults.h @@ -0,0 +1,39 @@ +/* vi: ts=8 sts=4 sw=4 + * + * This file is part of the KDE project, module kdesktop. + * Copyright (C) 1999 Geert Jansen <[email protected]> + * + * You can Freely distribute this program under the GNU General Public + * License. See the file "COPYING" for the exact licensing terms. + */ +#ifndef __BGDefaults_h_Included__ +#define __BGDefaults_h_Included__ + + +// Globals +#define _defDrawBackgroundPerScreen false +#define _defCommonScreen true +#define _defCommonDesk true +#define _defDock true +#define _defExport false +#define _defLimitCache false +#define _defCacheSize 2048 + +#define _defShm false +// there are usually poor results with bpp<16 when tiling +#define _defMinOptimizationDepth 1 + +// Per desktop defaults +// Before you change this get in touch with me ([email protected]) +// Thanks!! +#define _defColorA TQColor("#003082") +#define _defColorB TQColor("#C0C0C0") +#define _defBackgroundMode KBackgroundSettings::Flat +#define _defWallpaperMode KBackgroundSettings::Scaled +#define _defMultiMode KBackgroundSettings::NoMulti +#define _defBlendMode KBackgroundSettings::NoBlending +#define _defBlendBalance 100 +#define _defReverseBlending false +#define _defCrossFadeBg false + +#endif // __BGDefaults_h_Included__ diff --git a/kcontrol/background/bgdialog.cpp b/kcontrol/background/bgdialog.cpp new file mode 100644 index 000000000..e903b7bc2 --- /dev/null +++ b/kcontrol/background/bgdialog.cpp @@ -0,0 +1,1332 @@ +/* + kate: space-indent on; indent-width 3; indent-mode cstyle; + + This file is part of the KDE libraries + + Copyright (c) 2005 David Saxton <[email protected]> + Copyright (c) 2003 Waldo Bastian <[email protected]> + Copyright (c) 1999 Geert Jansen <[email protected]> + Copyright (c) 1996 Martin R. Jones + Copyright (c) 1997 Matthias Hoelzer + Copyright (c) 1997 Mark Donohoe + Copyright (c) 1998 Stephan Kulow + Copyright (c) 1998 Matej Koss + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <config.h> + +#include <tqbuttongroup.h> +#include <tqcheckbox.h> +#include <tqlabel.h> +#include <tqpainter.h> +#include <tqradiobutton.h> +#include <tqslider.h> +#include <tqtimer.h> +#include <tqtooltip.h> +#include <tqwhatsthis.h> +#include <tqapplication.h> + +#include <tdeconfig.h> +#include <kdebug.h> +#include <tdefiledialog.h> +#include <tdefilemetainfo.h> +#include <tdeglobal.h> +#include <kiconloader.h> +#include <kimageio.h> +#include <tdelocale.h> +#include <kpixmap.h> +#include <kstandarddirs.h> +#include <kstringhandler.h> +#include <kurlrequester.h> +#include <twin.h> +#include <twinmodule.h> +#include <kimagefilepreview.h> +#include <tdenewstuff/downloaddialog.h> + +#include <stdlib.h> + +#include "bgmonitor.h" +#include "bgwallpaper.h" +#include "bgadvanced.h" +#include "bgdialog.h" + +#define NR_PREDEF_PATTERNS 6 + +BGDialog::BGDialog(TQWidget* parent, TDEConfig* _config, bool _multidesktop) + : BGDialog_UI(parent, "BGDialog") +{ + m_pGlobals = new TDEGlobalBackgroundSettings(_config); + m_pDirs = TDEGlobal::dirs(); + m_multidesktop = _multidesktop; + m_previewUpdates = true; + + KWinModule *m_twin; + m_twin = new KWinModule(TQT_TQOBJECT(this)); + m_curDesk = m_twin->currentDesktop(); + TQSize s(m_twin->numberOfViewports(m_twin->currentDesktop())); + m_useViewports = s.width() * s.height() > 1; + + m_numDesks = m_multidesktop ? KWin::numberOfDesktops() : 1; + m_numViewports = s.width() * s.height(); + m_numScreens = TQApplication::desktop()->numScreens(); + + TQCString multiHead = getenv("TDE_MULTIHEAD"); + if (multiHead.lower() == "true") + { + m_numScreens = 1; + } + + TQPoint vx(m_twin->currentViewport(m_twin->currentDesktop())); + int t_eViewport = (vx.x() * vx.y()); + if (t_eViewport < 1) { + t_eViewport = 1; + } + delete m_twin; + + m_desk = m_multidesktop ? KWin::currentDesktop() : 1; + m_desk = m_multidesktop ? (m_useViewports ? (((m_desk - 1) * m_numViewports) + t_eViewport) : m_desk) : m_desk; + m_numDesks = m_multidesktop ? (m_useViewports ? (m_numDesks * m_numViewports) : m_numDesks) : m_numDesks; + + m_screen = TQApplication::desktop()->screenNumber(this); + if (m_screen >= (int)m_numScreens) + m_screen = m_numScreens-1; + + m_eDesk = m_pGlobals->commonDeskBackground() ? 0 : m_desk; + getEScreen(); + m_copyAllDesktops = true; + m_copyAllScreens = true; + + if (!m_multidesktop) + { + m_pDesktopLabel->hide(); + m_comboDesktop->hide(); + } + + if (m_numScreens < 2) + { + m_comboScreen->hide(); + m_buttonIdentifyScreens->hide(); + m_screen = 0; + m_eScreen = 0; + } + + connect(m_buttonIdentifyScreens, TQT_SIGNAL(clicked()), TQT_SLOT(slotIdentifyScreens())); + + // preview monitor + m_pMonitorArrangement = new BGMonitorArrangement(m_screenArrangement, "monitor arrangement"); + connect(m_pMonitorArrangement, TQT_SIGNAL(imageDropped(const TQString &)), TQT_SLOT(slotImageDropped(const TQString &))); + if( m_multidesktop) + { + // desktop + connect(m_comboDesktop, TQT_SIGNAL(activated(int)), + TQT_SLOT(slotSelectDesk(int))); + } + if (m_numScreens > 1) + { + connect(m_comboScreen, TQT_SIGNAL(activated(int)), + TQT_SLOT(slotSelectScreen(int))); + } + + // background image settings + TQIconSet iconSet = SmallIconSet(TQString::fromLatin1("document-open")); + TQPixmap pixMap = iconSet.pixmap( TQIconSet::Small, TQIconSet::Normal ); + m_urlWallpaperButton->setIconSet( iconSet ); + m_urlWallpaperButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 ); + TQToolTip::add(m_urlWallpaperButton, i18n("Open file dialog")); + + connect(m_buttonGroupBackground, TQT_SIGNAL(clicked(int)), + TQT_SLOT(slotWallpaperTypeChanged(int))); + connect(m_urlWallpaperBox, TQT_SIGNAL(activated(int)), + TQT_SLOT(slotWallpaper(int))); + connect(m_urlWallpaperButton, TQT_SIGNAL(clicked()), + TQT_SLOT(slotWallpaperSelection())); + connect(m_comboWallpaperPos, TQT_SIGNAL(activated(int)), + TQT_SLOT(slotWallpaperPos(int))); + connect(m_buttonSetupWallpapers, TQT_SIGNAL(clicked()), + TQT_SLOT(slotSetupMulti())); + + // set up the background colour stuff + connect(m_colorPrimary, TQT_SIGNAL(changed(const TQColor &)), + TQT_SLOT(slotPrimaryColor(const TQColor &))); + connect(m_colorSecondary, TQT_SIGNAL(changed(const TQColor &)), + TQT_SLOT(slotSecondaryColor(const TQColor &))); + connect(m_comboPattern, TQT_SIGNAL(activated(int)), + TQT_SLOT(slotPattern(int))); + + // blend + connect(m_comboBlend, TQT_SIGNAL(activated(int)), TQT_SLOT(slotBlendMode(int))); + connect(m_sliderBlend, TQT_SIGNAL(valueChanged(int)), + TQT_SLOT(slotBlendBalance(int))); + connect(m_cbBlendReverse, TQT_SIGNAL(toggled(bool)), + TQT_SLOT(slotBlendReverse(bool))); + + // Crossfading background + connect(m_cbCrossFadeBg, TQT_SIGNAL(toggled(bool)), + TQT_SLOT(slotCrossFadeBg(bool))); + + // advanced options + connect(m_buttonAdvanced, TQT_SIGNAL(clicked()), + TQT_SLOT(slotAdvanced())); + + connect(m_buttonGetNew, TQT_SIGNAL(clicked()), + TQT_SLOT(slotGetNewStuff())); + + // renderers + m_renderer.resize(m_numDesks+1); + + if (m_numScreens > 1) + { + for (unsigned i = 0; i < m_numDesks+1; ++i) + { + m_renderer[i].resize(m_numScreens+2); + m_renderer[i].setAutoDelete(true); + + int eDesk = i>0 ? i-1 : 0; + + // Setup the merged-screen renderer + KBackgroundRenderer * r = new KBackgroundRenderer(eDesk, 0, false, _config); + m_renderer[i].insert( 0, r ); + connect( r, TQT_SIGNAL(imageDone(int,int)), TQT_SLOT(slotPreviewDone(int,int)) ); + + // Setup the common-screen renderer + r = new KBackgroundRenderer(eDesk, 0, true, _config); + m_renderer[i].insert( 1, r ); + connect( r, TQT_SIGNAL(imageDone(int,int)), TQT_SLOT(slotPreviewDone(int,int)) ); + + // Setup the remaining renderers for each screen + for (unsigned j=0; j < m_numScreens; ++j ) + { + r = new KBackgroundRenderer(eDesk, j, true, _config); + m_renderer[i].insert( j+2, r ); + connect( r, TQT_SIGNAL(imageDone(int,int)), TQT_SLOT(slotPreviewDone(int,int)) ); + } + } + } + else + { + for (unsigned i = 0; i < m_numDesks+1; ++i ) + { + m_renderer[i].resize(1); + m_renderer[i].setAutoDelete(true); + } + + // set up the common desktop renderer + KBackgroundRenderer * r = new KBackgroundRenderer(0, 0, false, _config); + m_renderer[0].insert(0, r); + connect(r, TQT_SIGNAL(imageDone(int,int)), TQT_SLOT(slotPreviewDone(int,int))); + + // set up all the other desktop renderers + for (unsigned i = 0; i < m_numDesks; ++i) + { + r = new KBackgroundRenderer(i, 0, false, _config); + m_renderer[i+1].insert(0, r); + connect(r, TQT_SIGNAL(imageDone(int,int)), TQT_SLOT(slotPreviewDone(int,int))); + } + } + + // Random or InOrder + m_slideShowRandom = eRenderer()->multiWallpaperMode(); + if (m_slideShowRandom == KBackgroundSettings::NoMultiRandom) + m_slideShowRandom = KBackgroundSettings::Random; + if (m_slideShowRandom == KBackgroundSettings::NoMulti) + m_slideShowRandom = KBackgroundSettings::InOrder; + + // Wallpaper Position + m_wallpaperPos = eRenderer()->wallpaperMode(); + if (m_wallpaperPos == KBackgroundSettings::NoWallpaper) + m_wallpaperPos = KBackgroundSettings::Centred; // Default + + if (TDEGlobal::dirs()->isRestrictedResource("wallpaper")) + { + m_urlWallpaperButton->hide(); + m_buttonSetupWallpapers->hide(); + m_radioSlideShow->hide(); + } + + initUI(); + updateUI(); + +#if (TQT_VERSION-0 >= 0x030200) + connect( tqApp->desktop(), TQT_SIGNAL( resized( int )), TQT_SLOT( desktopResized())); // RANDR support +#endif +} + +BGDialog::~BGDialog() +{ + delete m_pGlobals; +} + +KBackgroundRenderer * BGDialog::eRenderer() +{ + return m_renderer[m_eDesk][m_eScreen]; +} + +void BGDialog::getEScreen() +{ + if ( m_pGlobals->drawBackgroundPerScreen( m_eDesk>0 ? m_eDesk-1 : 0 ) ) + m_eScreen = m_pGlobals->commonScreenBackground() ? 1 : m_screen+2; + else + m_eScreen = 0; + + if ( m_numScreens == 1 ) + m_eScreen = 0; + else if ( m_eScreen > int(m_numScreens+1) ) + m_eScreen = m_numScreens+1; +} + +void BGDialog::makeReadOnly() +{ + m_pMonitorArrangement->setEnabled( false ); + m_comboScreen->setEnabled( false ); + m_comboDesktop->setEnabled( false ); + m_colorPrimary->setEnabled( false ); + m_colorSecondary->setEnabled( false ); + m_comboPattern->setEnabled( false ); + m_radioNoPicture->setEnabled( false ); + m_radioPicture->setEnabled( false ); + m_radioSlideShow->setEnabled( false ); + m_urlWallpaperBox->setEnabled( false ); + m_urlWallpaperButton->setEnabled( false ); + m_comboWallpaperPos->setEnabled( false ); + m_buttonSetupWallpapers->setEnabled( false ); + m_comboBlend->setEnabled( false ); + m_sliderBlend->setEnabled( false ); + m_cbBlendReverse->setEnabled( false ); + m_buttonAdvanced->setEnabled( false ); + m_buttonGetNew->setEnabled( false ); + m_cbCrossFadeBg->setEnabled( false ); +} + +void BGDialog::load( bool useDefaults ) +{ + m_pGlobals->getConfig()->setReadDefaults( useDefaults ); + m_pGlobals->readSettings(); + m_eDesk = m_pGlobals->commonDeskBackground() ? 0 : m_desk; + getEScreen(); + + for (unsigned desk = 0; desk < m_renderer.size(); ++desk) + { + unsigned eDesk = desk>0 ? desk-1 : 0; + for (unsigned screen = 0; screen < m_renderer[desk].size(); ++screen) + { + unsigned eScreen = screen>1 ? screen-2 : 0; + m_renderer[desk][screen]->load( eDesk, eScreen, (screen>0), useDefaults ); + } + } + + m_copyAllDesktops = true; + m_copyAllScreens = true; + + // Random or InOrder + m_slideShowRandom = eRenderer()->multiWallpaperMode(); + if (m_slideShowRandom == KBackgroundSettings::NoMultiRandom) + m_slideShowRandom = KBackgroundSettings::Random; + if (m_slideShowRandom == KBackgroundSettings::NoMulti) + m_slideShowRandom = KBackgroundSettings::InOrder; + + // Wallpaper Position + m_wallpaperPos = eRenderer()->wallpaperMode(); + if (m_wallpaperPos == KBackgroundSettings::NoWallpaper) + m_wallpaperPos = KBackgroundSettings::Centred; // Default + + updateUI(); + emit changed(useDefaults); +} + +void BGDialog::save() +{ + m_pGlobals->writeSettings(); + + // write out the common desktop or the "Desktop 1" settings + // depending on which are the real settings + // they both share Desktop[0] in the config file + // similar for screen... + + for (unsigned desk = 0; desk < m_renderer.size(); ++desk) + { + if (desk == 0 && !m_pGlobals->commonDeskBackground()) + continue; + + if (desk == 1 && m_pGlobals->commonDeskBackground()) + continue; + + for (unsigned screen = 0; screen < m_renderer[desk].size(); ++screen) + { + if (screen == 1 && !m_pGlobals->commonScreenBackground()) + continue; + + if (screen == 2 && m_pGlobals->commonScreenBackground()) + continue; + + m_renderer[desk][screen]->writeSettings(); + } + } + + emit changed(false); +} + +void BGDialog::defaults() +{ + load( true ); + eRenderer()->setWallpaper( eRenderer()->wallpaper() ); +} + +TQString BGDialog::quickHelp() const +{ + return i18n("<h1>Background</h1> This module allows you to control the" + " appearance of the virtual desktops. TDE offers a variety of options" + " for customization, including the ability to specify different settings" + " for each virtual desktop, or a common background for all of them.<p>" + " The appearance of the desktop results from the combination of its" + " background colors and patterns, and optionally, wallpaper, which is" + " based on the image from a graphic file.<p>" + " The background can be made up of a single color, or a pair of colors" + " which can be blended in a variety of patterns. Wallpaper is also" + " customizable, with options for tiling and stretching images. The" + " wallpaper can be overlaid opaquely, or blended in different ways with" + " the background colors and patterns.<p>" + " TDE allows you to have the wallpaper change automatically at specified" + " intervals of time. You can also replace the background with a program" + " that updates the desktop dynamically. For example, the \"kworldclock\"" + " program shows a day/night map of the world which is updated periodically."); +} + +void BGDialog::slotIdentifyScreens() +{ + // Taken from PositionTab::showIdentify in tdebase/kcontrol/kicker/positiontab_impl.cpp + for(unsigned s = 0; s < m_numScreens; s++) + { + TQLabel *screenLabel = new TQLabel(0,"Screen Identify", (WFlags)(WDestructiveClose | WStyle_Customize | WX11BypassWM)); + + TQFont identifyFont(TDEGlobalSettings::generalFont()); + identifyFont.setPixelSize(100); + screenLabel->setFont(identifyFont); + + screenLabel->setFrameStyle(TQFrame::Panel); + screenLabel->setFrameShadow(TQFrame::Plain); + + screenLabel->setAlignment(Qt::AlignCenter); + screenLabel->setNum(int(s + 1)); + // BUGLET: we should not allow the identification to be entered again + // until the timer fires. + TQTimer::singleShot(1500, screenLabel, TQT_SLOT(close())); + + TQPoint screenCenter(TQApplication::desktop()->screenGeometry(s).center()); + TQRect targetGeometry(TQPoint(0,0),screenLabel->sizeHint()); + targetGeometry.moveCenter(screenCenter); + + screenLabel->setGeometry(targetGeometry); + + screenLabel->show(); + } +} + +void BGDialog::initUI() +{ + // Desktop names + if (m_useViewports == false) { + for (unsigned i = 0; i < m_numDesks; ++i) { + m_comboDesktop->insertItem(m_pGlobals->deskName(i)); + } + } + else { + for (unsigned i = 0; i < (m_numDesks/m_numViewports); ++i) { + for (unsigned j = 0; j < m_numViewports; ++j) { + m_comboDesktop->insertItem(i18n("Desktop %1 Viewport %2").arg(i+1).arg(j+1)); + } + } + } + + // Screens + for (unsigned i = 0; i < m_numScreens; ++i) + m_comboScreen->insertItem( i18n("Screen %1").arg(TQString::number(i+1)) ); + + // Patterns + m_comboPattern->insertItem(i18n("Single Color")); + m_comboPattern->insertItem(i18n("Horizontal Gradient")); + m_comboPattern->insertItem(i18n("Vertical Gradient")); + m_comboPattern->insertItem(i18n("Pyramid Gradient")); + m_comboPattern->insertItem(i18n("Pipecross Gradient")); + m_comboPattern->insertItem(i18n("Elliptic Gradient")); + + m_patterns = KBackgroundPattern::list(); + m_patterns.sort(); // Defined order + TQStringList::Iterator it; + for (it=m_patterns.begin(); it != m_patterns.end(); ++it) + { + KBackgroundPattern pat(*it); + if (pat.isAvailable()) + m_comboPattern->insertItem(pat.comment()); + } + + loadWallpaperFilesList(); + + // Wallpaper tilings: again they must match the ones from bgrender.cc + m_comboWallpaperPos->insertItem(i18n("Centered")); + m_comboWallpaperPos->insertItem(i18n("Tiled")); + m_comboWallpaperPos->insertItem(i18n("Center Tiled")); + m_comboWallpaperPos->insertItem(i18n("Centered Maxpect")); + m_comboWallpaperPos->insertItem(i18n("Tiled Maxpect")); + m_comboWallpaperPos->insertItem(i18n("Scaled")); + m_comboWallpaperPos->insertItem(i18n("Centered Auto Fit")); + m_comboWallpaperPos->insertItem(i18n("Scale & Crop")); + + // Blend modes: make sure these match with kdesktop/bgrender.cc !! + m_comboBlend->insertItem(i18n("No Blending")); + m_comboBlend->insertItem(i18n("Flat")); + m_comboBlend->insertItem(i18n("Horizontal")); + m_comboBlend->insertItem(i18n("Vertical")); + m_comboBlend->insertItem(i18n("Pyramid")); + m_comboBlend->insertItem(i18n("Pipecross")); + m_comboBlend->insertItem(i18n("Elliptic")); + m_comboBlend->insertItem(i18n("Intensity")); + m_comboBlend->insertItem(i18n("Saturation")); + m_comboBlend->insertItem(i18n("Contrast")); + m_comboBlend->insertItem(i18n("Hue Shift")); +} + +void BGDialog::loadWallpaperFilesList() { + + // Wallpapers + // the following TQMap is lower cased names mapped to cased names and URLs + // this way we get case insensitive sorting + TQMap<TQString, QPair<TQString, TQString> > papers; + + //search for .desktop files before searching for images without .desktop files + TQStringList lst = m_pDirs->findAllResources("wallpaper", "*desktop", false, true); + TQStringList files; + TQStringList hiddenfiles; + for (TQStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) + { + KSimpleConfig fileConfig(*it); + fileConfig.setGroup("Wallpaper"); + + int slash = (*it).findRev('/') + 1; + TQString directory = (*it).left(slash); + + TQString imageCaption = fileConfig.readEntry("Name"); + TQString fileName = fileConfig.readEntry("File"); + + if (fileConfig.readBoolEntry("Hidden",false)) { + hiddenfiles.append(directory + fileName); + continue; + } + + if (imageCaption.isEmpty()) + { + imageCaption = fileName; + imageCaption.replace('_', ' '); + imageCaption = KStringHandler::capwords(imageCaption); + } + + // avoid name collisions + TQString rs = imageCaption; + TQString lrs = rs.lower(); + for (int n = 1; papers.find(lrs) != papers.end(); ++n) + { + rs = imageCaption + " (" + TQString::number(n) + ')'; + lrs = rs.lower(); + } + bool canLoadScaleable = false; + +#ifdef HAVE_LIBART + canLoadScaleable = true; +#endif + if ( fileConfig.readEntry("ImageType") == "pixmap" || canLoadScaleable ) { + papers[lrs] = qMakePair(rs, directory + fileName); + files.append(directory + fileName); + } + } + + //now find any wallpapers that don't have a .desktop file + lst = m_pDirs->findAllResources("wallpaper", "*", false, true); + for (TQStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) + { + if ( !(*it).endsWith(".desktop") && files.grep(*it).empty() && hiddenfiles.grep(*it).empty() ) { + // First try to see if we have a comment describing the image. If we do + // just use the first line of said comment. + KFileMetaInfo metaInfo(*it); + TQString imageCaption; + + if (metaInfo.isValid() && metaInfo.item("Comment").isValid()) + imageCaption = metaInfo.item("Comment").string().section('\n', 0, 0); + + if (imageCaption.isEmpty()) + { + int slash = (*it).findRev('/') + 1; + int endDot = (*it).findRev('.'); + + // strip the extension if it exists + if (endDot != -1 && endDot > slash) + imageCaption = (*it).mid(slash, endDot - slash); + else + imageCaption = (*it).mid(slash); + + imageCaption.replace('_', ' '); + imageCaption = KStringHandler::capwords(imageCaption); + } + + // avoid name collisions + TQString rs = imageCaption; + TQString lrs = rs.lower(); + for (int n = 1; papers.find(lrs) != papers.end(); ++n) + { + rs = imageCaption + " (" + TQString::number(n) + ')'; + lrs = rs.lower(); + } + papers[lrs] = qMakePair(rs, *it); + } + } + + KComboBox *comboWallpaper = m_urlWallpaperBox; + comboWallpaper->clear(); + m_wallpaper.clear(); + int i = 0; + for (TQMap<TQString, QPair<TQString, TQString> >::Iterator it = papers.begin(); + it != papers.end(); + ++it) + { + comboWallpaper->insertItem(it.data().first); + m_wallpaper[it.data().second] = i; + i++; + } +} + +void BGDialog::setWallpaper(const TQString &s) +{ + KComboBox *comboWallpaper = m_urlWallpaperBox; + comboWallpaper->blockSignals(true); + + if (m_wallpaper.find(s) == m_wallpaper.end()) + { + int i = comboWallpaper->count(); + TQString imageCaption; + int slash = s.findRev('/') + 1; + int endDot = s.findRev('.'); + + // strip the extension if it exists + if (endDot != -1 && endDot > slash) + imageCaption = s.mid(slash, endDot - slash); + else + imageCaption = s.mid(slash); + if (comboWallpaper->text(i-1) == imageCaption) + { + i--; + comboWallpaper->removeItem(i); + } + comboWallpaper->insertItem(imageCaption); + m_wallpaper[s] = i; + comboWallpaper->setCurrentItem(i); + } + else + { + comboWallpaper->setCurrentItem(m_wallpaper[s]); + } + comboWallpaper->blockSignals(false); +} + +void BGDialog::slotWallpaperSelection() +{ + KFileDialog dlg( TQString::null, TQString::null, this, + "file dialog", true ); + + KImageFilePreview* previewWidget = new KImageFilePreview(&dlg); + dlg.setPreviewWidget(previewWidget); + + TQStringList mimeTypes = KImageIO::mimeTypes( KImageIO::Reading ); +#ifdef HAVE_LIBART + mimeTypes += "image/svg+xml"; +#endif + dlg.setFilter( mimeTypes.join( " " ) ); + dlg.setMode( KFile::File | KFile::ExistingOnly | KFile::LocalOnly ); + dlg.setCaption( i18n("Select Wallpaper") ); + + int j = m_urlWallpaperBox->currentItem(); + TQString uri; + for(TQMap<TQString,int>::ConstIterator it = m_wallpaper.begin(); + it != m_wallpaper.end(); + ++it) + { + if (it.data() == j) + { + uri = it.key(); + break; + } + } + + if ( !uri.isEmpty() ) { + dlg.setSelection( uri ); + } + + if ( dlg.exec() == TQDialog::Accepted ) + { + setWallpaper(dlg.selectedFile()); + + int optionID = m_buttonGroupBackground->id(m_radioPicture); + m_buttonGroupBackground->setButton( optionID ); + slotWallpaperTypeChanged( optionID ); + + emit changed(true); + } +} + +void BGDialog::updateUI() +{ + KBackgroundRenderer *r = eRenderer(); + m_comboDesktop->setCurrentItem(m_eDesk); + m_comboScreen->setCurrentItem(m_eScreen); + + m_colorPrimary->setColor(r->colorA()); + m_colorSecondary->setColor(r->colorB()); + + int wallpaperMode = r->wallpaperMode(); + int multiMode = r->multiWallpaperMode(); + + if (r->backgroundMode() == KBackgroundSettings::Program && + wallpaperMode == KBackgroundSettings::NoWallpaper) + groupBox3->setEnabled( false ); + else + groupBox3->setEnabled( true ); + + if ((multiMode == KBackgroundSettings::NoMultiRandom) || + (multiMode == KBackgroundSettings::NoMulti)) + { + // No wallpaper + if (wallpaperMode == KBackgroundSettings::NoWallpaper ) + { + m_urlWallpaperBox->setEnabled(false); + m_urlWallpaperButton->setEnabled(false); + m_buttonSetupWallpapers->setEnabled(false); + m_comboWallpaperPos->setEnabled(false); + m_lblWallpaperPos->setEnabled(false); + m_buttonGroupBackground->setButton( + m_buttonGroupBackground->id(m_radioNoPicture) ); + } + + // 1 Picture + else + { + m_urlWallpaperBox->setEnabled(true); + m_urlWallpaperButton->setEnabled(true); + m_buttonSetupWallpapers->setEnabled(false); + m_comboWallpaperPos->setEnabled(true); + m_lblWallpaperPos->setEnabled(true); + setWallpaper(r->wallpaper()); + m_buttonGroupBackground->setButton( + m_buttonGroupBackground->id(m_radioPicture) ); + } + } + + // Slide show + else + { + m_urlWallpaperBox->setEnabled(false); + m_urlWallpaperButton->setEnabled(false); + m_buttonSetupWallpapers->setEnabled(true); + m_comboWallpaperPos->setEnabled(true); + m_lblWallpaperPos->setEnabled(true); + m_buttonGroupBackground->setButton( + m_buttonGroupBackground->id(m_radioSlideShow) ); + } + + m_comboWallpaperPos->setCurrentItem(r->wallpaperMode()-1); + + bool bSecondaryEnabled = true; + m_comboPattern->blockSignals(true); + switch (r->backgroundMode()) { + case KBackgroundSettings::Flat: + m_comboPattern->setCurrentItem(0); + bSecondaryEnabled = false; + break; + + case KBackgroundSettings::Pattern: + { + int i = m_patterns.findIndex(r->KBackgroundPattern::name()); + if (i >= 0) + m_comboPattern->setCurrentItem(NR_PREDEF_PATTERNS+i); + else + m_comboPattern->setCurrentItem(0); + } + break; + + case KBackgroundSettings::Program: + m_comboPattern->setCurrentItem(0); + bSecondaryEnabled = false; + break; + + default: // Gradient + m_comboPattern->setCurrentItem( + 1 + r->backgroundMode() - KBackgroundSettings::HorizontalGradient); + break; + } + m_comboPattern->blockSignals(false); + + m_colorSecondary->setEnabled(bSecondaryEnabled); + + int mode = r->blendMode(); + + m_comboBlend->blockSignals(true); + m_sliderBlend->blockSignals(true); + + m_comboBlend->setCurrentItem(mode); + m_cbBlendReverse->setChecked(r->reverseBlending()); + m_sliderBlend->setValue( r->blendBalance() / 10 ); + + m_cbCrossFadeBg->setChecked(r->crossFadeBg()); + + m_comboBlend->blockSignals(false); + m_sliderBlend->blockSignals(false); + + // turn it off if there is no background picture set! + setBlendingEnabled(wallpaperMode != KBackgroundSettings::NoWallpaper); + + // Start preview renderer(s) + if ( m_eScreen == 0 ) + { + r->setPreview( m_pMonitorArrangement->combinedPreviewSize() ); + r->start(true); + } + else if ( m_eScreen == 1 ) + { + r->setPreview( m_pMonitorArrangement->maxPreviewSize() ); + r->start(true); + } + else + { + for (unsigned j = 0; j < m_numScreens; ++j) + { + m_renderer[m_eDesk][j+2]->stop(); + m_renderer[m_eDesk][j+2]->setPreview( m_pMonitorArrangement->monitor(j)->size() ); + m_renderer[m_eDesk][j+2]->start(true); + } + } +} + +void BGDialog::slotPreviewDone(int desk_done, int screen_done) +{ + int currentDesk = (m_eDesk > 0) ? m_eDesk-1 : 0; + + if ( desk_done != currentDesk ) + return; + + if (!m_previewUpdates) + return; + + KBackgroundRenderer * r = m_renderer[m_eDesk][(m_eScreen>1) ? (screen_done+2) : m_eScreen]; + + if (r->image().isNull()) + return; + + r->saveCacheFile(); + + KPixmap pm; + if (TQPixmap::defaultDepth() < 15) + pm.convertFromImage(r->image(), KPixmap::LowColor); + else + pm.convertFromImage(r->image()); + + if ( m_eScreen == 0 ) + { + m_pMonitorArrangement->setPixmap(pm); + } + else if ( m_eScreen == 1 ) + { + for (unsigned i = 0; i < m_pMonitorArrangement->numMonitors(); ++i) + m_pMonitorArrangement->monitor(i)->setPixmap(pm); + } + else + { + m_pMonitorArrangement->monitor(screen_done)->setPixmap(pm); + } +} + +void BGDialog::slotImageDropped(const TQString &uri) +{ + setWallpaper(uri); + + int optionID = m_buttonGroupBackground->id(m_radioPicture); + m_buttonGroupBackground->setButton( optionID ); + slotWallpaperTypeChanged( optionID ); +} + +void BGDialog::slotWallpaperTypeChanged(int i) +{ + KBackgroundRenderer *r = eRenderer(); + r->stop(); + + // No picture + if (i == m_buttonGroupBackground->id(m_radioNoPicture)) //None + { + m_urlWallpaperBox->setEnabled(false); + m_urlWallpaperButton->setEnabled(false); + m_buttonSetupWallpapers->setEnabled(false); + m_comboWallpaperPos->setEnabled(false); + m_lblWallpaperPos->setEnabled(false); + r->setWallpaperMode(KBackgroundSettings::NoWallpaper); + + if (m_slideShowRandom == KBackgroundSettings::InOrder) + r->setMultiWallpaperMode(KBackgroundSettings::NoMulti); + else + r->setMultiWallpaperMode(KBackgroundSettings::NoMultiRandom); + + setBlendingEnabled(false); + } + + // Slide show + else if (i == m_buttonGroupBackground->id(m_radioSlideShow)) + { + m_urlWallpaperBox->setEnabled(false); + m_urlWallpaperButton->setEnabled(false); + m_buttonSetupWallpapers->setEnabled(true); + m_comboWallpaperPos->setEnabled(true); + m_lblWallpaperPos->setEnabled(true); + setBlendingEnabled(true); + + m_comboWallpaperPos->blockSignals(true); + m_comboWallpaperPos->setCurrentItem(m_wallpaperPos-1); + m_comboWallpaperPos->blockSignals(false); + + if (r->wallpaperList().count() == 0) + r->setWallpaperMode( KBackgroundSettings::NoWallpaper ); + else + r->setWallpaperMode(m_wallpaperPos); + + r->setMultiWallpaperMode(m_slideShowRandom); + setWallpaper(r->wallpaper()); + setBlendingEnabled(true); + } + + // 1 Picture + else if (i == m_buttonGroupBackground->id(m_radioPicture)) + { + m_urlWallpaperBox->setEnabled(true); + m_urlWallpaperButton->setEnabled(true); + m_buttonSetupWallpapers->setEnabled(false); + m_lblWallpaperPos->setEnabled(true); + m_comboWallpaperPos->setEnabled(true); + setBlendingEnabled(true); + + if (m_slideShowRandom == KBackgroundSettings::InOrder) + r->setMultiWallpaperMode(KBackgroundSettings::NoMulti); + else + r->setMultiWallpaperMode(KBackgroundSettings::NoMultiRandom); + + int j = m_urlWallpaperBox->currentItem(); + TQString path; + for(TQMap<TQString,int>::ConstIterator it = m_wallpaper.begin(); + it != m_wallpaper.end(); + ++it) + { + if (it.data() == j) + { + path = it.key(); + break; + } + } + + KFileMetaInfo metaInfo(path); + if (metaInfo.isValid() && metaInfo.item("Dimensions").isValid()) + { + // If the image is greater than 800x600 default to using scaled mode, + // otherwise default to tiled. + + TQSize s = metaInfo.item("Dimensions").value().toSize(); + if (s.width() >= 800 && s.height() >= 600) + m_wallpaperPos = KBackgroundSettings::Scaled; + else + m_wallpaperPos = KBackgroundSettings::Tiled; + } + else if (KMimeType::findByPath(path)->is("image/svg+xml")) + { + m_wallpaperPos = KBackgroundSettings::Scaled; + } + + r->setWallpaperMode(m_wallpaperPos); + m_comboWallpaperPos->blockSignals(true); + m_comboWallpaperPos->setCurrentItem(m_wallpaperPos-1); + m_comboWallpaperPos->blockSignals(false); + + r->setWallpaper(path); + } + + r->start(true); + m_copyAllDesktops = true; + m_copyAllScreens = true; + emit changed(true); +} + +void BGDialog::slotWallpaper(int) +{ + slotWallpaperTypeChanged(m_buttonGroupBackground->id(m_radioPicture)); + emit changed(true); +} + +void BGDialog::setBlendingEnabled(bool enable) +{ + int mode = eRenderer()->blendMode(); + + bool b = !(mode == KBackgroundSettings::NoBlending); + m_lblBlending->setEnabled(enable); + m_comboBlend->setEnabled(enable); + m_lblBlendBalance->setEnabled(enable && b); + m_sliderBlend->setEnabled(enable && b); + + b = !(mode < KBackgroundSettings::IntensityBlending); + m_cbBlendReverse->setEnabled(enable && b); +} + +void BGDialog::slotWallpaperPos(int mode) +{ + KBackgroundRenderer *r = eRenderer(); + + mode++; + m_wallpaperPos = mode; + + if (mode == r->wallpaperMode()) + return; + + r->stop(); + r->setWallpaperMode(mode); + r->start(true); + m_copyAllDesktops = true; + m_copyAllScreens = true; + emit changed(true); +} + +void BGDialog::slotSetupMulti() +{ + KBackgroundRenderer *r = eRenderer(); + + BGMultiWallpaperDialog dlg(r, topLevelWidget()); + if (dlg.exec() == TQDialog::Accepted) { + r->stop(); + m_slideShowRandom = r->multiWallpaperMode(); + r->setWallpaperMode(m_wallpaperPos); + r->start(true); + m_copyAllDesktops = true; + m_copyAllScreens = true; + emit changed(true); + } +} + +void BGDialog::slotPrimaryColor(const TQColor &color) +{ + KBackgroundRenderer *r = eRenderer(); + + if (color == r->colorA()) + return; + + r->stop(); + r->setColorA(color); + r->start(true); + m_copyAllDesktops = true; + m_copyAllScreens = true; + emit changed(true); +} + +void BGDialog::slotSecondaryColor(const TQColor &color) +{ + KBackgroundRenderer *r = eRenderer(); + + if (color == r->colorB()) + return; + + r->stop(); + r->setColorB(color); + r->start(true); + m_copyAllDesktops = true; + m_copyAllScreens = true; + emit changed(true); +} + +void BGDialog::slotPattern(int pattern) +{ + KBackgroundRenderer *r = eRenderer(); + r->stop(); + bool bSecondaryEnabled = true; + if (pattern < NR_PREDEF_PATTERNS) + { + if (pattern == 0) + { + r->setBackgroundMode(KBackgroundSettings::Flat); + bSecondaryEnabled = false; + } + else + { + r->setBackgroundMode(pattern - 1 + KBackgroundSettings::HorizontalGradient); + } + } + else + { + r->setBackgroundMode(KBackgroundSettings::Pattern); + r->setPatternName(m_patterns[pattern - NR_PREDEF_PATTERNS]); + } + r->start(true); + m_colorSecondary->setEnabled(bSecondaryEnabled); + + m_copyAllDesktops = true; + m_copyAllScreens = true; + emit changed(true); +} + +void BGDialog::slotSelectScreen(int screen) +{ + // Copy the settings from "All screens" to all the other screens + // at a suitable point + if (m_pGlobals->commonScreenBackground() && (screen >1) && m_copyAllScreens) + { + // Copy stuff + for (unsigned desk = 0; desk < m_numDesks+1; ++desk ) + { + KBackgroundRenderer *master = m_renderer[desk][1]; + for (unsigned screen = 0; screen < m_numScreens; ++screen) + { + m_renderer[desk][screen+2]->copyConfig(master); + } + } + } + + if (screen == m_eScreen ) + { + return; // Nothing to do + } + + m_copyAllScreens = false; + + bool drawBackgroundPerScreen = screen > 0; + bool commonScreenBackground = screen < 2; + + // Update drawBackgroundPerScreen + if (m_eDesk == 0) + { + for (unsigned desk = 0; desk < m_numDesks; ++desk ) + m_pGlobals->setDrawBackgroundPerScreen(desk, drawBackgroundPerScreen); + } + else + { + m_pGlobals->setDrawBackgroundPerScreen(m_eDesk-1, drawBackgroundPerScreen); + } + + m_pGlobals->setCommonScreenBackground(commonScreenBackground); + + if (screen < 2) + emit changed(true); + else + { + for (unsigned i = 0; i < m_renderer[m_eDesk].size(); ++i) + { + if ( m_renderer[m_eDesk][i]->isActive() ) + m_renderer[m_eDesk][i]->stop(); + } + } + + m_eScreen = screen; + updateUI(); +} + +void BGDialog::slotSelectDesk(int desk) +{ + // Copy the settings from "All desktops" to all the other desktops + // at a suitable point. + if (m_pGlobals->commonDeskBackground() && (desk > 0) && m_copyAllDesktops) + { + // Copy stuff + for (unsigned screen = 0; screen < m_renderer[0].size(); ++screen ) + { + KBackgroundRenderer *master = m_renderer[0][screen]; + for (unsigned desk = 0; desk < m_numDesks; ++desk ) + { + m_renderer[desk+1][screen]->copyConfig(master); + } + } + } + + if (desk == m_eDesk) + { + return; // Nothing to do + } + + m_copyAllDesktops = false; + if (desk == 0) + { + if (m_pGlobals->commonDeskBackground()) + return; // Nothing to do + + m_pGlobals->setCommonDeskBackground(true); + emit changed(true); + } + else + { + for (unsigned i = 0; i < m_renderer[m_eDesk].size(); ++i) + { + if ( m_renderer[m_eDesk][i]->isActive() ) + m_renderer[m_eDesk][i]->stop(); + } + m_pGlobals->setCommonDeskBackground(false); + } + + m_eDesk = desk; + getEScreen(); + updateUI(); +} + +void BGDialog::slotAdvanced() +{ + KBackgroundRenderer *r = eRenderer(); + + m_previewUpdates = false; + BGAdvancedDialog dlg(r, topLevelWidget(), m_multidesktop); + + if (!m_pMonitorArrangement->isEnabled()) { + dlg.makeReadOnly(); + dlg.exec(); + return; + } + + dlg.setTextColor(m_pGlobals->textColor()); + dlg.setTextBackgroundColor(m_pGlobals->textBackgroundColor()); + dlg.setShadowEnabled(m_pGlobals->shadowEnabled()); + dlg.setTextLines(m_pGlobals->textLines()); + dlg.setTextWidth(m_pGlobals->textWidth()); + + if (m_pGlobals->limitCache()) + dlg.setCacheSize( m_pGlobals->cacheSize() ); + else + dlg.setCacheSize( 0 ); + + if( !dlg.exec()) + { + m_previewUpdates = true; + return; + } + + r->setBackgroundMode(dlg.backgroundMode()); + if (dlg.backgroundMode() == KBackgroundSettings::Program) + { + r->setProgram(dlg.backgroundProgram()); + } + + int cacheSize = dlg.cacheSize(); + if (cacheSize) + { + m_pGlobals->setCacheSize(cacheSize); + m_pGlobals->setLimitCache(true); + } + else + { + m_pGlobals->setLimitCache(false); + } + + m_pGlobals->setTextColor(dlg.textColor()); + m_pGlobals->setTextBackgroundColor(dlg.textBackgroundColor()); + m_pGlobals->setShadowEnabled(dlg.shadowEnabled()); + m_pGlobals->setTextLines(dlg.textLines()); + m_pGlobals->setTextWidth(dlg.textWidth()); + + r->stop(); + m_previewUpdates = true; + r->start(true); + + updateUI(); + m_copyAllDesktops = true; + emit changed(true); +} + +void BGDialog::slotGetNewStuff() +{ + //FIXME set this to a server when we get one + //should really be in a .rc file but could be either + //tdecmshellrc or kcontrolrc + TDEConfig* config = TDEGlobal::config(); + config->setGroup("TDENewStuff"); + config->writeEntry( "ProvidersUrl", "https://www.trinitydesktop.org/ocs/providers.xml" ); + config->writeEntry( "StandardResource", "wallpaper" ); + config->sync(); + + KNS::DownloadDialog::open("wallpaper", i18n("Get New Wallpapers")); + loadWallpaperFilesList(); +} + +void BGDialog::slotBlendMode(int mode) +{ + if (mode == eRenderer()->blendMode()) + return; + + bool b = !(mode == KBackgroundSettings::NoBlending); + m_sliderBlend->setEnabled( b ); + m_lblBlendBalance->setEnabled( b ); + + b = !(mode < KBackgroundSettings::IntensityBlending); + m_cbBlendReverse->setEnabled(b); + emit changed(true); + + eRenderer()->stop(); + eRenderer()->setBlendMode(mode); + eRenderer()->start(true); +} + +void BGDialog::slotBlendBalance(int value) +{ + value = value*10; + if (value == eRenderer()->blendBalance()) + return; + emit changed(true); + + eRenderer()->stop(); + eRenderer()->setBlendBalance(value); + eRenderer()->start(true); +} + +void BGDialog::slotBlendReverse(bool b) +{ + if (b == eRenderer()->reverseBlending()) + return; + emit changed(true); + + eRenderer()->stop(); + eRenderer()->setReverseBlending(b); + eRenderer()->start(true); +} + +void BGDialog::slotCrossFadeBg(bool b) +{ + if (b == eRenderer()->crossFadeBg()) + return; + emit changed(true); + + eRenderer()->stop(); + eRenderer()->setCrossFadeBg(b); + eRenderer()->start(true); +} + +void BGDialog::desktopResized() +{ + for (unsigned i = 0; i < m_renderer.size(); ++i) + { + for (unsigned j = 0; j < m_renderer[i].size(); ++j ) + { + KBackgroundRenderer * r = m_renderer[i][j]; + if( r->isActive()) + r->stop(); + r->desktopResized(); + } + } + eRenderer()->start(true); +} + + +#include "bgdialog.moc" diff --git a/kcontrol/background/bgdialog.h b/kcontrol/background/bgdialog.h new file mode 100644 index 000000000..6b33d8999 --- /dev/null +++ b/kcontrol/background/bgdialog.h @@ -0,0 +1,112 @@ +/* + This file is part of the KDE libraries + Copyright (c) 2003 Waldo Bastian <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 _BGDIALOG_H_ +#define _BGDIALOG_H_ + +#include <tqptrvector.h> +#include <tqmap.h> +#include <tqvaluevector.h> + +#include "bgdialog_ui.h" +#include "bgrender.h" +#include "bgsettings.h" +#include "bgdefaults.h" + +class BGMonitorArrangement; +class TDEStandardDirs; + +class BGDialog : public BGDialog_UI +{ + Q_OBJECT +public: + BGDialog(TQWidget* parent, TDEConfig* _config, bool _multidesktop = true); + ~BGDialog(); + + void load( bool useDefaults ); + void save(); + void defaults(); + + void makeReadOnly(); + + TQString quickHelp() const; + +signals: + void changed(bool); + +protected: + void initUI(); + void updateUI(); + KBackgroundRenderer * eRenderer(); + + void setWallpaper(const TQString &); + + void loadWallpaperFilesList(); + +protected slots: + void slotIdentifyScreens(); + void slotSelectScreen(int screen); + void slotSelectDesk(int desk); + void slotWallpaperTypeChanged(int i); + void slotWallpaper(int i); + void slotWallpaperPos(int); + void slotWallpaperSelection(); + void slotSetupMulti(); + void slotPrimaryColor(const TQColor &color); + void slotSecondaryColor(const TQColor &color); + void slotPattern(int pattern); + void slotImageDropped(const TQString &uri); + void slotPreviewDone(int desk, int screen); + void slotAdvanced(); + void slotGetNewStuff(); + void slotBlendMode(int mode); + void slotBlendBalance(int value); + void slotBlendReverse(bool b); + void desktopResized(); + void setBlendingEnabled(bool); + void slotCrossFadeBg(bool); + +protected: + void getEScreen(); + TDEGlobalBackgroundSettings *m_pGlobals; + TDEStandardDirs *m_pDirs; + bool m_multidesktop; + bool m_useViewports; + int m_curDesk; + unsigned m_numDesks; + unsigned m_numViewports; + unsigned m_numScreens; + int m_desk; + int m_screen; + int m_eDesk; + int m_eScreen; + TQValueVector< TQPtrVector<KBackgroundRenderer> > m_renderer; // m_renderer[desk][screen] + TQMap<TQString,int> m_wallpaper; + TQStringList m_patterns; + int m_slideShowRandom; // Remembers last Slide Show setting + int m_wallpaperPos; // Remembers last wallpaper pos + + BGMonitorArrangement * m_pMonitorArrangement; + + bool m_previewUpdates; + bool m_copyAllDesktops; + bool m_copyAllScreens; +}; + +#endif diff --git a/kcontrol/background/bgdialog_ui.ui b/kcontrol/background/bgdialog_ui.ui new file mode 100644 index 000000000..f35e19f78 --- /dev/null +++ b/kcontrol/background/bgdialog_ui.ui @@ -0,0 +1,733 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>BGDialog_UI</class> +<widget class="TQWidget"> + <property name="name"> + <cstring>BGDialog_UI</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>603</width> + <height>433</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>1</number> + </property> + + <widget class="TQLabel" row="0" column="0"> + <property name="name"> + <cstring>m_pDesktopLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Setting for &desktop:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_comboDesktop</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>Choose the desktop you wish to configure the background for from this list. If you want the same background settings to be applied to all desktops select the "All Desktops" option.</string> + </property> + </widget> + <widget class="KComboBox" row="0" column="1"> + <item> + <property name="text"> + <string>All Desktops</string> + </property> + </item> + <property name="name"> + <cstring>m_comboDesktop</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="whatsThis" stdset="0"> + <string>Choose the desktop you wish to configure the background for from this list. If you want the same background settings to be applied to all desktops select the "All Desktops" option.</string> + </property> + </widget> + <widget class="KComboBox" row="0" column="2"> + <item> + <property name="text"> + <string>Across All Screens</string> + </property> + </item> + <item> + <property name="text"> + <string>On Each Screen</string> + </property> + </item> + <property name="name"> + <cstring>m_comboScreen</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="whatsThis" stdset="0"> + <string>Choose the screen you wish to configure the background for from this list.</string> + </property> + </widget> + <spacer row="0" column="3" rowspan="1" colspan="2"> + <property name="name"> + <cstring>Spacer37</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + </spacer> + <widget class="TQLayoutWidget" row="1" column="4" rowspan="2" colspan="1"> + <property name="name"> + <cstring>layout36</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQWidget"> + <property name="name"> + <cstring>m_screenArrangement</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + </widget> + <widget class="TQLayoutWidget"> + <property name="name"> + <cstring>layout35</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer800</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Minimum</enum> + </property> + <property name="sizeHint"> + <size> + <width>4</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="TQPushButton"> + <property name="name"> + <cstring>m_buttonIdentifyScreens</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Identify Screens</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Click this button to show the identifying number for each screen.</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer810</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Minimum</enum> + </property> + <property name="sizeHint"> + <size> + <width>4</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer80</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Minimum</enum> + </property> + <property name="sizeHint"> + <size> + <width>4</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="TQPushButton"> + <property name="name"> + <cstring>m_buttonAdvanced</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Advanced Options</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Click this button to set the icon text colors and shadow, set up a program to run for the background picture or control the size of the background cache.</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer81</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Minimum</enum> + </property> + <property name="sizeHint"> + <size> + <width>4</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer80</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Minimum</enum> + </property> + <property name="sizeHint"> + <size> + <width>4</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="TQPushButton"> + <property name="name"> + <cstring>m_buttonGetNew</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Get New Wallpapers</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Click this button to give you a list of new wallpapers to download from the Internet.</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer81</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Minimum</enum> + </property> + <property name="sizeHint"> + <size> + <width>4</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </vbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer13</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>MinimumExpanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + </vbox> + </widget> + <widget class="TQGroupBox" row="2" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Options</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQLabel" row="0" column="0"> + <property name="name"> + <cstring>m_lblWallpaperPos</cstring> + </property> + <property name="text"> + <string>Posi&tion:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_comboWallpaperPos</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string><qt>You can choose here how a background picture is shown on the desktop: +<ul> +<li><em>Centered:</em> Center the picture on the desktop.</li> + <li><em>Tiled:</em> Tile the picture beginning at the top left of the desktop, so the desktop is totally covered up.</li> +<li><em>Center Tiled:</em> Center the picture on the desktop and then tile around it so that the background is totally covered up.</li> +<li><em>Centered Maxpect:</em> Magnify the picture without distorting it until it fills either the width or height of the desktop, and then center it on the desktop.</li> +<li><em>Scaled:</em> Magnify the picture, until the entire desktop is covered. This may result in some distortion of the picture.</li> +<li><em>Centered Auto Fit:</em> If the picture fits the desktop this mode works like the Centered option. If the picture is larger than the desktop it is scaled down to fit while keeping the aspect ratio.</li> +<li><em>Scale and Crop:</em> Magnify the picture without distorting it until it fills both the width and height of the desktop (cropping the picture if necessary), and then center it on the desktop.</li> +</ul></qt></string> + </property> + </widget> + <widget class="TQCheckBox" row="8" column="1"> + <property name="name"> + <cstring>m_cbCrossFadeBg</cstring> + </property> + <property name="text"> + <string>Cross-fading background</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Enables a smooth fading effect when changing background image.</string> + </property> + </widget> + <widget class="TQComboBox" row="5" column="1"> + <property name="name"> + <cstring>m_comboBlend</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>If you have selected to use a background picture you can choose various methods of blending the background colors with the picture. The default option of "No Blending" means that the picture simply obscures the background colors below.</string> + </property> + </widget> + <widget class="TQLayoutWidget" row="3" column="1"> + <property name="name"> + <cstring>layout31</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KColorButton"> + <property name="name"> + <cstring>m_colorPrimary</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="whatsThis" stdset="0"> + <string>Click to choose the primary background color.</string> + </property> + </widget> + <widget class="KColorButton"> + <property name="name"> + <cstring>m_colorSecondary</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="whatsThis" stdset="0"> + <string>Click to choose the secondary background color. If no secondary color is required by the pattern selected this button will be disabled.</string> + </property> + </widget> + </hbox> + </widget> + <widget class="TQLabel" row="2" column="0"> + <property name="name"> + <cstring>m_lblColors</cstring> + </property> + <property name="text"> + <string>Co&lors:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_comboPattern</cstring> + </property> + </widget> + <widget class="TQLabel" row="5" column="0"> + <property name="name"> + <cstring>m_lblBlending</cstring> + </property> + <property name="text"> + <string>&Blending:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_comboBlend</cstring> + </property> + </widget> + <widget class="TQLayoutWidget" row="6" column="1"> + <property name="name"> + <cstring>layout23</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQLabel"> + <property name="name"> + <cstring>m_lblBlendBalance</cstring> + </property> + <property name="text"> + <string>Balance:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_sliderBlend</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>You can use this slider to control the degree of blending. You can experiment by moving the slider and looking at the effects in the preview image.</string> + </property> + </widget> + <widget class="TQSlider"> + <property name="name"> + <cstring>m_sliderBlend</cstring> + </property> + <property name="minValue"> + <number>-20</number> + </property> + <property name="maxValue"> + <number>20</number> + </property> + <property name="pageStep"> + <number>1</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="tickmarks"> + <enum>NoMarks</enum> + </property> + <property name="tickInterval"> + <number>10</number> + </property> + <property name="whatsThis" stdset="0"> + <string>You can use this slider to control the degree of blending. You can experiment by moving the slider and looking at the effects in the preview image.</string> + </property> + </widget> + </hbox> + </widget> + <widget class="TQCheckBox" row="7" column="1"> + <property name="name"> + <cstring>m_cbBlendReverse</cstring> + </property> + <property name="text"> + <string>Reverse roles</string> + </property> + <property name="whatsThis" stdset="0"> + <string>For some types of blending, you can reverse the role of the background and the picture by checking this option.</string> + </property> + </widget> + <widget class="TQComboBox" row="2" column="1"> + <property name="name"> + <cstring>m_comboPattern</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <spacer row="1" column="1"> + <property name="name"> + <cstring>spacer6_2_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>120</width> + <height>10</height> + </size> + </property> + </spacer> + <spacer row="4" column="1"> + <property name="name"> + <cstring>spacer6_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>130</width> + <height>10</height> + </size> + </property> + </spacer> + <widget class="TQComboBox" row="0" column="1"> + <property name="name"> + <cstring>m_comboWallpaperPos</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string><qt>You can choose here how a background picture is shown on the desktop: +<ul> +<li><em>Centered:</em> Center the picture on the desktop.</li> + <li><em>Tiled:</em> Tile the picture beginning at the top left of the desktop, so the desktop is totally covered up.</li> +<li><em>Center Tiled:</em> Center the picture on the desktop and then tile around it so that the background is totally covered up.</li> +<li><em>Centered Maxpect:</em> Magnify the picture without distorting it until it fills either the width or height of the desktop, and then center it on the desktop.</li> +<li><em>Scaled:</em> Magnify the picture, until the entire desktop is covered. This may result in some distortion of the picture.</li> +<li><em>Centered Auto Fit:</em> If the picture fits the desktop this mode works like the Centered option. If the picture is larger than the desktop it is scaled down to fit while keeping the aspect ratio.</li> +<li><em>Scale and Crop:</em> Magnify the picture without distorting it until it fills both the width and height of the desktop (cropping the picture if necessary), and then center it on the desktop.</li> +</ul></qt></string> + </property> + </widget> + </grid> + </widget> + <widget class="TQButtonGroup" row="1" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>m_buttonGroupBackground</cstring> + </property> + <property name="title"> + <string>Background</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQRadioButton" row="0" column="0"> + <property name="name"> + <cstring>m_radioNoPicture</cstring> + </property> + <property name="text"> + <string>&No picture</string> + </property> + </widget> + <widget class="TQRadioButton" row="2" column="0"> + <property name="name"> + <cstring>m_radioSlideShow</cstring> + </property> + <property name="text"> + <string>&Slide show:</string> + </property> + </widget> + <widget class="TQRadioButton" row="1" column="0"> + <property name="name"> + <cstring>m_radioPicture</cstring> + </property> + <property name="text"> + <string>&Picture:</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <spacer row="0" column="1" rowspan="1" colspan="3"> + <property name="name"> + <cstring>spacer20</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>260</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="TQPushButton" row="2" column="1"> + <property name="name"> + <cstring>m_buttonSetupWallpapers</cstring> + </property> + <property name="text"> + <string>Set&up...</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Click this button to select a set of images to be used as background pictures. One picture at a time will be shown for a specified amount of time, after which another image from the set will be shown. Images can be shown at random or in the order you specify them.</string> + </property> + </widget> + <spacer row="2" column="2" rowspan="1" colspan="2"> + <property name="name"> + <cstring>spacer19</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>110</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="TQPushButton" row="1" column="3"> + <property name="name"> + <cstring>m_urlWallpaperButton</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KComboBox" row="1" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_urlWallpaperBox</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </grid> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>m_buttonGroupBackground</sender> + <signal>toggled(bool)</signal> + <receiver>groupBox3</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>m_comboScreen</tabstop> + <tabstop>m_comboDesktop</tabstop> + <tabstop>m_radioPicture</tabstop> + <tabstop>m_urlWallpaperBox</tabstop> + <tabstop>m_urlWallpaperButton</tabstop> + <tabstop>m_buttonSetupWallpapers</tabstop> + <tabstop>m_comboWallpaperPos</tabstop> + <tabstop>m_comboPattern</tabstop> + <tabstop>m_colorPrimary</tabstop> + <tabstop>m_colorSecondary</tabstop> + <tabstop>m_comboBlend</tabstop> + <tabstop>m_sliderBlend</tabstop> + <tabstop>m_cbBlendReverse</tabstop> + <tabstop>m_buttonAdvanced</tabstop> +</tabstops> +<includes> + <include location="global" impldecl="in declaration">kcolorbutton.h</include> + <include location="global" impldecl="in declaration">kcombobox.h</include> + <include location="global" impldecl="in implementation">kurlrequester.h</include> + <include location="global" impldecl="in implementation">kdialog.h</include> +</includes> +<layoutdefaults spacing="3" margin="6"/> +<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/> +<includehints> + <includehint>kcombobox.h</includehint> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> + <includehint>kcombobox.h</includehint> +</includehints> +</UI> diff --git a/kcontrol/background/bghash.h b/kcontrol/background/bghash.h new file mode 100644 index 000000000..7cc09ca43 --- /dev/null +++ b/kcontrol/background/bghash.h @@ -0,0 +1,22 @@ +#ifndef BGHASH_H +#define BGHASH_H + +/* + * TQString -> int hash. From Qt's TQGDict::hashKeyString(). + */ + +static int TQHash(TQString key) +{ + int g, h = 0; + const TQChar *p = key.unicode(); + for (unsigned i=0; i < key.length(); i++) { + h = (h << 4) + p[i].cell(); + if ((g = (h & 0xf0000000))) + h ^= (g >> 24); + h &= ~g; + } + return h; +} + +#endif + diff --git a/kcontrol/background/bgmonitor.cpp b/kcontrol/background/bgmonitor.cpp new file mode 100644 index 000000000..c05e70e5f --- /dev/null +++ b/kcontrol/background/bgmonitor.cpp @@ -0,0 +1,220 @@ +/* vi: ts=8 sts=4 sw=4 + kate: space-indent on; indent-width 4; indent-mode cstyle; + + This file is part of the KDE project, module kcmbackground. + + Copyright (C) 2002 Laurent Montel <[email protected]> + Copyright (C) 2003 Waldo Bastian <[email protected]> + Copyright (C) 2005 David Saxton <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <kdebug.h> +#include <tdelocale.h> +#include <kpixmap.h> +#include <kstandarddirs.h> +#include <kurldrag.h> +#include <tqapplication.h> +#include <tqpixmap.h> +#include <tqwhatsthis.h> + +#include "bgmonitor.h" + +// Constants used (should they be placed somewhere?) +// Size of monitor image: 200x186 +// Geometry of "display" part of monitor image: (23,14)-[151x115] + +//BEGIN class BGMonitorArrangement +BGMonitorArrangement::BGMonitorArrangement(TQWidget *parent, const char *name) + : TQWidget(parent, name) +{ + m_pBGMonitor.resize( TQApplication::desktop()->numScreens(), 0l ); + + for (int screen = 0; screen < TQApplication::desktop()->numScreens(); ++screen) + { + BGMonitorLabel * label = new BGMonitorLabel(this); + m_pBGMonitor[screen] = label; + + connect( label->monitor(), TQT_SIGNAL(imageDropped(const TQString &)), this, TQT_SIGNAL(imageDropped(const TQString &)) ); + } + + parent->setFixedSize(200, 186); + setFixedSize(200, 186); + updateArrangement(); +} + + +BGMonitor * BGMonitorArrangement::monitor( unsigned screen ) const +{ + return m_pBGMonitor[screen]->monitor(); +} + + +TQRect BGMonitorArrangement::expandToPreview( TQRect r ) const +{ + double scaleX = 200.0 / 151.0; + double scaleY = 186.0 / 115.0; + return TQRect( int(r.x()*scaleX), int(r.y()*scaleY), int(r.width()*scaleX), int(r.height()*scaleY) ); +} + + +TQSize BGMonitorArrangement::expandToPreview( TQSize s ) const +{ + double scaleX = 200.0 / 151.0; + double scaleY = 186.0 / 115.0; + return TQSize( int(s.width()*scaleX), int(s.height()*scaleY) ); +} + + +TQPoint BGMonitorArrangement::expandToPreview( TQPoint p ) const +{ + double scaleX = 200.0 / 151.0; + double scaleY = 186.0 / 115.0; + return TQPoint( int(p.x()*scaleX), int(p.y()*scaleY) ); +} + + +void BGMonitorArrangement::updateArrangement() +{ + // In this function, sizes, etc have a normal value, and their "expanded" + // value. The expanded value is used for setting the size of the monitor + // image that contains the preview of the background. The monitor image + // will set the background preview back to the normal value. + + TQRect overallGeometry; + for (int screen = 0; screen < TQApplication::desktop()->numScreens(); ++screen) + overallGeometry |= TQApplication::desktop()->screenGeometry(screen); + + TQRect expandedOverallGeometry = expandToPreview(overallGeometry); + + double scale = TQMIN( + double(width()) / double(expandedOverallGeometry.width()), + double(height()) / double(expandedOverallGeometry.height()) + ); + + m_combinedPreviewSize = overallGeometry.size() * scale; + + m_maxPreviewSize = TQSize(0,0); + int previousMax = 0; + + for (int screen = 0; screen < TQApplication::desktop()->numScreens(); ++screen) + { + TQPoint topLeft = (TQApplication::desktop()->screenGeometry(screen).topLeft() - overallGeometry.topLeft()) * scale; + TQPoint expandedTopLeft = expandToPreview(topLeft); + + TQSize previewSize = TQApplication::desktop()->screenGeometry(screen).size() * scale; + TQSize expandedPreviewSize = expandToPreview(previewSize); + + if ( (previewSize.width() * previewSize.height()) > previousMax ) + { + previousMax = previewSize.width() * previewSize.height(); + m_maxPreviewSize = previewSize; + } + + m_pBGMonitor[screen]->setPreviewPosition( TQRect( topLeft, previewSize ) ); + m_pBGMonitor[screen]->setGeometry( TQRect( expandedTopLeft, expandedPreviewSize ) ); + m_pBGMonitor[screen]->updateMonitorGeometry(); + } +} + + +void BGMonitorArrangement::resizeEvent( TQResizeEvent * e ) +{ + TQWidget::resizeEvent(e); + updateArrangement(); +} + + +void BGMonitorArrangement::setPixmap( const KPixmap & pm ) +{ + for (unsigned screen = 0; screen < m_pBGMonitor.size(); ++screen) + { + TQRect position = m_pBGMonitor[screen]->previewPosition(); + + TQPixmap monitorPixmap( position.size(), pm.depth() ); + copyBlt( &monitorPixmap, 0, 0, &pm, position.x(), position.y(), position.width(), position.height() ); + m_pBGMonitor[screen]->monitor()->setPixmap(monitorPixmap); + } +} +//END class BGMonitorArrangement + + + +//BEGIN class BGMonitorLabel +BGMonitorLabel::BGMonitorLabel(TQWidget *parent, const char *name) + : TQLabel(parent, name) +{ + setAlignment(AlignCenter); + setScaledContents(true); + setPixmap( TQPixmap( locate("data", "kcontrol/pics/monitor.png") ) ); + m_pBGMonitor = new BGMonitor(this); + + TQWhatsThis::add( this, i18n("This picture of a monitor contains a preview of what the current settings will look like on your desktop.") ); +} + + +void BGMonitorLabel::updateMonitorGeometry() +{ + double scaleX = double(width()) / double(sizeHint().width()); + double scaleY = double(height()) / double(sizeHint().height()); + + kdDebug() << k_funcinfo << " Setting geometry to " << TQRect( int(23*scaleX), int(14*scaleY), int(151*scaleX), int(115*scaleY) ) << endl; + m_pBGMonitor->setGeometry( int(23*scaleX), int(14*scaleY), int(151*scaleX), int(115*scaleY) ); +} + + +void BGMonitorLabel::resizeEvent( TQResizeEvent * e ) +{ + TQWidget::resizeEvent(e); + updateMonitorGeometry(); +} +//END class BGMonitorLabel + + + +//BEGIN class BGMonitor +BGMonitor::BGMonitor(TQWidget *parent, const char *name) + : TQLabel(parent, name) +{ + setAlignment(AlignCenter); + setScaledContents(true); + setAcceptDrops(true); +} + + +void BGMonitor::dropEvent(TQDropEvent *e) +{ + if (!KURLDrag::canDecode(e)) + return; + + KURL::List uris; + if (KURLDrag::decode(e, uris) && (uris.count() > 0)) { + // TODO: Download remote file + if (uris.first().isLocalFile()) + emit imageDropped(uris.first().path()); + } +} + +void BGMonitor::dragEnterEvent(TQDragEnterEvent *e) +{ + if (KURLDrag::canDecode(e)) + e->accept(rect()); + else + e->ignore(rect()); +} +//END class BGMonitor + +#include "bgmonitor.moc" diff --git a/kcontrol/background/bgmonitor.h b/kcontrol/background/bgmonitor.h new file mode 100644 index 000000000..4a86ea3d2 --- /dev/null +++ b/kcontrol/background/bgmonitor.h @@ -0,0 +1,111 @@ +/* vi: ts=8 sts=4 sw=4 + kate: space-indent on; indent-width 4; indent-mode cstyle; + + This file is part of the KDE project, module kcmbackground. + + Copyright (C) 2002 Laurent Montel <[email protected]> + Copyright (C) 2003 Waldo Bastian <[email protected]> + Copyright (C) 2005 David Saxton <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 _BGMONITOR_H_ +#define _BGMONITOR_H_ + +#include <tqlabel.h> +#include <tqvaluevector.h> +#include <tqwidget.h> + +class BGMonitor; +class BGMonitorLabel; +class KPixmap; + +/** + * This class arranges and resizes a set of monitor images according to the + * monitor geometries. + */ +class BGMonitorArrangement : public TQWidget +{ + Q_OBJECT +public: + BGMonitorArrangement(TQWidget *parent, const char *name=0L); + + /** + * Splits up the pixmap according to monitor geometries and sets each + * BGMonitor pixmap accordingly. + */ + void setPixmap( const KPixmap & pm ); + TQSize combinedPreviewSize() const { return m_combinedPreviewSize; } + TQSize maxPreviewSize() const { return m_maxPreviewSize; } + unsigned numMonitors() const { return m_pBGMonitor.size(); } + + BGMonitor * monitor( unsigned screen ) const; + void updateArrangement(); + +signals: + void imageDropped(const TQString &); + +protected: + virtual void resizeEvent( TQResizeEvent * ); + TQRect expandToPreview( TQRect r ) const; + TQSize expandToPreview( TQSize s ) const; + TQPoint expandToPreview( TQPoint p ) const; + + TQValueVector<BGMonitorLabel*> m_pBGMonitor; + TQSize m_combinedPreviewSize; + TQSize m_maxPreviewSize; +}; + +/** + * Contains a BGMonitor. + */ +class BGMonitorLabel : public TQLabel +{ +public: + BGMonitorLabel(TQWidget *parent, const char *name=0L); + + BGMonitor * monitor() const { return m_pBGMonitor; } + void updateMonitorGeometry(); + + void setPreviewPosition( TQRect r ) { m_previewPosition = r; } + TQRect previewPosition() const { return m_previewPosition; } + +protected: + virtual void resizeEvent( TQResizeEvent * ); + BGMonitor * m_pBGMonitor; + TQRect m_previewPosition; +}; + + +/** + * This class handles drops on the preview monitor. + */ +class BGMonitor : public TQLabel +{ + Q_OBJECT +public: + BGMonitor(TQWidget *parent, const char *name=0L); + +signals: + void imageDropped(const TQString &); + +protected: + virtual void dropEvent(TQDropEvent *); + virtual void dragEnterEvent(TQDragEnterEvent *); +}; + + +#endif diff --git a/kcontrol/background/bgrender.cpp b/kcontrol/background/bgrender.cpp new file mode 100644 index 000000000..d8cc53c9a --- /dev/null +++ b/kcontrol/background/bgrender.cpp @@ -0,0 +1,1363 @@ +/* vi: ts=8 sts=4 sw=4 + * kate: space-indent on; tab-width 8; indent-width 4; indent-mode cstyle; + * + * This file is part of the KDE project, module kdesktop. + * Copyright (C) 1999 Geert Jansen <[email protected]> + * + * You can Freely distribute this program under the GNU Library General + * Public License. See the file "COPYING.LIB" for the exact licensing terms. + */ + +#include <config.h> + +#include "KCrossBGRender.h" + +#include <time.h> +#include <stdlib.h> +#include <utime.h> + +#include <tqtimer.h> +#include <tqpainter.h> +#include <tqimage.h> +#include <tqfileinfo.h> +#include <tqdir.h> + +#include <dcopclient.h> +#include <tdeapplication.h> +#include <kdebug.h> +#include <kstandarddirs.h> +#include <kimageeffect.h> +#include <kprocess.h> +#include <kpixmapio.h> +#include <tdetempfile.h> +#include <kcursor.h> +#include <kmimetype.h> +#include <tdefilemetainfo.h> + +#ifdef HAVE_LIBART +#include <ksvgiconengine.h> +#endif + +#include "bgdefaults.h" +#include "bghash.h" +#include "bgrender.h" + +#include <X11/Xlib.h> + +#include <config.h> + +/**** KBackgroundRenderer ****/ + + +KBackgroundRenderer::KBackgroundRenderer(int desk, int screen, bool drawBackgroundPerScreen, TDEConfig *config) + : KBackgroundSettings(desk, screen, drawBackgroundPerScreen, config) +{ + m_State = 0; + m_isBusyCursor = false; + m_enableBusyCursor = false; + m_pDirs = TDEGlobal::dirs(); + m_rSize = m_Size = drawBackgroundPerScreen ? TDEApplication::desktop()->screenGeometry(screen).size() : TDEApplication::desktop()->geometry().size(); + m_pProc = 0L; + m_Tempfile = 0L; + m_bPreview = false; + m_Cached = false; + m_TilingEnabled = false; + + m_pTimer = new TQTimer(this); + connect(m_pTimer, TQT_SIGNAL(timeout()), TQT_SLOT(render())); +} + + +KBackgroundRenderer::~KBackgroundRenderer() +{ + cleanup(); + delete m_Tempfile; + m_Tempfile = 0; +} + + +void KBackgroundRenderer::setSize(const TQSize &size) +{ + m_rSize = m_Size = size; +} + +/* + * Re-configure because the desktop has been resized. + */ +void KBackgroundRenderer::desktopResized() +{ + m_State = 0; + m_rSize = drawBackgroundPerScreen() ? TDEApplication::desktop()->screenGeometry(screen()).size() : TDEApplication::desktop()->geometry().size(); + if( !m_bPreview ) + m_Size = m_rSize; +} + + +void KBackgroundRenderer::tile(TQImage& dest, TQRect rect, const TQImage& src) +{ + rect &= dest.rect(); + + int x, y; + int h = rect.height(), w = rect.width(); + int offx = rect.x(), offy = rect.y(); + int sw = src.width(), sh = src.height(); + + for (y=offy; y<offy+h; y++) + for (x=offx; x<offx+w; x++) + dest.setPixel(x, y, src.pixel(x%sw, y%sh)); +} + + +/* + * Build a command line to run the program. + */ + +TQString KBackgroundRenderer::buildCommand() +{ + TQString num; + int pos = 0; + + TQString cmd; + if (m_bPreview) + cmd = previewCommand(); + else + cmd = command(); + + if (cmd.isEmpty()) + return TQString(); + + while ((pos = cmd.find('%', pos)) != -1) { + + if (pos == (int) (cmd.length() - 1)) + break; + + switch (cmd.at(pos+1).latin1()) { + case 'f': + createTempFile(); + cmd.replace(pos, 2, KShellProcess::quote(m_Tempfile->name())); + pos += m_Tempfile->name().length() - 2; + break; + + case 'x': + num.setNum(m_Size.width()); + cmd.replace(pos, 2, num); + pos += num.length() - 2; + break; + + case 'y': + num.setNum(m_Size.height()); + cmd.replace(pos, 2, num); + pos += num.length() - 2; + break; + + case '%': + cmd.replace(pos, 2, "%"); + pos--; + break; + default: + ++pos; // avoid infinite loop + break; + } + + } + return cmd; +} + + +/* + * Create a background tile. If the background mode is `Program', + * this is asynchronous. + */ +int KBackgroundRenderer::doBackground(bool quit) +{ + if (m_State & BackgroundDone) + return Done; + int bgmode = backgroundMode(); + + if (!enabled()) + bgmode= Flat; + + if (quit) { + if (bgmode == Program && m_pProc) + m_pProc->kill(); + return Done; + } + + int retval = Done; + TQString file; + + static unsigned int tileWidth = 0; + static unsigned int tileHeight = 0; + if( tileWidth == 0 ) + { + int tile_val = TQPixmap::defaultDepth() >= 24 ? 1 : 2; + // some dithering may be needed even with bpb==15/16, so don't use tileWidth==1 + // for them + // with tileWidth>2, repainting the desktop causes nasty effect (XFree86 4.1.0 ) + if( XQueryBestTile( tqt_xdisplay(), tqt_xrootwin(), tile_val, tile_val, + &tileWidth, &tileHeight ) != Success ) + tileWidth = tileHeight = tile_val; // some defaults + } + switch (bgmode) { + + case Flat: + // this can be tiled correctly without problems + m_Background.create( tileWidth, tileHeight, 32); + m_Background.fill(colorA().rgb()); + break; + + case Pattern: + { + if (pattern().isEmpty()) + break; + file = m_pDirs->findResource("dtop_pattern", pattern()); + if (file.isEmpty()) + break; + + m_Background.load(file); + if (m_Background.isNull()) + break; + int w = m_Background.width(); + int h = m_Background.height(); + if ((w > m_Size.width()) || (h > m_Size.height())) { + w = TQMIN(w, m_Size.width()); + h = TQMIN(h, m_Size.height()); + m_Background = m_Background.copy(0, 0, w, h); + } + KImageEffect::flatten(m_Background, colorA(), colorB(), 0); + break; + } + case Program: + if (m_State & BackgroundStarted) + break; + m_State |= BackgroundStarted; + createTempFile(); + + file = buildCommand(); + if (file.isEmpty()) + break; + + delete m_pProc; + m_pProc = new KShellProcess; + *m_pProc << file; + connect(m_pProc, TQT_SIGNAL(processExited(TDEProcess *)), + TQT_SLOT(slotBackgroundDone(TDEProcess *))); + m_pProc->start(KShellProcess::NotifyOnExit); + retval = Wait; + break; + + case HorizontalGradient: + { + TQSize size = m_Size; + // on <16bpp displays the gradient sucks when tiled because of dithering + if( canTile()) + size.setHeight( tileHeight ); + m_Background = KImageEffect::gradient(size, colorA(), colorB(), + KImageEffect::HorizontalGradient, 0); + break; + } + case VerticalGradient: + { + TQSize size = m_Size; + // on <16bpp displays the gradient sucks when tiled because of dithering + if( canTile()) + size.setWidth( tileWidth ); + m_Background = KImageEffect::gradient(size, colorA(), colorB(), + KImageEffect::VerticalGradient, 0); + break; + } + case PyramidGradient: + m_Background = KImageEffect::gradient(m_Size, colorA(), colorB(), + KImageEffect::PyramidGradient, 0); + break; + + case PipeCrossGradient: + m_Background = KImageEffect::gradient(m_Size, colorA(), colorB(), + KImageEffect::PipeCrossGradient, 0); + break; + + case EllipticGradient: + m_Background = KImageEffect::gradient(m_Size, colorA(), colorB(), + KImageEffect::EllipticGradient, 0); + break; + } + + if (retval == Done) + m_State |= BackgroundDone; + + return retval; +} + + +int KBackgroundRenderer::doWallpaper(bool quit) +{ + if (m_State & WallpaperDone) + return Done; + + if (quit) + // currently no asynch. wallpapers + return Done; + + int wpmode= enabled()?wallpaperMode():NoWallpaper; + + m_Wallpaper = TQImage(); + if (wpmode != NoWallpaper) { +wp_load: + if (currentWallpaper().isEmpty()) { + wpmode = NoWallpaper; + goto wp_out; + } + TQString file = m_pDirs->findResource("wallpaper", currentWallpaper()); + if (file.isEmpty()) { + wpmode = NoWallpaper; + goto wp_out; + } + + // _Don't_ use KMimeType, as it relies on tdesycoca which we really + // don't want in krootimage (tdm context). + //if ( KMimeType::findByPath( file )->is( "image/svg+xml" ) ) { + if (file.endsWith(".svg") || file.endsWith(".svgz")) { +#ifdef HAVE_LIBART + // Special stuff for SVG icons + KSVGIconEngine* svgEngine = new KSVGIconEngine(); + + //FIXME + //ksvgiconloader doesn't seem to let us find out the + //ratio of width to height so for the most part we just + //assume it's a square + int svgWidth; + int svgHeight; + switch (wpmode) + { + case Centred: + case CentredAutoFit: + svgHeight = (int)(m_Size.height() * 0.8); + svgWidth = svgHeight; + break; + case Tiled: + case CenterTiled: + svgHeight = (int)(m_Size.height() * 0.5); + svgWidth = svgHeight; + break; + case Scaled: + svgHeight = m_Size.height(); + svgWidth = m_Size.width(); + break; + case CentredMaxpect: + case ScaleAndCrop: + case TiledMaxpect: + svgHeight = m_Size.height(); + svgWidth = svgHeight; + break; + case NoWallpaper: + default: + kdWarning() << k_funcinfo << "unknown diagram type" << endl; + svgHeight = m_Size.height(); + svgWidth = svgHeight; + break; + } + //FIXME hack due to strangeness with + //background control modules + if ( svgHeight < 200 ) { + svgHeight *= 6; + svgWidth *= 6; + } + + if (svgEngine->load(svgWidth, svgHeight, file )) { + TQImage *image = svgEngine->image(); + m_Wallpaper = *image; + delete image; + } else { + kdWarning() << "failed to load SVG file " << file << endl; + } + + delete svgEngine; +#else //not libart + kdWarning() << k_funcinfo + << "tried to load SVG file but libart not installed" << endl; +#endif + } else { + m_Wallpaper.load(file); + } + if (m_Wallpaper.isNull()) { + if (discardCurrentWallpaper()) + goto wp_load; + wpmode = NoWallpaper; + goto wp_out; + } + m_Wallpaper = m_Wallpaper.convertDepth(32, Qt::DiffuseAlphaDither); + + // If we're previewing, scale the wallpaper down to make the preview + // look more like the real desktop. + if (m_bPreview) { + int xs = m_Wallpaper.width() * m_Size.width() / m_rSize.width(); + int ys = m_Wallpaper.height() * m_Size.height() / m_rSize.height(); + if ((xs < 1) || (ys < 1)) + { + xs = ys = 1; + } + if( m_Wallpaper.size() != TQSize( xs, ys )) + m_Wallpaper = m_Wallpaper.smoothScale(xs, ys); + } + + // HACK: Use KFileMetaInfo only when we're attached to DCOP. + // KFileMetaInfo needs tdesycoca and so on, but this code is + // used also in krootimage (which in turn is used by tdm). + if( kapp->dcopClient()->isAttached()) { + KFileMetaInfo metaInfo(file); + if (metaInfo.isValid() && metaInfo.item("Orientation").isValid()) { + switch (metaInfo.item("Orientation").string().toInt()) { + case 2: + // Flipped horizontally + m_Wallpaper = m_Wallpaper.mirror(true, false); + break; + case 3: + // Rotated 180 degrees + m_Wallpaper = KImageEffect::rotate(m_Wallpaper, KImageEffect::Rotate180); + break; + case 4: + // Flipped vertically + m_Wallpaper = m_Wallpaper.mirror(false, true); + break; + case 5: + // Rotated 90 degrees & flipped horizontally + m_Wallpaper = KImageEffect::rotate(m_Wallpaper, KImageEffect::Rotate90).mirror(true, false); + break; + case 6: + // Rotated 90 degrees + m_Wallpaper = KImageEffect::rotate(m_Wallpaper, KImageEffect::Rotate90); + break; + case 7: + // Rotated 90 degrees & flipped vertically + m_Wallpaper = KImageEffect::rotate(m_Wallpaper, KImageEffect::Rotate90).mirror(false, true); + break; + case 8: + // Rotated 270 degrees + m_Wallpaper = KImageEffect::rotate(m_Wallpaper, KImageEffect::Rotate270); + break; + case 1: + default: + // Normal or invalid orientation + break; + } + } + } + } +wp_out: + + if (m_Background.isNull()) { + m_Background.create(8, 8, 32); + m_Background.fill(colorA().rgb()); + } + + int retval = Done; + + int w = m_Size.width(); // desktop width/height + int h = m_Size.height(); + + int ww = m_Wallpaper.width(); // wallpaper width/height + int wh = m_Wallpaper.height(); + + m_WallpaperRect = TQRect(); // to be filled destination rectangle; may exceed desktop! + + switch (wpmode) + { + case NoWallpaper: + break; + case Centred: + m_WallpaperRect.setRect((w - ww) / 2, (h - wh) / 2, ww, wh); + break; + case Tiled: + m_WallpaperRect.setRect(0, 0, w, h); + break; + case CenterTiled: + m_WallpaperRect.setCoords(-ww + ((w - ww) / 2) % ww, -wh + ((h - wh) / 2) % wh, w-1, h-1); + break; + case Scaled: + ww = w; + wh = h; + if( m_WallpaperRect.size() != TQSize( w, h )) + m_Wallpaper = m_Wallpaper.smoothScale( w, h ); + m_WallpaperRect.setRect(0, 0, w, h); + break; + case CentredAutoFit: + if( ww <= w && wh <= h ) { + m_WallpaperRect.setRect((w - ww) / 2, (h - wh) / 2, ww, wh); // like Centred + break; + } + // fall through + case CentredMaxpect: + { + double sx = (double) w / ww; + double sy = (double) h / wh; + if (sx > sy) { + ww = (int)(sy * ww); + wh = h; + } else { + wh = (int)(sx * wh); + ww = w; + } + if( m_WallpaperRect.size() != TQSize( ww, wh )) + m_Wallpaper = m_Wallpaper.smoothScale(ww, wh); + m_WallpaperRect.setRect((w - ww) / 2, (h - wh) / 2, ww, wh); + break; + } + case TiledMaxpect: + { + double sx = (double) w / ww; + double sy = (double) h / wh; + if (sx > sy) { + ww = (int)(sy * ww); + wh = h; + } else { + wh = (int)(sx * wh); + ww = w; + } + if( m_WallpaperRect.size() != TQSize( ww, wh )) + m_Wallpaper = m_Wallpaper.smoothScale(ww, wh); + m_WallpaperRect.setRect(0, 0, w, h); + break; + } + case ScaleAndCrop: + { + double sx = (double) w / ww; + double sy = (double) h / wh; + if (sx > sy) { + //Case 1: x needs bigger scaling. Lets increase x and leave part of y offscreen + ww = w; + wh=(int)(sx * wh); + } else { + //Case 2: y needs bigger scaling. Lets increase y and leave part of x offscreen + wh = h; + ww = (int)(sy*ww); + } + if( m_WallpaperRect.size() != TQSize( ww, wh )) + m_Wallpaper = m_Wallpaper.smoothScale(ww, wh); + m_WallpaperRect.setRect((w - ww) / 2, (h - wh) / 2,w, h); + break; + } + } + + wallpaperBlend(); + + if (retval == Done) + m_State |= WallpaperDone; + + return retval; +} + +bool KBackgroundRenderer::canTile() const +{ + return m_TilingEnabled && optimize(); +} + +extern bool tqt_use_xrender; // in Qt ( qapplication_x11.cpp ) + +void KBackgroundRenderer::wallpaperBlend() +{ + if( !enabled() || wallpaperMode() == NoWallpaper + || (blendMode() == NoBlending && ( tqt_use_xrender || !m_Wallpaper.hasAlphaBuffer()))) { + fastWallpaperBlend(); + } + else { + fullWallpaperBlend(); + } +} + +// works only for NoBlending and no alpha in wallpaper +// but is much faster than TQImage fidling +void KBackgroundRenderer::fastWallpaperBlend() +{ + m_Image = TQImage(); + // copy background to m_pPixmap + if( !enabled() || (wallpaperMode() == NoWallpaper && canTile())) { + // if there's no wallpaper, no need to tile the pixmap to the size of desktop, as X does + // that automatically and using a smaller pixmap should save some memory + m_Pixmap.convertFromImage( m_Background ); + return; + } + else if( wallpaperMode() == Tiled && !m_Wallpaper.hasAlphaBuffer() && canTile() && !m_bPreview ) { + // tiles will be tiled by X automatically + if( useShm()) { + KPixmapIO io; + m_Pixmap = io.convertToPixmap( m_Wallpaper ); + } + else + m_Pixmap.convertFromImage( m_Wallpaper ); + return; + } + else if( m_WallpaperRect.contains( TQRect( TQPoint( 0, 0 ), m_Size )) + && !m_Wallpaper.hasAlphaBuffer()) // wallpaper covers all and no blending + m_Pixmap = TQPixmap( m_Size ); + else if (m_Background.size() == m_Size) + m_Pixmap.convertFromImage( m_Background ); + else { + m_Pixmap = TQPixmap( m_Size ); + TQPainter p( &m_Pixmap ); + TQPixmap pm; + pm.convertFromImage( m_Background ); + p.drawTiledPixmap( 0, 0, m_Size.width(), m_Size.height(), pm ); + } + + // paint/alpha-blend wallpaper to destination rectangle of m_pPixmap + if (m_WallpaperRect.isValid()) { + TQPixmap wp_pixmap; + if( useShm() && !m_Wallpaper.hasAlphaBuffer()) { + KPixmapIO io; + wp_pixmap = io.convertToPixmap( m_Wallpaper ); + } + else + wp_pixmap.convertFromImage( m_Wallpaper ); + int ww = m_Wallpaper.width(); + int wh = m_Wallpaper.height(); + for (int y = m_WallpaperRect.top(); y < m_WallpaperRect.bottom(); y += wh) { + for (int x = m_WallpaperRect.left(); x < m_WallpaperRect.right(); x += ww) { + bitBlt( &m_Pixmap, x, y, &wp_pixmap, 0, 0, ww, wh ); + } + } + } +} + + +void KBackgroundRenderer::fullWallpaperBlend() +{ + m_Pixmap = TQPixmap(); + int w = m_Size.width(); // desktop width/height + int h = m_Size.height(); + // copy background to m_pImage + if (m_Background.size() == m_Size) { + m_Image = m_Background.copy(); + + if (m_Image.depth() < 32) + m_Image = m_Image.convertDepth(32, Qt::DiffuseAlphaDither); + + } else { + m_Image.create(w, h, 32); + tile(m_Image, TQRect(0, 0, w, h), m_Background); + } + + // blend wallpaper to destination rectangle of m_pImage + if (m_WallpaperRect.isValid()) + { + int blendFactor = 100; + if (blendMode() == FlatBlending) + blendFactor = (blendBalance()+200)/4; + int ww = m_Wallpaper.width(); + int wh = m_Wallpaper.height(); + for (int y = m_WallpaperRect.top(); y < m_WallpaperRect.bottom(); y += wh) { + for (int x = m_WallpaperRect.left(); x < m_WallpaperRect.right(); x += ww) { + blend(m_Image, TQRect(x, y, ww, wh), m_Wallpaper, + TQPoint(-TQMIN(x, 0), -TQMIN(y, 0)), blendFactor); + } + } + } + + + // blend whole desktop + if ( wallpaperMode() != NoWallpaper) { + int bal = blendBalance(); + + switch( blendMode() ) { + case HorizontalBlending: + KImageEffect::blend( m_Image, m_Background, + KImageEffect::HorizontalGradient, + bal, 100 ); + break; + + case VerticalBlending: + KImageEffect::blend( m_Image, m_Background, + KImageEffect::VerticalGradient, + 100, bal ); + break; + + case PyramidBlending: + KImageEffect::blend( m_Image, m_Background, + KImageEffect::PyramidGradient, + bal, bal ); + break; + + case PipeCrossBlending: + KImageEffect::blend( m_Image, m_Background, + KImageEffect::PipeCrossGradient, + bal, bal ); + break; + + case EllipticBlending: + KImageEffect::blend( m_Image, m_Background, + KImageEffect::EllipticGradient, + bal, bal ); + break; + + case IntensityBlending: + KImageEffect::modulate( m_Image, m_Background, reverseBlending(), + KImageEffect::Intensity, bal, KImageEffect::All ); + break; + + case SaturateBlending: + KImageEffect::modulate( m_Image, m_Background, reverseBlending(), + KImageEffect::Saturation, bal, KImageEffect::Gray ); + break; + + case ContrastBlending: + KImageEffect::modulate( m_Image, m_Background, reverseBlending(), + KImageEffect::Contrast, bal, KImageEffect::All ); + break; + + case HueShiftBlending: + KImageEffect::modulate( m_Image, m_Background, reverseBlending(), + KImageEffect::HueShift, bal, KImageEffect::Gray ); + break; + + case FlatBlending: + // Already handled + break; + } + } +} + +/* Alpha blend an area from <src> with offset <soffs> to rectangle <dr> of <dst> + * Default offset is TQPoint(0, 0). + * blendfactor = [0, 100%] + */ +void KBackgroundRenderer::blend(TQImage& dst, TQRect dr, const TQImage& src, TQPoint soffs, int blendFactor) +{ + int x, y, a; + dr &= dst.rect(); + + for (y = 0; y < dr.height(); y++) { + if (dst.scanLine(dr.y() + y) && src.scanLine(soffs.y() + y)) { + TQRgb *b, *d; + for (x = 0; x < dr.width(); x++) { + b = reinterpret_cast<TQRgb*>(dst.scanLine(dr.y() + y) + + (dr.x() + x) * sizeof(TQRgb)); + d = reinterpret_cast<TQRgb*>(const_cast<TQImage&>(src).scanLine(soffs.y() + y) + + (soffs.x() + x) * sizeof(TQRgb)); + a = (tqAlpha(*d) * blendFactor) / 100; + *b = tqRgb(tqRed(*b) - (((tqRed(*b) - tqRed(*d)) * a) >> 8), + tqGreen(*b) - (((tqGreen(*b) - tqGreen(*d)) * a) >> 8), + tqBlue(*b) - (((tqBlue(*b) - tqBlue(*d)) * a) >> 8)); + } + } + } +} + + + +void KBackgroundRenderer::slotBackgroundDone(TDEProcess *process) +{ + Q_ASSERT(process == m_pProc); + m_State |= BackgroundDone; + + if (m_pProc->normalExit() && !m_pProc->exitStatus()) { + m_Background.load(m_Tempfile->name()); + m_State |= BackgroundDone; + } + + m_Tempfile->unlink(); + delete m_Tempfile; m_Tempfile = 0; + m_pTimer->start(0, true); + setBusyCursor(false); +} + + + +/* + * Starts the rendering process. + */ +void KBackgroundRenderer::start(bool enableBusyCursor) +{ + m_enableBusyCursor = enableBusyCursor; + setBusyCursor(true); + + m_Cached = false; + + m_State = Rendering; + m_pTimer->start(0, true); +} + + +/* + * This slot is connected to a timer event. It is called repeatedly until + * the rendering is done. + */ +void KBackgroundRenderer::render() +{ + setBusyCursor(true); + if (!(m_State & Rendering)) + return; + + if( !(m_State & InitCheck)) { + TQString f = cacheFileName(); + if( useCacheFile()) { + TQString w = m_pDirs->findResource("wallpaper", currentWallpaper()); + TQFileInfo wi( w ); + TQFileInfo fi( f ); + if( wi.lastModified().isValid() && fi.lastModified().isValid() + && wi.lastModified() < fi.lastModified()) { + TQImage im; + if( im.load( f, "PNG" )) { + m_Image = im; + m_Pixmap = TQPixmap( m_Size ); + m_Pixmap.convertFromImage( m_Image ); + m_Cached = true; + m_State |= InitCheck | BackgroundDone | WallpaperDone; + } + } + } + m_pTimer->start(0, true); + m_State |= InitCheck; + return; + } + + int ret; + + if (!(m_State & BackgroundDone)) { + ret = doBackground(); + if (ret != Wait) + m_pTimer->start(0, true); + return; + } + + // No async wallpaper + doWallpaper(); + + done(); + setBusyCursor(false); +} + + +/* + * Rendering is finished. + */ +void KBackgroundRenderer::done() +{ + setBusyCursor(false); + m_State |= AllDone; + emit imageDone(desk(), screen()); + if(backgroundMode() == Program && m_pProc && + m_pProc->normalExit() && m_pProc->exitStatus()) { + emit programFailure(desk(), m_pProc->exitStatus()); + } else if(backgroundMode() == Program && m_pProc && + !m_pProc->normalExit()) { + emit programFailure(desk(), -1); + } else if(backgroundMode() == Program) { + emit programSuccess(desk()); + } + +} + +/* + * This function toggles a busy cursor on and off, for use in rendering. + * It is useful because of the ASYNC nature of the rendering - it is hard + * to make sure we don't set the busy cursor twice, but only restore + * once. + */ +void KBackgroundRenderer::setBusyCursor(bool isBusy) { + if(m_isBusyCursor == isBusy) + return; + if (isBusy && !m_enableBusyCursor) + return; + m_isBusyCursor = isBusy; + if(isBusy) + TQApplication::setOverrideCursor( KCursor::workingCursor() ); + else + TQApplication::restoreOverrideCursor(); +} + +/* + * Stop the rendering. + */ +void KBackgroundRenderer::stop() +{ + if (!(m_State & Rendering)) + return; + + doBackground(true); + doWallpaper(true); + m_State = 0; +} + + +/* + * Cleanup after rendering. + */ +void KBackgroundRenderer::cleanup() +{ + setBusyCursor(false); + m_Background = TQImage(); + m_Image = TQImage(); + m_Pixmap = TQPixmap(); + m_Wallpaper = TQImage(); + delete m_pProc; m_pProc = 0L; + m_State = 0; + m_WallpaperRect = TQRect(); + m_Cached = false; +} + + +void KBackgroundRenderer::setPreview(const TQSize &size) +{ + if (size.isNull()) + m_bPreview = false; + else { + m_bPreview = true; + m_Size = size; + } +} + + +TQPixmap KBackgroundRenderer::pixmap() +{ + if (m_State & AllDone) { + if( m_Pixmap.isNull()) + m_Pixmap.convertFromImage( m_Image ); + return m_Pixmap; + } + return TQPixmap(); +} + +TQImage KBackgroundRenderer::image() +{ + if (m_State & AllDone) { + if( m_Image.isNull()) + fullWallpaperBlend(); // create from m_Pixmap + return m_Image; + } + return TQImage(); +} + + +void KBackgroundRenderer::load(int desk, int screen, bool drawBackgroundPerScreen, bool reparseConfig) +{ + if (m_State & Rendering) + stop(); + + cleanup(); + m_bPreview = false; + m_Size = m_rSize; + + KBackgroundSettings::load(desk, screen, drawBackgroundPerScreen, reparseConfig); +} + +void KBackgroundRenderer::createTempFile() +{ + if( !m_Tempfile ) + m_Tempfile = new KTempFile(); +} + +TQString KBackgroundRenderer::cacheFileName() +{ + TQString f = fingerprint(); + f.replace ( ':', '_' ); // avoid characters that shouldn't be in filenames + f.replace ( '/', '#' ); + f = locateLocal( "cache", TQString( "background/%1x%2_%3.png" ) + .arg( m_Size.width()).arg( m_Size.height()).arg( f )); + return f; +} + +bool KBackgroundRenderer::useCacheFile() const +{ + if( !enabled()) + return false; + if( backgroundMode() == Program ) + return false; // don't cache these at all + if( wallpaperMode() == NoWallpaper ) + return false; // generating only background patterns should be always faster + TQString file = currentWallpaper(); + if( file.endsWith(".svg") || file.endsWith(".svgz")) + return true; // cache these, they can be bloody slow + switch( backgroundMode()) + { + case NoWallpaper: + case Centred: + case Tiled: + case CenterTiled: + return false; // these don't need scaling + case CentredMaxpect: + case TiledMaxpect: + case Scaled: + case CentredAutoFit: + case ScaleAndCrop: + default: + return true; + } +} + +void KBackgroundRenderer::saveCacheFile() +{ + if( !( m_State & AllDone )) + return; + if( !useCacheFile()) + return; + if( m_Image.isNull()) + fullWallpaperBlend(); // generate from m_Pixmap + TQString f = cacheFileName(); + if( TDEStandardDirs::exists( f ) || m_Cached ) + utime( TQFile::encodeName( f ), NULL ); + else { + m_Image.save( f, "PNG" ); + // remove old entries from the cache + TQDir dir( locateLocal( "cache", "background/" )); + if( const TQFileInfoList* list = dir.entryInfoList( "*.png", TQDir::Files, TQDir::Time | TQDir::Reversed )) { + int size = 0; + for( TQFileInfoListIterator it( *list ); + TQFileInfo* info = it.current(); + ++it ) + size += info->size(); + for( TQFileInfoListIterator it( *list ); + TQFileInfo* info = it.current(); + ++it ) { + if( size < 8 * 1024 * 1024 ) + break; + // keep everything newer than 10 minutes if the total size is less than 50M (just in case) + if( size < 50 * 1024 * 1024 + && ( time_t ) info->lastModified().toTime_t() >= time( NULL ) - 10 * 60 ) + break; + size -= info->size(); + TQFile::remove( info->absFilePath()); + } + } + } +} + +//BEGIN class KVirtualBGRenderer +KVirtualBGRenderer::KVirtualBGRenderer( int desk, TDEConfig *config ) +{ + m_pPixmap = 0l; + m_desk = desk; + m_numRenderers = 0; + m_scaleX = 1; + m_scaleY = 1; + + // The following code is borrowed from KBackgroundSettings::KBackgroundSettings + if (!config) { + int screen_number = 0; + if (tqt_xdisplay()) + screen_number = DefaultScreen(tqt_xdisplay()); + TQCString configname; + if (screen_number == 0) + configname = "kdesktoprc"; + else + configname.sprintf("kdesktop-screen-%drc", screen_number); + + m_pConfig = new TDEConfig(configname, false, false); + m_bDeleteConfig = true; + } else { + m_pConfig = config; + m_bDeleteConfig = false; + } + + initRenderers(); + m_size = TDEApplication::desktop()->geometry().size(); +} + +KVirtualBGRenderer::~KVirtualBGRenderer() +{ + for (unsigned i=0; i<m_numRenderers; ++i) + delete m_renderer[i]; + + delete m_pPixmap; + + if (m_bDeleteConfig) + delete m_pConfig; +} + + +KCrossBGRender * KVirtualBGRenderer::renderer(unsigned screen) +{ + return m_renderer[screen]; +} + + +TQPixmap KVirtualBGRenderer::pixmap() +{ + if (m_numRenderers == 1) + return m_renderer[0]->pixmap(); + + return *m_pPixmap; +} + + +bool KVirtualBGRenderer::needProgramUpdate() +{ + for (unsigned i=0; i<m_numRenderers; ++i) + { + if ( m_renderer[i]->backgroundMode() == KBackgroundSettings::Program && + m_renderer[i]->KBackgroundProgram::needUpdate() ) + return true; + } + return false; +} + + +void KVirtualBGRenderer::programUpdate() +{ + for (unsigned i=0; i<m_numRenderers; ++i) + { + if ( m_renderer[i]->backgroundMode() == KBackgroundSettings::Program && + m_renderer[i]->KBackgroundProgram::needUpdate() ) + { + m_renderer[i]->KBackgroundProgram::update(); + } + } +} + + +bool KVirtualBGRenderer::needWallpaperChange() +{ + for (unsigned i=0; i<m_numRenderers; ++i) + { + if ( m_renderer[i]->needWallpaperChange() ) + return true; + } + return false; +} + + +void KVirtualBGRenderer::changeWallpaper() +{ + for (unsigned i=0; i<m_numRenderers; ++i) + { + m_renderer[i]->changeWallpaper(); + } +} + + +int KVirtualBGRenderer::hash() +{ + TQString fp; + for (unsigned i=0; i<m_numRenderers; ++i) + { + fp += m_renderer[i]->fingerprint(); + } + //kdDebug() << k_funcinfo << " fp=\""<<fp<<"\" h="<<QHash(fp)<<endl; + return TQHash(fp); +} + + +bool KVirtualBGRenderer::isActive() +{ + for (unsigned i=0; i<m_numRenderers; ++i) + { + if ( m_renderer[i]->isActive() ) + return true; + } + return false; +} + + +void KVirtualBGRenderer::setEnabled(bool enable) +{ + for (unsigned i=0; i<m_numRenderers; ++i) + m_renderer[i]->setEnabled(enable); +} + + +void KVirtualBGRenderer::desktopResized() +{ + m_size = TDEApplication::desktop()->geometry().size(); + + if (m_pPixmap) + { + delete m_pPixmap; + m_pPixmap = new TQPixmap(m_size); + m_pPixmap->fill(Qt::black); + } + + initRenderers(); +} + + +void KVirtualBGRenderer::setPreview(const TQSize & size) +{ + if (m_size == size) + return; + + m_size = size; + + if (m_pPixmap) + m_pPixmap->resize(m_size); + + // Scaling factors + m_scaleX = float(m_size.width()) / float(TQApplication::desktop()->size().width()); + m_scaleY = float(m_size.height()) / float(TQApplication::desktop()->size().height()); + + // Scale renderers appropriately + for (unsigned i=0; i<m_renderer.size(); ++i) + { + TQSize unscaledRendererSize = renderSize(i); + + m_renderer[i]->setPreview( TQSize( + int(unscaledRendererSize.width() * m_scaleX), + int(unscaledRendererSize.height() * m_scaleY) ) ); + } +} + + +TQSize KVirtualBGRenderer::renderSize(int screen) +{ + return m_bDrawBackgroundPerScreen ? TDEApplication::desktop()->screenGeometry(screen).size() : TDEApplication::desktop()->geometry().size(); +} + + +void KVirtualBGRenderer::initRenderers() +{ + m_pConfig->setGroup("Background Common"); + m_bDrawBackgroundPerScreen = m_pConfig->readBoolEntry( TQString("DrawBackgroundPerScreen_%1").arg(m_desk), _defDrawBackgroundPerScreen ); + + m_bCommonScreen = m_pConfig->readBoolEntry("CommonScreen", _defCommonScreen); + + m_numRenderers = m_bDrawBackgroundPerScreen ? TDEApplication::desktop()->numScreens() : 1; + if (m_numRenderers < 2) { + // Only one screen is currently available; deactivate per-screen rendering but do not overwrite multi-screen settings + m_bDrawBackgroundPerScreen = false; + } + + m_bFinished.resize(m_numRenderers); + m_bFinished.fill(false); + + if (m_numRenderers == m_renderer.size()) + return; + + for (unsigned i=0; i<m_renderer.size(); ++i) + delete m_renderer[i]; + + m_renderer.resize(m_numRenderers); + for (unsigned i=0; i<m_numRenderers; ++i) + { + int eScreen = m_bCommonScreen ? 0 : i; + KCrossBGRender *r = new KCrossBGRender(m_desk, eScreen, m_bDrawBackgroundPerScreen, m_pConfig); + m_renderer.insert( i, r ); + r->setSize(renderSize(i)); + connect( r, TQT_SIGNAL(imageDone(int,int)), this, TQT_SLOT(screenDone(int,int)) ); + } +} + + +void KVirtualBGRenderer::load(int desk, bool reparseConfig) +{ + m_desk = desk; + + m_pConfig->setGroup("Background Common"); + m_bCommonScreen = m_pConfig->readBoolEntry("CommonScreen", _defCommonScreen); + + initRenderers(); + + for (unsigned i=0; i<m_numRenderers; ++i) + { + unsigned eScreen = m_bCommonScreen ? 0 : i; + m_renderer[i]->load(desk, eScreen, m_bDrawBackgroundPerScreen, reparseConfig); + } +} + + +void KVirtualBGRenderer::screenDone(int _desk, int _screen) +{ + Q_UNUSED(_desk); + Q_UNUSED(_screen); + + const KCrossBGRender * sender = dynamic_cast<const KCrossBGRender*>(this->sender()); + int screen = m_renderer.find(sender); + if (screen == -1) + //?? + return; + + m_bFinished[screen] = true; + + + if (m_pPixmap) + { + // There's more than one renderer, so we are drawing each output to our own pixmap + + TQRect overallGeometry; + for (int i=0; i < TDEApplication::desktop()->numScreens(); ++i) { + overallGeometry |= TDEApplication::desktop()->screenGeometry(i); + } + + TQPoint drawPos = TDEApplication::desktop()->screenGeometry(screen).topLeft() - overallGeometry.topLeft(); + drawPos.setX( int(drawPos.x() * m_scaleX) ); + drawPos.setY( int(drawPos.y() * m_scaleY) ); + + TQPixmap source = m_renderer[screen]->pixmap(); + TQSize renderSize = this->renderSize(screen); + renderSize.setWidth( int(renderSize.width() * m_scaleX) ); + renderSize.setHeight( int(renderSize.height() * m_scaleY) ); + + TQPainter p(m_pPixmap); + + if (renderSize == source.size()) + p.drawPixmap( drawPos, source ); + + else + p.drawTiledPixmap( drawPos.x(), drawPos.y(), renderSize.width(), renderSize.height(), source ); + + p.end(); + } + + for (unsigned i=0; i<m_bFinished.size(); ++i) + { + if (!m_bFinished[i]) + return; + } + + emit imageDone(m_desk); +} + + +void KVirtualBGRenderer::start() +{ + if (m_pPixmap) + { + delete m_pPixmap; + m_pPixmap = 0l; + } + + if (m_numRenderers > 1) + { + m_pPixmap = new TQPixmap(m_size); + // If are screen sizes do not properly tile the overall virtual screen + // size, then we want the untiled parts to be black for use in desktop + // previews, etc + m_pPixmap->fill(Qt::black); + } + + m_bFinished.fill(false); + for (unsigned i=0; i<m_numRenderers; ++i) + m_renderer[i]->start(); +} + + +void KVirtualBGRenderer::stop() +{ + for (unsigned i=0; i<m_numRenderers; ++i) + m_renderer[i]->stop(); +} + + +void KVirtualBGRenderer::cleanup() +{ + m_bFinished.fill(false); + + for (unsigned i=0; i<m_numRenderers; ++i) + m_renderer[i]->cleanup(); + + delete m_pPixmap; + m_pPixmap = 0l; +} + +void KVirtualBGRenderer::saveCacheFile() +{ + for (unsigned i=0; i<m_numRenderers; ++i) + m_renderer[i]->saveCacheFile(); +} + +void KVirtualBGRenderer::enableTiling( bool enable ) +{ + for (unsigned i=0; i<m_numRenderers; ++i) + m_renderer[i]->enableTiling( enable ); +} + +//END class KVirtualBGRenderer + + +#include "bgrender.moc" diff --git a/kcontrol/background/bgrender.h b/kcontrol/background/bgrender.h new file mode 100644 index 000000000..5ab1cc6c3 --- /dev/null +++ b/kcontrol/background/bgrender.h @@ -0,0 +1,183 @@ +/* vi: ts=8 sts=4 sw=4 + * kate: space-indent on; tab-width 8; indent-width 4; indent-mode cstyle; + * + * This file is part of the KDE project, module kdesktop. + * Copyright (C) 1999 Geert Jansen <[email protected]> + * + * You can Freely distribute this program under the GNU Library General + * Public License. See the file "COPYING.LIB" for the exact licensing terms. + */ + +#ifndef BGRender_h_Included +#define BGRender_h_Included + +#include <tqobject.h> +#include <tqptrvector.h> +#include <tqimage.h> +#include <tqpixmap.h> + +#include "bgsettings.h" + +class TQSize; +class TQRect; +class TQString; +class TQTimer; + +class TDEConfig; +class TDEProcess; +class KTempFile; +class KShellProcess; +class TDEStandardDirs; +class KCrossBGRender; + +/** + * This class renders a desktop background to a TQImage. The operation is + * asynchronous: connect to the signal imageDone() to find out when the + * rendering is finished. It also has support for preview images, like + * the monitor in kcmdisplay. + */ +class KBackgroundRenderer: + public TQObject, + public KBackgroundSettings +{ + Q_OBJECT + +public: + KBackgroundRenderer(int desk, int screen, bool drawBackgroundPerScreen, TDEConfig *config=0); + ~KBackgroundRenderer(); + + void load(int desk, int screen, bool drawBackgroundPerScreen, bool reparseConfig=true); + + void setPreview(const TQSize &size); + void setSize(const TQSize &size); + + TQPixmap pixmap(); + TQImage image(); + bool isActive() { return m_State & Rendering; } + void cleanup(); + void saveCacheFile(); + void enableTiling( bool enable ) { m_TilingEnabled = enable; } + +public slots: + void start(bool enableBusyCursor = false); + void stop(); + void desktopResized(); + +signals: + void imageDone(int desk, int screen); + void programFailure(int desk, int exitstatus); //Guaranteed either programFailure or + void programSuccess(int desk); //programSuccess is emitted after imageDone + +private slots: + void slotBackgroundDone(TDEProcess *); + void render(); + void done(); + +private: + enum { Error, Wait, WaitUpdate, Done }; + enum { Rendering = 1, InitCheck = 2, + BackgroundStarted = 4, BackgroundDone = 8, + WallpaperStarted = 0x10, WallpaperDone = 0x20, + AllDone = 0x40 }; + + TQString buildCommand(); + void createTempFile(); + void tile(TQImage& dst, TQRect rect, const TQImage& src); + void blend(TQImage& dst, TQRect dr, const TQImage& src, TQPoint soffs = TQPoint(0, 0), int blendFactor=100); + + void wallpaperBlend(); + void fastWallpaperBlend(); + void fullWallpaperBlend(); + + int doBackground(bool quit=false); + int doWallpaper(bool quit=false); + void setBusyCursor(bool isBusy); + TQString cacheFileName(); + bool useCacheFile() const; + bool canTile() const; + + bool m_isBusyCursor; + bool m_enableBusyCursor; + bool m_bPreview; + int m_State; + bool m_Cached; + bool m_TilingEnabled; + + KTempFile* m_Tempfile; + TQSize m_Size, m_rSize; + TQRect m_WallpaperRect; + TQImage m_Image, m_Background, m_Wallpaper; + TQPixmap m_Pixmap; + TQTimer *m_pTimer; + + TDEStandardDirs *m_pDirs; + KShellProcess *m_pProc; + +}; + +/** + * In xinerama mode, each screen is rendered seperately by KBackgroundRenderer. + * This class controls a set of renderers for a desktop, and coallates the + * images. Usage is similar to KBackgroundRenderer: connect to the imageDone + * signal. + */ +class KVirtualBGRenderer : public QObject +{ + Q_OBJECT +public: + KVirtualBGRenderer(int desk, TDEConfig *config=0l); + ~KVirtualBGRenderer(); + + KCrossBGRender * renderer(unsigned screen); + unsigned numRenderers() const { return m_numRenderers; } + + TQPixmap pixmap(); + + void setPreview(const TQSize & size); + + bool needProgramUpdate(); + void programUpdate(); + + bool needWallpaperChange(); + void changeWallpaper(); + + int hash(); + bool isActive(); + void setEnabled( bool enable ); + void desktopResized(); + + void load(int desk, bool reparseConfig=true); + void start(); + void stop(); + void cleanup(); + void saveCacheFile(); + void enableTiling( bool enable ); + +signals: + void imageDone(int desk); + +private slots: + void screenDone(int desk, int screen); + +private: + TQSize renderSize(int screen); // the size the renderer should be + void initRenderers(); + + TDEConfig *m_pConfig; + float m_scaleX; + float m_scaleY; + int m_desk; + unsigned m_numRenderers; + bool m_bDrawBackgroundPerScreen; + bool m_bCommonScreen; + bool m_bDeleteConfig; + TQSize m_size; + + TQMemArray<bool> m_bFinished; + TQPtrVector<KCrossBGRender> m_renderer; + TQPixmap *m_pPixmap; +}; + + +#endif // BGRender_h_Included + diff --git a/kcontrol/background/bgsettings.cpp b/kcontrol/background/bgsettings.cpp new file mode 100644 index 000000000..1ee452ac2 --- /dev/null +++ b/kcontrol/background/bgsettings.cpp @@ -0,0 +1,1281 @@ +/* vi: ts=8 sts=4 sw=4 + * kate: space-indent on; indent-width 4; indent-mode cstyle; + * + * This file is part of the KDE project, module kdesktop. + * Copyright (C) 1999 Geert Jansen <[email protected]> + * + * You can Freely distribute this program under the GNU Library General + * Public License. See the file "COPYING.LIB" for the exact licensing terms. + */ + +#include <netwm.h> +#include <time.h> +#include <stdlib.h> +#include <unistd.h> + +// Clean up after X.h/Xlib.h +#undef Bool +#undef Unsorted + +#include <tqdir.h> +#include <tqpixmap.h> + +#include <dcopclient.h> +#include <tdeapplication.h> +#include <kdebug.h> +#include <tdeglobalsettings.h> +#include <ksimpleconfig.h> +#include <kstandarddirs.h> +#include <krandomsequence.h> +#include <konq_defaults.h> + +#include "bgdefaults.h" +#include "bghash.h" +#include "bgsettings.h" + + +/**** KBackgroundPattern ****/ + + +KBackgroundPattern::KBackgroundPattern(TQString name) +{ + dirty = false; + hashdirty = true; + + m_pDirs = TDEGlobal::dirs(); + m_pDirs->addResourceType("dtop_pattern", m_pDirs->kde_default("data") + + "kdesktop/patterns"); + m_pConfig = 0L; + + m_Name = name; + if (m_Name.isEmpty()) + return; + + init(); + readSettings(); +} + + +KBackgroundPattern::~KBackgroundPattern() +{ + delete m_pConfig; +} + +void KBackgroundPattern::copyConfig(const KBackgroundPattern *settings) +{ + dirty = hashdirty = true; + m_Name = settings->m_Name; + m_Comment = settings->m_Comment; + m_Pattern = settings->m_Pattern; + m_File = settings->m_File; +} + +void KBackgroundPattern::load(TQString name) +{ + m_Name = name; + init(); + readSettings(); +} + + +void KBackgroundPattern::init(bool force_rw) +{ + delete m_pConfig; + + m_File = m_pDirs->findResource("dtop_pattern", m_Name + ".desktop"); + if (force_rw || m_File.isEmpty()) { + m_File = m_pDirs->saveLocation("dtop_pattern") + m_Name + ".desktop"; + m_pConfig = new KSimpleConfig(m_File); + } else + m_pConfig = new KSimpleConfig(m_File); + + m_pConfig->setGroup("KDE Desktop Pattern"); + + TQFileInfo fi(m_File); + m_bReadOnly = !fi.isWritable(); +} + + +void KBackgroundPattern::setComment(const TQString &comment) +{ + if (m_Comment == comment) + return; + dirty = true; + m_Comment = comment; +} + + +void KBackgroundPattern::setPattern(TQString pattern) +{ + if (m_Pattern == pattern) + return; + dirty = hashdirty = true; + m_Pattern = pattern; +} + + +void KBackgroundPattern::readSettings() +{ + dirty = false; + hashdirty = true; + + m_Pattern = m_pConfig->readPathEntry("File"); + m_Comment = m_pConfig->readEntry("Comment"); + if (m_Comment.isEmpty()) + m_Comment = m_File.mid(m_File.findRev('/')+1); +} + + +void KBackgroundPattern::writeSettings() +{ + if (!dirty) + return; + if (m_bReadOnly) + init(true); + + if ( !m_pConfig ) + return; // better safe than sorry + + m_pConfig->writePathEntry("File", m_Pattern); + m_pConfig->writeEntry("Comment", m_Comment); + m_pConfig->sync(); + dirty = false; +} + + +bool KBackgroundPattern::isAvailable() +{ + if (m_Pattern.isEmpty()) + return false; + TQString file = m_Pattern; + if (file.at(0) != '/') + file = m_pDirs->findResource("dtop_pattern", file); + TQFileInfo fi(file); + return (fi.exists()); +} + + +bool KBackgroundPattern::remove() +{ + if (m_bReadOnly) + return false; + return !unlink(TQFile::encodeName(m_File)); +} + + +TQString KBackgroundPattern::fingerprint() +{ + return m_File; +} + + +int KBackgroundPattern::hash() +{ + if (hashdirty) { + m_Hash = TQHash(fingerprint()); + hashdirty = false; + } + return m_Hash; +} + + +/* static */ +TQStringList KBackgroundPattern::list() +{ + TDEStandardDirs *dirs = TDEGlobal::dirs(); + dirs->addResourceType("dtop_pattern", dirs->kde_default("data") + + "kdesktop/patterns"); + TQStringList lst = dirs->findAllResources("dtop_pattern", "*.desktop", + false, true); + TQStringList::Iterator it; + for (it=lst.begin(); it!=lst.end(); ++it) { + // Strip path and suffix + int pos = (*it).findRev('/'); + if (pos != -1) + (*it) = (*it).mid(pos+1); + pos = (*it).findRev('.'); + if (pos != -1) + (*it) = (*it).left(pos); + } + return lst; +} + + +/**** KBackgroundProgram ****/ + + +KBackgroundProgram::KBackgroundProgram(TQString name) +{ + dirty = false; + hashdirty = true; + + m_pDirs = TDEGlobal::dirs(); + m_pDirs->addResourceType("dtop_program", m_pDirs->kde_default("data") + + "kdesktop/programs"); + m_pConfig = 0L; + + // prevent updates when just constructed. + m_LastChange = (int) time(0L); + + m_Name = name; + if (m_Name.isEmpty()) + return; + + init(); + readSettings(); +} + + +KBackgroundProgram::~KBackgroundProgram() +{ + delete m_pConfig; +} + +void KBackgroundProgram::copyConfig(const KBackgroundProgram *settings) +{ + dirty = hashdirty = true; + m_Refresh = settings->m_Refresh; + m_LastChange = settings->m_LastChange; + m_Name = settings->m_Name; + m_Command = settings->m_Command; + m_PreviewCommand = settings->m_PreviewCommand; + m_Comment = settings->m_Comment; + m_Executable = settings->m_Executable; + m_File = settings->m_File; +} + + +void KBackgroundProgram::init(bool force_rw) +{ + delete m_pConfig; + + m_File = m_pDirs->findResource("dtop_program", m_Name + ".desktop"); + if (force_rw || m_File.isEmpty()) { + m_File = m_pDirs->saveLocation("dtop_program") + m_Name + ".desktop"; + m_pConfig = new KSimpleConfig(m_File); + m_bReadOnly = false; + } else { + m_pConfig = new KSimpleConfig(m_File); + m_bReadOnly = (m_File != locateLocal("dtop_program", m_Name + ".desktop")); + } + m_pConfig->setGroup("KDE Desktop Program"); +} + + +void KBackgroundProgram::load(const TQString &name) +{ + m_Name = name; + init(); + readSettings(); +} + + +void KBackgroundProgram::setComment(const TQString &comment) +{ + if (m_Comment == comment) + return; + dirty = true; + m_Comment = comment; +} + + +void KBackgroundProgram::setExecutable(const TQString &executable) +{ + if (m_Executable == executable) + return; + dirty = true; + m_Executable = executable; +} + + +void KBackgroundProgram::setCommand(const TQString &command) +{ + if (m_Command == command) + return; + dirty = hashdirty = true; + m_Command = command; +} + + +void KBackgroundProgram::setPreviewCommand(const TQString &command) +{ + if (m_PreviewCommand == command) + return; + dirty = true; + m_PreviewCommand = command; +} + + +void KBackgroundProgram::setRefresh(int refresh) +{ + if (m_Refresh == refresh) + return; + dirty = hashdirty = true; + m_Refresh = refresh; +} + + +void KBackgroundProgram::readSettings() +{ + dirty = false; + hashdirty = true; + + m_Comment = m_pConfig->readEntry("Comment"); + m_Executable = m_pConfig->readPathEntry("Executable"); + m_Command = m_pConfig->readPathEntry("Command"); + m_PreviewCommand = m_pConfig->readPathEntry("PreviewCommand", m_Command); + m_Refresh = m_pConfig->readNumEntry("Refresh", 300); +} + + +void KBackgroundProgram::writeSettings() +{ + if (!dirty) + return; + if (m_bReadOnly) + init(true); + + if ( !m_pConfig ) + return; // better safe than sorry + + m_pConfig->writeEntry("Comment", m_Comment); + m_pConfig->writePathEntry("Executable", m_Executable); + m_pConfig->writePathEntry("Command", m_Command); + m_pConfig->writeEntry("PreviewCommand", m_PreviewCommand); + m_pConfig->writeEntry("Refresh", m_Refresh); + m_pConfig->sync(); + dirty = false; +} + + +bool KBackgroundProgram::isAvailable() +{ + return !m_pDirs->findExe(m_Executable).isEmpty(); +} + + +bool KBackgroundProgram::remove() +{ + if (m_bReadOnly) + return false; + return !unlink(TQFile::encodeName(m_File)); +} + + +bool KBackgroundProgram::needUpdate() +{ + return (m_LastChange + 60*m_Refresh <= time(0L)); +} + + +void KBackgroundProgram::update() +{ + m_LastChange = (int) time(0L); +} + + +TQString KBackgroundProgram::fingerprint() +{ + return TQString("co:%1;re:%2").arg(m_Command).arg(m_Refresh); +} + + +int KBackgroundProgram::hash() +{ + if (hashdirty) { + m_Hash = TQHash(fingerprint()); + hashdirty = false; + } + return m_Hash; +} + + +/* static */ +TQStringList KBackgroundProgram::list() +{ + TDEStandardDirs *dirs = TDEGlobal::dirs(); + dirs->addResourceType("dtop_program", dirs->kde_default("data") + + "kdesktop/programs"); + TQStringList lst = dirs->findAllResources("dtop_program", "*.desktop", + false, true); + TQStringList::Iterator it; + for (it=lst.begin(); it!=lst.end(); ++it) { + // Strip path and suffix + int pos = (*it).findRev('/'); + if (pos != -1) + (*it) = (*it).mid(pos+1); + pos = (*it).findRev('.'); + if (pos != -1) + (*it) = (*it).left(pos); + } + return lst; +} + + +/**** KBackgroundSettings ****/ + + +KBackgroundSettings::KBackgroundSettings(int desk, int screen, bool drawBackgroundPerScreen, TDEConfig *config) + : KBackgroundPattern(), + KBackgroundProgram() +{ + dirty = false; hashdirty = true; + m_bDrawBackgroundPerScreen = drawBackgroundPerScreen; + m_Desk = desk; + m_Screen = screen; + m_bEnabled = true; + + // Default values. + defColorA = _defColorA; + defColorB = _defColorB; + if (TQPixmap::defaultDepth() > 8) + defBackgroundMode = _defBackgroundMode; + else + defBackgroundMode = Flat; + defWallpaperMode = _defWallpaperMode; + defMultiMode = _defMultiMode; + defBlendMode = _defBlendMode; + defBlendBalance = _defBlendBalance; + defReverseBlending = _defReverseBlending; + defCrossFadeBg = _defCrossFadeBg; + + m_MinOptimizationDepth = _defMinOptimizationDepth; + m_bShm = _defShm; + + // Background modes + #define ADD_STRING(ID) m_BMMap[#ID] = ID; m_BMRevMap[ID] = (char *) #ID; + ADD_STRING(Flat) + ADD_STRING(Pattern) + ADD_STRING(Program) + ADD_STRING(HorizontalGradient) + ADD_STRING(VerticalGradient) + ADD_STRING(PyramidGradient) + ADD_STRING(PipeCrossGradient) + ADD_STRING(EllipticGradient) + #undef ADD_STRING + + // Blend modes + #define ADD_STRING(ID) m_BlMMap[#ID] = ID; m_BlMRevMap[ID] = (char *) #ID; + ADD_STRING(NoBlending) + ADD_STRING(FlatBlending) + ADD_STRING(HorizontalBlending) + ADD_STRING(VerticalBlending) + ADD_STRING(PyramidBlending) + ADD_STRING(PipeCrossBlending) + ADD_STRING(EllipticBlending) + ADD_STRING(IntensityBlending) + ADD_STRING(SaturateBlending) + ADD_STRING(ContrastBlending) + ADD_STRING(HueShiftBlending) + #undef ADD_STRING + + // Wallpaper modes + #define ADD_STRING(ID) m_WMMap[#ID] = ID; m_WMRevMap[ID] = (char *) #ID; + ADD_STRING(NoWallpaper) + ADD_STRING(Centred) + ADD_STRING(Tiled) + ADD_STRING(CenterTiled) + ADD_STRING(CentredMaxpect) + ADD_STRING(TiledMaxpect) + ADD_STRING(Scaled) + ADD_STRING(CentredAutoFit) + ADD_STRING(ScaleAndCrop) + #undef ADD_STRING + + // Multiple wallpaper modes + #define ADD_STRING(ID) m_MMMap[#ID] = ID; m_MMRevMap[ID] = (char *) #ID; + ADD_STRING(NoMulti) + ADD_STRING(InOrder) + ADD_STRING(Random) + ADD_STRING(NoMultiRandom) + #undef ADD_STRING + + m_pDirs = TDEGlobal::dirs(); + + if (!config) { + int screen_number = 0; + if (tqt_xdisplay()) + screen_number = DefaultScreen(tqt_xdisplay()); + TQCString configname; + if (screen_number == 0) + configname = "kdesktoprc"; + else + configname.sprintf("kdesktop-screen-%drc", screen_number); + + m_pConfig = new TDEConfig(configname, false, false); + m_bDeleteConfig = true; + } else { + m_pConfig = config; + m_bDeleteConfig = false; + } + + if (m_Desk == -1) + return; + + readSettings(); +} + + +KBackgroundSettings::~KBackgroundSettings() +{ + if (m_bDeleteConfig) + delete m_pConfig; +} + +void KBackgroundSettings::copyConfig(const KBackgroundSettings *settings) +{ + dirty = true; + hashdirty = true; + + m_ColorA = settings->m_ColorA; + m_ColorB = settings->m_ColorB; + m_Wallpaper = settings->m_Wallpaper; + m_WallpaperList = settings->m_WallpaperList; + m_WallpaperFiles = settings->m_WallpaperFiles; + + m_BackgroundMode = settings->m_BackgroundMode; + m_WallpaperMode = settings->m_WallpaperMode; + m_BlendMode = settings->m_BlendMode; + m_BlendBalance = settings->m_BlendBalance; + m_ReverseBlending = settings->m_ReverseBlending; + m_CrossFadeBg = settings->m_CrossFadeBg; + m_MinOptimizationDepth = settings->m_MinOptimizationDepth; + m_bShm = settings->m_bShm; + m_MultiMode = settings->m_MultiMode; + m_Interval = settings->m_Interval; + m_CurrentWallpaper = settings->m_CurrentWallpaper; + m_CurrentWallpaperName = settings->m_CurrentWallpaperName; + + KBackgroundPattern::copyConfig(settings); + KBackgroundProgram::copyConfig(settings); +} + + +void KBackgroundSettings::load(int desk, int screen, bool drawBackgroundPerScreen, bool reparseConfig) +{ + m_Desk = desk; + m_Screen = screen; + m_bDrawBackgroundPerScreen = drawBackgroundPerScreen; + readSettings(reparseConfig); +} + + +void KBackgroundSettings::setColorA(const TQColor& color) +{ + if (m_ColorA == color) + return; + dirty = hashdirty = true; + m_ColorA = color; +} + + +void KBackgroundSettings::setColorB(const TQColor& color) +{ + if (m_ColorB == color) + return; + dirty = hashdirty = true; + m_ColorB = color; +} + + +void KBackgroundSettings::setPatternName(TQString name) +{ + int ohash = KBackgroundPattern::hash(); + KBackgroundPattern::load(name); + if (ohash == KBackgroundPattern::hash()) + return; + + dirty = hashdirty = true; + return; +} + + +void KBackgroundSettings::setProgram(TQString name) +{ + int ohash = KBackgroundProgram::hash(); + KBackgroundProgram::load(name); + if (ohash == KBackgroundProgram::hash()) + return; + + dirty = hashdirty = true; + return; +} + + +void KBackgroundSettings::setBackgroundMode(int mode) +{ + if (m_BackgroundMode == mode) + return; + dirty = hashdirty = true; + m_BackgroundMode = mode; +} + +void KBackgroundSettings::setBlendMode(int mode) +{ + if (m_BlendMode == mode) + return; + dirty = hashdirty = true; + m_BlendMode = mode; +} + +void KBackgroundSettings::setBlendBalance(int value) +{ + if (m_BlendBalance == value) + return; + dirty = hashdirty = true; + m_BlendBalance = value; +} + +void KBackgroundSettings::setReverseBlending(bool value) +{ + if (m_ReverseBlending == value) + return; + dirty = hashdirty = true; + m_ReverseBlending = value; +} + + +void KBackgroundSettings::setCrossFadeBg(bool value) +{ + if (m_CrossFadeBg == value) + return; + dirty = hashdirty = true; + m_CrossFadeBg = value; +} + + +void KBackgroundSettings::setWallpaper(TQString wallpaper) +{ + dirty = hashdirty = true; + m_Wallpaper = wallpaper; +} + + +void KBackgroundSettings::setWallpaperMode(int mode) +{ + if (m_WallpaperMode == mode) + return; + dirty = hashdirty = true; + m_WallpaperMode = mode; +} + + +void KBackgroundSettings::setWallpaperList(TQStringList list) +{ + TDEStandardDirs *d = TDEGlobal::dirs(); + if (m_WallpaperList == list) + return; + + dirty = hashdirty = true; + m_WallpaperList.clear(); + for(TQStringList::ConstIterator it = list.begin(); + it != list.end(); ++it) + { + TQString rpath = d->relativeLocation("wallpaper", *it); + m_WallpaperList.append( !rpath.isEmpty() ? rpath : *it ); + } + updateWallpaperFiles(); + // Try to keep the current wallpaper (-1 to set position to one before it) + m_CurrentWallpaper = m_WallpaperFiles.findIndex(m_CurrentWallpaperName) - 1; + changeWallpaper(m_CurrentWallpaper < 0); +} + + +void KBackgroundSettings::setWallpaperChangeInterval(int interval) +{ + if (m_Interval == interval) + return; + dirty = hashdirty = true; + m_Interval = interval; +} + + +void KBackgroundSettings::setMultiWallpaperMode(int mode) +{ + if (m_MultiMode == mode) + return; + dirty = hashdirty = true; + m_MultiMode = mode; + changeWallpaper(true); +} + + +void KBackgroundSettings::setMinOptimizationDepth(int mode) +{ + if (m_MinOptimizationDepth == mode) + return; + dirty = hashdirty = true; + m_MinOptimizationDepth = mode; +} + +bool KBackgroundSettings::optimize() const +{ + switch( m_MinOptimizationDepth ) + { + case AlwaysOpt : + return true; + case Opt16bpp : + return TQPixmap::defaultDepth() >= 16; + case Opt15bpp : + return TQPixmap::defaultDepth() >= 15; + case NeverOpt : + default : + return false; + } +} + +void KBackgroundSettings::setUseShm(bool use) +{ + if (m_bShm == use) + return; + dirty = hashdirty = true; + m_bShm = use; +} + +TQString KBackgroundSettings::configGroupName() const +{ + TQString screenName; + if (m_bDrawBackgroundPerScreen) + screenName = TQString("Screen%1").arg(TQString::number(m_Screen)); + return TQString("Desktop%1%2").arg(m_Desk).arg(screenName); +} + +void KBackgroundSettings::readSettings(bool reparse) +{ + if (reparse) + m_pConfig->reparseConfiguration(); + + m_pConfig->setGroup(configGroupName()); + + // Background mode (Flat, div. Gradients, Pattern or Program) + m_ColorA = m_pConfig->readColorEntry("Color1", &defColorA); + m_ColorB = m_pConfig->readColorEntry("Color2", &defColorB); + + TQString s = m_pConfig->readPathEntry("Pattern"); + if (!s.isEmpty()) + KBackgroundPattern::load(s); + + s = m_pConfig->readPathEntry("Program"); + if (!s.isEmpty()) + KBackgroundProgram::load(s); + + m_BackgroundMode = defBackgroundMode; + s = m_pConfig->readEntry("BackgroundMode", "invalid"); + + if (m_BMMap.contains(s)) { + int mode = m_BMMap[s]; + // consistency check + if ( ((mode != Pattern) && (mode != Program)) || + ((mode == Pattern) && !pattern().isEmpty()) || + ((mode == Program) && !command().isEmpty()) + ) + m_BackgroundMode = mode; + } + + m_BlendMode = defBlendMode; + s = m_pConfig->readEntry("BlendMode", "invalid"); + if (m_BlMMap.contains(s)) { + m_BlendMode = m_BlMMap[s]; + } + + m_BlendBalance = defBlendBalance; + int value = m_pConfig->readNumEntry( "BlendBalance", defBlendBalance); + if (value > -201 && value < 201) + m_BlendBalance = value; + + m_ReverseBlending = m_pConfig->readBoolEntry( "ReverseBlending", defReverseBlending); + + m_CrossFadeBg = m_pConfig->readBoolEntry( "CrossFadeBg", defCrossFadeBg); + + // Multiple wallpaper config + m_WallpaperList = m_pConfig->readPathListEntry("WallpaperList"); + + m_Interval = m_pConfig->readNumEntry("ChangeInterval", 60); + m_LastChange = m_pConfig->readNumEntry("LastChange", 0); + m_CurrentWallpaper = m_pConfig->readNumEntry("CurrentWallpaper", 0); + m_CurrentWallpaperName = m_pConfig->readEntry("CurrentWallpaperName"); + + m_MultiMode = defMultiMode; + s = m_pConfig->readEntry("MultiWallpaperMode"); + if (m_MMMap.contains(s)) { + int mode = m_MMMap[s]; + m_MultiMode = mode; + } + + updateWallpaperFiles(); + if( !m_CurrentWallpaperName.isEmpty()) + m_CurrentWallpaper = m_WallpaperFiles.findIndex(m_CurrentWallpaperName); + if(m_CurrentWallpaper < 0) + m_CurrentWallpaper = 0; + + // Wallpaper mode (NoWallpaper, div. tilings) + m_WallpaperMode = defWallpaperMode; + m_Wallpaper = m_pConfig->readPathEntry("Wallpaper"); + s = m_pConfig->readEntry("WallpaperMode", "invalid"); + if (m_WMMap.contains(s)) { + int mode = m_WMMap[s]; + // consistency check. + if ((mode == NoWallpaper) || !m_Wallpaper.isEmpty() || (m_MultiMode == InOrder || m_MultiMode == Random)) + m_WallpaperMode = mode; + } + + m_MinOptimizationDepth = m_pConfig->readNumEntry( "MinOptimizationDepth", + _defMinOptimizationDepth ); + m_bShm = m_pConfig->readBoolEntry( "UseSHM", _defShm ); + + dirty = reparse; hashdirty = true; +} + + +void KBackgroundSettings::writeSettings() +{ + KBackgroundPattern::writeSettings(); + KBackgroundProgram::writeSettings(); + + if (!dirty) + return; + + m_pConfig->setGroup(configGroupName()); + m_pConfig->writeEntry("Color1", m_ColorA); + m_pConfig->writeEntry("Color2", m_ColorB); + m_pConfig->writePathEntry("Pattern", KBackgroundPattern::name()); + m_pConfig->writeEntry("Program", KBackgroundProgram::name()); + m_pConfig->writeEntry("BackgroundMode", m_BMRevMap[m_BackgroundMode]); + m_pConfig->writePathEntry("Wallpaper", m_Wallpaper); + m_pConfig->writeEntry("WallpaperMode", m_WMRevMap[m_WallpaperMode]); + m_pConfig->writeEntry("MultiWallpaperMode", m_MMRevMap[m_MultiMode]); + m_pConfig->writeEntry("BlendMode", m_BlMRevMap[m_BlendMode]); + m_pConfig->writeEntry("BlendBalance", m_BlendBalance); + m_pConfig->writeEntry("ReverseBlending", m_ReverseBlending); + m_pConfig->writeEntry("CrossFadeBg", m_CrossFadeBg); + m_pConfig->writeEntry("MinOptimizationDepth", m_MinOptimizationDepth); + m_pConfig->writeEntry("UseSHM", m_bShm); + + m_pConfig->writePathEntry("WallpaperList", m_WallpaperList); + m_pConfig->writeEntry("ChangeInterval", m_Interval); + m_pConfig->writeEntry("LastChange", m_LastChange); + m_pConfig->deleteEntry("CurrentWallpaper"); // obsolete, remember name + m_pConfig->writeEntry("CurrentWallpaperName", m_CurrentWallpaperName); + + m_pConfig->sync(); + + dirty = false; +} + +/* + * (re)Build m_WallpaperFiles from m_WallpaperList + */ +void KBackgroundSettings::updateWallpaperFiles() +{ + TQStringList::Iterator it; + m_WallpaperFiles.clear(); + for (it=m_WallpaperList.begin(); it!=m_WallpaperList.end(); ++it) { + TQString file = locate("wallpaper", *it); + if (file.isEmpty()) + continue; + TQFileInfo fi(file); + if (!fi.exists()) + continue; + if (fi.isFile() && fi.isReadable()) + m_WallpaperFiles.append(file); + if (fi.isDir()) { + TQDir dir(file); + TQStringList lst = dir.entryList(TQDir::Files | TQDir::Readable); + TQStringList::Iterator it; + for (it=lst.begin(); it!=lst.end(); ++it) + { + file = dir.absFilePath(*it); + TQFileInfo fi(file); + if (fi.isFile() && fi.isReadable()) + m_WallpaperFiles.append(file); + } + } + } + + if (m_MultiMode == Random) + randomizeWallpaperFiles(); +} + +// Randomize the m_WallpaperFiles in a non-repeating method. +void KBackgroundSettings::randomizeWallpaperFiles() +{ + if (m_WallpaperFiles.count() < 4) + return; + + KRandomSequence rseq; + TQStringList tmpList = m_WallpaperFiles; + TQStringList randomList; + randomList.append(tmpList.front()); + tmpList.pop_front(); + while(tmpList.count()) + { + randomList.insert(randomList.at( + rseq.getLong(randomList.count()+1)), + 1, tmpList.front()); + + tmpList.pop_front(); + } + m_WallpaperFiles = randomList; +} + +TQStringList KBackgroundSettings::wallpaperList() const +{ + if ( m_WallpaperMode == NoWallpaper ) + return TQStringList(); + if ( m_MultiMode == NoMulti || m_MultiMode == NoMultiRandom ) + return TQStringList(m_Wallpaper); + return m_WallpaperList; +} + +TQStringList KBackgroundSettings::wallpaperFiles() const +{ + if ( m_WallpaperMode == NoWallpaper ) + return TQStringList(); + if ( m_MultiMode == NoMulti || m_MultiMode == NoMultiRandom ) + return TQStringList(m_Wallpaper); + return m_WallpaperFiles; +} + +/* + * Select a new wallpaper from the list. + */ +void KBackgroundSettings::changeWallpaper(bool init) +{ + if (m_WallpaperFiles.count() == 0) { + if( init ) { + m_CurrentWallpaper = 0; + m_CurrentWallpaperName = TQString(); + } + return; + } + + switch (m_MultiMode) { + case InOrder: + m_CurrentWallpaper++; + if (init || (m_CurrentWallpaper >= (int) m_WallpaperFiles.count())) + m_CurrentWallpaper = 0; + break; + + case Random: + // Random: m_WallpaperFiles is randomized in a non-repeating + // method. Hence we just increment the index. + m_CurrentWallpaper++; + if (init || (m_CurrentWallpaper >= (int) m_WallpaperFiles.count())) { + m_CurrentWallpaper = 0; + randomizeWallpaperFiles(); // Get a new random-ordered list. + } + break; + default: + break; + } + + m_CurrentWallpaperName = m_WallpaperFiles[ m_CurrentWallpaper ]; + m_LastChange = (int) time(0L); + m_pConfig->setGroup(configGroupName()); + m_pConfig->deleteEntry("CurrentWallpaper"); // obsolete, remember name + m_pConfig->writeEntry("CurrentWallpaperName", m_CurrentWallpaperName); + m_pConfig->writeEntry("LastChange", m_LastChange); + m_pConfig->sync(); + + hashdirty = true; +} + + +TQString KBackgroundSettings::currentWallpaper() const +{ + if ( m_WallpaperMode == NoWallpaper ) + return TQString::null; + if (m_MultiMode == NoMulti || m_MultiMode == NoMultiRandom) + return m_Wallpaper; + + if (m_CurrentWallpaper >= 0 && m_CurrentWallpaper < (int) m_WallpaperFiles.count()) + return m_WallpaperFiles[m_CurrentWallpaper]; + return TQString::null; +} + +bool KBackgroundSettings::discardCurrentWallpaper() +{ + if (m_MultiMode == NoMulti || m_MultiMode == NoMultiRandom) + { + return false; + } + m_WallpaperFiles.remove(m_WallpaperFiles.at(m_CurrentWallpaper)); + --m_CurrentWallpaper; + changeWallpaper(); + + return true; +} + + +bool KBackgroundSettings::needWallpaperChange() +{ + if (m_MultiMode == NoMulti || m_MultiMode == NoMultiRandom) + return false; + + return ((m_LastChange + 60*m_Interval) <= time(0L)); +} + + +/* + * Create a fingerprint string for this config. Be somewhat (overly) carefull + * that only a different final result will give a different fingerprint. + */ + +TQString KBackgroundSettings::fingerprint() +{ + TQString s = TQString("bm:%1;en:%2").arg(m_BackgroundMode).arg(m_bEnabled); + switch (m_BackgroundMode) { + case Flat: + s += TQString("ca:%1;").arg(m_ColorA.rgb()); + break; + case Program: + s += TQString("pr:%1;").arg(KBackgroundProgram::hash()); + break; + case Pattern: + s += TQString("ca:%1;cb:%2;pt:%3;").arg(m_ColorA.rgb()) + .arg(m_ColorB.rgb()).arg(KBackgroundPattern::hash()); + break; + default: + s += TQString("ca:%1;cb:%2;").arg(m_ColorA.rgb()).arg(m_ColorB.rgb()); + break; + } + + s += TQString("wm:%1;").arg(m_WallpaperMode); + if (m_WallpaperMode != NoWallpaper) + { + TQ_UINT32 rh = TDEGlobal::dirs()->calcResourceHash("wallpaper", currentWallpaper(), false); + s += TQString("wp:%2:%1;").arg(rh).arg(currentWallpaper()); + + } + s += TQString("blm:%1;").arg(m_BlendMode); + if (m_BlendMode != NoBlending) { + s += TQString("blb:%1;").arg(m_BlendBalance); + s += TQString("rbl:%1;").arg(int(m_ReverseBlending)); + } + s += TQString::number( m_bShm ); + s += TQString::number( m_MinOptimizationDepth ); + + return s; +} + + +int KBackgroundSettings::hash() +{ + if (hashdirty) { + m_Hash = TQHash(fingerprint()); + hashdirty = false; + } + return m_Hash; +} + +void KBackgroundSettings::setEnabled(const bool enable) +{ + if (m_bEnabled == enable) + return; + + m_bEnabled= enable; + hashdirty = true; +} + +/**** TDEGlobalBackgroundSettings ****/ + +TDEGlobalBackgroundSettings::TDEGlobalBackgroundSettings(TDEConfig *_config) +{ + m_pConfig = _config; + + readSettings(); +} + + +TQString TDEGlobalBackgroundSettings::deskName(int desk) +{ + return m_Names[desk]; +} + + +/* +void TDEGlobalBackgroundSettings::setDeskName(int desk, TQString name) +{ + if (name == m_Names[desk]) + return; + dirty = true; + m_Names[desk] = name; +} +*/ + + +void TDEGlobalBackgroundSettings::setCacheSize(int size) +{ + if (size == m_CacheSize) + return; + dirty = true; + m_CacheSize = size; +} + + +void TDEGlobalBackgroundSettings::setLimitCache(bool limit) +{ + if (limit == m_bLimitCache) + return; + dirty = true; + m_bLimitCache = limit; +} + + +bool TDEGlobalBackgroundSettings::drawBackgroundPerScreen(int desk) const +{ + if ( desk > int(m_bDrawBackgroundPerScreen.size()) ) + return _defDrawBackgroundPerScreen; + return m_bDrawBackgroundPerScreen[desk]; +} + + +void TDEGlobalBackgroundSettings::setDrawBackgroundPerScreen(int desk, bool perScreen) +{ + if ( desk >= int(m_bDrawBackgroundPerScreen.size()) ) + return; + + if ( m_bDrawBackgroundPerScreen[desk] == perScreen ) + return; + + dirty = true; + m_bDrawBackgroundPerScreen[desk] = perScreen; +} + + +void TDEGlobalBackgroundSettings::setCommonScreenBackground(bool common) +{ + if (common == m_bCommonScreen) + return; + dirty = true; + m_bCommonScreen = common; +} + + +void TDEGlobalBackgroundSettings::setCommonDeskBackground(bool common) +{ + if (common == m_bCommonDesk) + return; + dirty = true; + m_bCommonDesk = common; +} + + +void TDEGlobalBackgroundSettings::setDockPanel(bool dock) +{ + if (dock == m_bDock) + return; + dirty = true; + m_bDock = dock; +} + + +void TDEGlobalBackgroundSettings::setExportBackground(bool _export) +{ + if (_export == m_bExport) + return; + dirty = true; + m_bExport = _export; +} + +void TDEGlobalBackgroundSettings::setTextColor(TQColor _color) +{ + if (_color == m_TextColor) + return; + dirty = true; + m_TextColor = _color; +} + +void TDEGlobalBackgroundSettings::setTextBackgroundColor(TQColor _color) +{ + if (_color == m_TextBackgroundColor) + return; + dirty = true; + m_TextBackgroundColor = _color; +} + +void TDEGlobalBackgroundSettings::setShadowEnabled(bool enabled) +{ + if (enabled == m_shadowEnabled) + return; + dirty = true; + m_shadowEnabled = enabled; +} + +void TDEGlobalBackgroundSettings::setTextLines(int lines) +{ + if (lines == m_textLines) + return; + dirty = true; + m_textLines = lines; +} + +void TDEGlobalBackgroundSettings::setTextWidth(int width) +{ + if (width == m_textWidth) + return; + dirty = true; + m_textWidth = width; +} + +void TDEGlobalBackgroundSettings::readSettings() +{ + m_pConfig->setGroup("Background Common"); + m_bCommonScreen = m_pConfig->readBoolEntry("CommonScreen", _defCommonScreen); + m_bCommonDesk = m_pConfig->readBoolEntry("CommonDesktop", _defCommonDesk); + m_bDock = m_pConfig->readBoolEntry("Dock", _defDock); + m_bExport = m_pConfig->readBoolEntry("Export", _defExport); + m_bLimitCache = m_pConfig->readBoolEntry("LimitCache", _defLimitCache); + m_CacheSize = m_pConfig->readNumEntry("CacheSize", _defCacheSize); + + m_Names.clear(); + NETRootInfo info( tqt_xdisplay(), NET::DesktopNames | NET::NumberOfDesktops ); + m_bDrawBackgroundPerScreen.resize(info.numberOfDesktops()); + for ( int i = 0 ; i < info.numberOfDesktops() ; ++i ) + m_bDrawBackgroundPerScreen[i] = m_pConfig->readBoolEntry( TQString("DrawBackgroundPerScreen_%1").arg(i), _defDrawBackgroundPerScreen ); + + m_TextColor = TDEGlobalSettings::textColor(); + m_pConfig->setGroup("FMSettings"); + m_TextColor = m_pConfig->readColorEntry("NormalTextColor", &m_TextColor); + m_TextBackgroundColor = m_pConfig->readColorEntry("ItemTextBackground"); + m_shadowEnabled = m_pConfig->readBoolEntry("ShadowEnabled", true); + m_textLines = m_pConfig->readNumEntry("TextHeight", DEFAULT_TEXTHEIGHT); + m_textWidth = m_pConfig->readNumEntry("TextWidth", DEFAULT_TEXTWIDTH); + + for ( int i = 0 ; i < info.numberOfDesktops() ; ++i ) + m_Names.append( TQString::fromUtf8(info.desktopName(i+1)) ); + + dirty = false; +} + +void TDEGlobalBackgroundSettings::writeSettings() +{ + if (!dirty) + return; + + m_pConfig->setGroup("Background Common"); + m_pConfig->writeEntry("CommonScreen", m_bCommonScreen); + m_pConfig->writeEntry("CommonDesktop", m_bCommonDesk); + m_pConfig->writeEntry("Dock", m_bDock); + m_pConfig->writeEntry("Export", m_bExport); + m_pConfig->writeEntry("LimitCache", m_bLimitCache); + m_pConfig->writeEntry("CacheSize", m_CacheSize); + + for ( unsigned i = 0 ; i < m_bDrawBackgroundPerScreen.size() ; ++i ) + m_pConfig->writeEntry(TQString("DrawBackgroundPerScreen_%1").arg(i), m_bDrawBackgroundPerScreen[i] ); + + m_pConfig->setGroup("FMSettings"); + m_pConfig->writeEntry("NormalTextColor", m_TextColor); + m_pConfig->writeEntry("ItemTextBackground", m_TextBackgroundColor); + m_pConfig->writeEntry("ShadowEnabled", m_shadowEnabled); + m_pConfig->writeEntry("TextHeight", m_textLines); + m_pConfig->writeEntry("TextWidth", m_textWidth); + + m_pConfig->sync(); + dirty = false; + + // tell kdesktop to get it's butt in gear and pick up the new settings + TQByteArray data; + kapp->dcopClient()->send("kdesktop", "KDesktopIface", "configure()", data); +} + diff --git a/kcontrol/background/bgsettings.h b/kcontrol/background/bgsettings.h new file mode 100644 index 000000000..a49873af2 --- /dev/null +++ b/kcontrol/background/bgsettings.h @@ -0,0 +1,376 @@ +/* vi: ts=8 sts=4 sw=4 + * kate: space-indent on; indent-width 4; indent-mode cstyle; + * + * This file is part of the KDE project, module kdesktop. + * Copyright (C) 1999 Geert Jansen <[email protected]> + * + * You can Freely distribute this program under the GNU Library General + * Public License. See the file "COPYING.LIB" for the exact licensing terms. + */ + +#ifndef __BGSETTINGS_H__ +#define __BGSETTINGS_H__ + + +#include <tqstringlist.h> +#include <tqcolor.h> +#include <tqvaluevector.h> + +template <class TQString, class T> class TQMap; +class TDEStandardDirs; +class KSimpleConfig; +class TDEConfig; +class TQString; +class TQImage; + +/** + * A class to manipulate/read/write/list KDE desktop patterns. + * + * A pattern is a raster image. An entry for earch pattern is + * stored as a .desktop file in $(datadir)/kdesktop/patterns. + */ +class KBackgroundPattern +{ +public: + KBackgroundPattern(TQString name=TQString::null); + ~KBackgroundPattern(); + + void copyConfig(const KBackgroundPattern*); + + TQString name() const { return m_Name; } + void load(TQString name); + + void setComment(const TQString &comment); + TQString comment() const {return m_Comment; } + + void setPattern(TQString file); + TQString pattern() const { return m_Pattern; } + + void readSettings(); + void writeSettings(); + + bool isAvailable(); + bool isGlobal()const { return m_bReadOnly; } + bool remove(); + + int hash(); + + static TQStringList list(); + +private: + void init(bool force_rw=false); + TQString fingerprint(); + + bool dirty, hashdirty; + bool m_bReadOnly; + int m_Hash; + TQString m_Name, m_Comment; + TQString m_Pattern, m_File; + TDEStandardDirs *m_pDirs; + KSimpleConfig *m_pConfig; +}; + + +/** + * A class to manipulate/read/write/list KDE desktop programs (a la xearth). + * + * A program is described by a string like: + * + * a_program -xres %x -yres %y -outfile %f + * + * Possible escape sequences: + * + * %x Horizontal resolution in pixels. + * %y Vertical resulution in pixels. + * %f Filename to dump to. + * + * An entry for each program is stored as a .desktop file in + * $(datadir)/kdesktop/programs. + */ +class KBackgroundProgram +{ +public: + KBackgroundProgram(TQString name=TQString::null); + ~KBackgroundProgram(); + + void copyConfig(const KBackgroundProgram*); + + TQString name()const { return m_Name; } + void load(const TQString & name); + + void setComment(const TQString &comment); + TQString comment()const { return m_Comment; } + + void setCommand(const TQString &command); + TQString command()const { return m_Command; } + + void setPreviewCommand(const TQString &command); + TQString previewCommand()const { return m_PreviewCommand; } + + void setRefresh(int refresh); + int refresh()const { return m_Refresh; } + + void setExecutable(const TQString &executable); + TQString executable()const { return m_Executable; } + + void readSettings(); + void writeSettings(); + + void update(); + bool needUpdate(); + + int hash(); + + bool isAvailable(); + bool isGlobal()const { return m_bReadOnly; } + bool remove(); + + static TQStringList list(); + +private: + void init(bool force_rw=false); + TQString fingerprint(); + + bool dirty, hashdirty; + bool m_bReadOnly; + int m_Refresh, m_Hash, m_LastChange; + TQString m_Name, m_Command; + TQString m_PreviewCommand, m_Comment; + TQString m_Executable, m_File; + TDEStandardDirs *m_pDirs; + KSimpleConfig *m_pConfig; +}; + + +/** + * KBackgroundSettings: A class to read/write/manipulate + * KDE desktop settings. + */ +class KBackgroundSettings + : public KBackgroundPattern, + public KBackgroundProgram +{ +public: + /** + * @param drawBackgroundPerScreen if false, then all screens (in xinerama + * mode) will be treated as one big display, and the "screen" paramater + * will be ignored. + */ + KBackgroundSettings(int desk, int screen, bool drawBackgroundPerScreen, TDEConfig *config); + ~KBackgroundSettings(); + + void copyConfig(const KBackgroundSettings*); + + bool drawBackgroundPerScreen() const { return m_bDrawBackgroundPerScreen; } + void setDrawBackgroundPerScreen(bool draw); + + int desk() const { return m_Desk; } + int screen() const { return m_Screen; } +// void load(int desk, int screen, bool drawBackgroundPerScreen, bool reparseConfig=true); + void load(int desk, int screen, bool drawBackgroundPerScreen, bool reparseConfig); + + void setColorA(const TQColor &color); + TQColor colorA() const { return m_ColorA; } + void setColorB(const TQColor &color); + TQColor colorB() const { return m_ColorB; } + + void setProgram(TQString program); + void setPatternName(TQString pattern); + + enum BackgroundMode { + Flat, Pattern, Program, + HorizontalGradient, VerticalGradient, PyramidGradient, + PipeCrossGradient, EllipticGradient, lastBackgroundMode + }; + void setBackgroundMode(int mode); + int backgroundMode() const { return m_BackgroundMode; } + + enum BlendMode { + NoBlending, FlatBlending, + HorizontalBlending, VerticalBlending, PyramidBlending, + PipeCrossBlending, EllipticBlending, + IntensityBlending, SaturateBlending, ContrastBlending, + HueShiftBlending, lastBlendMode + }; + void setBlendMode(int mode); + int blendMode() const { return m_BlendMode; } + + void setReverseBlending(bool value); + bool reverseBlending() const { return m_ReverseBlending; } + + void setCrossFadeBg(bool value); + bool crossFadeBg() const { return m_CrossFadeBg; } + + void setBlendBalance(int value); + int blendBalance() const { return m_BlendBalance; } + + void setWallpaper(TQString name); + TQString wallpaper() const { return m_Wallpaper; } + + enum WallpaperMode { + NoWallpaper, Centred, Tiled, CenterTiled, CentredMaxpect, TiledMaxpect, + Scaled, CentredAutoFit, ScaleAndCrop, lastWallpaperMode + }; + void setWallpaperMode(int mode); + int wallpaperMode() const { return m_WallpaperMode; } + + void setWallpaperList(TQStringList); + TQStringList wallpaperList() const; + TQStringList wallpaperFiles() const; + + void setWallpaperChangeInterval(int); + int wallpaperChangeInterval() const { return m_Interval; } + + enum MultiMode { + NoMulti, InOrder, Random, NoMultiRandom + }; + void setMultiWallpaperMode(int mode); + int multiWallpaperMode() const { return m_MultiMode; } + + enum MinOptDepth { + AlwaysOpt, Opt16bpp, Opt15bpp, NeverOpt }; + + void setMinOptimizationDepth( int mode ); + int minOptimizationDepth() const { return m_MinOptimizationDepth; } + bool optimize() const; + + void setUseShm( bool use ); + bool useShm() const { return m_bShm; } + + void changeWallpaper(bool init=false); + void updateWallpaperFiles(); + void randomizeWallpaperFiles(); + + TQString currentWallpaper() const; + /** + * @return true if the currentWallpaper has changed + */ + bool discardCurrentWallpaper(); + int lastWallpaperChange() const { return m_LastChange; } + bool needWallpaperChange(); + + void readSettings(bool reparse=false); + void writeSettings(); + TQString configGroupName() const; + + int hash(); + TQString fingerprint(); + + void setEnabled( const bool enable ); + bool enabled() const { return m_bEnabled; } + +private: + void updateHash(); + + bool dirty; + bool hashdirty; + int m_Screen, m_Desk, m_Hash; + + TQColor m_ColorA, defColorA; + TQColor m_ColorB, defColorB; + TQString m_Wallpaper; + TQStringList m_WallpaperList, m_WallpaperFiles; + + int m_BackgroundMode, defBackgroundMode; + int m_WallpaperMode, defWallpaperMode; + int m_BlendMode, defBlendMode; + int m_BlendBalance, defBlendBalance; + bool m_ReverseBlending, defReverseBlending; + bool m_CrossFadeBg, defCrossFadeBg; + int m_MinOptimizationDepth; + bool m_bShm; + bool m_bDrawBackgroundPerScreen; + + int m_MultiMode, defMultiMode; + int m_Interval, m_LastChange; + int m_CurrentWallpaper; + TQString m_CurrentWallpaperName; + + TDEConfig *m_pConfig; + TDEStandardDirs *m_pDirs; + bool m_bDeleteConfig; + bool m_bEnabled; + +public: + TQMap<TQString,int> m_BMMap; + TQMap<TQString,int> m_WMMap; + TQMap<TQString,int> m_MMMap; + TQMap<TQString,int> m_BlMMap; + char *m_BMRevMap[16]; + char *m_WMRevMap[16]; + char *m_MMRevMap[16]; + char *m_BlMRevMap[16]; +}; + + +/** + * A class to read/modify the global desktop background settings. + */ +class TDEGlobalBackgroundSettings +{ +public: + TDEGlobalBackgroundSettings(TDEConfig *config); + + TQString deskName(int desk); + //void setDeskName(int desk, TQString name); + + int cacheSize() { return m_CacheSize; } + void setCacheSize(int size); + + bool drawBackgroundPerScreen(int desk) const; + void setDrawBackgroundPerScreen(int desk, bool perScreen); + + bool limitCache() { return m_bLimitCache; } + void setLimitCache(bool limit); + + bool commonScreenBackground() { return m_bCommonScreen; } + void setCommonScreenBackground(bool common); + + bool commonDeskBackground() { return m_bCommonDesk; } + void setCommonDeskBackground(bool common); + + bool dockPanel() { return m_bDock; } + void setDockPanel(bool dock); + + bool exportBackground() {return m_bExport; } + void setExportBackground(bool _export); + + void setTextColor(TQColor _color); + TQColor textColor() const { return m_TextColor; } + + void setTextBackgroundColor(TQColor _color); + TQColor textBackgroundColor() const { return m_TextBackgroundColor; } + + void setShadowEnabled(bool enabled); + bool shadowEnabled() const { return m_shadowEnabled; } + + void setTextLines(int lines); + int textLines() const { return m_textLines; } + void setTextWidth(int width); + int textWidth() const { return m_textWidth; } + + void readSettings(); + void writeSettings(); + TDEConfig* getConfig() { return m_pConfig; } + +private: + bool dirty; + bool m_bCommonDesk; + bool m_bCommonScreen; + bool m_bDock; + bool m_bLimitCache, m_bExport; + int m_CacheSize; + TQStringList m_Names; + + TQColor m_TextColor; + TQColor m_TextBackgroundColor; + bool m_shadowEnabled; + int m_textLines; + int m_textWidth; + TDEConfig *m_pConfig; + bool m_bDeleteConfig; + TQValueVector<bool> m_bDrawBackgroundPerScreen; // m_bDrawBackgroundPerScreen[desk] +}; + + +#endif // __BGSETTINGS_H__ diff --git a/kcontrol/background/bgwallpaper.cpp b/kcontrol/background/bgwallpaper.cpp new file mode 100644 index 000000000..5e43caa4d --- /dev/null +++ b/kcontrol/background/bgwallpaper.cpp @@ -0,0 +1,238 @@ +/* vi: ts=8 sts=4 sw=4 + + This file is part of the KDE project, module kcmbackground. + + Copyright (C) 1999 Geert Jansen <[email protected]> + Copyright (C) 2003 Waldo Bastian <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 <config.h> + +#include <tqcheckbox.h> +#include <tqevent.h> +#include <tqpushbutton.h> +#include <tqspinbox.h> + +#include <tdefiledialog.h> +#include <kimageio.h> +#include <tdelocale.h> +#include <kstandarddirs.h> +#include <kurldrag.h> + +#include "bgsettings.h" +#include "bgwallpaper.h" +#include "bgwallpaper_ui.h" + +/**** BGMultiWallpaperList ****/ + +BGMultiWallpaperList::BGMultiWallpaperList(TQWidget *parent, const char *name) + : TQListBox(parent, name) +{ + setAcceptDrops(true); + setSelectionMode(TQListBox::Extended); +} + + +void BGMultiWallpaperList::dragEnterEvent(TQDragEnterEvent *ev) +{ + ev->accept(KURLDrag::canDecode(ev)); +} + + +void BGMultiWallpaperList::dropEvent(TQDropEvent *ev) +{ + TQStringList files; + KURL::List urls; + KURLDrag::decode(ev, urls); + for(KURL::List::ConstIterator it = urls.begin(); + it != urls.end(); ++it) + { + // TODO: Download remote files + if ((*it).isLocalFile()) + files.append((*it).path()); + } + insertStringList(files); +} + +bool BGMultiWallpaperList::hasSelection() +{ + for ( unsigned i = 0; i < count(); i++) + { + if ( item( i ) && item( i )->isSelected() ) + return true; + } + return false; +} + +void BGMultiWallpaperList::ensureSelectionVisible() +{ + for ( int i = topItem(); i < topItem() + numItemsVisible() - 1; i++) + if ( item( i ) && item( i )->isSelected() ) + return; + + for ( unsigned i = 0; i < count(); i++) + if ( item( i ) && item( i )->isSelected() ) + { + setTopItem( i ); + return; + } +} + +/**** BGMultiWallpaperDialog ****/ + +BGMultiWallpaperDialog::BGMultiWallpaperDialog(KBackgroundSettings *settings, + TQWidget *parent, const char *name) + : KDialogBase(parent, name, true, i18n("Setup Slide Show"), + Ok | Cancel, Ok, true), m_pSettings(settings) +{ + dlg = new BGMultiWallpaperBase(this); + setMainWidget(dlg); + + dlg->m_spinInterval->setRange(1, 99999); + dlg->m_spinInterval->setSteps(1, 15); + dlg->m_spinInterval->setSuffix(i18n(" min")); + + // Load + dlg->m_spinInterval->setValue(TQMAX(1,m_pSettings->wallpaperChangeInterval())); + + dlg->m_listImages->insertStringList(m_pSettings->wallpaperList()); + + if (m_pSettings->multiWallpaperMode() == KBackgroundSettings::Random) + dlg->m_cbRandom->setChecked(true); + + connect(dlg->m_buttonAdd, TQT_SIGNAL(clicked()), TQT_SLOT(slotAdd())); + connect(dlg->m_buttonRemove, TQT_SIGNAL(clicked()), TQT_SLOT(slotRemove())); + connect(dlg->m_buttonMoveUp, TQT_SIGNAL(clicked()), TQT_SLOT(slotMoveUp())); + connect(dlg->m_buttonMoveDown, TQT_SIGNAL(clicked()), TQT_SLOT(slotMoveDown())); + connect(dlg->m_listImages, TQT_SIGNAL(clicked ( TQListBoxItem * )), TQT_SLOT(slotItemSelected( TQListBoxItem *))); + dlg->m_buttonRemove->setEnabled( false ); + dlg->m_buttonMoveUp->setEnabled( false ); + dlg->m_buttonMoveDown->setEnabled( false ); + +} + +void BGMultiWallpaperDialog::slotItemSelected( TQListBoxItem * ) +{ + dlg->m_buttonRemove->setEnabled( dlg->m_listImages->hasSelection() ); + setEnabledMoveButtons(); +} + +void BGMultiWallpaperDialog::setEnabledMoveButtons() +{ + bool hasSelection = dlg->m_listImages->hasSelection(); + TQListBoxItem * item; + + item = dlg->m_listImages->firstItem(); + dlg->m_buttonMoveUp->setEnabled( hasSelection && item && !item->isSelected() ); + item = dlg->m_listImages->item( dlg->m_listImages->count() - 1 ); + dlg->m_buttonMoveDown->setEnabled( hasSelection && item && !item->isSelected() ); +} + +void BGMultiWallpaperDialog::slotAdd() +{ + TQStringList mimeTypes = KImageIO::mimeTypes( KImageIO::Reading ); +#ifdef HAVE_LIBART + mimeTypes += "image/svg+xml"; +#endif + + KFileDialog fileDialog(TDEGlobal::dirs()->findDirs("wallpaper", "").first(), + mimeTypes.join( " " ), this, + 0L, true); + + fileDialog.setCaption(i18n("Select Image")); + KFile::Mode mode = static_cast<KFile::Mode> (KFile::Files | + KFile::Directory | + KFile::ExistingOnly | + KFile::LocalOnly); + fileDialog.setMode(mode); + fileDialog.exec(); + TQStringList files = fileDialog.selectedFiles(); + if (files.isEmpty()) + return; + + dlg->m_listImages->insertStringList(files); +} + +void BGMultiWallpaperDialog::slotRemove() +{ + int current = -1; + for ( unsigned i = 0; i < dlg->m_listImages->count();) + { + TQListBoxItem * item = dlg->m_listImages->item( i ); + if ( item && item->isSelected()) + { + dlg->m_listImages->removeItem(i); + if (current == -1) + current = i; + } + else + i++; + } + if ((current != -1) && (current < (signed)dlg->m_listImages->count())) + dlg->m_listImages->setSelected(current, true); + + dlg->m_buttonRemove->setEnabled(dlg->m_listImages->hasSelection()); + + setEnabledMoveButtons(); +} + +void BGMultiWallpaperDialog::slotMoveUp() +{ + for ( unsigned i = 1; i < dlg->m_listImages->count(); i++) + { + TQListBoxItem * item = dlg->m_listImages->item( i ); + if ( item && item->isSelected() ) + { + dlg->m_listImages->takeItem( item ); + dlg->m_listImages->insertItem( item, i - 1 ); + } + } + dlg->m_listImages->ensureSelectionVisible(); + setEnabledMoveButtons(); +} + +void BGMultiWallpaperDialog::slotMoveDown() +{ + for ( unsigned i = dlg->m_listImages->count() - 1; i > 0; i--) + { + TQListBoxItem * item = dlg->m_listImages->item( i - 1 ); + if ( item && item->isSelected()) + { + dlg->m_listImages->takeItem( item ); + dlg->m_listImages->insertItem( item, i ); + } + } + dlg->m_listImages->ensureSelectionVisible(); + setEnabledMoveButtons(); +} + +void BGMultiWallpaperDialog::slotOk() +{ + TQStringList lst; + for (unsigned i=0; i < dlg->m_listImages->count(); i++) + lst.append(dlg->m_listImages->text(i)); + m_pSettings->setWallpaperList(lst); + m_pSettings->setWallpaperChangeInterval(dlg->m_spinInterval->value()); + if (dlg->m_cbRandom->isChecked()) + m_pSettings->setMultiWallpaperMode(KBackgroundSettings::Random); + else + m_pSettings->setMultiWallpaperMode(KBackgroundSettings::InOrder); + accept(); +} + + +#include "bgwallpaper.moc" diff --git a/kcontrol/background/bgwallpaper.h b/kcontrol/background/bgwallpaper.h new file mode 100644 index 000000000..dfee2066e --- /dev/null +++ b/kcontrol/background/bgwallpaper.h @@ -0,0 +1,66 @@ +/* vi: ts=8 sts=4 sw=4 + + This file is part of the KDE project, module kcmbackground. + + Copyright (C) 1999 Geert Jansen <[email protected]> + Copyright (C) 2003 Waldo Bastian <[email protected]> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU 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 _BGWALLPAPER_H_ +#define _BGWALLPAPER_H_ + +#include <tqlistbox.h> +#include <tqstringlist.h> + +#include <kdialogbase.h> + +class BGMultiWallpaperBase; +class KBackgroundSettings; + +class BGMultiWallpaperList : public TQListBox +{ +public: + BGMultiWallpaperList(TQWidget *parent, const char *name); + + void dragEnterEvent(TQDragEnterEvent *ev); + void dropEvent(TQDropEvent *ev); + bool hasSelection(); + void ensureSelectionVisible(); +}; + +class BGMultiWallpaperDialog : public KDialogBase +{ + Q_OBJECT +public: + BGMultiWallpaperDialog(KBackgroundSettings *settings, TQWidget *parent, const char *name=0); + +public slots: + void slotAdd(); + void slotRemove(); + void slotMoveUp(); + void slotMoveDown(); + void slotOk(); + void slotItemSelected( TQListBoxItem * ); +private: + void setEnabledMoveButtons(); + + KBackgroundSettings *m_pSettings; + + BGMultiWallpaperBase *dlg; +}; + +#endif diff --git a/kcontrol/background/bgwallpaper_ui.ui b/kcontrol/background/bgwallpaper_ui.ui new file mode 100644 index 000000000..14fca2eb2 --- /dev/null +++ b/kcontrol/background/bgwallpaper_ui.ui @@ -0,0 +1,167 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>BGMultiWallpaperBase</class> +<widget class="TQWidget"> + <property name="name"> + <cstring>BGMultiWallPaperBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>410</width> + <height>196</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="TQLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Show the following pictures:</string> + </property> + </widget> + <widget class="TQCheckBox" row="1" column="0"> + <property name="name"> + <cstring>m_cbRandom</cstring> + </property> + <property name="text"> + <string>&Show pictures in random order</string> + </property> + </widget> + <widget class="TQLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Change &picture after:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_spinInterval</cstring> + </property> + </widget> + <widget class="TQSpinBox"> + <property name="name"> + <cstring>m_spinInterval</cstring> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="TQLayoutWidget" row="3" column="0"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="BGMultiWallpaperList" row="0" column="0" rowspan="5" colspan="1"> + <property name="name"> + <cstring>m_listImages</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>100</height> + </size> + </property> + </widget> + <widget class="TQPushButton" row="0" column="1"> + <property name="name"> + <cstring>m_buttonAdd</cstring> + </property> + <property name="text"> + <string>&Add...</string> + </property> + </widget> + <spacer row="4" column="1"> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="TQPushButton" row="1" column="1"> + <property name="name"> + <cstring>m_buttonRemove</cstring> + </property> + <property name="text"> + <string>&Remove</string> + </property> + </widget> + <widget class="TQPushButton" row="3" column="1"> + <property name="name"> + <cstring>m_buttonMoveDown</cstring> + </property> + <property name="text"> + <string>Move &Down</string> + </property> + </widget> + <widget class="TQPushButton" row="2" column="1"> + <property name="name"> + <cstring>m_buttonMoveUp</cstring> + </property> + <property name="text"> + <string>Move &Up</string> + </property> + </widget> + </grid> + </widget> + </grid> +</widget> +<includes> + <include location="local" impldecl="in declaration">bgwallpaper.h</include> + <include location="local" impldecl="in implementation">kdialog.h</include> +</includes> +<layoutdefaults spacing="3" margin="6"/> +<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/> +</UI> diff --git a/kcontrol/background/crossfade.h b/kcontrol/background/crossfade.h new file mode 100644 index 000000000..dba34a3b4 --- /dev/null +++ b/kcontrol/background/crossfade.h @@ -0,0 +1,56 @@ +/* vi: ts=8 sts=4 sw=4 + * kate: space-indent on; tab-width 8; indent-width 4; indent-mode cstyle; + * + * This file is part of the KDE project, module kdesktop. + * Copyright (C) 1999,2000 Geert Jansen <[email protected]> + * + * You can Freely distribute this program under the GNU General Public + * License. See the file "COPYING" for the exact licensing terms. + */ + +#ifndef __CROSSFADE_H__ +#define __CROSSFADE_H__ + +#include <tqtimer.h> +#include <tqpainter.h> +#include <tqpixmap.h> +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <X11/extensions/Xrender.h> +#include <kdebug.h> +#include <unistd.h> + + + +inline TQPixmap crossFade(const TQPixmap &pix1, const TQPixmap &pix2, double r_alpha, + bool sync = false){ + + TQPixmap pix = TQPixmap(1,1,8); + int mw,mh; + mw = pix1.width(); + mh = pix1.height(); + + int alpha = 0xffff * (1-r_alpha); + + XRenderColor clr = { 0, 0, 0, alpha }; + XRenderPictureAttributes pa; + pa.repeat = True; + Picture pic = XRenderCreatePicture(pix.x11Display(), pix.handle(), + XRenderFindStandardFormat (pix.x11Display(), PictStandardA8), + CPRepeat, &pa); + XRenderFillRectangle(pix.x11Display(), PictOpSrc, pic, + &clr, 0, 0, 1, 1); + TQPixmap dst(pix1); + dst.detach(); + XRenderComposite(pix.x11Display(), PictOpOver, pix2.x11RenderHandle(), + pic, dst.x11RenderHandle(),0,0, 0,0, 0,0, mw,mh); + + if (sync) { + XSync(pix.x11Display(), false); + } + XRenderFreePicture(pix.x11Display(), pic); + return dst; +} + +#endif // __CROSSFADE_H__ diff --git a/kcontrol/background/main.cpp b/kcontrol/background/main.cpp new file mode 100644 index 000000000..2f6832dcc --- /dev/null +++ b/kcontrol/background/main.cpp @@ -0,0 +1,124 @@ +/* vi: ts=8 sts=4 sw=4 + * This file is part of the KDE project, module kcmbackground. + * Copyright (C) 1999 Geert Jansen <[email protected]> + * Copyright (C) 2003 Waldo Bastian <[email protected]> + * + * Based on old backgnd.cpp: + * + * Copyright (c) Martin R. Jones 1996 + * Converted to a kcc module by Matthias Hoelzer 1997 + * Gradient backgrounds by Mark Donohoe 1997 + * Pattern backgrounds by Stephan Kulow 1998 + * Randomizing & dnd & new display modes by Matej Koss 1998 + * + * You can Freely distribute this program under the GNU General Public + * License. See the file "COPYING" for the exact licensing terms. + */ + +#include <tqlayout.h> +#include <tdeapplication.h> +#include <tdeaboutdata.h> +#include <tdeconfig.h> +#include <kdebug.h> +#include <dcopclient.h> +#include <kimageio.h> +#include <kgenericfactory.h> + +#include "bgdialog.h" + +#include "main.h" + +/* as late as possible, as it includes some X headers without protecting them */ +#include <X11/Xlib.h> + +/**** DLL Interface ****/ +typedef KGenericFactory<KBackground, TQWidget> KBackGndFactory; +K_EXPORT_COMPONENT_FACTORY( kcm_background, KBackGndFactory("kcmbackground")) + +/**** KBackground ****/ +KBackground::~KBackground( ) +{ + delete m_pConfig; +} + +KBackground::KBackground(TQWidget *parent, const char *name, const TQStringList &/* */) + : TDECModule(KBackGndFactory::instance(), parent, name) +{ + int screen_number = 0; + if (tqt_xdisplay()) + screen_number = DefaultScreen(tqt_xdisplay()); + TQCString configname; + if (screen_number == 0) + configname = "kdesktoprc"; + else + configname.sprintf("kdesktop-screen-%drc", screen_number); + m_pConfig = new TDEConfig(configname, false, false); + + TQVBoxLayout *layout = new TQVBoxLayout(this); + m_base = new BGDialog(this, m_pConfig); + setQuickHelp( m_base->quickHelp()); + layout->add(m_base); + layout->addStretch(); + + KImageIO::registerFormats(); + + // reparenting that is done. + setAcceptDrops(true); + + connect(m_base, TQT_SIGNAL(changed(bool)), TQT_SIGNAL(changed(bool))); + + TDEAboutData *about = + new TDEAboutData(I18N_NOOP("kcmbackground"), I18N_NOOP("TDE Background Control Module"), + 0, 0, TDEAboutData::License_GPL, + I18N_NOOP("(c) 2009,2010 Timothy Pearson")); + + about->addAuthor("Timothy Pearson", 0, "[email protected]"); + about->addAuthor("Waldo Bastian", 0, "[email protected]"); + about->addAuthor("George Staikos", 0, "[email protected]"); + about->addAuthor("Martin R. Jones", 0, "[email protected]"); + about->addAuthor("Matthias Hoelzer-Kluepfel", 0, "[email protected]"); + about->addAuthor("Stephan Kulow", 0, "[email protected]"); + about->addAuthor("Mark Donohoe", 0, 0); + about->addAuthor("Matej Koss", 0 , 0); + + setAboutData( about ); +} + +void KBackground::load() +{ + load( false ); +} + +void KBackground::load( bool useDefaults ) +{ + m_base->load( useDefaults ); +} + + +void KBackground::save() +{ + m_base->save(); + + // reconfigure kdesktop. kdesktop will notify all clients + DCOPClient *client = kapp->dcopClient(); + if (!client->isAttached()) + client->attach(); + + int screen_number = 0; + if (tqt_xdisplay()) + screen_number = DefaultScreen(tqt_xdisplay()); + TQCString appname; + if (screen_number == 0) + appname = "kdesktop"; + else + appname.sprintf("kdesktop-screen-%d", screen_number); + + client->send(appname, "KBackgroundIface", "configure()", TQString("")); +} + +void KBackground::defaults() +{ + m_base->defaults(); +} + +#include "main.moc" diff --git a/kcontrol/background/main.h b/kcontrol/background/main.h new file mode 100644 index 000000000..9fdba57b8 --- /dev/null +++ b/kcontrol/background/main.h @@ -0,0 +1,40 @@ +/* vi: ts=8 sts=4 sw=4 + * + * This file is part of the KDE project, module kcmdisplay. + * Copyright (C) 1999 Geert Jansen <[email protected]> + * + * You can Freely distribute this program under the GNU General Public + * License. See the file "COPYING" for the exact licensing terms. + */ + +#ifndef __Bgnd_h_Included__ +#define __Bgnd_h_Included__ + +#include <tdecmodule.h> + +class TDEConfig; +class BGDialog; + +/** + * The Desktop/Background tab in kcontrol. + */ +class KBackground: public TDECModule +{ + Q_OBJECT + +public: + KBackground(TQWidget *parent, const char *name, const TQStringList &); + ~KBackground(); + + virtual void load(); + virtual void load( bool useDefaults ); + virtual void save(); + virtual void defaults(); + +private: + BGDialog *m_base; + TDEConfig *m_pConfig; +}; + + +#endif // __Bgnd_h_Included__ diff --git a/kcontrol/background/pics/CMakeLists.txt b/kcontrol/background/pics/CMakeLists.txt new file mode 100644 index 000000000..973a300cf --- /dev/null +++ b/kcontrol/background/pics/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +install( FILES monitor.png DESTINATION ${DATA_INSTALL_DIR}/kcontrol/pics ) diff --git a/kcontrol/background/pics/Makefile.am b/kcontrol/background/pics/Makefile.am new file mode 100644 index 000000000..d639379d0 --- /dev/null +++ b/kcontrol/background/pics/Makefile.am @@ -0,0 +1,5 @@ +pics_DATA = monitor.png +picsdir = $(kde_datadir)/kcontrol/pics + +EXTRA_DIST = $(pics_DATA) + diff --git a/kcontrol/background/pics/monitor.png b/kcontrol/background/pics/monitor.png Binary files differnew file mode 100644 index 000000000..ecd86b9e4 --- /dev/null +++ b/kcontrol/background/pics/monitor.png |