diff options
Diffstat (limited to 'kcontrol/background')
23 files changed, 7677 insertions, 0 deletions
diff --git a/kcontrol/background/Makefile.am b/kcontrol/background/Makefile.am new file mode 100644 index 000000000..e1d847ead --- /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_KFILE) $(LIB_KNEWSTUFF) + +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..7329a2b27 --- /dev/null +++ b/kcontrol/background/background.desktop @@ -0,0 +1,240 @@ +[Desktop Entry] +Exec=kcmshell background +Icon=background +Type=Application +DocPath=kcontrol/background/index.html + + +X-KDE-Library=background +X-KDE-FactoryName=background +X-KDE-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;KDE;X-KDE-settings-looknfeel; diff --git a/kcontrol/background/bgadvanced.cpp b/kcontrol/background/bgadvanced.cpp new file mode 100644 index 000000000..3218ec470 --- /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 <qbuttongroup.h> +#include <qcheckbox.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qcombobox.h> +#include <qpushbutton.h> +#include <qslider.h> +#include <qspinbox.h> +#include <qwhatsthis.h> + +#include <kconfig.h> +#include <kcolorbutton.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kpixmap.h> +#include <kstandarddirs.h> +#include <kwin.h> + +#include "bgrender.h" +#include "bgadvanced.h" +#include "bgadvanced_ui.h" + +#include <X11/Xlib.h> + +/**** BGAdvancedDialog ****/ + +static QCString desktopConfigname() +{ + int desktop=0; + if (qt_xdisplay()) + desktop = DefaultScreen(qt_xdisplay()); + QCString name; + if (desktop == 0) + name = "kdesktoprc"; + else + name.sprintf("kdesktop-screen-%drc", desktop); + + return name; +} + + +BGAdvancedDialog::BGAdvancedDialog(KBackgroundRenderer *_r, + QWidget *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, SIGNAL(clicked(QListViewItem *)), + SLOT(slotProgramItemClicked(QListViewItem *))); + + // Load programs + QStringList lst = KBackgroundProgram::list(); + QStringList::Iterator it; + for (it=lst.begin(); it != lst.end(); ++it) + addProgram(*it); + + if (m_multidesktop) + { + KConfig 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, SIGNAL(clicked()), + SLOT(slotAdd())); + connect(dlg->m_buttonRemove, SIGNAL(clicked()), + SLOT(slotRemove())); + connect(dlg->m_buttonModify, SIGNAL(clicked()), + SLOT(slotModify())); + + connect(dlg->m_listPrograms, SIGNAL(doubleClicked(QListViewItem *)), + SLOT(slotProgramItemDoubleClicked(QListViewItem *))); + } + 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, SIGNAL(toggled(bool)), + 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(); +} + +QColor BGAdvancedDialog::textColor() +{ + return dlg->m_colorText->color(); +} + +void BGAdvancedDialog::setTextColor(const QColor &color) +{ + dlg->m_colorText->setColor(color); +} + +QColor BGAdvancedDialog::textBackgroundColor() +{ + return dlg->m_cbSolidTextBackground->isChecked() ? + dlg->m_colorTextBackground->color() : QColor(); +} + +void BGAdvancedDialog::setTextBackgroundColor(const QColor &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() +{ + QString 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 QString &name) +{ + if (m_programItems.find(name)) + { + delete m_programItems[name]; + m_programItems.remove(name); + } +} + +void BGAdvancedDialog::addProgram(const QString &name) +{ + removeProgram(name); + + KBackgroundProgram prog(name); + if (prog.command().isEmpty() || (prog.isGlobal() && !prog.isAvailable())) + return; + + QListViewItem *item = new QListViewItem(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 QString &name) +{ + if (m_programItems.find(name)) + { + QListViewItem *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() == QDialog::Accepted) + { + QString 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 = QString::null; +} + +/* + * Modify a program. + */ +void BGAdvancedDialog::slotModify() +{ + if (m_selectedProgram.isEmpty()) + return; + + KProgramEditDialog dlg(m_selectedProgram); + dlg.exec(); + if (dlg.result() == QDialog::Accepted) + { + QString 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(QListViewItem *item) +{ + if (item) + m_selectedProgram = item->text(0); + slotProgramChanged(); +} + +void BGAdvancedDialog::slotProgramItemDoubleClicked(QListViewItem *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); + QListViewItem *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(); + } +} + +QString BGAdvancedDialog::backgroundProgram() const +{ + return m_selectedProgram; +} + +int BGAdvancedDialog::backgroundMode() const +{ + return m_backgroundMode; +} + +/**** KProgramEditDialog ****/ + +KProgramEditDialog::KProgramEditDialog(const QString &program, QWidget *parent, char *name) + : KDialogBase(parent, name, true, i18n("Configure Background Program"), + Ok | Cancel, Ok, true) +{ + QFrame *frame = makeMainWidget(); + + QGridLayout *grid = new QGridLayout(frame, 6, 2, 0, spacingHint()); + grid->addColSpacing(1, 300); + + QLabel *lbl = new QLabel(i18n("&Name:"), frame); + grid->addWidget(lbl, 0, 0); + m_NameEdit = new QLineEdit(frame); + lbl->setBuddy(m_NameEdit); + grid->addWidget(m_NameEdit, 0, 1); + + lbl = new QLabel(i18n("Co&mment:"), frame); + grid->addWidget(lbl, 1, 0); + m_CommentEdit = new QLineEdit(frame); + lbl->setBuddy(m_CommentEdit); + grid->addWidget(m_CommentEdit, 1, 1); + + lbl = new QLabel(i18n("Comman&d:"), frame); + grid->addWidget(lbl, 2, 0); + m_CommandEdit = new QLineEdit(frame); + lbl->setBuddy(m_CommandEdit); + grid->addWidget(m_CommandEdit, 2, 1); + + lbl = new QLabel(i18n("&Preview cmd:"), frame); + grid->addWidget(lbl, 3, 0); + m_PreviewEdit = new QLineEdit(frame); + lbl->setBuddy(m_PreviewEdit); + grid->addWidget(m_PreviewEdit, 3, 1); + + lbl = new QLabel(i18n("&Executable:"), frame); + grid->addWidget(lbl, 4, 0); + m_ExecEdit = new QLineEdit(frame); + lbl->setBuddy(m_ExecEdit); + grid->addWidget(m_ExecEdit, 4, 1); + + lbl = new QLabel(i18n("&Refresh time:"), frame); + grid->addWidget(lbl, 5, 0); + m_RefreshEdit = new QSpinBox(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, 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()); +} + + +QString KProgramEditDialog::program()const +{ + return m_NameEdit->text(); +} + +void KProgramEditDialog::slotOk() +{ + QString 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),QString::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..6ede665a1 --- /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 <qdict.h> +#include <qlistview.h> +#include <qstringlist.h> + +#include <kdialogbase.h> + +class QLineEdit; +class QSpinBox; + +class BGAdvancedBase; +class KBackgroundRenderer; +class KBackgroundProgram; + +class BGAdvancedDialog : public KDialogBase +{ + Q_OBJECT +public: + BGAdvancedDialog(KBackgroundRenderer *_r, QWidget *parent, bool m_multidesktop); + + void setCacheSize(int s); + int cacheSize(); + QColor textColor(); + void setTextColor(const QColor &color); + QColor textBackgroundColor(); + void setTextBackgroundColor(const QColor &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(); + + QString backgroundProgram() const; + int backgroundMode() const; + +public slots: + void slotAdd(); + void slotRemove(); + void slotModify(); + +protected: + void addProgram(const QString &name); + void removeProgram(const QString &name); + void selectProgram(const QString &name); + +protected slots: + void slotProgramItemClicked(QListViewItem *item); + void slotProgramItemDoubleClicked(QListViewItem *item); + void slotProgramChanged(); + void slotEnableProgram(bool b); + +private: + KBackgroundRenderer *r; + + BGAdvancedBase *dlg; + + QWidget *m_pMonitor; + QDict<QListViewItem> m_programItems; + QString m_selectedProgram; + int m_oldBackgroundMode; + int m_backgroundMode; +}; + +/** + * Dialog to edit a background program. + */ +class KProgramEditDialog: public KDialogBase +{ + Q_OBJECT + +public: + KProgramEditDialog(const QString &program=QString::null, QWidget *parent=0L, + char *name=0L); + + /** The program name is here in case the user changed it */ + QString program()const; + +public slots: + void slotOk(); + +private: + QString m_Program; + QLineEdit *m_NameEdit, *m_CommentEdit; + QLineEdit *m_ExecEdit, *m_CommandEdit; + QLineEdit *m_PreviewEdit; + QSpinBox *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..6aa3d436a --- /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="QWidget"> + <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="QButtonGroup"> + <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="QPushButton" 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="QPushButton" 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="QPushButton" 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="QListView" 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="QCheckBox" 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="QGroupBox"> + <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="QLabel" 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="QCheckBox" 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="QCheckBox" 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="QLabel" 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="QSpinBox" 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="QSpinBox" 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="QLabel" 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="QButtonGroup"> + <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="QLabel"> + <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 KDE 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="QSpinBox"> + <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 KDE 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..99846f0b0 --- /dev/null +++ b/kcontrol/background/bgdefaults.h @@ -0,0 +1,38 @@ +/* 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 QColor("#003082") +#define _defColorB QColor("#C0C0C0") +#define _defBackgroundMode KBackgroundSettings::Flat +#define _defWallpaperMode KBackgroundSettings::NoWallpaper +#define _defMultiMode KBackgroundSettings::NoMulti +#define _defBlendMode KBackgroundSettings::NoBlending +#define _defBlendBalance 100 +#define _defReverseBlending false + +#endif // __BGDefaults_h_Included__ diff --git a/kcontrol/background/bgdialog.cpp b/kcontrol/background/bgdialog.cpp new file mode 100644 index 000000000..398e30d56 --- /dev/null +++ b/kcontrol/background/bgdialog.cpp @@ -0,0 +1,1279 @@ +/* + 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 <qbuttongroup.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <qpainter.h> +#include <qradiobutton.h> +#include <qslider.h> +#include <qtimer.h> +#include <qtooltip.h> +#include <qwhatsthis.h> +#include <qapplication.h> + +#include <kconfig.h> +#include <kdebug.h> +#include <kfiledialog.h> +#include <kfilemetainfo.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <kimageio.h> +#include <klocale.h> +#include <kpixmap.h> +#include <kstandarddirs.h> +#include <kstringhandler.h> +#include <kurlrequester.h> +#include <kwin.h> +#include <kimagefilepreview.h> +#include <knewstuff/downloaddialog.h> + +#include <stdlib.h> + +#include "bgmonitor.h" +#include "bgwallpaper.h" +#include "bgadvanced.h" +#include "bgdialog.h" + +#define NR_PREDEF_PATTERNS 6 + +BGDialog::BGDialog(QWidget* parent, KConfig* _config, bool _multidesktop) + : BGDialog_UI(parent, "BGDialog") +{ + m_pGlobals = new KGlobalBackgroundSettings(_config); + m_pDirs = KGlobal::dirs(); + m_multidesktop = _multidesktop; + m_previewUpdates = true; + + m_numDesks = m_multidesktop ? KWin::numberOfDesktops() : 1; + m_numScreens = QApplication::desktop()->numScreens(); + + QCString multiHead = getenv("KDE_MULTIHEAD"); + if (multiHead.lower() == "true") + { + m_numScreens = 1; + } + + m_desk = m_multidesktop ? KWin::currentDesktop() : 1; + m_screen = QApplication::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, SIGNAL(clicked()), SLOT(slotIdentifyScreens())); + + // preview monitor + m_pMonitorArrangement = new BGMonitorArrangement(m_screenArrangement, "monitor arrangement"); + connect(m_pMonitorArrangement, SIGNAL(imageDropped(const QString &)), SLOT(slotImageDropped(const QString &))); + if( m_multidesktop) + { + // desktop + connect(m_comboDesktop, SIGNAL(activated(int)), + SLOT(slotSelectDesk(int))); + } + if (m_numScreens > 1) + { + connect(m_comboScreen, SIGNAL(activated(int)), + SLOT(slotSelectScreen(int))); + } + + // background image settings + QIconSet iconSet = SmallIconSet(QString::fromLatin1("fileopen")); + QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal ); + m_urlWallpaperButton->setIconSet( iconSet ); + m_urlWallpaperButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 ); + QToolTip::add(m_urlWallpaperButton, i18n("Open file dialog")); + + connect(m_buttonGroupBackground, SIGNAL(clicked(int)), + SLOT(slotWallpaperTypeChanged(int))); + connect(m_urlWallpaperBox, SIGNAL(activated(int)), + SLOT(slotWallpaper(int))); + connect(m_urlWallpaperButton, SIGNAL(clicked()), + SLOT(slotWallpaperSelection())); + connect(m_comboWallpaperPos, SIGNAL(activated(int)), + SLOT(slotWallpaperPos(int))); + connect(m_buttonSetupWallpapers, SIGNAL(clicked()), + SLOT(slotSetupMulti())); + + // set up the background colour stuff + connect(m_colorPrimary, SIGNAL(changed(const QColor &)), + SLOT(slotPrimaryColor(const QColor &))); + connect(m_colorSecondary, SIGNAL(changed(const QColor &)), + SLOT(slotSecondaryColor(const QColor &))); + connect(m_comboPattern, SIGNAL(activated(int)), + SLOT(slotPattern(int))); + + // blend + connect(m_comboBlend, SIGNAL(activated(int)), SLOT(slotBlendMode(int))); + connect(m_sliderBlend, SIGNAL(valueChanged(int)), + SLOT(slotBlendBalance(int))); + connect(m_cbBlendReverse, SIGNAL(toggled(bool)), + SLOT(slotBlendReverse(bool))); + + // advanced options + connect(m_buttonAdvanced, SIGNAL(clicked()), + SLOT(slotAdvanced())); + + connect(m_buttonGetNew, SIGNAL(clicked()), + 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, SIGNAL(imageDone(int,int)), SLOT(slotPreviewDone(int,int)) ); + + // Setup the common-screen renderer + r = new KBackgroundRenderer(eDesk, 0, true, _config); + m_renderer[i].insert( 1, r ); + connect( r, SIGNAL(imageDone(int,int)), 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, SIGNAL(imageDone(int,int)), 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, SIGNAL(imageDone(int,int)), 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, SIGNAL(imageDone(int,int)), 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 (KGlobal::dirs()->isRestrictedResource("wallpaper")) + { + m_urlWallpaperButton->hide(); + m_buttonSetupWallpapers->hide(); + m_radioSlideShow->hide(); + } + + initUI(); + updateUI(); + +#if (QT_VERSION-0 >= 0x030200) + connect( qApp->desktop(), SIGNAL( resized( int )), 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 ); +} + +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) ); + 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() ); +} + +QString BGDialog::quickHelp() const +{ + return i18n("<h1>Background</h1> This module allows you to control the" + " appearance of the virtual desktops. KDE 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>" + " KDE 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 \"kdeworld\"" + " program shows a day/night map of the world which is updated periodically."); +} + +void BGDialog::slotIdentifyScreens() +{ + // Taken from PositionTab::showIdentify in kdebase/kcontrol/kicker/positiontab_impl.cpp + for(unsigned s = 0; s < m_numScreens; s++) + { + QLabel *screenLabel = new QLabel(0,"Screen Identify", WDestructiveClose | WStyle_Customize | WX11BypassWM); + + QFont identifyFont(KGlobalSettings::generalFont()); + identifyFont.setPixelSize(100); + screenLabel->setFont(identifyFont); + + screenLabel->setFrameStyle(QFrame::Panel); + screenLabel->setFrameShadow(QFrame::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. + QTimer::singleShot(1500, screenLabel, SLOT(close())); + + QPoint screenCenter(QApplication::desktop()->screenGeometry(s).center()); + QRect targetGeometry(QPoint(0,0),screenLabel->sizeHint()); + targetGeometry.moveCenter(screenCenter); + + screenLabel->setGeometry(targetGeometry); + + screenLabel->show(); + } +} + +void BGDialog::initUI() +{ + // Desktop names + for (unsigned i = 0; i < m_numDesks; ++i) + m_comboDesktop->insertItem(m_pGlobals->deskName(i)); + + // Screens + for (unsigned i = 0; i < m_numScreens; ++i) + m_comboScreen->insertItem( i18n("Screen %1").arg(QString::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 + QStringList::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 QMap is lower cased names mapped to cased names and URLs + // this way we get case insensitive sorting + QMap<QString, QPair<QString, QString> > papers; + + //search for .desktop files before searching for images without .desktop files + QStringList lst = m_pDirs->findAllResources("wallpaper", "*desktop", false, true); + QStringList files; + for (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) + { + KSimpleConfig fileConfig(*it); + fileConfig.setGroup("Wallpaper"); + + QString imageCaption = fileConfig.readEntry("Name"); + QString fileName = fileConfig.readEntry("File"); + + if (imageCaption.isEmpty()) + { + imageCaption = fileName; + imageCaption.replace('_', ' '); + imageCaption = KStringHandler::capwords(imageCaption); + } + + // avoid name collisions + QString rs = imageCaption; + QString lrs = rs.lower(); + for (int n = 1; papers.find(lrs) != papers.end(); ++n) + { + rs = imageCaption + " (" + QString::number(n) + ')'; + lrs = rs.lower(); + } + int slash = (*it).findRev('/') + 1; + QString directory = (*it).left(slash); + 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 (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) + { + if ( !(*it).endsWith(".desktop") && files.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); + QString 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 + QString rs = imageCaption; + QString lrs = rs.lower(); + for (int n = 1; papers.find(lrs) != papers.end(); ++n) + { + rs = imageCaption + " (" + QString::number(n) + ')'; + lrs = rs.lower(); + } + papers[lrs] = qMakePair(rs, *it); + } + } + + KComboBox *comboWallpaper = m_urlWallpaperBox; + comboWallpaper->clear(); + m_wallpaper.clear(); + int i = 0; + for (QMap<QString, QPair<QString, QString> >::Iterator it = papers.begin(); + it != papers.end(); + ++it) + { + comboWallpaper->insertItem(it.data().first); + m_wallpaper[it.data().second] = i; + i++; + } +} + +void BGDialog::setWallpaper(const QString &s) +{ + KComboBox *comboWallpaper = m_urlWallpaperBox; + comboWallpaper->blockSignals(true); + + if (m_wallpaper.find(s) == m_wallpaper.end()) + { + int i = comboWallpaper->count(); + QString 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( QString::null, QString::null, this, + "file dialog", true ); + + KImageFilePreview* previewWidget = new KImageFilePreview(&dlg); + dlg.setPreviewWidget(previewWidget); + + QStringList 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(); + QString uri; + for(QMap<QString,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() == QDialog::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_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 (QPixmap::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 QString &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(); + QString path; + for(QMap<QString,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. + + QSize 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() == QDialog::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 QColor &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 QColor &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 + //kcmshellrc or kcontrolrc + KConfig* config = KGlobal::config(); + config->setGroup("KNewStuff"); + config->writeEntry( "ProvidersUrl", "http://download.kde.org/khotnewstuff/wallpaper-providers.xml" ); + config->writeEntry( "StandardResource", "wallpaper" ); + config->sync(); + + KNS::DownloadDialog::open("wallpapers", 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::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..02fbf3f3a --- /dev/null +++ b/kcontrol/background/bgdialog.h @@ -0,0 +1,109 @@ +/* + 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 <qptrvector.h> +#include <qmap.h> +#include <qvaluevector.h> + +#include "bgdialog_ui.h" +#include "bgrender.h" +#include "bgsettings.h" +#include "bgdefaults.h" + +class BGMonitorArrangement; +class KStandardDirs; + +class BGDialog : public BGDialog_UI +{ + Q_OBJECT +public: + BGDialog(QWidget* parent, KConfig* _config, bool _multidesktop = true); + ~BGDialog(); + + void load( bool useDefaults ); + void save(); + void defaults(); + + void makeReadOnly(); + + QString quickHelp() const; + +signals: + void changed(bool); + +protected: + void initUI(); + void updateUI(); + KBackgroundRenderer * eRenderer(); + + void setWallpaper(const QString &); + + 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 QColor &color); + void slotSecondaryColor(const QColor &color); + void slotPattern(int pattern); + void slotImageDropped(const QString &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); + +protected: + void getEScreen(); + KGlobalBackgroundSettings *m_pGlobals; + KStandardDirs *m_pDirs; + bool m_multidesktop; + + unsigned m_numDesks; + unsigned m_numScreens; + int m_desk; + int m_screen; + int m_eDesk; + int m_eScreen; + QValueVector< QPtrVector<KBackgroundRenderer> > m_renderer; // m_renderer[desk][screen] + QMap<QString,int> m_wallpaper; + QStringList 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..7cc6571d5 --- /dev/null +++ b/kcontrol/background/bgdialog_ui.ui @@ -0,0 +1,722 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>BGDialog_UI</class> +<widget class="QWidget"> + <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="QLabel" 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="QLayoutWidget" 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="QWidget"> + <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="QLayoutWidget"> + <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="QPushButton"> + <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="QPushButton"> + <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="QPushButton"> + <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="QGroupBox" 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="QLabel" 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="QComboBox" 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="QLayoutWidget" 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="QLabel" 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="QLabel" 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="QLayoutWidget" row="6" column="1"> + <property name="name"> + <cstring>layout23</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <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="QSlider"> + <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="QCheckBox" 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="QComboBox" 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="QComboBox" 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="QButtonGroup" 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="QRadioButton" row="0" column="0"> + <property name="name"> + <cstring>m_radioNoPicture</cstring> + </property> + <property name="text"> + <string>&No picture</string> + </property> + </widget> + <widget class="QRadioButton" row="2" column="0"> + <property name="name"> + <cstring>m_radioSlideShow</cstring> + </property> + <property name="text"> + <string>&Slide show:</string> + </property> + </widget> + <widget class="QRadioButton" 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="QPushButton" 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="QPushButton" 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..932c6ebab --- /dev/null +++ b/kcontrol/background/bghash.h @@ -0,0 +1,22 @@ +#ifndef BGHASH_H +#define BGHASH_H + +/* + * QString -> int hash. From Qt's QGDict::hashKeyString(). + */ + +static int QHash(QString key) +{ + int g, h = 0; + const QChar *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..6af2f7458 --- /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 <klocale.h> +#include <kpixmap.h> +#include <kstandarddirs.h> +#include <kurldrag.h> +#include <qapplication.h> +#include <qpixmap.h> +#include <qwhatsthis.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(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + m_pBGMonitor.resize( QApplication::desktop()->numScreens(), 0l ); + + for (int screen = 0; screen < QApplication::desktop()->numScreens(); ++screen) + { + BGMonitorLabel * label = new BGMonitorLabel(this); + m_pBGMonitor[screen] = label; + + connect( label->monitor(), SIGNAL(imageDropped(const QString &)), this, SIGNAL(imageDropped(const QString &)) ); + } + + parent->setFixedSize(200, 186); + setFixedSize(200, 186); + updateArrangement(); +} + + +BGMonitor * BGMonitorArrangement::monitor( unsigned screen ) const +{ + return m_pBGMonitor[screen]->monitor(); +} + + +QRect BGMonitorArrangement::expandToPreview( QRect r ) const +{ + double scaleX = 200.0 / 151.0; + double scaleY = 186.0 / 115.0; + return QRect( int(r.x()*scaleX), int(r.y()*scaleY), int(r.width()*scaleX), int(r.height()*scaleY) ); +} + + +QSize BGMonitorArrangement::expandToPreview( QSize s ) const +{ + double scaleX = 200.0 / 151.0; + double scaleY = 186.0 / 115.0; + return QSize( int(s.width()*scaleX), int(s.height()*scaleY) ); +} + + +QPoint BGMonitorArrangement::expandToPreview( QPoint p ) const +{ + double scaleX = 200.0 / 151.0; + double scaleY = 186.0 / 115.0; + return QPoint( 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. + + QRect overallGeometry; + for (int screen = 0; screen < QApplication::desktop()->numScreens(); ++screen) + overallGeometry |= QApplication::desktop()->screenGeometry(screen); + + QRect expandedOverallGeometry = expandToPreview(overallGeometry); + + double scale = QMIN( + double(width()) / double(expandedOverallGeometry.width()), + double(height()) / double(expandedOverallGeometry.height()) + ); + + m_combinedPreviewSize = overallGeometry.size() * scale; + + m_maxPreviewSize = QSize(0,0); + int previousMax = 0; + + for (int screen = 0; screen < QApplication::desktop()->numScreens(); ++screen) + { + QPoint topLeft = (QApplication::desktop()->screenGeometry(screen).topLeft() - overallGeometry.topLeft()) * scale; + QPoint expandedTopLeft = expandToPreview(topLeft); + + QSize previewSize = QApplication::desktop()->screenGeometry(screen).size() * scale; + QSize expandedPreviewSize = expandToPreview(previewSize); + + if ( (previewSize.width() * previewSize.height()) > previousMax ) + { + previousMax = previewSize.width() * previewSize.height(); + m_maxPreviewSize = previewSize; + } + + m_pBGMonitor[screen]->setPreviewPosition( QRect( topLeft, previewSize ) ); + m_pBGMonitor[screen]->setGeometry( QRect( expandedTopLeft, expandedPreviewSize ) ); + m_pBGMonitor[screen]->updateMonitorGeometry(); + } +} + + +void BGMonitorArrangement::resizeEvent( QResizeEvent * e ) +{ + QWidget::resizeEvent(e); + updateArrangement(); +} + + +void BGMonitorArrangement::setPixmap( const KPixmap & pm ) +{ + for (unsigned screen = 0; screen < m_pBGMonitor.size(); ++screen) + { + QRect position = m_pBGMonitor[screen]->previewPosition(); + + QPixmap 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(QWidget *parent, const char *name) + : QLabel(parent, name) +{ + setAlignment(AlignCenter); + setScaledContents(true); + setPixmap( QPixmap( locate("data", "kcontrol/pics/monitor.png") ) ); + m_pBGMonitor = new BGMonitor(this); + + QWhatsThis::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 " << QRect( 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( QResizeEvent * e ) +{ + QWidget::resizeEvent(e); + updateMonitorGeometry(); +} +//END class BGMonitorLabel + + + +//BEGIN class BGMonitor +BGMonitor::BGMonitor(QWidget *parent, const char *name) + : QLabel(parent, name) +{ + setAlignment(AlignCenter); + setScaledContents(true); + setAcceptDrops(true); +} + + +void BGMonitor::dropEvent(QDropEvent *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(QDragEnterEvent *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..1e714194e --- /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 <qlabel.h> +#include <qvaluevector.h> +#include <qwidget.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 QWidget +{ + Q_OBJECT +public: + BGMonitorArrangement(QWidget *parent, const char *name=0L); + + /** + * Splits up the pixmap according to monitor geometries and sets each + * BGMonitor pixmap accordingly. + */ + void setPixmap( const KPixmap & pm ); + QSize combinedPreviewSize() const { return m_combinedPreviewSize; } + QSize maxPreviewSize() const { return m_maxPreviewSize; } + unsigned numMonitors() const { return m_pBGMonitor.size(); } + + BGMonitor * monitor( unsigned screen ) const; + void updateArrangement(); + +signals: + void imageDropped(const QString &); + +protected: + virtual void resizeEvent( QResizeEvent * ); + QRect expandToPreview( QRect r ) const; + QSize expandToPreview( QSize s ) const; + QPoint expandToPreview( QPoint p ) const; + + QValueVector<BGMonitorLabel*> m_pBGMonitor; + QSize m_combinedPreviewSize; + QSize m_maxPreviewSize; +}; + +/** + * Contains a BGMonitor. + */ +class BGMonitorLabel : public QLabel +{ +public: + BGMonitorLabel(QWidget *parent, const char *name=0L); + + BGMonitor * monitor() const { return m_pBGMonitor; } + void updateMonitorGeometry(); + + void setPreviewPosition( QRect r ) { m_previewPosition = r; } + QRect previewPosition() const { return m_previewPosition; } + +protected: + virtual void resizeEvent( QResizeEvent * ); + BGMonitor * m_pBGMonitor; + QRect m_previewPosition; +}; + + +/** + * This class handles drops on the preview monitor. + */ +class BGMonitor : public QLabel +{ + Q_OBJECT +public: + BGMonitor(QWidget *parent, const char *name=0L); + +signals: + void imageDropped(const QString &); + +protected: + virtual void dropEvent(QDropEvent *); + virtual void dragEnterEvent(QDragEnterEvent *); +}; + + +#endif diff --git a/kcontrol/background/bgrender.cpp b/kcontrol/background/bgrender.cpp new file mode 100644 index 000000000..f17892dce --- /dev/null +++ b/kcontrol/background/bgrender.cpp @@ -0,0 +1,1359 @@ +/* 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 <time.h> +#include <stdlib.h> +#include <utime.h> + +#include <qtimer.h> +#include <qpainter.h> +#include <qimage.h> +#include <qfileinfo.h> +#include <qdir.h> + +#include <dcopclient.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kstandarddirs.h> +#include <kimageeffect.h> +#include <kprocess.h> +#include <kpixmapio.h> +#include <ktempfile.h> +#include <kcursor.h> +#include <kmimetype.h> +#include <kfilemetainfo.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, KConfig *config) + : KBackgroundSettings(desk, screen, drawBackgroundPerScreen, config) +{ + m_State = 0; + m_isBusyCursor = false; + m_enableBusyCursor = false; + m_pDirs = KGlobal::dirs(); + m_rSize = m_Size = drawBackgroundPerScreen ? + QApplication::desktop()->screenGeometry(screen).size() : QApplication::desktop()->size(); + m_pProc = 0L; + m_Tempfile = 0L; + m_bPreview = false; + m_Cached = false; + m_TilingEnabled = false; + + m_pTimer = new QTimer(this); + connect(m_pTimer, SIGNAL(timeout()), SLOT(render())); +} + + +KBackgroundRenderer::~KBackgroundRenderer() +{ + cleanup(); + delete m_Tempfile; + m_Tempfile = 0; +} + + +void KBackgroundRenderer::setSize(const QSize &size) +{ + m_rSize = m_Size = size; +} + +/* + * Re-configure because the desktop has been resized. + */ +void KBackgroundRenderer::desktopResized() +{ + m_State = 0; + m_rSize = drawBackgroundPerScreen() ? + QApplication::desktop()->screenGeometry(screen()).size() : QApplication::desktop()->size(); + if( !m_bPreview ) + m_Size = m_rSize; +} + + +void KBackgroundRenderer::tile(QImage& dest, QRect rect, const QImage& 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. + */ + +QString KBackgroundRenderer::buildCommand() +{ + QString num; + int pos = 0; + + QString cmd; + if (m_bPreview) + cmd = previewCommand(); + else + cmd = command(); + + if (cmd.isEmpty()) + return QString(); + + 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; + QString file; + + static unsigned int tileWidth = 0; + static unsigned int tileHeight = 0; + if( tileWidth == 0 ) + { + int tile_val = QPixmap::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( qt_xdisplay(), qt_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 = QMIN(w, m_Size.width()); + h = QMIN(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, SIGNAL(processExited(KProcess *)), + SLOT(slotBackgroundDone(KProcess *))); + m_pProc->start(KShellProcess::NotifyOnExit); + retval = Wait; + break; + + case HorizontalGradient: + { + QSize 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: + { + QSize 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 = QImage(); + if (wpmode != NoWallpaper) { +wp_load: + if (currentWallpaper().isEmpty()) { + wpmode = NoWallpaper; + goto wp_out; + } + QString file = m_pDirs->findResource("wallpaper", currentWallpaper()); + if (file.isEmpty()) { + wpmode = NoWallpaper; + goto wp_out; + } + + // _Don't_ use KMimeType, as it relies on ksycoca which we really + // don't want in krootimage (kdm 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 )) { + QImage *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, 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() != QSize( xs, ys )) + m_Wallpaper = m_Wallpaper.smoothScale(xs, ys); + } + + // HACK: Use KFileMetaInfo only when we're attached to DCOP. + // KFileMetaInfo needs ksycoca and so on, but this code is + // used also in krootimage (which in turn is used by kdm). + 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 = QRect(); // 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() != QSize( 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() != QSize( 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() != QSize( 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() != QSize( 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 qt_use_xrender; // in Qt ( qapplication_x11.cpp ) + +void KBackgroundRenderer::wallpaperBlend() +{ + if( !enabled() || wallpaperMode() == NoWallpaper + || (blendMode() == NoBlending && ( qt_use_xrender || !m_Wallpaper.hasAlphaBuffer()))) { + fastWallpaperBlend(); + } + else { + fullWallpaperBlend(); + } +} + +// works only for NoBlending and no alpha in wallpaper +// but is much faster than QImage fidling +void KBackgroundRenderer::fastWallpaperBlend() +{ + m_Image = QImage(); + // 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( QRect( QPoint( 0, 0 ), m_Size )) + && !m_Wallpaper.hasAlphaBuffer()) // wallpaper covers all and no blending + m_Pixmap = QPixmap( m_Size ); + else if (m_Background.size() == m_Size) + m_Pixmap.convertFromImage( m_Background ); + else { + m_Pixmap = QPixmap( m_Size ); + QPainter p( &m_Pixmap ); + QPixmap 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()) { + QPixmap 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 = QPixmap(); + 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, DiffuseAlphaDither); + + } else { + m_Image.create(w, h, 32); + tile(m_Image, QRect(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, QRect(x, y, ww, wh), m_Wallpaper, + QPoint(-QMIN(x, 0), -QMIN(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 QPoint(0, 0). + * blendfactor = [0, 100%] + */ +void KBackgroundRenderer::blend(QImage& dst, QRect dr, const QImage& src, QPoint 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)) { + QRgb *b, *d; + for (x = 0; x < dr.width(); x++) { + b = reinterpret_cast<QRgb*>(dst.scanLine(dr.y() + y) + + (dr.x() + x) * sizeof(QRgb)); + d = reinterpret_cast<QRgb*>(src.scanLine(soffs.y() + y) + + (soffs.x() + x) * sizeof(QRgb)); + a = (qAlpha(*d) * blendFactor) / 100; + *b = qRgb(qRed(*b) - (((qRed(*b) - qRed(*d)) * a) >> 8), + qGreen(*b) - (((qGreen(*b) - qGreen(*d)) * a) >> 8), + qBlue(*b) - (((qBlue(*b) - qBlue(*d)) * a) >> 8)); + } + } + } +} + + + +void KBackgroundRenderer::slotBackgroundDone(KProcess *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)) { + QString f = cacheFileName(); + if( useCacheFile()) { + QString w = m_pDirs->findResource("wallpaper", currentWallpaper()); + QFileInfo wi( w ); + QFileInfo fi( f ); + if( wi.lastModified().isValid() && fi.lastModified().isValid() + && wi.lastModified() < fi.lastModified()) { + QImage im; + if( im.load( f, "PNG" )) { + m_Image = im; + m_Pixmap = QPixmap( 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) + QApplication::setOverrideCursor( KCursor::workingCursor() ); + else + QApplication::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 = QImage(); + m_Image = QImage(); + m_Pixmap = QPixmap(); + m_Wallpaper = QImage(); + delete m_pProc; m_pProc = 0L; + m_State = 0; + m_WallpaperRect = QRect(); + m_Cached = false; +} + + +void KBackgroundRenderer::setPreview(const QSize &size) +{ + if (size.isNull()) + m_bPreview = false; + else { + m_bPreview = true; + m_Size = size; + } +} + + +QPixmap KBackgroundRenderer::pixmap() +{ + if (m_State & AllDone) { + if( m_Pixmap.isNull()) + m_Pixmap.convertFromImage( m_Image ); + return m_Pixmap; + } + return QPixmap(); +} + +QImage KBackgroundRenderer::image() +{ + if (m_State & AllDone) { + if( m_Image.isNull()) + fullWallpaperBlend(); // create from m_Pixmap + return m_Image; + } + return QImage(); +} + + +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(); +} + +QString KBackgroundRenderer::cacheFileName() +{ + QString f = fingerprint(); + f.replace ( ':', '_' ); // avoid characters that shouldn't be in filenames + f.replace ( '/', '#' ); + f = locateLocal( "cache", QString( "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 + QString 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 + QString f = cacheFileName(); + if( KStandardDirs::exists( f ) || m_Cached ) + utime( QFile::encodeName( f ), NULL ); + else { + m_Image.save( f, "PNG" ); + // remove old entries from the cache + QDir dir( locateLocal( "cache", "background/" )); + if( const QFileInfoList* list = dir.entryInfoList( "*.png", QDir::Files, QDir::Time | QDir::Reversed )) { + int size = 0; + for( QFileInfoListIterator it( *list ); + QFileInfo* info = it.current(); + ++it ) + size += info->size(); + for( QFileInfoListIterator it( *list ); + QFileInfo* 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(); + QFile::remove( info->absFilePath()); + } + } + } +} + +//BEGIN class KVirtualBGRenderer +KVirtualBGRenderer::KVirtualBGRenderer( int desk, KConfig *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 (qt_xdisplay()) + screen_number = DefaultScreen(qt_xdisplay()); + QCString configname; + if (screen_number == 0) + configname = "kdesktoprc"; + else + configname.sprintf("kdesktop-screen-%drc", screen_number); + + m_pConfig = new KConfig(configname, false, false); + m_bDeleteConfig = true; + } else { + m_pConfig = config; + m_bDeleteConfig = false; + } + + initRenderers(); + m_size = QApplication::desktop()->size(); +} + +KVirtualBGRenderer::~KVirtualBGRenderer() +{ + for (unsigned i=0; i<m_numRenderers; ++i) + delete m_renderer[i]; + + delete m_pPixmap; + + if (m_bDeleteConfig) + delete m_pConfig; +} + + +KBackgroundRenderer * KVirtualBGRenderer::renderer(unsigned screen) +{ + return m_renderer[screen]; +} + + +QPixmap 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() +{ + QString fp; + for (unsigned i=0; i<m_numRenderers; ++i) + { + fp += m_renderer[i]->fingerprint(); + } + //kdDebug() << k_funcinfo << " fp=\""<<fp<<"\" h="<<QHash(fp)<<endl; + return QHash(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 = QApplication::desktop()->size(); + + if (m_pPixmap) + { + delete m_pPixmap; + m_pPixmap = new QPixmap(m_size); + m_pPixmap->fill(Qt::black); + } + + initRenderers(); +} + + +void KVirtualBGRenderer::setPreview(const QSize & 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(QApplication::desktop()->size().width()); + m_scaleY = float(m_size.height()) / float(QApplication::desktop()->size().height()); + + // Scale renderers appropriately + for (unsigned i=0; i<m_renderer.size(); ++i) + { + QSize unscaledRendererSize = renderSize(i); + + m_renderer[i]->setPreview( QSize( + int(unscaledRendererSize.width() * m_scaleX), + int(unscaledRendererSize.height() * m_scaleY) ) ); + } +} + + +QSize KVirtualBGRenderer::renderSize(int screen) +{ + return m_bDrawBackgroundPerScreen ? + QApplication::desktop()->screenGeometry(screen).size() : QApplication::desktop()->size(); +} + + +void KVirtualBGRenderer::initRenderers() +{ + m_pConfig->setGroup("Background Common"); + m_bDrawBackgroundPerScreen = m_pConfig->readBoolEntry( QString("DrawBackgroundPerScreen_%1").arg(m_desk), _defDrawBackgroundPerScreen ); + + m_bCommonScreen = m_pConfig->readBoolEntry("CommonScreen", _defCommonScreen); + + m_numRenderers = m_bDrawBackgroundPerScreen ? QApplication::desktop()->numScreens() : 1; + + 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; + KBackgroundRenderer * r = new KBackgroundRenderer( m_desk, eScreen, m_bDrawBackgroundPerScreen, m_pConfig ); + m_renderer.insert( i, r ); + r->setSize(renderSize(i)); + connect( r, SIGNAL(imageDone(int,int)), this, 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 KBackgroundRenderer * sender = dynamic_cast<const KBackgroundRenderer*>(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 + + QRect overallGeometry; + for (int i=0; i < QApplication::desktop()->numScreens(); ++i) + overallGeometry |= QApplication::desktop()->screenGeometry(i); + + QPoint drawPos = QApplication::desktop()->screenGeometry(screen).topLeft() - overallGeometry.topLeft(); + drawPos.setX( int(drawPos.x() * m_scaleX) ); + drawPos.setY( int(drawPos.y() * m_scaleY) ); + + QPixmap source = m_renderer[screen]->pixmap(); + QSize renderSize = this->renderSize(screen); + renderSize.setWidth( int(renderSize.width() * m_scaleX) ); + renderSize.setHeight( int(renderSize.height() * m_scaleY) ); + + QPainter 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 QPixmap(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..39e00ff5d --- /dev/null +++ b/kcontrol/background/bgrender.h @@ -0,0 +1,182 @@ +/* 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 <qobject.h> +#include <qptrvector.h> +#include <qimage.h> +#include <qpixmap.h> + +#include "bgsettings.h" + +class QSize; +class QRect; +class QString; +class QTimer; + +class KConfig; +class KProcess; +class KTempFile; +class KShellProcess; +class KStandardDirs; + +/** + * This class renders a desktop background to a QImage. 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 QObject, + public KBackgroundSettings +{ + Q_OBJECT + +public: + KBackgroundRenderer(int desk, int screen, bool drawBackgroundPerScreen, KConfig *config=0); + ~KBackgroundRenderer(); + + void load(int desk, int screen, bool drawBackgroundPerScreen, bool reparseConfig=true); + + void setPreview(const QSize &size); + void setSize(const QSize &size); + + QPixmap pixmap(); + QImage 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(KProcess *); + 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 }; + + QString buildCommand(); + void createTempFile(); + void tile(QImage& dst, QRect rect, const QImage& src); + void blend(QImage& dst, QRect dr, const QImage& src, QPoint soffs = QPoint(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); + QString 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; + QSize m_Size, m_rSize; + QRect m_WallpaperRect; + QImage m_Image, m_Background, m_Wallpaper; + QPixmap m_Pixmap; + QTimer *m_pTimer; + + KStandardDirs *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, KConfig *config=0l); + ~KVirtualBGRenderer(); + + KBackgroundRenderer * renderer(unsigned screen); + unsigned numRenderers() const { return m_numRenderers; } + + QPixmap pixmap(); + + void setPreview(const QSize & 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: + QSize renderSize(int screen); // the size the renderer should be + void initRenderers(); + + KConfig *m_pConfig; + float m_scaleX; + float m_scaleY; + int m_desk; + unsigned m_numRenderers; + bool m_bDrawBackgroundPerScreen; + bool m_bCommonScreen; + bool m_bDeleteConfig; + QSize m_size; + + QMemArray<bool> m_bFinished; + QPtrVector<KBackgroundRenderer> m_renderer; + QPixmap *m_pPixmap; +}; + + +#endif // BGRender_h_Included + diff --git a/kcontrol/background/bgsettings.cpp b/kcontrol/background/bgsettings.cpp new file mode 100644 index 000000000..9b657393f --- /dev/null +++ b/kcontrol/background/bgsettings.cpp @@ -0,0 +1,1267 @@ +/* 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 <qdir.h> +#include <qpixmap.h> + +#include <dcopclient.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kglobalsettings.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(QString name) +{ + dirty = false; + hashdirty = true; + + m_pDirs = KGlobal::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(QString 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"); + + QFileInfo fi(m_File); + m_bReadOnly = !fi.isWritable(); +} + + +void KBackgroundPattern::setComment(const QString &comment) +{ + if (m_Comment == comment) + return; + dirty = true; + m_Comment = comment; +} + + +void KBackgroundPattern::setPattern(QString 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; + QString file = m_Pattern; + if (file.at(0) != '/') + file = m_pDirs->findResource("dtop_pattern", file); + QFileInfo fi(file); + return (fi.exists()); +} + + +bool KBackgroundPattern::remove() +{ + if (m_bReadOnly) + return false; + return !unlink(QFile::encodeName(m_File)); +} + + +QString KBackgroundPattern::fingerprint() +{ + return m_File; +} + + +int KBackgroundPattern::hash() +{ + if (hashdirty) { + m_Hash = QHash(fingerprint()); + hashdirty = false; + } + return m_Hash; +} + + +/* static */ +QStringList KBackgroundPattern::list() +{ + KStandardDirs *dirs = KGlobal::dirs(); + dirs->addResourceType("dtop_pattern", dirs->kde_default("data") + + "kdesktop/patterns"); + QStringList lst = dirs->findAllResources("dtop_pattern", "*.desktop", + false, true); + QStringList::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(QString name) +{ + dirty = false; + hashdirty = true; + + m_pDirs = KGlobal::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 QString &name) +{ + m_Name = name; + init(); + readSettings(); +} + + +void KBackgroundProgram::setComment(const QString &comment) +{ + if (m_Comment == comment) + return; + dirty = true; + m_Comment = comment; +} + + +void KBackgroundProgram::setExecutable(const QString &executable) +{ + if (m_Executable == executable) + return; + dirty = true; + m_Executable = executable; +} + + +void KBackgroundProgram::setCommand(const QString &command) +{ + if (m_Command == command) + return; + dirty = hashdirty = true; + m_Command = command; +} + + +void KBackgroundProgram::setPreviewCommand(const QString &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(QFile::encodeName(m_File)); +} + + +bool KBackgroundProgram::needUpdate() +{ + return (m_LastChange + 60*m_Refresh <= time(0L)); +} + + +void KBackgroundProgram::update() +{ + m_LastChange = (int) time(0L); +} + + +QString KBackgroundProgram::fingerprint() +{ + return QString("co:%1;re:%2").arg(m_Command).arg(m_Refresh); +} + + +int KBackgroundProgram::hash() +{ + if (hashdirty) { + m_Hash = QHash(fingerprint()); + hashdirty = false; + } + return m_Hash; +} + + +/* static */ +QStringList KBackgroundProgram::list() +{ + KStandardDirs *dirs = KGlobal::dirs(); + dirs->addResourceType("dtop_program", dirs->kde_default("data") + + "kdesktop/programs"); + QStringList lst = dirs->findAllResources("dtop_program", "*.desktop", + false, true); + QStringList::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, KConfig *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 (QPixmap::defaultDepth() > 8) + defBackgroundMode = _defBackgroundMode; + else + defBackgroundMode = Flat; + defWallpaperMode = _defWallpaperMode; + defMultiMode = _defMultiMode; + defBlendMode = _defBlendMode; + defBlendBalance = _defBlendBalance; + defReverseBlending = _defReverseBlending; + + 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 = KGlobal::dirs(); + + if (!config) { + int screen_number = 0; + if (qt_xdisplay()) + screen_number = DefaultScreen(qt_xdisplay()); + QCString configname; + if (screen_number == 0) + configname = "kdesktoprc"; + else + configname.sprintf("kdesktop-screen-%drc", screen_number); + + m_pConfig = new KConfig(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_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 QColor& color) +{ + if (m_ColorA == color) + return; + dirty = hashdirty = true; + m_ColorA = color; +} + + +void KBackgroundSettings::setColorB(const QColor& color) +{ + if (m_ColorB == color) + return; + dirty = hashdirty = true; + m_ColorB = color; +} + + +void KBackgroundSettings::setPatternName(QString name) +{ + int ohash = KBackgroundPattern::hash(); + KBackgroundPattern::load(name); + if (ohash == KBackgroundPattern::hash()) + return; + + dirty = hashdirty = true; + return; +} + + +void KBackgroundSettings::setProgram(QString 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::setWallpaper(QString 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(QStringList list) +{ + KStandardDirs *d = KGlobal::dirs(); + if (m_WallpaperList == list) + return; + + dirty = hashdirty = true; + m_WallpaperList.clear(); + for(QStringList::ConstIterator it = list.begin(); + it != list.end(); ++it) + { + QString 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 QPixmap::defaultDepth() >= 16; + case Opt15bpp : + return QPixmap::defaultDepth() >= 15; + case NeverOpt : + default : + return false; + } +} + +void KBackgroundSettings::setUseShm(bool use) +{ + if (m_bShm == use) + return; + dirty = hashdirty = true; + m_bShm = use; +} + +QString KBackgroundSettings::configGroupName() const +{ + QString screenName; + if (m_bDrawBackgroundPerScreen) + screenName = QString("Screen%1").arg(QString::number(m_Screen)); + return QString("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); + + QString 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); + + // 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("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() +{ + QStringList::Iterator it; + m_WallpaperFiles.clear(); + for (it=m_WallpaperList.begin(); it!=m_WallpaperList.end(); ++it) { + QString file = locate("wallpaper", *it); + if (file.isEmpty()) + continue; + QFileInfo fi(file); + if (!fi.exists()) + continue; + if (fi.isFile() && fi.isReadable()) + m_WallpaperFiles.append(file); + if (fi.isDir()) { + QDir dir(file); + QStringList lst = dir.entryList(QDir::Files | QDir::Readable); + QStringList::Iterator it; + for (it=lst.begin(); it!=lst.end(); ++it) + { + file = dir.absFilePath(*it); + QFileInfo 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; + QStringList tmpList = m_WallpaperFiles; + QStringList 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; +} + +QStringList KBackgroundSettings::wallpaperList() const +{ + if ( m_WallpaperMode == NoWallpaper ) + return QStringList(); + if ( m_MultiMode == NoMulti || m_MultiMode == NoMultiRandom ) + return QStringList(m_Wallpaper); + return m_WallpaperList; +} + +QStringList KBackgroundSettings::wallpaperFiles() const +{ + if ( m_WallpaperMode == NoWallpaper ) + return QStringList(); + if ( m_MultiMode == NoMulti || m_MultiMode == NoMultiRandom ) + return QStringList(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 = QString(); + } + 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; +} + + +QString KBackgroundSettings::currentWallpaper() const +{ + if ( m_WallpaperMode == NoWallpaper ) + return QString::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 QString::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. + */ + +QString KBackgroundSettings::fingerprint() +{ + QString s = QString("bm:%1;en:%2").arg(m_BackgroundMode).arg(m_bEnabled); + switch (m_BackgroundMode) { + case Flat: + s += QString("ca:%1;").arg(m_ColorA.rgb()); + break; + case Program: + s += QString("pr:%1;").arg(KBackgroundProgram::hash()); + break; + case Pattern: + s += QString("ca:%1;cb:%2;pt:%3;").arg(m_ColorA.rgb()) + .arg(m_ColorB.rgb()).arg(KBackgroundPattern::hash()); + break; + default: + s += QString("ca:%1;cb:%2;").arg(m_ColorA.rgb()).arg(m_ColorB.rgb()); + break; + } + + s += QString("wm:%1;").arg(m_WallpaperMode); + if (m_WallpaperMode != NoWallpaper) + { + Q_UINT32 rh = KGlobal::dirs()->calcResourceHash("wallpaper", currentWallpaper(), false); + s += QString("wp:%2:%1;").arg(rh).arg(currentWallpaper()); + + } + s += QString("blm:%1;").arg(m_BlendMode); + if (m_BlendMode != NoBlending) { + s += QString("blb:%1;").arg(m_BlendBalance); + s += QString("rbl:%1;").arg(int(m_ReverseBlending)); + } + s += QString::number( m_bShm ); + s += QString::number( m_MinOptimizationDepth ); + + return s; +} + + +int KBackgroundSettings::hash() +{ + if (hashdirty) { + m_Hash = QHash(fingerprint()); + hashdirty = false; + } + return m_Hash; +} + +void KBackgroundSettings::setEnabled(const bool enable) +{ + if (m_bEnabled == enable) + return; + + m_bEnabled= enable; + hashdirty = true; +} + +/**** KGlobalBackgroundSettings ****/ + +KGlobalBackgroundSettings::KGlobalBackgroundSettings(KConfig *_config) +{ + m_pConfig = _config; + + readSettings(); +} + + +QString KGlobalBackgroundSettings::deskName(int desk) +{ + return m_Names[desk]; +} + + +/* +void KGlobalBackgroundSettings::setDeskName(int desk, QString name) +{ + if (name == m_Names[desk]) + return; + dirty = true; + m_Names[desk] = name; +} +*/ + + +void KGlobalBackgroundSettings::setCacheSize(int size) +{ + if (size == m_CacheSize) + return; + dirty = true; + m_CacheSize = size; +} + + +void KGlobalBackgroundSettings::setLimitCache(bool limit) +{ + if (limit == m_bLimitCache) + return; + dirty = true; + m_bLimitCache = limit; +} + + +bool KGlobalBackgroundSettings::drawBackgroundPerScreen(int desk) const +{ + if ( desk > int(m_bDrawBackgroundPerScreen.size()) ) + return _defDrawBackgroundPerScreen; + return m_bDrawBackgroundPerScreen[desk]; +} + + +void KGlobalBackgroundSettings::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 KGlobalBackgroundSettings::setCommonScreenBackground(bool common) +{ + if (common == m_bCommonScreen) + return; + dirty = true; + m_bCommonScreen = common; +} + + +void KGlobalBackgroundSettings::setCommonDeskBackground(bool common) +{ + if (common == m_bCommonDesk) + return; + dirty = true; + m_bCommonDesk = common; +} + + +void KGlobalBackgroundSettings::setDockPanel(bool dock) +{ + if (dock == m_bDock) + return; + dirty = true; + m_bDock = dock; +} + + +void KGlobalBackgroundSettings::setExportBackground(bool _export) +{ + if (_export == m_bExport) + return; + dirty = true; + m_bExport = _export; +} + +void KGlobalBackgroundSettings::setTextColor(QColor _color) +{ + if (_color == m_TextColor) + return; + dirty = true; + m_TextColor = _color; +} + +void KGlobalBackgroundSettings::setTextBackgroundColor(QColor _color) +{ + if (_color == m_TextBackgroundColor) + return; + dirty = true; + m_TextBackgroundColor = _color; +} + +void KGlobalBackgroundSettings::setShadowEnabled(bool enabled) +{ + if (enabled == m_shadowEnabled) + return; + dirty = true; + m_shadowEnabled = enabled; +} + +void KGlobalBackgroundSettings::setTextLines(int lines) +{ + if (lines == m_textLines) + return; + dirty = true; + m_textLines = lines; +} + +void KGlobalBackgroundSettings::setTextWidth(int width) +{ + if (width == m_textWidth) + return; + dirty = true; + m_textWidth = width; +} + +void KGlobalBackgroundSettings::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( qt_xdisplay(), NET::DesktopNames | NET::NumberOfDesktops ); + m_bDrawBackgroundPerScreen.resize(info.numberOfDesktops()); + for ( int i = 0 ; i < info.numberOfDesktops() ; ++i ) + m_bDrawBackgroundPerScreen[i] = m_pConfig->readBoolEntry( QString("DrawBackgroundPerScreen_%1").arg(i), _defDrawBackgroundPerScreen ); + + m_TextColor = KGlobalSettings::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( QString::fromUtf8(info.desktopName(i+1)) ); + + dirty = false; +} + +void KGlobalBackgroundSettings::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(QString("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 + QByteArray 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..928f66360 --- /dev/null +++ b/kcontrol/background/bgsettings.h @@ -0,0 +1,372 @@ +/* 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_Included__ +#define __BGSettings_h_Included__ + + +#include <qstringlist.h> +#include <qcolor.h> +#include <qvaluevector.h> + +template <class QString, class T> class QMap; +class KStandardDirs; +class KSimpleConfig; +class KConfig; +class QString; +class QImage; + +/** + * 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(QString name=QString::null); + ~KBackgroundPattern(); + + void copyConfig(const KBackgroundPattern*); + + QString name() const { return m_Name; } + void load(QString name); + + void setComment(const QString &comment); + QString comment() const {return m_Comment; } + + void setPattern(QString file); + QString pattern() const { return m_Pattern; } + + void readSettings(); + void writeSettings(); + + bool isAvailable(); + bool isGlobal()const { return m_bReadOnly; } + bool remove(); + + int hash(); + + static QStringList list(); + +private: + void init(bool force_rw=false); + QString fingerprint(); + + bool dirty, hashdirty; + bool m_bReadOnly; + int m_Hash; + QString m_Name, m_Comment; + QString m_Pattern, m_File; + KStandardDirs *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(QString name=QString::null); + ~KBackgroundProgram(); + + void copyConfig(const KBackgroundProgram*); + + QString name()const { return m_Name; } + void load(const QString & name); + + void setComment(const QString &comment); + QString comment()const { return m_Comment; } + + void setCommand(const QString &command); + QString command()const { return m_Command; } + + void setPreviewCommand(const QString &command); + QString previewCommand()const { return m_PreviewCommand; } + + void setRefresh(int refresh); + int refresh()const { return m_Refresh; } + + void setExecutable(const QString &executable); + QString 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 QStringList list(); + +private: + void init(bool force_rw=false); + QString fingerprint(); + + bool dirty, hashdirty; + bool m_bReadOnly; + int m_Refresh, m_Hash, m_LastChange; + QString m_Name, m_Command; + QString m_PreviewCommand, m_Comment; + QString m_Executable, m_File; + KStandardDirs *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, KConfig *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 QColor &color); + QColor colorA() const { return m_ColorA; } + void setColorB(const QColor &color); + QColor colorB() const { return m_ColorB; } + + void setProgram(QString program); + void setPatternName(QString 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 setBlendBalance(int value); + int blendBalance() const { return m_BlendBalance; } + + void setWallpaper(QString name); + QString 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(QStringList); + QStringList wallpaperList() const; + QStringList 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(); + + QString 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(); + QString configGroupName() const; + + int hash(); + QString 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; + + QColor m_ColorA, defColorA; + QColor m_ColorB, defColorB; + QString m_Wallpaper; + QStringList m_WallpaperList, m_WallpaperFiles; + + int m_BackgroundMode, defBackgroundMode; + int m_WallpaperMode, defWallpaperMode; + int m_BlendMode, defBlendMode; + int m_BlendBalance, defBlendBalance; + bool m_ReverseBlending, defReverseBlending; + int m_MinOptimizationDepth; + bool m_bShm; + bool m_bDrawBackgroundPerScreen; + + int m_MultiMode, defMultiMode; + int m_Interval, m_LastChange; + int m_CurrentWallpaper; + QString m_CurrentWallpaperName; + + KConfig *m_pConfig; + KStandardDirs *m_pDirs; + bool m_bDeleteConfig; + bool m_bEnabled; + +public: + QMap<QString,int> m_BMMap; + QMap<QString,int> m_WMMap; + QMap<QString,int> m_MMMap; + QMap<QString,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 KGlobalBackgroundSettings +{ +public: + KGlobalBackgroundSettings(KConfig *config); + + QString deskName(int desk); + //void setDeskName(int desk, QString 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(QColor _color); + QColor textColor() const { return m_TextColor; } + + void setTextBackgroundColor(QColor _color); + QColor 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(); + KConfig* getConfig() { return m_pConfig; } + +private: + bool dirty; + bool m_bCommonDesk; + bool m_bCommonScreen; + bool m_bDock; + bool m_bLimitCache, m_bExport; + int m_CacheSize; + QStringList m_Names; + + QColor m_TextColor; + QColor m_TextBackgroundColor; + bool m_shadowEnabled; + int m_textLines; + int m_textWidth; + KConfig *m_pConfig; + bool m_bDeleteConfig; + QValueVector<bool> m_bDrawBackgroundPerScreen; // m_bDrawBackgroundPerScreen[desk] +}; + + +#endif // __BGSettings_h_Included__ diff --git a/kcontrol/background/bgwallpaper.cpp b/kcontrol/background/bgwallpaper.cpp new file mode 100644 index 000000000..9786059eb --- /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 <qcheckbox.h> +#include <qevent.h> +#include <qpushbutton.h> +#include <qspinbox.h> + +#include <kfiledialog.h> +#include <kimageio.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <kurldrag.h> + +#include "bgsettings.h" +#include "bgwallpaper.h" +#include "bgwallpaper_ui.h" + +/**** BGMultiWallpaperList ****/ + +BGMultiWallpaperList::BGMultiWallpaperList(QWidget *parent, const char *name) + : QListBox(parent, name) +{ + setAcceptDrops(true); + setSelectionMode(QListBox::Extended); +} + + +void BGMultiWallpaperList::dragEnterEvent(QDragEnterEvent *ev) +{ + ev->accept(KURLDrag::canDecode(ev)); +} + + +void BGMultiWallpaperList::dropEvent(QDropEvent *ev) +{ + QStringList 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, + QWidget *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(QMAX(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, SIGNAL(clicked()), SLOT(slotAdd())); + connect(dlg->m_buttonRemove, SIGNAL(clicked()), SLOT(slotRemove())); + connect(dlg->m_buttonMoveUp, SIGNAL(clicked()), SLOT(slotMoveUp())); + connect(dlg->m_buttonMoveDown, SIGNAL(clicked()), SLOT(slotMoveDown())); + connect(dlg->m_listImages, SIGNAL(clicked ( QListBoxItem * )), SLOT(slotItemSelected( QListBoxItem *))); + dlg->m_buttonRemove->setEnabled( false ); + dlg->m_buttonMoveUp->setEnabled( false ); + dlg->m_buttonMoveDown->setEnabled( false ); + +} + +void BGMultiWallpaperDialog::slotItemSelected( QListBoxItem * ) +{ + dlg->m_buttonRemove->setEnabled( dlg->m_listImages->hasSelection() ); + setEnabledMoveButtons(); +} + +void BGMultiWallpaperDialog::setEnabledMoveButtons() +{ + bool hasSelection = dlg->m_listImages->hasSelection(); + QListBoxItem * 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() +{ + QStringList mimeTypes = KImageIO::mimeTypes( KImageIO::Reading ); +#ifdef HAVE_LIBART + mimeTypes += "image/svg+xml"; +#endif + + KFileDialog fileDialog(KGlobal::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(); + QStringList 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();) + { + QListBoxItem * 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++) + { + QListBoxItem * 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--) + { + QListBoxItem * 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() +{ + QStringList 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..0ecc1e6a4 --- /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 <qlistbox.h> +#include <qstringlist.h> + +#include <kdialogbase.h> + +class BGMultiWallpaperBase; +class KBackgroundSettings; + +class BGMultiWallpaperList : public QListBox +{ +public: + BGMultiWallpaperList(QWidget *parent, const char *name); + + void dragEnterEvent(QDragEnterEvent *ev); + void dropEvent(QDropEvent *ev); + bool hasSelection(); + void ensureSelectionVisible(); +}; + +class BGMultiWallpaperDialog : public KDialogBase +{ + Q_OBJECT +public: + BGMultiWallpaperDialog(KBackgroundSettings *settings, QWidget *parent, const char *name=0); + +public slots: + void slotAdd(); + void slotRemove(); + void slotMoveUp(); + void slotMoveDown(); + void slotOk(); + void slotItemSelected( QListBoxItem * ); +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..c3d9a9a40 --- /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="QWidget"> + <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="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Show the following pictures:</string> + </property> + </widget> + <widget class="QCheckBox" 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="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <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="QSpinBox"> + <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="QLayoutWidget" 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="QPushButton" 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="QPushButton" row="1" column="1"> + <property name="name"> + <cstring>m_buttonRemove</cstring> + </property> + <property name="text"> + <string>&Remove</string> + </property> + </widget> + <widget class="QPushButton" row="3" column="1"> + <property name="name"> + <cstring>m_buttonMoveDown</cstring> + </property> + <property name="text"> + <string>Move &Down</string> + </property> + </widget> + <widget class="QPushButton" 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/main.cpp b/kcontrol/background/main.cpp new file mode 100644 index 000000000..433065c85 --- /dev/null +++ b/kcontrol/background/main.cpp @@ -0,0 +1,123 @@ +/* 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 <qlayout.h> +#include <kapplication.h> +#include <kaboutdata.h> +#include <kconfig.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, QWidget> KBackGndFactory; +K_EXPORT_COMPONENT_FACTORY( kcm_background, KBackGndFactory("kcmbackground")) + +/**** KBackground ****/ +KBackground::~KBackground( ) +{ + delete m_pConfig; +} + +KBackground::KBackground(QWidget *parent, const char *name, const QStringList &/* */) + : KCModule(KBackGndFactory::instance(), parent, name) +{ + int screen_number = 0; + if (qt_xdisplay()) + screen_number = DefaultScreen(qt_xdisplay()); + QCString configname; + if (screen_number == 0) + configname = "kdesktoprc"; + else + configname.sprintf("kdesktop-screen-%drc", screen_number); + m_pConfig = new KConfig(configname, false, false); + + QVBoxLayout *layout = new QVBoxLayout(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, SIGNAL(changed(bool)), SIGNAL(changed(bool))); + + KAboutData *about = + new KAboutData(I18N_NOOP("kcmbackground"), I18N_NOOP("KDE Background Control Module"), + 0, 0, KAboutData::License_GPL, + I18N_NOOP("(c) 1997-2002 Martin R. Jones")); + + 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 (qt_xdisplay()) + screen_number = DefaultScreen(qt_xdisplay()); + QCString appname; + if (screen_number == 0) + appname = "kdesktop"; + else + appname.sprintf("kdesktop-screen-%d", screen_number); + + client->send(appname, "KBackgroundIface", "configure()", ""); +} + +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..a220b57b6 --- /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 <kcmodule.h> + +class KConfig; +class BGDialog; + +/** + * The Desktop/Background tab in kcontrol. + */ +class KBackground: public KCModule +{ + Q_OBJECT + +public: + KBackground(QWidget *parent, const char *name, const QStringList &); + ~KBackground(); + + virtual void load(); + virtual void load( bool useDefaults ); + virtual void save(); + virtual void defaults(); + +private: + BGDialog *m_base; + KConfig *m_pConfig; +}; + + +#endif // __Bgnd_h_Included__ 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 |